def blocks_to_memrange(self, blocks): """Return an interval instance standing for blocks addresses @blocks: list of AsmBlock instances """ mem_range = interval() for block in blocks: mem_range += interval([(block.ad_min, block.ad_max - 1)]) return mem_range
def __init__(self, ir_arch, bin_stream): """Initialise a JitCore instance. @ir_arch: ir instance for current architecture @bin_stream: bin_stream instance """ # Arch related self.ir_arch = ir_arch self.ircfg = self.ir_arch.new_ircfg() self.arch_name = "%s%s" % (self.ir_arch.arch.name, self.ir_arch.attrib) # Structures for block tracking self.offset_to_jitted_func = BoundedDict(self.jitted_block_max_size, delete_cb=self.jitted_block_delete_cb) self.loc_key_to_block = {} self.blocks_mem_interval = interval() # Logging & options self.log_mn = False self.log_regs = False self.log_newbloc = False self.options = {"jit_maxline": 50, # Maximum number of line jitted "max_exec_per_call": 0 # 0 means no limit } # Disassembly Engine self.split_dis = set() self.mdis = disasmEngine( ir_arch.arch, ir_arch.attrib, bin_stream, lines_wd=self.options["jit_maxline"], loc_db=ir_arch.loc_db, follow_call=False, dontdis_retcall=False, split_dis=self.split_dis, )
def add_block_to_mem_interval(self, vm, block): "Update vm to include block addresses in its memory range" self.blocks_mem_interval += interval([(block.ad_min, block.ad_max - 1)]) vm.reset_code_bloc_pool() for a, b in self.blocks_mem_interval: vm.add_code_bloc(a, b + 1)
def vm_load_elf(vm, fdata, name="", base_addr=0, loc_db=None, apply_reloc=False, **kargs): """ Very dirty elf loader TODO XXX: implement real loader """ elf = elf_init.ELF(fdata, **kargs) i = interval() all_data = {} for p in elf.ph.phlist: if p.ph.type != elf_csts.PT_LOAD: continue log.debug( '0x%x 0x%x 0x%x 0x%x 0x%x', p.ph.vaddr, p.ph.memsz, p.ph.offset, p.ph.filesz, p.ph.type) data_o = elf._content[p.ph.offset:p.ph.offset + p.ph.filesz] addr_o = p.ph.vaddr + base_addr a_addr = addr_o & ~0xFFF b_addr = addr_o + max(p.ph.memsz, p.ph.filesz) b_addr = (b_addr + 0xFFF) & ~0xFFF all_data[addr_o] = data_o # -2: Trick to avoid merging 2 consecutive pages i += [(a_addr, b_addr - 2)] for a, b in i.intervals: vm.add_memory_page( a, PAGE_READ | PAGE_WRITE, b"\x00" * (b + 2 - a), repr(name) ) for r_vaddr, data in viewitems(all_data): vm.set_mem(r_vaddr, data) if loc_db is not None: fill_loc_db_with_symbols(elf, loc_db, base_addr) if apply_reloc: arch = guess_arch(elf) sections = [] for section in elf.sh: if not hasattr(section, 'reltab'): continue if isinstance(section, elf_init.RelATable): pass elif isinstance(section, elf_init.RelTable): if arch == "x86_64": log.warning("REL section should not happen in x86_64") else: raise RuntimeError("Unknown relocation section type: %r" % section) sections.append(section) for section in sections: if arch in ["x86_64", "x86_32"]: apply_reloc_x86(elf, vm, section, base_addr, loc_db) else: log.debug("Unsupported relocation for arch %r" % arch) return elf
def gen_all_intervals(size): """Return every possible interval for element of @size bit -> 2**(2**size) (number of partition) """ nb_elements = 1 << size for bvec in range(1 << nb_elements): # Bit vector: if bit i is on, i is in the interval to_ret = interval() for i in range(nb_elements): if bvec & i == i: to_ret += [(i, i)] yield to_ret
from miasm.core import asmblock from miasm.arch.x86 import arch from miasm.core import parse_asm from miasm.core.interval import interval my_mn = arch.mn_x86 asmcfg, loc_db = parse_asm.parse_txt( my_mn, 64, r''' main: PUSH RBP MOV RBP, RSP loop_dec: CMP RCX, RDX JB loop_dec end: MOV RSP, RBP POP RBP RET ''') loc_db.set_location_offset(loc_db.get_name_location("main"), 0x100001000) dst_interval = interval([(0x100001000, 0x100002000)]) patches = asmblock.asm_resolve_final(my_mn, asmcfg, loc_db, dst_interval)
def ret_func(self, *args): ret = interval() for x_min, x_max in self.intervals: ret += func(self, x_min, x_max, *args) return self.__class__(self.size, ret)
def ret_func(self, target): ret = interval() for left_i, right_i in product(self.intervals, target.intervals): ret += func(self, left_i[0], left_i[1], right_i[0], right_i[1]) return self.__class__(self.size, ret)
# Second chance, try with symbol loc_key = mdis.loc_db.get_name_location(addr) offset = mdis.loc_db.get_location_offset(loc_key) addrs.append(offset) if len(addrs) == 0 and default_addr is not None: addrs.append(default_addr) for ad in addrs: todo += [(mdis, None, ad)] done = set() all_funcs = set() all_funcs_blocks = {} done_interval = interval() finish = False entry_points = set() # Main disasm loop while not finish and todo: while not finish and todo: mdis, caller, ad = todo.pop(0) if ad in done: continue done.add(ad) asmcfg = mdis.dis_multiblock(ad) entry_points.add(mdis.loc_db.get_offset_location(ad)) log.info('func ok %.16x (%d)' % (ad, len(all_funcs)))
except ValueError: # Second chance, try with symbol loc_key = mdis.loc_db.get_name_location(addr) offset = mdis.loc_db.get_location_offset(loc_key) addrs.append(offset) if len(addrs) == 0 and default_addr is not None: addrs.append(default_addr) for ad in addrs: todo += [(mdis, None, ad)] done = set() all_funcs = set() all_funcs_blocks = {} done_interval = interval() finish = False entry_points = set() # Main disasm loop while not finish and todo: while not finish and todo: mdis, caller, ad = todo.pop(0) if ad in done: continue done.add(ad) asmcfg = mdis.dis_multiblock(ad) entry_points.add(mdis.loc_db.get_offset_location(ad)) log.info('func ok %.16x (%d)' % (ad, len(all_funcs)))
def mmap(self, addr, len_, prot, flags, fd, off, vmmngr): """Stub for 'mmap' syscall 'mmap2' must be implemented by calling this function with off * 4096 """ if addr == 0: addr = self.mmap_current self.mmap_current += (len_ + 0x1000) & ~0xfff all_mem = vmmngr.get_all_memory() mapped = interval( [ (start, start + info["size"] - 1) for start, info in viewitems(all_mem) ] ) MAP_FIXED = 0x10 if flags & MAP_FIXED: # Alloc missing and override missing = interval([(addr, addr + len_ - 1)]) - mapped for start, stop in missing: vmmngr.add_memory_page( start, PAGE_READ|PAGE_WRITE, b"\x00" * (stop - start + 1), "mmap allocated" ) else: # Find first candidate segment nearby addr for start, stop in mapped: if stop < addr: continue rounded = (stop + 1 + 0x1000) & ~0xfff if (interval([(rounded, rounded + len_)]) & mapped).empty: addr = rounded break else: assert (interval([(addr, addr + len_)]) & mapped).empty vmmngr.add_memory_page( addr, PAGE_READ|PAGE_WRITE, b"\x00" * len_, "mmap allocated" ) if fd == 0xffffffff: if off != 0: raise RuntimeError("Not implemented") data = b"\x00" * len_ else: fdesc = self.file_descriptors[fd] cur_pos = fdesc.tell() fdesc.seek(off) data = fdesc.read(len_) fdesc.seek(cur_pos) vmmngr.set_mem(addr, data) return addr
pe = pe_init.PE(wsize=size) s_text = pe.SHList.add_section(name="text", addr=0x1000, rawsize=0x1000) s_iat = pe.SHList.add_section(name="iat", rawsize=0x100) new_dll = [({ "name": "USER32.dll", "firstthunk": s_iat.addr }, ["MessageBoxA"])] pe.DirImport.add_dlldesc(new_dll) s_myimp = pe.SHList.add_section(name="myimp", rawsize=len(pe.DirImport)) pe.DirImport.set_rva(s_myimp.addr) pe.Opthdr.AddressOfEntryPoint = s_text.addr addr_main = pe.rva2virt(s_text.addr) virt = pe.virt output = pe dst_interval = interval([(pe.rva2virt(s_text.addr), pe.rva2virt(s_text.addr + s_text.size))]) else: st = StrPatchwork() addr_main = 0 virt = st output = st # Get and parse the source code with open(args.source) as fstream: source = fstream.read() loc_db = LocationDB() asmcfg = parse_asm.parse_txt(machine.mn, attrib, source, loc_db)
def run(jitter_setup, dse_setup): JitCore_Python.SymbExecClass = ESETrackMemory # Create sandbox parser = Sandbox_Linux_x86_64.parser(description='PE sandboxer') parser.add_argument('filename', help='PE Filename') parser.add_argument('-if', '--infile', nargs='?', help='Input buffer from file') parser.add_argument('-is', '--insize', nargs='?', default='32', help='Input buffer size') parser.add_argument('-fs', '--fullsymb', action='store_true', default=False, help='Forbid fallback to concretizing') parser.add_argument('-v', '--verbose', nargs='?', default='2', help='Verbosity level (0-4)') parser.add_argument('-df', '--dump', action='store_true', default=False, help='Dump crashing data blobs to files') options = parser.parse_args() # First thing, set log level log.setLevel(50-int(options.verbose)*10) options.jitter = 'llvm' options.mimic_env= True #options.singlestep = True # Input params if options.infile: with open(options.infile, 'rb') as f: input_buf= f.read() else: input_buf = os.urandom(int(options.insize, 0)) # Instantiate loc_db = LocationDB() sb = Sandbox_Linux_x86_64(loc_db, options.filename, options, globals()) jitter_setup(sb.jitter, int(options.address, 16), input_buf, len(input_buf)) # Create and attach DSE dse = SecDSE(sb.machine, loc_db) dse.add_lib_handler(sb.libs, globals()) dse.attach(sb.jitter) # Record valid memory ranges dse.refresh_valid_jitter_ranges() dse.update_state_from_concrete() # Configure DSE dse_setup(dse, input_buf) # Take snapshot snapshot = dse.take_snapshot() nb_run=0 while dse.todos: nb_run+=1 current = dse.get_todo() # Restore concrete & symb contexts dse.restore_snapshot(snapshot, keep_known_solutions=True) dse.symbolize_memory(current.to_symbolize) # Update the buffer in concrete engine sb.jitter.vm.set_mem(dse.input_buffer_ptr, current.buf) log.error('-'*80 + ' RUN #%i | %i INSTR visited | %i todos | %i crashes' % (nb_run, len(dse.visited_bbls), \ len(dse.todos), len(dse.crashes) \ ) ) log.error('SYMBOLIZED %s (%i/%i bytes)' % (str(current.to_symbolize), current.to_symbolize.length, len(input_buf))) try: sb.jitter.continue_run() except DriftException as e: print(hex(dse.jitter.pc) + ' ' + str(e)) break # TODO: Rename to SymbToConcException except MemSquareException as e: # TODO: We can just concretize the byte and continue from here print(hex(dse.jitter.pc) + ' ' + str(e.info)) dse.done() new_to_symbolize = current.to_symbolize for mem in e.ptr: # Concretize that byte and retry new_to_symbolize -= interval([(mem, mem)]) # Compute all possible concrete bytes if options.fullsymb: for buf in dse.gen_new_bufs(e.ptr): dse.todos.append(todo(buf, current.to_symbolize)) # Put it in the todo list else: print('CONCRETIZING: ' + hex(mem)) dse.todos.insert(0, todo(current.buf, new_to_symbolize)) # Continue the current run? #import pdb; pdb.set_trace() continue except RuntimeError as e: message = str(e) log.warning(f'LIVE 0x{dse.jitter.pc:08X}: AV with "{message:s}"') dse.crashes.append(crash(dse.jitter.pc, None, 'UNDEFINED', current.buf)) dse.done() continue except FnReturnException as e: log.info('FUNCTION RET') dse.done() continue except KeyboardInterrupt: break except Exception as e: dse.done() print(hex(dse.jitter.pc) + ' ' + str(type(e)) + ': ' + str(e)) import pdb; pdb.set_trace() continue log.error('-'*80 + ' RESULTS | %i INSTR visited | %i todos | %i unique crashes' % (len(dse.visited_bbls), \ len(dse.todos), len(set(dse.crashes)) \ ) ) for i, record in enumerate(set(dse.crashes)): if options.dump: hashval = record.__hash__() with open(f'crash_{hashval:X}', 'wb') as f: f.write(record.buf) log.error(str(record)) log.error('-'*80)
def clear_jitted_blocks(self): "Reset all jitted blocks" self.offset_to_jitted_func.clear() self.loc_key_to_block.clear() self.blocks_mem_interval = interval()
def _process_jmp_table(self, cur_bloc, mn, attrib, loc_db, pool_bin, offsets_to_dis): # TODO add support for jump tables with "AND cntrl_var, range" boundary check; such jmp tables were present only # in library functions in Stantinko samples # add current block to the asmcfg to make it accessible in the ircfg edges, add_block is called anyway right # after this callback, it will notice that the block has been already added self.add_block(cur_bloc) dst_address = loc_db.get_location_offset(cur_bloc.loc_key) logger.info("Possible jump table addr: 0x%x" % dst_address) ira = get_ira(mn, attrib) ir_arch = ira(loc_db) ircfg = ir_arch.new_ircfg_from_asmcfg(self) # the previous blocks should have exactly 1 predecessor dictating range predecessors = self.predecessors(cur_bloc.loc_key) if len(predecessors) != 1: logger.info("Expected exactly one predecessor") return predecessor = ircfg.blocks[predecessors.pop()] irdst_block = ircfg.blocks[cur_bloc.loc_key] if len(irdst_block.assignblks) != len(cur_bloc.lines): processed = set() todo = {irdst_block.loc_key} while not irdst_block.dst.is_mem(): loc_key = todo.pop() if loc_key in processed: continue processed.add(loc_key) irdst_block = ircfg.blocks[loc_key] todo.update(ircfg.successors(loc_key)) # we shouldn't stumble upon crashing segm and call operators even thought implicit is required to process # initial IRDst(mentioned operators cause crashes of the engine behind implicit) since we operate only on the # 2 crucial basic blocks. The predecessor contains range of the jump table, we use it to determine constructs # of the jump table and track back base code segment address assignment to target the msvc compiler and x64 # architecture, other compilers use directly RIP related addressing to get the address. # get real predecessor asm_block = self.loc_key_to_block(predecessor.loc_key) if len(predecessor.assignblks) != len(asm_block.lines): processed = set() todo = {predecessor.loc_key} while cur_bloc.loc_key not in ircfg.successors( predecessor.loc_key): loc_key = todo.pop() if loc_key in processed: continue processed.add(loc_key) predecessor = ircfg.blocks[loc_key] todo.update(ircfg.successors(loc_key)) # get jump_table_control_variable from predecessor dg = DependencyGraph(ircfg, implicit=True, apply_simp=True, follow_mem=True, follow_call=False) jtcdg = JTCVariableDependencyGraph(predecessor.loc_key, ircfg, implicit=True, apply_simp=True, follow_mem=False, follow_call=False) dependency_result_iter = iter( jtcdg.get(irdst_block.loc_key, {ircfg.IRDst}, len(predecessor.assignblks), {predecessor.loc_key})) solution_predecessor = next(dependency_result_iter) # jump table control variable jtc_var = jtcdg.jtc_var if not jtc_var: logger.info( "couldn't determine single jump table control variable") return # get symbolic execution engine to be used in both predecessor and jmp table block symb_exec_both = MySymbolicExecutionEngine(pool_bin, jtc_var, ir_arch) try: # symbolically evaluate lines influencing IRDst of the predecessor leading to jtc_var for line_nb in sorted({ node.line_nb for node in solution_predecessor.relevant_nodes if node.loc_key == predecessor.loc_key }): assign_blk = predecessor.assignblks[line_nb] symb_exec_both.eval_updt_assignblk(assign_blk) except (KeyError, TypeError): logger.error("Couldn't symbolically eval predecessor of 0x%x" % loc_db.get_location_offset(cur_bloc.loc_key)) # stantinko contains illegal unreachable dereferences prior jmp tables, such as # xor eax, eax; movsx eax, byte ptr [eax] return # get symbolic execution engine supporting binary memory dereference symb_exec_minimal = MySymbolicExecutionEngine( pool_bin, ir_arch, symb_exec_both.symbols.copy()) predecessor_irdst_equation = symb_exec_both.symbols[ircfg.IRDst] # get equation whose solutions solve the indirect jump irdst_block = ircfg.blocks[cur_bloc.loc_key] if len(irdst_block.assignblks) != len(cur_bloc.lines): processed = set() todo = {irdst_block.loc_key} while not irdst_block.dst.is_mem(): symb_exec_both.eval_updt_irblock(irdst_block) loc_key = todo.pop() if loc_key in processed: continue processed.add(loc_key) irdst_block = ircfg.blocks[loc_key] todo.update(ircfg.successors(loc_key)) irdst_equation = symb_exec_both.eval_updt_irblock(irdst_block) sizes = set() # prevent mem processing via raw arrays by using var ID instead # we also want to set a maximum boundary so slices don't cause the sat solver generate a huge number of results visitor = ExprVisitorCallbackTopToBottom( lambda x: self._eliminate_jtc_var_slice_cb(x, sizes, jtc_var)) irdst_equation = visitor.visit(irdst_equation) predecessor_irdst_equation = visitor.visit(predecessor_irdst_equation) size_boundary = jtc_var.size sizes = sorted(filter(lambda x: x > 1, sizes)) if sizes: size_boundary = sizes[0] jtc_var_id = ExprId("jtc_var", jtc_var.size) irdst_equation = irdst_equation.replace_expr({jtc_var: jtc_var_id}) predecessor_irdst_equation = predecessor_irdst_equation.replace_expr( {jtc_var: jtc_var_id}) # track possible CS base address dependency, ignore control variable from predecessor eliminated_jtc_var_equation = irdst_equation.replace_expr( {jtc_var_id: ExprInt(0, jtc_var_id.size)}) evaluated_ejtc_var_equation = symb_exec_both.eval_expr( eliminated_jtc_var_equation) if not evaluated_ejtc_var_equation.is_int(): # we need to determine code base dependencies = dg._follow_apply_cb(evaluated_ejtc_var_equation) expr_deps = { fexpr.element for fexpr in dependencies if fexpr.follow } dg_base = DependencyGraph(ircfg, implicit=False, apply_simp=True, follow_mem=True, follow_call=False) dependency_result_iter = iter( dg_base.get(cur_bloc.loc_key, expr_deps, len(cur_bloc.lines), {self.heads()[0]})) solution = next(dependency_result_iter) code_base_dict = { expr: solution.emul(ir_arch)[expr] for expr in expr_deps } irdst_equation = irdst_equation.replace_expr(code_base_dict) predecessor_irdst_equation = predecessor_irdst_equation.replace_expr( code_base_dict) # we need backward slice of the jump table destination dependencies to retain the other independent assignments # during cmp chain assembling dependency_result = dg.get(cur_bloc.loc_key, {ircfg.IRDst}, len(cur_bloc.lines), {cur_bloc.loc_key}) dependent_line_nbs = {} for solution in dependency_result: dependent_line_nbs.setdefault(solution.loc_key, set()).update( {dn.line_nb for dn in solution.relevant_nodes}) cur_bloc_new_lines = [] for loc_key, lines in dependent_line_nbs.items(): for line_nb, assignblk in enumerate( ircfg.blocks[loc_key].assignblks): if line_nb not in lines: symb_exec_minimal.eval_assignblk(assignblk) cur_bloc_new_lines.append(assignblk.instr) comparison_reg_id = None comparison_reg_value = None if jtc_var not in symb_exec_minimal.symbols.symbols_id: comparison_reg_id = jtc_var comparison_reg_value = jtc_var else: for symbol, comparison_reg_value in symb_exec_minimal.symbols.symbols_id.items( ): if jtc_var in comparison_reg_value and ( symbol.is_mem() or (symbol.is_id() and symbol.name not in [ "RIP", "EIP", "zf", "nf", "pf", "of", "cf", "af", "df", ircfg.IRDst.name ])): replaced_jtcv = comparison_reg_value.replace_expr( {jtc_var: ExprInt(0, jtc_var.size)}) if isinstance(symb_exec_minimal.eval_expr(replaced_jtcv), ExprInt): comparison_reg_id = symbol break if not comparison_reg_id or not comparison_reg_value: logger.debug( "Couldn't find any candidate for comparison register at 0x%x" % loc_db.get_location_offset(cur_bloc.loc_key)) return from miasm.ir.translators import Translator import z3 translator = Translator.to_language("z3") solver = z3.Solver() logger.debug("predecessor_irdst_equation: %s" % str(predecessor_irdst_equation)) logger.debug(("dst_address: 0x%x" % dst_address)) logger.debug(("jump_table_control_variable: %s" % str(jtc_var))) solver.add( translator.from_expr(predecessor_irdst_equation) == dst_address) translated_jtc_var = translator.from_expr(jtc_var_id) solver.add(translated_jtc_var >= 0) solver.add(translated_jtc_var < 2**(size_boundary - 1) - 1) if solver.check() != z3.sat: logger.debug( "Couldn't find at least one jump table control variable") return dbg_destinations = set() next_loc_key = new_block_loc_key = loc_db.add_location() logger.debug("comparison_reg_id: %s" % str(comparison_reg_id)) dst_ranges = {} counter = 0 while counter < 500: val = solver.model()[translated_jtc_var].as_long() final_irdst_equation = irdst_equation.replace_expr( {jtc_var_id: ExprInt(val, jtc_var_id.size)}) final_dst = int(symb_exec_both.eval_expr(final_irdst_equation)) cmp_reg_val = comparison_reg_value.replace_expr( {jtc_var: ExprInt(val, jtc_var.size)}) cmp_reg_val = int(symb_exec_minimal.eval_expr(cmp_reg_val)) dst_ranges[final_dst] = dst_ranges.get(final_dst, interval()).union([ (cmp_reg_val, cmp_reg_val) ]) dbg_destinations.add(final_dst) offsets_to_dis.add(final_dst) solver.add(translated_jtc_var != translator.from_expr( ExprInt(val, jtc_var_id.size))) if solver.check() != z3.sat: break counter += 1 if counter == 500: raise RuntimeError("Interrupted; there might be a broken slice") for dst, interv in dst_ranges.items(): cond_target_loc_key = loc_db.get_or_create_offset_location(dst) for lower, upper in interv: lower = ExprInt(lower, self.mode) upper = ExprInt(upper, self.mode) new_asm_block = AsmBlock(new_block_loc_key) new_block_loc_key = loc_db.add_location() if lower == upper: new_asm_block.lines = create_cmp_j_instructions( self.mode, comparison_reg_id, lower, ExprLoc(cond_target_loc_key, self.mode), "JZ") new_asm_block.add_cst(cond_target_loc_key, "c_to") new_asm_block.add_cst(new_block_loc_key, "c_next") else: upper_check_loc_key = loc_db.add_location() # lower boundary check new_asm_block.lines = create_cmp_j_instructions( self.mode, comparison_reg_id, lower, ExprLoc(new_block_loc_key, self.mode), "JB") new_asm_block.add_cst(new_block_loc_key, "c_to") new_asm_block.add_cst(upper_check_loc_key, "c_next") # upper boundary check upper_check_block = AsmBlock(upper_check_loc_key) upper_check_block.lines = create_cmp_j_instructions( self.mode, comparison_reg_id, upper, ExprLoc(cond_target_loc_key, self.mode), "JBE") upper_check_block.add_cst(cond_target_loc_key, "c_to") upper_check_block.add_cst(new_block_loc_key, "c_next") self.add_block(upper_check_block) self.add_block(new_asm_block) # trigger last jump unconditionally new_asm_block.bto = {AsmConstraintTo(cond_target_loc_key)} new_asm_block.lines = [ create_jump_instruction(self.mode, ExprLoc(cond_target_loc_key, self.mode)) ] cur_bloc.lines = cur_bloc_new_lines cur_bloc.add_cst(next_loc_key, "c_next") if not cur_bloc.lines: cur_bloc.lines = [create_nop(self.mode)] self.jmp_table_loc_keys.add(cur_bloc.loc_key) logger.debug("destinations: %s" % pformat([hex(i or 0) for i in dbg_destinations])) logger.debug("blocks: %d" % counter)
def codeRange(self): for section in self.parser.sections: if '.text' in section.Name.decode(): return interval([( section.VirtualAddress + self.imageBase, section.VirtualAddress + self.imageBase + section.Misc_VirtualSize)])
[ "MessageBoxA" ] ) ] pe.DirImport.add_dlldesc(new_dll) s_myimp = pe.SHList.add_section(name="myimp", rawsize=len(pe.DirImport)) pe.DirImport.set_rva(s_myimp.addr) pe.Opthdr.AddressOfEntryPoint = s_text.addr addr_main = pe.rva2virt(s_text.addr) virt = pe.virt output = pe dst_interval = interval( [ (pe.rva2virt(s_text.addr), pe.rva2virt(s_text.addr + s_text.size)) ] ) else: st = StrPatchwork() addr_main = 0 virt = st output = st # Get and parse the source code with open(args.source) as fstream: source = fstream.read()