about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/jitter/unpack_upx.py2
-rw-r--r--miasm2/analysis/sandbox.py129
-rw-r--r--miasm2/jitter/loader/pe.py135
-rw-r--r--miasm2/jitter/loader/utils.py8
-rw-r--r--miasm2/os_dep/win_api_x86_32_seh.py46
5 files changed, 214 insertions, 106 deletions
diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py
index f1f179b8..c329244e 100644
--- a/example/jitter/unpack_upx.py
+++ b/example/jitter/unpack_upx.py
@@ -43,7 +43,7 @@ parser.add_argument("--graph",
                     help="Export the CFG graph in graph.dot",
                     action="store_true")
 options = parser.parse_args()
-sb = Sandbox_Win_x86_32(options.filename, options, globals())
+sb = Sandbox_Win_x86_32(options.filename, options, globals(), parse_reloc=False)
 
 
 if options.verbose is True:
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py
index b3184626..078663fe 100644
--- a/miasm2/analysis/sandbox.py
+++ b/miasm2/analysis/sandbox.py
@@ -1,13 +1,15 @@
+import os
 import logging
 from argparse import ArgumentParser
 
 from miasm2.analysis.machine import Machine
-from miasm2.os_dep import win_api_x86_32_seh
 from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm2.analysis import debugging
 from miasm2.jitter.jitload import log_func
 
+
 class Sandbox(object):
+
     """
     Parent class for Sandbox abstraction
     """
@@ -29,9 +31,9 @@ class Sandbox(object):
 
             yield base_cls
 
-    classes = property(lambda x:x.__class__._classes_())
+    classes = property(lambda x: x.__class__._classes_())
 
-    def __init__(self, fname, options, custom_methods = {}):
+    def __init__(self, fname, options, custom_methods={}, **kwargs):
         """
         Initialize a sandbox
         @fname: str file name
@@ -46,9 +48,9 @@ class Sandbox(object):
             if cls == Sandbox:
                 continue
             if issubclass(cls, OS):
-                cls.__init__(self, custom_methods)
+                cls.__init__(self, custom_methods, **kwargs)
             else:
-                cls.__init__(self)
+                cls.__init__(self, **kwargs)
 
         # Logging options
         if self.options.singlestep:
@@ -84,8 +86,11 @@ class Sandbox(object):
         parser.add_argument("-j", "--jitter",
                             help="Jitter engine. Possible values are: tcc (default), llvm, python",
                             default="tcc")
-        parser.add_argument('-q', "--quiet-function-calls", action="store_true",
+        parser.add_argument(
+            '-q', "--quiet-function-calls", action="store_true",
                             help="Don't log function calls")
+        parser.add_argument('-i', "--dependencies", action="store_true",
+                            help="Load PE and its dependencies")
 
         for base_cls in cls._classes_():
             base_cls.update_parser(parser)
@@ -121,11 +126,12 @@ class Sandbox(object):
 
 
 class OS(object):
+
     """
     Parent class for OS abstraction
     """
 
-    def __init__(self, custom_methods):
+    def __init__(self, custom_methods, **kwargs):
         pass
 
     @classmethod
@@ -134,13 +140,15 @@ class OS(object):
 
 
 class Arch(object):
+
     """
     Parent class for Arch abstraction
     """
 
     # Architecture name
     _ARCH_ = None
-    def __init__(self):
+
+    def __init__(self, **kwargs):
         self.machine = Machine(self._ARCH_)
         self.jitter = self.machine.jitter(self.options.jitter)
 
@@ -155,10 +163,12 @@ class OS_Win(OS):
                    "ole32.dll", "urlmon.dll",
                    "ws2_32.dll", 'advapi32.dll', "psapi.dll",
                ]
+    modules_path = "win_dll"
 
     def __init__(self, custom_methods, *args, **kwargs):
-        from miasm2.jitter.loader.pe import vm_load_pe, vm_load_pe_libs, preload_pe, libimp_pe
-        from miasm2.os_dep import win_api_x86_32
+        from miasm2.jitter.loader.pe import vm_load_pe, vm_load_pe_libs,\
+            preload_pe, libimp_pe, vm_load_pe_and_dependencies
+        from miasm2.os_dep import win_api_x86_32, win_api_x86_32_seh
         methods = win_api_x86_32.__dict__
         methods.update(custom_methods)
 
@@ -169,20 +179,35 @@ class OS_Win(OS):
         self.libs = libs
         win_api_x86_32.winobjs.runtime_dll = libs
 
+        self.name2module = {}
+        fname_basename = os.path.basename(self.fname).lower()
+
+        # Load main pe
+        with open(self.fname) as fstream:
+            self.pe = vm_load_pe(self.jitter.vm, fstream.read(), **kwargs)
+            self.name2module[fname_basename] = self.pe
+
         # Load library
         if self.options.loadbasedll:
-            all_pe = []
 
             # Load libs in memory
-            all_pe = vm_load_pe_libs(self.jitter.vm, self.ALL_IMP_DLL, libs)
+            self.name2module.update(vm_load_pe_libs(self.jitter.vm,
+                                                    self.ALL_IMP_DLL,
+                                                    libs,
+                                                    self.modules_path,
+                                                    **kwargs))
 
             # Patch libs imports
-            for pe in all_pe.values():
+            for pe in self.name2module.itervalues():
                 preload_pe(self.jitter.vm, pe, libs)
 
-        # Load main pe
-        with open(self.fname) as fstream:
-            self.pe = vm_load_pe(self.jitter.vm, fstream.read())
+        if self.options.dependencies:
+            vm_load_pe_and_dependencies(self.jitter.vm,
+                                        fname_basename,
+                                        self.name2module,
+                                        libs,
+                                        self.modules_path,
+                                        **kwargs)
 
         win_api_x86_32.winobjs.current_pe = self.pe
 
@@ -194,13 +219,15 @@ class OS_Win(OS):
 
         # Manage SEH
         if self.options.use_seh:
-            win_api_x86_32_seh.main_pe_name = self.fname
+            win_api_x86_32_seh.main_pe_name = fname_basename
             win_api_x86_32_seh.main_pe = self.pe
-            win_api_x86_32_seh.loaded_modules = self.ALL_IMP_DLL
+            win_api_x86_32.winobjs.hcurmodule = self.pe.NThdr.ImageBase
+            win_api_x86_32_seh.name2module = self.name2module
             win_api_x86_32_seh.init_seh(self.jitter)
             win_api_x86_32_seh.set_win_fs_0(self.jitter)
 
-        self.entry_point =  self.pe.rva2virt(self.pe.Opthdr.AddressOfEntryPoint)
+        self.entry_point = self.pe.rva2virt(
+            self.pe.Opthdr.AddressOfEntryPoint)
 
     @classmethod
     def update_parser(cls, parser):
@@ -230,7 +257,7 @@ class OS_Linux(OS):
         self.libs = libimp_elf()
 
         with open(self.fname) as fstream:
-            self.elf = vm_load_elf(self.jitter.vm, fstream.read())
+            self.elf = vm_load_elf(self.jitter.vm, fstream.read(), **kwargs)
         preload_elf(self.jitter.vm, self.elf, self.libs)
 
         self.entry_point = self.elf.Ehdr.entry
@@ -238,7 +265,9 @@ class OS_Linux(OS):
         # Library calls handler
         self.jitter.add_lib_handler(self.libs, methods)
 
+
 class OS_Linux_str(OS):
+
     def __init__(self, custom_methods, *args, **kwargs):
         from miasm2.jitter.loader.elf import libimp_elf
         from miasm2.os_dep import linux_stdlib
@@ -253,7 +282,8 @@ class OS_Linux_str(OS):
 
         data = open(self.fname).read()
         self.options.load_base_addr = int(self.options.load_base_addr, 0)
-        self.jitter.vm.add_memory_page(self.options.load_base_addr, PAGE_READ | PAGE_WRITE, data)
+        self.jitter.vm.add_memory_page(
+            self.options.load_base_addr, PAGE_READ | PAGE_WRITE, data)
 
         # Library calls handler
         self.jitter.add_lib_handler(libs, methods)
@@ -264,16 +294,16 @@ class OS_Linux_str(OS):
 
 
 class Arch_x86(Arch):
-    _ARCH_ = None # Arch name
+    _ARCH_ = None  # Arch name
     STACK_SIZE = 0x10000
     STACK_BASE = 0x130000
 
-    def __init__(self):
-        super(Arch_x86, self).__init__()
+    def __init__(self, **kwargs):
+        super(Arch_x86, self).__init__(**kwargs)
 
         if self.options.usesegm:
-            self.jitter.ir_arch.do_stk_segm=  True
-            self.jitter.ir_arch.do_ds_segm=  True
+            self.jitter.ir_arch.do_stk_segm = True
+            self.jitter.ir_arch.do_ds_segm = True
             self.jitter.ir_arch.do_str_segm = True
             self.jitter.ir_arch.do_all_segm = True
 
@@ -282,11 +312,10 @@ class Arch_x86(Arch):
         self.jitter.stack_base = self.STACK_BASE
         self.jitter.init_stack()
 
-
     @classmethod
     def update_parser(cls, parser):
         parser.add_argument('-s', "--usesegm", action="store_true",
-                          help="Use segments")
+                            help="Use segments")
 
 
 class Arch_x86_32(Arch_x86):
@@ -302,34 +331,36 @@ class Arch_arml(Arch):
     STACK_SIZE = 0x100000
     STACK_BASE = 0x100000
 
-    def __init__(self):
-        super(Arch_arml, self).__init__()
+    def __init__(self, **kwargs):
+        super(Arch_arml, self).__init__(**kwargs)
 
         # Init stack
         self.jitter.stack_size = self.STACK_SIZE
         self.jitter.stack_base = self.STACK_BASE
         self.jitter.init_stack()
 
+
 class Arch_armb(Arch):
     _ARCH_ = "armb"
     STACK_SIZE = 0x100000
     STACK_BASE = 0x100000
 
-    def __init__(self):
-        super(Arch_armb, self).__init__()
+    def __init__(self, **kwargs):
+        super(Arch_armb, self).__init__(**kwargs)
 
         # Init stack
         self.jitter.stack_size = self.STACK_SIZE
         self.jitter.stack_base = self.STACK_BASE
         self.jitter.init_stack()
 
+
 class Arch_aarch64l(Arch):
     _ARCH_ = "aarch64l"
     STACK_SIZE = 0x100000
     STACK_BASE = 0x100000
 
-    def __init__(self):
-        super(Arch_aarch64l, self).__init__()
+    def __init__(self, **kwargs):
+        super(Arch_aarch64l, self).__init__(**kwargs)
 
         # Init stack
         self.jitter.stack_size = self.STACK_SIZE
@@ -342,8 +373,8 @@ class Arch_aarch64b(Arch):
     STACK_SIZE = 0x100000
     STACK_BASE = 0x100000
 
-    def __init__(self):
-        super(Arch_aarch64b, self).__init__()
+    def __init__(self, **kwargs):
+        super(Arch_aarch64b, self).__init__(**kwargs)
 
         # Init stack
         self.jitter.stack_size = self.STACK_SIZE
@@ -351,7 +382,6 @@ class Arch_aarch64b(Arch):
         self.jitter.init_stack()
 
 
-
 class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win):
 
     def __init__(self, *args, **kwargs):
@@ -366,8 +396,7 @@ class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         """
         If addr is not set, use entrypoint
         """
@@ -391,8 +420,7 @@ class Sandbox_Win_x86_64(Sandbox, Arch_x86_64, OS_Win):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         """
         If addr is not set, use entrypoint
         """
@@ -415,8 +443,7 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         """
         If addr is not set, use entrypoint
         """
@@ -440,8 +467,7 @@ class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         """
         If addr is not set, use entrypoint
         """
@@ -460,12 +486,12 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         if addr is None and self.options.address is not None:
             addr = int(self.options.address, 16)
         super(Sandbox_Linux_arml, self).run(addr)
 
+
 class Sandbox_Linux_armb_str(Sandbox, Arch_armb, OS_Linux_str):
 
     def __init__(self, *args, **kwargs):
@@ -476,8 +502,7 @@ class Sandbox_Linux_armb_str(Sandbox, Arch_armb, OS_Linux_str):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         if addr is None and self.options.address is not None:
             addr = int(self.options.address, 0)
         super(Sandbox_Linux_armb_str, self).run(addr)
@@ -493,8 +518,7 @@ class Sandbox_Linux_arml_str(Sandbox, Arch_arml, OS_Linux_str):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         if addr is None and self.options.address is not None:
             addr = int(self.options.address, 0)
         super(Sandbox_Linux_arml_str, self).run(addr)
@@ -510,8 +534,7 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux):
         # Set the runtime guard
         self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle)
 
-
-    def run(self, addr = None):
+    def run(self, addr=None):
         if addr is None and self.options.address is not None:
             addr = int(self.options.address, 0)
         super(Sandbox_Linux_aarch64l, self).run(addr)
diff --git a/miasm2/jitter/loader/pe.py b/miasm2/jitter/loader/pe.py
index aaa7a469..32d92164 100644
--- a/miasm2/jitter/loader/pe.py
+++ b/miasm2/jitter/loader/pe.py
@@ -10,12 +10,24 @@ from elfesteem import *
 from miasm2.jitter.csts import *
 from miasm2.jitter.loader.utils import canon_libname_libfunc, libimp
 
-
 log = logging.getLogger('loader_pe')
 hnd = logging.StreamHandler()
 hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
 log.addHandler(hnd)
-log.setLevel(logging.CRITICAL)
+log.setLevel(logging.INFO)
+
+
+def get_pe_dependencies(pe_obj):
+    """Return dependency set
+    @pe_obj: pe object"""
+
+    if pe_obj.DirImport.impdesc is None:
+        return set()
+    out = set()
+    for dependency in pe_obj.DirImport.impdesc:
+        libname = dependency.dlldescname.name.lower()
+        out.add(libname)
+    return out
 
 
 def get_import_address_pe(e):
@@ -101,6 +113,7 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, **kargs):
     If all sections are aligned, they will be mapped on several different pages
     Otherwise, a big page is created, containing all sections
     """
+
     # Parse and build a PE instance
     pe = pe_init.PE(fdata, **kargs)
 
@@ -197,6 +210,9 @@ def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs):
     Return the corresponding PE instance
     Extra arguments are passed to vm_load_pe
     """
+
+    log.info('Loading module %r', fname_in)
+
     fname = os.path.join(lib_path_base, fname_in)
     with open(fname) as fstream:
         pe = vm_load_pe(vm, fstream.read(), **kargs)
@@ -204,7 +220,7 @@ def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs):
     return pe
 
 
-def vm_load_pe_libs(vm, libs_name, libs, lib_path_base="win_dll", **kargs):
+def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs):
     """Call vm_load_pe_lib on each @libs_name filename
     @vm: VmMngr instance
     @libs_name: list of str
@@ -217,7 +233,7 @@ def vm_load_pe_libs(vm, libs_name, libs, lib_path_base="win_dll", **kargs):
             for fname in libs_name}
 
 
-def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base="win_dll",
+def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base,
                            patch_vm_imp=True, **kargs):
     for e in lib_imgs.values():
         preload_pe(e, libs, patch_vm_imp)
@@ -226,7 +242,7 @@ def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base="win_dll",
 def vm2pe(myjit, fname, libs=None, e_orig=None,
           min_addr=None, max_addr=None,
           min_section_offset=0x1000, img_base=None,
-          added_funcs=None):
+          added_funcs=None, **kwargs):
     if e_orig:
         size = e_orig._wsize
     else:
@@ -272,7 +288,9 @@ def vm2pe(myjit, fname, libs=None, e_orig=None,
                 libbase, dllname = libs.fad2info[funcaddr]
                 libs.lib_get_add_func(libbase, dllname, addr)
 
-        new_dll = libs.gen_new_lib(mye, mye.virt.is_addr_in)
+        filter_import = kwargs.get(
+            'filter_import', lambda _, ad: mye.virt.is_addr_in(ad))
+        new_dll = libs.gen_new_lib(mye, filter_import)
     else:
         new_dll = {}
 
@@ -303,11 +321,26 @@ def vm2pe(myjit, fname, libs=None, e_orig=None,
 
 class libimp_pe(libimp):
 
+    def __init__(self, *args, **kwargs):
+        super(libimp_pe, self).__init__(*args, **kwargs)
+        # dependency -> redirector
+        self.created_redirected_imports = {}
+
     def add_export_lib(self, e, name):
+        if name in self.created_redirected_imports:
+            log.error("%r has previously been created due to redirect\
+            imports due to %r. Change the loading order.",
+                      name, self.created_redirected_imports[name])
+            raise RuntimeError('Bad import: loading previously created import')
+
         self.all_exported_lib.append(e)
         # will add real lib addresses to database
         if name in self.name2off:
             ad = self.name2off[name]
+            if e is not None and name in self.fake_libs:
+                log.error(
+                    "You are trying to load %r but it has been faked previously. Try loading this module earlier.", name)
+                raise RuntimeError("Bad import")
         else:
             log.debug('new lib %s', name)
             ad = e.NThdr.ImageBase
@@ -330,8 +363,6 @@ class libimp_pe(libimp):
                 ret = is_redirected_export(e, ad)
                 if ret:
                     exp_dname, exp_fname = ret
-                    # log.debug('export redirection %s' % imp_ord_or_name)
-                    # log.debug('source %s %s' % (exp_dname, exp_fname))
                     exp_dname = exp_dname + '.dll'
                     exp_dname = exp_dname.lower()
                     # if dll auto refes in redirection
@@ -341,17 +372,21 @@ class libimp_pe(libimp):
                             # schedule func
                             todo = [(imp_ord_or_name, ad)] + todo
                             continue
-                    elif not exp_dname in self.name2off:
-                        raise ValueError('load %r first' % exp_dname)
+                    else:
+                        # import redirected lib from non loaded dll
+                        if not exp_dname in self.name2off:
+                            self.created_redirected_imports.setdefault(
+                                exp_dname, set()).add(name)
+
+                        # Ensure import entry is created
+                        new_lib_base = self.lib_get_add_base(exp_dname)
+                        # Ensure function entry is created
+                        _ = self.lib_get_add_func(new_lib_base, exp_fname)
+
                     c_name = canon_libname_libfunc(exp_dname, exp_fname)
                     libad_tmp = self.name2off[exp_dname]
                     ad = self.lib_imp2ad[libad_tmp][exp_fname]
-                    # log.debug('%s' % hex(ad))
-                # if not imp_ord_or_name in self.lib_imp2dstad[libad]:
-                #    self.lib_imp2dstad[libad][imp_ord_or_name] = set()
-                # self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad)
 
-                # log.debug('new imp %s %s' % (imp_ord_or_name, hex(ad)))
                 self.lib_imp2ad[libad][imp_ord_or_name] = ad
 
                 name_inv = dict([(x[1], x[0]) for x in self.name2off.items()])
@@ -360,10 +395,10 @@ class libimp_pe(libimp):
                 self.fad2cname[ad] = c_name
                 self.fad2info[ad] = libad, imp_ord_or_name
 
-    def gen_new_lib(self, target_pe, flt=lambda _: True):
+    def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs):
         """Gen a new DirImport description
         @target_pe: PE instance
-        @flt: (boolean f(address)) restrict addresses to keep
+        @filter_import: (boolean f(pe, address)) restrict addresses to keep
         """
 
         new_lib = []
@@ -375,8 +410,9 @@ class libimp_pe(libimp):
             for func_name, dst_addresses in self.lib_imp2dstad[ad].items():
                 out_ads.update({addr: func_name for addr in dst_addresses})
 
-            # Filter available addresses according to @flt
-            all_ads = [addr for addr in out_ads.keys() if flt(addr)]
+            # Filter available addresses according to @filter_import
+            all_ads = [
+                addr for addr in out_ads.keys() if filter_import(target_pe, addr)]
             log.debug('ads: %s', map(hex, all_ads))
             if not all_ads:
                 continue
@@ -414,6 +450,67 @@ class libimp_pe(libimp):
 
         return new_lib
 
+
+def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib,
+                                lib_path_base, **kwargs):
+    """Load a binary and all its dependencies. Returns a dictionnary containing
+    the association between binaries names and it's pe object
+
+    @vm: virtual memory manager instance
+    @fname: full path of the binary
+    @name2module: dict containing association between name and pe
+    object. Updated.
+    @runtime_lib: libimp instance
+    @lib_path_base: directory of the libraries containing dependencies
+
+    """
+
+    todo = [(fname, fname, 0)]
+    dependencies = []
+    weight2name = {}
+    done = set()
+
+    # Walk dependencies recursively
+    while todo:
+        name, fname, weight = todo.pop()
+        if name in done:
+            continue
+        done.add(name)
+        weight2name.setdefault(weight, set()).add(name)
+        if name in name2module:
+            pe_obj = name2module[name]
+        else:
+            try:
+                with open(fname) as fstream:
+                    log.info('Loading module name %r', fname)
+                    pe_obj = vm_load_pe(vm, fstream.read(), **kwargs)
+            except IOError:
+                log.error('Cannot open %s' % fname)
+                name2module[name] = None
+                continue
+            name2module[name] = pe_obj
+
+        new_dependencies = get_pe_dependencies(pe_obj)
+        todo += [(name, os.path.join(lib_path_base, name), weight - 1)
+                 for name in new_dependencies]
+
+    ordered_modules = sorted(weight2name.items())
+    for _, modules in ordered_modules:
+        for name in modules:
+            pe_obj = name2module[name]
+            if pe_obj is None:
+                continue
+            # Fix imports
+            if pe_obj.DirExport:
+                runtime_lib.add_export_lib(pe_obj, name)
+
+    for pe_obj in name2module.itervalues():
+        if pe_obj is None:
+            continue
+        preload_pe(vm, pe_obj, runtime_lib, patch_vm_imp=True)
+
+    return name2module
+
 # machine -> arch
 PE_machine = {0x14c: "x86_32",
               0x8664: "x86_64",
diff --git a/miasm2/jitter/loader/utils.py b/miasm2/jitter/loader/utils.py
index a6a19cb3..83d1a796 100644
--- a/miasm2/jitter/loader/utils.py
+++ b/miasm2/jitter/loader/utils.py
@@ -4,7 +4,7 @@ log = logging.getLogger('loader_common')
 hnd = logging.StreamHandler()
 hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
 log.addHandler(hnd)
-log.setLevel(logging.CRITICAL)
+log.setLevel(logging.INFO)
 
 
 def canon_libname_libfunc(libname, libfunc):
@@ -15,7 +15,7 @@ def canon_libname_libfunc(libname, libfunc):
         return str(dn), libfunc
 
 
-class libimp:
+class libimp(object):
 
     def __init__(self, lib_base_ad=0x71111000, **kargs):
         self.name2off = {}
@@ -26,6 +26,7 @@ class libimp:
         self.fad2cname = {}
         self.fad2info = {}
         self.all_exported_lib = []
+        self.fake_libs = set()
 
     def lib_get_add_base(self, name):
         name = name.lower().strip(' ')
@@ -38,7 +39,8 @@ class libimp:
             ad = self.name2off[name]
         else:
             ad = self.libbase_ad
-            log.debug('new lib %s 0x%x', name, ad)
+            log.warning("Create dummy entry for %r", name)
+            self.fake_libs.add(name)
             self.name2off[name] = ad
             self.libbase2lastad[ad] = ad + 0x1
             self.lib_imp2ad[ad] = {}
diff --git a/miasm2/os_dep/win_api_x86_32_seh.py b/miasm2/os_dep/win_api_x86_32_seh.py
index d86bd46a..58cc48af 100644
--- a/miasm2/os_dep/win_api_x86_32_seh.py
+++ b/miasm2/os_dep/win_api_x86_32_seh.py
@@ -80,7 +80,7 @@ FAKE_SEH_B_AD = context_address + 0x2000
 
 cur_seh_ad = FAKE_SEH_B_AD
 
-loaded_modules = ["ntdll.dll", "kernel32.dll"]
+name2module = []
 main_pe = None
 main_pe_name = "c:\\xxx\\toto.exe"
 
@@ -206,11 +206,10 @@ class LoadedModules(object):
         self.module2name[module] = name
 
     def __repr__(self):
-        out = self.name2module.iteritems()
-        return "\n".join(out)
+        return "\n".join([str(x) for x in self.name2module.iteritems()])
 
 
-def create_modules_chain(jitter, modules_name):
+def create_modules_chain(jitter, name2module):
     """
     Create the modules entries. Those modules are not linked in this function.
 
@@ -235,7 +234,7 @@ def create_modules_chain(jitter, modules_name):
     +0x04c PatchInformation : Ptr32 Void
 
     @jitter: jitter instance
-    @modules_name: a list of modules names
+    @name2module: dict containing association between name and its pe instance
     """
 
     modules_info = LoadedModules()
@@ -249,31 +248,18 @@ def create_modules_chain(jitter, modules_name):
     dummy_e.NThdr.sizeofimage = 0
 
     out = ""
-    for i, m in enumerate([(main_pe_name, main_pe),
-                           ("", dummy_e)] + modules_name):
+    for i, (fname, pe_obj) in enumerate([("", dummy_e)] + name2module.items()):
+        if pe_obj is None:
+            log.warning("Unknown module: ommited from link list (%r)",
+                        fname)
+            continue
         addr = base_addr + i * 0x1000
-        if isinstance(m, tuple):
-            fname, e = m
-        else:
-            fname, e = m, None
         bpath = fname.replace('/', '\\')
         bname_str = os.path.split(fname)[1].lower()
         bname = "\x00".join(bname_str) + "\x00"
-        if e is None:
-            if i == 0:
-                full_name = fname
-            else:
-                full_name = os.path.join("win_dll", fname)
-            try:
-                e = pe_init.PE(open(full_name, 'rb').read())
-            except IOError:
-                log.error('No main pe, ldr data will be unconsistant!')
-                e = None
-        if e is None:
-            continue
-        log.info("Add module %x %r", e.NThdr.ImageBase, bname_str)
+        log.info("Add module %x %r", pe_obj.NThdr.ImageBase, bname_str)
 
-        modules_info.add(bname_str, e, addr)
+        modules_info.add(bname_str, pe_obj, addr)
 
         m_o = ""
         m_o += pck32(0)
@@ -282,9 +268,9 @@ def create_modules_chain(jitter, modules_name):
         m_o += pck32(0)
         m_o += pck32(0)
         m_o += pck32(0)
-        m_o += pck32(e.NThdr.ImageBase)
-        m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
-        m_o += pck32(e.NThdr.sizeofimage)
+        m_o += pck32(pe_obj.NThdr.ImageBase)
+        m_o += pck32(pe_obj.rva2virt(pe_obj.Opthdr.AddressOfEntryPoint))
+        m_o += pck32(pe_obj.NThdr.sizeofimage)
         m_o += struct.pack('HH', len(bname), len(bname) + 2)
         m_o += pck32(addr + offset_path)
         m_o += struct.pack('HH', len(bname), len(bname) + 2)
@@ -321,7 +307,7 @@ def fix_InLoadOrderModuleList(jitter, modules_info):
     dummy_pe = modules_info.name2module.get("", None)
     special_modules = [main_pe, kernel32_pe, ntdll_pe, dummy_pe]
     if not all(special_modules):
-        log.warn('No main pe, ldr data will be unconsistant')
+        log.warn('No main pe, ldr data will be unconsistant %r', special_modules)
         loaded_modules = modules_info.modules
     else:
         loaded_modules = [module for module in modules_info.modules
@@ -461,7 +447,7 @@ def init_seh(jitter):
     build_teb(jitter, FS_0_AD)
     build_peb(jitter, peb_address)
 
-    modules_info = create_modules_chain(jitter, loaded_modules)
+    modules_info = create_modules_chain(jitter, name2module)
     fix_InLoadOrderModuleList(jitter, modules_info)
     fix_InMemoryOrderModuleList(jitter, modules_info)
     fix_InInitializationOrderModuleList(jitter, modules_info)