diff options
| -rw-r--r-- | miasm2/core/asmbloc.py | 412 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore.py | 42 | ||||
| -rw-r--r-- | miasm2/os_dep/win_api_x86_32_seh.py | 80 |
3 files changed, 267 insertions, 267 deletions
diff --git a/miasm2/core/asmbloc.py b/miasm2/core/asmbloc.py index 96c2f4ec..54cd51cf 100644 --- a/miasm2/core/asmbloc.py +++ b/miasm2/core/asmbloc.py @@ -410,183 +410,6 @@ class asm_symbol_pool: return label -def dis_bloc(mnemo, pool_bin, label, offset, job_done, symbol_pool, - dont_dis=None, split_dis=None, follow_call=False, - dontdis_retcall=False, lines_wd=None, dis_bloc_callback=None, - dont_dis_nulstart_bloc=False, attrib=None): - # pool_bin.offset = offset - if dont_dis is None: - dont_dis = [] - if split_dis is None: - split_dis = [] - if attrib is None: - attrib = {} - lines_cpt = 0 - in_delayslot = False - delayslot_count = mnemo.delayslot - offsets_to_dis = set() - add_next_offset = False - cur_block = asm_bloc(label) - log_asmbloc.debug("dis at %X", int(offset)) - while not in_delayslot or delayslot_count > 0: - if in_delayslot: - delayslot_count -= 1 - - if offset in dont_dis: - if not cur_block.lines: - job_done.add(offset) - # Block is empty -> bad block - cur_block = asm_block_bad(label, errno=2) - else: - # Block is not empty, stop the desassembly pass and add a - # constraint to the next block - cur_block.add_cst(offset, asm_constraint.c_next, symbol_pool) - break - - if lines_cpt > 0 and offset in split_dis: - cur_block.add_cst(offset, asm_constraint.c_next, symbol_pool) - offsets_to_dis.add(offset) - break - - lines_cpt += 1 - if lines_wd is not None and lines_cpt > lines_wd: - # log_asmbloc.warning( "lines watchdog reached at %X"%int(offset)) - break - - if offset in job_done: - cur_block.add_cst(offset, asm_constraint.c_next, symbol_pool) - break - - off_i = offset - try: - instr = mnemo.dis(pool_bin, attrib, offset) - except (Disasm_Exception, IOError), e: - log_asmbloc.warning(e) - instr = None - - if instr is None: - log_asmbloc.warning("cannot disasm at %X", int(off_i)) - if not cur_block.lines: - job_done.add(offset) - # Block is empty -> bad block - cur_block = asm_block_bad(label, errno=0) - else: - # Block is not empty, stop the desassembly pass and add a - # constraint to the next block - cur_block.add_cst(off_i, asm_constraint.c_next, symbol_pool) - break - - # XXX TODO nul start block option - if dont_dis_nulstart_bloc and instr.b.count('\x00') == instr.l: - log_asmbloc.warning("reach nul instr at %X", int(off_i)) - if not cur_block.lines: - # Block is empty -> bad block - cur_block = asm_block_bad(label, errno=1) - else: - # Block is not empty, stop the desassembly pass and add a - # constraint to the next block - cur_block.add_cst(off_i, asm_constraint.c_next, symbol_pool) - break - - # special case: flow graph modificator in delayslot - if in_delayslot and instr and (instr.splitflow() or instr.breakflow()): - add_next_offset = True - break - - job_done.add(offset) - log_asmbloc.debug("dis at %X", int(offset)) - - offset += instr.l - log_asmbloc.debug(instr) - log_asmbloc.debug(instr.args) - - cur_block.addline(instr) - if not instr.breakflow(): - continue - # test split - if instr.splitflow() and not (instr.is_subcall() and dontdis_retcall): - add_next_offset = True - # cur_bloc.add_cst(n, asm_constraint.c_next, symbol_pool) - pass - if instr.dstflow(): - instr.dstflow2label(symbol_pool) - dst = instr.getdstflow(symbol_pool) - dstn = [] - for d in dst: - if isinstance(d, m2_expr.ExprId) and \ - isinstance(d.name, asm_label): - dstn.append(d.name) - dst = dstn - if (not instr.is_subcall()) or follow_call: - cur_block.bto.update( - [asm_constraint(x, asm_constraint.c_to) for x in dst]) - - # get in delayslot mode - in_delayslot = True - delayslot_count = instr.delayslot - - for c in cur_block.bto: - offsets_to_dis.add(c.label.offset) - - if add_next_offset: - cur_block.add_cst(offset, asm_constraint.c_next, symbol_pool) - offsets_to_dis.add(offset) - - # Fix multiple constraints - cur_block.fix_constraints() - - if dis_bloc_callback is not None: - dis_bloc_callback(mn=mnemo, attrib=attrib, pool_bin=pool_bin, - cur_bloc=cur_block, offsets_to_dis=offsets_to_dis, - symbol_pool=symbol_pool) - # print 'dst', [hex(x) for x in offsets_to_dis] - return cur_block, offsets_to_dis - - -def dis_bloc_all(mnemo, pool_bin, offset, job_done, symbol_pool, dont_dis=None, - split_dis=None, follow_call=False, dontdis_retcall=False, - blocs_wd=None, lines_wd=None, blocs=None, - dis_bloc_callback=None, dont_dis_nulstart_bloc=False, - attrib=None): - log_asmbloc.info("dis bloc all") - if dont_dis is None: - dont_dis = [] - if split_dis is None: - split_dis = [] - if attrib is None: - attrib = {} - if blocs is None: - blocs = AsmCFG() - todo = [offset] - - bloc_cpt = 0 - while len(todo): - bloc_cpt += 1 - if blocs_wd is not None and bloc_cpt > blocs_wd: - log_asmbloc.debug("blocs watchdog reached at %X", int(offset)) - break - - n = int(todo.pop(0)) - if n is None: - continue - if n in job_done: - continue - label = symbol_pool.getby_offset_create(n) - cur_block, nexts = dis_bloc(mnemo, pool_bin, label, n, job_done, - symbol_pool, dont_dis, split_dis, - follow_call, dontdis_retcall, - dis_bloc_callback=dis_bloc_callback, - lines_wd=lines_wd, - dont_dis_nulstart_bloc=dont_dis_nulstart_bloc, - attrib=attrib) - todo += nexts - blocs.add_node(cur_block) - - blocs.apply_splitting(symbol_pool, dis_block_callback=dis_bloc_callback, - mn=mnemo, attrib=attrib, pool_bin=pool_bin) - return blocs - - class AsmCFG(DiGraph): """Directed graph standing for a ASM Control Flow Graph with: @@ -1433,11 +1256,50 @@ def asm_resolve_final(mnemo, blocks, symbol_pool, dst_interval=None): class disasmEngine(object): - def __init__(self, arch, attrib, bs=None, **kwargs): + """Disassembly engine, taking care of disassembler options and mutli-block + strategy. + + Engine options: + + + Object supporting membership test (offset in ..) + - dont_dis: stop the current disassembly branch if reached + - split_dis: force a basic block end if reached, + with a next constraint on its successor + + + On/Off + - follow_call: recursively disassemble CALL destinations + - dontdis_retcall: stop on CALL return addresses + - dont_dis_nulstart_bloc: stop if a block begin with a few \x00 + + + Number + - lines_wd: maximum block's size (in number of instruction) + - blocs_wd: maximum number of distinct disassembled block + + + callback(arch, attrib, pool_bin, cur_bloc, offsets_to_dis, + symbol_pool) + - dis_bloc_callback: callback after each new disassembled block + + The engine also tracks already handled block, for performance and to avoid + infinite cycling. + Addresses of disassembled block is in the attribute `job_done`. + To force a new disassembly, the targeted offset must first be removed from + this structure. + """ + + def __init__(self, arch, attrib, bin_stream, **kwargs): + """Instanciate a new disassembly engine + @arch: targeted architecture + @attrib: architecture attribute + @bin_stream: bytes source + @kwargs: (optional) custom options + """ self.arch = arch self.attrib = attrib - self.bs = bs + self.bin_stream = bin_stream self.symbol_pool = asm_symbol_pool() + self.job_done = set() + + # Setup options self.dont_dis = [] self.split_dis = [] self.follow_call = False @@ -1446,33 +1308,179 @@ class disasmEngine(object): self.blocs_wd = None self.dis_bloc_callback = None self.dont_dis_nulstart_bloc = False - self.job_done = set() + + # Override options if needed self.__dict__.update(kwargs) - def dis_bloc(self, offset): + def _dis_bloc(self, offset): + """Disassemble the block at offset @offset + Return the created asm_bloc and future offsets to disassemble + """ + + lines_cpt = 0 + in_delayslot = False + delayslot_count = self.arch.delayslot + offsets_to_dis = set() + add_next_offset = False label = self.symbol_pool.getby_offset_create(offset) - current_block, _ = dis_bloc(self.arch, self.bs, label, offset, - self.job_done, self.symbol_pool, - dont_dis=self.dont_dis, - split_dis=self.split_dis, - follow_call=self.follow_call, - dontdis_retcall=self.dontdis_retcall, - lines_wd=self.lines_wd, - dis_bloc_callback=self.dis_bloc_callback, - dont_dis_nulstart_bloc=self.dont_dis_nulstart_bloc, - attrib=self.attrib) + cur_block = asm_bloc(label) + log_asmbloc.debug("dis at %X", int(offset)) + while not in_delayslot or delayslot_count > 0: + if in_delayslot: + delayslot_count -= 1 + + if offset in self.dont_dis: + if not cur_block.lines: + self.job_done.add(offset) + # Block is empty -> bad block + cur_block = asm_block_bad(label, errno=2) + else: + # Block is not empty, stop the desassembly pass and add a + # constraint to the next block + cur_block.add_cst(offset, asm_constraint.c_next, + self.symbol_pool) + break + + if lines_cpt > 0 and offset in self.split_dis: + cur_block.add_cst(offset, asm_constraint.c_next, + self.symbol_pool) + offsets_to_dis.add(offset) + break + + lines_cpt += 1 + if self.lines_wd is not None and lines_cpt > self.lines_wd: + log_asmbloc.debug("lines watchdog reached at %X", int(offset)) + break + + if offset in self.job_done: + cur_block.add_cst(offset, asm_constraint.c_next, + self.symbol_pool) + break + + off_i = offset + try: + instr = self.arch.dis(self.bin_stream, self.attrib, offset) + except (Disasm_Exception, IOError), e: + log_asmbloc.warning(e) + instr = None + + if instr is None: + log_asmbloc.warning("cannot disasm at %X", int(off_i)) + if not cur_block.lines: + self.job_done.add(offset) + # Block is empty -> bad block + cur_block = asm_block_bad(label, errno=0) + else: + # Block is not empty, stop the desassembly pass and add a + # constraint to the next block + cur_block.add_cst(off_i, asm_constraint.c_next, + self.symbol_pool) + break + + # XXX TODO nul start block option + if self.dont_dis_nulstart_bloc and instr.b.count('\x00') == instr.l: + log_asmbloc.warning("reach nul instr at %X", int(off_i)) + if not cur_block.lines: + # Block is empty -> bad block + cur_block = asm_block_bad(label, errno=1) + else: + # Block is not empty, stop the desassembly pass and add a + # constraint to the next block + cur_block.add_cst(off_i, asm_constraint.c_next, + self.symbol_pool) + break + + # special case: flow graph modificator in delayslot + if in_delayslot and instr and (instr.splitflow() or instr.breakflow()): + add_next_offset = True + break + + self.job_done.add(offset) + log_asmbloc.debug("dis at %X", int(offset)) + + offset += instr.l + log_asmbloc.debug(instr) + log_asmbloc.debug(instr.args) + + cur_block.addline(instr) + if not instr.breakflow(): + continue + # test split + if instr.splitflow() and not (instr.is_subcall() and self.dontdis_retcall): + add_next_offset = True + pass + if instr.dstflow(): + instr.dstflow2label(self.symbol_pool) + dst = instr.getdstflow(self.symbol_pool) + dstn = [] + for d in dst: + if isinstance(d, m2_expr.ExprId) and \ + isinstance(d.name, asm_label): + dstn.append(d.name) + dst = dstn + if (not instr.is_subcall()) or self.follow_call: + cur_block.bto.update( + [asm_constraint(x, asm_constraint.c_to) for x in dst]) + + # get in delayslot mode + in_delayslot = True + delayslot_count = instr.delayslot + + for c in cur_block.bto: + offsets_to_dis.add(c.label.offset) + + if add_next_offset: + cur_block.add_cst(offset, asm_constraint.c_next, self.symbol_pool) + offsets_to_dis.add(offset) + + # Fix multiple constraints + cur_block.fix_constraints() + + if self.dis_bloc_callback is not None: + self.dis_bloc_callback(mn=self.arch, attrib=self.attrib, + pool_bin=self.bin_stream, cur_bloc=cur_block, + offsets_to_dis=offsets_to_dis, + symbol_pool=self.symbol_pool) + return cur_block, offsets_to_dis + + def dis_bloc(self, offset): + """Disassemble the block at offset @offset and return the created + asm_bloc + @offset: targeted offset to disassemble + """ + current_block, _ = self._dis_bloc(offset) return current_block def dis_multibloc(self, offset, blocs=None): - blocs = dis_bloc_all(self.arch, self.bs, offset, self.job_done, - self.symbol_pool, - dont_dis=self.dont_dis, split_dis=self.split_dis, - follow_call=self.follow_call, - dontdis_retcall=self.dontdis_retcall, - blocs_wd=self.blocs_wd, - lines_wd=self.lines_wd, - blocs=blocs, - dis_bloc_callback=self.dis_bloc_callback, - dont_dis_nulstart_bloc=self.dont_dis_nulstart_bloc, - attrib=self.attrib) + """Disassemble every block reachable from @offset regarding + specific disasmEngine conditions + Return an AsmCFG instance containing disassembled blocks + @offset: starting offset + @blocs: (optional) AsmCFG instance of already disassembled blocks to + merge with + """ + log_asmbloc.info("dis bloc all") + if blocs is None: + blocs = AsmCFG() + todo = [offset] + + bloc_cpt = 0 + while len(todo): + bloc_cpt += 1 + if self.blocs_wd is not None and bloc_cpt > self.blocs_wd: + log_asmbloc.debug("blocs watchdog reached at %X", int(offset)) + break + + target_offset = int(todo.pop(0)) + if (target_offset is None or + target_offset in self.job_done): + continue + cur_block, nexts = self._dis_bloc(target_offset) + todo += nexts + blocs.add_node(cur_block) + + blocs.apply_splitting(self.symbol_pool, + dis_block_callback=self.dis_bloc_callback, + mn=self.arch, attrib=self.attrib, + pool_bin=self.bin_stream) return blocs diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py index 59e7b752..74c438a7 100644 --- a/miasm2/jitter/jitcore.py +++ b/miasm2/jitter/jitcore.py @@ -56,6 +56,15 @@ class JitCore(object): self.options = {"jit_maxline": 50 # Maximum number of line jitted } + self.mdis = asmbloc.disasmEngine(ir_arch.arch, ir_arch.attrib, bs, + lines_wd=self.options["jit_maxline"], + symbol_pool=ir_arch.symbol_pool, + follow_call=False, + dontdis_retcall=False, + split_dis=self.split_dis, + dis_bloc_callback=self.disasm_cb) + + def set_options(self, **kwargs): "Set options relative to the backend" @@ -76,9 +85,8 @@ class JitCore(object): """The disassembly engine will no longer stop on address in args""" self.split_dis.difference_update(set(args)) - def load(self, arch, attrib): - "Initialise the Jitter according to arch and attrib" - + def load(self): + "Initialise the Jitter" raise NotImplementedError("Abstract class") def get_bloc_min_max(self, cur_bloc): @@ -114,26 +122,24 @@ class JitCore(object): b.irblocs = irblocs self.jitirblocs(b.label, irblocs) - def disbloc(self, addr, cpu, vm): - "Disassemble a new bloc and JiT it" + def disbloc(self, addr, vm): + """Disassemble a new bloc and JiT it + @addr: address of the block to disassemble (asm_label or int) + @vm: VmMngr instance + """ # Get the bloc if isinstance(addr, asmbloc.asm_label): addr = addr.offset - label = self.ir_arch.symbol_pool.getby_offset_create(addr) + # Prepare disassembler + self.mdis.job_done.clear() + self.mdis.lines_wd = self.options["jit_maxline"] + self.mdis.dis_bloc_callback = self.disasm_cb # Disassemble it try: - cur_bloc, _ = asmbloc.dis_bloc(self.ir_arch.arch, self.bs, label, - addr, set(), - self.ir_arch.symbol_pool, [], - follow_call=False, - dontdis_retcall=False, - lines_wd=self.options["jit_maxline"], - # max 10 asm lines - attrib=self.ir_arch.attrib, - split_dis=self.split_dis) + cur_bloc = self.mdis.dis_bloc(addr) except IOError: # vm_exception_flag is set cur_bloc = asmbloc.asm_bloc(label) @@ -141,15 +147,13 @@ class JitCore(object): # Logging if self.log_newbloc: print cur_bloc - if self.disasm_cb is not None: - self.disasm_cb(cur_bloc) # Check for empty blocks if not cur_bloc.lines: raise ValueError("Cannot JIT a block without any assembly line") # Update label -> bloc - self.lbl2bloc[label] = cur_bloc + self.lbl2bloc[cur_bloc.label] = cur_bloc # Store min/max bloc address needed in jit automod code self.get_bloc_min_max(cur_bloc) @@ -180,7 +184,7 @@ class JitCore(object): if not lbl in self.lbl2jitbloc: # Need to JiT the bloc - self.disbloc(lbl, cpu, vm) + self.disbloc(lbl, vm) # Run the bloc and update cpu/vmmngr state ret = self.jit_call(lbl, cpu, vm, breakpoints) diff --git a/miasm2/os_dep/win_api_x86_32_seh.py b/miasm2/os_dep/win_api_x86_32_seh.py index f90198f9..6bf491bf 100644 --- a/miasm2/os_dep/win_api_x86_32_seh.py +++ b/miasm2/os_dep/win_api_x86_32_seh.py @@ -148,13 +148,15 @@ def build_ldr_data(jitter, modules_info): +0x00c InLoadOrderModuleList : _LIST_ENTRY +0x014 InMemoryOrderModuleList : _LIST_ENTRY +0x01C InInitializationOrderModuleList : _LIST_ENTRY + # dummy dll base + +0x024 DllBase : Ptr32 Void @jitter: jitter instance @modules_info: LoadedModules instance """ # ldr offset pad - offset = LDR_AD + peb_ldr_data_offset + 0xC + offset = peb_ldr_data_address + 0xC # get main pe info main_pe = modules_info.name2module.get(main_pe_name, None) @@ -178,6 +180,11 @@ def build_ldr_data(jitter, modules_info): jitter.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, data, "Loader struct") + # Add dummy dll base + jitter.vm.add_memory_page(peb_ldr_data_address + 0x24, + PAGE_READ | PAGE_WRITE, pck32(0), + "Loader struct dummy dllbase") + class LoadedModules(object): @@ -238,13 +245,8 @@ def create_modules_chain(jitter, name2module): offset_name = 0x500 offset_path = 0x600 - dummy_e = pe_init.PE() - dummy_e.NThdr.ImageBase = 0 - dummy_e.Opthdr.AddressOfEntryPoint = 0 - dummy_e.NThdr.sizeofimage = 0 - out = "" - for i, (fname, pe_obj) in enumerate([("", dummy_e)] + name2module.items()): + for i, (fname, pe_obj) in enumerate(name2module.items(), 1): if pe_obj is None: log.warning("Unknown module: ommited from link list (%r)", fname) @@ -291,9 +293,25 @@ def create_modules_chain(jitter, name2module): return modules_info +def set_link_list_entry(jitter, loaded_modules, modules_info, offset): + for i, module in enumerate(loaded_modules): + cur_module_entry = modules_info.module2entry[module] + prev_module = loaded_modules[(i - 1) % len(loaded_modules)] + next_module = loaded_modules[(i + 1) % len(loaded_modules)] + prev_module_entry = modules_info.module2entry[prev_module] + next_module_entry = modules_info.module2entry[next_module] + if i == 0: + prev_module_entry = peb_ldr_data_address + 0xC + if i == len(loaded_modules) - 1: + next_module_entry = peb_ldr_data_address + 0xC + jitter.vm.set_mem(cur_module_entry + offset, + (pck32(next_module_entry + offset) + + pck32(prev_module_entry + offset))) + + def fix_InLoadOrderModuleList(jitter, modules_info): """Fix InLoadOrderModuleList double link list. First module is the main pe, - then ntdll, kernel32. dummy is last pe. + then ntdll, kernel32. @jitter: the jitter instance @modules_info: the LoadedModules instance @@ -303,8 +321,7 @@ def fix_InLoadOrderModuleList(jitter, modules_info): main_pe = modules_info.name2module.get(main_pe_name, None) kernel32_pe = modules_info.name2module.get("kernel32.dll", None) ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - dummy_pe = modules_info.name2module.get("", None) - special_modules = [main_pe, kernel32_pe, ntdll_pe, dummy_pe] + special_modules = [main_pe, kernel32_pe, ntdll_pe] if not all(special_modules): log.warn( 'No main pe, ldr data will be unconsistant %r', special_modules) @@ -315,22 +332,13 @@ def fix_InLoadOrderModuleList(jitter, modules_info): loaded_modules[0:0] = [main_pe] loaded_modules[1:1] = [ntdll_pe] loaded_modules[2:2] = [kernel32_pe] - loaded_modules.append(dummy_pe) - for i, module in enumerate(loaded_modules): - cur_module_entry = modules_info.module2entry[module] - prev_module = loaded_modules[(i - 1) % len(loaded_modules)] - next_module = loaded_modules[(i + 1) % len(loaded_modules)] - prev_module_entry = modules_info.module2entry[prev_module] - next_module_entry = modules_info.module2entry[next_module] - jitter.vm.set_mem(cur_module_entry, - (pck32(next_module_entry) + - pck32(prev_module_entry))) + set_link_list_entry(jitter, loaded_modules, modules_info, 0x0) def fix_InMemoryOrderModuleList(jitter, modules_info): """Fix InMemoryOrderLinks double link list. First module is the main pe, - then ntdll, kernel32. dummy is last pe. + then ntdll, kernel32. @jitter: the jitter instance @modules_info: the LoadedModules instance @@ -340,8 +348,7 @@ def fix_InMemoryOrderModuleList(jitter, modules_info): main_pe = modules_info.name2module.get(main_pe_name, None) kernel32_pe = modules_info.name2module.get("kernel32.dll", None) ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - dummy_pe = modules_info.name2module.get("", None) - special_modules = [main_pe, kernel32_pe, ntdll_pe, dummy_pe] + special_modules = [main_pe, kernel32_pe, ntdll_pe] if not all(special_modules): log.warn('No main pe, ldr data will be unconsistant') loaded_modules = modules_info.modules @@ -351,22 +358,13 @@ def fix_InMemoryOrderModuleList(jitter, modules_info): loaded_modules[0:0] = [main_pe] loaded_modules[1:1] = [ntdll_pe] loaded_modules[2:2] = [kernel32_pe] - loaded_modules.append(dummy_pe) - for i, module in enumerate(loaded_modules): - cur_module_entry = modules_info.module2entry[module] - prev_module = loaded_modules[(i - 1) % len(loaded_modules)] - next_module = loaded_modules[(i + 1) % len(loaded_modules)] - prev_module_entry = modules_info.module2entry[prev_module] - next_module_entry = modules_info.module2entry[next_module] - jitter.vm.set_mem(cur_module_entry + 0x8, - (pck32(next_module_entry + 0x8) + - pck32(prev_module_entry + 0x8))) + set_link_list_entry(jitter, loaded_modules, modules_info, 0x8) def fix_InInitializationOrderModuleList(jitter, modules_info): """Fix InInitializationOrderModuleList double link list. First module is the - ntdll, then kernel32. dummy is last pe. + ntdll, then kernel32. @jitter: the jitter instance @modules_info: the LoadedModules instance @@ -377,8 +375,7 @@ def fix_InInitializationOrderModuleList(jitter, modules_info): main_pe = modules_info.name2module.get(main_pe_name, None) kernel32_pe = modules_info.name2module.get("kernel32.dll", None) ntdll_pe = modules_info.name2module.get("ntdll.dll", None) - dummy_pe = modules_info.name2module.get("", None) - special_modules = [main_pe, kernel32_pe, ntdll_pe, dummy_pe] + special_modules = [main_pe, kernel32_pe, ntdll_pe] if not all(special_modules): log.warn('No main pe, ldr data will be unconsistant') loaded_modules = modules_info.modules @@ -387,17 +384,8 @@ def fix_InInitializationOrderModuleList(jitter, modules_info): if module not in special_modules] loaded_modules[0:0] = [ntdll_pe] loaded_modules[1:1] = [kernel32_pe] - loaded_modules.append(dummy_pe) - for i, module in enumerate(loaded_modules): - cur_module_entry = modules_info.module2entry[module] - prev_module = loaded_modules[(i - 1) % len(loaded_modules)] - next_module = loaded_modules[(i + 1) % len(loaded_modules)] - prev_module_entry = modules_info.module2entry[prev_module] - next_module_entry = modules_info.module2entry[next_module] - jitter.vm.set_mem(cur_module_entry + 0x10, - (pck32(next_module_entry + 0x10) + - pck32(prev_module_entry + 0x10))) + set_link_list_entry(jitter, loaded_modules, modules_info, 0x10) def add_process_env(jitter): |