1 import os
2 import sys
3 import getopt
4
5 import vtrace
6 import vtrace.tools.win32heap as win32heap
7 import vtrace.tools.win32aslr as win32_aslr
8 import vtrace.tools.iathook as vt_iathook
9 import vtrace.tools.win32stealth as win32_stealth
10 import vtrace.util as v_util
11
12 import envi.memory as e_mem
13 import envi.cli as e_cli
14 import envi.bits as e_bits
15
16 import PE
17 import vstruct.defs.pe as vs_pe
18
36
48
62
64 """
65 Show all the current exception information.
66
67 -P Toggle the "PendingSignal" meta key which controls
68 delivery (or handling) of the current exception.
69
70 Usage: einfo [options]
71 """
72 argv = e_cli.splitargs(line)
73 t = vdb.getTrace()
74
75 try:
76 opts,args = getopt.getopt(argv, 'P')
77 except Exception, e:
78 return vdb.do_help('einfo')
79
80 for opt,optarg in opts:
81 if opt == '-P':
82 p = t.getMeta('PendingSignal')
83 if p != None:
84 t.setMeta('OrigSignal', p)
85 t.setMeta('PendingSignal', None)
86 else:
87 newp = t.getMeta('OrigSignal', None)
88 t.setMeta('PendingSignal', newp)
89
90 exc = t.getMeta("Win32Event", None)
91 if exc == None:
92 vdb.vprint("No Exception Information Found")
93 ecode = exc.get("ExceptionCode", 0)
94 eaddr = exc.get("ExceptionAddress",0)
95 chance = 2
96 if exc.get("FirstChance", False):
97 chance = 1
98
99 einfo = exc.get("ExceptionInformation", [])
100
101
102 vdb.vprint("Win32 Exception 0x%.8x at 0x%.8x (%d chance)" % (ecode, eaddr, chance))
103 vdb.vprint("Exception Information: %s" % " ".join([hex(i) for i in einfo]))
104 dbool = True
105 if t.getCurrentSignal() == None:
106 dbool = False
107 vdb.vprint('Deliver Exception: %s' % dbool)
108
110 """
111 Walk and print the SEH chain for the current (or specified) thread.
112
113 Usage: seh [threadid]
114 """
115 t = vdb.getTrace()
116 if len(line) == 0:
117 tid = t.getMeta("ThreadId")
118 else:
119 tid = int(line)
120 tinfo = t.getThreads().get(tid, None)
121 if tinfo == None:
122 vdb.vprint("Unknown Thread Id: %d" % tid)
123 return
124 teb = t.getStruct("ntdll.TEB", tinfo)
125 addr = long(teb.NtTib.ExceptionList)
126 vdb.vprint("REG HANDLER")
127 while addr != 0xffffffff:
128
129 er = t.getStruct("ntdll.EXCEPTION_REGISTRATION_RECORD", addr)
130 vdb.vprint("0x%.8x 0x%.8x" % (addr, er.Handler))
131 addr = long(er.Next)
132
134 """
135 Show the SafeSEH status of all the loaded DLLs or list the
136 handlers for a particular dll by normalized name.
137
138 Usage: safeseh [libname]
139 """
140 t = vdb.getTrace()
141 libs = t.getMeta("LibraryBases")
142 if len(line):
143 base = libs.get(line)
144 if base == None:
145 vdb.vprint("Unknown library: %s" % line)
146 return
147
148 vdb.vprint("%s:" % line)
149
150 try:
151 p = PE.peFromMemoryObject(t, base)
152 except Exception, e:
153 vdb.vprint('Error: %s (0x%.8x) %s' % (line, base, e))
154 return
155
156 if p.IMAGE_LOAD_CONFIG != None:
157 va = int(p.IMAGE_LOAD_CONFIG.SEHandlerTable)
158 if va != 0:
159 count = int(p.IMAGE_LOAD_CONFIG.SEHandlerCount)
160 for h in t.readMemoryFormat(va, "<%dL" % count):
161 vdb.vprint("\t0x%.8x %s" % (base+h, vdb.reprPointer(base+h)))
162 return
163 vdb.vprint("None...")
164
165 else:
166 lnames = libs.keys()
167 lnames.sort()
168 for name in lnames:
169 base = libs.get(name)
170 try:
171 p = PE.peFromMemoryObject(t, base)
172 except Exception, e:
173 vdb.vprint('Error: %s (0x%.8x) %s' % (name, base, e))
174 continue
175
176 enabled = False
177 if p.IMAGE_LOAD_CONFIG != None:
178 va = int(p.IMAGE_LOAD_CONFIG.SEHandlerTable)
179 if va != 0:
180 enabled = True
181
182
183 vdb.vprint("%16s\t%s" % (name, enabled))
184
186 """
187 A simple routine that works like the built in windows
188 heap checkers to show where blocks and/or freelist
189 is potentially dorked.
190 """
191 trace = db.getTrace()
192 db.vprint("Validating:")
193 for heap in win32heap.getHeaps(trace):
194 db.vprint("%s: 0x%.8x" % ("heap".rjust(9), heap.address))
195
196 try:
197 f = heap.getFreeLists()
198 except Exception, e:
199
200
201 db.vprint("%s: %s" % (e.__class__.__name__,e))
202
203 for seg in heap.getSegments():
204 db.vprint("%s: 0x%.8x" % ("segment".rjust(9),seg.address))
205 try:
206 blist = seg.getChunks()
207 for i,chunk in enumerate(blist):
208 if i == 0:
209 continue
210 if heap._win7_heap:
211 continue
212 pchunk = blist[i-1]
213 if chunk.chunk.PreviousSize != pchunk.chunk.Size:
214 db.vprint('Corruption! (block at 0x%.8x (size: %d) block at 0x%.8x (prevsize: %d)' %
215 (pchunk.address, pchunk.chunk.Size, chunk.address, chunk.chunk.PreviousSize))
216 break
217
218 except Exception, e:
219 db.vprint("%s: %s" % (e.__class__.__name__,e))
220
222 """
223 Show Win32 Heap Information.
224
225 Usage: heaps [-F <heapaddr>] [-C <address>] [-L <segmentaddr>]
226 -F <heapaddr> print the freelist for the heap
227 -C <address> Find and print the heap chunk containing <address>
228 -S <segmentaddr> Print the chunks for the given heap segment
229 -L <heapaddr> Print the look aside list for the given heap
230 -V Validate the heaps (check next/prev sizes and free list)
231 -l <heapaddr> Leak detection (list probable leaked chunks)
232 -U <heapaddr> Show un-commited ranges for the specified heap
233 (no options lists heaps and segments)
234 """
235 t = vdb.getTrace()
236 t.requireAttached()
237
238 if t.getMeta('Architecture') == 'amd64':
239 vdb.vprint("WARNING: not all 64bit heap stuff works quite right yet!")
240
241 argv = e_cli.splitargs(line)
242 freelist_heap = None
243 chunkfind_addr = None
244 chunklist_seg = None
245 lookaside_heap = None
246 leakfind_heap = None
247 uncommit_heap = None
248 try:
249 opts,args = getopt.getopt(argv, "F:C:S:L:l:U:V")
250 except Exception, e:
251 return vdb.do_help('heaps')
252
253 for opt,optarg in opts:
254 if opt == "-F":
255 freelist_heap = t.parseExpression(optarg)
256 elif opt == "-C":
257 chunkfind_addr = t.parseExpression(optarg)
258 elif opt == "-L":
259 lookaside_heap = t.parseExpression(optarg)
260 elif opt == "-S":
261 chunklist_seg = t.parseExpression(optarg)
262 elif opt == "-V":
263 return validate_heaps(vdb)
264 elif opt == "-l":
265 leakfind_heap = t.parseExpression(optarg)
266 elif opt == '-U':
267 uncommit_heap = t.parseExpression(optarg)
268
269 if lookaside_heap != None:
270 haddrs = [h.address for h in win32heap.getHeaps(t)]
271 if lookaside_heap not in haddrs:
272 vdb.vprint("0x%.8x is NOT a valid heap!" % lookaside_heap)
273 return
274
275 heap = win32heap.Win32Heap(t, lookaside_heap)
276 vdb.vprint('[Index] [Chunks]')
277 for i,l in enumerate(heap.getLookAsideLists()):
278 vdb.vprint("[%d]" % i)
279 for c in l:
280 vdb.vprint(" %s" % (repr(c)))
281
282 elif uncommit_heap != None:
283
284 haddrs = [h.address for h in win32heap.getHeaps(t)]
285 if uncommit_heap not in haddrs:
286 vdb.vprint("0x%.8x is NOT a valid heap!" % uncommit_heap)
287 return
288
289 heap = win32heap.Win32Heap(t, uncommit_heap)
290 ucrdict = heap.getUCRDict()
291 addrs = ucrdict.keys()
292 addrs.sort()
293 if len(addrs) == 0:
294 vdb.vprint('Heap 0x%.8x has 0 uncommited-ranges!' % uncommit_heap)
295 return
296
297 vdb.vprint('Uncommited ranges for heap: 0x%.8x' % uncommit_heap)
298 for ucraddr in addrs:
299 size = ucrdict.get(ucraddr)
300 vdb.vprint('0x%.8x (%d)' % (ucraddr, size))
301
302 return
303
304 elif freelist_heap != None:
305 haddrs = [h.address for h in win32heap.getHeaps(t)]
306 if freelist_heap not in haddrs:
307 vdb.vprint("0x%.8x is NOT a valid heap!" % freelist_heap)
308 return
309
310 heap = win32heap.Win32Heap(t, freelist_heap)
311 for i,l in enumerate(heap.getFreeLists()):
312 if len(l):
313 vdb.vprint("Freelist Index: %d" % i)
314 for c in l:
315 vdb.vprint(" %s" % repr(c))
316
317 elif chunkfind_addr != None:
318 heap,seg,chunk = win32heap.getHeapSegChunk(t, chunkfind_addr)
319 vdb.vprint("Address 0x%.8x found in:" % (chunkfind_addr,))
320 vdb.vprint("Heap: 0x%.8x" % (heap.address))
321 vdb.vprint("Segment: 0x%.8x" % (seg.address))
322 vdb.vprint("Chunk: 0x%.8x (%d) FLAGS: %s" % (chunk.address, len(chunk),chunk.reprFlags()))
323
324 elif chunklist_seg != None:
325
326 for heap in win32heap.getHeaps(t):
327 for seg in heap.getSegments():
328 if chunklist_seg == seg.address:
329 vdb.vprint("Chunks for segment at 0x%.8x (X == in use)" % chunklist_seg)
330 for chunk in seg.getChunks():
331 c = " "
332 if chunk.isBusy():
333 c = "X"
334 vdb.vprint("0x%.8x %s (%d)" % (chunk.address,c,len(chunk)))
335 return
336
337 vdb.vprint("Segment 0x%.8x not found!" % chunklist_seg)
338
339 elif leakfind_heap != None:
340
341 haddrs = [h.address for h in win32heap.getHeaps(t)]
342 if leakfind_heap not in haddrs:
343 vdb.vprint("0x%.8x is NOT a valid heap!" % leakfind_heap)
344 return
345
346 h = win32heap.Win32Heap(t, leakfind_heap)
347 for seg in h.getSegments():
348 for chunk in seg.getChunks():
349 if chunk.address == seg.address:
350 continue
351
352
353 if not chunk.isBusy():
354 continue
355 addr = chunk.getDataAddress()
356
357 pat = e_bits.buildbytes(addr, 4)
358 l = t.searchMemory(pat)
359 if len(l) == 0:
360 vdb.vprint("0x%.8x may be leaked!" % addr)
361
362 else:
363 vdb.vprint("Heap\t\tSegment")
364 for heap in win32heap.getHeaps(t):
365 flags = " ".join(heap.getFlagNames())
366 for s in heap.getSegments():
367 vdb.vprint("0x%.8x\t0x%.8x\t%s" % (heap.address, s.address, flags))
368
369 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040
370
383
384 -def aslr(vdb, line):
385 """
386 Determine which PE's in the current process address space
387 support Vista's ASLR implementation by the presence of the
388 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE (0x0040) bit in the
389 DllCharacteristics field of the PE header.
390
391 Usage: aslr [libname]
392 """
393 t = vdb.getTrace()
394 libs = t.getMeta("LibraryBases")
395 if line:
396 base = libs.get(line)
397 if base == None:
398 vdb.vprint("Unknown library: %s" % line)
399 return
400 showaslr(vdb, base, line)
401 else:
402 lnames = libs.keys()
403 lnames.sort()
404 for name in lnames:
405 base = libs.get(name)
406 showaslr(vdb, base, name)
407
408 -def _printPageHits(vdb, hits, unique=False):
409 vdb.vprint('[ eip ] [ mem addr ] [ access ]')
410 if unique:
411 newhits = []
412 [newhits.append(h) for h in hits if not newhits.count(h)]
413 hits = newhits
414
415 for eip,addr,perm in hits:
416 vdb.vprint("0x%.8x 0x%.8x %s" % (eip,addr,e_mem.getPermName(perm)))
417
418 -def pagewatch(vdb, line):
419 """
420 Enable write access watching on a given memory page. This works
421 by setting the page to read-only and then specially handling the
422 access violations as though they were hardware Watchpoints.
423
424 Usage: pagewatch [options] [<addr_expression>]
425 -C - Clear the current pagewatch log
426 -F - Toggle auto-continue behavior (run and record vs. stop on hit)
427 -L - List the current hits from the pagewatch log
428 -M - Add page watches to the entire memory map from addr_expression
429 -R - Use to enable *read* watching while adding a page watch
430 -S <addr> - Show touches to the specified address
431 -P <addr> - Show memory touched by specifed program counter (eip)
432 -u - When listing, show only *unique* entries
433 """
434 argv = e_cli.splitargs(line)
435 try:
436 opts,args = getopt.getopt(argv, "CFLMP:RS:u")
437 except Exception, e:
438 return vdb.do_help('pagewatch')
439
440 if vdb.trace.getMeta('pagewatch') == None:
441 vdb.trace.setMeta('pagewatch', [])
442
443 if vdb.trace.getMeta('pagerun') == None:
444 vdb.trace.setMeta('pagerun', False)
445
446 domap = False
447 unique = False
448 watchread = False
449 for opt,optarg in opts:
450
451 if opt == "-C":
452 vdb.trace.setMeta("pagewatch", [])
453 vdb.vprint("Pagewatch log cleared")
454 return
455
456 elif opt == '-F':
457 pr = vdb.trace.getMeta('pagerun', False)
458 pr = not pr
459 vdb.trace.setMeta('pagerun', pr)
460 vdb.vprint('Pagewatch Auto Continue: %s' % pr)
461 return
462
463 elif opt == "-L":
464 hits = vdb.trace.getMeta('pagewatch', [])
465 _printPageHits(vdb, hits, unique=unique)
466 return
467
468 elif opt == "-M":
469 domap = True
470
471 elif opt == '-R':
472 watchread = True
473
474 elif opt == "-S":
475 saddr = vdb.trace.parseExpression(optarg)
476 hits = vdb.trace.getMeta("pagewatch")
477 if hits == None:
478 vdb.vprint("No pagewatch log!")
479 return
480 hits = [ h for h in hits if h[1] == saddr ]
481 _printPageHits(vdb, hits, unique=unique)
482 return
483
484 elif opt == "-P":
485 saddr = vdb.trace.parseExpression(optarg)
486 hits = vdb.trace.getMeta("pagewatch")
487 if hits == None:
488 vdb.vprint("No pagewatch log!")
489 return
490
491 hits = [ h for h in hits if h[0] == saddr ]
492 _printPageHits(vdb, hits, unique=unique)
493 return
494
495 elif opt == '-u':
496 unique = True
497
498 if len(args) == 0:
499 return vdb.do_help('pagewatch')
500
501 baseaddr = vdb.trace.parseExpression(args[0])
502
503 baseaddr = baseaddr & 0xfffff000
504 maxaddr = baseaddr + 4096
505
506 map = vdb.trace.getMemoryMap(baseaddr)
507 if map == None:
508 raise Exception("Invalid memory map address 0x%.8x" % baseaddr)
509
510 if domap:
511 baseaddr = map[0]
512 maxaddr = baseaddr + map[1]
513
514 bpset = vdb.trace.breakpoints
515 while baseaddr < maxaddr:
516
517 if not bpset.get(baseaddr):
518 wp = vtrace.PageWatchpoint(baseaddr, size=4096, watchread=watchread)
519 wpid = vdb.trace.addBreakpoint(wp)
520 baseaddr += 4096
521
523 """
524 Enable basic debugger stealth. This has the following effects:
525
526 Change PEB to show BeingDebugged == 0
527 Special breakpoint on CheckRemoteDebuggerPresent
528
529 WARNING:
530 break/sendBreak() behave VERY strange with this because the
531 kernel aparently doesn't think he needs to post the exception
532 to the debugger?
533 """
534 if vdb.trace.getMeta("Win32Stealth") != None:
535 win32_stealth.unstealthify(vdb.trace)
536 vdb.vprint("Stealth disabled")
537 else:
538 win32_stealth.stealthify(vdb.trace)
539 vdb.vprint("Stealth enabled")
540
541
542 gflag_stuff = [
543 ('loader_snaps', 'ntdll.ShowSnaps', '<B', 0, 1),
544 ('loader_debug', 'ntdll.LdrpDebugFlags', '<I', 0, 0xffffffff),
545 ]
546
548 '''
549 Support a subset of gflags like behavior on windows. This enables
550 features *exclusively* by direct process manipulation and does NOT
551 set any registry settings or persist across processes...
552
553 Usage: gflags [toggle_type]
554
555 NOTE: Most of these options require symbols!
556 '''
557 argv = e_cli.splitargs(line)
558
559 optnames = [ x[0] for x in gflag_stuff ]
560
561 for opt in argv:
562
563 if opt not in optnames:
564 vdb.vprint('Unknown/Unsupported Option: %s' % opt)
565 continue
566
567 for hname, symname, fmt, offval, onval in gflag_stuff:
568 if opt == hname:
569 try:
570 addr = vdb.trace.parseExpression(symname)
571 cur = vdb.trace.readMemoryFormat(addr, fmt)[0]
572 if cur == offval:
573 newval = onval
574 else:
575 newval = offval
576 vdb.trace.writeMemoryFormat(addr, fmt, newval)
577 except Exception, e:
578 vdb.vprint('Symbol Failure: %s' % symname)
579 break
580
581 for hname, symname, fmt, offval, onval in gflag_stuff:
582 status = 'Unknown'
583 try:
584 addr = vdb.trace.parseExpression(symname)
585 val = vdb.trace.readMemoryFormat(addr, fmt)[0]
586 if val == offval:
587 status = 'Off'
588 elif val == onval:
589 status = 'On'
590 except Exception, e:
591 pass
592 vdb.vprint('%s : %s' % (hname.rjust(20), status))
593
594
596 """
597 Show extended info about loaded PE binaries.
598
599 Usage: pe [opts] [<libname>...]
600 -I Show PE import files.
601 -m Toggle inmem/ondisk behavior (directly mapped DLLs)
602 -N Show full NT header
603 -t Show PE timestamp information
604 -E Show PE exports
605 -S Show PE sections
606 -v Show FileVersion from VS_VERSIONINFO
607 -V Show all keys from VS_VERSIONINFO
608
609 NOTE: "libname" may be a vtrace expression:
610
611 Examples:
612
613 # Show the imports from a PE loaded at 0x777c0000
614 pe -I 0x777c0000
615
616 # Show the exports from advapi32.dll
617 pe -E advapi32
618
619 # Show the build timestamp of the PE pointed to by a register
620 pe -t esi+10
621
622 """
623
624 argv = e_cli.splitargs(line)
625 try:
626 opts,args = getopt.getopt(argv, "EImNStvV")
627 except Exception, e:
628 return vdb.do_help('pe')
629
630 inmem = True
631
632 showsecs = False
633 showvers = False
634 showtime = False
635 showimps = False
636 shownthd = False
637 showexps = False
638 showvsin = False
639 for opt,optarg in opts:
640 if opt == '-I':
641 showimps = True
642 elif opt == '-t':
643 showtime = True
644 elif opt == '-v':
645 showvers = True
646 elif opt == '-V':
647 showvsin = True
648 elif opt == '-N':
649 shownthd = True
650 elif opt == '-m':
651 inmem = False
652 elif opt == '-S':
653 showsecs = True
654 elif opt == '-E':
655 showexps = True
656
657 t = vdb.trace
658 bases = t.getMeta("LibraryBases")
659 paths = t.getMeta("LibraryPaths")
660
661 names = args
662 if len(names) == 0:
663 names = t.getNormalizedLibNames()
664
665 names.sort()
666 names = e_cli.columnstr(names)
667 for libname in names:
668 base = bases.get(libname.strip(), None)
669 if base == None:
670 base = vdb.trace.parseExpression(libname)
671 path = paths.get(base, "unknown")
672
673 try:
674 pobj = PE.peFromMemoryObject(t, base)
675 except Exception, e:
676 vdb.vprint('Error: %s (0x%.8x) %s' % (libname, base, e))
677 continue
678
679 if showimps:
680 ldeps = {}
681 try:
682 for rva,lname,fname in pobj.getImports():
683 ldeps[lname.lower()] = True
684 lnames = ldeps.keys()
685 lnames.sort()
686 vdb.vprint('0x%.8x - %.30s %s' % (base, libname, ' '.join(lnames)))
687 except Exception, e:
688 vdb.vprint('Import Parser Error On %s: %s' % (libname, e))
689
690 elif showvers:
691 version = 'Unknown!'
692 vs = pobj.getVS_VERSIONINFO()
693 if vs != None:
694 version = vs.getVersionValue('FileVersion')
695 vdb.vprint('%s: %s' % (libname.rjust(30),version))
696
697 elif showvsin:
698 vs = pobj.getVS_VERSIONINFO()
699 vdb.vprint('==== %s' % libname)
700 if vs == None:
701 vdb.vprint('no VS_VERSIONINFO...')
702 else:
703 vskeys = vs.getVersionKeys()
704 vskeys.sort()
705 for vskey in vskeys:
706 vsval = vs.getVersionValue(vskey)
707 vdb.vprint('%s: %s' % (vskey.rjust(20), vsval[:50]))
708
709 elif showtime:
710 tstamp = pobj.IMAGE_NT_HEADERS.FileHeader.TimeDateStamp
711 vdb.vprint('0x%.8x - %.30s 0x%.8x' % (base, libname, tstamp))
712
713 elif shownthd:
714 t = pobj.IMAGE_NT_HEADERS.tree(reprmax=32)
715 vdb.vprint(t)
716
717 elif showsecs:
718 for sec in pobj.getSections():
719 vdb.vprint(sec.tree(reprmax=32))
720
721 elif showexps:
722 vdb.vprint('[Ord] [Address] [Name]')
723 for fva, ord, name in pobj.getExports():
724 vdb.vprint('%.4d 0x%.8x %s' % (ord, fva, name))
725 else:
726 vdb.vprint('0x%.8x - %.30s %s' % (base, libname, path))
727
729 ret = []
730 i = 0
731 imax = len(mem1)
732 while i < imax:
733 r = i
734 while mem1[r] != mem2[r] and r < imax:
735 r += 1
736
737 if r != i:
738 size = (r-i)
739 ret.append((i,size))
740 i+=r
741 i+=1
742 return ret
743
745 '''
746 Rebase the specified address expression as though the origin
747 library had gotten it's suggested base address rather than
748 being ASLR'd.
749
750 Usage: deaslr <addr_expr>
751 '''
752 if len(line) == 0:
753 return vdb.do_help('deaslr')
754
755 addr = vdb.trace.parseExpression(line)
756 newaddr = win32_aslr.deAslr(vdb.trace, addr)
757
758 vdb.vprint('aslr: 0x%.8x deaslr: 0x%.8x' % (addr, newaddr))
759
761 '''
762 Set the symbol path for the tracer. This will currently only
763 effect *subsequent* library loads!
764
765 Usage: sympath <new_path>
766 '''
767 if len(line):
768 vdb.trace.setMeta('NtSymbolPath', line)
769 sympath = vdb.trace.getMeta('NtSymbolPath')
770 if sympath == None:
771 sympath = os.getenv('_NT_SYMBOL_PATH')
772 vdb.vprint('Current Symbol Path: %s' % sympath)
773
775 '''
776 Use the extended intel hardware support to step to the next branch
777 target.
778
779 Usage: stepb
780
781 NOTE: This will *not* work inside VMware / VirtualBox. Other hypervisors
782 may vary... (it will simply single step)
783 '''
784 if len(line):
785 vdb.do_help('stepb')
786
787 orig = vdb.trace.getMode('BranchStep')
788 vdb.trace.setMode('BranchStep', True)
789
790 vdb.do_stepi('')
791 vdb.trace.setMode('BranchStep', orig)
792
794 '''
795 Check the executable regions of the target process for any
796 hooks by comparing against the PE on disk. This will
797 account for relocations and import entries.
798 '''
799 t = vdb.getTrace()
800 bases = t.getMeta("LibraryBases")
801 paths = t.getMeta("LibraryPaths")
802 found = False
803 for bname in bases.keys():
804 base = bases.get(bname)
805 fpath = paths.get(base)
806 pobj = PE.PE(file(fpath,'rb'))
807 filebase = pobj.IMAGE_NT_HEADERS.OptionalHeader.ImageBase
808
809 skips = {}
810
811 r = (0,1,2,3)
812 for relrva, reltype in pobj.getRelocations():
813 for i in r:
814 skips[base+relrva+i] = True
815
816 for iva,libname,name in pobj.getImports():
817 for i in r:
818 skips[base+iva+i] = True
819
820 for sec in pobj.getSections():
821 if sec.Characteristics & PE.IMAGE_SCN_MEM_EXECUTE:
822 size = sec.VirtualSize
823 va = base + sec.VirtualAddress
824 fileva = filebase + sec.VirtualAddress
825 filebytes = pobj.readAtRva(sec.VirtualAddress, sec.VirtualSize)
826 procbytes = t.readMemory(va, size)
827 for off,size in bindiff(filebytes, procbytes):
828 difva = va + off
829 fdifva = fileva + off
830
831 if skips.get(difva):
832 continue
833 found = True
834 dmem = procbytes[off:off+size].encode('hex')[:10]
835 dfil = filebytes[off:off+size].encode('hex')[:10]
836
837 vdb.canvas.addVaText('0x%.8x' % difva, difva)
838 vdb.canvas.addText(' (0x%.8x) (%d)' % (fdifva,size))
839 vdb.canvas.addText(' mem: %s file: %s ' % (dmem, dfil))
840
841 sym = vdb.symobj.getSymByAddr(difva, exact=False)
842 if sym != None:
843 vdb.canvas.addText(' ')
844 vdb.canvas.addVaText('%s + %d' % (repr(sym),difva-long(sym)), difva)
845 vdb.canvas.addText('\n')
846
847 if not found: vdb.canvas.addText('No Hooks Found!\n')
848
850 '''
851 Enable/Disable the current VDB location as the current Just-In-Time
852 debugger for windows applications.
853
854 Usage: jitenable [-D]
855 -E Enable VDB JIT debugging
856 -D Disable JIT debugging
857 '''
858 argv = e_cli.splitargs(line)
859 try:
860 opts,args = getopt.getopt(argv, "ED")
861 except Exception, e:
862 return vdb.do_help('jit')
863
864 try:
865 import _winreg
866 except Exception, e:
867 vdb.vprint('Error Importing _winreg: %s' % e)
868 return
869
870 HKLM = _winreg.HKEY_LOCAL_MACHINE
871 HKCU = _winreg.HKEY_CURRENT_USER
872 REG_SZ = _winreg.REG_SZ
873
874 regpath = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug'
875
876
877
878 regkey = _winreg.CreateKey(HKLM, regpath)
879
880 vdb.vprint('JIT Currently: %s' % _winreg.QueryValueEx(regkey, 'Debugger')[0])
881
882 setval = None
883 for opt,optarg in opts:
884
885 if opt == '-D':
886 setval = ''
887
888 elif opt == '-E':
889 vdbpath = os.path.abspath(sys.argv[0])
890 setval = '%s %s -r -p %%ld -e %%Id' % (sys.executable, vdbpath)
891
892
893 if setval != None:
894 vdb.vprint('Setting JIT: %s' % (setval,))
895 _winreg.SetValueEx(regkey, 'Debugger', None, REG_SZ, setval)
896
898 '''
899 List the running service names and pids.
900
901 Usage: svclist
902 '''
903 cols = []
904 pids = []
905 names = []
906 descrs = []
907 for pid, name, descr in vdb.trace._getSvcList():
908 pids.append('%d' % pid)
909 names.append(name)
910 descrs.append(descr)
911
912 names = e_cli.columnstr(names)
913
914 for i in xrange(len(pids)):
915 vdb.vprint('%8s %s %s' % (pids[i], names[i], descrs[i]))
916
918 '''
919 Inject a shared object (DLL) into the target process.
920
921 Usage: injectso <dllname>
922 '''
923 if not line:
924 return vdb.do_help('injectso')
925 t = vdb.trace
926 t.injectso(line)
927
928 token_elevation_types = {
929 0: 'UAC Not Present',
930 1: 'Default Elevation',
931 2: 'Elevated',
932 3: 'Low',
933 }
944
946 '''
947 Hook the specified IAT entries by munging a pointer and emulating
948 "breakpoint" like behavior on the resultant memory access errors. Basically,
949 break on import call...
950
951 Usage: hookiat <libname> [ <implibname> [ <impfuncname> ] ]
952
953 Example:
954 hookiat calc
955 hookiat calc kernel32
956 hookiat calc kernel32 LoadLibraryA
957
958 NOTE: Once added, you may use "bp" and commands like "bpedit" to modify,
959 remove, or add code to "iat hooks"
960 '''
961 argv = e_cli.splitargs(line)
962 arglen = len(argv)
963 if arglen < 1:
964 return db.do_help('hookiat')
965 if arglen > 3:
966 return db.do_help('hookiat')
967
968 db.vprint('Adding IAT Hooks (use bp/bpedit cmds to review/modify...)')
969 hooks = vt_iathook.hookIat(db.trace, *argv)
970 if len(hooks):
971 db.vprint('[ bpid ] [ IAT Name ]')
972 for iatname, bpid in hooks:
973 db.vprint('[%6d] %s' % (bpid, iatname))
974 db.vprint('Added %d hooks.' % len(hooks))
975
976
999