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 """