Package vdb :: Package extensions :: Module windows
[hide private]
[frames] | no frames]

Source Code for Module vdb.extensions.windows

   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   
19 -def teb(vdb, line):
20 """ 21 Print out the TEB for the current or specified thread. 22 23 Usage: teb [threadid] 24 """ 25 t = vdb.getTrace() 26 threads = t.getThreads() 27 tid = t.getMeta("ThreadId") 28 if len(line): 29 tid = t.parseExpression(line) 30 taddr = threads.get(tid) 31 if taddr == None: 32 vdb.vprint("Invalid Thread ID: %d" % tid) 33 return 34 teb = t.getStruct("ntdll.TEB", taddr) 35 vdb.vprint(teb.tree(va=taddr, reprmax=32))
36
37 -def peb(vdb, line):
38 """ 39 Print the PEB 40 41 Usage: peb 42 """ 43 t = vdb.getTrace() 44 t.requireAttached() 45 pebaddr = t.getMeta("PEB") 46 peb = t.getStruct("ntdll.PEB", pebaddr) 47 vdb.vprint(peb.tree(pebaddr, reprmax=32))
48
49 -def regkeys(vdb, line):
50 """ 51 Show all the registry keys the target process currently has open. 52 53 Usage: regkeys 54 """ 55 t = vdb.getTrace() 56 t.requireAttached() 57 vdb.vprint("\nOpen Registry Keys:\n") 58 for fd,ftype,fname in t.getFds(): 59 if ftype == vtrace.FD_REGKEY: 60 vdb.vprint("\t%s" % fname) 61 vdb.vprint("")
62
63 -def einfo(vdb, line):
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 #FIXME get extended infoz 101 #FIXME unify with cli thing 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
109 -def seh(vdb, line):
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 #FIXME print out which frame these are in 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
133 -def safeseh(vdb, line):
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 #print name 182 #print p.IMAGE_LOAD_CONFIG 183 vdb.vprint("%16s\t%s" % (name, enabled))
184
185 -def validate_heaps(db):
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 #import traceback 200 #traceback.print_exc() 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
221 -def heaps(vdb, line):
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 # FIXME do this the slow way for now... 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 # Obviously, only check for leaks if they are in use... 352 # FIXME we will need to check the lookaside also... 353 if not chunk.isBusy(): 354 continue 355 addr = chunk.getDataAddress() 356 # FIXME get size and endian from trace 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
371 -def showaslr(vdb, base, libname):
372 t = vdb.getTrace() 373 try: 374 p = PE.peFromMemoryObject(t, base) 375 except Exception, e: 376 vdb.vprint('Error: %s (0x%.8x) %s' % (name, base, e)) 377 return 378 enabled = False 379 c = p.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics 380 if c & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE: 381 enabled = True 382 vdb.vprint("%16s\t%s" % (libname, enabled))
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 # Page align 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 # Skip ones that are already there! 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
522 -def stealth(vdb, line):
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
547 -def gflags(vdb, line):
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
595 -def pe(vdb, line):
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 #-v Show PE version information 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
728 -def bindiff(mem1, mem2):
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 # We found a discrepency 737 if r != i: 738 size = (r-i) 739 ret.append((i,size)) 740 i+=r 741 i+=1 742 return ret
743
744 -def deaslr(vdb, line):
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
760 -def sympath(vdb, line):
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
774 -def stepb(vdb, line):
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 # For now, lets cheat so we get FastStep behavior for free... 790 vdb.do_stepi('') 791 vdb.trace.setMode('BranchStep', orig)
792
793 -def hooks(vdb, line):
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 # Get relocations for skipping 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 # Add the import entries to skip 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 # Check for a relocation covering this... 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
849 -def jit(vdb, line):
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 #wow64path = r'SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug' 876 877 #regkey = _winreg.CreateKey(HKLM, regpath) 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 #_winreg.SetValue(HKLM 892 893 if setval != None: 894 vdb.vprint('Setting JIT: %s' % (setval,)) 895 _winreg.SetValueEx(regkey, 'Debugger', None, REG_SZ, setval)
896
897 -def svclist(vdb, line):
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
917 -def injectso(vdb, line):
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 }
934 -def uac(db, line):
935 ''' 936 Display the current UAC status of the target process. 937 (User Account Control) 938 939 Usage: uac 940 ''' 941 t = db.trace 942 u = t._getUacStatus() 943 db.vprint('UAC Status: %s' % token_elevation_types.get(u))
944
945 -def hookiat(db, line):
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 # The necissary module extension function
977 -def vdbExtension(db, trace):
978 db.registerCmdExtension(hookiat) 979 db.registerCmdExtension(pe) 980 db.registerCmdExtension(peb) 981 db.registerCmdExtension(einfo) 982 db.registerCmdExtension(heaps) 983 db.registerCmdExtension(regkeys) 984 db.registerCmdExtension(seh) 985 db.registerCmdExtension(safeseh) 986 db.registerCmdExtension(teb) 987 db.registerCmdExtension(pagewatch) 988 db.registerCmdExtension(stealth) 989 db.registerCmdExtension(aslr) 990 db.registerCmdExtension(hooks) 991 db.registerCmdExtension(gflags) 992 #db.registerCmdExtension(deaslr) 993 db.registerCmdExtension(sympath) 994 db.registerCmdExtension(jit) 995 db.registerCmdExtension(svclist) 996 #db.registerCmdExtension(stepb) 997 db.registerCmdExtension(injectso) 998 db.registerCmdExtension(uac)
999