about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/os_dep/win_api_x86_32_seh.py276
1 files changed, 45 insertions, 231 deletions
diff --git a/miasm2/os_dep/win_api_x86_32_seh.py b/miasm2/os_dep/win_api_x86_32_seh.py
index c74346f5..8c6f9b88 100644
--- a/miasm2/os_dep/win_api_x86_32_seh.py
+++ b/miasm2/os_dep/win_api_x86_32_seh.py
@@ -52,22 +52,20 @@ MAX_MODULES = 0x40
 tib_address = FS_0_AD
 peb_address = PEB_AD
 peb_ldr_data_offset = 0x1ea0
-peb_ldr_data_address = LDR_AD + peb_ldr_data_offset  # PEB_AD + 0x1000
+peb_ldr_data_address = LDR_AD + peb_ldr_data_offset
 
 
 modules_list_offset = 0x1f00
 
-InInitializationOrderModuleList_offset = 0x1ee0  # 0x1f48
+InInitializationOrderModuleList_offset = 0x1ee0
 InInitializationOrderModuleList_address = LDR_AD + \
-    InInitializationOrderModuleList_offset  # PEB_AD + 0x2000
+    InInitializationOrderModuleList_offset
 
 InLoadOrderModuleList_offset = 0x1ee0 + \
-    MAX_MODULES * 0x1000  # 0x1f48 + MAX_MODULES*0x1000
+    MAX_MODULES * 0x1000
 InLoadOrderModuleList_address = LDR_AD + \
-    InLoadOrderModuleList_offset  # PEB_AD + 0x2000
+    InLoadOrderModuleList_offset
 
-# in_load_order_module_1 = LDR_AD +
-# in_load_order_module_list_offset#PEB_AD + 0x3000
 default_seh = PEB_AD + 0x20000
 
 process_environment_address = 0x10000
@@ -85,8 +83,9 @@ loaded_modules = ["ntdll.dll", "kernel32.dll"]
 main_pe = None
 main_pe_name = "c:\\xxx\\toto.exe"
 
+MAX_SEH = 5
 
-def build_fake_teb(myjit, teb_address):
+def build_teb(myjit, teb_address):
     """
     +0x000 NtTib                     : _NT_TIB
     +0x01c EnvironmentPointer        : Ptr32 Void
@@ -109,7 +108,7 @@ def build_fake_teb(myjit, teb_address):
     myjit.vm.add_memory_page(teb_address, PAGE_READ | PAGE_WRITE, o)
 
 
-def build_fake_peb(myjit, peb_address):
+def build_peb(myjit, peb_address):
     """
     +0x000 InheritedAddressSpace    : UChar
     +0x001 ReadImageFileExecOptions : UChar
@@ -132,7 +131,7 @@ def build_fake_peb(myjit, peb_address):
     myjit.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, o)
 
 
-def build_fake_ldr_data(myjit, modules_info):
+def build_ldr_data(myjit, modules_info):
     """
     +0x000 Length                          : Uint4B
     +0x004 Initialized                     : UChar
@@ -144,7 +143,6 @@ def build_fake_ldr_data(myjit, modules_info):
     o = ""
     # ldr offset pad
     offset = LDR_AD + peb_ldr_data_offset + 0xC
-    # text XXX
 
     # get main pe info
     m_e = None
@@ -168,7 +166,6 @@ def build_fake_ldr_data(myjit, modules_info):
     if not ntdll_e:
         log.warn('no ntdll, ldr data will be unconsistant')
     else:
-        print 'ntdll', hex(ntdll_e[2])
         data += pck32(ntdll_e[2] + 0x8) + pck32(0)  # XXX TODO
         data += pck32(ntdll_e[2] + 0x10) + pck32(0)
 
@@ -176,82 +173,6 @@ def build_fake_ldr_data(myjit, modules_info):
         myjit.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, data)
 
 
-
-# def build_fake_InInitializationOrderModuleList(modules_name):
-#    """
-#    +0x000 Flink : Ptr32                                 -+ This distance
-#    +0x004 Blink : Ptr32                                  | is eight bytes
-#    +0x018 DllBase                        : Ptr32 Void   -+ DllBase
-#    +0x01c EntryPoint                     : Ptr32 Void
-#    +0x020 SizeOfImage                    : Uint4B
-#    +0x024 FullDllName                    : _UNICODE_STRING
-#    +0x02c BaseDllName                    : _UNICODE_STRING
-#    +0x034 Flags                          : Uint4B
-#    +0x038 LoadCount                      : Uint2B
-#    +0x03a TlsIndex                       : Uint2B
-#    +0x03c HashLinks                      : _LIST_ENTRY
-#    +0x03c SectionPointer                 : Ptr32 Void
-#    +0x040 CheckSum                       : Uint4B
-#    +0x044 TimeDateStamp                  : Uint4B
-#    +0x044 LoadedImports                  : Ptr32 Void
-#    +0x048 EntryPointActivationContext    : Ptr32 Void
-#    +0x04c PatchInformation               : Ptr32 Void
-#    """
-#
-#    o = ""
-#    offset_name = 0x700
-#    for i, m in enumerate(modules_name):
-# fname = os.path.join('win_dll', m)
-#        if isinstance(m, tuple):
-#            fname, e = m
-#        else:
-#            fname, e = m, None
-#        bname = os.path.split(fname)[1].lower()
-#        bname = "\x00".join(bname)+"\x00"
-#        print "add module", repr(bname)
-#        print hex(InInitializationOrderModuleList_address+i*0x1000)
-#        if e == None:
-#            e = pe_init.PE(open(fname, 'rb').read())
-#
-#        next_ad = InInitializationOrderModuleList_address + (i+1)*0x1000
-#        if i == len(modules_name) -1:
-#            next_ad = InInitializationOrderModuleList_address
-#        m_o = ""
-#        m_o += pck32(next_ad )
-#        m_o += pck32(InInitializationOrderModuleList_address + (i-1)*0x1000)
-#        m_o += pck32(next_ad + 8 )
-#        m_o += pck32(InInitializationOrderModuleList_address
-#            +  (i-1)*0x1000 + 8)
-#        m_o += pck32(next_ad + 0x10 )
-#        m_o += pck32(InInitializationOrderModuleList_address
-#            +  (i-1)*0x1000 + 0x10)
-#        m_o += pck32(e.NThdr.ImageBase)
-#        m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
-#        m_o += pck32(e.NThdr.sizeofimage)
-#
-#        m_o += (0x24 - len(m_o))*"A"
-#        print hex(len(bname)), repr(bname)
-#        m_o += struct.pack('HH', len(bname), len(bname)+2)
-#        m_o += pck32(InInitializationOrderModuleList_address
-#            +  i*0x1000+offset_name)
-#
-#        m_o += (0x2C - len(m_o))*"A"
-#        m_o += struct.pack('HH', len(bname), len(bname)+2)
-#        m_o += pck32(InInitializationOrderModuleList_address
-#            +  i*0x1000+offset_name)
-#
-#        m_o += (offset_name - len(m_o))*"B"
-#        m_o += bname
-#        m_o += "\x00"*3
-#
-#
-#        m_o += (0x1000 - len(m_o))*"J"
-#
-#        print "module", "%.8X"%e.NThdr.ImageBase, fname
-#
-#        o += m_o
-#    return o
-#
 dummy_e = pe_init.PE()
 dummy_e.NThdr.ImageBase = 0
 dummy_e.Opthdr.AddressOfEntryPoint = 0
@@ -259,6 +180,28 @@ dummy_e.NThdr.sizeofimage = 0
 
 
 def create_modules_chain(myjit, modules_name):
+    """
+    kd> dt nt!_LDR_DATA_TABLE_ENTRY
+    +0x000 InLoadOrderLinks : _LIST_ENTRY
+    +0x008 InMemoryOrderLinks : _LIST_ENTRY
+    +0x010 InInitializationOrderLinks : _LIST_ENTRY
+    +0x018 DllBase : Ptr32 Void
+    +0x01c EntryPoint : Ptr32 Void
+    +0x020 SizeOfImage : Uint4B
+    +0x024 FullDllName : _UNICODE_STRING
+    +0x02c BaseDllName : _UNICODE_STRING
+    +0x034 Flags : Uint4B
+    +0x038 LoadCount : Uint2B
+    +0x03a TlsIndex : Uint2B
+    +0x03c HashLinks : _LIST_ENTRY
+    +0x03c SectionPointer : Ptr32 Void
+    +0x040 CheckSum : Uint4B
+    +0x044 TimeDateStamp : Uint4B
+    +0x044 LoadedImports : Ptr32 Void
+    +0x048 EntryPointActivationContext : Ptr32 Void
+    +0x04c PatchInformation : Ptr32 Void
+    """
+
     modules_info = {}
     base_addr = LDR_AD + modules_list_offset  # XXXX
     offset_name = 0x500
@@ -268,16 +211,13 @@ def create_modules_chain(myjit, modules_name):
     for i, m in enumerate([(main_pe_name, main_pe),
         ("", dummy_e)] + modules_name):
         addr = base_addr + i * 0x1000
-        # fname = os.path.join('win_dll', m)
         if isinstance(m, tuple):
             fname, e = m
         else:
             fname, e = m, None
         bpath = fname.replace('/', '\\')
-        bname = os.path.split(fname)[1].lower()
-        bname = "\x00".join(bname) + "\x00"
-        # print "add module", repr(bname), repr(bpath)
-        # print hex(InInitializationOrderModuleList_address+i*0x1000)
+        bname_str = os.path.split(fname)[1].lower()
+        bname = "\x00".join(bname_str) + "\x00"
         if e is None:
             if i == 0:
                 full_name = fname
@@ -290,12 +230,10 @@ def create_modules_chain(myjit, modules_name):
                 e = None
         if e is None:
             continue
-        print "add module", hex(e.NThdr.ImageBase), repr(bname)
+        log.info("add module %r %r"%(hex(e.NThdr.ImageBase), bname_str))
 
         modules_info[bname] = addr, e
 
-        print hex(len(bname)), repr(bname)
-
         m_o = ""
         m_o += pck32(0)
         m_o += pck32(0)
@@ -471,109 +409,6 @@ def add_process_parameters(myjit):
                              o)
 
 
-def build_fake_InLoadOrderModuleList(modules_name):
-    """
-    +0x000 Flink : Ptr32                                 -+ This distance
-    +0x004 Blink : Ptr32                                  | is eight bytes
-    +0x018 DllBase                        : Ptr32 Void   -+ DllBase -> _IMAGE_DOS_HEADER
-    +0x01c EntryPoint                     : Ptr32 Void
-    +0x020 SizeOfImage                    : Uint4B
-    +0x024 FullDllName                    : _UNICODE_STRING
-    +0x02c BaseDllName                    : _UNICODE_STRING
-    +0x034 Flags                          : Uint4B
-    +0x038 LoadCount                      : Uint2B
-    +0x03a TlsIndex                       : Uint2B
-    +0x03c HashLinks                      : _LIST_ENTRY
-    +0x03c SectionPointer                 : Ptr32 Void
-    +0x040 CheckSum                       : Uint4B
-    +0x044 TimeDateStamp                  : Uint4B
-    +0x044 LoadedImports                  : Ptr32 Void
-    +0x048 EntryPointActivationContext    : Ptr32 Void
-    +0x04c PatchInformation               : Ptr32 Void
-    """
-
-    o = ""
-    offset_name = 0x700
-    first_name = "\x00".join(main_pe_name + "\x00\x00")
-
-    o = ""
-    o += pck32(InLoadOrderModuleList_address)
-    o += pck32(InLoadOrderModuleList_address +
-               (len(modules_name) - 1) * 0x1000)
-    o += pck32(InLoadOrderModuleList_address + 8)
-    o += pck32(InLoadOrderModuleList_address +
-               (len(modules_name) - 1) * 0x1000 + 8)
-    o += pck32(InLoadOrderModuleList_address + 0x10)
-    o += pck32(InLoadOrderModuleList_address +
-               (len(modules_name) - 1) * 0x1000 + 0x10)
-
-    if main_pe:
-        o += pck32(main_pe.NThdr.ImageBase)
-        o += pck32(main_pe.rva2virt(main_pe.Opthdr.AddressOfEntryPoint))
-    else:
-        # no fixed values
-        pass
-
-    o += (0x24 - len(o)) * "A"
-    o += struct.pack('HH', len(first_name), len(first_name))
-    o += pck32(InLoadOrderModuleList_address + offset_name)
-
-    o += (0x2C - len(o)) * "A"
-    o += struct.pack('HH', len(first_name), len(first_name))
-    o += pck32(InLoadOrderModuleList_address + offset_name)
-
-    o += (offset_name - len(o)) * "B"
-    o += first_name
-    o += (0x1000 - len(o)) * "C"
-    for i, m in enumerate(modules_name):
-        # fname = os.path.join('win_dll', m)
-        if isinstance(m, tuple):
-            fname, e = m
-        else:
-            fname, e = m, None
-        bname = os.path.split(fname)[1].lower()
-        bname = "\x00".join(bname) + "\x00"
-        print hex(InLoadOrderModuleList_address + i * 0x1000)
-        if e is None:
-            e = pe_init.PE(open(fname, 'rb').read())
-
-        print "add module", hex(e.NThdr.ImageBase), repr(bname)
-
-        next_ad = InLoadOrderModuleList_address + (i + 1) * 0x1000
-        if i == len(modules_name) - 1:
-            next_ad = InLoadOrderModuleList_address
-        m_o = ""
-        m_o += pck32(next_ad)
-        m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000)
-        m_o += pck32(next_ad + 8)
-        m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 8)
-        m_o += pck32(next_ad + 0x10)
-        m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 0x10)
-        m_o += pck32(e.NThdr.ImageBase)
-        m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
-        m_o += pck32(e.NThdr.sizeofimage)
-
-        m_o += (0x24 - len(m_o)) * "A"
-        print hex(len(bname)), repr(bname)
-        m_o += struct.pack('HH', len(bname), len(bname) + 2)
-        m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name)
-
-        m_o += (0x2C - len(m_o)) * "A"
-        m_o += struct.pack('HH', len(bname), len(bname) + 2)
-        m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name)
-
-        m_o += (offset_name - len(m_o)) * "B"
-        m_o += bname
-        m_o += "\x00" * 3
-
-        m_o += (0x1000 - len(m_o)) * "J"
-
-        print "module", "%.8X" % e.NThdr.ImageBase, fname
-
-        o += m_o
-    return o
-
-
 all_seh_ad = dict([(x, None)
                   for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD + 0x1000, 0x20)])
 # http://blog.fireeye.com/research/2010/08/download_exec_notes.html
@@ -582,28 +417,18 @@ seh_count = 0
 def init_seh(myjit):
     global seh_count
     seh_count = 0
-    build_fake_teb(myjit, FS_0_AD)
+    build_teb(myjit, FS_0_AD)
     build_peb(myjit, peb_address)
 
-    """
-    ldr_data += "\x00"*(InInitializationOrderModuleList_offset - len(ldr_data))
-    ldr_data += build_fake_InInitializationOrderModuleList(loaded_modules)
-    ldr_data += "\x00"*(InLoadOrderModuleList_offset - len(ldr_data))
-    ldr_data += build_fake_InLoadOrderModuleList(loaded_modules)
-    """
     module_info = create_modules_chain(myjit, loaded_modules)
     fix_InLoadOrderModuleList(myjit, module_info)
     fix_InMemoryOrderModuleList(myjit, module_info)
     fix_InInitializationOrderModuleList(myjit, module_info)
 
-    build_fake_ldr_data(myjit, module_info)
+    build_ldr_data(myjit, module_info)
     add_process_env(myjit)
     add_process_parameters(myjit)
 
-    # myjit.vm.add_memory_page(in_load_order_module_list_address,
-    #     PAGE_READ | PAGE_WRITE, p(0) * 40)
-    # myjit.vm.add_memory_page(in_load_order_module_list_address,
-    #     PAGE_READ | PAGE_WRITE, build_fake_inordermodule(loaded_modules))
     myjit.vm.add_memory_page(default_seh, PAGE_READ | PAGE_WRITE, pck32(
         0xffffffff) + pck32(0x41414141) + pck32(0x42424242))
 
@@ -638,33 +463,33 @@ def regs2ctxt(regs):
 def ctxt2regs(ctxt):
     ctxt = ctxt[:]
     regs = {}
-    # regs['ctxtsflags'] = upck32(ctxt[:4])
+    # ctxtsflags
     ctxt = ctxt[4:]
     for i in xrange(8):
         if i in [4, 5]:
             continue
-        # regs['dr%d'%i] = upck32(ctxt[:4])
+        # regs i
         ctxt = ctxt[4:]
 
     ctxt = ctxt[112:]  # skip float
 
-    # regs['seg_gs'] = upck32(ctxt[:4])
+    # gs
     ctxt = ctxt[4:]
-    # regs['seg_fs'] = upck32(ctxt[:4])
+    # fs
     ctxt = ctxt[4:]
-    # regs['seg_es'] = upck32(ctxt[:4])
+    # es
     ctxt = ctxt[4:]
-    # regs['seg_ds'] = upck32(ctxt[:4])
+    # ds
     ctxt = ctxt[4:]
 
     regs['EDI'], regs['ESI'], regs['EBX'], regs['EDX'], regs['ECX'], regs[
         'EAX'], regs['EBP'], regs['EIP'] = struct.unpack('I' * 8, ctxt[:4 * 8])
     ctxt = ctxt[4 * 8:]
 
-    # regs['seg_cs'] = upck32(ctxt[:4])
+    # cs
     ctxt = ctxt[4:]
 
-    # regs['eflag'] = upck32(ctxt[:4])
+    # eflag
     ctxt = ctxt[4:]
 
     regs['ESP'] = upck32(ctxt[:4])
@@ -709,8 +534,6 @@ def fake_seh_handler(myjit, except_code):
     # Help lambda
     p = lambda s: struct.pack('I', s)
 
-    # dump_gpregs_py()
-    # jitarch.dump_gpregs()
     # Forge a CONTEXT
     ctxt = '\x00\x00\x00\x00' + '\x00\x00\x00\x00' * 6 + '\x00' * 112
     ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00'
@@ -721,10 +544,6 @@ def fake_seh_handler(myjit, except_code):
             pck32(myjit.cpu.EBP) + pck32(myjit.cpu.EIP)
     ctxt += '\x23\x00\x00\x00' + '\x00\x00\x00\x00' + pck32(myjit.cpu.ESP)
     ctxt += '\x23\x00\x00\x00'
-    # ctxt = regs2ctxt(regs)
-
-    # Find a room for seh
-    # seh = (get_memory_page_max_address_py()+0x1000)&0xfffff000
 
     # Get current seh (fs:[0])
     seh_ptr = upck32(myjit.vm.get_mem(tib_address, 4))
@@ -735,11 +554,6 @@ def fake_seh_handler(myjit, except_code):
 
     print '-> seh_ptr', hex(seh_ptr), '-> { old_seh',
     print hex(old_seh), 'eh', hex(eh), 'safe_place', hex(safe_place), '}'
-    # print '-> write SEH at', hex(seh&0xffffffff)
-
-    # Write current seh
-    # myjit.vm.add_memory_page(seh, PAGE_READ | PAGE_WRITE, p(old_seh) +
-    # p(eh) + p(safe_place) + p(0x99999999))
 
     # Write context
     myjit.vm.set_mem(context_address, ctxt)
@@ -797,7 +611,7 @@ def dump_seh(myjit):
     indent = 1
     loop = 0
     while True:
-        if loop > 5:
+        if loop > MAX_SEH:
             print "too many seh, quit"
             return
         prev_seh, eh = struct.unpack('II', myjit.vm.get_mem(cur_seh_ptr, 8))