├── presentations ├── vdb_internals.key ├── vdb_internals.pdf ├── Scriptable debugging.pdf └── Scriptable debugging.pptx ├── sulley ├── README.md ├── utils │ └── crash_binning.py └── process_monitor.py ├── ida ├── README.md └── ida_stalkerColor.py ├── other ├── README.md └── switchToVDB.py ├── vdb ├── README.md └── simpleIAT_NX_vdb.py ├── ida_stalkerColor.py ├── extensions ├── README.md ├── passBack.py ├── loadSyms.py └── scripts │ └── loadSymbols.py ├── simpleRun.py ├── command_line ├── simpleRun.py ├── simpleAttach.py ├── simpleFunctionList.py ├── simpleSnapshot.py ├── simpleOEP.py ├── simpleDisasm.py ├── simpleIAT.py ├── simpleStalker.py ├── README.md ├── simpleRet.py ├── simpleReg.py ├── simpleStalker_ChildProc.py ├── simpleFuzz.py ├── simpleFollowChild.py ├── simpleNotifier.py ├── simpleIAT_NX.py └── simpleAPI.py ├── README.md ├── simpleAttach.py ├── simpleFunctionList.py ├── simpleSnapshot.py ├── simpleOEP.py ├── simpleDisasm.py ├── simpleIAT.py ├── simpleStalker.py ├── simpleRet.py ├── simpleReg.py ├── simpleStalker_ChildProc.py ├── README ├── simpleFuzz.py ├── simpleFollowChild.py ├── simpleNotifier.py ├── simpleIAT_NX_vdb.py ├── simpleIAT_NX.py └── simpleAPI.py /presentations/vdb_internals.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdasilva/vtrace_scripts/HEAD/presentations/vdb_internals.key -------------------------------------------------------------------------------- /presentations/vdb_internals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdasilva/vtrace_scripts/HEAD/presentations/vdb_internals.pdf -------------------------------------------------------------------------------- /presentations/Scriptable debugging.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdasilva/vtrace_scripts/HEAD/presentations/Scriptable debugging.pdf -------------------------------------------------------------------------------- /presentations/Scriptable debugging.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdasilva/vtrace_scripts/HEAD/presentations/Scriptable debugging.pptx -------------------------------------------------------------------------------- /sulley/README.md: -------------------------------------------------------------------------------- 1 | # sulley 2 | > Drop in replacement files for sulley that use vtrace instead of pydbg. 3 | > Just replace process_monitor.py and utils/crash_binning.py and it will use vtrace. 4 | > Currently only tested on windows... 5 | -------------------------------------------------------------------------------- /ida/README.md: -------------------------------------------------------------------------------- 1 | # ida 2 | > Folder for scripts that parse vdb data into ida 3 | 4 | ## ida_stalker 5 | > Will colorize an IDA graph based on the contents of simpleStalker output. 6 | > Does NOT account for the change of base addresses yet. 7 | -------------------------------------------------------------------------------- /other/README.md: -------------------------------------------------------------------------------- 1 | # other 2 | > vtrace code snippets... 3 | 4 | ## switchToVDB.py 5 | > This is a function that will allow a vtrace script to switch to the vdb debugger. 6 | > Use this in conjunction with the passback command in the extensions folder to switch between a script and vdb 7 | 8 | -------------------------------------------------------------------------------- /other/switchToVDB.py: -------------------------------------------------------------------------------- 1 | def switchToVDB(trace): 2 | import vdb 3 | db = vdb.Vdb(trace) 4 | while not db.shutdown.isSet(): 5 | try: 6 | db.cmdloop() 7 | 8 | except KeyboardInterrupt: 9 | if db.trace.isRunning(): 10 | db.trace.sendBreak() 11 | except SystemExit: 12 | break 13 | except: 14 | traceback.print_exc() 15 | -------------------------------------------------------------------------------- /vdb/README.md: -------------------------------------------------------------------------------- 1 | # Sample scripts to run in vdb 2 | 3 | ## simpleIAT_NX_vdb 4 | > Extension of simpleIAT script. Scripts will set the IAT of a binary to unreadable causing a signal to be thrown on each external library reference and call. The signal is then caught by a custom notifier class that will log them into a list in the order they were called, and continue the program. Once process ends it will print out the list of called functions. 5 | > simpleIAT_NX_vdb is meant to be started within an already running vdb instance 6 | -------------------------------------------------------------------------------- /ida_stalkerColor.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idc 3 | 4 | # color = 0xBBGGRR 5 | # use DEFCOLOR to remove coloring 6 | 7 | # use offsets from base address to fix how ida sees things 8 | fn = idc.AskFile(0, "*.stalk", "Select stalker output file to view") 9 | if not fn: 10 | pass 11 | else: 12 | file = open(fn, 'r') 13 | a = file.read().split('\n\t ') 14 | 15 | for i in range(len(a)): 16 | a[i] = a[i].strip() 17 | 18 | for i in a: 19 | if isEnabled(int(i,16)): 20 | print "ADDR: %s" % i 21 | idc.SetColor(int(i,16), CIC_ITEM, 0x00AAFF) 22 | idaapi.refresh_idaview_anyway() 23 | 24 | #idc.Exit(0) 25 | -------------------------------------------------------------------------------- /ida/ida_stalkerColor.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idc 3 | 4 | # color = 0xBBGGRR 5 | # use DEFCOLOR to remove coloring 6 | 7 | # use offsets from base address to fix how ida sees things 8 | fn = idc.AskFile(0, "*.stalk", "Select stalker output file to view") 9 | if not fn: 10 | pass 11 | else: 12 | file = open(fn, 'r') 13 | a = file.read().split('\n\t ') 14 | 15 | for i in range(len(a)): 16 | a[i] = a[i].strip() 17 | 18 | for i in a: 19 | if isEnabled(int(i,16)): 20 | print "ADDR: %s" % i 21 | idc.SetColor(int(i,16), CIC_ITEM, 0x00AAFF) 22 | idaapi.refresh_idaview_anyway() 23 | 24 | #idc.Exit(0) 25 | -------------------------------------------------------------------------------- /extensions/README.md: -------------------------------------------------------------------------------- 1 | # extensions 2 | > Uses the new(ish) vtrace extension capability to add new commands into vdb. 3 | > 4 | > **NOTE:** Must set VDB_EXT_PATH as an environment variable. 5 | 6 | ## loadSyms.py 7 | > will attempt to load a pdb file from a path. 8 | > 9 | > usage: loadsyms 10 | 11 | ## passBack.py 12 | > Allows the debugger to hand execution control back to a running command line script. 13 | 14 | # extensions/scripts 15 | > The logic needed for the extensions is kept in this folder. Some extensions 16 | > will typically add this directory to its path. 17 | 18 | ## loadSymbols.py 19 | > The logic to load symbols is stored in this script. 20 | -------------------------------------------------------------------------------- /extensions/passBack.py: -------------------------------------------------------------------------------- 1 | ''' 2 | An extension module for vdb to pass control back to a script. 3 | 4 | ''' 5 | 6 | def passback(db, line): 7 | ''' 8 | Function to exit vdb without releasing the trace object 9 | 10 | Usage: passback 11 | 12 | Exits VDB without releasing the trace object 13 | ''' 14 | 15 | db.shutdown.set() 16 | 17 | def vdbExtension(db, trace): 18 | ''' 19 | Regiser command withing vdb 20 | 21 | Usage: vdbExtension(db, trace) 22 | db - An instance of VdbCli() (and therefor vdb...) 23 | trace - An example of a trace for the platform. 24 | ''' 25 | 26 | # Here we use our reference to the vdb debugger object 27 | # to add a command extension. 28 | db.registerCmdExtension(passback) 29 | 30 | -------------------------------------------------------------------------------- /simpleRun.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | 10 | ####################################################################### 11 | def load_binary(filepath, base=None): 12 | # Get the current vtrace object 13 | trace = vtrace.getTrace() 14 | 15 | # If attempting to attach to a 64 bit process 16 | # 64 bit python is required. 17 | trace.execute(filepath) 18 | 19 | # Start the program executing 20 | trace.run() 21 | 22 | ###################################################################### 23 | def main(argv): 24 | if len(argv) != 2: 25 | print "Usage: %s " % sys.argv[0] 26 | sys.exit(1) 27 | 28 | filepath = sys.argv[1] 29 | 30 | load_binary(filepath) 31 | 32 | if __name__ == "__main__": 33 | main(sys.argv) 34 | sys.exit(0) 35 | -------------------------------------------------------------------------------- /command_line/simpleRun.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | 10 | ####################################################################### 11 | def load_binary(filepath, base=None): 12 | # Get the current vtrace object 13 | trace = vtrace.getTrace() 14 | 15 | # If attempting to attach to a 64 bit process 16 | # 64 bit python is required. 17 | trace.execute(filepath) 18 | 19 | # Start the program executing 20 | trace.run() 21 | 22 | ###################################################################### 23 | def main(argv): 24 | if len(argv) != 2: 25 | print "Usage: %s " % sys.argv[0] 26 | sys.exit(1) 27 | 28 | filepath = sys.argv[1] 29 | 30 | load_binary(filepath) 31 | 32 | if __name__ == "__main__": 33 | main(sys.argv) 34 | sys.exit(0) 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sample scripts and things related to vtrace/vdb 2 | 3 | ## command_line 4 | > Scripts that can be run from the command prompt. 5 | > This is where all the old scripts went... 6 | 7 | ## extensions 8 | > Uses the new(ish) vtrace extension capability to add new commands into vdb. 9 | > 10 | > **NOTE:** Must set VDB_EXT_PATH as an environment variable. 11 | 12 | ### extensions/scripts 13 | > The logic needed for the extensions is kept in this folder. Some extensions 14 | > will typically add this directory to its path. 15 | 16 | ## ida 17 | > Folder for scripts that parse vdb data into ida 18 | 19 | ## other 20 | > vtrace code snippets... 21 | 22 | ## presentations 23 | > A few presentations about the vdb/vtrace api. Hopefully useful to some... 24 | 25 | ## sulley 26 | > Drop in replacement files for sulley that use vtrace instead of pydbg. 27 | > Just replace process_monitor.py and utils/crash_binning.py and it will use vtrace. 28 | > Currently only tested on windows... 29 | 30 | ## vdb 31 | > scripts that can be run within the vdb debugger using the script command. 32 | 33 | -------------------------------------------------------------------------------- /simpleAttach.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | from envi.archs.i386 import * 10 | 11 | 12 | ####################################################################### 13 | def load_binary(filePID, base=None): 14 | 15 | # Ask for the current trace object so we can play with it 16 | trace = vtrace.getTrace() 17 | 18 | # If attempting to attach to a 64 bit process 19 | # 64 bit python is required. 20 | if pid != None: 21 | trace.attach(filePID) 22 | 23 | # Start executing the program. 24 | # Will not stop until it finishes or is killed 25 | trace.run() 26 | ###################################################################### 27 | def main(argv): 28 | if len(argv) != 2: 29 | print "Usage: %s " % sys.argv[0] 30 | sys.exit(1) 31 | 32 | filePID = sys.argv[1] 33 | 34 | load_binary(filePID) 35 | 36 | if __name__ == "__main__": 37 | main(sys.argv) 38 | sys.exit(0) -------------------------------------------------------------------------------- /command_line/simpleAttach.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | from envi.archs.i386 import * 10 | 11 | 12 | ####################################################################### 13 | def load_binary(filePID, base=None): 14 | 15 | # Ask for the current trace object so we can play with it 16 | trace = vtrace.getTrace() 17 | 18 | # If attempting to attach to a 64 bit process 19 | # 64 bit python is required. 20 | if pid != None: 21 | trace.attach(filePID) 22 | 23 | # Start executing the program. 24 | # Will not stop until it finishes or is killed 25 | trace.run() 26 | ###################################################################### 27 | def main(argv): 28 | if len(argv) != 2: 29 | print "Usage: %s " % sys.argv[0] 30 | sys.exit(1) 31 | 32 | filePID = sys.argv[1] 33 | 34 | load_binary(filePID) 35 | 36 | if __name__ == "__main__": 37 | main(sys.argv) 38 | sys.exit(0) -------------------------------------------------------------------------------- /simpleFunctionList.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | 13 | ####################################################################### 14 | def load_binary(filepath, pattern, base=None): 15 | # Get the current trace object from vtrace 16 | trace = vtrace.getTrace() 17 | 18 | # If attempting to attach to a 64 bit process 19 | # 64 bit python is required. 20 | trace.execute(filepath) 21 | 22 | pattern = pattern.lower() 23 | 24 | # Get the list of all library names 25 | # Iterate over the list of function names for values that match pattern 26 | libs = trace.getNormalizedLibNames() 27 | libs.sort() 28 | for libname in libs: 29 | for sym in trace.getSymsForFile(libname): 30 | r = repr(sym) 31 | if pattern != None: 32 | if r.lower().find(pattern) == -1: 33 | continue 34 | print("0x%.8x %s" % (sym.value, r)) 35 | 36 | ###################################################################### 37 | def main(argv): 38 | if len(argv) != 3: 39 | print "Usage: %s " " "% sys.argv[0] 40 | sys.exit(1) 41 | 42 | filepath = sys.argv[1] 43 | # Pattern is the dll you want to search for function names in 44 | pattern = sys.argv[2] 45 | 46 | load_binary(filepath, pattern) 47 | 48 | if __name__ == "__main__": 49 | main(sys.argv) 50 | sys.exit(0) 51 | -------------------------------------------------------------------------------- /command_line/simpleFunctionList.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | 13 | ####################################################################### 14 | def load_binary(filepath, pattern, base=None): 15 | # Get the current trace object from vtrace 16 | trace = vtrace.getTrace() 17 | 18 | # If attempting to attach to a 64 bit process 19 | # 64 bit python is required. 20 | trace.execute(filepath) 21 | 22 | pattern = pattern.lower() 23 | 24 | # Get the list of all library names 25 | # Iterate over the list of function names for values that match pattern 26 | libs = trace.getNormalizedLibNames() 27 | libs.sort() 28 | for libname in libs: 29 | for sym in trace.getSymsForFile(libname): 30 | r = repr(sym) 31 | if pattern != None: 32 | if r.lower().find(pattern) == -1: 33 | continue 34 | print("0x%.8x %s" % (sym.value, r)) 35 | 36 | ###################################################################### 37 | def main(argv): 38 | if len(argv) != 3: 39 | print "Usage: %s " " "% sys.argv[0] 40 | sys.exit(1) 41 | 42 | filepath = sys.argv[1] 43 | # Pattern is the dll you want to search for function names in 44 | pattern = sys.argv[2] 45 | 46 | load_binary(filepath, pattern) 47 | 48 | if __name__ == "__main__": 49 | main(sys.argv) 50 | sys.exit(0) 51 | -------------------------------------------------------------------------------- /extensions/loadSyms.py: -------------------------------------------------------------------------------- 1 | ''' 2 | An extension module for vdb that will load symbols for a given library 3 | 4 | ''' 5 | import os 6 | 7 | 8 | def loadsyms(db, line): 9 | ''' 10 | A doc string for the function, becomes the doc string for the command line interface 11 | 12 | Usage: loadsyms 13 | 14 | args: space delimited 15 | library: string containing the name of the library to load symbols for 16 | (optional) pdb: path to the pdb file for that library 17 | 18 | Loads the symbols for a given library 19 | ''' 20 | import imp 21 | import os 22 | 23 | try: 24 | library, pdb = line.split() 25 | except: 26 | library = line 27 | pdb = None 28 | 29 | trace = db.getTrace() 30 | 31 | VDB_EXTENSION = os.getenv('VDB_EXT_PATH') 32 | if VDB_EXTENSION == None: 33 | VDB_EXTENSION = os.path.dirname(os.getcwd()) 34 | path = VDB_EXTENSION + '\\scripts\\loadSymbols.py' 35 | loadSym = imp.load_source('loadSym', path) 36 | symbols = loadSym.loadSymbols(trace, library, pdb=pdb) 37 | 38 | if symbols == 0: 39 | db.vprint ("[*] symbols for %s: loaded successfully" % library) 40 | elif symbols == 1: 41 | db.vprint ("[*] symbols for %s: failed to load" % library) 42 | elif symbols == 2: 43 | db.vprint ("[*] %s library not loaded" % library) 44 | 45 | 46 | def vdbExtension(db, trace): 47 | ''' 48 | Regiser command withing vdb 49 | 50 | Usage: vdbExtension(db, trace) 51 | db - An instance of VdbCli() (and therefor vdb...) 52 | trace - An example of a trace for the platform. 53 | ''' 54 | 55 | # Here we use our reference to the vdb debugger object 56 | # to add a command extension. 57 | db.registerCmdExtension(loadsyms) 58 | 59 | -------------------------------------------------------------------------------- /simpleSnapshot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | import vtrace.snapshot as vs_snap 13 | 14 | ####################################################################### 15 | def load_binary(filepath, base=None): 16 | # Get the current trace object from vtrace 17 | trace = vtrace.getTrace() 18 | 19 | # If attempting to attach to a 64 bit process 20 | # 64 bit python is required. 21 | trace.execute(filepath) 22 | ############################################################### 23 | 24 | # Call a function to set BP on OEP 25 | oep = v_api.getOEP(trace, filepath) 26 | 27 | # Set breakpoint at address 28 | bp = vtrace.Breakpoint(oep) 29 | trace.addBreakpoint(bp) 30 | 31 | # Start executing the program until you hit a breakpoint or it ends 32 | trace.run() 33 | ################################################################# 34 | 35 | # takes a snapshot of memory 36 | snap = vs_snap.takeSnapshot(trace) 37 | # saves it to a file 38 | snap.saveToFile("zTest.snap") 39 | 40 | # loads a snapshot from a filename 41 | #snap.loadSnapshot("zTest.snap") 42 | 43 | ###################################################################### 44 | def main(argv): 45 | if len(argv) != 2: 46 | print "Usage: %s " % sys.argv[0] 47 | sys.exit(1) 48 | 49 | filepath = sys.argv[1] 50 | 51 | load_binary(filepath) 52 | 53 | if __name__ == "__main__": 54 | main(sys.argv) 55 | sys.exit(0) 56 | -------------------------------------------------------------------------------- /simpleOEP.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | 12 | # The following MUST be done otherwise windows catches the stopped program 13 | # in a horrible attempt to "help". 14 | # Go to the following registry location and change the value data to 1. 15 | # HKEY_CURRENT_USER\Software\ Microsoft\Windows\Windows Error Reporting\DontShowUI 16 | 17 | ####################################################################### 18 | def load_binary(filepath, base=None): 19 | # Get the current trace object from vtrace 20 | trace = vtrace.getTrace() 21 | 22 | # If attempting to attach to a 64 bit process 23 | # 64 bit python is required. 24 | trace.execute(filepath) 25 | 26 | oep = v_api.getOEP(trace, filepath) 27 | 28 | # Set breakpoint at address 29 | bp = vtrace.Breakpoint(oep) 30 | trace.addBreakpoint(bp) 31 | 32 | # Print out all the current breakpoints as well as if they are enabled. 33 | for bp in trace.getBreakpoints(): 34 | print("%s enabled: %s" % (bp, bp.isEnabled())) 35 | 36 | # Start executing the program until you hit a breakpoint or it ends 37 | trace.run() 38 | 39 | print "Holy BreakPoint Batman!" 40 | 41 | ###################################################################### 42 | def main(argv): 43 | if len(argv) != 2: 44 | print "Usage: %s " % sys.argv[0] 45 | sys.exit(1) 46 | 47 | filepath = sys.argv[1] 48 | 49 | load_binary(filepath) 50 | 51 | if __name__ == "__main__": 52 | main(sys.argv) 53 | sys.exit(0) 54 | -------------------------------------------------------------------------------- /command_line/simpleSnapshot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | import vtrace.snapshot as vs_snap 13 | 14 | ####################################################################### 15 | def load_binary(filepath, base=None): 16 | # Get the current trace object from vtrace 17 | trace = vtrace.getTrace() 18 | 19 | # If attempting to attach to a 64 bit process 20 | # 64 bit python is required. 21 | trace.execute(filepath) 22 | ############################################################### 23 | 24 | # Call a function to set BP on OEP 25 | oep = v_api.getOEP(trace, filepath) 26 | 27 | # Set breakpoint at address 28 | bp = vtrace.Breakpoint(oep) 29 | trace.addBreakpoint(bp) 30 | 31 | # Start executing the program until you hit a breakpoint or it ends 32 | trace.run() 33 | ################################################################# 34 | 35 | # takes a snapshot of memory 36 | snap = vs_snap.takeSnapshot(trace) 37 | # saves it to a file 38 | snap.saveToFile("zTest.snap") 39 | 40 | # loads a snapshot from a filename 41 | #snap.loadSnapshot("zTest.snap") 42 | 43 | ###################################################################### 44 | def main(argv): 45 | if len(argv) != 2: 46 | print "Usage: %s " % sys.argv[0] 47 | sys.exit(1) 48 | 49 | filepath = sys.argv[1] 50 | 51 | load_binary(filepath) 52 | 53 | if __name__ == "__main__": 54 | main(sys.argv) 55 | sys.exit(0) 56 | -------------------------------------------------------------------------------- /command_line/simpleOEP.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | 12 | # The following MUST be done otherwise windows catches the stopped program 13 | # in a horrible attempt to "help". 14 | # Go to the following registry location and change the value data to 1. 15 | # HKEY_CURRENT_USER\Software\ Microsoft\Windows\Windows Error Reporting\DontShowUI 16 | 17 | ####################################################################### 18 | def load_binary(filepath, base=None): 19 | # Get the current trace object from vtrace 20 | trace = vtrace.getTrace() 21 | 22 | # If attempting to attach to a 64 bit process 23 | # 64 bit python is required. 24 | trace.execute(filepath) 25 | 26 | oep = v_api.getOEP(trace, filepath) 27 | 28 | # Set breakpoint at address 29 | bp = vtrace.Breakpoint(oep) 30 | trace.addBreakpoint(bp) 31 | 32 | # Print out all the current breakpoints as well as if they are enabled. 33 | for bp in trace.getBreakpoints(): 34 | print("%s enabled: %s" % (bp, bp.isEnabled())) 35 | 36 | # Start executing the program until you hit a breakpoint or it ends 37 | trace.run() 38 | 39 | print "Holy BreakPoint Batman!" 40 | 41 | ###################################################################### 42 | def main(argv): 43 | if len(argv) != 2: 44 | print "Usage: %s " % sys.argv[0] 45 | sys.exit(1) 46 | 47 | filepath = sys.argv[1] 48 | 49 | load_binary(filepath) 50 | 51 | if __name__ == "__main__": 52 | main(sys.argv) 53 | sys.exit(0) 54 | -------------------------------------------------------------------------------- /simpleDisasm.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import pickle 8 | from socket import htonl 9 | from optparse import OptionParser 10 | import vtrace 11 | import vdb 12 | import envi as envi 13 | import envi.archs.i386.disasm as dis 14 | from envi.archs.i386 import * 15 | import vtrace.envitools as envitools 16 | import vtrace.snapshot as vs_snap 17 | import PE as PE 18 | import binascii 19 | 20 | ####################################################################### 21 | def load_binary(shellcode, fileLoc, base=None): 22 | trace = vtrace.getTrace() 23 | 24 | if shellcode is not None: 25 | v_api.disasm(trace, binascii.unhexlify(shellcode)) 26 | 27 | else: 28 | print "FILE LOCATION: %s" % fileLoc 29 | f = open(fileLoc, 'rb') 30 | tmp = f.read() 31 | f.close() 32 | 33 | shell = binascii.unhexlify(tmp) 34 | v_api.disasm(trace, shell) 35 | 36 | trace.release() 37 | 38 | ###################################################################### 39 | def main(argv): 40 | parser = OptionParser() 41 | parser.add_option("-f", "--file", dest="fileLoc", help="input file to be parsed", action='store') 42 | parser.add_option("-s", "--shellcode", dest="shell", help="shellcode to be parsed", action='store') 43 | (options, args) = parser.parse_args() 44 | 45 | if not options.fileLoc and not options.shell: 46 | print "A mandatory option is missing\n" 47 | parser.print_help() 48 | exit(-1) 49 | 50 | if len(argv) != 3: 51 | parser.print_help() 52 | sys.exit(1) 53 | 54 | shellcode = options.shell 55 | fileLoc = options.fileLoc 56 | 57 | load_binary(shellcode, fileLoc) 58 | 59 | if __name__ == "__main__": 60 | main(sys.argv) 61 | sys.exit(0) 62 | -------------------------------------------------------------------------------- /command_line/simpleDisasm.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import pickle 8 | from socket import htonl 9 | from optparse import OptionParser 10 | import vtrace 11 | import vdb 12 | import envi as envi 13 | import envi.archs.i386.disasm as dis 14 | from envi.archs.i386 import * 15 | import vtrace.envitools as envitools 16 | import vtrace.snapshot as vs_snap 17 | import PE as PE 18 | import binascii 19 | 20 | ####################################################################### 21 | def load_binary(shellcode, fileLoc, base=None): 22 | trace = vtrace.getTrace() 23 | 24 | if shellcode is not None: 25 | v_api.disasm(trace, binascii.unhexlify(shellcode)) 26 | 27 | else: 28 | print "FILE LOCATION: %s" % fileLoc 29 | f = open(fileLoc, 'rb') 30 | tmp = f.read() 31 | f.close() 32 | 33 | shell = binascii.unhexlify(tmp) 34 | v_api.disasm(trace, shell) 35 | 36 | trace.release() 37 | 38 | ###################################################################### 39 | def main(argv): 40 | parser = OptionParser() 41 | parser.add_option("-f", "--file", dest="fileLoc", help="input file to be parsed", action='store') 42 | parser.add_option("-s", "--shellcode", dest="shell", help="shellcode to be parsed", action='store') 43 | (options, args) = parser.parse_args() 44 | 45 | if not options.fileLoc and not options.shell: 46 | print "A mandatory option is missing\n" 47 | parser.print_help() 48 | exit(-1) 49 | 50 | if len(argv) != 3: 51 | parser.print_help() 52 | sys.exit(1) 53 | 54 | shellcode = options.shell 55 | fileLoc = options.fileLoc 56 | 57 | load_binary(shellcode, fileLoc) 58 | 59 | if __name__ == "__main__": 60 | main(sys.argv) 61 | sys.exit(0) 62 | -------------------------------------------------------------------------------- /extensions/scripts/loadSymbols.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def loadSymbols(trace, library, pdb=None): 4 | 5 | import PE as PE 6 | SYMBOLS_PATH = os.getenv('_NT_SYMBOL_PATH') 7 | if SYMBOLS_PATH == None: 8 | SYMBOLS_PATH = "C:\\Symbols" 9 | 10 | baseaddr = trace.getMeta('LibraryBases').get(library) 11 | 12 | if baseaddr == None: 13 | #raise Exception("%s library not loaded" % library) 14 | return 2 15 | else: 16 | pe = PE.peFromMemoryObject(trace, baseaddr) 17 | oh = pe.IMAGE_NT_HEADERS.OptionalHeader 18 | deb = pe.IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[PE.IMAGE_DIRECTORY_ENTRY_DEBUG] 19 | virtaddr = deb.vsGetField('VirtualAddress') 20 | virtsize = deb.vsGetField('Size') 21 | poff = pe.rvaToOffset(virtaddr) 22 | 23 | if poff == 0: 24 | return 1 25 | 26 | imageDebugDirectory = pe.readStructAtOffset(poff, 'pe.IMAGE_DEBUG_DIRECTORY') 27 | addrRawData = imageDebugDirectory.vsGetField('AddressOfRawData') 28 | cvInfoPdb = pe.readStructAtOffset(addrRawData, 'pe.CV_INFO_PDB70') 29 | cvGuid = cvInfoPdb.vsGetField('GuidSignature') 30 | cvSig = cvInfoPdb.vsGetField('CvSignature') 31 | tmpGuid = cvGuid.vsGetFields() 32 | tmpGuid.sort() 33 | guid = bytearray(16) 34 | for elem in range(len(tmpGuid)): 35 | guid[elem] = tmpGuid[elem][1].vsGetValue() 36 | 37 | guid_str = str(guid).encode('hex') 38 | 39 | if pdb == None: 40 | sympath = os.getenv('_NT_SYMBOL_PATH') 41 | if sympath == None: 42 | # Guess that the symbols are in the typical spot for windows. 43 | sympath = SYMBOLS_PATH 44 | filename = sympath + "\\" + library + ".pdb\\" + guid_str + "1\\" + library + ".pdb" 45 | else: 46 | filename = pdb 47 | 48 | if os.path.isfile(filename): 49 | try: 50 | trace.parseWithDbgHelp(filename, baseaddr, library) 51 | return 0 52 | except: 53 | return 1 54 | else: 55 | return 1 56 | 57 | -------------------------------------------------------------------------------- /simpleIAT.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | 10 | import envi 11 | import envi.memory as mem 12 | from envi.archs.i386 import * 13 | 14 | import vtrace.envitools as envitools 15 | 16 | import PE 17 | import vstruct 18 | 19 | import vdb.recon as v_recon 20 | import vdb.recon.sniper as v_sniper 21 | import vdb.stalker as v_stalker 22 | 23 | debug = True 24 | 25 | ####################################################################### 26 | def load_binary(filepath, base=None): 27 | 28 | trace = vtrace.getTrace() 29 | trace.execute(filepath) 30 | ####################################################################### 31 | # Call a function to set BP on OEP 32 | oep = v_api.getOEP(trace, filepath) 33 | 34 | # Set breakpoint at address 35 | bp = vtrace.Breakpoint(oep) 36 | trace.addBreakpoint(bp) 37 | 38 | ###################################################################### 39 | # Start executing the program until you hit a breakpoint or it ends 40 | trace.run() 41 | ####################################################################### 42 | # function takes in just filename not the full path to filename.exe 43 | exeName = filepath.split(".exe")[0] 44 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 45 | 46 | # Get the list of imported functions to compare against 47 | base, importTable = v_api.printIAT(trace, fileName, debug) 48 | 49 | ####################################################################### 50 | ###################################################################### 51 | def main(argv): 52 | if len(argv) != 2: 53 | print "Usage: %s " % sys.argv[0] 54 | sys.exit(1) 55 | 56 | filepath = sys.argv[1] 57 | 58 | load_binary(filepath) 59 | 60 | if __name__ == "__main__": 61 | main(sys.argv) 62 | sys.exit(0) 63 | -------------------------------------------------------------------------------- /command_line/simpleIAT.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | 10 | import envi 11 | import envi.memory as mem 12 | from envi.archs.i386 import * 13 | 14 | import vtrace.envitools as envitools 15 | 16 | import PE 17 | import vstruct 18 | 19 | import vdb.recon as v_recon 20 | import vdb.recon.sniper as v_sniper 21 | import vdb.stalker as v_stalker 22 | 23 | debug = True 24 | 25 | ####################################################################### 26 | def load_binary(filepath, base=None): 27 | 28 | trace = vtrace.getTrace() 29 | trace.execute(filepath) 30 | ####################################################################### 31 | # Call a function to set BP on OEP 32 | oep = v_api.getOEP(trace, filepath) 33 | 34 | # Set breakpoint at address 35 | bp = vtrace.Breakpoint(oep) 36 | trace.addBreakpoint(bp) 37 | 38 | ###################################################################### 39 | # Start executing the program until you hit a breakpoint or it ends 40 | trace.run() 41 | ####################################################################### 42 | # function takes in just filename not the full path to filename.exe 43 | exeName = filepath.split(".exe")[0] 44 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 45 | 46 | # Get the list of imported functions to compare against 47 | base, importTable = v_api.printIAT(trace, fileName, debug) 48 | 49 | ####################################################################### 50 | ###################################################################### 51 | def main(argv): 52 | if len(argv) != 2: 53 | print "Usage: %s " % sys.argv[0] 54 | sys.exit(1) 55 | 56 | filepath = sys.argv[1] 57 | 58 | load_binary(filepath) 59 | 60 | if __name__ == "__main__": 61 | main(sys.argv) 62 | sys.exit(0) 63 | -------------------------------------------------------------------------------- /simpleStalker.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | 11 | import envi 12 | import envi.memory as mem 13 | from envi.archs.i386 import * 14 | 15 | import vdb.stalker as v_stalker 16 | 17 | debug = False 18 | 19 | ################################################################### 20 | ################################################################### 21 | def load_binary(filepath, base=None): 22 | 23 | # Get the current trace object from vtrace 24 | trace = vtrace.getTrace() 25 | trace.setMode("FastBreak", True) 26 | 27 | # If attempting to attach to a 64 bit process 28 | # 64 bit python is required. 29 | trace.execute(filepath) 30 | 31 | # Call a function to set BP on OEP 32 | oep = v_api.getOEP(trace, filepath) 33 | print "OEP: %x" % oep 34 | ########################################################## 35 | # Stalker 36 | #addr is here since child process doens't start at oep 37 | addr = oep 38 | 39 | try: 40 | v_stalker.addStalkerEntry(trace, addr) 41 | except: 42 | pass 43 | print('Added 0x%.8x to Stalker list' % addr) 44 | ###################################################################### 45 | ## Beyond this point the debugger is attached to the child process 46 | ## 47 | trace.setMode("FastBreak", True) 48 | while trace.isAttached(): 49 | trace.run() 50 | 51 | f = file("zTest.stalk", "wb") 52 | 53 | # Prints out the current stalker hits 54 | # Not currently working.... 55 | #print('Current Stalker Hits:') 56 | for hitva in v_stalker.getStalkerHits(trace): 57 | print('\t 0x%.8x' % hitva) 58 | f.write('\t 0x%.8x\n' % hitva) 59 | f.close() 60 | 61 | ###################################################################### 62 | def main(argv): 63 | if len(argv) != 2: 64 | print "Usage: %s " % sys.argv[0] 65 | sys.exit(1) 66 | 67 | filepath = sys.argv[1] 68 | 69 | load_binary(filepath) 70 | 71 | if __name__ == "__main__": 72 | main(sys.argv) 73 | sys.exit(0) 74 | -------------------------------------------------------------------------------- /command_line/simpleStalker.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | 11 | import envi 12 | import envi.memory as mem 13 | from envi.archs.i386 import * 14 | 15 | import vdb.stalker as v_stalker 16 | 17 | debug = False 18 | 19 | ################################################################### 20 | ################################################################### 21 | def load_binary(filepath, base=None): 22 | 23 | # Get the current trace object from vtrace 24 | trace = vtrace.getTrace() 25 | trace.setMode("FastBreak", True) 26 | 27 | # If attempting to attach to a 64 bit process 28 | # 64 bit python is required. 29 | trace.execute(filepath) 30 | 31 | # Call a function to set BP on OEP 32 | oep = v_api.getOEP(trace, filepath) 33 | print "OEP: %x" % oep 34 | ########################################################## 35 | # Stalker 36 | #addr is here since child process doens't start at oep 37 | addr = oep 38 | 39 | try: 40 | v_stalker.addStalkerEntry(trace, addr) 41 | except: 42 | pass 43 | print('Added 0x%.8x to Stalker list' % addr) 44 | ###################################################################### 45 | ## Beyond this point the debugger is attached to the child process 46 | ## 47 | trace.setMode("FastBreak", True) 48 | while trace.isAttached(): 49 | trace.run() 50 | 51 | f = file("zTest.stalk", "wb") 52 | 53 | # Prints out the current stalker hits 54 | # Not currently working.... 55 | #print('Current Stalker Hits:') 56 | for hitva in v_stalker.getStalkerHits(trace): 57 | print('\t 0x%.8x' % hitva) 58 | f.write('\t 0x%.8x\n' % hitva) 59 | f.close() 60 | 61 | ###################################################################### 62 | def main(argv): 63 | if len(argv) != 2: 64 | print "Usage: %s " % sys.argv[0] 65 | sys.exit(1) 66 | 67 | filepath = sys.argv[1] 68 | 69 | load_binary(filepath) 70 | 71 | if __name__ == "__main__": 72 | main(sys.argv) 73 | sys.exit(0) 74 | -------------------------------------------------------------------------------- /command_line/README.md: -------------------------------------------------------------------------------- 1 | # Sample scripts using the vtrace API 2 | 3 | > **NOTE:** To run these scritps you need the latest version of vdb from: 4 | > [http://visi.kenshoto.com/releases/](http://visi.kenshoto.com/releases/) 5 | > 6 | > Untar the latest version and update the VDB_ROOT in the scripts to make them work. 7 | 8 | ## simpleAPI 9 | > List of functions to use as reference on how to accomplish specific tasks. 10 | 11 | ## simpleAttach 12 | > Script that attaches to a given PID and continues execution of the program. 13 | 14 | ## simpleDisasm 15 | > Script that converts a string of hex data to assembly output. 16 | 17 | ## simpleFollowChild 18 | > Script that follows a child process created from CreateProcessA in windows. Will breakpoint on the first instruction executing in the child process. 19 | 20 | ## simpleFunctionList 21 | > Script that outputs all the functions in a dll. 22 | 23 | ## simpleIAT 24 | > Prints out the import table for the given executable. 25 | 26 | ## simpleIAT_NX 27 | > Extension of simpleIAT script. Scripts will set the IAT of a binary to unreadable causing a signal to be thrown on each external library reference and call. The signal is then caught by a custom notifier class that will log them into a list in the order they were called, and continue the program. Once process ends it will print out the list of called functions. 28 | > The difference between the two scripts is that simpleIAT_NX_vdb is meant to be started within an already running vdb instance, simpleIAT_NX can be run from a commandline directly. 29 | 30 | ## simpleNotifier 31 | > Script that implements a notifier class to output data when specific signals are caught. 32 | 33 | ## simpleOEP 34 | > Script that parses the PE headers and calculates Original Entry Point (OEP). 35 | 36 | ## simpleReg 37 | > Script that prints out the current values of some registers. 38 | 39 | ## simpleRet 40 | > Calculates the return address of a function upon entering into the function. 41 | 42 | ## simpleRun 43 | > Script showing how to start a program with the debugger attached and continue execution. 44 | 45 | ## simpleSnapshot 46 | > Takes a snapshot of memory after a process is run to OEP. Saves the snapshot to a file called zTest.snap. 47 | 48 | ## simpleStalker 49 | > Uses the stalker functionality within vtrace. 50 | 51 | ## simpleStalker_ChildProc 52 | > Uses the stalker functionality to stalk a child process. Combination of the simpleFollowChild and simpleStalker scripts. 53 | -------------------------------------------------------------------------------- /simpleRet.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | 13 | ####################################################################### 14 | def load_binary(filepath, base=None): 15 | # Get the current trace object from vtrace 16 | trace = vtrace.getTrace() 17 | 18 | # If attempting to attach to a 64 bit process 19 | # 64 bit python is required. 20 | trace.execute(filepath) 21 | 22 | # Call a function to set BP on OEP 23 | oep = v_api.getOEP(trace, filepath) 24 | 25 | # Set breakpoint at address 26 | bp = vtrace.Breakpoint(oep) 27 | trace.addBreakpoint(bp) 28 | 29 | # Print out all the current breakpoints as well as if they are enabled. 30 | for bp in trace.getBreakpoints(): 31 | print("%s enabled: %s" % (bp, bp.isEnabled())) 32 | 33 | # Start executing the program until you hit a breakpoint or it ends 34 | trace.run() 35 | ############################################################## 36 | # At this point you are at OEP of the program 37 | 38 | # We know that there is a call 5 instructions in 39 | # There are ways to programmatically find a call 40 | for i in range(5): 41 | trace.stepi() 42 | 43 | # Print the value of EIP as a long and as hex 44 | print "\n" 45 | print "EIP: ", trace.getRegister(REG_EIP) 46 | print "HEX EIP: ", hex(trace.getRegister(REG_EIP)) 47 | 48 | # Once you are in the function you can read the value of ESP 49 | # ESP points to the value of the return address 50 | print "\n" 51 | esp = trace.getRegister(REG_ESP) 52 | retaddr = trace.readMemory(esp, 4) 53 | 54 | # Returns the exact memory locations 55 | # Just in the WRONG order 56 | print "RET: ", retaddr.encode('hex') 57 | 58 | # This returns the address correctly formatted 59 | print "RET: ", hex(struct.unpack("I",retaddr)[0]) 60 | 61 | ###################################################################### 62 | def main(argv): 63 | if len(argv) != 2: 64 | print "Usage: %s " % sys.argv[0] 65 | sys.exit(1) 66 | 67 | filepath = sys.argv[1] 68 | 69 | load_binary(filepath) 70 | 71 | if __name__ == "__main__": 72 | main(sys.argv) 73 | sys.exit(0) 74 | -------------------------------------------------------------------------------- /command_line/simpleRet.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | 13 | ####################################################################### 14 | def load_binary(filepath, base=None): 15 | # Get the current trace object from vtrace 16 | trace = vtrace.getTrace() 17 | 18 | # If attempting to attach to a 64 bit process 19 | # 64 bit python is required. 20 | trace.execute(filepath) 21 | 22 | # Call a function to set BP on OEP 23 | oep = v_api.getOEP(trace, filepath) 24 | 25 | # Set breakpoint at address 26 | bp = vtrace.Breakpoint(oep) 27 | trace.addBreakpoint(bp) 28 | 29 | # Print out all the current breakpoints as well as if they are enabled. 30 | for bp in trace.getBreakpoints(): 31 | print("%s enabled: %s" % (bp, bp.isEnabled())) 32 | 33 | # Start executing the program until you hit a breakpoint or it ends 34 | trace.run() 35 | ############################################################## 36 | # At this point you are at OEP of the program 37 | 38 | # We know that there is a call 5 instructions in 39 | # There are ways to programmatically find a call 40 | for i in range(5): 41 | trace.stepi() 42 | 43 | # Print the value of EIP as a long and as hex 44 | print "\n" 45 | print "EIP: ", trace.getRegister(REG_EIP) 46 | print "HEX EIP: ", hex(trace.getRegister(REG_EIP)) 47 | 48 | # Once you are in the function you can read the value of ESP 49 | # ESP points to the value of the return address 50 | print "\n" 51 | esp = trace.getRegister(REG_ESP) 52 | retaddr = trace.readMemory(esp, 4) 53 | 54 | # Returns the exact memory locations 55 | # Just in the WRONG order 56 | print "RET: ", retaddr.encode('hex') 57 | 58 | # This returns the address correctly formatted 59 | print "RET: ", hex(struct.unpack("I",retaddr)[0]) 60 | 61 | ###################################################################### 62 | def main(argv): 63 | if len(argv) != 2: 64 | print "Usage: %s " % sys.argv[0] 65 | sys.exit(1) 66 | 67 | filepath = sys.argv[1] 68 | 69 | load_binary(filepath) 70 | 71 | if __name__ == "__main__": 72 | main(sys.argv) 73 | sys.exit(0) 74 | -------------------------------------------------------------------------------- /simpleReg.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | 12 | ####################################################################### 13 | def load_binary(filepath, base=None): 14 | # Get the current trace object from vtrace 15 | trace = vtrace.getTrace() 16 | trace.execute(filepath) 17 | ###################################################################### 18 | # Call a function to set BP on OEP 19 | oep = v_api.getOEP(trace, filepath) 20 | 21 | # Set breakpoint at address 22 | bp = vtrace.Breakpoint(oep) 23 | trace.addBreakpoint(bp) 24 | 25 | # Print out all the current breakpoints as well as if they are enabled. 26 | for bp in trace.getBreakpoints(): 27 | print("%s enabled: %s" % (bp, bp.isEnabled())) 28 | ###################################################################### 29 | # Start executing the program until you hit a breakpoint or it ends 30 | trace.run() 31 | ###################################################################### 32 | # print out the value of EIP as a long and as a hex value 33 | print "\n" 34 | print "EIP: ", trace.getRegister(REG_EIP) 35 | print "HEX EIP: ", hex(trace.getRegister(REG_EIP)) 36 | 37 | # Read the address of EIP 38 | eip = trace.getRegister(REG_EIP) 39 | # Read the memory values pointed to by EIP 40 | s = trace.readMemory(eip,15) 41 | # Determine the opcode of the memory pointed to by EIP 42 | op1 = trace.makeOpcode(s, 0, eip) 43 | print "OP CODE: ", op1 44 | 45 | # print out the value of EAX as a long and as a hex value 46 | print "\n" 47 | print "EAX: ", trace.getRegister(REG_EAX) 48 | print "HEX EAX: ", hex(trace.getRegister(REG_EAX)) 49 | 50 | # Print out the value of ESP as a long and as a hex value 51 | print "\n" 52 | print "ESP: ", trace.getRegister(REG_ESP) 53 | print "HEX ESP: ", hex(trace.getRegister(REG_ESP)) 54 | 55 | ###################################################################### 56 | def main(argv): 57 | if len(argv) != 2: 58 | print "Usage: %s " % sys.argv[0] 59 | sys.exit(1) 60 | 61 | filepath = sys.argv[1] 62 | 63 | load_binary(filepath) 64 | 65 | if __name__ == "__main__": 66 | main(sys.argv) 67 | sys.exit(0) 68 | -------------------------------------------------------------------------------- /command_line/simpleReg.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | 12 | ####################################################################### 13 | def load_binary(filepath, base=None): 14 | # Get the current trace object from vtrace 15 | trace = vtrace.getTrace() 16 | trace.execute(filepath) 17 | ###################################################################### 18 | # Call a function to set BP on OEP 19 | oep = v_api.getOEP(trace, filepath) 20 | 21 | # Set breakpoint at address 22 | bp = vtrace.Breakpoint(oep) 23 | trace.addBreakpoint(bp) 24 | 25 | # Print out all the current breakpoints as well as if they are enabled. 26 | for bp in trace.getBreakpoints(): 27 | print("%s enabled: %s" % (bp, bp.isEnabled())) 28 | ###################################################################### 29 | # Start executing the program until you hit a breakpoint or it ends 30 | trace.run() 31 | ###################################################################### 32 | # print out the value of EIP as a long and as a hex value 33 | print "\n" 34 | print "EIP: ", trace.getRegister(REG_EIP) 35 | print "HEX EIP: ", hex(trace.getRegister(REG_EIP)) 36 | 37 | # Read the address of EIP 38 | eip = trace.getRegister(REG_EIP) 39 | # Read the memory values pointed to by EIP 40 | s = trace.readMemory(eip,15) 41 | # Determine the opcode of the memory pointed to by EIP 42 | op1 = trace.makeOpcode(s, 0, eip) 43 | print "OP CODE: ", op1 44 | 45 | # print out the value of EAX as a long and as a hex value 46 | print "\n" 47 | print "EAX: ", trace.getRegister(REG_EAX) 48 | print "HEX EAX: ", hex(trace.getRegister(REG_EAX)) 49 | 50 | # Print out the value of ESP as a long and as a hex value 51 | print "\n" 52 | print "ESP: ", trace.getRegister(REG_ESP) 53 | print "HEX ESP: ", hex(trace.getRegister(REG_ESP)) 54 | 55 | ###################################################################### 56 | def main(argv): 57 | if len(argv) != 2: 58 | print "Usage: %s " % sys.argv[0] 59 | sys.exit(1) 60 | 61 | filepath = sys.argv[1] 62 | 63 | load_binary(filepath) 64 | 65 | if __name__ == "__main__": 66 | main(sys.argv) 67 | sys.exit(0) 68 | -------------------------------------------------------------------------------- /simpleStalker_ChildProc.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | 11 | import envi 12 | import envi.memory as mem 13 | from envi.archs.i386 import * 14 | 15 | import vdb.stalker as v_stalker 16 | 17 | debug = False 18 | 19 | ################################################################### 20 | ################################################################### 21 | def load_binary(filepath, base=None): 22 | 23 | # Get the current trace object from vtrace 24 | trace = vtrace.getTrace() 25 | trace.setMode("FastBreak", True) 26 | 27 | # If attempting to attach to a 64 bit process 28 | # 64 bit python is required. 29 | trace.execute(filepath) 30 | 31 | # Call a function to set BP on OEP 32 | oep = v_api.getOEP(trace, filepath) 33 | print "OEP: %x" % oep 34 | 35 | ####################################################################### 36 | # Add a breakpoint on CreateProcessA 37 | # Run until the breakpoint 38 | pattern = "kernel32.CreateProcessA" 39 | v_api.setBpOnPattern(trace, pattern) 40 | trace.run() 41 | trace = v_api.followCreateProcessA(trace) 42 | ########################################################## 43 | # Stalker 44 | #addr is here since child process doens't start at oep 45 | addr = 0x004015ac 46 | 47 | try: 48 | v_stalker.addStalkerEntry(trace, addr) 49 | except: 50 | pass 51 | print('Added 0x%.8x to Stalker list' % addr) 52 | ###################################################################### 53 | ## Beyond this point the debugger is attached to the child process 54 | ## 55 | trace.setMode("FastBreak", True) 56 | while trace.isAttached(): 57 | trace.run() 58 | 59 | f = file("zTest.stalk", "wb") 60 | 61 | # Prints out the current stalker hits 62 | # Not currently working.... 63 | #print('Current Stalker Hits:') 64 | for hitva in v_stalker.getStalkerHits(trace): 65 | print('\t 0x%.8x' % hitva) 66 | f.write('\t 0x%.8x\n' % hitva) 67 | f.close() 68 | 69 | ###################################################################### 70 | def main(argv): 71 | if len(argv) != 2: 72 | print "Usage: %s " % sys.argv[0] 73 | sys.exit(1) 74 | 75 | filepath = sys.argv[1] 76 | 77 | load_binary(filepath) 78 | 79 | if __name__ == "__main__": 80 | main(sys.argv) 81 | sys.exit(0) 82 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Sample scripts using the vtrace API 2 | 3 | NOTES: 4 | To run these scritps you need the latest version of vdb from: 5 | http://visi.kenshoto.com/releases/ 6 | 7 | Untar the latest version and update the VDB_ROOT in the scripts to make them work. 8 | 9 | ## 10 | simpleAPI 11 | List of functions to use as reference on how to accomplish specific tasks. 12 | 13 | simpleAttach 14 | Script that attaches to a given PID and continues execution of the program. 15 | 16 | simpleDisasm 17 | Script that converts a string of hex data to assembly output. 18 | 19 | simpleFollowChild 20 | Script that follows a child process created from CreateProcessA in windows. Will breakpoint on the first instruction executing in the child process. 21 | 22 | simpleFunctionList 23 | Script that outputs all the functions in a dll. 24 | 25 | simpleIAT 26 | Prints out the import table for the given executable. 27 | 28 | simpleIAT_NX 29 | simpleIAT_NX_vdb 30 | Extension of simpleIAT script. Scripts will set the IAT of a binary to unreadable causing a signal to be thrown on each external library reference and call. The signal is then caught by a custom notifier class that will log them into a list in the order they were called, and continue the program. Once process ends it will print out the list of called functions. 31 | The difference between the two scripts is that simpleIAT_NX_vdb is meant to be started within an already running vdb instance, simpleIAT_NX can be run from a commandline directly. 32 | 33 | simpleNotifier 34 | Script that implements a notifier class to output data when specific signals are caught. 35 | 36 | simpleOEP 37 | Script that parses the PE headers and calculates Original Entry Point (OEP). 38 | 39 | simpleReg 40 | Script that prints out the current values of some registers. 41 | 42 | simpleRet 43 | Calculates the return address of a function upon entering into the function. 44 | 45 | simpleRun 46 | Script showing how to start a program with the debugger attached and continue execution. 47 | 48 | simpleSnapshot 49 | Takes a snapshot of memory after a process is run to OEP. Saves the snapshot to a file called zTest.snap. 50 | 51 | simpleStalker 52 | Uses the stalker functionality within vtrace. 53 | 54 | simpleStalker_ChildProc 55 | Uses the stalker functionality to stalk a child process. Combination of the simpleFollowChild and simpleStalker scripts. 56 | 57 | ## 58 | ida_stalker 59 | Will colorize an IDA graph based on the contents of simpleStalker output. 60 | Does NOT account for the change of base addresses yet. 61 | -------------------------------------------------------------------------------- /command_line/simpleStalker_ChildProc.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | 11 | import envi 12 | import envi.memory as mem 13 | from envi.archs.i386 import * 14 | 15 | import vdb.stalker as v_stalker 16 | 17 | debug = False 18 | 19 | ################################################################### 20 | ################################################################### 21 | def load_binary(filepath, base=None): 22 | 23 | # Get the current trace object from vtrace 24 | trace = vtrace.getTrace() 25 | trace.setMode("FastBreak", True) 26 | 27 | # If attempting to attach to a 64 bit process 28 | # 64 bit python is required. 29 | trace.execute(filepath) 30 | 31 | # Call a function to set BP on OEP 32 | oep = v_api.getOEP(trace, filepath) 33 | print "OEP: %x" % oep 34 | 35 | ####################################################################### 36 | # Add a breakpoint on CreateProcessA 37 | # Run until the breakpoint 38 | pattern = "kernel32.CreateProcessA" 39 | v_api.setBpOnPattern(trace, pattern) 40 | trace.run() 41 | trace = v_api.followCreateProcessA(trace) 42 | ########################################################## 43 | # Stalker 44 | #addr is here since child process doens't start at oep 45 | addr = 0x004015ac 46 | 47 | try: 48 | v_stalker.addStalkerEntry(trace, addr) 49 | except: 50 | pass 51 | print('Added 0x%.8x to Stalker list' % addr) 52 | ###################################################################### 53 | ## Beyond this point the debugger is attached to the child process 54 | ## 55 | trace.setMode("FastBreak", True) 56 | while trace.isAttached(): 57 | trace.run() 58 | 59 | f = file("zTest.stalk", "wb") 60 | 61 | # Prints out the current stalker hits 62 | # Not currently working.... 63 | #print('Current Stalker Hits:') 64 | for hitva in v_stalker.getStalkerHits(trace): 65 | print('\t 0x%.8x' % hitva) 66 | f.write('\t 0x%.8x\n' % hitva) 67 | f.close() 68 | 69 | ###################################################################### 70 | def main(argv): 71 | if len(argv) != 2: 72 | print "Usage: %s " % sys.argv[0] 73 | sys.exit(1) 74 | 75 | filepath = sys.argv[1] 76 | 77 | load_binary(filepath) 78 | 79 | if __name__ == "__main__": 80 | main(sys.argv) 81 | sys.exit(0) 82 | -------------------------------------------------------------------------------- /simpleFuzz.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | import time 5 | import threading 6 | 7 | # Change this to your vdb path 8 | VDB_ROOT = "" 9 | sys.path.append(VDB_ROOT) 10 | 11 | import vtrace 12 | import vdb 13 | from envi.archs.i386 import * 14 | 15 | # Hard coded for IE 16 | exepath = "C:\Program Files (x86)\Internet Explorer\iexplore.exe" 17 | 18 | ####################################################################### 19 | def getOpCode(trace, eip): 20 | s = trace.readMemory(eip,15) 21 | op1 = trace.makeOpcode(s, 0, eip) 22 | return op1 23 | 24 | def printInfo(trace): 25 | # print ("DIR: %s") % (dir(trace)) 26 | 27 | # print("META: %s") % (trace.metadata) 28 | eip = trace.getRegisterByName("eip") 29 | 30 | 31 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 32 | disLen = len(dis) 33 | opcode = trace.readMemory(eip, len(dis)) 34 | 35 | es = trace.getRegisterByName("es") 36 | ds = trace.getRegisterByName("ds") 37 | cs = trace.getRegisterByName("cs") 38 | 39 | ef = trace.getRegisterByName("eflags") 40 | 41 | edi = trace.getRegister(REG_EDI) 42 | esi = trace.getRegister(REG_ESI) 43 | esp = trace.getRegister(REG_ESP) 44 | 45 | print "[*] Bestname: ", trace.getSymByAddr(eip, exact=False) 46 | print "%16s: %s" % ("EIP", hex(eip)) 47 | 48 | print "%16s: %s" % ("DIS", dis) 49 | print "%16s: %s" % ("OPCODE", repr(opcode)) 50 | print "%16s: %s" % ("ES", es) 51 | print "%16s: %s" % ("DS", ds) 52 | print "%16s: %s" % ("CS", cs) 53 | print "%16s: %s" % ("EAX", hex(trace.getRegister(REG_EAX))) 54 | print "%16s: %s" % ("EBX", hex(trace.getRegister(REG_EBX))) 55 | print "%16s: %s" % ("ECX", hex(trace.getRegister(REG_ECX))) 56 | print "%16s: %s" % ("EDX", hex(trace.getRegister(REG_EDX))) 57 | 58 | print "%16s: %s" % ("EDI", hex(edi)) 59 | print "%16s: %s" % ("ESI", hex(esi)) 60 | 61 | print "%16s: %s" % ("ESP", hex(esp)) 62 | print "%16s: %s" % ("[ESP]", repr(trace.readMemory(esp, 4))) 63 | 64 | print("%16s: %s" % ("Direction", bool(ef & EFLAGS_DF))) 65 | 66 | 67 | ####################################################################### 68 | def load_binary(trace, filepath, base=None): 69 | global exepath 70 | 71 | # If attempting to attach to a 64 bit process 72 | # 64 bit python is required. 73 | # sample cmdline: C:\Program Files (x86)\Internet Explorer\iexplore.exe C:\test\ie\index_0.html 74 | cmdline = exepath + " " + filepath 75 | trace.execute(cmdline) 76 | 77 | print("Executing: %s") % (cmdline) 78 | # Start the program executing 79 | trace.run() 80 | 81 | ###################################################################### 82 | def main(argv): 83 | global exepath 84 | 85 | if len(argv) != 2: 86 | print "Usage: %s " % sys.argv[0] 87 | sys.exit(1) 88 | 89 | # verify that the path to test files is valid 90 | filepath = sys.argv[1] 91 | if os.path.isdir(filepath) == False: 92 | sys.exit("Invalid Input Directory") 93 | 94 | # Get the current vtrace object 95 | trace = vtrace.getTrace() 96 | 97 | threads = [] 98 | crashes = [] 99 | count = 1 100 | print ("[*] Starting fuzz process") 101 | 102 | # call load_binary on the filenames stored in the directory 103 | for fname in os.listdir(filepath): 104 | #print fname 105 | cmdline = filepath + "\\" + fname 106 | 107 | t = threading.Thread(target = load_binary, args = (trace, cmdline,)) 108 | threads.append(t) 109 | t.start() 110 | time.sleep(10) 111 | if trace.isRunning(): 112 | trace.sendBreak() 113 | printInfo(trace) 114 | 115 | print ("[*] Death to the process %d") % (trace.getPid()) 116 | trace.kill() 117 | else: 118 | print ("[*] %s crashed") % (fname) 119 | time.sleep(1) 120 | count += 1 121 | 122 | print ("") 123 | print ("[*] Death to all %d of %d processes") % ( (count-len(crashes)), count ) 124 | print ("[*] %d files caused crashes") % (len(crashes)) 125 | for i in crashes: 126 | print ("\t filename: %s") % (i) 127 | 128 | if __name__ == "__main__": 129 | main(sys.argv) 130 | sys.exit(0) 131 | -------------------------------------------------------------------------------- /command_line/simpleFuzz.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | import time 5 | import threading 6 | 7 | # Change this to your vdb path 8 | VDB_ROOT = "" 9 | sys.path.append(VDB_ROOT) 10 | 11 | import vtrace 12 | import vdb 13 | from envi.archs.i386 import * 14 | 15 | # Hard coded for IE 16 | exepath = "C:\Program Files (x86)\Internet Explorer\iexplore.exe" 17 | 18 | ####################################################################### 19 | def getOpCode(trace, eip): 20 | s = trace.readMemory(eip,15) 21 | op1 = trace.makeOpcode(s, 0, eip) 22 | return op1 23 | 24 | def printInfo(trace): 25 | # print ("DIR: %s") % (dir(trace)) 26 | 27 | # print("META: %s") % (trace.metadata) 28 | eip = trace.getRegisterByName("eip") 29 | 30 | 31 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 32 | disLen = len(dis) 33 | opcode = trace.readMemory(eip, len(dis)) 34 | 35 | es = trace.getRegisterByName("es") 36 | ds = trace.getRegisterByName("ds") 37 | cs = trace.getRegisterByName("cs") 38 | 39 | ef = trace.getRegisterByName("eflags") 40 | 41 | edi = trace.getRegister(REG_EDI) 42 | esi = trace.getRegister(REG_ESI) 43 | esp = trace.getRegister(REG_ESP) 44 | 45 | print "[*] Bestname: ", trace.getSymByAddr(eip, exact=False) 46 | print "%16s: %s" % ("EIP", hex(eip)) 47 | 48 | print "%16s: %s" % ("DIS", dis) 49 | print "%16s: %s" % ("OPCODE", repr(opcode)) 50 | print "%16s: %s" % ("ES", es) 51 | print "%16s: %s" % ("DS", ds) 52 | print "%16s: %s" % ("CS", cs) 53 | print "%16s: %s" % ("EAX", hex(trace.getRegister(REG_EAX))) 54 | print "%16s: %s" % ("EBX", hex(trace.getRegister(REG_EBX))) 55 | print "%16s: %s" % ("ECX", hex(trace.getRegister(REG_ECX))) 56 | print "%16s: %s" % ("EDX", hex(trace.getRegister(REG_EDX))) 57 | 58 | print "%16s: %s" % ("EDI", hex(edi)) 59 | print "%16s: %s" % ("ESI", hex(esi)) 60 | 61 | print "%16s: %s" % ("ESP", hex(esp)) 62 | print "%16s: %s" % ("[ESP]", repr(trace.readMemory(esp, 4))) 63 | 64 | print("%16s: %s" % ("Direction", bool(ef & EFLAGS_DF))) 65 | 66 | 67 | ####################################################################### 68 | def load_binary(trace, filepath, base=None): 69 | global exepath 70 | 71 | # If attempting to attach to a 64 bit process 72 | # 64 bit python is required. 73 | # sample cmdline: C:\Program Files (x86)\Internet Explorer\iexplore.exe C:\test\ie\index_0.html 74 | cmdline = exepath + " " + filepath 75 | trace.execute(cmdline) 76 | 77 | print("Executing: %s") % (cmdline) 78 | # Start the program executing 79 | trace.run() 80 | 81 | ###################################################################### 82 | def main(argv): 83 | global exepath 84 | 85 | if len(argv) != 2: 86 | print "Usage: %s " % sys.argv[0] 87 | sys.exit(1) 88 | 89 | # verify that the path to test files is valid 90 | filepath = sys.argv[1] 91 | if os.path.isdir(filepath) == False: 92 | sys.exit("Invalid Input Directory") 93 | 94 | # Get the current vtrace object 95 | trace = vtrace.getTrace() 96 | 97 | threads = [] 98 | crashes = [] 99 | count = 1 100 | print ("[*] Starting fuzz process") 101 | 102 | # call load_binary on the filenames stored in the directory 103 | for fname in os.listdir(filepath): 104 | #print fname 105 | cmdline = filepath + "\\" + fname 106 | 107 | t = threading.Thread(target = load_binary, args = (trace, cmdline,)) 108 | threads.append(t) 109 | t.start() 110 | time.sleep(10) 111 | if trace.isRunning(): 112 | trace.sendBreak() 113 | printInfo(trace) 114 | 115 | print ("[*] Death to the process %d") % (trace.getPid()) 116 | trace.kill() 117 | else: 118 | print ("[*] %s crashed") % (fname) 119 | time.sleep(1) 120 | count += 1 121 | 122 | print ("") 123 | print ("[*] Death to all %d of %d processes") % ( (count-len(crashes)), count ) 124 | print ("[*] %d files caused crashes") % (len(crashes)) 125 | for i in crashes: 126 | print ("\t filename: %s") % (i) 127 | 128 | if __name__ == "__main__": 129 | main(sys.argv) 130 | sys.exit(0) 131 | -------------------------------------------------------------------------------- /simpleFollowChild.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | 10 | import envi 11 | from envi.archs.i386 import * 12 | import vtrace.envitools as envitools 13 | import PE as PE 14 | 15 | import vdb.recon as v_recon 16 | import vdb.recon.sniper as v_sniper 17 | import vdb.stalker as v_stalker 18 | 19 | class CustomNotifier(vtrace.Notifier): 20 | # Event is one of the vtrace.NOTIFY_* things listed under vtrace 21 | 22 | def notify(self, event, trace): 23 | if event == vtrace.NOTIFY_ALL: 24 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 25 | 26 | elif event == vtrace.NOTIFY_SIGNAL: 27 | print "vtrace.NOTIFY_SIGNAL" 28 | print "PendingSignal",trace.getMeta("PendingSignal") 29 | print "PendingException",trace.getMeta("PendingException") 30 | if trace.getMeta("Platform") == "Windows": 31 | win32event = trace.getMeta("Win32Event") 32 | #print repr(win32event) 33 | print "ExceptionAddress: %(ExceptionAddress)x" % win32event 34 | 35 | addr = v_api.getOEP(trace, "pwnables100") 36 | memMap = trace.getMemoryMap(addr) 37 | begin = memMap[0] 38 | size = memMap[1] 39 | trace.protectMemory(begin, size, envi.memory.MM_READ_EXEC) 40 | 41 | win32 = trace.getMeta("Win32Event", None) 42 | if win32: 43 | code = win32["ExceptionCode"] 44 | print "Win32 ExceptCode: ", code 45 | 46 | elif event == vtrace.NOTIFY_BREAK: 47 | print "vtrace.NOTIFY_BREAK", v_api.printableEIP(trace) 48 | #print "BESTNAME: ", trace.getSymByAddr(v_api.getEIP(trace), exact=False) 49 | #pass 50 | elif event == vtrace.NOTIFY_EXIT: 51 | print "vtrace.NOTIFY_EXIT" 52 | print "ExitCode",trace.getMeta("ExitCode") 53 | elif event == vtrace.NOTIFY_ATTACH: 54 | print "vtrace.NOTIFY_ATTACH" 55 | #pass 56 | elif event == vtrace.NOTIFY_DETACH: 57 | print "vtrace.NOTIFY_DETACH" 58 | #pass 59 | elif event == vtrace.NOTIFY_STEP: 60 | #print "vtrace.NOTIFY_STEP" 61 | # print "BESTNAME: ", trace.getSymByAddr(getEIP(trace), exact=False) 62 | # print "Current Thread: ", trace.getCurrentThread() 63 | # print "THREADS: ", trace.getThreads() 64 | pass 65 | else: 66 | pass 67 | 68 | 69 | ####################################################################### 70 | def load_binary(filepath, base=None): 71 | opList = {} 72 | trace = vtrace.getTrace() 73 | 74 | trace.execute(filepath) 75 | ####################################################################### 76 | # Enable the notifier. Used later to catch the page execute exception. 77 | notif = CustomNotifier() 78 | eve = vtrace.NOTIFY_ALL 79 | trace.registerNotifier(eve, notif) 80 | ####################################################################### 81 | # Set a breakpoint on CreateProcessA and run until it is hit 82 | pattern = "CreateProcessA()" 83 | v_api.setBpOnPattern(trace, pattern) 84 | v_api.printBp(trace) 85 | trace.run() 86 | 87 | ####################################################################### 88 | # Functions sets child process to start suspended and attaches to it 89 | # as soon as it returns to userland by setting the Entry Point page 90 | # as non executable and catching the exception that is thrown. 91 | print "followCreateProcessA" 92 | v_api.followCreateProcessA(trace) 93 | 94 | addr = v_api.getOEP(trace, "pwnables100") 95 | v_api.nxMemPerm(trace, addr) 96 | ##################################################################### 97 | # Beyond this point the debugger is attached to the child process 98 | # 99 | print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 100 | print "HOLY BREAKPOINT BATMAN!" 101 | print "EIP: ", v_api.printableEIP(trace) 102 | 103 | ###################################################################### 104 | def main(argv): 105 | if len(argv) != 2: 106 | print "Usage: %s " % sys.argv[0] 107 | sys.exit(1) 108 | 109 | filepath = sys.argv[1] 110 | 111 | load_binary(filepath) 112 | 113 | if __name__ == "__main__": 114 | main(sys.argv) 115 | sys.exit(0) 116 | -------------------------------------------------------------------------------- /command_line/simpleFollowChild.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | 10 | import envi 11 | from envi.archs.i386 import * 12 | import vtrace.envitools as envitools 13 | import PE as PE 14 | 15 | import vdb.recon as v_recon 16 | import vdb.recon.sniper as v_sniper 17 | import vdb.stalker as v_stalker 18 | 19 | class CustomNotifier(vtrace.Notifier): 20 | # Event is one of the vtrace.NOTIFY_* things listed under vtrace 21 | 22 | def notify(self, event, trace): 23 | if event == vtrace.NOTIFY_ALL: 24 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 25 | 26 | elif event == vtrace.NOTIFY_SIGNAL: 27 | print "vtrace.NOTIFY_SIGNAL" 28 | print "PendingSignal",trace.getMeta("PendingSignal") 29 | print "PendingException",trace.getMeta("PendingException") 30 | if trace.getMeta("Platform") == "Windows": 31 | win32event = trace.getMeta("Win32Event") 32 | #print repr(win32event) 33 | print "ExceptionAddress: %(ExceptionAddress)x" % win32event 34 | 35 | addr = v_api.getOEP(trace, "pwnables100") 36 | memMap = trace.getMemoryMap(addr) 37 | begin = memMap[0] 38 | size = memMap[1] 39 | trace.protectMemory(begin, size, envi.memory.MM_READ_EXEC) 40 | 41 | win32 = trace.getMeta("Win32Event", None) 42 | if win32: 43 | code = win32["ExceptionCode"] 44 | print "Win32 ExceptCode: ", code 45 | 46 | elif event == vtrace.NOTIFY_BREAK: 47 | print "vtrace.NOTIFY_BREAK", v_api.printableEIP(trace) 48 | #print "BESTNAME: ", trace.getSymByAddr(v_api.getEIP(trace), exact=False) 49 | #pass 50 | elif event == vtrace.NOTIFY_EXIT: 51 | print "vtrace.NOTIFY_EXIT" 52 | print "ExitCode",trace.getMeta("ExitCode") 53 | elif event == vtrace.NOTIFY_ATTACH: 54 | print "vtrace.NOTIFY_ATTACH" 55 | #pass 56 | elif event == vtrace.NOTIFY_DETACH: 57 | print "vtrace.NOTIFY_DETACH" 58 | #pass 59 | elif event == vtrace.NOTIFY_STEP: 60 | #print "vtrace.NOTIFY_STEP" 61 | # print "BESTNAME: ", trace.getSymByAddr(getEIP(trace), exact=False) 62 | # print "Current Thread: ", trace.getCurrentThread() 63 | # print "THREADS: ", trace.getThreads() 64 | pass 65 | else: 66 | pass 67 | 68 | 69 | ####################################################################### 70 | def load_binary(filepath, base=None): 71 | opList = {} 72 | trace = vtrace.getTrace() 73 | 74 | trace.execute(filepath) 75 | ####################################################################### 76 | # Enable the notifier. Used later to catch the page execute exception. 77 | notif = CustomNotifier() 78 | eve = vtrace.NOTIFY_ALL 79 | trace.registerNotifier(eve, notif) 80 | ####################################################################### 81 | # Set a breakpoint on CreateProcessA and run until it is hit 82 | pattern = "CreateProcessA()" 83 | v_api.setBpOnPattern(trace, pattern) 84 | v_api.printBp(trace) 85 | trace.run() 86 | 87 | ####################################################################### 88 | # Functions sets child process to start suspended and attaches to it 89 | # as soon as it returns to userland by setting the Entry Point page 90 | # as non executable and catching the exception that is thrown. 91 | print "followCreateProcessA" 92 | v_api.followCreateProcessA(trace) 93 | 94 | addr = v_api.getOEP(trace, "pwnables100") 95 | v_api.nxMemPerm(trace, addr) 96 | ##################################################################### 97 | # Beyond this point the debugger is attached to the child process 98 | # 99 | print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 100 | print "HOLY BREAKPOINT BATMAN!" 101 | print "EIP: ", v_api.printableEIP(trace) 102 | 103 | ###################################################################### 104 | def main(argv): 105 | if len(argv) != 2: 106 | print "Usage: %s " % sys.argv[0] 107 | sys.exit(1) 108 | 109 | filepath = sys.argv[1] 110 | 111 | load_binary(filepath) 112 | 113 | if __name__ == "__main__": 114 | main(sys.argv) 115 | sys.exit(0) 116 | -------------------------------------------------------------------------------- /simpleNotifier.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | 13 | class CustomNotifier(vtrace.Notifier): 14 | # Event is one of the vtrace.NOTIFY_* things listed under vtrace 15 | 16 | def notify(self, event, trace): 17 | #print "Got event: %d from pid %d" % (event, trace.getPid()) 18 | #print "PID %d thread(%d) got" % (trace.getPid(), trace.getMeta("ThreadId")) 19 | 20 | if event == vtrace.NOTIFY_ALL: 21 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 22 | 23 | elif event == vtrace.NOTIFY_SIGNAL: 24 | print "vtrace.NOTIFY_SIGNAL" 25 | print "PendingSignal",trace.getMeta("PendingSignal") 26 | print "PendingException",trace.getMeta("PendingException") 27 | if trace.getMeta("Platform") == "Windows": 28 | print repr(trace.getMeta("Win32Event")) 29 | print vdb.getSignal(trace.getMeta("PendingSignal")) 30 | win32 = self.getMeta("Win32Event", None) 31 | if win32: 32 | code = win32["ExceptionCode"] 33 | print "Win32 ExceptCode: ", code 34 | 35 | elif event == vtrace.NOTIFY_BREAK: 36 | print "vtrace.NOTIFY_BREAK", printableEIP(trace) 37 | pass 38 | elif event == vtrace.NOTIFY_SYSCALL: 39 | print "vtrace.NOTIFY_SYSCALL" 40 | elif event == vtrace.NOTIFY_CONTINUE: 41 | print "vtrace.NOTIFY_CONTINUE" 42 | pass 43 | elif event == vtrace.NOTIFY_EXIT: 44 | print "vtrace.NOTIFY_EXIT" 45 | print "ExitCode",trace.getMeta("ExitCode") 46 | elif event == vtrace.NOTIFY_ATTACH: 47 | print "vtrace.NOTIFY_ATTACH" 48 | pass 49 | elif event == vtrace.NOTIFY_DETACH: 50 | print "vtrace.NOTIFY_DETACH" 51 | pass 52 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 53 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 54 | pass 55 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 56 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 57 | pass 58 | elif event == vtrace.NOTIFY_CREATE_THREAD: 59 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 60 | pass 61 | elif event == vtrace.NOTIFY_EXIT_THREAD: 62 | print "vtrace.NOTIFY_EXIT_THREAD" 63 | print "ExitThread",trace.getMeta("ExitThread", -1) 64 | pass 65 | elif event == vtrace.NOTIFY_STEP: 66 | print "vtrace.NOTIFY_STEP" 67 | print "BESTNAME: ", trace.getSymByAddr(getEIP(trace), exact=False) 68 | print "EIP: ", printableEIP(trace) 69 | print "OP CODE: ", getOpCode(trace, getEIP(trace)) 70 | print "\n" 71 | pass 72 | else: 73 | print "vtrace.NOTIFY_WTF_HUH?" 74 | 75 | def getEIP(trace): 76 | eip = trace.getRegister(REG_EIP) 77 | return eip 78 | 79 | def printableEIP(trace): 80 | return hex(getEIP(trace)) 81 | 82 | def getESP(trace): 83 | esp = trace.getRegister(REG_ESP) 84 | return esp 85 | 86 | def getRET(trace): 87 | esp = getESP(trace) 88 | retaddr = trace.readMemory(esp, 4) 89 | return struct.unpack("I",retaddr)[0] 90 | 91 | def getPrintableRET(trace): 92 | esp = getESP(trace) 93 | retprt = trace.readMemory(esp, 4) 94 | return hex(struct.unpack("I",retaddr)[0]) 95 | 96 | def getOpCode(trace, eip): 97 | s = trace.readMemory(eip,15) 98 | op1 = trace.makeOpcode(s, 0, eip) 99 | return op1 100 | 101 | ####################################################################### 102 | def load_binary(filepath, base=None): 103 | # Get the current trace object from vtrace 104 | trace = vtrace.getTrace() 105 | 106 | # If attempting to attach to a 64 bit process 107 | # 64 bit python is required. 108 | trace.execute(filepath) 109 | ############################################################### 110 | # The notifier class we want to register 111 | notif = CustomNotifier() 112 | # The list of events we want the notifier to handle 113 | eve = vtrace.NOTIFY_ALL 114 | # Tell our vtrace object that we want to capture all events with CustomNotifier 115 | trace.registerNotifier(eve, notif) 116 | ############################################################### 117 | # Call a function to set BP on OEP 118 | oep = v_api.getOEP(trace, filepath) 119 | 120 | # Set breakpoint at address 121 | bp = vtrace.Breakpoint(oep) 122 | trace.addBreakpoint(bp) 123 | 124 | # Start executing the program until you hit a breakpoint or it ends 125 | trace.run() 126 | ################################################################# 127 | 128 | # Step 5 times into the program 129 | for i in range(5): 130 | trace.stepi() 131 | 132 | # Deregister our notifier 133 | trace.deregisterNotifier(eve, notif) 134 | 135 | ###################################################################### 136 | def main(argv): 137 | if len(argv) != 2: 138 | print "Usage: %s " % sys.argv[0] 139 | sys.exit(1) 140 | 141 | filepath = sys.argv[1] 142 | 143 | load_binary(filepath) 144 | 145 | if __name__ == "__main__": 146 | main(sys.argv) 147 | sys.exit(0) 148 | -------------------------------------------------------------------------------- /command_line/simpleNotifier.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import simpleAPI as v_api 3 | #VDB_ROOT = "" 4 | 5 | sys.path.append(VDB_ROOT) 6 | 7 | import vtrace 8 | import vdb 9 | import PE as PE 10 | from envi.archs.i386 import * 11 | import vdb.stalker as v_stalker 12 | 13 | class CustomNotifier(vtrace.Notifier): 14 | # Event is one of the vtrace.NOTIFY_* things listed under vtrace 15 | 16 | def notify(self, event, trace): 17 | #print "Got event: %d from pid %d" % (event, trace.getPid()) 18 | #print "PID %d thread(%d) got" % (trace.getPid(), trace.getMeta("ThreadId")) 19 | 20 | if event == vtrace.NOTIFY_ALL: 21 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 22 | 23 | elif event == vtrace.NOTIFY_SIGNAL: 24 | print "vtrace.NOTIFY_SIGNAL" 25 | print "PendingSignal",trace.getMeta("PendingSignal") 26 | print "PendingException",trace.getMeta("PendingException") 27 | if trace.getMeta("Platform") == "Windows": 28 | print repr(trace.getMeta("Win32Event")) 29 | print vdb.getSignal(trace.getMeta("PendingSignal")) 30 | win32 = self.getMeta("Win32Event", None) 31 | if win32: 32 | code = win32["ExceptionCode"] 33 | print "Win32 ExceptCode: ", code 34 | 35 | elif event == vtrace.NOTIFY_BREAK: 36 | print "vtrace.NOTIFY_BREAK", printableEIP(trace) 37 | pass 38 | elif event == vtrace.NOTIFY_SYSCALL: 39 | print "vtrace.NOTIFY_SYSCALL" 40 | elif event == vtrace.NOTIFY_CONTINUE: 41 | print "vtrace.NOTIFY_CONTINUE" 42 | pass 43 | elif event == vtrace.NOTIFY_EXIT: 44 | print "vtrace.NOTIFY_EXIT" 45 | print "ExitCode",trace.getMeta("ExitCode") 46 | elif event == vtrace.NOTIFY_ATTACH: 47 | print "vtrace.NOTIFY_ATTACH" 48 | pass 49 | elif event == vtrace.NOTIFY_DETACH: 50 | print "vtrace.NOTIFY_DETACH" 51 | pass 52 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 53 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 54 | pass 55 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 56 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 57 | pass 58 | elif event == vtrace.NOTIFY_CREATE_THREAD: 59 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 60 | pass 61 | elif event == vtrace.NOTIFY_EXIT_THREAD: 62 | print "vtrace.NOTIFY_EXIT_THREAD" 63 | print "ExitThread",trace.getMeta("ExitThread", -1) 64 | pass 65 | elif event == vtrace.NOTIFY_STEP: 66 | print "vtrace.NOTIFY_STEP" 67 | print "BESTNAME: ", trace.getSymByAddr(getEIP(trace), exact=False) 68 | print "EIP: ", printableEIP(trace) 69 | print "OP CODE: ", getOpCode(trace, getEIP(trace)) 70 | print "\n" 71 | pass 72 | else: 73 | print "vtrace.NOTIFY_WTF_HUH?" 74 | 75 | def getEIP(trace): 76 | eip = trace.getRegister(REG_EIP) 77 | return eip 78 | 79 | def printableEIP(trace): 80 | return hex(getEIP(trace)) 81 | 82 | def getESP(trace): 83 | esp = trace.getRegister(REG_ESP) 84 | return esp 85 | 86 | def getRET(trace): 87 | esp = getESP(trace) 88 | retaddr = trace.readMemory(esp, 4) 89 | return struct.unpack("I",retaddr)[0] 90 | 91 | def getPrintableRET(trace): 92 | esp = getESP(trace) 93 | retprt = trace.readMemory(esp, 4) 94 | return hex(struct.unpack("I",retaddr)[0]) 95 | 96 | def getOpCode(trace, eip): 97 | s = trace.readMemory(eip,15) 98 | op1 = trace.makeOpcode(s, 0, eip) 99 | return op1 100 | 101 | ####################################################################### 102 | def load_binary(filepath, base=None): 103 | # Get the current trace object from vtrace 104 | trace = vtrace.getTrace() 105 | 106 | # If attempting to attach to a 64 bit process 107 | # 64 bit python is required. 108 | trace.execute(filepath) 109 | ############################################################### 110 | # The notifier class we want to register 111 | notif = CustomNotifier() 112 | # The list of events we want the notifier to handle 113 | eve = vtrace.NOTIFY_ALL 114 | # Tell our vtrace object that we want to capture all events with CustomNotifier 115 | trace.registerNotifier(eve, notif) 116 | ############################################################### 117 | # Call a function to set BP on OEP 118 | oep = v_api.getOEP(trace, filepath) 119 | 120 | # Set breakpoint at address 121 | bp = vtrace.Breakpoint(oep) 122 | trace.addBreakpoint(bp) 123 | 124 | # Start executing the program until you hit a breakpoint or it ends 125 | trace.run() 126 | ################################################################# 127 | 128 | # Step 5 times into the program 129 | for i in range(5): 130 | trace.stepi() 131 | 132 | # Deregister our notifier 133 | trace.deregisterNotifier(eve, notif) 134 | 135 | ###################################################################### 136 | def main(argv): 137 | if len(argv) != 2: 138 | print "Usage: %s " % sys.argv[0] 139 | sys.exit(1) 140 | 141 | filepath = sys.argv[1] 142 | 143 | load_binary(filepath) 144 | 145 | if __name__ == "__main__": 146 | main(sys.argv) 147 | sys.exit(0) 148 | -------------------------------------------------------------------------------- /simpleIAT_NX_vdb.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | 5 | #VDB_ROOT = "" 6 | #API_ROOT = "" 7 | 8 | sys.path.append(VDB_ROOT) 9 | sys.path.append(API_ROOT) 10 | 11 | #import simpleAPI as v_api 12 | from simpleAPI import getOpCode, getIATLocation, printIAT, store_IAT, nxMemPerm, getOEP, printInfo 13 | 14 | 15 | import vtrace 16 | # import vdb 17 | 18 | import envi 19 | import envi.memory as mem 20 | from envi.archs.i386 import * 21 | 22 | import vtrace.envitools as envitools 23 | 24 | import PE 25 | import vstruct 26 | 27 | # import vdb.recon as v_recon 28 | # import vdb.recon.sniper as v_sniper 29 | # import vdb.stalker as v_stalker 30 | 31 | debug = True 32 | 33 | ################################################################### 34 | class CustomNotifier(vtrace.Notifier): 35 | def notify(self, event, trace): 36 | iat_handler(event, trace) 37 | 38 | ####################################################################### 39 | # Call this function from within a notifier to handle breakpoints on IAT 40 | def iat_handler(event, trace): 41 | print "[*] Got event: %d from pid %d" % (event, trace.getPid()) 42 | 43 | if event == vtrace.NOTIFY_ALL: 44 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 45 | 46 | elif event == vtrace.NOTIFY_SIGNAL: 47 | #print "vtrace.NOTIFY_SIGNAL" 48 | print "[*] PendingSignal",trace.getMeta("PendingSignal") 49 | print "[*] PendingException",trace.getMeta("PendingException") 50 | if trace.getMeta("Platform") == "Windows": 51 | begin = trace.getMeta("IATBegin") 52 | size = trace.getMeta("IATSize") 53 | print "[*] Removing Memory Protections Location: %s" % hex(begin) 54 | print "[*] Memory Size: %s" % size 55 | trace.protectMemory(begin, size, envi.memory.MM_RWX) 56 | 57 | # because MSVC debugger sucks at life 58 | # 1080890248 (0x406d1388) is an exception used to name a thread 59 | # 3765269347 (0xe06d7363) is an exception that is triggered when a throw happens 60 | if (trace.getMeta("PendingSignal") != None) and \ 61 | (trace.getMeta("PendingSignal") != 1080890248) and\ 62 | (trace.getMeta("PendingSignal") != 3765269347): 63 | 64 | win32event = trace.getMeta("Win32Event") 65 | print "[*] ExceptionAddress: %(ExceptionAddress)x" % win32event 66 | 67 | eip = trace.getRegister(REG_EIP) 68 | 69 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 70 | disLen = len(dis) 71 | opcode = trace.readMemory(eip, len(dis)) 72 | 73 | es = trace.getRegisterByName("es") 74 | ds = trace.getRegisterByName("ds") 75 | cs = trace.getRegisterByName("cs") 76 | 77 | ef = trace.getRegisterByName("eflags") 78 | 79 | edi = trace.getRegister(REG_EDI) 80 | esi = trace.getRegister(REG_ESI) 81 | esp = trace.getRegister(REG_ESP) 82 | 83 | printInfo(trace) 84 | 85 | if (len(opcode) == 1): 86 | pass 87 | 88 | # What is this for again? 89 | # scasd i think \x66\xF2 90 | elif (ord(opcode[0]) != 102 and ord(opcode[1]) != 242): 91 | 92 | # function takes in just filename not the full path to filename.exe 93 | filepath = trace.getMeta('ExeName') 94 | exeName = filepath.split(".exe")[0] 95 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 96 | 97 | if(trace.getMeta('IATLocation') == None): 98 | base, poff, psize = getIATLocation(trace, fileName) 99 | trace.setMeta('IATLocation', {'base':base, 'poff':poff, 'psize':psize}) 100 | else: 101 | iatLoc = trace.getMeta('IATLocation') 102 | base = iatLoc['base'] 103 | poff = iatLoc['poff'] 104 | psize = iatLoc['psize'] 105 | 106 | eip = trace.getRegister(REG_EIP) 107 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 108 | 109 | # Check for \xff to determine if a deref call 110 | if (ord(opcode[0]) == 255): 111 | print "OPCODE[1]: ", ord(opcode[1]) 112 | 113 | # Need to accomodate more than just call [eax] and call [edx] 114 | if (ord(opcode[1]) == 48): 115 | eax = trace.getRegister(REG_EAX) 116 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 117 | elif (ord(opcode[1]) == 16): 118 | eax = trace.getRegister(REG_EAX) 119 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 120 | elif (ord(opcode[1]) == 18): 121 | edx = trace.getRegister(REG_EDX) 122 | tmp_addr = struct.unpack("I",trace.readMemory(edx, 4))[0] 123 | 124 | 125 | elif (ord(opcode[1]) == 80): 126 | print "OPCODE[2]: ", ord(opcode[2]) 127 | #if (ord(opcode[2]) == 24): 128 | eax = trace.getRegister(REG_EAX) 129 | #eax += 24 130 | eax += ord(opcode[2]) 131 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 132 | #print "EAX+24: %s" % repr(tmp_addr) 133 | 134 | elif (ord(opcode[1]) == 112): 135 | print "OPCODE[2]: ", ord(opcode[2]) 136 | eax = trace.getRegister(REG_EAX) 137 | eax += ord(opcode[2]) 138 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 139 | elif (ord(opcode[1]) == 215): 140 | edi = trace.getRegister(REG_EDI) 141 | tmp_addr = struct.unpack("I",trace.readMemory(edi, 4))[0] 142 | 143 | else : 144 | tmp_addr = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 145 | 146 | ################################ 147 | # Get the list of imported functions to compare against 148 | try: 149 | instr = trace.getMeta('IATInfo') 150 | except: 151 | base, importTable = printIAT(trace, fileName) 152 | store_IAT(trace, base, importTable, "IATInfo") 153 | instr = trace.getMeta('IATInfo') 154 | 155 | print "TMP_ADDR: %s" % hex(tmp_addr) 156 | try: 157 | a = instr[tmp_addr] 158 | except: 159 | a = "UNKNOWN LIB: UNKNOWN FUNCTION" 160 | 161 | b = a.split(':') 162 | 163 | print "[*] \tLibrary: %s \n[*] \tFunction: %s" % (b[0], b[1]) 164 | 165 | try: 166 | lst = trace.getMeta('IATList') 167 | lst.append(hex(tmp_addr)+':'+b[0]+':'+b[1]) 168 | trace.setMeta('IATList', lst) 169 | except: 170 | print "SET Initial IATList Metadata" 171 | trace.setMeta('IATList', [hex(tmp_addr)+':'+b[0]+':'+b[1]]) 172 | 173 | print "%16s: %s" % ("[*] Opcode[0]", ord(opcode[0])) 174 | 175 | p = trace.getMeta('PendingSignal') 176 | if p!= None: 177 | trace.setMeta('OrigSignal', p) 178 | trace.setMeta('PendingSignal', None) 179 | 180 | print "STEPS" 181 | trace.stepi() 182 | 183 | print "[*] Protecting Memory Location: %s" % hex(begin) 184 | print "[*] Memory Size: %s" % size 185 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 186 | 187 | print "Run Again Set" 188 | trace.runAgain(val=True) 189 | 190 | print "---------------------------------------------------------" 191 | elif event == vtrace.NOTIFY_BREAK: 192 | print "vtrace.NOTIFY_BREAK", hex(trace.getRegister(REG_EIP)) 193 | print "[*] Bestname: ", trace.getSymByAddr(trace.getRegister(REG_EIP), exact=False) 194 | pass 195 | elif event == vtrace.NOTIFY_SYSCALL: 196 | print "vtrace.NOTIFY_SYSCALL" 197 | 198 | elif event == vtrace.NOTIFY_CONTINUE: 199 | print "vtrace.NOTIFY_CONTINUE" 200 | trace.runAgain(val=True) 201 | print "---------------------------------------------------------" 202 | 203 | elif event == vtrace.NOTIFY_EXIT: 204 | print "vtrace.NOTIFY_EXIT" 205 | print "ExitCode",trace.getMeta("ExitCode") 206 | 207 | elif event == vtrace.NOTIFY_ATTACH: 208 | print "vtrace.NOTIFY_ATTACH" 209 | pass 210 | elif event == vtrace.NOTIFY_DETACH: 211 | print "vtrace.NOTIFY_DETACH" 212 | pass 213 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 214 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 215 | pass 216 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 217 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 218 | pass 219 | elif event == vtrace.NOTIFY_CREATE_THREAD: 220 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 221 | pass 222 | elif event == vtrace.NOTIFY_EXIT_THREAD: 223 | print "vtrace.NOTIFY_EXIT_THREAD" 224 | print "ExitThread",trace.getMeta("ExitThread", -1) 225 | pass 226 | elif event == vtrace.NOTIFY_STEP: 227 | print "vtrace.NOTIFY_STEP" 228 | 229 | else: 230 | print "vtrace.NOTIFY_WTF_HUH?", hex(trace.getRegister(REG_EIP)) 231 | 232 | ####################################################################### 233 | def load_binary(filepath, base=None): 234 | 235 | trace.setMode("FastStep", 1) 236 | 237 | filepath = trace.getMeta('ExeName') 238 | fileName = os.path.basename(filepath).split('.')[0] 239 | 240 | # Call a function to set BP on OEP 241 | oep = getOEP(trace, filepath) 242 | 243 | ####################################################################### 244 | # Get the list of imported functions to compare against 245 | base, importTable = printIAT(trace, fileName) 246 | 247 | base, poff, psize = getIATLocation(trace, fileName, debug) 248 | 249 | # Store the IAT under the meta name IATInfo 250 | store_IAT(trace, base, importTable, "IATInfo") 251 | 252 | psize = trace.arch.getPointerSize() 253 | 254 | memMap = trace.getMemoryMap(base+poff) 255 | begin = memMap[0] 256 | size = len(importTable) * psize 257 | 258 | # put begin in size into the meta data 259 | trace.setMeta("IATBegin", begin) 260 | trace.setMeta("IATSize", size) 261 | 262 | print "[*] Protecting Memory Location: %s" % hex(begin) 263 | print "[*] Memory Size: %s" % size 264 | 265 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 266 | 267 | ####################################################################### 268 | # Enable the notifier. Used later to catch the page execute exception. 269 | notif = CustomNotifier() 270 | eve = vtrace.NOTIFY_ALL 271 | #eve = vtrace.NOTIFY_SIGNAL 272 | trace.registerNotifier(eve, notif) 273 | 274 | 275 | ####################################################################### 276 | ###################################################################### 277 | load_binary("FOO") -------------------------------------------------------------------------------- /vdb/simpleIAT_NX_vdb.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | 5 | #VDB_ROOT = "" 6 | #API_ROOT = "" 7 | 8 | sys.path.append(VDB_ROOT) 9 | sys.path.append(API_ROOT) 10 | 11 | #import simpleAPI as v_api 12 | from simpleAPI import getOpCode, getIATLocation, printIAT, store_IAT, nxMemPerm, getOEP, printInfo 13 | 14 | 15 | import vtrace 16 | # import vdb 17 | 18 | import envi 19 | import envi.memory as mem 20 | from envi.archs.i386 import * 21 | 22 | import vtrace.envitools as envitools 23 | 24 | import PE 25 | import vstruct 26 | 27 | # import vdb.recon as v_recon 28 | # import vdb.recon.sniper as v_sniper 29 | # import vdb.stalker as v_stalker 30 | 31 | debug = True 32 | 33 | ################################################################### 34 | class CustomNotifier(vtrace.Notifier): 35 | def notify(self, event, trace): 36 | iat_handler(event, trace) 37 | 38 | ####################################################################### 39 | # Call this function from within a notifier to handle breakpoints on IAT 40 | def iat_handler(event, trace): 41 | print "[*] Got event: %d from pid %d" % (event, trace.getPid()) 42 | 43 | if event == vtrace.NOTIFY_ALL: 44 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 45 | 46 | elif event == vtrace.NOTIFY_SIGNAL: 47 | #print "vtrace.NOTIFY_SIGNAL" 48 | print "[*] PendingSignal",trace.getMeta("PendingSignal") 49 | print "[*] PendingException",trace.getMeta("PendingException") 50 | if trace.getMeta("Platform") == "Windows": 51 | begin = trace.getMeta("IATBegin") 52 | size = trace.getMeta("IATSize") 53 | print "[*] Removing Memory Protections Location: %s" % hex(begin) 54 | print "[*] Memory Size: %s" % size 55 | trace.protectMemory(begin, size, envi.memory.MM_RWX) 56 | 57 | # because MSVC debugger sucks at life 58 | # 1080890248 (0x406d1388) is an exception used to name a thread 59 | # 3765269347 (0xe06d7363) is an exception that is triggered when a throw happens 60 | if (trace.getMeta("PendingSignal") != None) and \ 61 | (trace.getMeta("PendingSignal") != 1080890248) and\ 62 | (trace.getMeta("PendingSignal") != 3765269347): 63 | 64 | win32event = trace.getMeta("Win32Event") 65 | print "[*] ExceptionAddress: %(ExceptionAddress)x" % win32event 66 | 67 | eip = trace.getRegister(REG_EIP) 68 | 69 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 70 | disLen = len(dis) 71 | opcode = trace.readMemory(eip, len(dis)) 72 | 73 | es = trace.getRegisterByName("es") 74 | ds = trace.getRegisterByName("ds") 75 | cs = trace.getRegisterByName("cs") 76 | 77 | ef = trace.getRegisterByName("eflags") 78 | 79 | edi = trace.getRegister(REG_EDI) 80 | esi = trace.getRegister(REG_ESI) 81 | esp = trace.getRegister(REG_ESP) 82 | 83 | printInfo(trace) 84 | 85 | if (len(opcode) == 1): 86 | pass 87 | 88 | # What is this for again? 89 | # scasd i think \x66\xF2 90 | elif (ord(opcode[0]) != 102 and ord(opcode[1]) != 242): 91 | 92 | # function takes in just filename not the full path to filename.exe 93 | filepath = trace.getMeta('ExeName') 94 | exeName = filepath.split(".exe")[0] 95 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 96 | 97 | if(trace.getMeta('IATLocation') == None): 98 | base, poff, psize = getIATLocation(trace, fileName) 99 | trace.setMeta('IATLocation', {'base':base, 'poff':poff, 'psize':psize}) 100 | else: 101 | iatLoc = trace.getMeta('IATLocation') 102 | base = iatLoc['base'] 103 | poff = iatLoc['poff'] 104 | psize = iatLoc['psize'] 105 | 106 | eip = trace.getRegister(REG_EIP) 107 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 108 | 109 | # Check for \xff to determine if a deref call 110 | if (ord(opcode[0]) == 255): 111 | print "OPCODE[1]: ", ord(opcode[1]) 112 | 113 | # Need to accomodate more than just call [eax] and call [edx] 114 | if (ord(opcode[1]) == 48): 115 | eax = trace.getRegister(REG_EAX) 116 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 117 | elif (ord(opcode[1]) == 16): 118 | eax = trace.getRegister(REG_EAX) 119 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 120 | elif (ord(opcode[1]) == 18): 121 | edx = trace.getRegister(REG_EDX) 122 | tmp_addr = struct.unpack("I",trace.readMemory(edx, 4))[0] 123 | 124 | 125 | elif (ord(opcode[1]) == 80): 126 | print "OPCODE[2]: ", ord(opcode[2]) 127 | #if (ord(opcode[2]) == 24): 128 | eax = trace.getRegister(REG_EAX) 129 | #eax += 24 130 | eax += ord(opcode[2]) 131 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 132 | #print "EAX+24: %s" % repr(tmp_addr) 133 | 134 | elif (ord(opcode[1]) == 112): 135 | print "OPCODE[2]: ", ord(opcode[2]) 136 | eax = trace.getRegister(REG_EAX) 137 | eax += ord(opcode[2]) 138 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 139 | elif (ord(opcode[1]) == 215): 140 | edi = trace.getRegister(REG_EDI) 141 | tmp_addr = struct.unpack("I",trace.readMemory(edi, 4))[0] 142 | 143 | else : 144 | tmp_addr = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 145 | 146 | ################################ 147 | # Get the list of imported functions to compare against 148 | try: 149 | instr = trace.getMeta('IATInfo') 150 | except: 151 | base, importTable = printIAT(trace, fileName) 152 | store_IAT(trace, base, importTable, "IATInfo") 153 | instr = trace.getMeta('IATInfo') 154 | 155 | print "TMP_ADDR: %s" % hex(tmp_addr) 156 | try: 157 | a = instr[tmp_addr] 158 | except: 159 | a = "UNKNOWN LIB: UNKNOWN FUNCTION" 160 | 161 | b = a.split(':') 162 | 163 | print "[*] \tLibrary: %s \n[*] \tFunction: %s" % (b[0], b[1]) 164 | 165 | try: 166 | lst = trace.getMeta('IATList') 167 | lst.append(hex(tmp_addr)+':'+b[0]+':'+b[1]) 168 | trace.setMeta('IATList', lst) 169 | except: 170 | print "SET Initial IATList Metadata" 171 | trace.setMeta('IATList', [hex(tmp_addr)+':'+b[0]+':'+b[1]]) 172 | 173 | print "%16s: %s" % ("[*] Opcode[0]", ord(opcode[0])) 174 | 175 | p = trace.getMeta('PendingSignal') 176 | if p!= None: 177 | trace.setMeta('OrigSignal', p) 178 | trace.setMeta('PendingSignal', None) 179 | 180 | print "STEPS" 181 | trace.stepi() 182 | 183 | print "[*] Protecting Memory Location: %s" % hex(begin) 184 | print "[*] Memory Size: %s" % size 185 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 186 | 187 | print "Run Again Set" 188 | trace.runAgain(val=True) 189 | 190 | print "---------------------------------------------------------" 191 | elif event == vtrace.NOTIFY_BREAK: 192 | print "vtrace.NOTIFY_BREAK", hex(trace.getRegister(REG_EIP)) 193 | print "[*] Bestname: ", trace.getSymByAddr(trace.getRegister(REG_EIP), exact=False) 194 | pass 195 | elif event == vtrace.NOTIFY_SYSCALL: 196 | print "vtrace.NOTIFY_SYSCALL" 197 | 198 | elif event == vtrace.NOTIFY_CONTINUE: 199 | print "vtrace.NOTIFY_CONTINUE" 200 | trace.runAgain(val=True) 201 | print "---------------------------------------------------------" 202 | 203 | elif event == vtrace.NOTIFY_EXIT: 204 | print "vtrace.NOTIFY_EXIT" 205 | print "ExitCode",trace.getMeta("ExitCode") 206 | 207 | elif event == vtrace.NOTIFY_ATTACH: 208 | print "vtrace.NOTIFY_ATTACH" 209 | pass 210 | elif event == vtrace.NOTIFY_DETACH: 211 | print "vtrace.NOTIFY_DETACH" 212 | pass 213 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 214 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 215 | pass 216 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 217 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 218 | pass 219 | elif event == vtrace.NOTIFY_CREATE_THREAD: 220 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 221 | pass 222 | elif event == vtrace.NOTIFY_EXIT_THREAD: 223 | print "vtrace.NOTIFY_EXIT_THREAD" 224 | print "ExitThread",trace.getMeta("ExitThread", -1) 225 | pass 226 | elif event == vtrace.NOTIFY_STEP: 227 | print "vtrace.NOTIFY_STEP" 228 | 229 | else: 230 | print "vtrace.NOTIFY_WTF_HUH?", hex(trace.getRegister(REG_EIP)) 231 | 232 | ####################################################################### 233 | def load_binary(filepath, base=None): 234 | 235 | trace.setMode("FastStep", 1) 236 | 237 | filepath = trace.getMeta('ExeName') 238 | fileName = os.path.basename(filepath).split('.')[0] 239 | 240 | # Call a function to set BP on OEP 241 | oep = getOEP(trace, filepath) 242 | 243 | ####################################################################### 244 | # Get the list of imported functions to compare against 245 | base, importTable = printIAT(trace, fileName) 246 | 247 | base, poff, psize = getIATLocation(trace, fileName, debug) 248 | 249 | # Store the IAT under the meta name IATInfo 250 | store_IAT(trace, base, importTable, "IATInfo") 251 | 252 | psize = trace.arch.getPointerSize() 253 | 254 | memMap = trace.getMemoryMap(base+poff) 255 | begin = memMap[0] 256 | size = len(importTable) * psize 257 | 258 | # put begin in size into the meta data 259 | trace.setMeta("IATBegin", begin) 260 | trace.setMeta("IATSize", size) 261 | 262 | print "[*] Protecting Memory Location: %s" % hex(begin) 263 | print "[*] Memory Size: %s" % size 264 | 265 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 266 | 267 | ####################################################################### 268 | # Enable the notifier. Used later to catch the page execute exception. 269 | notif = CustomNotifier() 270 | eve = vtrace.NOTIFY_ALL 271 | #eve = vtrace.NOTIFY_SIGNAL 272 | trace.registerNotifier(eve, notif) 273 | 274 | 275 | ####################################################################### 276 | ###################################################################### 277 | load_binary("FOO") -------------------------------------------------------------------------------- /simpleIAT_NX.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pprint 4 | 5 | #VDB_ROOT = "" 6 | #API_ROOT = "" 7 | 8 | sys.path.append(VDB_ROOT) 9 | sys.path.append(API_ROOT) 10 | 11 | #import simpleAPI as v_api 12 | from simpleAPI import getOpCode, getIATLocation, printIAT, store_IAT, nxMemPerm, getOEP, printInfo 13 | 14 | 15 | import vtrace 16 | # import vdb 17 | 18 | import envi 19 | import envi.memory as mem 20 | from envi.archs.i386 import * 21 | 22 | import vtrace.envitools as envitools 23 | 24 | import PE 25 | import vstruct 26 | 27 | # import vdb.recon as v_recon 28 | # import vdb.recon.sniper as v_sniper 29 | # import vdb.stalker as v_stalker 30 | 31 | debug = True 32 | 33 | ################################################################### 34 | class CustomNotifier(vtrace.Notifier): 35 | def notify(self, event, trace): 36 | iat_handler(event, trace) 37 | 38 | ####################################################################### 39 | # Call this function from within a notifier to handle breakpoints on IAT 40 | def iat_handler(event, trace): 41 | print "[*] Got event: %d from pid %d" % (event, trace.getPid()) 42 | 43 | if event == vtrace.NOTIFY_ALL: 44 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 45 | 46 | elif event == vtrace.NOTIFY_SIGNAL: 47 | #print "vtrace.NOTIFY_SIGNAL" 48 | print "[*] PendingSignal",trace.getMeta("PendingSignal") 49 | print "[*] PendingException",trace.getMeta("PendingException") 50 | if trace.getMeta("Platform") == "Windows": 51 | begin = trace.getMeta("IATBegin") 52 | size = trace.getMeta("IATSize") 53 | print "[*] Removing Memory Protections Location: %s" % hex(begin) 54 | print "[*] Memory Size: %s" % size 55 | trace.protectMemory(begin, size, envi.memory.MM_RWX) 56 | 57 | # because MSVC debugger sucks at life 58 | # 1080890248 (0x406d1388) is an exception used to name a thread 59 | # 3765269347 (0xe06d7363) is an exception that is triggered when a throw happens 60 | if (trace.getMeta("PendingSignal") != None) and \ 61 | (trace.getMeta("PendingSignal") != 1080890248) and\ 62 | (trace.getMeta("PendingSignal") != 3765269347): 63 | 64 | win32event = trace.getMeta("Win32Event") 65 | print "[*] ExceptionAddress: %(ExceptionAddress)x" % win32event 66 | 67 | eip = trace.getRegister(REG_EIP) 68 | 69 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 70 | disLen = len(dis) 71 | opcode = trace.readMemory(eip, len(dis)) 72 | 73 | es = trace.getRegisterByName("es") 74 | ds = trace.getRegisterByName("ds") 75 | cs = trace.getRegisterByName("cs") 76 | 77 | ef = trace.getRegisterByName("eflags") 78 | 79 | edi = trace.getRegister(REG_EDI) 80 | esi = trace.getRegister(REG_ESI) 81 | esp = trace.getRegister(REG_ESP) 82 | 83 | printInfo(trace) 84 | 85 | if (len(opcode) == 1): 86 | pass 87 | 88 | # What is this for again? 89 | # scasd i think \x66\xF2 90 | elif (ord(opcode[0]) != 102 and ord(opcode[1]) != 242): 91 | 92 | # function takes in just filename not the full path to filename.exe 93 | filepath = trace.getMeta('ExeName') 94 | exeName = filepath.split(".exe")[0] 95 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 96 | 97 | if(trace.getMeta('IATLocation') == None): 98 | base, poff, psize = getIATLocation(trace, fileName) 99 | trace.setMeta('IATLocation', {'base':base, 'poff':poff, 'psize':psize}) 100 | else: 101 | iatLoc = trace.getMeta('IATLocation') 102 | base = iatLoc['base'] 103 | poff = iatLoc['poff'] 104 | psize = iatLoc['psize'] 105 | 106 | eip = trace.getRegister(REG_EIP) 107 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 108 | 109 | # Check for \xff to determine if a deref call 110 | if (ord(opcode[0]) == 255): 111 | print "OPCODE[1]: ", ord(opcode[1]) 112 | 113 | # Need to accomodate more than just call [eax] and call [edx] 114 | if (ord(opcode[1]) == 48): 115 | eax = trace.getRegister(REG_EAX) 116 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 117 | elif (ord(opcode[1]) == 16): 118 | eax = trace.getRegister(REG_EAX) 119 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 120 | elif (ord(opcode[1]) == 18): 121 | edx = trace.getRegister(REG_EDX) 122 | tmp_addr = struct.unpack("I",trace.readMemory(edx, 4))[0] 123 | 124 | 125 | elif (ord(opcode[1]) == 80): 126 | print "OPCODE[2]: ", ord(opcode[2]) 127 | #if (ord(opcode[2]) == 24): 128 | eax = trace.getRegister(REG_EAX) 129 | #eax += 24 130 | eax += ord(opcode[2]) 131 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 132 | #print "EAX+24: %s" % repr(tmp_addr) 133 | 134 | elif (ord(opcode[1]) == 112): 135 | print "OPCODE[2]: ", ord(opcode[2]) 136 | eax = trace.getRegister(REG_EAX) 137 | eax += ord(opcode[2]) 138 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 139 | elif (ord(opcode[1]) == 215): 140 | edi = trace.getRegister(REG_EDI) 141 | tmp_addr = struct.unpack("I",trace.readMemory(edi, 4))[0] 142 | 143 | else : 144 | tmp_addr = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 145 | 146 | ################################ 147 | # Get the list of imported functions to compare against 148 | try: 149 | instr = trace.getMeta('IATInfo') 150 | except: 151 | base, importTable = printIAT(trace, fileName) 152 | store_IAT(trace, base, importTable, "IATInfo") 153 | instr = trace.getMeta('IATInfo') 154 | 155 | print "TMP_ADDR: %s" % hex(tmp_addr) 156 | try: 157 | a = instr[tmp_addr] 158 | except: 159 | a = "UNKNOWN LIB: UNKNOWN FUNCTION" 160 | 161 | b = a.split(':') 162 | 163 | print "[*] \tLibrary: %s \n[*] \tFunction: %s" % (b[0], b[1]) 164 | 165 | try: 166 | lst = trace.getMeta('IATList') 167 | lst.append(hex(tmp_addr)+':'+b[0]+':'+b[1]) 168 | trace.setMeta('IATList', lst) 169 | except: 170 | print "SET Initial IATList Metadata" 171 | trace.setMeta('IATList', [hex(tmp_addr)+':'+b[0]+':'+b[1]]) 172 | 173 | print "%16s: %s" % ("[*] Opcode[0]", ord(opcode[0])) 174 | 175 | p = trace.getMeta('PendingSignal') 176 | if p!= None: 177 | trace.setMeta('OrigSignal', p) 178 | trace.setMeta('PendingSignal', None) 179 | 180 | print "STEPS" 181 | trace.stepi() 182 | 183 | print "[*] Protecting Memory Location: %s" % hex(begin) 184 | print "[*] Memory Size: %s" % size 185 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 186 | 187 | print "Run Again Set" 188 | trace.runAgain(val=True) 189 | 190 | print "---------------------------------------------------------" 191 | elif event == vtrace.NOTIFY_BREAK: 192 | print "vtrace.NOTIFY_BREAK", hex(trace.getRegister(REG_EIP)) 193 | print "[*] Bestname: ", trace.getSymByAddr(trace.getRegister(REG_EIP), exact=False) 194 | pass 195 | elif event == vtrace.NOTIFY_SYSCALL: 196 | print "vtrace.NOTIFY_SYSCALL" 197 | 198 | elif event == vtrace.NOTIFY_CONTINUE: 199 | print "vtrace.NOTIFY_CONTINUE" 200 | trace.runAgain(val=True) 201 | print "---------------------------------------------------------" 202 | 203 | elif event == vtrace.NOTIFY_EXIT: 204 | print "vtrace.NOTIFY_EXIT" 205 | print "ExitCode",trace.getMeta("ExitCode") 206 | 207 | elif event == vtrace.NOTIFY_ATTACH: 208 | print "vtrace.NOTIFY_ATTACH" 209 | pass 210 | elif event == vtrace.NOTIFY_DETACH: 211 | print "vtrace.NOTIFY_DETACH" 212 | pass 213 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 214 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 215 | pass 216 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 217 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 218 | pass 219 | elif event == vtrace.NOTIFY_CREATE_THREAD: 220 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 221 | pass 222 | elif event == vtrace.NOTIFY_EXIT_THREAD: 223 | print "vtrace.NOTIFY_EXIT_THREAD" 224 | print "ExitThread",trace.getMeta("ExitThread", -1) 225 | pass 226 | elif event == vtrace.NOTIFY_STEP: 227 | print "vtrace.NOTIFY_STEP" 228 | 229 | else: 230 | print "vtrace.NOTIFY_WTF_HUH?", hex(trace.getRegister(REG_EIP)) 231 | 232 | ####################################################################### 233 | def load_binary(filepath, base=None): 234 | trace = vtrace.getTrace() 235 | trace.execute(filepath) 236 | 237 | trace.setMode("FastStep", 1) 238 | 239 | filepath = trace.getMeta('ExeName') 240 | fileName = os.path.basename(filepath).split('.')[0] 241 | 242 | # Call a function to set BP on OEP 243 | oep = getOEP(trace, filepath) 244 | 245 | ####################################################################### 246 | # Get the list of imported functions to compare against 247 | base, importTable = printIAT(trace, fileName) 248 | 249 | base, poff, psize = getIATLocation(trace, fileName, debug) 250 | 251 | # Store the IAT under the meta name IATInfo 252 | store_IAT(trace, base, importTable, "IATInfo") 253 | 254 | psize = trace.arch.getPointerSize() 255 | 256 | memMap = trace.getMemoryMap(base+poff) 257 | begin = memMap[0] 258 | size = len(importTable) * psize 259 | 260 | # put begin in size into the meta data 261 | trace.setMeta("IATBegin", begin) 262 | trace.setMeta("IATSize", size) 263 | 264 | print "[*] Protecting Memory Location: %s" % hex(begin) 265 | print "[*] Memory Size: %s" % size 266 | 267 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 268 | 269 | ####################################################################### 270 | # Enable the notifier. Used later to catch the page execute exception. 271 | notif = CustomNotifier() 272 | eve = vtrace.NOTIFY_ALL 273 | #eve = vtrace.NOTIFY_SIGNAL 274 | trace.registerNotifier(eve, notif) 275 | ####################################################################### 276 | #trace.run() 277 | count = 0 278 | lst = trace.getMeta('IATList') 279 | 280 | # Until you hit Ctrl+C keep looping and printing out IAT calls 281 | # On termination print out all the calls in the order that they were called 282 | while True: 283 | try: 284 | trace.run() 285 | count += 1 286 | lst = trace.getMeta('IATList') 287 | except KeyboardInterrupt: 288 | for i in lst: 289 | a = i.split(':') 290 | print "\t[*] %s \t %s \t %s" % (a[0], a[1], a[2]) 291 | sys.exit(1) 292 | except: 293 | x = pprint.pformat(lst) 294 | 295 | a = x.lstrip('[') 296 | a = a.rstrip(']') 297 | a = a.split('\n') 298 | 299 | for i in a: 300 | i = i.replace("'", "") 301 | i = i.replace("\'", "") 302 | 303 | b = i.split(':') 304 | print "\t[*] %s \t %s \t %s" % (b[0].lstrip(), b[1], b[2].rstrip('\',')) 305 | 306 | sys.exit(2) 307 | 308 | ####################################################################### 309 | ###################################################################### 310 | def main(argv): 311 | if len(argv) != 2: 312 | print "Usage: %s " % sys.argv[0] 313 | sys.exit(1) 314 | 315 | filepath = sys.argv[1] 316 | 317 | load_binary(filepath) 318 | 319 | if __name__ == "__main__": 320 | main(sys.argv) 321 | sys.exit(0) 322 | -------------------------------------------------------------------------------- /command_line/simpleIAT_NX.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pprint 4 | 5 | #VDB_ROOT = "" 6 | #API_ROOT = "" 7 | 8 | sys.path.append(VDB_ROOT) 9 | sys.path.append(API_ROOT) 10 | 11 | #import simpleAPI as v_api 12 | from simpleAPI import getOpCode, getIATLocation, printIAT, store_IAT, nxMemPerm, getOEP, printInfo 13 | 14 | 15 | import vtrace 16 | # import vdb 17 | 18 | import envi 19 | import envi.memory as mem 20 | from envi.archs.i386 import * 21 | 22 | import vtrace.envitools as envitools 23 | 24 | import PE 25 | import vstruct 26 | 27 | # import vdb.recon as v_recon 28 | # import vdb.recon.sniper as v_sniper 29 | # import vdb.stalker as v_stalker 30 | 31 | debug = True 32 | 33 | ################################################################### 34 | class CustomNotifier(vtrace.Notifier): 35 | def notify(self, event, trace): 36 | iat_handler(event, trace) 37 | 38 | ####################################################################### 39 | # Call this function from within a notifier to handle breakpoints on IAT 40 | def iat_handler(event, trace): 41 | print "[*] Got event: %d from pid %d" % (event, trace.getPid()) 42 | 43 | if event == vtrace.NOTIFY_ALL: 44 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 45 | 46 | elif event == vtrace.NOTIFY_SIGNAL: 47 | #print "vtrace.NOTIFY_SIGNAL" 48 | print "[*] PendingSignal",trace.getMeta("PendingSignal") 49 | print "[*] PendingException",trace.getMeta("PendingException") 50 | if trace.getMeta("Platform") == "Windows": 51 | begin = trace.getMeta("IATBegin") 52 | size = trace.getMeta("IATSize") 53 | print "[*] Removing Memory Protections Location: %s" % hex(begin) 54 | print "[*] Memory Size: %s" % size 55 | trace.protectMemory(begin, size, envi.memory.MM_RWX) 56 | 57 | # because MSVC debugger sucks at life 58 | # 1080890248 (0x406d1388) is an exception used to name a thread 59 | # 3765269347 (0xe06d7363) is an exception that is triggered when a throw happens 60 | if (trace.getMeta("PendingSignal") != None) and \ 61 | (trace.getMeta("PendingSignal") != 1080890248) and\ 62 | (trace.getMeta("PendingSignal") != 3765269347): 63 | 64 | win32event = trace.getMeta("Win32Event") 65 | print "[*] ExceptionAddress: %(ExceptionAddress)x" % win32event 66 | 67 | eip = trace.getRegister(REG_EIP) 68 | 69 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 70 | disLen = len(dis) 71 | opcode = trace.readMemory(eip, len(dis)) 72 | 73 | es = trace.getRegisterByName("es") 74 | ds = trace.getRegisterByName("ds") 75 | cs = trace.getRegisterByName("cs") 76 | 77 | ef = trace.getRegisterByName("eflags") 78 | 79 | edi = trace.getRegister(REG_EDI) 80 | esi = trace.getRegister(REG_ESI) 81 | esp = trace.getRegister(REG_ESP) 82 | 83 | printInfo(trace) 84 | 85 | if (len(opcode) == 1): 86 | pass 87 | 88 | # What is this for again? 89 | # scasd i think \x66\xF2 90 | elif (ord(opcode[0]) != 102 and ord(opcode[1]) != 242): 91 | 92 | # function takes in just filename not the full path to filename.exe 93 | filepath = trace.getMeta('ExeName') 94 | exeName = filepath.split(".exe")[0] 95 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 96 | 97 | if(trace.getMeta('IATLocation') == None): 98 | base, poff, psize = getIATLocation(trace, fileName) 99 | trace.setMeta('IATLocation', {'base':base, 'poff':poff, 'psize':psize}) 100 | else: 101 | iatLoc = trace.getMeta('IATLocation') 102 | base = iatLoc['base'] 103 | poff = iatLoc['poff'] 104 | psize = iatLoc['psize'] 105 | 106 | eip = trace.getRegister(REG_EIP) 107 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 108 | 109 | # Check for \xff to determine if a deref call 110 | if (ord(opcode[0]) == 255): 111 | print "OPCODE[1]: ", ord(opcode[1]) 112 | 113 | # Need to accomodate more than just call [eax] and call [edx] 114 | if (ord(opcode[1]) == 48): 115 | eax = trace.getRegister(REG_EAX) 116 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 117 | elif (ord(opcode[1]) == 16): 118 | eax = trace.getRegister(REG_EAX) 119 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 120 | elif (ord(opcode[1]) == 18): 121 | edx = trace.getRegister(REG_EDX) 122 | tmp_addr = struct.unpack("I",trace.readMemory(edx, 4))[0] 123 | 124 | 125 | elif (ord(opcode[1]) == 80): 126 | print "OPCODE[2]: ", ord(opcode[2]) 127 | #if (ord(opcode[2]) == 24): 128 | eax = trace.getRegister(REG_EAX) 129 | #eax += 24 130 | eax += ord(opcode[2]) 131 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 132 | #print "EAX+24: %s" % repr(tmp_addr) 133 | 134 | elif (ord(opcode[1]) == 112): 135 | print "OPCODE[2]: ", ord(opcode[2]) 136 | eax = trace.getRegister(REG_EAX) 137 | eax += ord(opcode[2]) 138 | tmp_addr = struct.unpack("I",trace.readMemory(eax, 4))[0] 139 | elif (ord(opcode[1]) == 215): 140 | edi = trace.getRegister(REG_EDI) 141 | tmp_addr = struct.unpack("I",trace.readMemory(edi, 4))[0] 142 | 143 | else : 144 | tmp_addr = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 145 | 146 | ################################ 147 | # Get the list of imported functions to compare against 148 | try: 149 | instr = trace.getMeta('IATInfo') 150 | except: 151 | base, importTable = printIAT(trace, fileName) 152 | store_IAT(trace, base, importTable, "IATInfo") 153 | instr = trace.getMeta('IATInfo') 154 | 155 | print "TMP_ADDR: %s" % hex(tmp_addr) 156 | try: 157 | a = instr[tmp_addr] 158 | except: 159 | a = "UNKNOWN LIB: UNKNOWN FUNCTION" 160 | 161 | b = a.split(':') 162 | 163 | print "[*] \tLibrary: %s \n[*] \tFunction: %s" % (b[0], b[1]) 164 | 165 | try: 166 | lst = trace.getMeta('IATList') 167 | lst.append(hex(tmp_addr)+':'+b[0]+':'+b[1]) 168 | trace.setMeta('IATList', lst) 169 | except: 170 | print "SET Initial IATList Metadata" 171 | trace.setMeta('IATList', [hex(tmp_addr)+':'+b[0]+':'+b[1]]) 172 | 173 | print "%16s: %s" % ("[*] Opcode[0]", ord(opcode[0])) 174 | 175 | p = trace.getMeta('PendingSignal') 176 | if p!= None: 177 | trace.setMeta('OrigSignal', p) 178 | trace.setMeta('PendingSignal', None) 179 | 180 | print "STEPS" 181 | trace.stepi() 182 | 183 | print "[*] Protecting Memory Location: %s" % hex(begin) 184 | print "[*] Memory Size: %s" % size 185 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 186 | 187 | print "Run Again Set" 188 | trace.runAgain(val=True) 189 | 190 | print "---------------------------------------------------------" 191 | elif event == vtrace.NOTIFY_BREAK: 192 | print "vtrace.NOTIFY_BREAK", hex(trace.getRegister(REG_EIP)) 193 | print "[*] Bestname: ", trace.getSymByAddr(trace.getRegister(REG_EIP), exact=False) 194 | pass 195 | elif event == vtrace.NOTIFY_SYSCALL: 196 | print "vtrace.NOTIFY_SYSCALL" 197 | 198 | elif event == vtrace.NOTIFY_CONTINUE: 199 | print "vtrace.NOTIFY_CONTINUE" 200 | trace.runAgain(val=True) 201 | print "---------------------------------------------------------" 202 | 203 | elif event == vtrace.NOTIFY_EXIT: 204 | print "vtrace.NOTIFY_EXIT" 205 | print "ExitCode",trace.getMeta("ExitCode") 206 | 207 | elif event == vtrace.NOTIFY_ATTACH: 208 | print "vtrace.NOTIFY_ATTACH" 209 | pass 210 | elif event == vtrace.NOTIFY_DETACH: 211 | print "vtrace.NOTIFY_DETACH" 212 | pass 213 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 214 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 215 | pass 216 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 217 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 218 | pass 219 | elif event == vtrace.NOTIFY_CREATE_THREAD: 220 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 221 | pass 222 | elif event == vtrace.NOTIFY_EXIT_THREAD: 223 | print "vtrace.NOTIFY_EXIT_THREAD" 224 | print "ExitThread",trace.getMeta("ExitThread", -1) 225 | pass 226 | elif event == vtrace.NOTIFY_STEP: 227 | print "vtrace.NOTIFY_STEP" 228 | 229 | else: 230 | print "vtrace.NOTIFY_WTF_HUH?", hex(trace.getRegister(REG_EIP)) 231 | 232 | ####################################################################### 233 | def load_binary(filepath, base=None): 234 | trace = vtrace.getTrace() 235 | trace.execute(filepath) 236 | 237 | trace.setMode("FastStep", 1) 238 | 239 | filepath = trace.getMeta('ExeName') 240 | fileName = os.path.basename(filepath).split('.')[0] 241 | 242 | # Call a function to set BP on OEP 243 | oep = getOEP(trace, filepath) 244 | 245 | ####################################################################### 246 | # Get the list of imported functions to compare against 247 | base, importTable = printIAT(trace, fileName) 248 | 249 | base, poff, psize = getIATLocation(trace, fileName, debug) 250 | 251 | # Store the IAT under the meta name IATInfo 252 | store_IAT(trace, base, importTable, "IATInfo") 253 | 254 | psize = trace.arch.getPointerSize() 255 | 256 | memMap = trace.getMemoryMap(base+poff) 257 | begin = memMap[0] 258 | size = len(importTable) * psize 259 | 260 | # put begin in size into the meta data 261 | trace.setMeta("IATBegin", begin) 262 | trace.setMeta("IATSize", size) 263 | 264 | print "[*] Protecting Memory Location: %s" % hex(begin) 265 | print "[*] Memory Size: %s" % size 266 | 267 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 268 | 269 | ####################################################################### 270 | # Enable the notifier. Used later to catch the page execute exception. 271 | notif = CustomNotifier() 272 | eve = vtrace.NOTIFY_ALL 273 | #eve = vtrace.NOTIFY_SIGNAL 274 | trace.registerNotifier(eve, notif) 275 | ####################################################################### 276 | #trace.run() 277 | count = 0 278 | lst = trace.getMeta('IATList') 279 | 280 | # Until you hit Ctrl+C keep looping and printing out IAT calls 281 | # On termination print out all the calls in the order that they were called 282 | while True: 283 | try: 284 | trace.run() 285 | count += 1 286 | lst = trace.getMeta('IATList') 287 | except KeyboardInterrupt: 288 | for i in lst: 289 | a = i.split(':') 290 | print "\t[*] %s \t %s \t %s" % (a[0], a[1], a[2]) 291 | sys.exit(1) 292 | except: 293 | x = pprint.pformat(lst) 294 | 295 | a = x.lstrip('[') 296 | a = a.rstrip(']') 297 | a = a.split('\n') 298 | 299 | for i in a: 300 | i = i.replace("'", "") 301 | i = i.replace("\'", "") 302 | 303 | b = i.split(':') 304 | print "\t[*] %s \t %s \t %s" % (b[0].lstrip(), b[1], b[2].rstrip('\',')) 305 | 306 | sys.exit(2) 307 | 308 | ####################################################################### 309 | ###################################################################### 310 | def main(argv): 311 | if len(argv) != 2: 312 | print "Usage: %s " % sys.argv[0] 313 | sys.exit(1) 314 | 315 | filepath = sys.argv[1] 316 | 317 | load_binary(filepath) 318 | 319 | if __name__ == "__main__": 320 | main(sys.argv) 321 | sys.exit(0) 322 | -------------------------------------------------------------------------------- /sulley/utils/crash_binning.py: -------------------------------------------------------------------------------- 1 | # 2 | # Crash Binning 3 | # Copyright (C) 2006 Pedram Amini 4 | # 5 | # $Id: crash_binning.py 193 2007-04-05 13:30:01Z cameron $ 6 | # 7 | # This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public 8 | # License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 12 | # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along with this program; if not, write to the Free 15 | # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | # 17 | 18 | ''' 19 | @author: Pedram Amini 20 | @license: GNU General Public License 2.0 or later 21 | @contact: pedram.amini@gmail.com 22 | @organization: www.openrce.org 23 | ''' 24 | 25 | import cPickle 26 | import pprint 27 | import sys 28 | import zlib 29 | 30 | import distorm3 31 | 32 | class __crash_bin_struct__: 33 | exception_module = None 34 | exception_address = 0 35 | write_violation = 0 36 | violation_address = 0 37 | violation_thread_id = 0 38 | context = None 39 | context_dump = None 40 | disasm = None 41 | disasm_around = [] 42 | stack_unwind = [] 43 | seh_unwind = [] 44 | extra = None 45 | 46 | def __getitem__(self, key): 47 | return self.data[key] 48 | 49 | 50 | class crash_binning: 51 | ''' 52 | @todo: Add MySQL import/export. 53 | ''' 54 | 55 | bins = {} 56 | last_crash = None 57 | trace = None 58 | arch = '32' # by default we use x86 architecture 59 | 60 | #################################################################################################################### 61 | def __init__ (self): 62 | ''' 63 | ''' 64 | 65 | self.bins = {} 66 | self.last_crash = None 67 | self.trace = None 68 | 69 | 70 | #################################################################################################################### 71 | def set_architecture(self, arch): 72 | ''' 73 | set the architecture to use during disassembly. default is 32bit. 74 | 75 | @type arch: string 76 | @param arch: string value representing bit architecture for disassembly 77 | ''' 78 | if arch == '16': 79 | self.arch = '16' 80 | elif arch == '32': 81 | self.arch = '32' 82 | elif arch == '64': 83 | self.arch = '64' 84 | else: 85 | print '[!] danger: architecture probably not supported!' 86 | self.arch = arch 87 | 88 | 89 | #################################################################################################################### 90 | def record_crash (self, trace, extra=None): 91 | ''' 92 | Given a vtrace instantiation that at the current time is assumed to have "crashed" (access violation for example) 93 | record various details such as the disassemly around the violating address, the ID of the offending thread, the 94 | call stack and the SEH unwind. Store the recorded data in an internal dictionary, binning them by the exception 95 | address. 96 | 97 | @type trace: vtrace 98 | @param trace: Instance of vtrace 99 | @type extra: Mixed 100 | @param extra: (Optional, Def=None) Whatever extra data you want to store with this bin 101 | ''' 102 | 103 | self.trace = trace 104 | crash = __crash_bin_struct__() 105 | 106 | # add module name to the exception address. 107 | exception_module = trace.getSymByAddr(trace.getMeta('Win32Event')['ExceptionAddress'], False) 108 | 109 | if exception_module: 110 | pass 111 | else: 112 | exception_module = "[INVALID]" 113 | 114 | crash.exception_module = exception_module 115 | crash.exception_address = trace.getMeta('Win32Event')['ExceptionAddress'] 116 | crash.write_violation = trace.getMeta('Win32Event')['ExceptionInformation'][0] 117 | crash.violation_address = trace.getMeta('Win32Event')['ExceptionInformation'][1] 118 | crash.violation_thread_id = trace.getMeta('ThreadId') 119 | crash.context = self.register_context(trace, thread=crash.violation_thread_id) 120 | crash.context_dump = self.dump_register_context(crash.context, print_dots=False) 121 | crash.disasm = trace.parseOpcode(crash.exception_address) 122 | crash.disasm_around = self.disasm_around(trace, crash.exception_address, 10) 123 | crash.stack_unwind = trace.getStackTrace() 124 | crash.seh_unwind = self.seh_unwind(trace) 125 | crash.extra = extra 126 | 127 | # add module names to the stack unwind. 128 | for i in xrange(len(crash.stack_unwind)): 129 | addr = crash.stack_unwind[i][0] 130 | frame = crash.stack_unwind[i][1] 131 | try: 132 | rva = self.addr_to_rva(trace, program_counter) 133 | except: 134 | rva = '' 135 | crash.stack_unwind[i] = "rva: %s\t addr: 0x%08x\t frame:0x%08x" \ 136 | % (rva, addr, frame) 137 | 138 | # add module names to the SEH unwind. 139 | for i in xrange(len(crash.seh_unwind)): 140 | (addr, handler) = crash.seh_unwind[i] 141 | try: 142 | rva = self.addr_to_rva(trace, handler) 143 | except: 144 | rva = '' 145 | crash.seh_unwind[i] = (addr, handler, "%s" % (rva, )) 146 | 147 | if not self.bins.has_key(crash.exception_address): 148 | self.bins[crash.exception_address] = [] 149 | 150 | self.bins[crash.exception_address].append(crash) 151 | self.last_crash = crash 152 | 153 | 154 | #################################################################################################################### 155 | def disasm_around(self, trace, starting_addr, size): 156 | ''' 157 | returns the disassembly starting at addr for size instructions. 158 | 159 | @type trace: vtrace 160 | @param trace: instance of vtrace 161 | @type addr: int 162 | @param addr: address where to begin disassembly 163 | @type size: int 164 | @param size: number of instructions to disassemble 165 | ''' 166 | disasm = [] 167 | try: 168 | code = trace.readMemory(starting_addr, size) 169 | except: 170 | raise Exception("unable to read memory for disasm") 171 | 172 | if self.arch == '32': 173 | asm_arch = distorm3.Decode32Bits 174 | elif self.arch == '64': 175 | asm_arch = distorm3.Decode64Bits 176 | elif self.arch == '16': 177 | asm_arch = distorm3.Decode16Bits 178 | 179 | for inst in distorm3.DecomposeGenerator(starting_addr, 180 | code, 181 | asm_arch): 182 | if not inst.valid: 183 | return disasm 184 | else: 185 | disasm.append(inst) 186 | return disasm 187 | 188 | #################################################################################################################### 189 | def dump_register_context(self, regs, print_dots=False): 190 | """ 191 | grab the values for each register 192 | 193 | @type trace: vtrace 194 | @param trace: Instance of vtrace 195 | @type print_dots: boolean 196 | @param print_dots: print dots for non-ascii characters 197 | 198 | @rtype: string 199 | @return: ascii string representation of register contexts 200 | """ 201 | register_string = "" 202 | 203 | for i in sorted(regs.keys()): 204 | ascii_view = "" 205 | bytes_view = [] 206 | for byte in str(regs[i]): 207 | if ord(byte) >= 0x20 and ord(byte) < 0x7f: 208 | ascii_view += byte 209 | else: 210 | if print_dots: 211 | ascii_view += '.' 212 | bytes_view.append("\\x%02x" % ord(byte)) 213 | register_string += '%s: %s-> %s\n' % (i, ''.join(bytes_view), ascii_view, ) 214 | return register_string 215 | 216 | #################################################################################################################### 217 | def register_context(self, trace, thread=None): 218 | """ 219 | grab the values for each register 220 | 221 | @type trace: vtrace 222 | @param trace: Instance of vtrace 223 | 224 | @rtype: dict 225 | @return: register contexts 226 | """ 227 | registers = {} 228 | count = 0 229 | 230 | if not(thread): 231 | regs = trace 232 | else: 233 | regs = trace.getRegisterContext(threadid=thread) 234 | 235 | for reg in regs.getRegisterNames(): 236 | registers[reg] = regs.getRegisterByName(reg) 237 | return registers 238 | 239 | 240 | #################################################################################################################### 241 | def stack_unwind(self, trace, thread=None): 242 | ''' 243 | walk and save the stack trace for the current (or specified) thread. 244 | will be saved in the format [rva, instr addr, frame pointer] 245 | 246 | @type trace: vtrace 247 | @param trace: Instance of vtrace 248 | @type thread: integer 249 | @param thread: id of thread to process seh chain 250 | 251 | @rtype: list 252 | @return: list containing stack trace in (rva, instr addr, frame pointer) format 253 | ''' 254 | call_chain = trace.getStackTrace() 255 | 256 | for i in xrange(len(call_chain)): 257 | addr = call_chain[i][0] 258 | frame = call_chain[i][1] 259 | try: 260 | rva = self.addr_to_rva(trace, addr) 261 | except: 262 | rva = '' 263 | call_chain[i] = "rva: %20s\t addr: 0x%08x\t frame:0x%08x" \ 264 | % (rva, addr, frame) 265 | 266 | return call_chain 267 | 268 | 269 | #################################################################################################################### 270 | def seh_unwind(self, trace, thread=None): 271 | ''' 272 | walk and save the SEH chain for the current (or specified) thread. 273 | will be saved in the format [reg record addr, handler] 274 | adapted from vdb/vdb/extensions/windows.py seh(vdb, line) 275 | 276 | @type trace: vtrace 277 | @param trace: Instance of vtrace 278 | @type thread: integer 279 | @param thread: id of thread to process seh chain 280 | 281 | @rtype: list 282 | @return: list containing seh chain in (reg record addr, handler) format 283 | ''' 284 | seh_chain = [] 285 | 286 | if not(thread): 287 | thread = trace.getMeta('ThreadId') 288 | 289 | thread_info = trace.getThreads().get(thread, None) 290 | if not(thread_info): 291 | raise Exception("Unknown Thread Id: %d" % thread) 292 | 293 | teb = trace.getStruct("ntdll.TEB", thread_info) 294 | addr = long(teb.NtTib.ExceptionList) 295 | while addr != 0xffffffff: 296 | er = trace.getStruct("ntdll.EXCEPTION_REGISTRATION_RECORD", addr) 297 | seh_chain.append((addr, er)) 298 | addr = long(er.Next) 299 | return seh_chain 300 | 301 | 302 | #################################################################################################################### 303 | def addr_to_rva(self, trace, addr): 304 | """ 305 | Convert a virtual address to the RVA with a module name so we 306 | can find it even with ASLR. 307 | 308 | @type trace: vtrace 309 | @param trace: Instance of vtrace 310 | @type addr: integer 311 | @param addr: address to convert to relative virtual address (rva) 312 | 313 | @rtype: string 314 | @return: string representation of rva in [module base]+offset format 315 | """ 316 | sym_for_addr = '' 317 | if trace.getSymByAddr(addr , False): 318 | sym_for_ret_addr = '[ ' + trace.getSymByAddr(addr, False) + ']' 319 | 320 | mem_map = trace.getMemoryMap(addr) 321 | 322 | if not(mem_map): 323 | raise Exception("memory not mapped") 324 | 325 | rva = addr - mem_map[0] 326 | base_module = mem_map[3][mem_map[3].rfind('\\'):].replace('\\','') 327 | base_module = base_module.replace('.dll','') 328 | 329 | return base_module + ('+%08x' % rva) + ' ' + sym_for_addr 330 | 331 | 332 | #################################################################################################################### 333 | def crash_synopsis (self, crash=None): 334 | ''' 335 | For the supplied crash, generate and return a report containing the disassemly around the violating address, 336 | the ID of the offending thread, the call stack and the SEH unwind. If no crash is specified, then return the 337 | same information for the last recorded crash. 338 | 339 | @see: crash_synopsis() 340 | 341 | @type crash: __crash_bin_struct__ 342 | @param crash: (Optional, def=None) Crash object to generate report on 343 | 344 | @rtype: String 345 | @return: Crash report 346 | ''' 347 | 348 | if not crash: 349 | crash = self.last_crash 350 | 351 | if crash.write_violation: 352 | direction = "write to" 353 | else: 354 | direction = "read from" 355 | 356 | synopsis = "%s:%08x %s from thread %d caused access violation\nwhen attempting to %s 0x%08x\n\n" % \ 357 | ( 358 | crash.exception_module, \ 359 | crash.exception_address, \ 360 | crash.disasm, \ 361 | crash.violation_thread_id, \ 362 | direction, \ 363 | crash.violation_address \ 364 | ) 365 | 366 | synopsis += crash.context_dump 367 | 368 | synopsis += "\ndisasm around:\n" 369 | for inst in crash.disasm_around: 370 | synopsis += "\t0x%08s %s\n" % (hex(inst.address).replace('L',''), 371 | str(inst)) 372 | 373 | if len(crash.stack_unwind): 374 | synopsis += "\nstack unwind:\n" 375 | for entry in crash.stack_unwind: 376 | synopsis += "\t%s\n" % entry 377 | 378 | if len(crash.seh_unwind): 379 | synopsis += "\nSEH unwind:\n" 380 | for (addr, handler, handler_str) in crash.seh_unwind: 381 | try: 382 | disasm = trace.parseOpcode(addr) 383 | except: 384 | disasm = "[INVALID]" 385 | 386 | synopsis += "\t0x%08x -> %s\t %s\n" % (addr, handler_str, disasm) 387 | 388 | return synopsis + "\n" 389 | 390 | 391 | #################################################################################################################### 392 | def export_file (self, file_name): 393 | ''' 394 | Dump the entire object structure to disk. 395 | 396 | @see: import_file() 397 | 398 | @type file_name: String 399 | @param file_name: File name to export to 400 | 401 | @rtype: crash_binning 402 | @return: self 403 | ''' 404 | 405 | # null out what we don't serialize but save copies to restore after dumping to disk. 406 | last_crash = self.last_crash 407 | trace = self.trace 408 | 409 | self.last_crash = self.trace = None 410 | 411 | fh = open(file_name, "wb+") 412 | fh.write(zlib.compress(cPickle.dumps(self, protocol=2))) 413 | fh.close() 414 | 415 | self.last_crash = last_crash 416 | self.trace = trace 417 | 418 | return self 419 | 420 | 421 | #################################################################################################################### 422 | def import_file (self, file_name): 423 | ''' 424 | Load the entire object structure from disk. 425 | 426 | @see: export_file() 427 | 428 | @type file_name: String 429 | @param file_name: File name to import from 430 | 431 | @rtype: crash_binning 432 | @return: self 433 | ''' 434 | 435 | fh = open(file_name, "rb") 436 | tmp = cPickle.loads(zlib.decompress(fh.read())) 437 | fh.close() 438 | 439 | self.bins = tmp.bins 440 | 441 | return self 442 | 443 | 444 | #################################################################################################################### 445 | -------------------------------------------------------------------------------- /sulley/process_monitor.py: -------------------------------------------------------------------------------- 1 | import getopt 2 | import os 3 | import pprint 4 | import subprocess 5 | import sys 6 | import threading 7 | import time 8 | 9 | from sulley import pedrpc 10 | 11 | try: 12 | # attempt to import the vtrace module 13 | import vtrace 14 | except: 15 | VDB_ROOT = "..\\vdb\\" 16 | sys.path.append(VDB_ROOT) 17 | import vtrace 18 | 19 | try: 20 | import utils 21 | except: 22 | SULLEY_PATH = ".\\sulley\\" 23 | sys.path.append(SULLEY_PATH) 24 | import utils 25 | 26 | PORT = 26002 27 | ERR = lambda msg: sys.stderr.write("ERR> " + msg + "\n") or sys.exit(1) 28 | USAGE = "USAGE: process_monitor.py"\ 29 | "\n <-c|--crash_bin FILENAME> filename to serialize crash bin class to"\ 30 | "\n [-p|--proc_name NAME] process name to search for and attach to"\ 31 | "\n [-i|--ignore_pid PID] ignore this PID when searching for the target process"\ 32 | "\n [-l|--log_level LEVEL] log level (default 1), increase for more verbosity"\ 33 | "\n [--port PORT] TCP port to bind this agent to" 34 | 35 | ######################################################################################################################## 36 | class ScriptError(Exception): 37 | """ General error """ 38 | pass 39 | 40 | class CallbackNotifier(vtrace.Notifier): 41 | """ 42 | Callback used for procmon. 43 | 44 | Will catch signals and breaks. 45 | """ 46 | ACCESS_VIOLATION = 0xc0000005 47 | READ_VIOLATION = 0x0 48 | WRITE_VIOLATION = 0x1 49 | 50 | def __init__(self, dbg): 51 | vtrace.Notifier.__init__(self) 52 | #self.log = log 53 | self.dbg = dbg 54 | 55 | def notify(self, event, trace): 56 | """ 57 | Handle an event 58 | """ 59 | #print "[!] holy notification batman!" 60 | if event == vtrace.NOTIFY_SIGNAL: # 1 61 | # detect an access violation 62 | self.dbg.process_monitor.log("signal/exception detected witch code: %s" % (trace.getCurrentSignal(), )) 63 | 64 | event_info = trace.getMeta('Win32Event') 65 | for event in event_info.keys(): 66 | try: 67 | self.dbg.process_monitor.log('\t%s value: 0x%08x' % (event, event_info[event])) 68 | except: 69 | self.dbg.process_monitor.log('\t%s value: %s' % (event, event_info[event])) 70 | 71 | # ignore first chance exceptions 72 | if event_info['FirstChance'] == 1: 73 | self.dbg.process_monitor.log("first chance exception") 74 | 75 | if trace.getCurrentSignal() == CallbackNotifier.ACCESS_VIOLATION: 76 | self.dbg_callback_access_violation(trace) 77 | else: 78 | 79 | regs = self.dbg.process_monitor.crash_bin.register_context(trace) 80 | reg = self.dbg.process_monitor.crash_bin.dump_register_context(regs, print_dots=True) 81 | self.dbg.process_monitor.log("Register Context: \n%s\n" % reg, 2) 82 | 83 | stack = self.dbg.process_monitor.crash_bin.stack_unwind(trace) 84 | self.dbg.process_monitor.log("Stack Trace: \n%s\n" % '\n'.join(stack), 2) 85 | 86 | elif event == vtrace.NOTIFY_BREAK: # 2 87 | pass 88 | elif event == vtrace.NOTIFY_CONTINUE: # 5 89 | pass 90 | elif event == vtrace.NOTIFY_EXIT: # 6 91 | self.dbg.process_monitor.log("ExitCode %s" % trace.getMeta("ExitCode")) 92 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: # 9 93 | pass 94 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: # 10 95 | pass 96 | elif event == vtrace.NOTIFY_CREATE_THREAD: # 11 97 | self.dbg.process_monitor.log("CreateThread %s" % trace.getMeta("ThreadId", -1), 5) 98 | pass 99 | elif event == vtrace.NOTIFY_EXIT_THREAD: # 12 100 | self.dbg.process_monitor.log("ExitThread %s" % trace.getMeta("ThreadId", -1), 5) 101 | pass 102 | elif event == vtrace.NOTIFY_DEBUG_PRINT: # 13 103 | self.dbg.process_monitor.log("debug print event number: %s" % (event, ), 5) 104 | self.dbg_callback_debug(trace, self.dbg) 105 | pass 106 | else: 107 | self.dbg.process_monitor.log("other event detected with id: %s" % (event, )) 108 | 109 | trace.runAgain() 110 | 111 | def dbg_callback_access_violation(self, trace): 112 | ''' 113 | Ignore first chance exceptions. Record all unhandled exceptions to the 114 | process monitor crash bin and kill the target process. 115 | ''' 116 | print "[!] access violation " 117 | self.dbg.access_violation = True 118 | 119 | # record the crash to the process monitor crash bin. 120 | # include the test case number in the "extra" information block. 121 | self.dbg.process_monitor.crash_bin.record_crash(trace, extra=self.dbg.process_monitor.test_number) 122 | 123 | # save the the crash synopsis. 124 | self.dbg.process_monitor.last_synopsis = self.dbg.process_monitor.crash_bin.crash_synopsis() 125 | first_line = self.dbg.process_monitor.last_synopsis.split("\n")[0] 126 | 127 | self.dbg.process_monitor.log("debugger thread-%s caught access violation: '%s'" % (self.dbg.getName(), first_line)) 128 | 129 | self.dbg.process_monitor.crash_bin.trace = None 130 | 131 | # save the data to a file 132 | self.dbg.process_monitor.crash_bin.export_file(self.dbg.process_monitor.crash_filename) 133 | # kill the process. 134 | trace.kill() 135 | 136 | return True 137 | 138 | def dbg_callback_debug(self, trace, dbg): 139 | ''' 140 | The debug callback is run each time a debug signal is caught. It will then 141 | print out and log the debugstring. 142 | ''' 143 | debug_info = trace.getMeta('Win32Event')['DebugString'] 144 | self.process_monitor.log(' DebugPrint: \n%s' % (debug_info, )) 145 | 146 | #dbg.process_monitor.log("debugger thread-%s detaching" % dbg.getName(), 5) 147 | return True 148 | 149 | 150 | class debugger_thread(threading.Thread): 151 | def __init__(self, process_monitor, proc_name, ignore_pid=None): 152 | ''' 153 | Instantiate a new vtrace instance and register user and access violation 154 | callbacks. 155 | ''' 156 | threading.Thread.__init__(self) 157 | 158 | self.process_monitor = process_monitor 159 | self.proc_name = proc_name 160 | self.ignore_pid = ignore_pid 161 | 162 | self.access_violation = False 163 | self.active = True 164 | self.trace = vtrace.getTrace() 165 | self.pid = None 166 | 167 | # give this thread a unique name. 168 | self.setName("%d" % time.time()) 169 | 170 | self.process_monitor.log("debugger thread initialized with UID: %s" % self.getName(), 5) 171 | 172 | def run(self): 173 | ''' 174 | Main thread routine, called on thread.start(). Thread exits when this 175 | routine returns. 176 | ''' 177 | self.process_monitor.log("debugger thread-%s looking for process name: %s" % (self.getName(), self.proc_name)) 178 | 179 | # watch for and try attaching to the process. 180 | try: 181 | self.watch() 182 | self.trace.attach(self.pid) 183 | 184 | # set the user callback which is responseable for checking if this thread has been killed. 185 | self.process_monitor.log("registering notifiers") 186 | self.trace.registerNotifier(vtrace.NOTIFY_ALL, CallbackNotifier(self)) 187 | 188 | self.trace.run() 189 | except: 190 | pass 191 | 192 | def watch(self): 193 | ''' 194 | Continuously loop, watching for the target process. This routine "blocks" 195 | until the target process is found. Update self.pid when found and return. 196 | ''' 197 | while not self.pid: 198 | for (pid, name) in self.trace.ps(): 199 | # ignore the optionally specified PID. 200 | if pid == self.ignore_pid: 201 | continue 202 | 203 | if name.lower() == self.proc_name.lower(): 204 | self.pid = pid 205 | break 206 | 207 | self.process_monitor.log("debugger thread-%s found match on pid %d" % (self.getName(), self.pid)) 208 | 209 | 210 | 211 | ######################################################################################################################## 212 | class process_monitor_pedrpc_server (pedrpc.server): 213 | def __init__ (self, host, port, crash_filename, proc_name=None, ignore_pid=None, log_level=1): 214 | ''' 215 | @type host: String 216 | @param host: Hostname or IP address 217 | @type port: Integer 218 | @param port: Port to bind server to 219 | @type crash_filename: String 220 | @param crash_filename: Name of file to (un)serialize crash bin to/from 221 | @type proc_name: String 222 | @param proc_name: (Optional, def=None) Process name to search for and attach to 223 | @type ignore_pid: Integer 224 | @param ignore_pid: (Optional, def=None) Ignore this PID when searching for the target process 225 | @type log_level: Integer 226 | @param log_level: (Optional, def=1) Log output level, increase for more verbosity 227 | ''' 228 | 229 | # initialize the PED-RPC server. 230 | pedrpc.server.__init__(self, host, port) 231 | 232 | self.crash_filename = crash_filename 233 | self.proc_name = proc_name 234 | self.ignore_pid = ignore_pid 235 | self.log_level = log_level 236 | 237 | self.stop_commands = [] 238 | self.start_commands = [] 239 | self.test_number = None 240 | self.debugger_thread = None 241 | self.crash_bin = utils.crash_binning.crash_binning() 242 | 243 | 244 | self.last_synopsis = "" 245 | 246 | if not os.access(os.path.dirname(self.crash_filename), os.X_OK): 247 | self.log("invalid path specified for crash bin: %s" % self.crash_filename) 248 | raise Exception 249 | 250 | # restore any previously recorded crashes. 251 | try: 252 | self.crash_bin.import_file(self.crash_filename) 253 | except: 254 | pass 255 | 256 | self.log("Process Monitor PED-RPC server initialized:") 257 | self.log("\t crash file: %s" % self.crash_filename) 258 | self.log("\t # records: %d" % len(self.crash_bin.bins)) 259 | self.log("\t proc name: %s" % self.proc_name) 260 | self.log("\t log level: %d" % self.log_level) 261 | self.log("awaiting requests...") 262 | 263 | 264 | def alive (self): 265 | ''' 266 | Returns True. Useful for PED-RPC clients who want to see if the PED-RPC connection is still alive. 267 | ''' 268 | 269 | return True 270 | 271 | 272 | def get_crash_synopsis (self): 273 | ''' 274 | Return the last recorded crash synopsis. 275 | 276 | @rtype: String 277 | @return: Synopsis of last recorded crash. 278 | ''' 279 | 280 | return self.last_synopsis 281 | 282 | 283 | def get_bin_keys (self): 284 | ''' 285 | Return the crash bin keys, ie: the unique list of exception addresses. 286 | 287 | @rtype: List 288 | @return: List of crash bin exception addresses (keys). 289 | ''' 290 | 291 | return self.crash_bin.bins.keys() 292 | 293 | 294 | def get_bin (self, bin): 295 | ''' 296 | Return the crash entries from the specified bin or False if the bin key is invalid. 297 | 298 | @type bin: Integer (DWORD) 299 | @param bin: Crash bin key (ie: exception address) 300 | 301 | @rtype: List 302 | @return: List of crashes in specified bin. 303 | ''' 304 | 305 | if not self.crash_bin.bins.has_key(bin): 306 | return False 307 | 308 | return self.crash_bin.bins[bin] 309 | 310 | 311 | def log (self, msg="", level=1): 312 | ''' 313 | If the supplied message falls under the current log level, print the specified message to screen. 314 | 315 | @type msg: String 316 | @param msg: Message to log 317 | ''' 318 | 319 | if self.log_level >= level: 320 | print "[%s] %s" % (time.strftime("%I:%M.%S"), msg) 321 | 322 | 323 | def post_send (self): 324 | ''' 325 | This routine is called after the fuzzer transmits a test case and returns the status of the target. 326 | 327 | @rtype: Boolean 328 | @return: Return True if the target is still active, False otherwise. 329 | ''' 330 | 331 | av = self.debugger_thread.access_violation 332 | print "post_send: av: %s" % (av, ) 333 | 334 | # if there was an access violation, wait for the debugger thread to finish then kill thread handle. 335 | # it is important to wait for the debugger thread to finish because it could be taking its sweet ass time 336 | # uncovering the details of the access violation. 337 | if av: 338 | while self.debugger_thread.isAlive(): 339 | time.sleep(1) 340 | 341 | self.debugger_thread = None 342 | 343 | # serialize the crash bin to disk. 344 | self.crash_bin.export_file(self.crash_filename) 345 | 346 | bins = len(self.crash_bin.bins) 347 | crashes = 0 348 | 349 | print "post_send: crash_bins: %d" % (bins, ) 350 | 351 | for bin in self.crash_bin.bins.keys(): 352 | crashes += len(self.crash_bin.bins[bin]) 353 | 354 | return not av 355 | 356 | 357 | def pre_send (self, test_number): 358 | ''' 359 | This routine is called before the fuzzer transmits a test case and ensure the debugger thread is operational. 360 | 361 | @type test_number: Integer 362 | @param test_number: Test number to retrieve PCAP for. 363 | ''' 364 | 365 | self.log("pre_send(%d)" % test_number, 10) 366 | 367 | self.test_number = test_number 368 | 369 | # unserialize the crash bin from disk. 370 | # this ensures we have the latest copy (ie: vmware image is cycling). 371 | try: 372 | self.crash_bin.import_file(self.crash_filename) 373 | except: 374 | pass 375 | 376 | # if we don't already have a debugger thread, instantiate and start one now. 377 | if not self.debugger_thread or not self.debugger_thread.isAlive(): 378 | self.log("creating debugger thread", 5) 379 | self.debugger_thread = debugger_thread(self, self.proc_name, self.ignore_pid) 380 | 381 | self.debugger_thread.start() 382 | self.log("giving debugger thread 2 seconds to settle in", 5) 383 | time.sleep(2) 384 | 385 | 386 | def start_target (self): 387 | ''' 388 | Start up the target process by issuing the commands in self.start_commands. 389 | ''' 390 | 391 | self.log("starting target process") 392 | 393 | for command in self.start_commands: 394 | #subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 395 | subprocess.Popen(command) 396 | 397 | self.log("done. target up and running, giving it 5 seconds to settle in.") 398 | time.sleep(5) 399 | 400 | 401 | def stop_target (self): 402 | ''' 403 | Kill the current debugger thread and stop the target process by issuing the commands in self.stop_commands. 404 | ''' 405 | 406 | # give the debugger thread a chance to exit. 407 | time.sleep(1) 408 | 409 | self.log("stopping target process") 410 | 411 | for command in self.stop_commands: 412 | if command == "TERMINATE_PID": 413 | trace = vtrace.getTrace() 414 | for (pid, name) in trace.ps(): 415 | if name.find(self.proc_name.lower()) != -1: 416 | os.system("taskkill /pid %d" % pid) 417 | break 418 | else: 419 | os.system(command) 420 | 421 | 422 | def set_proc_name (self, proc_name): 423 | self.log("updating target process name to '%s'" % proc_name) 424 | 425 | self.proc_name = proc_name 426 | 427 | 428 | def set_start_commands (self, start_commands): 429 | self.log("updating start commands to: %s" % start_commands) 430 | 431 | self.start_commands = start_commands 432 | 433 | 434 | def set_stop_commands (self, stop_commands): 435 | self.log("updating stop commands to: %s" % stop_commands) 436 | 437 | self.stop_commands = stop_commands 438 | 439 | 440 | ######################################################################################################################## 441 | 442 | if __name__ == "__main__": 443 | # parse command line options. 444 | try: 445 | opts, args = getopt.getopt(sys.argv[1:], "c:i:l:p:", ["crash_bin=", "ignore_pid=", "log_level=", "proc_name=", "port="]) 446 | except getopt.GetoptError: 447 | ERR(USAGE) 448 | 449 | crash_bin = ignore_pid = proc_name = None 450 | log_level = 1 451 | 452 | for opt, arg in opts: 453 | if opt in ("-c", "--crash_bin"): crash_bin = arg 454 | if opt in ("-i", "--ignore_pid"): ignore_pid = int(arg) 455 | if opt in ("-l", "--log_level"): log_level = int(arg) 456 | if opt in ("-p", "--proc_Name"): proc_name = arg 457 | if opt in ("-P", "--port"): PORT = int(arg) 458 | 459 | if not crash_bin: 460 | ERR(USAGE) 461 | 462 | # spawn the PED-RPC servlet. 463 | try: 464 | servlet = process_monitor_pedrpc_server("0.0.0.0", PORT, crash_bin, proc_name, ignore_pid, log_level) 465 | servlet.serve_forever() 466 | except: 467 | print "Error starting RPC server!" 468 | pass 469 | -------------------------------------------------------------------------------- /simpleAPI.py: -------------------------------------------------------------------------------- 1 | #VDB_ROOT = "" 2 | 3 | import sys 4 | sys.path.append(VDB_ROOT) 5 | 6 | import binascii 7 | 8 | import vtrace 9 | import vdb 10 | 11 | import envi 12 | import envi.archs.i386.disasm as dis 13 | from envi.archs.i386 import * 14 | import envi.memory as mem 15 | 16 | 17 | import PE as PE 18 | #import vstruct 19 | 20 | import vtrace.envitools as envitools 21 | import vtrace.snapshot as vs_snap 22 | 23 | import vdb.recon as v_recon 24 | import vdb.recon.sniper as v_sniper 25 | import vdb.stalker as v_stalker 26 | 27 | AddrFmt='L' 28 | debug = False 29 | 30 | # Sample Notifier class 31 | # Prints a statement for each type of event encountered 32 | class CustomNotifier(vtrace.Notifier): 33 | # Event is one of the vtrace.NOTIFY_* things listed under vtrace 34 | 35 | def notify(self, event, trace): 36 | print "Got event: %d from pid %d" % (event, trace.getPid()) 37 | print "PID %d thread(%d) got" % (trace.getPid(), trace.getMeta("ThreadId")) 38 | 39 | # get the details 40 | #details = trace.getMeta('Win32Event') 41 | #print "DETAILS: ", details 42 | 43 | if event == vtrace.NOTIFY_ALL: 44 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 45 | 46 | elif event == vtrace.NOTIFY_SIGNAL: 47 | print "vtrace.NOTIFY_SIGNAL" 48 | print "PendingSignal",trace.getMeta("PendingSignal") 49 | print "PendingException",trace.getMeta("PendingException") 50 | if trace.getMeta("Platform") == "Windows": 51 | print repr(trace.getMeta("Win32Event")) 52 | print vdb.getSignal(trace.getMeta("PendingSignal")) 53 | win32 = self.getMeta("Win32Event", None) 54 | if win32: 55 | code = win32["ExceptionCode"] 56 | print "Win32 ExceptCode: ", code 57 | 58 | elif event == vtrace.NOTIFY_BREAK: 59 | print "vtrace.NOTIFY_BREAK", printableEIP(trace) 60 | pass 61 | elif event == vtrace.NOTIFY_SYSCALL: 62 | print "vtrace.NOTIFY_SYSCALL" 63 | elif event == vtrace.NOTIFY_CONTINUE: 64 | print "vtrace.NOTIFY_CONTINUE" 65 | pass 66 | elif event == vtrace.NOTIFY_EXIT: 67 | print "vtrace.NOTIFY_EXIT" 68 | print "ExitCode",trace.getMeta("ExitCode") 69 | elif event == vtrace.NOTIFY_ATTACH: 70 | print "vtrace.NOTIFY_ATTACH" 71 | pass 72 | elif event == vtrace.NOTIFY_DETACH: 73 | print "vtrace.NOTIFY_DETACH" 74 | pass 75 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 76 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 77 | pass 78 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 79 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 80 | pass 81 | elif event == vtrace.NOTIFY_CREATE_THREAD: 82 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 83 | pass 84 | elif event == vtrace.NOTIFY_EXIT_THREAD: 85 | print "vtrace.NOTIFY_EXIT_THREAD" 86 | print "ExitThread",trace.getMeta("ExitThread", -1) 87 | pass 88 | elif event == vtrace.NOTIFY_STEP: 89 | print "vtrace.NOTIFY_STEP" 90 | pass 91 | else: 92 | print "vtrace.NOTIFY_WTF_HUH?" 93 | 94 | # Print out the value in EIP as a long 95 | def getEIP(trace): 96 | eip = trace.getRegister(REG_EIP) 97 | return eip 98 | 99 | # Print out the value in EIP as a hex number 100 | def printableEIP(trace): 101 | return hex(getEIP(trace)) 102 | 103 | # Print out the value of ESP as a long 104 | def getESP(trace): 105 | esp = trace.getRegister(REG_ESP) 106 | return esp 107 | 108 | # Print out the value of the memory ESP points to 109 | # if the program is stopped in the appropriate spot 110 | # this is the return value for the function. 111 | def getRET(trace): 112 | esp = getESP(trace) 113 | retaddr = trace.readMemory(esp, 4) 114 | return struct.unpack("I",retaddr)[0] 115 | 116 | # Same as above only in hex 117 | def getPrintableRET(trace): 118 | esp = getESP(trace) 119 | retprt = trace.readMemory(esp, 4) 120 | return hex(struct.unpack("I",retaddr)[0]) 121 | 122 | def getOpCode(trace, eip): 123 | s = trace.readMemory(eip,15) 124 | op1 = trace.makeOpcode(s, 0, eip) 125 | return op1 126 | 127 | def getSnapshot(trace): 128 | # Snapshot still broken when new features are enabled (Stalker) 129 | # might have something to do with the deep copy of the meta tags 130 | return vs_snap.takeSnapshot(trace) 131 | 132 | def snapshotToFile(snap, filename): 133 | f = file(filename, "wb") 134 | f.write(str(snap)) 135 | #pickle.dump(snap, f) 136 | f.close() 137 | 138 | def getStalkerInfo(trace): 139 | print("STALKER BREAKS: ", trace.getMeta("StalkerBreaks")) 140 | print("STALKER HITS: ", trace.getMeta("StalkerHits")) 141 | print("STALKER CODE FLOW: ", trace.getMeta("StalkerCodeFlow")) 142 | 143 | def getReconInfo(trace): 144 | print("RECON HITS: ", trace.getMeta("recon_hits")) 145 | print("RECON QUIET: ", trace.getMeta("recon_quiet")) 146 | print("TRACKER BREAK: ", trace.getMeta("TrackerBreak")) 147 | 148 | # Only returns the address to the first function found 149 | def findFunc(trace, pattern): 150 | pattern = pattern.lower() 151 | libs = trace.getNormalizedLibNames() 152 | libs.sort() 153 | for libname in libs: 154 | for sym in trace.getSymsForFile(libname): 155 | r = repr(sym) 156 | if pattern != None: 157 | if r.lower().find(pattern.lower()) == -1: 158 | continue 159 | print("0x%.8x %s" % (sym.value, r)) 160 | return sym.value 161 | 162 | def setBpOnPattern(trace, pattern): 163 | addr = findFunc(trace, pattern) 164 | bp = vtrace.Breakpoint(addr) 165 | trace.addBreakpoint(bp) 166 | 167 | def printBp(trace): 168 | for bp in trace.getBreakpoints(): 169 | print("%s enabled: %s" % (bp, bp.isEnabled())) 170 | 171 | def getOEP(trace, filepath): 172 | base = None 173 | 174 | libs = trace.getMeta("LibraryPaths") 175 | for k, v in libs.iteritems(): 176 | if filepath in v: 177 | base = k 178 | 179 | if base is None: 180 | p = PE.peFromFileName(filepath) 181 | base = p.IMAGE_NT_HEADERS.OptionalHeader.ImageBase 182 | else: 183 | p = PE.peFromMemoryObject(trace, base) 184 | 185 | ep = p.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint 186 | oep = base + ep 187 | return oep 188 | 189 | # This function will change the input variables so that child process 190 | # starts paused. Then reads the PID of the newly created child process 191 | # and attaches to it 192 | # NOTE: trace object should be at the _1st_ instruction in CreateProcessA 193 | # for this to function. Upon return you will be at OEP for child process 194 | def followCreateProcessA(trace): 195 | dwAddr = trace.getRegister(REG_ESP) 196 | 197 | dwAddr +=4#remove eip 198 | dwAddr +=4#remove lpApplicationName 199 | dwAddr +=4#remove lpCommandLine 200 | dwAddr +=4#remove procattrs 201 | 202 | dwAddr +=4#remove threadattrs 203 | dwAddr +=4#remove inheritHandles 204 | dwCreateFlags=struct.unpack("I",trace.readMemory(dwAddr,4))[0] 205 | dwCreateFlags|=4 206 | dwCreateFlags=struct.pack("I",dwCreateFlags) 207 | try: 208 | trace.writeMemory(dwCreateFlags,dwAddr) 209 | except: 210 | pass 211 | 212 | # Add a breakpoint on the return address from CreateProcessA 213 | # Run to it and then call afterCreateProcessA 214 | # This is so the PID variable is populated. 215 | 216 | esp = trace.getRegister(REG_ESP) 217 | ret = trace.readMemory(esp,4) 218 | ret2 = struct.unpack("I",ret)[0] 219 | bp = vtrace.Breakpoint(None, expression=hex(ret2)) 220 | trace.addBreakpoint(bp) 221 | printBp(trace) 222 | 223 | trace.run() 224 | esp = trace.getRegister(REG_ESP) 225 | 226 | dwAddr = esp 227 | dwAddr -=44#move esp to location of stack from CreateProcessA 228 | dwAddr +=24#move esp to location after some CreateProcessA variables 229 | 230 | dwAddr +=4#remove dwCreationFlags 231 | dwAddr +=4#remove lpEnvironment 232 | 233 | dwAddr +=4#remove lpCurrentDirectory 234 | dwAddr +=4#remove lsStartupInfo 235 | # dwAddr points to lpProcessInformation 236 | #print "dwAddr: ", dwAddr 237 | procid = trace.readMemory(dwAddr, 4) 238 | procid = struct.unpack("I", procid)[0] 239 | procid +=4#remove hProcess 240 | procid +=4#remove hThread 241 | # procid points to dwProcessId 242 | try: 243 | pid = struct.unpack("I", trace.readMemory(procid, 4))[0] 244 | print "ProcID: ", pid 245 | if pid != None: 246 | trace.attach(pid) 247 | print "ADD TRACE: ", trace.getPid() 248 | except: 249 | pass 250 | 251 | return trace 252 | 253 | # Change the permissions on the memory map containing addr 254 | # removing execute permissions. 255 | # Catch the exception in the notifier, change the permissions 256 | # back and continue running the child process with the debugger attached. 257 | # NOTE: Notifier must be enabled before the call to this function. 258 | def nxMemPerm(trace, addr): 259 | memMap = trace.getMemoryMap(addr) 260 | begin = memMap[0] 261 | size = memMap[1] 262 | #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 263 | #print "FROM: ", hex(begin) 264 | #print "SIZE: ", size 265 | 266 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 267 | print "[*] Memory Perm Set to None from: %s size: %s" % (hex(begin), size) 268 | #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 269 | trace.run() 270 | 271 | # Will parse the PE in memory and return the array containing the IAT 272 | # If verbose is true it will also print out the IAT 273 | def printIAT(trace, fileName, verbose=False): 274 | #print "FileName: %s" % fileName 275 | 276 | libs = trace.getMeta("LibraryPaths") 277 | libBase = trace.getMeta("LibraryBases") 278 | #print "Lib Base: %s" % libBase 279 | #print "File Name: %s" % fileName 280 | 281 | base = libBase[fileName.lower()] 282 | 283 | p = PE.peFromMemoryObject(trace, base) 284 | 285 | IMAGE_DIRECTORY_ENTRY_IMPORT =1 # Import Directory 286 | IMAGE_DIRECTORY_ENTRY_IAT =12 # Import Address Table 287 | 288 | idir = p.IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] 289 | poff = p.rvaToOffset(idir.VirtualAddress) 290 | psize = idir.Size 291 | # Once you have VirtualAddress BP on that and you can stop 292 | # the program before any external call. 293 | 294 | p.parseImports() 295 | if verbose == True: 296 | for i in p.imports: 297 | print("Address: %s \tLibrary: %s \tFirstThunk: %s" % (hex(base+i[0]), i[1], i[2])) 298 | return base, p.imports 299 | 300 | # Will parse the PE in memory and return the array containing the IAT 301 | # If verbose is true it will also print out the IAT 302 | def getIATLocation(trace, fileName, verbose=False): 303 | #print "FileName: %s" % fileName 304 | 305 | libs = trace.getMeta("LibraryPaths") 306 | libBase = trace.getMeta("LibraryBases") 307 | #print "Lib Base: %s" % libBase 308 | #print "File Name: %s" % fileName 309 | 310 | base = libBase[fileName.lower()] 311 | 312 | p = PE.peFromMemoryObject(trace, base) 313 | 314 | IMAGE_DIRECTORY_ENTRY_IMPORT =1 # Import Directory 315 | IMAGE_DIRECTORY_ENTRY_IAT =12 # Import Address Table 316 | 317 | idir = p.IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] 318 | poff = p.rvaToOffset(idir.VirtualAddress) 319 | psize = idir.Size 320 | # Once you have VirtualAddress BP on that and you can stop 321 | # the program before any external call. 322 | return base, poff, psize 323 | 324 | # Store the IAT under the meta name 325 | def store_IAT(trace, base, importTable, metaname): 326 | for i in importTable: 327 | #print "[*] \tAddr: %s \tLibrary: %s [*] \tFunction: %s" % (hex(base+i[0]), i[1], i[2]) 328 | 329 | instr = trace.getMeta(metaname) 330 | if instr == None: 331 | trace.setMeta(metaname, {base+i[0]:i[1]+':'+i[2]}) 332 | else: 333 | instr[base+i[0]] = i[1]+':'+i[2] 334 | #instr.append(hex(base+i[0])+':'+i[1]+':'+i[2]) 335 | trace.setMeta(metaname, instr) 336 | 337 | # Call this function from within a notifier to handle breakpoints on IAT 338 | def iat_handler(event, trace): 339 | print "[*] Got event: %d from pid %d" % (event, trace.getPid()) 340 | 341 | if event == vtrace.NOTIFY_SIGNAL: 342 | #print "vtrace.NOTIFY_SIGNAL" 343 | print "[*] PendingSignal",trace.getMeta("PendingSignal") 344 | print "[*] PendingException",trace.getMeta("PendingException") 345 | if trace.getMeta("Platform") == "Windows": 346 | win32event = trace.getMeta("Win32Event") 347 | print "[*] ExceptionAddress: %(ExceptionAddress)x" % win32event 348 | 349 | eip = trace.getRegister(REG_EIP) 350 | print "[*] Bestname: ", trace.getSymByAddr(eip, exact=False) 351 | 352 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 353 | disLen = len(dis) 354 | opcode = trace.readMemory(eip, len(dis)) 355 | 356 | print "%16s: %s" % ("DIS", dis) 357 | print "%16s: %s" % ("OPCODE", repr(opcode)) 358 | 359 | print "%16s: %s" % ("EAX", hex(trace.getRegister(REG_EAX))) 360 | es = trace.getRegisterByName("es") 361 | print "%16s: %s" % ("ES", es) 362 | ds = trace.getRegisterByName("ds") 363 | print "%16s: %s" % ("DS", ds) 364 | cs = trace.getRegisterByName("cs") 365 | print "%16s: %s" % ("CS", cs) 366 | edi = trace.getRegister(REG_EDI) 367 | print "%16s: %s" % ("EDI", hex(edi)) 368 | esi = trace.getRegister(REG_ESI) 369 | print "%16s: %s" % ("ESI", hex(esi)) 370 | esp = trace.getRegister(REG_ESP) 371 | print "%16s: %s" % ("ESP", hex(esp)) 372 | print "%16s: %s" % ("[ESP]", repr(trace.readMemory(esp, 4))) 373 | 374 | ef = trace.getRegisterByName("eflags") 375 | print("%16s: %s" % ("Direction", bool(ef & EFLAGS_DF))) 376 | 377 | #print("%16s: %s" % ("Carry", bool(ef & EFLAGS_CF))) 378 | #print("%16s: %s" % ("Parity", bool(ef & EFLAGS_PF))) 379 | #print("%16s: %s" % ("Adjust", bool(ef & EFLAGS_AF))) 380 | #print("%16s: %s" % ("Zero", bool(ef & EFLAGS_ZF))) 381 | #print("%16s: %s" % ("Sign", bool(ef & EFLAGS_SF))) 382 | #print("%16s: %s" % ("Trap", bool(ef & EFLAGS_TF))) 383 | #print("%16s: %s" % ("Interrupt", bool(ef & EFLAGS_IF))) 384 | #print("%16s: %s" % ("Overflow", bool(ef & EFLAGS_OF))) 385 | 386 | #regs = trace.getRegisters() 387 | #print "REGS: ", regs 388 | #rnames = regs.keys() 389 | #rnames.sort() 390 | 391 | # function takes in just filename not the full path to filename.exe 392 | filepath = trace.getMeta('ExeName') 393 | exeName = filepath.split(".exe")[0] 394 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 395 | 396 | if(trace.getMeta('IATLocation') == None): 397 | base, poff, psize = getIATLocation(trace, fileName) 398 | trace.setMeta('IATLocation', {'base':base, 'poff':poff, 'psize':psize}) 399 | else: 400 | iatLoc = trace.getMeta('IATLocation') 401 | base = iatLoc['base'] 402 | poff = iatLoc['poff'] 403 | psize = iatLoc['psize'] 404 | 405 | memMap = trace.getMemoryMap(base+poff) 406 | begin = memMap[0] 407 | size = memMap[1] 408 | 409 | trace.protectMemory(begin, size, envi.memory.MM_RWX) 410 | 411 | # Check the opcode to see if it is a call or a deref call 412 | if (ord(opcode[0]) == 255 and ord(opcode[1]) == 21): 413 | # Increment eip by length of command to get next eip 414 | # then pack it so it will be written to memory correctly 415 | 416 | nextAddr = eip + disLen 417 | pack = struct.pack("I", nextAddr) 418 | 419 | # Get esp register location and sub 4 bytes to simulate push 420 | esp = trace.getRegister(REG_ESP) 421 | popesp = esp - 4 422 | 423 | # write 4 byte next eip to new esp location 424 | # then update esp variable 425 | trace.setRegister(REG_ESP, popesp) 426 | esp = trace.getRegister(REG_ESP) 427 | 428 | # write the return addr to the new esp location 429 | trace.writeMemory(esp, pack) 430 | 431 | # Check the opcode to see if it is a call or a deref call 432 | if (ord(opcode[0]) == 255 and ord(opcode[1]) == 21): 433 | tmp = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 434 | newEip = tmp 435 | 436 | newOpcode = "\xFF\x25" 437 | newOpcode += struct.pack("I", newEip) 438 | 439 | trace.writeMemory(eip, newOpcode) 440 | 441 | eip = trace.getRegister(REG_EIP) 442 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 443 | 444 | # Check for \xff to determine if a deref call 445 | if (ord(opcode[0]) == 255): 446 | #and ord(opcode[1]) == 21) or (ord(opcode[0]) == 255 and ord(opcode[1]) == 37)): 447 | #print "OPCODE: %s" % repr(opcode) 448 | tmp_addr = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 449 | 450 | ################################ 451 | # Get the list of imported functions to compare against 452 | instr = trace.getMeta('IATInfo') 453 | 454 | try: 455 | print "TMP_ADDR: %s" % hex(tmp_addr) 456 | a = instr[tmp_addr] 457 | b = a.split(':') 458 | 459 | print "[*] \tLibrary: %s \n[*] \tFunction: %s" % (b[0], b[1]) 460 | 461 | lst = trace.getMeta('IATList') 462 | if lst == None: 463 | trace.setMeta('IATList', [hex(tmp_addr)+':'+b[0]+':'+b[1]]) 464 | else: 465 | lst.append(hex(tmp_addr)+':'+b[0]+':'+b[1]) 466 | trace.setMeta('IATList', lst) 467 | 468 | except: 469 | print "\t\t ********** ISSUE **********" 470 | 471 | # if(i[2] == accept): 472 | # Do something specific to accept 473 | # ****************************** 474 | 475 | 476 | 477 | print "%16s: %s" % ("[*] Opcode[0]", ord(opcode[0])) 478 | 479 | # 15 is movzx esi, word [edi] AND movzx edi, word [ecx] 480 | # 102 is scasd 481 | # 242 is scasb ? 482 | if((ord(opcode[0]) == 102) or (ord(opcode[0]) == 15) or (ord(opcode[0]) == 242)): 483 | print "%16s: %s" % ("[*] PROBLEM OPCODE", "Detected") 484 | try: 485 | test = trace.probeMemory(edi,4, envi.memory.MM_READ) 486 | print "[*] Readable Memory: ", test 487 | if test: 488 | print "%16s: %s" % ("MEM", trace.readMemory(edi, 4)) 489 | 490 | except Exception as e: 491 | print type(e) 492 | print e.args 493 | print e 494 | 495 | print "%16s: %s" % ("Error Reading Mem from", hex(edi)) 496 | 497 | p = trace.getMeta('PendingSignal') 498 | if p!= None: 499 | trace.setMeta('OrigSignal', p) 500 | trace.setMeta('PendingSignal', None) 501 | 502 | #notif = CustomNotifier() 503 | eve = vtrace.NOTIFY_SIGNAL 504 | 505 | trace.deregisterNotifier(eve, notif) 506 | trace.stepi() 507 | 508 | trace.registerNotifier(eve, notif) 509 | 510 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 511 | trace.runAgain(val=True) 512 | print "---------------------------------------------------------" 513 | else: 514 | print "vtrace.NOTIFY_WTF_HUH?", printableEIP(trace) 515 | 516 | # Will decode shellcode in a linear manner 517 | # shellcode must be in the format '\x90\x90\xCC\xCC' 518 | # for the code to function properly 519 | def disasm(trace, shell): 520 | d = dis.i386Disasm() 521 | i = 0 522 | count = 0 523 | while count < len(shell): 524 | try: 525 | op = trace.makeOpcode(shell, offset=i, va=0) 526 | print "%14s:\t %s" %(shell[count:count+op.size].encode('hex'), op) 527 | #print "COUNT: ", count 528 | #print "OP SIZE: ", op.size 529 | i += 1 530 | count += op.size 531 | except: 532 | print "ERROR: ", sys.exc_info()[1] 533 | i += 1 534 | count += 1 535 | continue 536 | 537 | def printInfo(trace): 538 | eip = trace.getRegister(REG_EIP) 539 | 540 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 541 | disLen = len(dis) 542 | opcode = trace.readMemory(eip, len(dis)) 543 | 544 | es = trace.getRegisterByName("es") 545 | ds = trace.getRegisterByName("ds") 546 | cs = trace.getRegisterByName("cs") 547 | 548 | ef = trace.getRegisterByName("eflags") 549 | 550 | edi = trace.getRegister(REG_EDI) 551 | esi = trace.getRegister(REG_ESI) 552 | esp = trace.getRegister(REG_ESP) 553 | 554 | print "[*] Bestname: ", trace.getSymByAddr(eip, exact=False) 555 | print "%16s: %s" % ("EIP", hex(eip)) 556 | 557 | print "%16s: %s" % ("DIS", dis) 558 | print "%16s: %s" % ("OPCODE", repr(opcode)) 559 | print "%16s: %s" % ("ES", es) 560 | print "%16s: %s" % ("DS", ds) 561 | print "%16s: %s" % ("CS", cs) 562 | print "%16s: %s" % ("EAX", hex(trace.getRegister(REG_EAX))) 563 | print "%16s: %s" % ("EBX", hex(trace.getRegister(REG_EBX))) 564 | print "%16s: %s" % ("ECX", hex(trace.getRegister(REG_ECX))) 565 | print "%16s: %s" % ("EDX", hex(trace.getRegister(REG_EDX))) 566 | 567 | print "%16s: %s" % ("EDI", hex(edi)) 568 | print "%16s: %s" % ("ESI", hex(esi)) 569 | 570 | print "%16s: %s" % ("ESP", hex(esp)) 571 | print "%16s: %s" % ("[ESP]", repr(trace.readMemory(esp, 4))) 572 | 573 | print("%16s: %s" % ("Direction", bool(ef & EFLAGS_DF))) 574 | 575 | 576 | ############################################################ 577 | # Super ghetto, not recommended 578 | def addOpCodeToList(opList): 579 | try: 580 | opList[getEIP(trace)] += 1 581 | except: 582 | opList[getEIP(trace)] = 1 583 | 584 | 585 | 586 | def mainTemplate(argv): 587 | if len(argv) != 2: 588 | # sys.argv[0] is the name of the script 589 | print "Usage: %s " % sys.argv[0] 590 | sys.exit(1) 591 | 592 | # sys.argv[1] is the first argument passed to script 593 | filepath = sys.argv[1] 594 | 595 | load_binary(filepath) 596 | 597 | # if __name__ == "__main__": 598 | # main(sys.argv) 599 | # sys.exit(0) -------------------------------------------------------------------------------- /command_line/simpleAPI.py: -------------------------------------------------------------------------------- 1 | #VDB_ROOT = "" 2 | 3 | import sys 4 | sys.path.append(VDB_ROOT) 5 | 6 | import binascii 7 | 8 | import vtrace 9 | import vdb 10 | 11 | import envi 12 | import envi.archs.i386.disasm as dis 13 | from envi.archs.i386 import * 14 | import envi.memory as mem 15 | 16 | 17 | import PE as PE 18 | #import vstruct 19 | 20 | import vtrace.envitools as envitools 21 | import vtrace.snapshot as vs_snap 22 | 23 | import vdb.recon as v_recon 24 | import vdb.recon.sniper as v_sniper 25 | import vdb.stalker as v_stalker 26 | 27 | AddrFmt='L' 28 | debug = False 29 | 30 | # Sample Notifier class 31 | # Prints a statement for each type of event encountered 32 | class CustomNotifier(vtrace.Notifier): 33 | # Event is one of the vtrace.NOTIFY_* things listed under vtrace 34 | 35 | def notify(self, event, trace): 36 | print "Got event: %d from pid %d" % (event, trace.getPid()) 37 | print "PID %d thread(%d) got" % (trace.getPid(), trace.getMeta("ThreadId")) 38 | 39 | # get the details 40 | #details = trace.getMeta('Win32Event') 41 | #print "DETAILS: ", details 42 | 43 | if event == vtrace.NOTIFY_ALL: 44 | print "WTF, how did we get a vtrace.NOTIFY_ALL event?!?!" 45 | 46 | elif event == vtrace.NOTIFY_SIGNAL: 47 | print "vtrace.NOTIFY_SIGNAL" 48 | print "PendingSignal",trace.getMeta("PendingSignal") 49 | print "PendingException",trace.getMeta("PendingException") 50 | if trace.getMeta("Platform") == "Windows": 51 | print repr(trace.getMeta("Win32Event")) 52 | print vdb.getSignal(trace.getMeta("PendingSignal")) 53 | win32 = self.getMeta("Win32Event", None) 54 | if win32: 55 | code = win32["ExceptionCode"] 56 | print "Win32 ExceptCode: ", code 57 | 58 | elif event == vtrace.NOTIFY_BREAK: 59 | print "vtrace.NOTIFY_BREAK", printableEIP(trace) 60 | pass 61 | elif event == vtrace.NOTIFY_SYSCALL: 62 | print "vtrace.NOTIFY_SYSCALL" 63 | elif event == vtrace.NOTIFY_CONTINUE: 64 | print "vtrace.NOTIFY_CONTINUE" 65 | pass 66 | elif event == vtrace.NOTIFY_EXIT: 67 | print "vtrace.NOTIFY_EXIT" 68 | print "ExitCode",trace.getMeta("ExitCode") 69 | elif event == vtrace.NOTIFY_ATTACH: 70 | print "vtrace.NOTIFY_ATTACH" 71 | pass 72 | elif event == vtrace.NOTIFY_DETACH: 73 | print "vtrace.NOTIFY_DETACH" 74 | pass 75 | elif event == vtrace.NOTIFY_LOAD_LIBRARY: 76 | print "vtrace.NOTIFY_LOAD_LIBRARY \t", trace.getMeta('LatestLibrary') 77 | pass 78 | elif event == vtrace.NOTIFY_UNLOAD_LIBRARY: 79 | print "vtrace.NOTIFY_UNLOAD_LIBRARY" 80 | pass 81 | elif event == vtrace.NOTIFY_CREATE_THREAD: 82 | print "vtrace.NOTIFY_CREATE_THREAD \t", trace.getMeta("ThreadId") 83 | pass 84 | elif event == vtrace.NOTIFY_EXIT_THREAD: 85 | print "vtrace.NOTIFY_EXIT_THREAD" 86 | print "ExitThread",trace.getMeta("ExitThread", -1) 87 | pass 88 | elif event == vtrace.NOTIFY_STEP: 89 | print "vtrace.NOTIFY_STEP" 90 | pass 91 | else: 92 | print "vtrace.NOTIFY_WTF_HUH?" 93 | 94 | # Print out the value in EIP as a long 95 | def getEIP(trace): 96 | eip = trace.getRegister(REG_EIP) 97 | return eip 98 | 99 | # Print out the value in EIP as a hex number 100 | def printableEIP(trace): 101 | return hex(getEIP(trace)) 102 | 103 | # Print out the value of ESP as a long 104 | def getESP(trace): 105 | esp = trace.getRegister(REG_ESP) 106 | return esp 107 | 108 | # Print out the value of the memory ESP points to 109 | # if the program is stopped in the appropriate spot 110 | # this is the return value for the function. 111 | def getRET(trace): 112 | esp = getESP(trace) 113 | retaddr = trace.readMemory(esp, 4) 114 | return struct.unpack("I",retaddr)[0] 115 | 116 | # Same as above only in hex 117 | def getPrintableRET(trace): 118 | esp = getESP(trace) 119 | retprt = trace.readMemory(esp, 4) 120 | return hex(struct.unpack("I",retaddr)[0]) 121 | 122 | def getOpCode(trace, eip): 123 | s = trace.readMemory(eip,15) 124 | op1 = trace.makeOpcode(s, 0, eip) 125 | return op1 126 | 127 | def getSnapshot(trace): 128 | # Snapshot still broken when new features are enabled (Stalker) 129 | # might have something to do with the deep copy of the meta tags 130 | return vs_snap.takeSnapshot(trace) 131 | 132 | def snapshotToFile(snap, filename): 133 | f = file(filename, "wb") 134 | f.write(str(snap)) 135 | #pickle.dump(snap, f) 136 | f.close() 137 | 138 | def getStalkerInfo(trace): 139 | print("STALKER BREAKS: ", trace.getMeta("StalkerBreaks")) 140 | print("STALKER HITS: ", trace.getMeta("StalkerHits")) 141 | print("STALKER CODE FLOW: ", trace.getMeta("StalkerCodeFlow")) 142 | 143 | def getReconInfo(trace): 144 | print("RECON HITS: ", trace.getMeta("recon_hits")) 145 | print("RECON QUIET: ", trace.getMeta("recon_quiet")) 146 | print("TRACKER BREAK: ", trace.getMeta("TrackerBreak")) 147 | 148 | # Only returns the address to the first function found 149 | def findFunc(trace, pattern): 150 | pattern = pattern.lower() 151 | libs = trace.getNormalizedLibNames() 152 | libs.sort() 153 | for libname in libs: 154 | for sym in trace.getSymsForFile(libname): 155 | r = repr(sym) 156 | if pattern != None: 157 | if r.lower().find(pattern.lower()) == -1: 158 | continue 159 | print("0x%.8x %s" % (sym.value, r)) 160 | return sym.value 161 | 162 | def setBpOnPattern(trace, pattern): 163 | addr = findFunc(trace, pattern) 164 | bp = vtrace.Breakpoint(addr) 165 | trace.addBreakpoint(bp) 166 | 167 | def printBp(trace): 168 | for bp in trace.getBreakpoints(): 169 | print("%s enabled: %s" % (bp, bp.isEnabled())) 170 | 171 | def getOEP(trace, filepath): 172 | base = None 173 | 174 | libs = trace.getMeta("LibraryPaths") 175 | for k, v in libs.iteritems(): 176 | if filepath in v: 177 | base = k 178 | 179 | if base is None: 180 | p = PE.peFromFileName(filepath) 181 | base = p.IMAGE_NT_HEADERS.OptionalHeader.ImageBase 182 | else: 183 | p = PE.peFromMemoryObject(trace, base) 184 | 185 | ep = p.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint 186 | oep = base + ep 187 | return oep 188 | 189 | # This function will change the input variables so that child process 190 | # starts paused. Then reads the PID of the newly created child process 191 | # and attaches to it 192 | # NOTE: trace object should be at the _1st_ instruction in CreateProcessA 193 | # for this to function. Upon return you will be at OEP for child process 194 | def followCreateProcessA(trace): 195 | dwAddr = trace.getRegister(REG_ESP) 196 | 197 | dwAddr +=4#remove eip 198 | dwAddr +=4#remove lpApplicationName 199 | dwAddr +=4#remove lpCommandLine 200 | dwAddr +=4#remove procattrs 201 | 202 | dwAddr +=4#remove threadattrs 203 | dwAddr +=4#remove inheritHandles 204 | dwCreateFlags=struct.unpack("I",trace.readMemory(dwAddr,4))[0] 205 | dwCreateFlags|=4 206 | dwCreateFlags=struct.pack("I",dwCreateFlags) 207 | try: 208 | trace.writeMemory(dwCreateFlags,dwAddr) 209 | except: 210 | pass 211 | 212 | # Add a breakpoint on the return address from CreateProcessA 213 | # Run to it and then call afterCreateProcessA 214 | # This is so the PID variable is populated. 215 | 216 | esp = trace.getRegister(REG_ESP) 217 | ret = trace.readMemory(esp,4) 218 | ret2 = struct.unpack("I",ret)[0] 219 | bp = vtrace.Breakpoint(None, expression=hex(ret2)) 220 | trace.addBreakpoint(bp) 221 | printBp(trace) 222 | 223 | trace.run() 224 | esp = trace.getRegister(REG_ESP) 225 | 226 | dwAddr = esp 227 | dwAddr -=44#move esp to location of stack from CreateProcessA 228 | dwAddr +=24#move esp to location after some CreateProcessA variables 229 | 230 | dwAddr +=4#remove dwCreationFlags 231 | dwAddr +=4#remove lpEnvironment 232 | 233 | dwAddr +=4#remove lpCurrentDirectory 234 | dwAddr +=4#remove lsStartupInfo 235 | # dwAddr points to lpProcessInformation 236 | #print "dwAddr: ", dwAddr 237 | procid = trace.readMemory(dwAddr, 4) 238 | procid = struct.unpack("I", procid)[0] 239 | procid +=4#remove hProcess 240 | procid +=4#remove hThread 241 | # procid points to dwProcessId 242 | try: 243 | pid = struct.unpack("I", trace.readMemory(procid, 4))[0] 244 | print "ProcID: ", pid 245 | if pid != None: 246 | trace.attach(pid) 247 | print "ADD TRACE: ", trace.getPid() 248 | except: 249 | pass 250 | 251 | return trace 252 | 253 | # Change the permissions on the memory map containing addr 254 | # removing execute permissions. 255 | # Catch the exception in the notifier, change the permissions 256 | # back and continue running the child process with the debugger attached. 257 | # NOTE: Notifier must be enabled before the call to this function. 258 | def nxMemPerm(trace, addr): 259 | memMap = trace.getMemoryMap(addr) 260 | begin = memMap[0] 261 | size = memMap[1] 262 | #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 263 | #print "FROM: ", hex(begin) 264 | #print "SIZE: ", size 265 | 266 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 267 | print "[*] Memory Perm Set to None from: %s size: %s" % (hex(begin), size) 268 | #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 269 | trace.run() 270 | 271 | # Will parse the PE in memory and return the array containing the IAT 272 | # If verbose is true it will also print out the IAT 273 | def printIAT(trace, fileName, verbose=False): 274 | #print "FileName: %s" % fileName 275 | 276 | libs = trace.getMeta("LibraryPaths") 277 | libBase = trace.getMeta("LibraryBases") 278 | #print "Lib Base: %s" % libBase 279 | #print "File Name: %s" % fileName 280 | 281 | base = libBase[fileName.lower()] 282 | 283 | p = PE.peFromMemoryObject(trace, base) 284 | 285 | IMAGE_DIRECTORY_ENTRY_IMPORT =1 # Import Directory 286 | IMAGE_DIRECTORY_ENTRY_IAT =12 # Import Address Table 287 | 288 | idir = p.IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] 289 | poff = p.rvaToOffset(idir.VirtualAddress) 290 | psize = idir.Size 291 | # Once you have VirtualAddress BP on that and you can stop 292 | # the program before any external call. 293 | 294 | p.parseImports() 295 | if verbose == True: 296 | for i in p.imports: 297 | print("Address: %s \tLibrary: %s \tFirstThunk: %s" % (hex(base+i[0]), i[1], i[2])) 298 | return base, p.imports 299 | 300 | # Will parse the PE in memory and return the array containing the IAT 301 | # If verbose is true it will also print out the IAT 302 | def getIATLocation(trace, fileName, verbose=False): 303 | #print "FileName: %s" % fileName 304 | 305 | libs = trace.getMeta("LibraryPaths") 306 | libBase = trace.getMeta("LibraryBases") 307 | #print "Lib Base: %s" % libBase 308 | #print "File Name: %s" % fileName 309 | 310 | base = libBase[fileName.lower()] 311 | 312 | p = PE.peFromMemoryObject(trace, base) 313 | 314 | IMAGE_DIRECTORY_ENTRY_IMPORT =1 # Import Directory 315 | IMAGE_DIRECTORY_ENTRY_IAT =12 # Import Address Table 316 | 317 | idir = p.IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] 318 | poff = p.rvaToOffset(idir.VirtualAddress) 319 | psize = idir.Size 320 | # Once you have VirtualAddress BP on that and you can stop 321 | # the program before any external call. 322 | return base, poff, psize 323 | 324 | # Store the IAT under the meta name 325 | def store_IAT(trace, base, importTable, metaname): 326 | for i in importTable: 327 | #print "[*] \tAddr: %s \tLibrary: %s [*] \tFunction: %s" % (hex(base+i[0]), i[1], i[2]) 328 | 329 | instr = trace.getMeta(metaname) 330 | if instr == None: 331 | trace.setMeta(metaname, {base+i[0]:i[1]+':'+i[2]}) 332 | else: 333 | instr[base+i[0]] = i[1]+':'+i[2] 334 | #instr.append(hex(base+i[0])+':'+i[1]+':'+i[2]) 335 | trace.setMeta(metaname, instr) 336 | 337 | # Call this function from within a notifier to handle breakpoints on IAT 338 | def iat_handler(event, trace): 339 | print "[*] Got event: %d from pid %d" % (event, trace.getPid()) 340 | 341 | if event == vtrace.NOTIFY_SIGNAL: 342 | #print "vtrace.NOTIFY_SIGNAL" 343 | print "[*] PendingSignal",trace.getMeta("PendingSignal") 344 | print "[*] PendingException",trace.getMeta("PendingException") 345 | if trace.getMeta("Platform") == "Windows": 346 | win32event = trace.getMeta("Win32Event") 347 | print "[*] ExceptionAddress: %(ExceptionAddress)x" % win32event 348 | 349 | eip = trace.getRegister(REG_EIP) 350 | print "[*] Bestname: ", trace.getSymByAddr(eip, exact=False) 351 | 352 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 353 | disLen = len(dis) 354 | opcode = trace.readMemory(eip, len(dis)) 355 | 356 | print "%16s: %s" % ("DIS", dis) 357 | print "%16s: %s" % ("OPCODE", repr(opcode)) 358 | 359 | print "%16s: %s" % ("EAX", hex(trace.getRegister(REG_EAX))) 360 | es = trace.getRegisterByName("es") 361 | print "%16s: %s" % ("ES", es) 362 | ds = trace.getRegisterByName("ds") 363 | print "%16s: %s" % ("DS", ds) 364 | cs = trace.getRegisterByName("cs") 365 | print "%16s: %s" % ("CS", cs) 366 | edi = trace.getRegister(REG_EDI) 367 | print "%16s: %s" % ("EDI", hex(edi)) 368 | esi = trace.getRegister(REG_ESI) 369 | print "%16s: %s" % ("ESI", hex(esi)) 370 | esp = trace.getRegister(REG_ESP) 371 | print "%16s: %s" % ("ESP", hex(esp)) 372 | print "%16s: %s" % ("[ESP]", repr(trace.readMemory(esp, 4))) 373 | 374 | ef = trace.getRegisterByName("eflags") 375 | print("%16s: %s" % ("Direction", bool(ef & EFLAGS_DF))) 376 | 377 | #print("%16s: %s" % ("Carry", bool(ef & EFLAGS_CF))) 378 | #print("%16s: %s" % ("Parity", bool(ef & EFLAGS_PF))) 379 | #print("%16s: %s" % ("Adjust", bool(ef & EFLAGS_AF))) 380 | #print("%16s: %s" % ("Zero", bool(ef & EFLAGS_ZF))) 381 | #print("%16s: %s" % ("Sign", bool(ef & EFLAGS_SF))) 382 | #print("%16s: %s" % ("Trap", bool(ef & EFLAGS_TF))) 383 | #print("%16s: %s" % ("Interrupt", bool(ef & EFLAGS_IF))) 384 | #print("%16s: %s" % ("Overflow", bool(ef & EFLAGS_OF))) 385 | 386 | #regs = trace.getRegisters() 387 | #print "REGS: ", regs 388 | #rnames = regs.keys() 389 | #rnames.sort() 390 | 391 | # function takes in just filename not the full path to filename.exe 392 | filepath = trace.getMeta('ExeName') 393 | exeName = filepath.split(".exe")[0] 394 | fileName = exeName.split("\\")[len(exeName.split("\\"))-1] 395 | 396 | if(trace.getMeta('IATLocation') == None): 397 | base, poff, psize = getIATLocation(trace, fileName) 398 | trace.setMeta('IATLocation', {'base':base, 'poff':poff, 'psize':psize}) 399 | else: 400 | iatLoc = trace.getMeta('IATLocation') 401 | base = iatLoc['base'] 402 | poff = iatLoc['poff'] 403 | psize = iatLoc['psize'] 404 | 405 | memMap = trace.getMemoryMap(base+poff) 406 | begin = memMap[0] 407 | size = memMap[1] 408 | 409 | trace.protectMemory(begin, size, envi.memory.MM_RWX) 410 | 411 | # Check the opcode to see if it is a call or a deref call 412 | if (ord(opcode[0]) == 255 and ord(opcode[1]) == 21): 413 | # Increment eip by length of command to get next eip 414 | # then pack it so it will be written to memory correctly 415 | 416 | nextAddr = eip + disLen 417 | pack = struct.pack("I", nextAddr) 418 | 419 | # Get esp register location and sub 4 bytes to simulate push 420 | esp = trace.getRegister(REG_ESP) 421 | popesp = esp - 4 422 | 423 | # write 4 byte next eip to new esp location 424 | # then update esp variable 425 | trace.setRegister(REG_ESP, popesp) 426 | esp = trace.getRegister(REG_ESP) 427 | 428 | # write the return addr to the new esp location 429 | trace.writeMemory(esp, pack) 430 | 431 | # Check the opcode to see if it is a call or a deref call 432 | if (ord(opcode[0]) == 255 and ord(opcode[1]) == 21): 433 | tmp = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 434 | newEip = tmp 435 | 436 | newOpcode = "\xFF\x25" 437 | newOpcode += struct.pack("I", newEip) 438 | 439 | trace.writeMemory(eip, newOpcode) 440 | 441 | eip = trace.getRegister(REG_EIP) 442 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 443 | 444 | # Check for \xff to determine if a deref call 445 | if (ord(opcode[0]) == 255): 446 | #and ord(opcode[1]) == 21) or (ord(opcode[0]) == 255 and ord(opcode[1]) == 37)): 447 | #print "OPCODE: %s" % repr(opcode) 448 | tmp_addr = struct.unpack("I",opcode[len(dis)-4:len(dis)])[0] 449 | 450 | ################################ 451 | # Get the list of imported functions to compare against 452 | instr = trace.getMeta('IATInfo') 453 | 454 | try: 455 | print "TMP_ADDR: %s" % hex(tmp_addr) 456 | a = instr[tmp_addr] 457 | b = a.split(':') 458 | 459 | print "[*] \tLibrary: %s \n[*] \tFunction: %s" % (b[0], b[1]) 460 | 461 | lst = trace.getMeta('IATList') 462 | if lst == None: 463 | trace.setMeta('IATList', [hex(tmp_addr)+':'+b[0]+':'+b[1]]) 464 | else: 465 | lst.append(hex(tmp_addr)+':'+b[0]+':'+b[1]) 466 | trace.setMeta('IATList', lst) 467 | 468 | except: 469 | print "\t\t ********** ISSUE **********" 470 | 471 | # if(i[2] == accept): 472 | # Do something specific to accept 473 | # ****************************** 474 | 475 | 476 | 477 | print "%16s: %s" % ("[*] Opcode[0]", ord(opcode[0])) 478 | 479 | # 15 is movzx esi, word [edi] AND movzx edi, word [ecx] 480 | # 102 is scasd 481 | # 242 is scasb ? 482 | if((ord(opcode[0]) == 102) or (ord(opcode[0]) == 15) or (ord(opcode[0]) == 242)): 483 | print "%16s: %s" % ("[*] PROBLEM OPCODE", "Detected") 484 | try: 485 | test = trace.probeMemory(edi,4, envi.memory.MM_READ) 486 | print "[*] Readable Memory: ", test 487 | if test: 488 | print "%16s: %s" % ("MEM", trace.readMemory(edi, 4)) 489 | 490 | except Exception as e: 491 | print type(e) 492 | print e.args 493 | print e 494 | 495 | print "%16s: %s" % ("Error Reading Mem from", hex(edi)) 496 | 497 | p = trace.getMeta('PendingSignal') 498 | if p!= None: 499 | trace.setMeta('OrigSignal', p) 500 | trace.setMeta('PendingSignal', None) 501 | 502 | #notif = CustomNotifier() 503 | eve = vtrace.NOTIFY_SIGNAL 504 | 505 | trace.deregisterNotifier(eve, notif) 506 | trace.stepi() 507 | 508 | trace.registerNotifier(eve, notif) 509 | 510 | trace.protectMemory(begin, size, envi.memory.MM_NONE) 511 | trace.runAgain(val=True) 512 | print "---------------------------------------------------------" 513 | else: 514 | print "vtrace.NOTIFY_WTF_HUH?", printableEIP(trace) 515 | 516 | # Will decode shellcode in a linear manner 517 | # shellcode must be in the format '\x90\x90\xCC\xCC' 518 | # for the code to function properly 519 | def disasm(trace, shell): 520 | d = dis.i386Disasm() 521 | i = 0 522 | count = 0 523 | while count < len(shell): 524 | try: 525 | op = trace.makeOpcode(shell, offset=i, va=0) 526 | print "%14s:\t %s" %(shell[count:count+op.size].encode('hex'), op) 527 | #print "COUNT: ", count 528 | #print "OP SIZE: ", op.size 529 | i += 1 530 | count += op.size 531 | except: 532 | print "ERROR: ", sys.exc_info()[1] 533 | i += 1 534 | count += 1 535 | continue 536 | 537 | def printInfo(trace): 538 | eip = trace.getRegister(REG_EIP) 539 | 540 | dis = getOpCode(trace, trace.getRegister(REG_EIP)) 541 | disLen = len(dis) 542 | opcode = trace.readMemory(eip, len(dis)) 543 | 544 | es = trace.getRegisterByName("es") 545 | ds = trace.getRegisterByName("ds") 546 | cs = trace.getRegisterByName("cs") 547 | 548 | ef = trace.getRegisterByName("eflags") 549 | 550 | edi = trace.getRegister(REG_EDI) 551 | esi = trace.getRegister(REG_ESI) 552 | esp = trace.getRegister(REG_ESP) 553 | 554 | print "[*] Bestname: ", trace.getSymByAddr(eip, exact=False) 555 | print "%16s: %s" % ("EIP", hex(eip)) 556 | 557 | print "%16s: %s" % ("DIS", dis) 558 | print "%16s: %s" % ("OPCODE", repr(opcode)) 559 | print "%16s: %s" % ("ES", es) 560 | print "%16s: %s" % ("DS", ds) 561 | print "%16s: %s" % ("CS", cs) 562 | print "%16s: %s" % ("EAX", hex(trace.getRegister(REG_EAX))) 563 | print "%16s: %s" % ("EBX", hex(trace.getRegister(REG_EBX))) 564 | print "%16s: %s" % ("ECX", hex(trace.getRegister(REG_ECX))) 565 | print "%16s: %s" % ("EDX", hex(trace.getRegister(REG_EDX))) 566 | 567 | print "%16s: %s" % ("EDI", hex(edi)) 568 | print "%16s: %s" % ("ESI", hex(esi)) 569 | 570 | print "%16s: %s" % ("ESP", hex(esp)) 571 | print "%16s: %s" % ("[ESP]", repr(trace.readMemory(esp, 4))) 572 | 573 | print("%16s: %s" % ("Direction", bool(ef & EFLAGS_DF))) 574 | 575 | 576 | ############################################################ 577 | # Super ghetto, not recommended 578 | def addOpCodeToList(opList): 579 | try: 580 | opList[getEIP(trace)] += 1 581 | except: 582 | opList[getEIP(trace)] = 1 583 | 584 | 585 | 586 | def mainTemplate(argv): 587 | if len(argv) != 2: 588 | # sys.argv[0] is the name of the script 589 | print "Usage: %s " % sys.argv[0] 590 | sys.exit(1) 591 | 592 | # sys.argv[1] is the first argument passed to script 593 | filepath = sys.argv[1] 594 | 595 | load_binary(filepath) 596 | 597 | # if __name__ == "__main__": 598 | # main(sys.argv) 599 | # sys.exit(0) --------------------------------------------------------------------------------