As you’ll discover later, it is for optimizing size of egg hunter.
So if our egg is nope and our payload is x90x90x90x90, our final payload will look like:payload = "nopenope" + "x90x90x90x90"Egg hunter is a special shellcode that searches for the provided egg in the memory and run the payload marked by it.
It’s very small in size.
This egg hunter is the shellcode that you will be running after the overflow.
So, earlier we used to have a buffer like this while performing buffer overflow:buf = "A"*[offset] + [JMP ESP] + [NOP Sled] + [Shellcode]Now, with egg hunting you’ll have these:payload = "nopenope" + [Shellcode]buf = "A"*[offset] + [JMP ESP] + [NOP Sled] + [EggHunter('nope')]An important thing to note here is that when the program will be executing the EggHunter, the payload must already be there in the memory, otherwise the egg hunter will keep searching the memory and spike the CPU to 100%.
It would now be a good time to read the most awesome resource for egg hunting- Skape’s paper.
Since we are sticking to Windows in this article, I will only focus on techniques related to Windows.
Skape’s paper highlights two methods:Using SEH- By registering our own exception handler that performs the hunting.
Size is 60 bytes.
Using syscalls- IsBadReadPtr or NtDisplayString functions are used for hunting.
IsBadReadPtr is 37 bytes and NtDisplayString is 32 bytes.
I’m not going into technical details of how these methods work otherwise I’ll just end up repeating Skape’s paper, better go ahead and read that first.
What I can do here is repeat the code Skape used in his NtDisplayString method (can be found here):The hex equivalent of this code would look something like this:Hex Instruction6681CAFF0F OR DX,0FFF42 INC EDX52 PUSH EDX6A02 PUSH 0000000258 POP EAXCD2E INT 2E3C05 CMP AL,055A POP EDX74EF JE 00000100B86E6F7065 MOV EAX,65706F6E # 0x6e6f7065 = "nope"8BFA MOV EDI,EDXAF SCASD75EA JNE 00000105AF SCASD75E7 JNE 00000105FFE7 JMP EDIIf you look closely, the code seems to be using NtAccessCheckAndAuditAlarm, not NtDisplayString.
Both of them function in same way, the only difference is syscall number so no need to worry about that.
If you want to see the above code in action, you can go through Security Sift’s blog which does a wonderful job of stepping through each line to explain its working.
ExploitationWe’ll be exploiting PMSoftware Simple Web Server 2.
2-rc2 for demonstration.
It is a simple HTTP server which had a buffer overflow vulnerability in Connection HTTP header.
The original exploit is discussed here.
We also have a metasploit module for this one:Metasploit moduleLet’s write an exploit of our own using Egg hunting technique.
Considering Connection header is vulnerable, the skeleton code to perform the overflow would look like:Here’s how that overflow would look like:Replicating the crashTo find the exact number of bytes after which EIP is getting overwritten, we will send the Metasploit pattern.
The offset comes out to be 2048 bytes.
Finding offsetAnd, we quickly get the JMP ESP sorted out too:Finding JMP ESPTime to generate some venom!.Since we are doing this the egg hunting way, the shellcode variable in my skeleton code would contain the hex version of egg hunter.
So, for egghunter I have used the hex equivalents (opcodes) mentioned above, but !mona egghunter can also generate it for you (as shown in opening image of this blog).
There will be another variable payload that would contain the venom with a prefix of egg being repeated twice.
But I have to ensure the payload is already there in the memory while egghunter is getting executed.
For that, I’ll be sending payload as part of the User-Agent header.
Enough talk, here is the code:The data being sent here has payload in User-Agent header and exploit in the vulnerable Connection header.
The exploit variable is executing egghunter on overflow.
payload variable contains the shellcode and will be there in memory, waiting for the egghunter.
After running this code, there will a spike in CPU and in a minute or two you can notice that our payload gets executed:Shell from our test machineGreat! What now? There is a very interesting possibility that the payload may end up in multiple places in the memory, and some copies of it can contain incomplete/overwritten shellcode.
So, how can we ensure that the shellcode attached with the egg is in its entirety? How can we ensure the integrity of our shellcode before we start executing it? This problem was tackled in Security Sift’s blog under section Overcoming Corrupted Shellcode- The Egg Sandwich.
The author has discussed multiple options there, but the egg sandwich method was the one that I found most neat and elegant.
ConclusionThis blog was not meant to be a comprehensive guide of Egg hunting.
The purpose was to introduce you to Egg hunting.
I would encourage you to try exploiting it on your own and then jump onto much more detailed blogs like the one from Corelan Team.
Happy hunting, happy cracking! :).. More details