Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
win_api_x86_32_seh.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 
4 #
5 # Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License along
18 # with this program; if not, write to the Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #
21 import logging
22 import os
23 import struct
24 
25 from elfesteem import pe_init
26 
27 from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
28 from miasm2.core.utils import pck32, upck32
29 import miasm2.arch.x86.regs as x86_regs
30 
31 
32 # Constants Windows
33 EXCEPTION_BREAKPOINT = 0x80000003
34 EXCEPTION_ACCESS_VIOLATION = 0xc0000005
35 EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094
36 EXCEPTION_PRIV_INSTRUCTION = 0xc0000096
37 EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d
38 
39 
40 log = logging.getLogger("seh_helper")
41 console_handler = logging.StreamHandler()
42 console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
43 log.addHandler(console_handler)
44 log.setLevel(logging.INFO)
45 
46 FS_0_AD = 0x7ff70000
47 PEB_AD = 0x7ffdf000
48 LDR_AD = 0x340000
49 
50 MAX_MODULES = 0x40
51 
52 # fs:[0] Page (TIB)
53 tib_address = FS_0_AD
54 peb_address = PEB_AD
55 peb_ldr_data_offset = 0x1ea0
56 peb_ldr_data_address = LDR_AD + peb_ldr_data_offset
57 
58 
59 modules_list_offset = 0x1f00
60 
61 InInitializationOrderModuleList_offset = 0x1ee0
62 InInitializationOrderModuleList_address = LDR_AD + \
63  InInitializationOrderModuleList_offset
64 
65 InLoadOrderModuleList_offset = 0x1ee0 + \
66  MAX_MODULES * 0x1000
67 InLoadOrderModuleList_address = LDR_AD + \
68  InLoadOrderModuleList_offset
69 
70 default_seh = PEB_AD + 0x20000
71 
72 process_environment_address = 0x10000
73 process_parameters_address = 0x200000
74 
75 context_address = 0x201000
76 exception_record_address = context_address + 0x1000
77 return_from_exception = 0x6eadbeef
78 
79 FAKE_SEH_B_AD = context_address + 0x2000
80 
81 cur_seh_ad = FAKE_SEH_B_AD
82 
83 loaded_modules = ["ntdll.dll", "kernel32.dll"]
84 main_pe = None
85 main_pe_name = "c:\\xxx\\toto.exe"
86 
87 MAX_SEH = 5
88 
89 
90 def build_teb(myjit, teb_address):
91  """
92  +0x000 NtTib : _NT_TIB
93  +0x01c EnvironmentPointer : Ptr32 Void
94  +0x020 ClientId : _CLIENT_ID
95  +0x028 ActiveRpcHandle : Ptr32 Void
96  +0x02c ThreadLocalStoragePointer : Ptr32 Void
97  +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
98  +0x034 LastErrorValue : Uint4B
99  ...
100  """
101  o = ""
102  o += pck32(default_seh)
103  o += (0x18 - len(o)) * "\x00"
104  o += pck32(tib_address)
105 
106  o += (0x30 - len(o)) * "\x00"
107  o += pck32(peb_address)
108  o += pck32(0x11223344)
109 
110  myjit.vm.add_memory_page(teb_address, PAGE_READ | PAGE_WRITE, o)
111 
112 
113 def build_peb(myjit, peb_address):
114  """
115  +0x000 InheritedAddressSpace : UChar
116  +0x001 ReadImageFileExecOptions : UChar
117  +0x002 BeingDebugged : UChar
118  +0x003 SpareBool : UChar
119  +0x004 Mutant : Ptr32 Void
120  +0x008 ImageBaseAddress : Ptr32 Void
121  +0x00c Ldr : Ptr32 _PEB_LDR_DATA
122  +0x010 processparameter
123  """
124 
125  offset = peb_address + 8
126  o = ""
127  if main_pe:
128  o += pck32(main_pe.NThdr.ImageBase)
129  else:
130  offset += 4
131  o += pck32(peb_ldr_data_address)
132  o += pck32(process_parameters_address)
133  myjit.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, o)
134 
135 
136 def build_ldr_data(myjit, modules_info):
137  """
138  +0x000 Length : Uint4B
139  +0x004 Initialized : UChar
140  +0x008 SsHandle : Ptr32 Void
141  +0x00c InLoadOrderModuleList : _LIST_ENTRY
142  +0x014 InMemoryOrderModuleList : _LIST_ENTRY
143  +0x01C InInitializationOrderModuleList : _LIST_ENTRY
144  """
145  o = ""
146  # ldr offset pad
147  offset = LDR_AD + peb_ldr_data_offset + 0xC
148 
149  # get main pe info
150  m_e = None
151  for bname, (addr, e) in modules_info.items():
152  if e == main_pe:
153  m_e = (e, bname, addr)
154  break
155  if not m_e:
156  log.warn('No main pe, ldr data will be unconsistant')
157  offset, data = offset + 8, ""
158  else:
159  log.info('Ldr %x', m_e[2])
160  data = pck32(m_e[2]) + pck32(0)
161 
162  # get ntdll
163  ntdll_e = None
164  for bname, (addr, e) in modules_info.items():
165  if bname[::2].lower() == "ntdll.dll":
166  ntdll_e = (e, bname, addr)
167  continue
168  if not ntdll_e:
169  log.warn('No ntdll, ldr data will be unconsistant')
170  else:
171  data += pck32(ntdll_e[2] + 0x8) + pck32(0) # XXX TODO
172  data += pck32(ntdll_e[2] + 0x10) + pck32(0)
173 
174  if data:
175  myjit.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, data)
176 
177 
178 dummy_e = pe_init.PE()
179 dummy_e.NThdr.ImageBase = 0
180 dummy_e.Opthdr.AddressOfEntryPoint = 0
181 dummy_e.NThdr.sizeofimage = 0
182 
183 
184 def create_modules_chain(myjit, modules_name):
185  """
186  kd> dt nt!_LDR_DATA_TABLE_ENTRY
187  +0x000 InLoadOrderLinks : _LIST_ENTRY
188  +0x008 InMemoryOrderLinks : _LIST_ENTRY
189  +0x010 InInitializationOrderLinks : _LIST_ENTRY
190  +0x018 DllBase : Ptr32 Void
191  +0x01c EntryPoint : Ptr32 Void
192  +0x020 SizeOfImage : Uint4B
193  +0x024 FullDllName : _UNICODE_STRING
194  +0x02c BaseDllName : _UNICODE_STRING
195  +0x034 Flags : Uint4B
196  +0x038 LoadCount : Uint2B
197  +0x03a TlsIndex : Uint2B
198  +0x03c HashLinks : _LIST_ENTRY
199  +0x03c SectionPointer : Ptr32 Void
200  +0x040 CheckSum : Uint4B
201  +0x044 TimeDateStamp : Uint4B
202  +0x044 LoadedImports : Ptr32 Void
203  +0x048 EntryPointActivationContext : Ptr32 Void
204  +0x04c PatchInformation : Ptr32 Void
205  """
206 
207  modules_info = {}
208  base_addr = LDR_AD + modules_list_offset # XXXX
209  offset_name = 0x500
210  offset_path = 0x600
211 
212  out = ""
213  for i, m in enumerate([(main_pe_name, main_pe),
214  ("", dummy_e)] + modules_name):
215  addr = base_addr + i * 0x1000
216  if isinstance(m, tuple):
217  fname, e = m
218  else:
219  fname, e = m, None
220  bpath = fname.replace('/', '\\')
221  bname_str = os.path.split(fname)[1].lower()
222  bname = "\x00".join(bname_str) + "\x00"
223  if e is None:
224  if i == 0:
225  full_name = fname
226  else:
227  full_name = os.path.join("win_dll", fname)
228  try:
229  e = pe_init.PE(open(full_name, 'rb').read())
230  except IOError:
231  log.error('No main pe, ldr data will be unconsistant!')
232  e = None
233  if e is None:
234  continue
235  log.info("Add module %x %r", e.NThdr.ImageBase, bname_str)
236 
237  modules_info[bname] = addr, e
238 
239  m_o = ""
240  m_o += pck32(0)
241  m_o += pck32(0)
242  m_o += pck32(0)
243  m_o += pck32(0)
244  m_o += pck32(0)
245  m_o += pck32(0)
246  m_o += pck32(e.NThdr.ImageBase)
247  m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
248  m_o += pck32(e.NThdr.sizeofimage)
249  m_o += struct.pack('HH', len(bname), len(bname) + 2)
250  m_o += pck32(addr + offset_path)
251  m_o += struct.pack('HH', len(bname), len(bname) + 2)
252  m_o += pck32(addr + offset_name)
253  myjit.vm.add_memory_page(addr, PAGE_READ | PAGE_WRITE, m_o)
254 
255  m_o = ""
256  m_o += bname
257  m_o += "\x00" * 3
258  myjit.vm.add_memory_page(
259  addr + offset_name, PAGE_READ | PAGE_WRITE, m_o)
260 
261  m_o = ""
262  m_o += "\x00".join(bpath) + "\x00"
263  m_o += "\x00" * 3
264  myjit.vm.add_memory_page(
265  addr + offset_path, PAGE_READ | PAGE_WRITE, m_o)
266 
267  return modules_info
268 
269 
270 def fix_InLoadOrderModuleList(myjit, module_info):
271  log.debug("Fix InLoadOrderModuleList")
272  # first binary is PE
273  # last is dumm_e
274  olist = []
275  m_e = None
276  d_e = None
277  for m in [main_pe_name, ""] + loaded_modules:
278 
279  if isinstance(m, tuple):
280  fname, e = m
281  else:
282  fname, e = m, None
283 
284  if "/" in fname:
285  fname = fname[fname.rfind("/") + 1:]
286  bname_str = fname
287  bname = '\x00'.join(bname_str) + '\x00'
288  if not bname.lower() in module_info:
289  log.warn('Module not found, ldr data will be unconsistant')
290  continue
291 
292  addr, e = module_info[bname.lower()]
293  log.debug(bname_str)
294  if e == main_pe:
295  m_e = (e, bname, addr)
296  continue
297  elif e == dummy_e:
298  d_e = (e, bname, addr)
299  continue
300  olist.append((e, bname, addr))
301  if not m_e or not d_e:
302  log.warn('No main pe, ldr data will be unconsistant')
303  else:
304  olist[0:0] = [m_e]
305  olist.append(d_e)
306 
307  last_addr = 0
308  for i in xrange(len(olist)):
309  e, bname, addr = olist[i]
310  p_e, p_bname, p_addr = olist[(i - 1) % len(olist)]
311  n_e, n_bname, n_addr = olist[(i + 1) % len(olist)]
312  myjit.vm.set_mem(addr + 0, pck32(n_addr) + pck32(p_addr))
313 
314 
315 def fix_InMemoryOrderModuleList(myjit, module_info):
316  log.debug("Fix InMemoryOrderModuleList")
317  # first binary is PE
318  # last is dumm_e
319  olist = []
320  m_e = None
321  d_e = None
322  for m in [main_pe_name, ""] + loaded_modules:
323 
324  if isinstance(m, tuple):
325  fname, e = m
326  else:
327  fname, e = m, None
328 
329  if "/" in fname:
330  fname = fname[fname.rfind("/") + 1:]
331  bname_str = fname
332  bname = '\x00'.join(bname_str) + '\x00'
333  if not bname.lower() in module_info:
334  log.warn('Module not found, ldr data will be unconsistant')
335  continue
336  addr, e = module_info[bname.lower()]
337  log.debug(bname_str)
338  if e == main_pe:
339  m_e = (e, bname, addr)
340  continue
341  elif e == dummy_e:
342  d_e = (e, bname, addr)
343  continue
344  olist.append((e, bname, addr))
345  if not m_e or not d_e:
346  log.warn('No main pe, ldr data will be unconsistant')
347  else:
348  olist[0:0] = [m_e]
349  olist.append(d_e)
350 
351  last_addr = 0
352 
353  for i in xrange(len(olist)):
354  e, bname, addr = olist[i]
355  p_e, p_bname, p_addr = olist[(i - 1) % len(olist)]
356  n_e, n_bname, n_addr = olist[(i + 1) % len(olist)]
357  myjit.vm.set_mem(
358  addr + 0x8, pck32(n_addr + 0x8) + pck32(p_addr + 0x8))
359 
360 
361 def fix_InInitializationOrderModuleList(myjit, module_info):
362  # first binary is ntdll
363  # second binary is kernel32
364  olist = []
365  ntdll_e = None
366  kernel_e = None
367  for bname, (addr, e) in module_info.items():
368  if bname[::2].lower() == "ntdll.dll":
369  ntdll_e = (e, bname, addr)
370  continue
371  elif bname[::2].lower() == "kernel32.dll":
372  kernel_e = (e, bname, addr)
373  continue
374  elif e == dummy_e:
375  d_e = (e, bname, addr)
376  continue
377  elif e == main_pe:
378  continue
379  olist.append((e, bname, addr))
380  if not ntdll_e or not kernel_e or not d_e:
381  log.warn('No kernel ntdll, ldr data will be unconsistant')
382  else:
383  olist[0:0] = [ntdll_e]
384  olist[1:1] = [kernel_e]
385 
386  olist.append(d_e)
387 
388  last_addr = 0
389  for i in xrange(len(olist)):
390  e, bname, addr = olist[i]
391  p_e, p_bname, p_addr = olist[(i - 1) % len(olist)]
392  n_e, n_bname, n_addr = olist[(i + 1) % len(olist)]
393  myjit.vm.set_mem(
394  addr + 0x10, pck32(n_addr + 0x10) + pck32(p_addr + 0x10))
395 
396 
397 def add_process_env(myjit):
398  env_str = 'ALLUSEESPROFILE=C:\\Documents and Settings\\All Users\x00'
399  env_str = '\x00'.join(env_str)
400  env_str += "\x00" * 0x10
401  myjit.vm.add_memory_page(process_environment_address,
402  PAGE_READ | PAGE_WRITE,
403  env_str)
404  myjit.vm.set_mem(process_environment_address, env_str)
405 
406 
408  o = ""
409  o += pck32(0x1000) # size
410  o += "E" * (0x48 - len(o))
411  o += pck32(process_environment_address)
412  myjit.vm.add_memory_page(process_parameters_address,
413  PAGE_READ | PAGE_WRITE,
414  o)
415 
416 
417 all_seh_ad = dict([(x, None)
418  for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD + 0x1000, 0x20)])
419 # http://blog.fireeye.com/research/2010/08/download_exec_notes.html
420 seh_count = 0
421 
422 
423 def init_seh(myjit):
424  global seh_count
425  seh_count = 0
426  build_teb(myjit, FS_0_AD)
427  build_peb(myjit, peb_address)
428 
429  module_info = create_modules_chain(myjit, loaded_modules)
430  fix_InLoadOrderModuleList(myjit, module_info)
431  fix_InMemoryOrderModuleList(myjit, module_info)
432  fix_InInitializationOrderModuleList(myjit, module_info)
433 
434  build_ldr_data(myjit, module_info)
435  add_process_env(myjit)
437 
438  myjit.vm.add_memory_page(default_seh, PAGE_READ | PAGE_WRITE, pck32(
439  0xffffffff) + pck32(0x41414141) + pck32(0x42424242))
440 
441  myjit.vm.add_memory_page(
442  context_address, PAGE_READ | PAGE_WRITE, '\x00' * 0x2cc)
443  myjit.vm.add_memory_page(
444  exception_record_address, PAGE_READ | PAGE_WRITE, '\x00' * 200)
445 
446  myjit.vm.add_memory_page(
447  FAKE_SEH_B_AD, PAGE_READ | PAGE_WRITE, 0x10000 * "\x00")
448 
449 # http://www.codeproject.com/KB/system/inject2exe.aspx#RestorethefirstRegistersContext5_1
450 
451 
452 def regs2ctxt(myjit):
453  """
454  Build x86_32 cpu context for exception handling
455  @myjit: jitload instance
456  """
457 
458  ctxt = []
459  # ContextFlags
460  ctxt += [pck32(0x0)]
461  # DRX
462  ctxt += [pck32(0x0)] * 6
463  # Float context
464  ctxt += ['\x00' * 112]
465  # Segment selectors
466  ctxt += [pck32(reg) for reg in (myjit.cpu.GS, myjit.cpu.FS,
467  myjit.cpu.ES, myjit.cpu.DS)]
468  # Gpregs
469  ctxt += [pck32(reg) for reg in (myjit.cpu.EDI, myjit.cpu.ESI,
470  myjit.cpu.EBX, myjit.cpu.EDX,
471  myjit.cpu.ECX, myjit.cpu.EAX,
472  myjit.cpu.EBP, myjit.cpu.EIP)]
473  # CS
474  ctxt += [pck32(myjit.cpu.CS)]
475  # Eflags
476  # XXX TODO real eflag
477  ctxt += [pck32(0x0)]
478  # ESP
479  ctxt += [pck32(myjit.cpu.ESP)]
480  # SS
481  ctxt += [pck32(myjit.cpu.SS)]
482  return "".join(ctxt)
483 
484 
485 def ctxt2regs(ctxt, myjit):
486  """
487  Restore x86_32 registers from an exception context
488  @ctxt: the serialized context
489  @myjit: jitload instance
490  """
491 
492  ctxt = ctxt[:]
493  # ContextFlags
494  ctxt = ctxt[4:]
495  # DRX XXX TODO
496  ctxt = ctxt[4 * 6:]
497  # Float context XXX TODO
498  ctxt = ctxt[112:]
499  # gs
500  myjit.cpu.GS = upck32(ctxt[:4])
501  ctxt = ctxt[4:]
502  # fs
503  myjit.cpu.FS = upck32(ctxt[:4])
504  ctxt = ctxt[4:]
505  # es
506  myjit.cpu.ES = upck32(ctxt[:4])
507  ctxt = ctxt[4:]
508  # ds
509  myjit.cpu.DS = upck32(ctxt[:4])
510  ctxt = ctxt[4:]
511 
512  # Gpregs
513  myjit.cpu.EDI = upck32(ctxt[:4])
514  ctxt = ctxt[4:]
515  myjit.cpu.ESI = upck32(ctxt[:4])
516  ctxt = ctxt[4:]
517  myjit.cpu.EBX = upck32(ctxt[:4])
518  ctxt = ctxt[4:]
519  myjit.cpu.EDX = upck32(ctxt[:4])
520  ctxt = ctxt[4:]
521  myjit.cpu.ECX = upck32(ctxt[:4])
522  ctxt = ctxt[4:]
523  myjit.cpu.EAX = upck32(ctxt[:4])
524  ctxt = ctxt[4:]
525  myjit.cpu.EBP = upck32(ctxt[:4])
526  ctxt = ctxt[4:]
527  myjit.cpu.EIP = upck32(ctxt[:4])
528  ctxt = ctxt[4:]
529 
530  # CS
531  myjit.cpu.CS = upck32(ctxt[:4])
532  ctxt = ctxt[4:]
533  # Eflag XXX TODO
534  ctxt = ctxt[4:]
535  # ESP
536  myjit.cpu.ESP = upck32(ctxt[:4])
537  ctxt = ctxt[4:]
538 
539 
540 def fake_seh_handler(myjit, except_code):
541  global seh_count, context_address
542  regs = myjit.cpu.get_gpreg()
543  log.warning('Exception at %x %r', myjit.cpu.EIP, seh_count)
544  seh_count += 1
545 
546  # Help lambda
547  p = lambda s: struct.pack('I', s)
548 
549  # Forge a CONTEXT
550  ctxt = regs2ctxt(myjit)
551 
552  # Get current seh (fs:[0])
553  seh_ptr = upck32(myjit.vm.get_mem(tib_address, 4))
554 
555  # Retrieve seh fields
556  old_seh, eh, safe_place = struct.unpack(
557  'III', myjit.vm.get_mem(seh_ptr, 0xc))
558 
559  # Get space on stack for exception handling
560  myjit.cpu.ESP -= 0x3c8
561  exception_base_address = myjit.cpu.ESP
562  exception_record_address = exception_base_address + 0xe8
563  context_address = exception_base_address + 0xfc
564  fake_seh_address = exception_base_address + 0x14
565 
566  log.info('seh_ptr %x { old_seh %x eh %x safe_place %x} ctx_addr %x',
567  seh_ptr, old_seh, eh, safe_place, context_address)
568 
569  # Write context
570  myjit.vm.set_mem(context_address, ctxt)
571 
572  # Write exception_record
573 
574  """
575  #http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
576 
577  typedef struct _EXCEPTION_RECORD {
578  DWORD ExceptionCode;
579  DWORD ExceptionFlags;
580  struct _EXCEPTION_RECORD *ExceptionRecord;
581  PVOID ExceptionAddress;
582  DWORD NumberParameters;
583  ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
584  } EXCEPTION_RECORD, *PEXCEPTION_RECORD;
585  """
586 
587  myjit.vm.set_mem(exception_record_address,
588  pck32(except_code) + pck32(0) + pck32(0) +
589  pck32(myjit.cpu.EIP) + pck32(0))
590 
591  # Prepare the stack
592  myjit.push_uint32_t(context_address) # Context
593  myjit.push_uint32_t(seh_ptr) # SEH
594  myjit.push_uint32_t(exception_record_address) # ExceptRecords
595  myjit.push_uint32_t(return_from_exception) # Ret address
596 
597  # Set fake new current seh for exception
598  log.info("Fake seh ad %x", fake_seh_address)
599  myjit.vm.set_mem(fake_seh_address, pck32(seh_ptr) + pck32(
600  0xaaaaaaaa) + pck32(0xaaaaaabb) + pck32(0xaaaaaacc))
601  myjit.vm.set_mem(tib_address, pck32(fake_seh_address))
602 
603  dump_seh(myjit)
604 
605  log.info('Jumping at %x', eh)
606  myjit.vm.set_exception(0)
607  myjit.cpu.set_exception(0)
608 
609  # XXX set ebx to nul?
610  myjit.cpu.EBX = 0
611 
612  return eh
613 
614 fake_seh_handler.base = FAKE_SEH_B_AD
615 
616 
617 def dump_seh(myjit):
618  log.info('Dump_seh. Tib_address: %x', tib_address)
619  cur_seh_ptr = upck32(myjit.vm.get_mem(tib_address, 4))
620  indent = 1
621  loop = 0
622  while True:
623  if loop > MAX_SEH:
624  log.warn("Too many seh, quit")
625  return
626  prev_seh, eh = struct.unpack('II', myjit.vm.get_mem(cur_seh_ptr, 8))
627  log.info('\t' * indent + 'seh_ptr: %x { prev_seh: %x eh %x }',
628  cur_seh_ptr, prev_seh, eh)
629  if prev_seh in [0xFFFFFFFF, 0]:
630  break
631  cur_seh_ptr = prev_seh
632  indent += 1
633  loop += 1
634 
635 
636 def set_win_fs_0(myjit, fs=4):
637  regs = myjit.cpu.get_gpreg()
638  regs['FS'] = 0x4
639  myjit.cpu.set_gpreg(regs)
640  myjit.cpu.set_segm_base(regs['FS'], FS_0_AD)
641  segm_to_do = set([x86_regs.FS])
642  return segm_to_do
643 
644 
645 def add_modules_info(pe_in, pe_in_name="toto.exe", all_pe=None):
646  global main_pe, main_pe_name, loaded_modules
647  if all_pe is None:
648  all_pe = []
649  main_pe = pe_in
650  main_pe_name = pe_in_name
651  loaded_modules = all_pe
652 
653 
654 def return_from_seh(myjit):
655  "Handle return after a call to fake seh handler"
656 
657  # Get current context
658  context_address = upck32(myjit.vm.get_mem(myjit.cpu.ESP + 0x8, 4))
659  log.info('Context address: %x', context_address)
660  myjit.cpu.ESP = upck32(myjit.vm.get_mem(context_address + 0xc4, 4))
661  log.info('New esp: %x', myjit.cpu.ESP)
662 
663  # Rebuild SEH
664  old_seh = upck32(myjit.vm.get_mem(tib_address, 4))
665  new_seh = upck32(myjit.vm.get_mem(old_seh, 4))
666  log.info('Old seh: %x New seh: %x', old_seh, new_seh)
667  myjit.vm.set_mem(tib_address, pck32(new_seh))
668 
669  dump_seh(myjit)
670 
671  if myjit.cpu.EAX == 0x0:
672  # ExceptionContinueExecution
673  ctxt_ptr = context_address
674  log.info('Seh continues Context: %x', ctxt_ptr)
675 
676  # Get registers changes
677  ctxt_str = myjit.vm.get_mem(ctxt_ptr, 0x2cc)
678  ctxt2regs(ctxt_str, myjit)
679  myjit.pc = myjit.cpu.EIP
680  log.info('Context::Eip: %x', myjit.pc)
681 
682  elif myjit.cpu.EAX == -1:
683  raise NotImplementedError("-> seh try to go to the next handler")
684 
685  elif myjit.cpu.EAX == 1:
686  # ExceptionContinueSearch
687  raise NotImplementedError("-> seh, gameover")
tuple upck32
Definition: utils.py:8
tuple pck32
Definition: utils.py:12