This is an old revision of the document!
A shellcode is a little piece of binary data that is meant to be executed by a process as part of an attack vector. An attacker would usually place a shellcode in the process memory and aim to execute it to trigger an advantageous effect for the attacker.
While a shellcode would typically result in the attacker gaining a shell process by the means the of the execve system call, this needn't always be the case. Some shellcodes may result in writing data to a socket, scanning the memory, opening/creating a file and many others.
A shellcode is typically written in assembly language and then compiled into binary object code and fed to the vulnerable program. There are three actions an attacker must undertake to run a shellcode in a vulnerable program:
Go to 01-tutorial-shellcode/
in the activities archive.
shellcode.S
is a simple shellcode doing an exit(42)
. You can build it in shellcode.bin
and print it by running
$ make print \xbb\x2a\x00\x00\x00\xb8\x01\x00\x00\x00\xcd\x80
The shellcode is already part of vuln.c
, compiled into the vuln
executable, in the shellcode
global variable. It's run by forcing the shellcode
variable and by casting it to a function pointer and calling it:
void (*func_ptr)(void) = (void (*)(void)) shellcode; func_ptr();
This is possible due to making the data section executable when linking the vuln
executable with the -zexecstack
option, as shown in the Makefile
.
You can check it works properly by running it and checking the return code:
$ ./vuln Nice function at 0x8048510 $ echo $? 42
You can also check that by running the vuln
program under strace
:
$ strace ./vuln execve("./vuln", ["./vuln"], [/* 27 vars */]) = 0 strace: [ Process PID=11063 runs in 32 bit mode. ] [...] write(1, "Nice function at 0x8048510\n", 27Nice function at 0x8048510 ) = 27 exit(42) = ? +++ exited with 42 +++