#!/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"
