class Rex::Exploitation::Egghunter

This class provides an interface to generating egghunters. Egghunters are used to search process address space for a known byte sequence. This is useful in situations where there is limited room for a payload when an overflow occurs, but it’s possible to stick a larger payload somewhere else in memory that may not be directly predictable.

Original implementation by skape (See www.hick.org/code/skape/papers/egghunt-shellcode.pdf)

Checksum checking implemented by dijital1/corelanc0d3r Checksum code merged to Egghunter by jduck Conversion to use Metasm by jduck Startreg code added by corelanc0d3r Added routine to disable DEP for discovered egg (for win, added by corelanc0d3r) Added support for searchforward option (true or false)

Public Class Methods

new(platform, arch = nil) click to toggle source

Creates a new egghunter instance and acquires the sub-class that should be used for generating the stub based on the supplied platform and architecture.

# File lib/rex/exploitation/egghunter.rb, line 328
def initialize(platform, arch = nil)
  Egghunter.constants.each { |c|
    mod = self.class.const_get(c)

    next if ((!mod.kind_of?(::Module)) or
             (!mod.const_defined?('Alias')))

    if (platform =~ /#{mod.const_get('Alias')}/i)
      self.extend(mod)

      if (arch and mod)
        mod.constants.each { |a|
          amod = mod.const_get(a)

          next if ((!amod.kind_of?(::Module)) or
                   (!amod.const_defined?('Alias')))

          if (arch =~ /#{mod.const_get(a).const_get('Alias')}/i)
            amod = mod.const_get(a)

            self.extend(amod)
          end
        }
      end
    end
  }
end

Public Instance Methods

generate(payload, badchars = '', opts = {}) click to toggle source

This method generates an egghunter using the derived hunter stub.

# File lib/rex/exploitation/egghunter.rb, line 359
def generate(payload, badchars = '', opts = {})
  # set defaults if options are missing

  # NOTE: there is no guarantee this won't exist in memory, even when doubled.
  # To address this, use the checksum feature :)
  opts[:eggtag] ||= Rex::Text.rand_text(4, badchars)

  # Generate the hunter_stub portion
  return nil if ((hunter = hunter_stub(payload, badchars, opts)) == nil)

  # Generate the marker bits to be prefixed to the real payload
  egg = ''
  egg << opts[:eggtag] * 2
  egg << payload
  if opts[:checksum]
    cksum = 0
    payload.each_byte { |b|
      cksum += b
    }
    egg << [cksum & 0xff].pack('C')
  end

  return [ hunter, egg ]
end

Protected Instance Methods

checksum_stub(payload, badchars = '', opts = {}) click to toggle source
# File lib/rex/exploitation/egghunter.rb, line 393
  def checksum_stub(payload, badchars = '', opts = {})
    return '' if not opts[:checksum]

    if payload.length < 0x100
      cmp_reg = "cl"
    elsif payload.length < 0x10000
      cmp_reg = "cx"
    else
      raise RuntimeError, "Payload too big!"
    end
    egg_size = "0x%x" % payload.length

    checksum = <<EOS
  push ecx
  xor ecx,ecx
  xor eax,eax
calc_chksum_loop:
  add al,byte [edi+ecx]
  inc ecx
  cmp #{cmp_reg},#{egg_size}
  jnz calc_chksum_loop
test_chksum:
  cmp al,byte [edi+ecx]
  pop ecx
  jnz next_addr
EOS
  end
hunter_stub(payload, badchars = '', opts = {}) click to toggle source

Stub method that is meant to be overridden. It returns the raw stub that should be used as the egghunter.

# File lib/rex/exploitation/egghunter.rb, line 390
def hunter_stub(payload, badchars = '', opts = {})
end