EggSandwich – An Egghunter with Integrity

Written on:February 12, 2015
Add One



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,


Developing a Security Assessment Program

Written on:December 19, 2014

Introduction Most organizations and are deploying new applications and technologies at a high rate and without a means to adequately assess them prior to implementation, it’s difficult to accurately gauge your organization’s risk. No matter what the size or industry, it’s imperative that an organization has a standardized and repeatable process for assessing the security of the IT solutions it implements.  My goal with today’s post is to provide some recommendations on…


Exploiting MS14-066 / CVE-2014-6321 (aka “Winshock”)

Written on:November 29, 2014

Introduction I think enough time has passed now to provide a little more detail on how to exploit MS14-066 schannel vulnerability (aka “Winshock”). In this post I won’t be providing a complete PoC exploit, but I will delve into the details on exactly how to trigger the heap overflow along with some example modifications to OpenSSL so you can replicate the issue yourself. This vulnerability was announced while I was on…


Windows OLE RCE Exploit MS14-060 (CVE-2014-4114) – Sandworm

Written on:October 22, 2014

This recent exploit (dubbed “Sandworm”) took advantage of a vulnerability in which a specially crafted OLE object could allow remote code execution. In the case of the live sample exploit PPSX file I examined, it automatically downloaded the payload from a remote SMB share. I won’t rehash much of the details that others have covered but if you want to read more, here are some resources: Microsoft Security Bulletin: Original Discovery by…


Drupal 7 SQL Injection (CVE-2014-3704)

Written on:October 17, 2014

Introduction This vuln has been getting a lot of attention, and rightfully so. The good news is an update is available (and a supplemental patch has been released as well). The bad news is that it’s pre-auth SQLi. The basic problem is the way Drupal core 7.x versions prior to 7.32 construct a SQL query. Contrary to some claims, this is not a flaw in the use of prepared statements/parameterized queries, which…


Phishing for Shellshock

Written on:October 10, 2014

Introduction I thought I was done writing about Shellshock, but a recent discussion with some colleagues got me back on the topic. We were commenting about how organizations tend to react very quickly to patching external assets for a bug like Shellshock but many probably wait to patch internal assets due to a false sense of security. It got me thinking about how an external actor could exploit a bug like…


Shellshock – Targeting Non-CGI PHP

Written on:September 30, 2014

I’ve seen debates as to whether or not it’s possible to have an unpatched PHP server running in mod_php mode (i.e. not CGI) that is vulnerable to Shellshock. From my testing, the answer appears to be Yes…with some prerequisite conditions. First, the PHP application would have to be using Bash for its system commands — exec(), passthru(), system(), popen(), etc. This is pretty obvious since Shellshock is a Bash-specific vulnerability. Although PHP system command…


The Search For Shellshock

Written on:September 28, 2014

Introduction By now there are hundreds or even thousands of posts and articles about the Bash “Shellshock” vuln and more will be written tomorrow (and the next day …). With that in mind, this post will be fairly short and I won’t be rehashing what shellshock is or why it’s a problem. For that you can simply Google “shellshock” and you’ll find all you wanted to know and more. If you want…


Why Google Makes My Job More Difficult

Written on:September 23, 2014

Let me start this post by saying I’m a huge Google fan. I use multiple Android devices and like many others, I’ve become an avid user of services such as Gmail, Docs, Maps, Photos, and Youtube. I even find myself fondly reminiscing about discontinued services such as Reader. And, if you’re like me, Google search has become an instrumental tool in your professional endeavors. So please keep in mind, this post is…


Windows Exploit Development – Part 7: Unicode Buffer Overflows

Written on:September 3, 2014

Introduction In this seventh installment of the Windows Exploit Development Series, I’ll introduce Unicode Buffer Overflows. We’ll start with a brief introduction to Unicode (what it is and why/how it’s used in Windows) and then jump right in to some example exploits. If you plan on following along, I recommend you have the following: A Windows environment (XP or Win 7 — my demos will be on the latter) Metasploit, Alpha2 or…