EggSandwich – An Egghunter with Integrity

Written on:February 12, 2015
Comments are closed



A while back I introduced the EggSandwich in my tutorial on Egghunting as a means to implement some basic integrity checks into the traditional Egghunter and overcome the problem of fragmented / corrupted shellcode. I recently took the opportunity to update my implementation so it could accomodate shellcode of any size. The code and a brief explanation follows.

What is the EggSandwich?

I ran into a situation when developing an exploit for an application in which my shellcode was corrupted in multiple locations but left intact in one occurrence. Unfortunately, the corrupted versions of the shellcode appeared first in memory and the Egghunter never reached the valid payload.

It was a situation that definitely called for an Egghunter (as I could not reliably jump to the valid copy of my shellcode) but I needed to figure out a way for that Egghunter to be smart enough to know when it reached the valid payload and skip all of the rest.

When I wrote my tutorial on Egghunting one of the things I covered was dealing with corrupted shellcode. There are a few of different methods you can use, which include 1) changing the shellcode offset, 2) changing the starting memory page, and 3) using the Omelette Egghunter (breaking up your shellcode into smaller chunks. I won’t go over these again (feel free to check out that tutorial for more information) but changing the shellcode offset didn’t fix the problem and I didn’t feel like experimenting with smaller shellcode chunks due to the sheer number of copies the application put in memory.

Instead, I decided that a better approach would be to “sandwich” my shellcode between two egg tags. Along with those egg tags I included an additional byte that represented the total length of the shellcode. The Egghunter would use that byte to jump ahead and verify the presence of both tags before executing the shellcode (thereby avoiding shellcode fragments of invalid lengths). If the shellcode failed this integrity check, the Egghunter would move on to the next copy in memory (and so on) until an intact version was located.

My initial POC was limited in that it only used a single byte for the shellcode length, limiting it to less than 255 total bytes in length — not very accommodating for most payloads!

I decided to update that POC to accomodate shellcode of any length and I added an additional check to verify the order of tag discovery (to prevent a false positive should the second egg be found first). This updated version of the EggSandwich Egghunter is described in the following sections.

How Does It Work?

Let’s assume you have a shellcode payload of length 510 bytes and you’re using an egg tag of PWND. Your payload would look as follows:

eggsandwich1Let’s quickly walk through each of the eggs so you understand their purpose.

Egg 1


Here I prepend the shellcode with the first egg tag (PWNDPWND) as well as a series of bytes that represents the size of the shellcode or the offset to egg 2 (also taking into account the five bytes that make up the offset tags). For example, in a scenario where your shellcode is 510 bytes in size, the offset bytes would be 0xff + 0xff + 0x05 (or 255 + 255 + 5 = 515).  These bytes are sandwiched between two tag identifiers (0x1) so the  EggSandwich Egghunter knows when to start and stop processing them.

When the Egghunter finds the first tag, it checks the byte immediately following. If it’s 0x1 it knows this is the first tag and the bytes that follow represent the size of shellcode, until it reaches another 0x1. For each offset length byte that it processes, it adds that value to a register holding the current address and increments an “integrity” counter (in register ECX). Assuming the shellcode is intact, once all of the offset bytes are processed, the register holding the shellcode location will now point to the second egg tag (PWNDPWND).

Egg 2


The Egghunter checks the register holding the updated address for the presence of the second egg and if it finds the correct tag (PWNDPWND), it checks the next byte (0x2) to verify its found the second egg and not the first. The byte that follows (0x3) indicates the total number of offset bytes from tag 1 (0xff, 0xff, 0x5). Since the Eggsandwich code from Egg #1 was incrementing a counter in ECX for each offset byte it encountered, if ECX matches the value, it can be sure that it is processing the eggs in order, at which point it executes the shellcode. If the Egghunter does not find the second egg immediately following the first, it clears ECX.

It is this latter check that provides an extra bit of integrity verification that it necessary if your shellcode becomes fragmented. For example, let’s say the Egghunter processes the first egg attached to a corrupted form of your shellcode and jumps to the updated address looking for the second egg. Because the shellcode is corrupted, it would not find the tag (PWNDPWND) and the next loop would clear the ECX register used for the integrity check. Now let’s say the next egg the Egghunter comes across in memory is the second one (due to another corrupted copy of shellcode). It would check the integrity byte against the value in ECX and fail the check, at which point it would move on to the next egg and skip the corrupted payload altogether.

Here is a generalized flow diagram so you get a high-level idea of how it works before diving into the code:


The Code

Here’s a look at the assembly:


Here’s a copy of some example C code you can compile so you can see exactly how this works in your debugger.

Version: 2.0
9.0 KiB

Also, here is a perl script to generate the EggSandwich shellcode to use in your own exploits:

4.2 KiB

The Drawbacks

There are a few drawbacks to using the EggSandwich, making it unnecessary if you don’t require some form of integrity check in your Egghunter-based exploit.


The first and most obvious drawback of using the EggSandwich is its size. At 62 bytes, it is almost twice the size of Matt Miller’s original 32-byte Egghunter. There are also the additional bytes appended and prepended to the shellcode, which will add around 14 additional bytes to your payload, depending on its size. That said, 62 bytes is still relatively small and if you have a buffer large enough (but still too small for a 500+ byte exploit payload) and need to implement some form of integrity check, you may find this useful.


Second, the integrity check is not foolproof. As you will notice in the Assembly presented in the previous section, several of the integrity checks make assumptions in the interest of keeping the EggSandwich as small as possible. For example, if the first byte after the Egg tag is 0x1, it knows it has found the first egg otherwise it assumes it has found the second. There is no check to validate that that byte value is 0x2, just that it’s not 0x1. The integrity byte will help in this situation, though it is also assumed that if it matches ECX, the shellcode is intact. If that integrity check byte becomes corrupted and changed to 0x0, it may lead to a false positive detection. If you really needed to address this issue, you could modify the second egg check as follows:

Of course this adds to the length of the Egghunter so you would only need to make adjustments if its absolutely necessary.

Length Not Content

Third, this additional integrity check only validates original shellcode length, not its content. If bad characters are altered by an application in a one-to-one swap (vs character expansion), then the shellcode size will remain the same yet your exploit will not run. This only provides protection against shellcode that becomes split or partially saved in memory thereby altering its size in some way.


While not without drawbacks, if you need to implement some basic integrity checks into your Egghunter to prevent it from executing fragmented shellcode you may find the EggSandwich useful. Feel free to modify or make improvements to suit your needs!

Until next time,


Sorry, the comment form is closed at this time.