When writing or modifying custom assembly shellcode (such as egg hunters, socket reuse payloads, or stagers), you must verify that the payload functions correctly before embedding it into a full exploit delivery chain.
A standard C test harness executes shellcode by casting a char array in memory to a function pointer and calling it directly.
The C Test Harness
#include <stdio.h>
#include <string.h>
// Example: Software breakpoint (INT3) or your target shellcode
const char shellcode[] =
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
int main(int argc, char **argv)
{
printf("Shellcode length: %zu bytes\n", strlen(shellcode));
// Cast the array address to a callable function pointer
int (*ret)() = (int (*)())shellcode;
// Transfer control flow to shellcode
ret();
return 0;
}
Compilation Flags: Disabling Modern Mitigations
Modern compilers enable Stack Canaries and enforce Non-Executable Memory (DEP / NX) by default. If you attempt to execute data placed in the .rodata or .data section without special flags, the kernel terminates the process with a SIGSEGV / segmentation fault.
Compile with -z execstack and -fno-stack-protector:
# 32-bit compilation:
gcc -m32 -fno-stack-protector -z execstack shellcode_test.c -o test32
# 64-bit compilation:
gcc -fno-stack-protector -z execstack shellcode_test.c -o test64
-z execstack: Clears theGNU_STACKELF header flag, instructing the kernel loader to mark memory pages containing data and the stack as executable (RWX).-fno-stack-protector: Disables stack canary verification.
Debugging Under GDB
To step through your shellcode instruction-by-instruction:
gdb -q ./test32
(gdb) break main
(gdb) run
(gdb) stepi