EggHunting, if simply put, is a technique in exploit development which is used to search for a specific keyword in an application memory space to further aid in the exploit if there is a length restriction. Egg in this case refers to specific keyword/pattern and “hunter” as put you’re searching in all the accessible address space to find the pattern, hence the hunt.


Before we begin, we must understand the need of the egghunting technique. Consider a scenario where you are trying to exploit a buffer overflow but for some reason, you are unable to put the shellcode due to the length limitation of input (we will see this later in action). Given as an exploit developer, the end goal is always to get code execution by using any method possible.

Scenario like this is where creative thinking comes handy, let’s say you have another input field which can have your shellcode/payload but that buffer is not writing instruction pointer. Consider following example:

InputA -> Large buffer but does not trigger overflow
InputB -> This one is limited in length and triggers overflow

Here, if we were able to put our payload in InputA and somehow overwrite the instruction pointer to the address of InputA during the overflow trigger via InputB we can gain shellcode execution.

Following image shows it in a better way:

EggHunting Explained


This should clear it up but there’s always a part which confuses most is the part where this comes handy. To understand it better, we will do a hands-on practical to understand it in a deeper level. This is just to understand the fundamentals of egghunting technique so that once presented with an actual exploitation of this, it will be easier to make sense out of the overall process.

Now, we have following things cleared out:


Analyzing the EggHunting Shellcode


There is a well known paper that explains the overall methodologies of egghunting and how it can be used, it was written by Skape. It is recommended to read it to understand two different ways the egghunting technique can be deployed but we will use the syscall technique as I prefer that and it is very simple to grasp.

Before we begin, I will be using the NtDisplayString syscall and the shellcode is supposed to work on Windows XP and the 0x43 is used to specify the NtDisplayString syscall. The reason we are using NtDisplayString is because as quoted by Skape himself: “The NtDisplayString system call is typically used to display text to the blue-screen that some people are (unfortunately) all too familiar with. For the purposes of an egg hunter, however, it is abused due to the fact that its only argument is a pointer that is read from and not written to, thus making it a most desirable choice.”

It makes sense as NtDisplayString function accepts one argument which is a pointer to memory and read the string from the memory:

NTSYSAPI 
NTSTATUS
NTAPI

NtDisplayString(
					  IN PUNICODE_STRING      String 
);

It is also a good thing to note that if this function gets a memory address which for some reason is not accessible, it will throw a STATUS ACCESS VIOLATION or 0xc0000005 value.

Here is one sample egghunting shellcode:

0x0000000000000000:  66 81 CA FF 0F    or    dx, 0xfff
0x0000000000000005:  42                inc   edx
0x0000000000000006:  52                push  edx
0x0000000000000007:  6A 02             push  43
0x0000000000000009:  58                pop   eax
0x000000000000000a:  CD 2E             int   0x2e
0x000000000000000c:  3C 05             cmp   al, 5
0x000000000000000e:  5A                pop   edx
0x000000000000000f:  74 EF             je    0
0x0000000000000011:  B8 77 30 30 74    mov   eax, 0x74303077
0x0000000000000016:  8B FA             mov   edi, edx
0x0000000000000018:  AF                scasd eax, dword ptr es:[edi]
0x0000000000000019:  75 EA             jne   5
0x000000000000001b:  AF                scasd eax, dword ptr es:[edi]
0x000000000000001c:  75 E7             jne   5
0x000000000000001e:  FF E7             jmp   edi

This is a classic EggHunter shellcode, assuming you know a little bit about assembly such as mov , pop and conditional jumps, there is two things that still stands out here:

Let’s just assume that we have taken a control of EIP and somehow made the execution our egghunting shellcode, now I will walk you through how it works, we will break it down:


At this point you are wondering why we have two calls of scasd , good question. the reason being is that during the exploitation phase we write 8 bytes of pattern/egg, in this our first stage shellcode looks like:

w00tw00t + shellcode

Having a unique 8 byte egg helps in not having any false positive during the analysis of the memory for finding this very egg.

Another is why instead of using scasd why not go with cmp , there are few reasons for that, first is that when writing a shellcode a rule of thumb is that less bytes of shellcode and since we already making use of eax , edi registers and scasd is specifically designed to compare double words (4 bytes) and by default it checks the eax and edi which helps in achieving that because we will have less unnecessary insturctions in our shellcode. Often times, you might have to tackle with bad characters and it is very good practice to use whatever good option is there and of course, given the shellcode actually searches through the memory space, you would want the shellcode to be more efficient hence the scasd


I hope you have understood how egghunting technique works and if required, you can now write your own egghunting shellcode or use an existing one and modify it according to your need.

References: