Package Libs ::
Module libhook
|
|
1
2
3 """
4 (c) Immunity, Inc. 2004-2007
5
6
7 U{Immunity Inc.<http://www.immunityinc.com>}
8
9
10 """
11
12 __VERSION__ = '1.1'
13
14 import struct
15 import debugger
16 import pickle
17
18 FS_UNHOOK = 0
19 FS_HOOK = 1
20 FS_PAUSE = 2
21
22 HookTypes = {"ORDINARY_BP_HOOK" : 3900, "LOG_BP_HOOK" : 3909,\
23 "EVERY_EXCEPTION_HOOK" : 3901,\
24 "POST_ANALYSIS_HOOK" : 3902, "ACCESS_VIOLATION_HOOK": 3910,\
25 "LOAD_DLL_HOOK" : 3903, "UNLOAD_DLL_HOOK" : 3904,\
26 "CREATE_THREAD_HOOK" : 3905, "EXIT_THREAD_HOOK" : 3906,\
27 "CREATE_PROCESS_HOOK" : 3907, "EXIT_PROCESS_HOOK" : 3908,\
28 "PRE_BP_HOOK" : 3911}
29
30 HOOK_REG = {'ESI': '[ESP+4 ]', 'EDI': '[ESP]',\
31 'EBX': '[ESP+0x10]', 'EAX': '[ESP+0x1C]',\
32 'ECX': '[ESP+0x18]', 'EDX': '[ESP+0x14]',\
33 'EBP': '[ESP+0x8 ]', 'ESP': '[ESP+0xC ]'}
34
35
38 self.address = None
39 self.tbl = []
40 self.list = []
41 self.entry = []
42 self.hooked = False
43 self.mem = None
44 self.imm = imm
45 self.restore = []
46 self.status = FS_UNHOOK
47 self.AllocSize = 0
48 self.memAddress = 0
49
52
55
57 if not self.isHooked():
58 return False
59
60
61 for ndx in range(0, len(self.tbl) ):
62 self.imm.writeMemory( self.tbl[ndx][0], self.restore[ndx][0] )
63
64 self.status = FS_PAUSE
65 return True
66
68 if not self.isPause():
69 return False
70
71 for ndx in range(0, len(self.tbl) ):
72 self.imm.writeMemory( self.tbl[ndx][0], self.restore[ndx][1] )
73 self.status = FS_HOOK
74 return True
75
77 if not self.isHooked():
78 return False
79
80
81 for ndx in range(0, len(self.tbl) ):
82 self.imm.writeMemory( self.tbl[ndx][0], self.restore[ndx][0] )
83 self.imm.rVirtualFree( self.mem )
84 self.status = FS_UNHOOK
85 return True
86
88 self.restore = restore
89
94
97
99 if self.address:
100 self.tbl.append( (self.address, self.entry) )
101 self.entry = []
102 self.address = address
103
105 self.entry.append( (REG,) )
106
108 self.entry.append( (address,) )
109
111 self.entry.append( ( REG, offset) )
112
114 ndx = 0
115 addr = self.mem
116 self._fn = {}
117 self.ret = []
118
119 while ndx != -1 :
120 mem = self.imm.readMemory( addr, 0x1000)
121 ndx = self._parseUniqueFn( mem )
122 addr += ndx
123
124 return self._fn
125
127 mem = ""
128 self.ret = []
129 flag = False
130 addr = self.mem
131 end = self.imm.readLong(self.memAddress)
132
133 mem = self.imm.readMemory( addr, end-addr)
134 self._parseMem( mem )
135
136 return self.ret
137
139 mem_size = len(mem)
140 ndx = 0
141 while ndx < len(mem):
142 index = struct.unpack("L", mem[ ndx : ndx+4 ] )[0]
143 if index == 0:
144 return -1
145 if index > (len(self.tbl) + 1) :
146 return -1
147
148 entry = self.tbl[ index -1 ][1]
149 ndx += 4
150 size_e = len(entry)
151 if (size_e*4 + ndx) > ( mem_size):
152 return ndx - 4
153 ndx += size_e * 4
154
155 addr = self.tbl[ index -1 ][0]
156 if self._fn.has_key( addr ):
157 self._fn[ addr ] += 1
158 else:
159 self._fn[ addr ] = 1
160 return ndx
161
162
164
165 self.imm.writeLong( self.memAddress, self.mem )
166
167
169 mem_size = len(mem)
170 ndx = 0
171
172 while ndx < len(mem) :
173 index = struct.unpack("L", mem[ ndx : ndx+4 ] )[0]
174
175 if index == 0:
176 return -1
177 if index > (len(self.tbl) + 1) :
178 return -1
179
180 entry = self.tbl[ index -1 ][1]
181 ndx += 4
182 size_e = len(entry)
183 if (size_e*4 + ndx) > ( mem_size):
184 return ndx - 4
185 ret = struct.unpack( "L" * size_e, mem[ ndx : ndx + size_e *4 ] )
186 ndx += size_e * 4
187 self.ret.append( ( self.tbl[ index - 1 ][0], ret) )
188 return ndx
189
193
196
198 CODE_HOOK_START = 8
199
200
201 self.AllocSize = alloc_size
202
203 table = self.get()
204 self.imm.log("TABLE SIZE: %d" % len(table) )
205
206 if not memAddress:
207 memAddress = self.imm.remoteVirtualAlloc( alloc_size )
208
209 self.memAddress = memAddress
210
211 self.imm.log( "Logging at 0x%08x" % memAddress )
212
213
214
215
216
217
218
219
220 ptr = memAddress + CODE_HOOK_START
221
222 fn_restore = []
223
224
225 fn_ndx = 0
226 while fn_ndx < len(table) :
227 hookAddress = table[ fn_ndx ][0]
228 entry = table[ fn_ndx ][1]
229
230 idx = 0
231
232 patch_code = self.imm.assemble( "JMP 0x%08x" % ptr, address = hookAddress )
233
234 while idx < len(patch_code):
235 op = self.imm.disasm( hookAddress + idx )
236 idx += op.getOpSize()
237 if op.isCall() or op.isJmp():
238 op = None
239 break
240
241
242 if not op:
243 self.imm.log("deleting: %d" % fn_ndx)
244 del table[ fn_ndx ]
245 continue
246
247 ex_prelude = self.imm.readMemory( hookAddress, idx )
248
249 code = self.imm._createCodeforHook( memAddress, hookAddress + idx,\
250 fn_ndx + 1, entry, ex_prelude, alloc_size)
251
252 self.imm.writeMemory( ptr , code )
253 ptr += len(code)
254 self.imm.writeMemory( hookAddress, patch_code )
255
256 fn_restore.append( (ex_prelude, patch_code ) )
257 fn_ndx += 1
258
259 self.setTable( table )
260 if ptr % 4:
261 ptr = 4 + ptr & ~(4-1)
262 self.setMem( ptr )
263 self.imm.writeLong( memAddress, ptr )
264 self.setRestore( fn_restore )
265
266
267
272 if self.address:
273 self.tbl.append( (self.address, self.entry) )
274 self.entry = []
275
276 self.address = address
277 for ndx in range(0, args):
278 self.logBaseDisplacement( "ESP", ndx*4 + 4 )
279
280
283 self.type=0
284 self.msg=""
285 self.string=""
286 self.address=0
287 self.enabled=True
288
290 """Enable hook execution"""
291 self.enabled=True
292
294 """Disable hook execution"""
295 self.enabled=False
296
298 """Remove the hook"""
299 debugger.remove_hook(self.desc)
300
301 - def add(self,description,address=0,force=0,timeout=0,mode=0):
302 """Add hook to Immunity Debugger hook database
303 @param type: Type of hook
304 @param desc: Descriptive string
305 @param force: Force hook adding
306 @param timeout: time to live in memory
307 @param mode: thread mode of ttl execution
308 """
309
310 self.desc = description
311 self.address = address
312 self.force=force
313 self.timeout=timeout
314
315
316
317
318 self.mode=mode
319 if self.type == HookTypes["ORDINARY_BP_HOOK"]:
320 debugger.set_breakpoint(self.address,0x200L,"")
321 elif self.type == HookTypes["LOG_BP_HOOK"]:
322 debugger.set_logging_breakpoint(self.address)
323 pickled_object = pickle.dumps(self)
324 return debugger.add_hook( pickled_object , self.desc , self.type, self.address,self.force,self.timeout,self.mode)
325
326 - def _run(self,regs):
327 """regs is the actual cpu context, be sure of using this values
328 and not the ones from imm.getRegs() at hook time"""
329 self.regs=regs
330 self.run(regs)
331
333 """regs is the actual cpu context, be sure of using this values
334 and not the ones from imm.getRegs() at hook time"""
335 self.regs=regs
336 self.runTimeout(regs)
337
338
339 - def run(self,regs):
340 debugger.Error("Your hook doesnt seem to have run() defined")
341 return
342
344 debugger.Error("Your hook doesnt seem to have runTimeout() defined")
345 return
346
352
358
364
367 Hook.__init__(self)
368 self.type = HookTypes["EVERY_EXCEPTION_HOOK"]
369 self.desc = "EveryExceptionHook"
370
371 -class PostAnalysisHook(Hook):
372 - def __init__(self):
373 Hook.__init__(self)
374 self.type = HookTypes["POST_ANALYSIS_HOOK"]
375 self.desc = "PostAnalysisHook"
376
379 Hook.__init__(self)
380 self.type = HookTypes["ACCESS_VIOLATION_HOOK"]
381 self.desc = "AcessViolationHook"
382
385 Hook.__init__(self)
386 self.type = HookTypes["ACCESS_VIOLATION_HOOK"]
387 self.desc = "AcessViolationHook"
388 imm.run()
389
395
401
404 Hook.__init__(self)
405 self.type = HookTypes["CREATE_THREAD_HOOK"]
406 self.desc = "CreateThreadHook"
407
413
416 Hook.__init__(self)
417 self.type = HookTypes["CREATE_PROCESS_HOOK"]
418 self.desc = "CreateProcessHook"
419
425