Package Libs :: Module immlib
[hide private]
[frames] | no frames]

Source Code for Module Libs.immlib

   1  #!/usr/bin/env python 
   2  """ 
   3      Immunity Debugger API for python 
   4   
   5      (c) Immunity, Inc. 2004-2007 
   6   
   7   
   8      U{Immunity Inc.<http://www.immunityinc.com>} Debugger API for python 
   9   
  10   
  11      """ 
  12   
  13  __VERSION__ = '1.3' 
  14   
  15   
  16  import debugger 
  17  import immutils 
  18  import string 
  19  import time 
  20  import struct 
  21  import pickle 
  22  import cPickle 
  23  import libheap 
  24   
  25  from libhook    import * 
  26  from libevent   import * 
  27  from debugtypes import * 
  28  from libanalyze import * 
  29  from librecognition import FunctionRecognition 
  30  from libcontrolflow import ControlFlowAnalysis 
  31   
  32  # CONSTANT 
  33  BpKeys        =  {"VK_F2": 0x71, "VK_F4" : 0x73} 
  34  BpFlags       = {"TY_STOPAN": 0x80L, "TY_SET": 0x100L, "TY_ACTIVE": 0x200L, "TY_DISABLED":0x400,\ 
  35                   "TY_ONESHOT": 0x800L, "TY_TEMP":0x1000L, "TY_KEEPCODE":0x2000L, "TY_KEEPCOND": 0x4000L,\ 
  36                   "TY_NOUPDATE":0x8000, "TY_RTRACE": 0x10000} 
  37   
  38  # Hardware breakpoint type flags 
  39   
  40  HB_FREE=0      # Breakpoint is not used 
  41  HB_CODE=1      # Active on command execution 
  42  HB_ACCESS=2    # Active on read/write access 
  43  HB_WRITE=3     # Active on write access 
  44  HB_IO=4        # Active on port I/O 
  45  HB_ONESHOT=5   # One-shot on command execution 
  46  HB_STOPAN=6    # One-shot on command and stop 
  47  HB_TEMP=7      # Temporary on command execution 
  48   
  49  DebugerStatus = { "NONE":0, "STOPPED":1, "EVENT":2, "RUNNING": 3, "FINISHED":4, "CLOSING":5 } 
  50   
  51  Register      = { "EAX" : 0 , "ECX" : 1, "EDX": 2, "EBX": 3, "ESP": 4, "EBP": 5, "ESI": 6, "EDI": 7, "EIP":8} 
  52   
  53  PageFlags     = {0x1 : "   ",0x2: "R  ", 0x4:"RW ", 0x8: "RW  COW", 0x10: "  E",\ 
  54                   0x20: "R E", 0x40: "RWE", 0x80: "RWE  COW"} 
  55   
  56  ImmFonts      =   {"fixed": 0, "terminal6": 1, "fixedsys":2, "courier":3, "lucida":4, "font5": 5,\ 
  57                     "font6": 6, "font7":7, "main": 8, "sys": 9, "info": 10} 
  58   
  59   
  60   
  61  BpMemFlags    = {"R": 0x1, "W":0x2, "S":0x1000L} 
  62   
  63  MemoryProtection = { "PAGE_EXECUTE" :0x10, "PAGE_EXECUTE_READ" :0x20 , "PAGE_EXECUTE_READWRITE": 0x40,\ 
  64                       "PAGE_EXECUTE_WRITECOPY":0x80,  "PAGE_NOACCESS":0x01, "PAGE_READONLY":0x02,\ 
  65                       "PAGE_READWRITE":0x04, "PAGE_WRITECOPY": 0x08 } 
  66   
  67   
  68   
  69  IgnoreSingleStep = {"DISABLE" : 0 , "FORCE" : 1 , "CONTINUE" : 2} 
  70   
  71   
  72   
  73  #define JT_JUMP        0               // Unconditional jump 
  74  #define JT_COND        1               // Conditional jump 
  75  #define JT_SWITCH      2               // Jump via switch table 
  76  #define JT_CALL        3               // Local (intramodular) call 
  77  #define CALL_INTER     4               // intermodular call 
  78  jmpTypeFlags = {"JUMP":0,\ 
  79                  "JUMP_COND":1,\ 
  80                  "JUMP_SWITCH":2,\ 
  81                  "CALL":3,\ 
  82                  "CALL_INTER":4} 
  83   
  84   
  85  NM_NONAME=0x00            # Undefined name 
  86  NM_MODSEARCH=0xFD 
  87  NM_ANYNAME=0xFF           # Name of any type 
  88  #Names saved in the data file of module they appear. 
  89  NM_PLUGCMD=0x30           # Plugin commands to execute at break 
  90  NM_LABEL=0x31             # User-defined label 
  91  NM_EXPORT=0x32            # Exported (global) name 
  92  NM_IMPORT=0x33            # Imported name 
  93  NM_LIBRARY=0x34           # Name from library or object file 
  94  NM_CONST=0x35             # User-defined constant 
  95  NM_COMMENT=0x36           # User-defined comment 
  96  NM_LIBCOMM=0x37           # Comment from library or object file 
  97  NM_BREAK=0x38             # Condition related with breakpoint 
  98  NM_ARG=0x39               # Arguments decoded by analyzer 
  99  NM_ANALYSE=0x3A           # Comment added by analyzer 
 100  NM_BREAKEXPR=0x3B         # Expression related with breakpoint 
 101  NM_BREAKEXPL=0x3C         # Explanation related with breakpoint 
 102  NM_ASSUME=0x3D            # Assume function with known arguments 
 103  NM_STRUCT=0x3E            # Code structure decoded by analyzer 
 104  NM_CASE=0x3F              # Case description decoded by analyzer 
 105  #Names saved in the data file of main module. 
 106  NM_INSPECT=0x40           # Several last inspect expressions 
 107  NM_WATCH=0x41             # Watch expressions 
 108  NM_ASM=0x42               # Several last assembled strings 
 109  NM_FINDASM=0x43           # Several last find assembler strings 
 110  NM_LASTWATCH=0x48         # Several last watch expressions 
 111  NM_SOURCE=0x49            # Several last source search strings 
 112  NM_REFTXT=0x4A            # Several last ref text search strings 
 113  NM_GOTO=0x4B              # Several last expressions to follow 
 114  NM_GOTODUMP=0x4C          # Several expressions to follow in Dump 
 115  NM_TRPAUSE=0x4D           # Several expressions to pause trace 
 116  #Names saved in the data file of debugged DLL. 
 117  NM_DLLPARMS=0x50          # (10 parms + 6 regs) x 10-line history 
 118  #Names that are not saved in the data file. 
 119  NM_DEBUG=0x80             # Names from debug data 
 120  NM_IMPLIB=0x81            # Names of import library files 
 121  NM_IMPNAME=0x82           # Names of import library entries 
 122  NM_FONT=0x83              # Names of fonts 
 123  NM_SCHEME=0x84            # Names of colour schemes 
 124  NM_GOTOSTACK=0x85         # Several expressions to follow in Stack 
 125  NM_HILITE=0x86            # Names of highlighting schemes 
 126  #Pseudonames. 
 127  NM_IMCALL=0xFE            # Intermodular call 
 128   
 129   
 130  import UserDict 
 131   
 132  # Dict that returns classess 
133 -class DictTypes(UserDict.IterableUserDict):
134 - def __init__(self):
135 UserDict.IterableUserDict.__init__(self)
136 - def __iter__(self):
137 for k in self.data.keys(): 138 yield self.data[k]
139 140 141 ImmDrawColors = {"Black":0,"Maroon":128,"Green":32768,"Olive":32896,"Navy":8388608,"Purple":8388736,"Teal":8421376,\ 142 "Gray":8421504,"Silver":12632256,"Red":255,"Lime":65280,"Yellow":65535,"Blue":16711680,"Fuchsia":16711935,\ 143 "Aqua":16776960,"LightGray":12632256,"DarkGray":8421504,"White":16777215,"MoneyGreen":12639424,\ 144 "SkyBlue":15780518,"Cream":15793151,"MedGray":10789024,"red":255,"darkgreen":32768} 145 146 ########################### 147 ########################### 148 ### Debugger main class ### 149 ########################### 150 ###########################
151 -class Debugger:
152 - def __init__(self):
153 """ Initialize the Immunity Debugger API""" 154 self.threadid = 0 155 os = self.getOsInformation() 156 self.ossystem = os[ 0 ].lower() 157 self.osversion = os[ 1 ].lower() 158 self.osrelease = os[ 2 ].lower() 159 160 # we want to distinguish Vista over other Windows. 161 self.isVista = self.getOsRelease()[0] == '6' 162 163 self.Eventndx = { debugger.CREATE_PROCESS_DEBUG_EVENT : CreateProcessEvent, 164 debugger.CREATE_THREAD_DEBUG_EVENT : CreateThreadEvent, 165 debugger.EXCEPTION_DEBUG_EVENT : ExceptionEvent, 166 debugger.EXIT_PROCESS_DEBUG_EVENT : ExitProcessEvent, 167 debugger.EXIT_THREAD_DEBUG_EVENT : ExitThreadEvent, 168 debugger.LOAD_DLL_DEBUG_EVENT : LoadDLLEvent, 169 debugger.OUTPUT_DEBUG_STRING_EVENT : OutputDebugEvent, 170 debugger.UNLOAD_DLL_DEBUG_EVENT : UnloadDLLEvent, 171 debugger.RIP_EVENT : RIPEvent } 172 173 self.clearState()
174
175 - def clearState(self):
176 self.Symbols = DictTypes() 177 self.Handles = DictTypes() 178 self.Threads = DictTypes() 179 self.MemoryPages = DictTypes() 180 self.Modules = DictTypes() 181 self.BackTrace = [] 182 self.HeapsAddr = [] 183 self.Heaps = {}
184 185 186 ### Get the ultimate solution ###
188 return self.Error("%d" % (0x15 * 2))
189 190 191 ### Immunity Debugger Knowledge ### 192 # Sharing information between scripts 193
194 - def addKnowledge(self, id, object, force_add = 0x0):
195 """ 196 This function add a python object to the knowledge database. 197 198 @type id: STRING 199 @param id: unique name tag of the object 200 201 @type object: Python object 202 @param object: Object to be saved in the knowledge database 203 """ 204 205 pickled_object=pickle.dumps(object) 206 return debugger.AddKnowledge(pickled_object,id, force_add)
207
208 - def getKnowledge(self,id):
209 """ 210 Gets python object from the knowledge database. 211 212 @type id: STRING 213 @param id: unique name tag of the object 214 215 @rtype: PYTHON OBJECT 216 @return: Object retrieved from the knowledge database 217 """ 218 pickled_object=debugger.GetKnowledge(id) 219 #try: 220 if not pickled_object: 221 return None 222 return pickle.loads(pickled_object)
223
224 - def listKnowledge(self):
225 """ 226 Gets the list of saved objects in the knowledge database. 227 228 @rtype: TUPLE 229 @return: List of String ids currently saved 230 """ 231 return debugger.ListKnowledge()
232
233 - def findPacker(self, name, OnMemory = True):
234 """ 235 Find possible Packer/Cryptors/etc on a Module 236 237 @type name: STRING 238 @param name: Module name 239 240 @type OnMemory: (Optional, Def: True) BOOLEAN 241 @param OnMemory: Whether to look in memory or on a file. 242 243 @rtype: LIST of TUPLES in the form of (DWORD, LIST OF STRING) 244 @return: A list of the Packer founded (Offset, List of Packer found in that address) 245 """ 246 if OnMemory: 247 mem = self.getMemoryPagebyOwner(name) 248 if not mem: 249 raise Exception, "Coudln't find a Memory Page belonging to %s" % name 250 data = "" 251 for a in mem: 252 data+= a.getMemory() 253 else: 254 mod = self.getModule( name ) 255 if not mod: 256 raise Exception, "Coudln't find the correct Module belonging to %s" % name 257 data = mod.getPath() 258 259 import pefile 260 import peutils 261 if OnMemory: 262 pe = pefile.PE( data = data ) 263 else: 264 pe = pefile.PE( name = data ) 265 266 sig_db = peutils.SignatureDatabase('Data/UserDB.TXT') 267 return sig_db.match( pe )
268
269 - def forgetKnowledge(self,id):
270 """ 271 Remove python object from knowledge database. 272 273 @type id: STRING 274 @param id: unique name tag of the object 275 """ 276 return debugger.ForgetKnowledge(id)
277
278 - def cleanKnowledge(self):
279 """ Clean ID memory from known objects 280 """ 281 for ke in self.listKnowledge(): 282 self.forgetKnowledge(ke)
283 284
285 - def addGenHook(self,object):
286 """ 287 Add a hook to Immunity Debugger 288 """ 289 290 import pickle 291 try: 292 rtype=object.type 293 except: 294 rtype=0 295 try: 296 label=object.label 297 except: 298 label="No Label specified for this hook" 299 pickled_object=pickle.dumps(object) 300 debugger.Addhook(pickled_object,label,rtype)
301 302
303 - def cleanHooks(self):
304 """ 305 Clean ID memory from hook objects 306 """ 307 for hk in self.listHooks(): 308 debugger.Removehook(hk)
309 310 311
312 - def cleanUP(self):
313 """ 314 Clean ID memory for every kind of object saved in it 315 """ 316 self.cleanHooks() 317 self.cleanKnowledge()
318 319
320 - def getPEBaddress(self):
321 """ 322 Gets PEB. 323 @rtype: DWORD 324 @return: PEB address 325 """ 326 return debugger.GetPEB()
327 328 329 330 ### Disassembling / Analyzing Functions / etc ### 331
332 - def analyseCode(self,address):
333 """ 334 Analyse module's code 335 336 @type Address: DWORD 337 @param Address: Address from module to be analysed 338 """ 339 debugger.Analysecode(address)
340
341 - def isAnalysed(self,address):
342 """ 343 Check if module is already analysed 344 345 @type Address: DWORD 346 @param Address: Address from module 347 348 @rtype: DWORD 349 @return: 1 if module already analysed 350 """ 351 ret = debugger.IsAnalysed(address) 352 353 if ret == -1: 354 return 0 355 else: 356 return ret
357
358 - def setVariable(self,address,string):
359 """ 360 Set Variable name to specified address. 361 362 @type Address: DWORD 363 @param Address: Address from assembly line 364 365 @type String: STRING 366 @param String: Variable name to be set 367 368 """ 369 return debugger.SetVariable(address,string)
370
371 - def getVariable(self,address):
372 """ 373 Get Variable name from specified address 374 375 @type Address: DWORD 376 @param Address: Address from assembly line 377 378 @rtype: STRING 379 @return: Variable name for given address. 380 381 """ 382 return debugger.GetVariable(address)
383 384 385 # Disasm tooks 0.00008130 usec/pass
386 - def Disasm(self, address, mode = DISASM_ALL):
387 """ 388 Disasm address 389 390 @type Address: DWORD 391 @param Address: Address to disasm 392 393 @type Mode: (Optional, Def: DISASM_ALL) 394 @param Mode: Disasm mode 395 396 @rtype: opCode Object (Check libanalyze.py) 397 @return: Disassmbled Opcode 398 """ 399 400 op= opCode( self, address ) 401 op._getfromtuple( debugger.Disasm( address, mode) ) 402 return op
403 404 # Disasm tooks 0.00008130 usec/pass 405
406 - def disasm(self, address, mode = DISASM_ALL):
407 return self.Disasm(address, mode)
408 409 410 # DisasmSize 0.00007515 usec/pass
411 - def disasmSizeOnly(self, address):
412 """ 413 Determine command size only 414 415 @type Address: DWORD 416 @param Address: Address to disasm 417 418 @rtype: opCode Object (Check libanalyze.py) 419 @return: Disassmbled Opcode 420 """ 421 return self.Disasm(address, DISASM_SIZE)
422 423 # DisasmData 0.00007375 usec/pass
424 - def disasmData(self, address):
425 """ 426 Determine size and analysis data 427 428 @type Address: DWORD 429 @param Address: Address to disasm 430 431 @rtype: opCode Object (Check libanalyze.py) 432 @return: Disassmbled Opcode 433 """ 434 return self.Disasm(address, DISASM_DATA)
435
436 - def disasmTrace(self, address):
437 """ 438 Trace integer registers 439 440 @type Address: DWORD 441 @param Address: Address to disasm 442 443 @rtype: opCode Object (Check libanalyze.py) 444 @return: Disassmbled Opcode 445 """ 446 return self.Disasm(address, DISASM_TRACE)
447 448 # DisasmFile 0.00007934 usec/pass
449 - def disasmFile(self, address):
450 """ 451 Disassembly, no symbols/registers 452 453 @type Address: DWORD 454 @param Address: Address to disasm 455 456 @rtype: opCode Object (Check libanalyze.py) 457 @return: Disassmbled Opcode 458 """ 459 return self.Disasm(address, DISASM_FILE)
460 461 # DisasmCode 0.00008549 usec/pass
462 - def disasmCode(self, address):
463 """ 464 Disassembly, registers undefined 465 466 @type Address: DWORD 467 @param Address: Address to disasm 468 469 @rtype: opCode Object (Check libanalyze.py) 470 @return: Disassmbled Opcode 471 """ 472 return self.Disasm(address, DISASM_CODE)
473
474 - def disasmRTrace(self, address):
475 """ 476 Disassemble with run-trace registers 477 478 @type Address: DWORD 479 @param Address: Address to disasm 480 481 @rtype: opCode Object (Check libanalyze.py) 482 @return: Disassmbled Opcode 483 """ 484 return self.Disasm(address, DISASM_RTRACE)
485 486
487 - def disasmForward( self, address, nlines=1, mode = DISASM_ALL):
488 """ 489 Disasm nlines forward of given address 490 491 @type Address: DWORD 492 @param Address: Address to disasm 493 494 @type nlines: DWORD 495 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 496 497 @type Mode: (Optional, Def: DISASM_ALL) 498 @param Mode: Disasm mode 499 500 @rtype: opCode Object (Check libanalyze.py) 501 @return: Disassmbled Opcode 502 """ 503 forward_address = debugger.Disasmforward( address, nlines ) 504 op=opCode( self, forward_address ) 505 op._getfromtuple( debugger.Disasm( forward_address, mode ) ) 506 return op
507 508 509
510 - def disasmForwardAddressOnly(self, address, nlines=1):
511 """ 512 Disasm nlines forward to the given address 513 514 @type Address: DWORD 515 @param Address: Address to disasm 516 517 @type nlines: DWORD 518 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 519 520 @type Mode: (Optional, Def: DISASM_ALL) 521 @param Mode: Disasm mode 522 523 @rtype: DWORD 524 @return: Address of the opcode 525 """ 526 return debugger.Disasmforward(address,nlines)
527
528 - def disasmForwardSizeOnly(self, address, nlines=1):
529 """ 530 Determine command size only 531 532 @type Address: DWORD 533 @param Address: Address to disasm 534 535 @type nlines: DWORD 536 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 537 538 @rtype: opCode Object (Check libanalyze.py) 539 @return: Disassmbled Opcode 540 """ 541 return self.disasmForward(address, nlines, DISASM_SIZE)
542
543 - def disasmForwardData(self, address, nlines=1):
544 """ 545 Determine size and analysis data 546 547 @type Address: DWORD 548 @param Address: Address to disasm 549 550 @type nlines: DWORD 551 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 552 553 @rtype: opCode Object (Check libanalyze.py) 554 @return: Disassmbled Opcode 555 556 """ 557 return self.disasmForward(address, nlines, DISASM_DATA)
558
559 - def disasmForwardTrace(self, address, nlines=1):
560 """ 561 Trace integer registers 562 563 @type Address: DWORD 564 @param Address: Address to disasm 565 566 @type nlines: DWORD 567 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 568 569 @rtype: opCode Object (Check libanalyze.py) 570 @return: Disassmbled Opcode 571 """ 572 return self.disasmForward(address, nlines, DISASM_TRACE)
573
574 - def disasmForwardFile(self, address, nlines=1):
575 """ 576 Disassembly, no symbols/registers 577 578 @type Address: DWORD 579 @param Address: Address to disasm 580 581 @type nlines: DWORD 582 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 583 584 @rtype: opCode Object (Check libanalyze.py) 585 @return: Disassmbled Opcode 586 """ 587 return self.disasmForward(address, nlines, DISASM_FILE)
588
589 - def disasmForwardCode(self, address, nlines=1):
590 """ 591 Disassembly, registers undefined 592 593 @type Address: DWORD 594 @param Address: Address to disasm 595 596 @type nlines: DWORD 597 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 598 599 @rtype: opCode Object (Check libanalyze.py) 600 @return: Disassmbled Opcode 601 """ 602 return self.disasmForward(address, DISASM_CODE)
603
604 - def disasmForwardRTrace(self, address, nlines=1):
605 """ 606 Disassemble with run-trace registers 607 608 @type Address: DWORD 609 @param Address: Address to disasm 610 611 @type nlines: DWORD 612 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 613 614 @rtype: opCode Object (Check libanalyze.py) 615 @return: Disassmbled Opcode 616 """ 617 return self.disasmForward(address, nlines, DISASM_RTRACE)
618
619 - def disasmBackward( self, address, nlines = 1, mode = DISASM_ALL):
620 """ 621 Disasm nlines backward from the given address 622 623 @type Address: DWORD 624 @param Address: Address to disasm 625 626 @type nlines: DWORD 627 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 628 629 @rtype: opCode Object (Check libanalyze.py) 630 @return: Disassmbled Opcode 631 """ 632 backward_address = debugger.Disasmbackward( address, nlines ) 633 op = opCode( self, backward_address ) 634 op._getfromtuple( debugger.Disasm( backward_address, mode ) ) 635 return op
636
637 - def disasmBackwardAddressOnly(self,address,nlines=1):
638 """ 639 Disasm nlines backward of given address 640 641 @type Address: DWORD 642 @param Address: Address to disasm 643 644 @type nlines: DWORD 645 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 646 647 @rtype: DWORD 648 @return: Address of the Opcode""" 649 return debugger.Disasmbackward(address,nlines)
650 651 652
653 - def disasmBackwardSizeOnly(self, address, nlines = 1):
654 """ 655 Determine command size only 656 657 @type Address: DWORD 658 @param Address: Address to disasm 659 660 @type nlines: DWORD 661 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 662 663 @rtype: opCode Object (Check libanalyze.py) 664 @return: Disassmbled Opcode 665 """ 666 return self.disasmBackward(address, nlines, DISASM_SIZE)
667
668 - def disasmBackwardData(self, address, nlines = 1):
669 """ 670 Determine size and analysis data 671 672 @type Address: DWORD 673 @param Address: Address to disasm 674 675 @type nlines: DWORD 676 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 677 678 @rtype: opCode Object (Check libanalyze.py) 679 @return: Disassmbled Opcode 680 """ 681 return self.disasmBackward(address, nlines, DISASM_DATA)
682
683 - def disasmBackwardTrace(self, address, nlines = 1):
684 """ 685 Trace integer registers 686 687 @type Address: DWORD 688 @param Address: Address to disasm 689 690 @type nlines: DWORD 691 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 692 693 @rtype: opCode Object (Check libanalyze.py) 694 @return: Disassmbled Opcode 695 """ 696 return self.disasmBackward(address, nlines, DISASM_TRACE)
697
698 - def disasmBackwardFile(self, address, nlines = 1):
699 """ 700 Disassembly, no symbols/registers 701 702 @type Address: DWORD 703 @param Address: Address to disasm 704 705 @type nlines: DWORD 706 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 707 708 @rtype: opCode Object (Check libanalyze.py) 709 @return: Disassmbled Opcode 710 """ 711 return self.disasmBackward(address, nlines, DISASM_FILE)
712
713 - def disasmBackwardCode(self, address, nlines = 1):
714 """ 715 Disassembly, registers undefined 716 717 @type Address: DWORD 718 @param Address: Address to disasm 719 720 @type nlines: DWORD 721 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 722 723 @rtype: opCode Object (Check libanalyze.py) 724 @return: Disassmbled Opcode 725 """ 726 return self.disasmBackward(address, nlines, DISASM_CODE)
727
728 - def disasmBackwardRTrace(self, address, nlines = 1):
729 """ 730 Disassemble with run-trace registers 731 732 @type Address: DWORD 733 @param Address: Address to disasm 734 735 @type nlines: DWORD 736 @param nlines: (Optional, Def: 1) Number of lines to disassemble forward 737 738 @rtype: opCode Object (Check libanalyze.py) 739 @return: Disassmbled Opcode 740 """ 741 return self.disasmBackward(address, nlines, DISASM_RTRACE)
742
743 - def findDecode(self, address):
744 """ 745 Get the internal decode information from an analysed module 746 747 @type Address: DWORD 748 @param Address: Address in the range of the module page 749 750 @rtype: Decode OBJECT 751 @return: Decode Object containing the analized information 752 """ 753 return Decode( address )
754 #return debugger.FindDecode( address ) 755
756 - def goNextProcedure(self):
757 """ 758 Go to next procedure 759 760 @rtype: DWORD 761 @return: Address of next procedure 762 """ 763 return debugger.GoNextProcedure()
764
765 - def goPreviousProcedure(self):
766 """ 767 Go to previous procedure 768 769 @rtype: DWORD 770 @return: Address of previous procedure 771 """ 772 return debugger.GoPreviousProcedure()
773
774 - def getOpcode(self,address):
775 """ 776 Get address's Opcode 777 778 @type Address: DWORD 779 @param Address: Address to disasm 780 781 @rtype: opCode Object (Check libanalyze.py) 782 @return: Disassmbled Opcode 783 """ 784 op=opCode(self, address) 785 op._getfromtuple(debugger.Disasm(address)) 786 return op
787
788 - def Assemble(self, code,address=0x0):
789 """ 790 Assemble code. 791 792 @type code: STRING 793 @param code: Code to be assembled 794 795 @rtype: STRING 796 @return: Opcodes of the assembled code 797 """ 798 opcode = [] 799 for line in code.split("\n"): 800 line = line.strip() 801 if line: 802 opcode.append( debugger.Assemble(line,address) ) 803 return string.joinfields( opcode, "")
804
805 - def decodeAddress(self,address):
806 """ 807 Decode given address 808 809 @rtype: STRING 810 @return: decoded value 811 """ 812 return debugger.DecodeAddress(address)
813
814 - def undecorateName(self,decorated):
815 """ 816 Undecorate given name 817 818 @type decorated: STRING 819 @param decorated: decorated name 820 @rtype: STRING 821 @return: undecorated name 822 """ 823 return debugger.UndecorateName(decorated)
824
825 - def getTraceArgs(self, address, tracedarg, shownonusersupplied = False):
826 """ 827 Trace Parameters of a function, return only when is user-supplied 828 829 @type Address: DWORD 830 @param Address: Address of the function call 831 832 @type Tracedarg: DWORD 833 @param Tracedarg: Parameter to trace 834 835 @type Shownonusersupplied: BOOLEAN 836 @param Shownonusersupplied: (Optional, Def: False) Flag whether or not show user supplied param 837 838 @rtype: TUPLES 839 @return: Returns a tuple of (Push Opcode, TABLE of OPCODES setting the PUSH) 840 """ 841 t = TraceArgs( self, address, tracedarg, shownonusersupplied ) 842 return t.get()
843
844 - def getAllFunctions(self,address):
845 """ 846 Gets all function of given module's address 847 848 @rtype: LIST 849 @return: Function start address 850 """ 851 return debugger.Getallfunctions(address)
852
853 - def getFunction(self, address):
854 """ 855 Get the Function information 856 857 @type Address: DWORD 858 @param Address: Address of the function 859 860 @rtype: Function Object 861 @return: Function Object containing information of the requested function 862 863 """ 864 return Function(self, address)
865
866 - def getFunctionBegin(self,address):
867 """ 868 Find start address of funcion 869 870 @rtype: DWORD 871 @return: Start Address""" 872 return debugger.Getfuncbegin(address)
873
874 - def getFunctionEnd(self, function_address):
875 """ 876 Get all the possible ends of a Function 877 878 @type function_address: DWORD 879 @param function_address: Address of the function 880 881 @rtype: LIST 882 @return: List of Address of all the possible ret address 883 """ 884 if type(function_address) in (type(1), type(1L)): 885 func = self.getFunction( function_address ) 886 return func.getFunctionEnd() 887 elif isinstance(function_address, Function): 888 return function_address.getFunctionEnd() 889 else: 890 raise Exception, "Function type not recognized"
891 892 #def getFunctionEnd(self,address): 893 #""" 894 #Find end address of funcion (Deprecated, use Function) 895 896 #@rtype: DWORD 897 #@return: End address 898 #""" 899 #return debugger.Getfuncend(address) 900
901 - def getAllBasicBlocks(self,address):
902 """ 903 Gets all basic blocks of given procedure (Deprecated, use Function) 904 905 @rtype: LIST 906 @return: (start,end) addresses of basic blocks 907 """ 908 bblocks = debugger.Getallbasicblocks(address) 909 basicblocks = [] 910 if bblocks: 911 for block in bblocks: 912 basicblocks.append(basicBlock(self,block[0],block[1])) 913 return basicblocks
914
915 - def findDataRef(self,address):
916 """ 917 Find data references to given address 918 919 @rtype: LIST 920 @return: Table with found references 921 """ 922 return debugger.FindDataRef(address)
923
924 - def getXrefFrom(self, address):
925 """ 926 Get X Reference from a given address 927 928 @type Address: DWORD 929 @param Address: Address 930 931 @rtype: LIST 932 @return: List of X reference from the given address 933 """ 934 for mod in self.getAllModules(): 935 xref = mod.getXrefFrom(address) 936 937 if xref: return xref 938 return []
939
940 - def getXrefTo(self, address):
941 """ 942 Get X Reference to a given address 943 944 @type Address: DWORD 945 @param Address: Address 946 947 @rtype: LIST 948 @return: List of X reference to the given address 949 """ 950 for mod in self.getAllModules(): 951 xref = mod.getXrefTo(address) 952 953 if xref: return xref 954 return []
955
956 - def getInterCalls(self,address):
957 """ 958 Get intermodular calls 959 960 @type Address: DWORD 961 @param Address: Address 962 963 @rtype: DICTIONARY 964 @return: Dict of intermodular calls to the given address 965 """ 966 self.gotoDisasmWindow(address) 967 return debugger.GetInterCalls(address)
968 969 970 ### Gathering Information for the debugged process ### 971 # All kind of information that can be gathered for the process (PEB, Heap, Events, Modules, etc) 972
973 - def getRegs(self):
974 """ 975 Get CPU Context values. 976 977 @rtype: DICTIONARY 978 @return: x86 Registers 979 """ 980 return debugger.Getregs()
981
982 - def getRegsRepr(self):
983 """ 984 We have to do this to handle the Long integers, which XML-RPC cannot do 985 986 @rtype: DICTIONARY 987 @return: x86 registers in string format (repr) 988 """ 989 regs=self.getRegs() 990 991 for r in regs: 992 regs[r]=repr(regs[r]) 993 return regs
994
995 - def setReg(self,reg,value):
996 """ 997 Set REG value 998 999 @type reg: STRING 1000 @param reg: Register name 1001 1002 @type value: DWORD 1003 @param vale: Value to set the register 1004 """ 1005 return debugger.Setreg(Register[reg],value)
1006
1007 - def getPEB(self):
1008 """ 1009 Get the PEB information of the debugged process 1010 1011 @rtype: PEB OBJECT 1012 @return: PEB """ 1013 1014 return PEB(self)
1015 1016
1017 - def getHeap(self, addr, restore = False):
1018 """ 1019 Get Heap Information 1020 1021 @type addr: DWORD 1022 @param addr: Address of the heap 1023 1024 @type restore: BOOLEAN 1025 @param restore: (Optional, Def: False) Flag whether or not use a restore heap 1026 1027 @rtype: PHeap OBJECT 1028 @return: Heap 1029 """ 1030 if self.Heaps.has_key(addr): 1031 return self.Heaps[addr] 1032 1033 if self.isVista: 1034 pheap = libheap.VistaPHeap( self, addr, restore ) 1035 else: 1036 pheap = libheap.PHeap( self, addr, restore ) 1037 1038 if pheap: 1039 self.Heaps[addr] = pheap 1040 return pheap
1041
1042 - def getDebuggedName(self):
1043 """ 1044 Get debugged name 1045 1046 @rtype: STRING 1047 @return: Name of the Process been debugged 1048 """ 1049 return debugger.getDebuggedName()
1050
1051 - def getDebuggedPid(self):
1052 """ 1053 Get debugged pid 1054 1055 @rtype: DWORD 1056 @return: Process ID 1057 """ 1058 return debugger.getPID()
1059
1060 - def isAdmin(self):
1061 """ 1062 Is debugger running as admin? 1063 @rtype: INTEGER 1064 @return: 1 if running as admin 1065 """ 1066 return debugger.IsAdmin()
1067
1068 - def getInfoPanel(self):
1069 """ 1070 Get information displayed on Info Panel 1071 1072 @rtype: TUPLE 1073 @return: Python Tuple with the 3 lines from InfoPanel 1074 """ 1075 return debugger.Getinfopanel()
1076
1077 - def getCurrentAddress(self):
1078 """ 1079 Get the current address been focus on the Disasm window 1080 1081 @rtype: DWORD 1082 @return: Address 1083 """ 1084 return debugger.GetCurrentAddress()
1085 1086
1087 - def getAllModules(self):
1088 """ 1089 Get all loaded modules. 1090 1091 @rtype: DICTIONARY 1092 @return: Dict of Modules 1093 """ 1094 1095 if self.Modules: 1096 return self.Modules 1097 1098 modulos = debugger.Getallmodules() 1099 symbol = 1 1100 for mod in modulos.keys(): 1101 if not self.Modules.has_key(mod): 1102 # Modules are stable 1103 m = Module(mod, modulos[mod][0], modulos[mod][1], modulos[mod][2]) 1104 mod_dict = self._getmoduleinfo(modulos[mod][0]) 1105 m.setModuleExtension(mod_dict) 1106 if symbol: 1107 self.getAllSymbols() #_getsymbols() 1108 symbol = 0 1109 1110 try: 1111 m.setSymbols( self.Symbols[ mod.lower() ] ) 1112 except KeyError: 1113 pass 1114 self.Modules[mod] = m 1115 # XXX TODO: Here we must check between the modules that are loaded and the catched one on self.Modules 1116 # so we know if a module is not there anymore 1117 1118 return self.Modules
1119
1120 - def getModulebyAddress(self, address):
1121 1122 modulos = debugger.Getallmodules() 1123 1124 for name in modulos.keys(): 1125 total_range = modulos[name][0] + modulos[name][1] 1126 if address > modulos[name][0] and address < total_range: 1127 if not self.Modules.has_key(name): 1128 m = Module(name, modulos[name][0], modulos[name][1], modulos[name][2]) 1129 mod_dict = self._getmoduleinfo(modulos[name][0]) 1130 m.setModuleExtension(mod_dict) 1131 self.Modules[name] = m 1132 return m 1133 else: 1134 return self.Modules[name]
1135
1136 - def getModule(self, name):
1137 """ 1138 Get Module Information 1139 1140 @type name: STRING 1141 @param name: Name of the module 1142 1143 @rtype: Module OBJECT 1144 @return: A Module object 1145 """ 1146 1147 #self.getAllModules() 1148 1149 modulos = debugger.Getallmodules() 1150 if modulos.has_key(name): 1151 if not self.Modules.has_key(name): 1152 # Modules are stable 1153 m = Module(name, modulos[name][0], modulos[name][1], modulos[name][2]) 1154 mod_dict = self._getmoduleinfo(modulos[name][0]) 1155 m.setModuleExtension(mod_dict) 1156 #if symbol: 1157 # self.getAllSymbols() #_getsymbols() 1158 # symbol = 0 1159 1160 #try: 1161 # m.setSymbols( self.Symbols[ mod.lower() ] ) 1162 #except KeyError: 1163 # pass 1164 self.Modules[name] = m 1165 return m 1166 else: 1167 return self.Modules[name] 1168 1169 #if type(name) == type(''): 1170 # try: 1171 # return self.Modules[ name ] 1172 # except KeyError: 1173 # return None 1174 #else: 1175 # for mod in self.Modules.keys(): 1176 # if self.Modules[ mod ].baseaddress == name: 1177 # return self.Modules[ mod ] 1178 return None
1179
1180 - def _getmoduleinfo(self,base_address):
1181 return debugger.Getmodinfo(base_address)
1182
1183 - def getReferencedStrings(self,code_base):
1184 """ 1185 Get all referenced string from module 1186 1187 @type name: DWORD 1188 @param name: Code Base Address 1189 @rtype: LIST 1190 @return: A list of tuples with referenced strings (address, string, comment) 1191 """ 1192 return debugger.Getreferencedstrings(code_base)
1193
1194 - def Ps(self):
1195 """ 1196 List all active processes. 1197 1198 @rtype: LIST 1199 @return: A list of tuples with process information (pid, name, path, services, tcp list, udp list) 1200 """ 1201 return debugger.ps()
1202
1203 - def ps(self):
1204 """ 1205 List all active processes. 1206 1207 @rtype: LIST 1208 @return: A list of tuples with process information (pid, name, path, services, tcp list, udp list) 1209 """ 1210 return self.Ps()
1211
1212 - def getSehChain(self):
1213 """ 1214 Get the SEH chain. 1215 1216 @rtype: LIST 1217 @return: A list of tuples with SEH information (seh, handler) 1218 """ 1219 return debugger.Getsehchain()
1220
1221 - def getEvent(self):
1222 """ 1223 Get the current Event 1224 1225 @rtype: Event Object 1226 @return: Event 1227 """ 1228 event = debugger.Getevent() 1229 EventCode = event[0][0] 1230 try: 1231 return self.Eventndx[ EventCode ]( event ) 1232 except KeyError: # We cannot handle this event 1233 return None
1234
1235 - def getPage(self, addr):
1236 """ 1237 Get a memory page. 1238 1239 @type addr: DWORD 1240 @param addr: Address of a beginning of the Page 1241 1242 @rtype: Page OBJECT 1243 @return: Memory Page 1244 """ 1245 self.getMemoryPages() 1246 try: 1247 return self.MemoryPages[addr] 1248 except KeyError: 1249 return None
1250
1251 - def getMemoryPagebyOwner(self, owner):
1252 """ 1253 Get the Memory Pages belonging to the given dll. 1254 1255 @type owner: STRING 1256 @param owner: Name of the dll 1257 1258 @rtype: LIST 1259 @return: LIST of Memory Pages belonging to the given dll 1260 """ 1261 self.getMemoryPages() 1262 1263 pages = [] 1264 for a in self.MemoryPages.keys(): 1265 mem = self.MemoryPages[a] 1266 if mem.getOwner() == owner: 1267 pages.append( mem ) 1268 1269 return pages
1270
1271 - def getMemoryPagebyOwnerAddress(self, owner_addr):
1272 """ 1273 Get the Memory Pages belonging to the given dll by its base address. 1274 1275 @type owner: STRING 1276 @param owner: Name of the dll 1277 1278 @rtype: LIST 1279 @return: LIST of Memory Pages belonging to the given dll 1280 """ 1281 self.getMemoryPages() 1282 1283 pages = [] 1284 for a in self.MemoryPages.keys(): 1285 mem = self.MemoryPages[a] 1286 if mem.owner == owner_addr: 1287 pages.append( mem ) 1288 1289 return pages
1290
1291 - def getMemoryPagebyAddress(self, address):
1292 """ 1293 Get a memory page. 1294 1295 @type address: DWORD 1296 @param address: Address in the range of the Page 1297 1298 @rtype: Page OBJECT 1299 @return: Memory Page 1300 """ 1301 1302 self.getMemoryPages() 1303 for a in self.MemoryPages.keys(): 1304 mem = self.MemoryPages[a] 1305 if mem.baseaddress <= address and (mem.getBaseAddress() + mem.size) > address : 1306 return mem 1307 return None
1308
1309 - def getMemoryPages(self):
1310 """ 1311 Get All memory pages. 1312 1313 @rtype: DICTIONARY 1314 @return: List of all memory pages 1315 """ 1316 if self.MemoryPages: 1317 return self.MemoryPages 1318 1319 pages = debugger.Getmemorypages() 1320 1321 for addr in pages.keys(): 1322 m = MemoryPage(addr, self) 1323 m._getfromtuple(pages[addr]) 1324 self.MemoryPages[addr] = m 1325 return self.MemoryPages
1326
1327 - def vmQuery(self,address):
1328 """ 1329 Query Memory Page 1330 1331 @type address: DWORD 1332 @param address: Base Address of memory page 1333 1334 @rtype: Python List 1335 @return: List with memory page structure 1336 """ 1337 return debugger.VmQuery(address)
1338 1339
1340 - def getAllHandles(self):
1341 """ 1342 Get all handles. 1343 1344 @rtype: DICTIONARY 1345 @return: All the process handles 1346 """ 1347 if self.Handles: 1348 return self.Handles 1349 1350 handles = debugger.Getallhandles() 1351 for h in handles.keys(): 1352 H = Handle( h ) 1353 H._getfromtuple( handles[h] ) 1354 self.Handles[ h ] = H 1355 return self.Handles
1356
1357 - def getAllThreads(self):
1358 """ 1359 Get all threads. 1360 @rtype: LIST 1361 @return: All process threads 1362 """ 1363 threads = debugger.Getallthreads() 1364 for thread in threads: 1365 T = Thread(thread) 1366 T._getfromtuple(thread) 1367 self.Threads[T.getId()] = T 1368 return self.Threads
1369 1370 1371 1372
1373 - def getAllSymbols(self):
1374 """ 1375 Get All Symbols. 1376 1377 @rtype: DICTIONARY 1378 @return: All the symbols of the process 1379 """ 1380 if self.Symbols: 1381 return self.Symbols 1382 1383 names = debugger.Getallnames() 1384 current = self.getDebuggedName().rsplit(".", 1)[0] 1385 # reorder it a little bit 1386 for a in names.keys(): 1387 s=Symbol(a) 1388 s._getfromtuple( names[a] ) 1389 if current.lower() != s.getModule().lower(): 1390 module = s.getModule() + ".dll" 1391 else: 1392 module = s.getModule() + ".exe" 1393 1394 if self.Symbols.has_key( module ): 1395 self.Symbols[ module ][ a ] = s 1396 else: 1397 self.Symbols[ module ] = { a : s } 1398 1399 return self.Symbols
1400
1401 - def getAllSymbolsFromModule(self,address):
1402 """ 1403 Get Symbols from module. 1404 @type Address: DWORD 1405 @param Address: Address from module. 1406 1407 @rtype: DICTIONARY 1408 @return: All the symbols of the module 1409 """ 1410 1411 names = debugger.Getallnames(address) 1412 return names
1413 1414 1415
1416 - def callStack(self):
1417 """ 1418 Get a Back Trace (Call stack). 1419 1420 @rtype: LIST of Stack OBJECT 1421 @return: list of all the stack trace 1422 """ 1423 if self.BackTrace: 1424 return self.BackTrace 1425 1426 callstack = debugger.Getcallstack() 1427 for a in callstack: 1428 s = Stack() 1429 s._setfromtuple(a) 1430 self.BackTrace.append(s) 1431 return self.BackTrace
1432
1433 - def getCallTree(self,address=0):
1434 """ 1435 Get the call tree of given address. 1436 @rtype: LIST of Call tuples 1437 @return: list of all the call tree 1438 ulong line; // Line number in column 1439 ulong dummy; // Must be 1 1440 ulong type; // Type, set of TY_xxx 1441 ulong entry; // Address of function 1442 ulong from; // Address of calling instruction 1443 ulong calls; // Address of called subfunction 1444 """ 1445 1446 return debugger.Getcalltree(address)
1447 1448
1449 - def findModule(self, address):
1450 """ 1451 Find which module an address belongs to. 1452 1453 @type address: DWORD 1454 @param address: Address 1455 1456 @rtype: LIST 1457 @return: Tuple of module information (name, base address) 1458 1459 """ 1460 mod = debugger.Findmodule( address ) 1461 if mod == -1: 1462 mod = () 1463 return mod
1464
1465 - def getHeapsAddress(self):
1466 """ 1467 Get a the process heaps 1468 1469 @rtype: LIST of DWORD 1470 @return: List of Heap Address 1471 """ 1472 self.HeapsAddr = [] 1473 1474 peb = self.getPEB() 1475 addr = peb.ProcessHeaps 1476 for ndx in range(0, peb.NumberOfHeaps): 1477 l = self.readLong( addr + ndx * 4 ) 1478 if l: 1479 self.HeapsAddr.append( l ) 1480 1481 return self.HeapsAddr
1482
1483 - def getAddressOfExpression(self, expression):
1484 """ 1485 Get the address from an expression as ntdll.RtlAllocateHeap 1486 1487 @type expression: STRING 1488 @param expression: Expression to translate into an address 1489 1490 @rtype: DWORD 1491 @return: Address of the Expression 1492 """ 1493 return debugger.Getaddrfromexp(expression)
1494 1495
1496 - def getAddress(self, expression):
1497 """ 1498 Get the address from an expression as ntdll.RtlAllocateHeap 1499 1500 @type expression: STRING 1501 @param expression: Expression to translate into an address 1502 1503 @rtype: DWORD 1504 @return: Address of the Expression 1505 1506 """ 1507 return debugger.Getaddrfromexp(expression)
1508 1509 ### Displaying information ### 1510 # Error, Log, Creating new windows, etc 1511
1512 - def Error(self, msg):
1513 """ 1514 This function shows an Error dialog with a custom message. 1515 1516 @type msg: STRING 1517 @param msg: Message 1518 """ 1519 return debugger.Error( msg )
1520
1521 - def openTextFile(self,path=""):
1522 """ 1523 Opens text file in MDI windows. ( if no path is specified browsefile dialog will pop up ) 1524 1525 @type: STRING 1526 @param: (Optional, Def= "") Path to file 1527 """ 1528 if (len(path) > 0): 1529 return debugger.Opentextfile(path) 1530 else: 1531 return debugger.Opentextfile()
1532
1533 - def setStatusBar(self, msg):
1534 """ 1535 Sets the status bar message. 1536 1537 @type msg: STRING 1538 @param msg: Message 1539 """ 1540 return debugger.Infoline(msg)
1541
1542 - def clearStatusBar(self):
1543 """ 1544 Removes the current status bar message. 1545 """ 1546 return debugger.Infoline()
1547
1548 - def logLines(self, data, address = 0, highlight = False, gray = False , focus = 0):
1549 """ 1550 Adds multiple lines of ASCII text to the log window. 1551 1552 @type msg: LIST of STRING 1553 @param msg: List of Message to add (max size of msg is 255 bytes) 1554 1555 @type address: DWORD 1556 @param address: Address associated with the message 1557 1558 @type highlight: BOOLEAN 1559 @param highlight: Set highlight text 1560 1561 @type gray: BOOLEAN 1562 @param gray: Set gray text 1563 """ 1564 return [ self.Log(d, address, highlight, gray, focus) for d in data.split("\n") ]
1565
1566 - def LogLines(self,data,address = 0, highlight = False, gray = False , focus = 0):
1567 return [ self.Log(d, address, highlight, gray, focus) for d in data.split("\n") ]
1568 1569
1570 - def Log(self, msg, address = 0 ,highlight = False, gray = False , focus = 0):
1571 """ 1572 Adds a single line of ASCII text to the log window. 1573 1574 @type msg: STRING 1575 @param msg: Message (max size is 255 bytes) 1576 1577 @type address: DWORD 1578 @param address: Address associated with the message 1579 1580 @type highlight: BOOLEAN 1581 @param highlight: Set highlight text 1582 1583 @type gray: BOOLEAN 1584 @param gray: Set gray text 1585 """ 1586 if gray and not highlight: 1587 highlight = -1 1588 return debugger.Addtolist( address, int(highlight), msg[:255],focus)
1589
1590 - def log(self, msg, address = 0 ,highlight = False, gray = False , focus = 0):
1591 """ 1592 Adds a single line of ASCII text to the log window. 1593 1594 @type msg: STRING 1595 @param msg: Message (max size is 255 bytes) 1596 1597 @type address: DWORD 1598 @param address: Address associated with the message 1599 1600 @type highlight: BOOLEAN 1601 @param highlight: Set highlight text 1602 1603 @type gray: BOOLEAN 1604 @param gray: Set gray text 1605 """ 1606 if gray and not highlight: 1607 highlight = -1 1608 return debugger.Addtolist( address, int(highlight), msg[:255],focus)
1609 1610
1611 - def updateLog(self):
1612 """ 1613 Forces an immediate update of the log window. 1614 """ 1615 debugger.Updatelist()
1616
1617 - def createLogWindow(self):
1618 """ 1619 Creates or restores the log window. 1620 """ 1621 return debugger.Createlistwindow()
1622
1623 - def createWindow(self, title, col_titles):
1624 """ 1625 Creates a custom window. 1626 1627 @type title: STRING 1628 @param title: Window title 1629 1630 @type col_titles: LIST OF STRING 1631 @param col_titles: Column titles list 1632 1633 @return HWND: Handler of created table 1634 """ 1635 return self.createTable( title, col_titles )
1636
1637 - def createTable(self,title,col_titles):
1638 """ 1639 Creates a custom window. 1640 1641 @type title: STRING 1642 @param title: Window title 1643 1644 @type col_titles: LIST OF STRING 1645 @param col_titles: Column titles list 1646 1647 """ 1648 table=Table(self,title,col_titles) 1649 return table
1650
1651 - def setFocus(self,handler):
1652 """ 1653 Set focus on window. 1654 1655 @type handler: ULONG 1656 @param handler: Windows Handler 1657 1658 @return phandler: Handle to the window that previously had the focus. 1659 """ 1660 return debugger.SetFocus(handler)
1661
1662 - def isValidHandle(self,handler):
1663 """ 1664 Does a window still exist? 1665 1666 @type handler: ULONG 1667 @param handler: Windows to check handle 1668 1669 @return: INT : 1 Exists, 0 Doesnt exist 1670 """ 1671 return debugger.IsValidHandle(handler)
1672
1673 - def setStatusBarandLog(self, addr, msg):
1674 """ 1675 Sets and logs a status bar message. 1676 1677 @type addr: DWORD 1678 @param addr: Address related with the message 1679 1680 @type msg: STRING 1681 @param msg: Message 1682 """ 1683 return debugger.Message(addr, msg)
1684
1685 - def flashMessage(self, msg):
1686 """ 1687 Flashes a message at status bar. 1688 1689 @type msg: STRING 1690 @param msg: Message 1691 """ 1692 return debugger.Flash(msg)
1693
1694 - def setProgressBar(self, message, promille=100):
1695 """ 1696 Displays a progress bar which can contain formatted text and a progress percentage. 1697 If the formatted text contains a dollar sign ('$') it will be replaced by the current progress percentage. 1698 1699 @type msg: STRING 1700 @param msg: Message 1701 1702 @type promille: DWORD 1703 @param promille: Progress. At 0 the progress bar is closed and the previous message restored. 1704 """ 1705 return debugger.Progress(promille, message)
1706
1707 - def closeProgressBar(self):
1708 """ 1709 Close Progress Bar. 1710 """ 1711 return debugger.Progress(0, "")
1712
1713 - def getComment(self, address,type=0xFD):
1714 """ 1715 Get the comment of the opcode line. 1716 1717 @type address: DWORD 1718 @param address: Address of the requested comment 1719 1720 @rtype: STRING 1721 @return: Requested comment 1722 """ 1723 comment=None 1724 #First, try to fetch any comment 1725 if type == 0xFD: 1726 #alway look for user defined comments first 1727 comment=debugger.Getcomment(address,NM_COMMENT) 1728 if not comment: 1729 #try argument comment 1730 comment=debugger.Getcomment(address,NM_ARG) 1731 if not comment: 1732 #try library comment 1733 comment=debugger.Getcomment(address,NM_LIBCOMM) 1734 if not comment: 1735 #try Analyse comment 1736 comment=debugger.Getcomment(address,NM_ANALYSE) 1737 else: 1738 #Let the user pick the comment type 1739 comment=debugger.Getcomment(address,type) 1740 1741 return comment
1742 1743 1744 #If you are unsure about what kind of comment are you looking for, 1745 #dont use this methods, and go for the automatic one "getComment(address)" 1746
1747 - def getUserComment(self,address):
1748 return debugger.Getcomment(address,NM_COMMENT)
1749
1750 - def getArgumentsComment(self,address):
1751 return debugger.Getcomment(address,NM_ARG)
1752
1753 - def getAnalyseComment(self,address):
1754 return debugger.Getcomment(address,NM_ANALYSE)
1755
1756 - def getLibraryComment(self,address):
1757 return debugger.Getcomment(address,NM_LIBCOMM)
1758 1759
1760 - def setComment(self, address, comment):
1761 """ 1762 Set a comment. 1763 1764 @type address: DWORD 1765 @param address: Address of the Comment 1766 1767 @type comment: STRING 1768 @param comment: Comment to add 1769 """ 1770 return debugger.Setcomment(address, comment)
1771
1772 - def setLabel(self, address, label):
1773 """ 1774 Set a label. 1775 1776 @type adresss: DWORD 1777 @param address: Address to the new label 1778 1779 @type label: STRING 1780 @param label: Label to add 1781 """ 1782 return debugger.Setlabel(address, label)
1783
1784 - def markBegin(self):
1785 """ 1786 Place a start mark for timming your script 1787 """ 1788 self.timer=time.clock()
1789
1790 - def markEnd(self):
1791 """ 1792 Place an End mark for timming your script 1793 1794 @rtype time: DWORD 1795 @return time: time in seconds 1796 """ 1797 if self.timer >0: 1798 return time.clock() - self.timer 1799 else: 1800 return 0
1801
1802 - def findDependecies(self, lookfor):
1803 """ 1804 Find exported function on the loaded dlls. 1805 1806 @type lookfor: TABLE of DWORD 1807 @param lookfor: Table of functions to search 1808 1809 @rtype: DICTIONARY 1810 @return: Dictionary 1811 """ 1812 #lookfor = ["rpcrt4.rpcserveruseprotseq","rpcrt4.rpcserveruseprotseqex","rpcrt4.rpcserveruseprotseqw", "rpcrt4.rpcserveruseprotseqEp", "rpcrt4.rpcserveruseprotseqif",\ 1813 # "rpcrt4.rpcserveruseallprotseqs", "rpcrt4.rpcserveruseallprotseqsif", "rpcrt4.rpcserveruseprotseqepw",\ 1814 # "rpcrt4.rpcserveruseprotseqepexw", "rpcrt4.rpcserveruseallprotseqsifw"] 1815 symbol = self.getAllSymbols() 1816 1817 result = {} 1818 for modname in symbol.keys(): 1819 modsym = symbol[modname] 1820 for modaddr in modsym.keys(): 1821 mod = modsym[modaddr] 1822 if mod.name.lower() in lookfor: 1823 if mod.type == "Import": 1824 if result.has_key(modname): 1825 result[modname].append(mod) 1826 else: 1827 result[modname] = [mod] 1828 return result
1829 1830 1831
1832 - def isvmWare(self):
1833 """ 1834 Check if debugger is running under a vmware machine 1835 1836 @rtype: DWORD 1837 @return: 1 if vmware machine exists 1838 """ 1839 return debugger.checkvmWare()
1840 1841 1842 1843 1844 1845 ### Breakpoint Functions ### 1846 # All kind of breakpoint functions 1847 1848 # For manual breakpoints: 1849 # key shiftkey Action 1850 # VK_F2 0 Toggle unconditional breakpoint 1851 # VK_F2 Pressed (not 0) Set conditional breakpoint 1852 # VK_F4 Pressed (not 0) Set logging breakpoint 1853
1854 - def ManualBreakpoint(self, address, key, shiftkey, font):
1855 """ 1856 Set a Manual Breakpoint. 1857 1858 @type address: DWORD 1859 @param address: Address of the breakpoint 1860 1861 @type key: DWORD 1862 @param key: VK_F2 (Conditional Breakpoint) or VK_F4 (Logging Breakpoint) 1863 1864 @type shiftkey: DWORD 1865 @param shiftkey: State of the shiftkey 1866 1867 @type font: STRING 1868 @param font: See ImmFonts 1869 """ 1870 if not ImmFonts.has_key( font.lower() ): 1871 font = ImmFonts[ "fixed" ] 1872 else: 1873 font = ImmFonts[ font.lower() ] 1874 1875 return debugger.Manualbreakpoint(address, key, int(shiftkey), font)
1876
1877 - def setUnconditionalBreakpoint(self, address, font="fixed"):
1878 """ 1879 Set an Unconditional Breakpoint. 1880 1881 @type address: DWORD 1882 @param address: Address for the breakpoint 1883 1884 @type font: STRING 1885 @param font: (Optional, Def: fixed) Font for the breakpoint 1886 """ 1887 return self.ManualBreakpoint(address, BpKeys["VK_F2"], False, font)
1888
1889 - def setConditionalBreakpoint(self, address, font="fixed"):
1890 """ 1891 Set a Conditional Breakpoint. 1892 1893 @type address: DWORD 1894 @param address: Address for the breakpoint 1895 1896 @type font: STRING 1897 @param font: (Optional, Def: fixed) Font for the breakpoint 1898 """ 1899 return self.ManualBreakpoint(address, BpKeys["VK_F2"], True, font)
1900
1901 - def setLoggingBreakpoint(self, address):
1902 """ 1903 Set a Logging Breakpoint. (This breakpoint will not puase the execution, it will just act as a Watch point" 1904 1905 @type address: DWORD 1906 @param address: Address for the breakpoint 1907 """ 1908 return debugger.Setloggingbreakpoint(address)
1909
1910 - def setWatchPoint(self,address):
1911 """ 1912 Set a watching Breakpoint. 1913 1914 @type address: DWORD 1915 @param address: Address for the watchpoint 1916 """ 1917 return debugger.Setloggingbreakpoint(address)
1918 1919 1920 #define TY_SET 0x00000100 // Code INT3 is in memory 1921 #define TY_ACTIVE 0x00000200 // Permanent breakpoint 1922 #define TY_DISABLED 0x00000400 // Permanent disabled breakpoint 1923 #define TY_ONESHOT 0x00000800 // Temporary stop 1924 #define TY_TEMP 0x00001000 // Temporary breakpoint 1925 #define TY_KEEPCODE 0x00002000 // Set and keep command code 1926 #define TY_KEEPCOND 0x00004000 // Keep condition unchanged (0: remove) 1927 #define TY_NOUPDATE 0x00008000 // Don't redraw breakpoint window 1928 #define TY_RTRACE 0x00010000 // Pseudotype of run trace breakpoint 1929
1930 - def setTemporaryBreakpoint(self, address, continue_execution = False, stoptrace = False):
1931 """ 1932 Set a Temporary Breakpoint. 1933 1934 @type address: DWORD 1935 @param address: Address for the breakpoint 1936 1937 @type continue_execution: BOOLEAN 1938 @param continue_execution: Automatically removes temporary breakpoint when hit and continue execution 1939 1940 @type stoptrace: BOOLEAN 1941 @param stoptrace: Stop any kind of trace or animation when hit 1942 """ 1943 if continue_execution: 1944 flags = BpFlags["TY_TEMP"] | BpFlags["TY_KEEPCOND"] 1945 else: 1946 flags = BpFlags["TY_ONESHOT"] | BpFlags["TY_KEEPCOND"] 1947 if stoptrace: 1948 flags |= BpFlags["TY_STOPAN"] 1949 1950 return debugger.Tempbreakpoint(address, flags)
1951
1952 - def setBreakpoint(self, address):
1953 """ 1954 Set a Breakpoint. 1955 1956 @type address: DWORD 1957 @param address: Address for the breakpoint 1958 """ 1959 flags = BpFlags["TY_ACTIVE"] 1960 return debugger.Setbreakpoint(address, flags, "")
1961
1962 - def setBreakpointOnName(self,name):
1963 """ 1964 Set a Breakpoint. 1965 1966 @type Name: STRING 1967 @param Name: name of the function to bp 1968 1969 @rtype: DWORD 1970 @return: Address of name 1971 """ 1972 return debugger.Setbreakpointonname(name)
1973
1974 - def disableBreakpoint(self, address):
1975 """ 1976 Disable Breakpoint. 1977 1978 @type address: DWORD 1979 @param address: Address for the breakpoint 1980 """ 1981 flags = BpFlags["TY_DISABLED"] 1982 return debugger.Setbreakpoint(address, flags, "")
1983
1984 - def deleteBreakpoint(self,address,address2=0):
1985 """ 1986 Delete Breakpoint. 1987 1988 @type address: DWORD 1989 @param address: Start range of addresses to delete breakpoints 1990 @type address2: DWORD 1991 @param Address: End range of addresses to delete breakpoints 1992 """ 1993 return debugger.DeleteBreakpoints(address,address2)
1994 1995
1996 - def getBreakpointType(self, address):
1997 """ 1998 Get the Breakpoint type. 1999 2000 @type address: DWORD 2001 @param address: Address for the breakpoint 2002 2003 @rtype: STRING 2004 @return: Breakpoint type 2005 """ 2006 2007 type = debugger.Getbreakpointtypecount(address) 2008 for a in BpFlags.keys(): 2009 if BpFlags[a] == type: 2010 return a 2011 return ""
2012
2013 - def setMemBreakpoint(self,addr, type, size=4):
2014 """ 2015 Modifies or removes a memory breakpoint. 2016 2017 @type address: DWORD 2018 @param address: Address for the breakpoint 2019 2020 @type type: DWORD 2021 @param type: Type of Memory Breakpoint (READ/WRITE/SFX) 2022 2023 @type size: DWORD 2024 @param size: (Optional, Def: 4) Size of Memory Breakpoint 2025 """ 2026 ty = type.strip().split("|") 2027 flags = 0 2028 for a in ty: 2029 try: 2030 flags |= BpMemFlags[a] 2031 except KeyError: 2032 raise Exception("Bad Flags for setMembreakpoint: %s" % type) 2033 2034 return debugger.Setmembreakpoint(flags, addr, size)
2035
2036 - def disableMemBreakpoint(self, addr):
2037 """ 2038 Disable Memory Breakpoint. 2039 """ 2040 return debugger.Setmembreakpoint(0, addr,0)
2041 2042
2043 - def setHardwareBreakpoint(self,addr,type=HB_CODE,size=1):
2044 """ 2045 Sets Hardware breakpoint 2046 """ 2047 return debugger.Sethardwarebreakpoint(type,addr,size)
2048 2049 2050 ### Read/Write/Search ### 2051 # Read/Write from process memory 2052
2053 - def writeLong(self, address, dword):
2054 """ 2055 Write long to memory address. 2056 2057 @type address: DWORD 2058 @param address: Address 2059 2060 @type dword: DWORD 2061 @param dword: long to write 2062 """ 2063 return debugger.Writememory( immutils.intel_order( dword ), address, 4, 0x2 )
2064
2065 - def writeMemory(self, address, buf):
2066 """ 2067 Write buffer to memory address. 2068 2069 @type address: DWORD 2070 @param address: Address 2071 2072 @type buf: BUFFER 2073 @param buf: Buffer 2074 """ 2075 return debugger.Writememory(buf, address, len(buf), 0x2)
2076
2077 - def readMemory(self, address, size):
2078 """ 2079 Read block of memory. 2080 2081 @type address: DWORD 2082 @param address: Address 2083 2084 @type size: DWORD 2085 @param size: Size 2086 2087 @rtype: BUFFER 2088 @return: Process memory 2089 """ 2090 return debugger.Readmemory(address, size, 0x01|0x02)
2091
2092 - def readLong(self, address):
2093 """ 2094 Read a Long from the debugged process 2095 2096 @type address: DWORD 2097 @param address: Address 2098 2099 @rtype: DWORD 2100 @return: Long 2101 """ 2102 long = self.readMemory(address, 0x4) 2103 if len(long) == 4: 2104 try: 2105 return immutils.str2int32_swapped(long) 2106 except ValueError: 2107 raise Exception, "readLong failed to gather a long at 0x%08x" % address 2108 else: 2109 raise Exception, "readLong failed to gather a long at 0x%08x" % address
2110
2111 - def readString(self, address):
2112 """ 2113 Read a string from the remote process 2114 2115 @type address: DWORD 2116 @param address: Address of the string 2117 2118 @rtype: String 2119 @return: String 2120 """ 2121 return self.readUntil(address, '\x00')
2122
2123 - def readWString(self,address):
2124 """ 2125 Read a unicode string from the remote process 2126 2127 @type address: DWORD 2128 @param address: Address of the unicode string 2129 2130 @rtype: Unicode String 2131 @return: Unicode String 2132 """ 2133 wstring = self.readUntil(address, "\x00\x00") 2134 2135 if not wstring.endswith("\x00"): 2136 wstring = wstring + "\x00" 2137 2138 return wstring
2139
2140 - def readUntil(self, address, ending):
2141 """ 2142 Read string until ending starting at given address 2143 2144 @param Address: Start address 2145 @return Readed String 2146 """ 2147 readed=[] 2148 while(1): 2149 read = self.readMemory( address, 16 ) 2150 address += 16 2151 ndx = read.find(ending) 2152 if ndx != -1: 2153 readed.append( read[0:ndx] ) 2154 break 2155 else: 2156 readed.append( read ) 2157 2158 return string.joinfields(readed, "")
2159
2160 - def readShort(self, address):
2161 """ 2162 Read a short integer from the remote process 2163 2164 @type address: DWORD 2165 @param address: Address of the short 2166 2167 @rtype: Short Integer 2168 @return: Short 2169 """ 2170 short = self.readMemory(address, 0x2) 2171 return immutils.str2int16_swapped(short)
2172
2173 - def searchShort(self, short , flag=None):
2174 """ 2175 Search a short integer on the remote process memory 2176 2177 @type short: SHORT 2178 @param short: Short integer to search for 2179 2180 @type flag: STRING 2181 @param flag: Memory Protection String Flag 2182 2183 @rtype: List 2184 @return: List of address of the short integer founded 2185 """ 2186 return self.Search(immutils.int2str16_swapped(short),flag)
2187
2188 - def searchLong(self, long, flag=None):
2189 """ 2190 Search a short integer on the remote process memory 2191 2192 @type long: DWORD 2193 @param long: integer to search for 2194 @type flag: STRING 2195 @param flag: Memory Protection String Flag 2196 2197 @rtype: List 2198 @return: List of address of the integer founded 2199 """ 2200 return self.Search( immutils.int2str32_swapped(long),flag) 2201
2202 - def searchOnExecute(self,buf):
2203 """ 2204 Search string in executable memory. 2205 2206 @param buf: Buffer to search for 2207 @return: A list of address where the string was found on memory 2208 """ 2209 if not buf: 2210 return [] 2211 self.getMemoryPages() 2212 find = [] 2213 buf_size = len(buf) 2214 for a in self.MemoryPages.keys(): 2215 if (MemoryProtection["PAGE_EXECUTE"] == self.MemoryPages[a].access\ 2216 or MemoryProtection["PAGE_EXECUTE_READ"] == self.MemoryPages[a].access\ 2217 or MemoryProtection["PAGE_EXECUTE_READWRITE"] == self.MemoryPages[a].access\ 2218 or MemoryProtection["PAGE_EXECUTE_WRITECOPY"] == self.MemoryPages[a].access): 2219 mem = self.MemoryPages[a].getMemory() 2220 if not mem: 2221 continue 2222 ndx = 0 2223 while 1: 2224 f = mem[ndx:].find( buf ) 2225 if f == -1 : break 2226 find.append( ndx + f + a ) 2227 ndx += f + buf_size 2228 return find
2229
2230 - def searchOnWrite(self,buf):
2231 """ 2232 Search string in writable memory. 2233 2234 @param buf: Buffer to search for 2235 @return: A list of address where the string was found on memory 2236 """ 2237 if not buf: 2238 return [] 2239 self.getMemoryPages() 2240 find = [] 2241 buf_size = len(buf) 2242 for a in self.MemoryPages.keys(): 2243 if (MemoryProtection["PAGE_READWRITE"] == self.MemoryPages[a].access\ 2244 or MemoryProtection["PAGE_WRITECOPY"] == self.MemoryPages[a].access\ 2245 or MemoryProtection["PAGE_EXECUTE_READWRITE"] == self.MemoryPages[a].access\ 2246 or MemoryProtection["PAGE_EXECUTE_WRITECOPY"] == self.MemoryPages[a].access): 2247 mem = self.MemoryPages[a].getMemory() 2248 if not mem: 2249 continue 2250 ndx = 0 2251 while 1: 2252 f = mem[ndx:].find( buf ) 2253 if f == -1 : break 2254 find.append( ndx + f + a ) 2255 ndx += f + buf_size 2256 return find
2257
2258 - def searchOnRead(self,buf):
2259 """ 2260 Search string in readable memory. 2261 2262 @param buf: Buffer to search for 2263 @return: A list of address where the string was found on memory 2264 """ 2265 if not buf: 2266 return [] 2267 self.getMemoryPages() 2268 find = [] 2269 buf_size = len(buf) 2270 for a in self.MemoryPages.keys(): 2271 if (MemoryProtection["PAGE_READONLY"] == self.MemoryPages[a].access\ 2272 or MemoryProtection["PAGE_EXECUTE_READ"] == self.MemoryPages[a].access): 2273 mem = self.MemoryPages[a].getMemory() 2274 if not mem: 2275 continue 2276 ndx = 0 2277 while 1: 2278 f = mem[ndx:].find( buf ) 2279 if f == -1 : break 2280 find.append( ndx + f + a ) 2281 ndx += f + buf_size 2282 return find
2283 2284 2285 2286 2287
2288 - def Search(self, buf,flag=None):
2289 """ 2290 Search string in memory. 2291 2292 @param buf: Buffer to search for 2293 @param flag: Memory Protection String Flag 2294 @return: A list of address where the string was found on memory 2295 2296 2297 """ 2298 if not buf: 2299 return [] 2300 2301 self.getMemoryPages() 2302 find = [] 2303 buf_size = len(buf) 2304 for a in self.MemoryPages.keys(): 2305 if flag: 2306 if (MemoryProtection[flag] == self.MemoryPages[a].access): 2307 mem = self.MemoryPages[a].getMemory() 2308 if not mem: 2309 continue 2310 ndx = 0 2311 while 1: 2312 f = mem[ndx:].find( buf ) 2313 if f == -1 : break 2314 find.append( ndx + f + a ) 2315 ndx += f + buf_size 2316 else: 2317 mem = self.MemoryPages[a].getMemory() 2318 if not mem: 2319 continue 2320 ndx = 0 2321 while 1: 2322 f = mem[ndx:].find( buf ) 2323 if f == -1 : break 2324 find.append( ndx + f + a ) 2325 ndx += f + buf_size 2326 return find
2327
2328 - def searchCommands(self, cmd):
2329 """ 2330 Search for a sequence of commands in all executable modules loaded. 2331 @type cmd: STRING 2332 @param cmd: Assembly code to search for (Search using regexp is available. See Documentation) 2333 2334 @rtype: List 2335 @return: List of address of the command found 2336 2337 NOTE: Since ImmunityDebugger 1.2 , the returning tuple[1] value is deprecated, 2338 if you need the opcode string of the resulted address, you'll have to do a immlib.Disasm(tuple[0]). 2339 2340 """ 2341 address=0 # all loaded modules 2342 return debugger.Searchregexp(address,cmd)
2343
2344 - def searchCommandsOnModule(self,address,cmd):
2345 """ 2346 Search for a sequence of commands in given executable module. 2347 @type cmd: STRING 2348 @param cmd: Assembly code to search for (Search using regexp is available. See Documentation) 2349 2350 @rtype: List 2351 @return: List of address of the command found 2352 2353 NOTE: Since ImmunityDebugger 1.2 , the returning tuple[1] value is deprecated, 2354 if you need the opcode string of the resulted address, you'll have to do a immlib.Disasm(tuple[0]). 2355 2356 """ 2357 return debugger.Searchregexp(address,cmd)
2358 2359 ### Execution control ### 2360 # All kind of functions that interact with code execution 2361
2362 - def Run(self, address=0):
2363 """Run Process untill address. 2364 @param address: Address""" 2365 self.clearState() 2366 return debugger.Run(address)
2367
2368 - def runTillRet(self):
2369 """Run Process till ret. 2370 """ 2371 self.clearState() 2372 return debugger.Runtillret()
2373 2374
2375 - def Pause(self):
2376 """Pause process""" 2377 return debugger.Pause()
2378
2379 - def stepOver(self, address=0):
2380 """ 2381 Step-Over Process untill address. 2382 2383 @type address: DWORD 2384 @param address: (Optional, Def = 0) Address 2385 """ 2386 self.clearState() 2387 return debugger.Stepover(address)
2388
2389 - def stepIn(self, address=0):
2390 """ 2391 Step-in Process untill address. 2392 2393 @type address: DWORD 2394 @param address: (Optional, Def = 0) Address 2395 """ 2396 self.clearState() 2397 return debugger.Stepin(address)
2398
2399 - def quitDebugger(self):
2400 """ 2401 Quits debugger 2402 """ 2403 return debugger.exitID()
2404 2405
2406 - def ignoreSingleStep(self,flag="CONTINUE"):
2407 """ 2408 Ignore Single Step events 2409 @type flag: STRING 2410 @param flag: How to continue after a single event is catched 2411 flag = DISABLE : Disable ignoring 2412 flag = FORCE : Conventional Force continue method 2413 flag = CONTINUE : Transparent continue method 2414 2415 CAUTION: This method overrides GUI option 'single-step break' 2416 """ 2417 return debugger.IgnoreSingleStep(IgnoreSingleStep[flag])
2418 2419 #Consider the following three methods of experimental nature.
2420 - def openProcess(self, path,mode=0):
2421 """ 2422 Open process for debugging 2423 @type path: STRING 2424 @param path: Path to file to debug 2425 @type mode: INTEGER 2426 @param mode: How to start: -2 SILENT, 0 NORMAL 2427 """ 2428 return debugger.Open(path,mode)
2429
2430 - def restartProcess(self,mode=-1):
2431 """ 2432 Restart debuggee 2433 @type mode: INTEGER 2434 @param mode: How to restart : -2 SILENT, -1 MSGBOX 2435 2436 """ 2437 return debugger.Open("",mode)
2438 2439
2440 - def Attach(self, pid):
2441 """ 2442 Attach to an active process 2443 @type pid: INTEGER 2444 @param pid: Process Id. 2445 """ 2446 return debugger.Attach(pid)
2447
2448 - def Dettach(self):
2449 """ 2450 Dettach from active process 2451 """ 2452 #this methos is still very experimental 2453 return debugger.Dettach()
2454 2455
2456 - def prepareForNewProcess(self):
2457 """ 2458 Prepare Debugger for fresh debugging session 2459 NOTE: be sure to know what you are doing when 2460 calling this method 2461 """ 2462 return debugger.Preparefornewps()
2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 ### GUI interaction ### 2476 # Whatever interaction on the gui 2477
2478 - def goSilent(self,silent):
2479 """ Set/Unset silent debugging flag 2480 @type silent: INTEGER 2481 @param silent: 1 to set silent, 0 to unset 2482 """ 2483 return debugger.GoSilent(silent)
2484
2485 - def addHeader(self,address,header,color="Black"):
2486 """ 2487 Add a header to given row. 2488 @type address: DWORD 2489 @param address: Address to add the header into 2490 @type header: STRING 2491 @param header: Header string to add into row 2492 @type color: STRING 2493 @param color: Color of text 2494 """ 2495 return debugger.AddHeaderToRow(address,header,ImmDrawColors[color])
2496
2497 - def removeHeader(self,address):
2498 """ 2499 Removes header from row. 2500 @type address: DWORD 2501 @param address: Address to remove the header from 2502 """ 2503 return debugger.RemoveHeaderFromRow(address)
2504
2505 - def removeLine(self,address):
2506 """ 2507 Removes header from row. 2508 @type address: DWORD 2509 @param address: Address to remove the header from 2510 """ 2511 return debugger.RemoveHeaderFromRow(address)
2512
2513 - def getHeader(self,address):
2514 """ 2515 Get Header from row. 2516 @type address: DWORD 2517 @param address: Address to get the headers from 2518 @return PYLIST: List of strings 2519 """ 2520 return debugger.GetHeaderFromRow(address)
2521 2522 2523 2524
2525 - def addLine(self,address,header,color="Black"):
2526 """ 2527 Add a line to cpu window. 2528 @type address: DWORD 2529 @param address: Address to add line 2530 @type header: STRING 2531 @param header: Header string to add into row 2532 @type color: STRING 2533 @param color: Color of text 2534 """ 2535 return debugger.AddHeaderToRow(address,header,ImmDrawColors[color])
2536 2537
2538 - def gotoDisasmWindow(self, addr):
2539 """ 2540 GoTo the Disassembler Window. 2541 2542 @type addr: DWORD 2543 @param addr: Address to show on the Disassembler Window 2544 """ 2545 return debugger.Setcpu( self.threadid, addr, 0, 0, 0x8000L) # redraw
2546
2547 - def gotoDumpWindow(self, addr):
2548 """ 2549 GoTo Dump Window. 2550 2551 @type addr: DWORD 2552 @param addr: Address to show on the Dump Window 2553 """ 2554 return debugger.Setcpu( self.threadid, 0, addr, 0, 0x8000L) # redraw
2555
2556 - def gotoStackWindow(self, addr):
2557 """ 2558 GoTo the Stack Window. 2559 @type addr: DWORD 2560 @param addr: Address to show on the Stack Window 2561 """ 2562 return debugger.Setcpu( self.threadid, 0, 0, addr, 0x8000L) # redraw
2563
2564 - def inputBox(self,title):
2565 """ 2566 Creates Dialog with an Inputbox. 2567 2568 @type title: STRING 2569 @param title: Title for the Inputbox dialog 2570 2571 @return: String from the inputbox 2572 """ 2573 return debugger.Inputbox(title)
2574
2575 - def comboBox(self,title,combolist):
2576 """ 2577 Creates Dialog with a Combobox. 2578 2579 @type title: STRING 2580 @param title: Title for the dialog 2581 2582 @type combolist: LIST 2583 @param combolist: List of items to add to combo dialog 2584 2585 @return: Selected item 2586 """ 2587 return debugger.Combobox(title,combolist,len(combolist))
2588 2589 2590 2591 ### Debugger State ### 2592 # The state of the debugger 2593
2594 - def getStatus(self):
2595 """ 2596 Get the status of the debugged process. 2597 2598 @return: Status of the debugged process 2599 """ 2600 return debugger.Getstatus()
2601
2602 - def isStopped(self):
2603 """ 2604 Is the debugged process stopped? 2605 2606 @rtype: BOOL 2607 @return: Boolean (True/False) 2608 """ 2609 return DebugerStatus["STOPPED"] == self.getStatus()
2610
2611 - def isEvent(self):
2612 """ 2613 Is the debugged process in an event state? 2614 2615 @rtype: BOOL 2616 @return: Boolean (True/False) 2617 """ 2618 return DebugerStatus["EVENT"] == self.getStatus()
2619
2620 - def isRunning(self):
2621 """ 2622 Is the debugged process running? 2623 2624 @rtype: BOOL 2625 @return: Boolean (True/False) 2626 """ 2627 return DebugerStatus["RUNNING"] == self.getStatus()
2628
2629 - def isFinished(self):
2630 """ 2631 Is the debugged process finished? 2632 2633 @rtype: BOOL 2634 @return: Boolean (True/False) 2635 """ 2636 return DebugerStatus["FINISHED"] == self.getStatus()
2637
2638 - def isClosing(self):
2639 """ 2640 Is the debugged process closed? 2641 2642 @rtype: BOOL 2643 @return: Boolean (True/False) 2644 """ 2645 return DebugerStatus["CLOSING"] == self.getStatus()
2646 2647 2648 2649 ### Hooks ### 2650
2651 - def listHooks(self):
2652 """ 2653 List of active hooks 2654 2655 @rtype: LIST 2656 @return: List of active hooks 2657 """ 2658 return debugger.Listhook()
2659
2660 - def removeHook(self,hook_str):
2661 """Unhook from memory 2662 """ 2663 debugger.Removehook(hook_str)
2664 2665 2666
2667 - def _getHookEntry(self, entry):
2668 tbl = [] 2669 # We need to use HOOK_REG, since some of the original register 2670 # are saved on the stack 2671 try: 2672 reg = HOOK_REG[ entry[0] ] 2673 tbl.append( "MOV EAX, %s" % reg ) 2674 except KeyError: 2675 if entry[0] == 'ESP': 2676 tbl.append("LEA EAX, [ESP+0x14]") 2677 elif type( entry[0] ) == type(0): 2678 tbl.append("MOV EAX, [0x%08x]" % entry[0] ) 2679 else: 2680 return [] 2681 2682 2683 if len(entry) == 2: 2684 tbl.append( "MOV EAX, [EAX + 0x%x]" % entry[1] ) 2685 tbl.append( "STOSD" ) 2686 2687 return tbl
2688 2689 # afterHookAddr = hookAddr + idx 2690 # ndx = function num 2691 # table = [ (reg), (reg, offset) ]
2692 - def _createCodeforHook( self, memAddress, afterHookAddr, ndx, table, execute_prelude, alloc_size):
2693 # SAVING REGS, WE DONT WANT TO TOUCH ANYTHING! 2694 # XXX: Replace it with a PUSHA/POPA 2695 # Add a global deadlock 2696 alloc_stub = [ "PUSHAD" ] # Save all registers 2697 alloc_stub += [ "MOV EBX, 0x%08x" % memAddress ] # 2698 alloc_stub += [ "MOV EDI, [EBX]"] # GETTING A POINTER to top of data 2699 alloc_stub += [ "CMP DWORD DS:[EBX+4],1"] # Check the deadlock 2700 alloc_stub += [ "JZ -C" ] # If its in use, loop 2701 alloc_stub += [ "MOV DWORD DS:[EBX+4],1"] # Turn deadlock on 2702 alloc_stub += [ "MOV EAX, EDI"] 2703 alloc_stub += [ "SUB EAX, EBX"] 2704 alloc_stub += [ "ADD EAX, 0x%08x" % (len(table) * 4 + 4) ] 2705 alloc_stub += [ "CMP EAX, 0x%08x" % alloc_size] # Did we reach the end of memory? 2706 # JE -> JMP TO THE END OF THE FUNCTION 2707 alloc_stub_reg = [ "MOV EAX, 0x%x" % ndx] 2708 alloc_stub_reg += [ "STOSD"] # SAVE IN MEMORY THE FUNCTION NUMBER 2709 for entry in table: 2710 alloc_stub_reg += self._getHookEntry( entry ) # Get all the regs/mem and save them in data 2711 alloc_stub_reg += [ "MOV [EBX], EDI"] # Save the top of the data 2712 alloc_stub_reg += [ "MOV DWORD DS:[EBX+4],0"] # Turn Lock OFF 2713 2714 alloc_stub_pos = [ "POPAD"] # Restore register 2715 # Right here is where the 'saved' instruction 2716 # of the hook are executed 2717 alloc_ret = "PUSH 0x%08x\nRET" % afterHookAddr # Back to the function 2718 2719 code = self.Assemble( "\n".join( alloc_stub ) ) 2720 reg_code = self.Assemble( "\n".join( alloc_stub_reg ) ) 2721 code += "\x0f\x83" + struct.pack("L", len(reg_code) ) 2722 code += reg_code 2723 code += self.Assemble( "\n".join( alloc_stub_pos ) ) 2724 code += execute_prelude 2725 code += self.Assemble( alloc_ret ) 2726 2727 return code
2728 2729
2730 - def addFastLogHook(self, hook, alloc_size = 0x100000):
2731 CODE_HOOK_START = 8 2732 flh = hook 2733 # Get the table of functions from the hook 2734 table = flh.get() 2735 # Allocate memory for the hook and the log 2736 memAddress = self.remoteVirtualAlloc( alloc_size ) 2737 self.Log( "Logging at 0x%08x" % memAddress ) 2738 2739 # MEMORY LOOKS LIKE: 2740 # mem [ ptr to data ] 2741 # mem + 4 [ deadlock ] 2742 # mem + 8 [ start of hook code ] 2743 # mem + n [ ... ] 2744 # mem + n [ start of data ] 2745 2746 ptr = memAddress + CODE_HOOK_START 2747 2748 fn_restore = [] 2749 2750 for fn_ndx in range( 0, len(table) ): 2751 hookAddress = table[ fn_ndx ][0] 2752 entry = table[ fn_ndx ][1] 2753 2754 idx = 0 2755 #patch_code = self.Assemble( "PUSH 0x%08x\nRET" % ptr ) 2756 patch_code = self.Assemble( "JMP 0x%08x" % ptr, address = hookAddress) 2757 2758 while idx < len(patch_code): 2759 op = self.Disasm( hookAddress + idx ) 2760 if op.isCall() or op.isJmp(): 2761 op = None 2762 break 2763 2764 idx += op.getOpSize() 2765 if not op: 2766 continue 2767 2768 2769 ex_prelude = self.readMemory( hookAddress, idx ) 2770 2771 code = self._createCodeforHook( memAddress, hookAddress + idx,\ 2772 fn_ndx + 1, entry, ex_prelude, alloc_size) 2773 2774 self.writeMemory( ptr , code ) 2775 ptr+= len(code) 2776 self.writeMemory( hookAddress, patch_code ) 2777 2778 fn_restore.append( ex_prelude ) # Correspond in index with function address 2779 2780 if ptr % 4: 2781 ptr = 4 + ptr & ~(4-1) 2782 hook.setMem( ptr ) 2783 self.writeLong( memAddress, ptr ) 2784 2785 hook.setRestore( fn_restore ) 2786 2787 2788 2789 ### Remote Allocation/Deallocation ### 2790
2791 - def rVirtualAlloc(self, lpAddress, dwSize, flAllocationType, flProtect):
2792 """ 2793 Virtual Allocation on the Debugged Process 2794 2795 @type lpAddress: DWORD 2796 @param lpAddress: Desired starting Address 2797 2798 @type dwSize: DWORD 2799 @param dwSize: Size of the memory to be allocated (in bytes) 2800 2801 @type flAllocationType: DWORD 2802 @param flAllocationType: Type of Memory Allocation (MEM_COMMIT, MEM_RESERVED, MEM_RESET, etc) 2803 2804 @type flProtect: DWORD 2805 @param flProtect: Flag protection of the memory allocated 2806 2807 @rtype: DWORD 2808 @return: Address of the memory allocated 2809 """ 2810 return debugger.pVirtualAllocEx( lpAddress, dwSize, flAllocationType, flProtect )
2811 2812 # default dwFreetype == MEM_RELEASE
2813 - def rVirtualFree(self, lpAddress, dwSize = 0x0, dwFreeType = 0x8000):
2814 """ 2815 Virtual Free of memory on the Debugged Process 2816 2817 @type size: DWORD 2818 @param size: (Optional, Def: 0) Size of the memory to free 2819 2820 @type dwFreeType: DWORD 2821 @param dwFreeType: (Optional, Def: MEM_RELEASE) Type of Free operation 2822 2823 @rtype: DWORD 2824 @return: On Successful, returns a non zero value 2825 """ 2826 return debugger.pVirtualFreeEx( lpAddress, dwSize, dwFreeType )
2827
2828 - def remoteVirtualAlloc(self, size = 0x10000, interactive = True):
2829 """ 2830 Virtual Allocation on the Debugged Process 2831 2832 @type size: DWORD 2833 @param size: (Optional, Def: 0x10000) Size of the memory to allocated, in bytes 2834 2835 @rtype: DWORD 2836 @return: Address of the memory allocated 2837 """ 2838 2839 return self.rVirtualAlloc( 0x0, size, 0x1000, 0x40)
2840 2841 ### OS information ###
2842 - def getOsVersion(self):
2843 return self.osversion
2844
2845 - def getOsRelease(self):
2846 return self.osrelease
2847
2848 - def getOsInformation(self):
2849 """ 2850 Get OS information 2851 2852 @rtype: TUPLE 2853 @return: List with ( system, release, version) 2854 """ 2855 import platform 2856 return (platform.system(),platform.release(),platform.version())
2857
2858 - def getThreadId(self):
2859 """ 2860 Return current debuggee thread id 2861 2862 @trype: LONG 2863 @return: Thread ID 2864 """ 2865 return debugger.GetThreadId()
2866 2867 2868 ### Accessing Recognition Routines ### 2869
2870 - def searchFunctionByName(self, name, heuristic = 90, module = None, version = None, data=""):
2871 """ 2872 Look up into our dictionaries to find a function match. 2873 2874 @type name: STRING 2875 @param name: Name of the function to search 2876 2877 @type module: STRING 2878 @param module: name of a module to restrict the search 2879 2880 @type version: STRING 2881 @param version: restrict the search to the given version 2882 2883 @type heuristic: INTEGER 2884 @param heuristic: heuristic threasold to consider a real function match 2885 2886 @type data: STRING|LIST 2887 @param data: Name (or list of names) of the .dat file inside the Data folder, where're stored the function 2888 patterns. Use an empty string to use all the files in the Data folder. 2889 2890 @rtype: DWORD|None 2891 @return: the address of the function or None if we can't find it 2892 """ 2893 recon = FunctionRecognition(self, data) 2894 return recon.searchFunctionByName(name, heuristic , module, version )
2895
2896 - def searchFunctionByHeuristic(self, csvline, heuristic = 90, module = None, data=""):
2897 """ 2898 Search memory to find a function that fullfit the options. 2899 2900 @type csvline: STRING 2901 @param csvline: A line of a Data CSV file. This's a simple support for copy 'n paste from a CSV file. 2902 2903 @type heuristic: INTEGER 2904 @param heuristic: heuristic threasold to consider a real function match 2905 2906 @type module: STRING 2907 @param module: name of a module to restrict the search 2908 2909 @type data: STRING|LIST 2910 @param data: Name (or list of names) of the .dat file inside the Data folder, where're stored the function 2911 patterns. Use an empty string to use all the files in the Data folder. 2912 2913 @rtype: DWORD|None 2914 @return: the address of the function or None if we can't find it 2915 """ 2916 2917 recon = FunctionRecognition(self, data) 2918 return recon.searchFunctionByHeuristic(csvline, heuristic , module )
2919
2920 - def resolvFunctionByAddress(self, address, heuristic=90,data=""):
2921 """ 2922 Look up into our dictionaries to find a function match. 2923 2924 @type address: DWORD 2925 @param address: Address of the function to search 2926 2927 @type heuristic: INTEGER 2928 @param heuristic: heuristic threasold to consider a real function match 2929 2930 @type data: STRING|LIST 2931 @param data: Name (or list of names) of the .dat file inside the Data folder, where're stored the function 2932 patterns. Use an empty string to use all the files in the Data folder. 2933 2934 @rtype: STRING 2935 @return: a STRING with the function's real name or the given address if there's no match 2936 """ 2937 recon = FunctionRecognition(self,data) 2938 return recon.resolvFunctionByAddress(address, heuristic,data)
2939
2940 - def makeFunctionHashHeuristic(self, address, compressed = False, followCalls = True, data=""):
2941 """ 2942 @type address: DWORD 2943 @param address: address of the function to hash 2944 2945 @type compressed: Boolean 2946 @param compressed: return a compressed base64 representation or the raw data 2947 2948 @type followCalls: Boolean 2949 @param followCalls: follow the first call in a single basic block function 2950 2951 @type data: STRING|LIST 2952 @param data: Name (or list of names) of the .dat file inside the Data folder, where're stored the function 2953 patterns. Use an empty string to use all the files in the Data folder. 2954 2955 @rtype: LIST 2956 @return: the first element is described below and the second is the result of this same function but over the first 2957 call of a single basic block function (if applies), each element is like this: 2958 a base64 representation of the compressed version of each bb hash: 2959 [4 bytes BB(i) start][4 bytes BB(i) 1st edge][4 bytes BB(i) 2nd edge] 2960 0 <= i < BB count 2961 or the same but like a LIST with raw data. 2962 """ 2963 recon = FunctionRecognition(self, data) 2964 return FunctionRecognition.makeFunctionHashHeuristic(address, compressed, followCalls)
2965
2966 - def makeFunctionHashExact(self, address,data=""):
2967 """ 2968 Return a SHA-1 hash of the function, taking the raw bytes as data. 2969 2970 @type address: DWORD 2971 @param address: address of the function to hash 2972 2973 @type data: STRING|LIST 2974 @param data: Name (or list of names) of the .dat file inside the Data folder, where're stored the function 2975 patterns. Use an empty string to use all the files in the Data folder. 2976 2977 @rtype: STRING 2978 @return: SHA-1 hash of the function 2979 """ 2980 2981 recon = FunctionRecognition(self,data) 2982 return recon.makeFunctionHashExact(address)
2983
2984 - def makeFunctionHash(self, address, compressed = False,data=""):
2985 """ 2986 Return a list with the best BB to use for a search and the heuristic hash 2987 of the function. This two components are the function hash. 2988 2989 @type address: DWORD 2990 @param address: address of the function to hash 2991 2992 @type compressed: Boolean 2993 @param compressed: return a compressed base64 representation or the raw data 2994 2995 @type data: STRING|LIST 2996 @param data: Name (or list of names) of the .dat file inside the Data folder, where're stored the function 2997 patterns. Use an empty string to use all the files in the Data folder. 2998 2999 @rtype: LIST 3000 @return: 1st element is the generalized instructions to use with searchCommand 3001 2nd element is the heuristic function hash (makeFunctionHashHeuristic) 3002 3rd element is an exact hash of the function (makeFunctionHashExact) 3003 """ 3004 recon = FunctionRecognition(self,data) 3005 return recon.makeFunctionHash(address, compressed)
3006 3007 3008 ### Accessing Control Flow Analysis Routines ### 3009
3010 - def findLoops(self, address):
3011 """ 3012 This function finds Natural Loops inside a function. 3013 3014 Each loop item has the following structure: 3015 [ start, end, nodes ] 3016 start: address of node receiving the back edge. 3017 end: address of node which has the back edge. 3018 node: list of node's addresses involved in this loop. 3019 3020 @type address: DWORD 3021 @param address: function start address 3022 3023 @rtype: LIST 3024 @return: A list of loops 3025 """ 3026 3027 cfa = ControlFlowAnalysis(self, address) 3028 return cfa.findNaturalLoops()
3029 3030
3031 - def sleep_till_stopped(self, timeout):
3032 """ 3033 timeout is in seconds. this function will sleep 1 second at a time until timeout is reached 3034 or the debugger has stopped (probably due to AV) 3035 returns True if we were stopped before timeout happened 3036 """ 3037 for i in xrange(timeout): 3038 #sleep 1 second at a time 3039 if self.isStopped(): 3040 return True 3041 if self.isEvent(): 3042 return True 3043 3044 time.sleep(1) 3045 return False
3046