diff options
| -rw-r--r-- | miasm2/jitter/loader/elf.py | 5 | ||||
| -rw-r--r-- | miasm2/jitter/loader/pe.py | 115 | ||||
| -rw-r--r-- | miasm2/jitter/loader/utils.py | 110 |
3 files changed, 118 insertions, 112 deletions
diff --git a/miasm2/jitter/loader/elf.py b/miasm2/jitter/loader/elf.py index 9a81c4f7..528ff4f5 100644 --- a/miasm2/jitter/loader/elf.py +++ b/miasm2/jitter/loader/elf.py @@ -5,7 +5,7 @@ from elfesteem import pe from elfesteem import cstruct from elfesteem import * from miasm2.jitter.csts import * -from utils import canon_libname_libfunc +from utils import canon_libname_libfunc, libimp from miasm2.core.interval import interval import logging @@ -78,3 +78,6 @@ def vm_load_elf(vm, fname, **kargs): for r_vaddr, data in all_data.items(): vm.set_mem(r_vaddr, data) return e + +class libimp_elf(libimp): + pass diff --git a/miasm2/jitter/loader/pe.py b/miasm2/jitter/loader/pe.py index c0053f35..f492cba3 100644 --- a/miasm2/jitter/loader/pe.py +++ b/miasm2/jitter/loader/pe.py @@ -5,7 +5,7 @@ from elfesteem import pe from elfesteem import cstruct from elfesteem import * from miasm2.jitter.csts import * -from utils import canon_libname_libfunc +from utils import canon_libname_libfunc, libimp import logging @@ -255,3 +255,116 @@ def vm2pe(myjit, fname, libs=None, e_orig=None, # generation open(fname, 'w').write(str(mye)) return mye + + +class libimp_pe(libimp): + + def add_export_lib(self, e, name): + self.all_exported_lib.append(e) + # will add real lib addresses to database + if name in self.name2off: + ad = self.name2off[name] + else: + log.debug('new lib %s' % name) + ad = e.NThdr.ImageBase + libad = ad + self.name2off[name] = ad + self.libbase2lastad[ad] = ad + 0x1 + self.lib_imp2ad[ad] = {} + self.lib_imp2dstad[ad] = {} + self.libbase_ad += 0x1000 + + ads = get_export_name_addr_list(e) + todo = ads + # done = [] + while todo: + # for imp_ord_or_name, ad in ads: + imp_ord_or_name, ad = todo.pop() + + # if export is a redirection, search redirected dll + # and get function real addr + 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 + if exp_dname == name: + libad_tmp = self.name2off[exp_dname] + if not exp_fname in self.lib_imp2ad[libad_tmp]: + # schedule func + todo = [(imp_ord_or_name, ad)] + todo + continue + elif not exp_dname in self.name2off: + raise ValueError('load %r first' % exp_dname) + 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()]) + c_name = canon_libname_libfunc( + name_inv[libad], imp_ord_or_name) + self.fad2cname[ad] = c_name + self.fad2info[ad] = libad, imp_ord_or_name + + def gen_new_lib(self, target_pe, filter=lambda _: True): + """Gen a new DirImport description + @target_pe: PE instance + @filter: (boolean f(address)) restrict addresses to keep + """ + + new_lib = [] + for lib_name, ad in self.name2off.items(): + # Build an IMAGE_IMPORT_DESCRIPTOR + + # Get fixed addresses + out_ads = dict() # addr -> func_name + 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 @filter + all_ads = [addr for addr in out_ads.keys() if filter(addr)] + log.debug('ads: %s' % map(hex, all_ads)) + if not all_ads: + continue + + # Keep non-NULL elements + all_ads.sort() + for i, x in enumerate(all_ads): + if x not in [0, None]: + break + all_ads = all_ads[i:] + + while all_ads: + # Find libname's Import Address Table + othunk = all_ads[0] + i = 0 + while i + 1 < len(all_ads) and all_ads[i] + 4 == all_ads[i + 1]: + i += 1 + # 'i + 1' is IAT's length + + # Effectively build an IMAGE_IMPORT_DESCRIPTOR + funcs = [out_ads[addr] for addr in all_ads[:i + 1]] + try: + rva = target_pe.virt2rva(othunk) + except pe.InvalidOffset: + pass + else: + new_lib.append(({"name": lib_name, + "firstthunk": rva}, + funcs) + ) + + # Update elements to handle + all_ads = all_ads[i + 1:] + + return new_lib diff --git a/miasm2/jitter/loader/utils.py b/miasm2/jitter/loader/utils.py index de269f83..9305e713 100644 --- a/miasm2/jitter/loader/utils.py +++ b/miasm2/jitter/loader/utils.py @@ -84,114 +84,4 @@ class libimp: return False return True - def add_export_lib(self, e, name): - self.all_exported_lib.append(e) - # will add real lib addresses to database - if name in self.name2off: - ad = self.name2off[name] - else: - log.debug('new lib %s' % name) - ad = e.NThdr.ImageBase - libad = ad - self.name2off[name] = ad - self.libbase2lastad[ad] = ad + 0x1 - self.lib_imp2ad[ad] = {} - self.lib_imp2dstad[ad] = {} - self.libbase_ad += 0x1000 - - ads = get_export_name_addr_list(e) - todo = ads - # done = [] - while todo: - # for imp_ord_or_name, ad in ads: - imp_ord_or_name, ad = todo.pop() - - # if export is a redirection, search redirected dll - # and get function real addr - 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 - if exp_dname == name: - libad_tmp = self.name2off[exp_dname] - if not exp_fname in self.lib_imp2ad[libad_tmp]: - # schedule func - todo = [(imp_ord_or_name, ad)] + todo - continue - elif not exp_dname in self.name2off: - raise ValueError('load %r first' % exp_dname) - 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()]) - c_name = canon_libname_libfunc( - name_inv[libad], imp_ord_or_name) - self.fad2cname[ad] = c_name - self.fad2info[ad] = libad, imp_ord_or_name - - def gen_new_lib(self, target_pe, filter=lambda _: True): - """Gen a new DirImport description - @target_pe: PE instance - @filter: (boolean f(address)) restrict addresses to keep - """ - - new_lib = [] - for lib_name, ad in self.name2off.items(): - # Build an IMAGE_IMPORT_DESCRIPTOR - - # Get fixed addresses - out_ads = dict() # addr -> func_name - 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 @filter - all_ads = [addr for addr in out_ads.keys() if filter(addr)] - log.debug('ads: %s' % map(hex, all_ads)) - if not all_ads: - continue - - # Keep non-NULL elements - all_ads.sort() - for i, x in enumerate(all_ads): - if x not in [0, None]: - break - all_ads = all_ads[i:] - - while all_ads: - # Find libname's Import Address Table - othunk = all_ads[0] - i = 0 - while i + 1 < len(all_ads) and all_ads[i] + 4 == all_ads[i + 1]: - i += 1 - # 'i + 1' is IAT's length - - # Effectively build an IMAGE_IMPORT_DESCRIPTOR - funcs = [out_ads[addr] for addr in all_ads[:i + 1]] - try: - rva = target_pe.virt2rva(othunk) - except pe.InvalidOffset: - pass - else: - new_lib.append(({"name": lib_name, - "firstthunk": rva}, - funcs) - ) - - # Update elements to handle - all_ads = all_ads[i + 1:] - - return new_lib - |