def _range_shift_uniq(self, x_min, x_max, shift, op): """Bounds interval for x @op @shift with - x of size self.size - @x_min <= x <= @x_max - operations are considered unsigned - shift <= self.size """ assert shift <= self.size # Shift operations are monotonic, and overflow results in 0 max_bound = self.mask if op == "<<": obtain_max = x_max << shift if obtain_max > max_bound: # Overflow at least on max, best-effort # result '0' often happen, include it return interval([(0, 0), ((1 << shift) - 1, max_bound)]) else: return interval([(x_min << shift, obtain_max)]) elif op == ">>": return interval([((x_min >> shift) & max_bound, (x_max >> shift) & max_bound)]) elif op == "a>>": # The Miasm2 version (Expr or ModInt) could have been used, but # introduce unnecessary dependencies for this module # Python >> is the arithmetic one ashr = lambda x, y: self._signed2unsigned(self._unsigned2signed(x) >> y) end_min, end_max = ashr(x_min, shift), ashr(x_max, shift) end_min, end_max = min(end_min, end_max), max(end_min, end_max) return interval([(end_min, end_max)]) else: raise ValueError("%s is not a shifter" % op)
def __init__(self, ir_arch, bs=None): """Initialise a JitCore instance. @ir_arch: ir instance for current architecture @bs: bitstream """ self.ir_arch = ir_arch self.bs = bs self.known_blocs = {} self.lbl2jitbloc = BoundedDict(self.jitted_block_max_size, delete_cb=self.jitted_block_delete_cb) self.lbl2bloc = {} self.log_mn = False self.log_regs = False self.log_newbloc = False self.segm_to_do = set() self.job_done = set() self.jitcount = 0 self.addr2obj = {} self.addr2objref = {} self.blocs_mem_interval = interval() self.disasm_cb = None self.split_dis = set() self.addr_mod = interval() 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 asm_resolve_final(mnemo, blocks, symbol_pool, dst_interval=None): """Resolve and assemble @blocks using @symbol_pool into interval @dst_interval""" sanity_check_blocks(blocks) guess_blocks_size(mnemo, blocks) blockChains = group_constrained_blocks(symbol_pool, blocks) resolved_blockChains = resolve_symbol(blockChains, symbol_pool, dst_interval) asmbloc_final(mnemo, blocks, resolved_blockChains, symbol_pool) patches = {} output_interval = interval() for block in blocks: offset = block.label.offset for instr in block.lines: if not instr.data: # Empty line continue assert len(instr.data) == instr.l patches[offset] = instr.data instruction_interval = interval([(offset, offset + instr.l-1)]) if not (instruction_interval & output_interval).empty: raise RuntimeError("overlapping bytes %X" % int(offset)) instr.offset = offset offset += instr.l return patches
def __init__(self, ir_arch, bs=None): """Initialise a JitCore instance. @ir_arch: ir instance for current architecture @bs: bitstream """ self.ir_arch = ir_arch self.bs = bs self.known_blocs = {} self.lbl2jitbloc = BoundedDict(self.jitted_block_max_size, delete_cb=self.jitted_block_delete_cb) self.lbl2bloc = {} self.log_mn = False self.log_regs = False self.log_newbloc = False self.segm_to_do = set() self.job_done = set() self.jitcount = 0 self.addr2obj = {} self.addr2objref = {} self.blocs_mem_interval = interval() self.disasm_cb = None self.split_dis = set() self.addr_mod = interval() self.options = {"jit_maxline": 50 # Maximum number of line jitted }
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 blocs2memrange(self, blocs): """Return an interval instance standing for blocs addresses @blocs: list of asm_bloc instances """ mem_range = interval() for b in blocs: mem_range += interval([(b.ad_min, b.ad_max - 1)]) return mem_range
def _range_mul(self, x_min, x_max, y_min, y_max): """Interval bounds for x * y, with - x, y of size self.size - @x_min <= x <= @x_max - @y_min <= y <= @y_max - operations are considered unsigned This is a naive version, going to TOP on overflow""" max_bound = self.mask if y_max * x_max > max_bound: return interval([(0, max_bound)]) else: return interval([(x_min * y_min, x_max * y_max)])
def _range_minus_uniq(self, x_min, x_max): """Bounds interval for -x, with - x of size self.size - @x_min <= x <= @x_max - operations are considered unsigned From Hacker's Delight: Chapter 4 """ max_bound = self.mask if (x_min == 0 and x_max != 0): # HD returns 0, max_bound; see _range_add return interval([(0, 0), ((- x_max) & max_bound, max_bound)]) else: return interval([((- x_max) & max_bound, (- x_min) & max_bound)])
def get_blockchains_address_interval(blockChains, dst_interval): """Compute the interval used by the pinned @blockChains Check if the placed chains are in the @dst_interval""" allocated_interval = interval() for chain in blockChains: if not chain.pinned: continue chain_interval = interval([(chain.offset_min, chain.offset_max-1)]) if chain_interval not in dst_interval: raise ValueError('Chain placed out of destination interval') allocated_interval += chain_interval return allocated_interval
def _range_mod_uniq(self, x_min, x_max, mod): """Interval bounds for x % @mod, with - x, @mod of size self.size - @x_min <= x <= @x_max - operations are considered unsigned """ if (x_max - x_min) >= mod: return interval([(0, mod - 1)]) x_max = x_max % mod x_min = x_min % mod if x_max < x_min: return interval([(0, x_max), (x_min, mod - 1)]) else: return interval([(x_min, x_max)])
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 all_mem.iteritems()]) 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, "\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, "\x00" * len_, "mmap allocated") if fd == 0xffffffff: if off != 0: raise RuntimeError("Not implemented") data = "\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
def _interval_shift(self, operation, shifter): """Apply the shifting operation @operation with a shifting ModularIntervals @shifter on the current instance""" # Work on a copy of shifter intervals shifter = interval(shifter.intervals) if (shifter.hull()[1] >= self.size): shifter += interval([(self.size, self.size)]) shifter &= interval([(0, self.size)]) ret = interval() for shift_range in shifter: for shift in xrange(shift_range[0], shift_range[1] + 1): for x_min, x_max in self.intervals: ret += self._range_shift_uniq(x_min, x_max, shift, operation) return self.__class__(self.size, ret)
def retrieve_stack_accesses(ir_arch_a, ssa): """ Walk the ssa graph and find stack based variables. Return a dictionnary linking stack base address to its size/name @ir_arch_a: ira instance @ssa: SSADiGraph instance """ stack_vars = set() for block in ssa.graph.blocks.itervalues(): for assignblk in block: for dst, src in assignblk.iteritems(): stack_vars.update(get_stack_accesses(ir_arch_a, dst)) stack_vars.update(get_stack_accesses(ir_arch_a, src)) stack_vars = filter(lambda expr: check_expr_below_stack(ir_arch_a, expr), stack_vars) base_to_var = {} for var in stack_vars: base_to_var.setdefault(var.ptr, set()).add(var) base_to_interval = {} for addr, vars in base_to_var.iteritems(): var_interval = interval() for var in vars: offset = expr_simp(addr - ir_arch_a.sp) if not offset.is_int(): # skip non linear stack offset continue start = int(offset) stop = int(expr_simp(offset + ExprInt(var.size / 8, offset.size))) mem = interval([(start, stop-1)]) var_interval += mem base_to_interval[addr] = var_interval if not base_to_interval: return {} # Check if not intervals overlap _, tmp = base_to_interval.popitem() while base_to_interval: addr, mem = base_to_interval.popitem() assert (tmp & mem).empty tmp += mem base_to_info = {} for addr, vars in base_to_var.iteritems(): name = "var_%d" % (len(base_to_info)) size = max([var.size for var in vars]) base_to_info[addr] = size, name return base_to_info
def vm_load_elf(vm, fdata, **kargs): """ Very dirty elf loader TODO XXX: implement real loader """ #log.setLevel(logging.DEBUG) e = elf_init.ELF(fdata, **kargs) i = interval() all_data = {} for p in e.ph.phlist: if p.ph.type != 1: continue log.debug('0x%x 0x%x 0x%x 0x%x', p.ph.vaddr, p.ph.memsz, p.ph.offset, p.ph.filesz) data_o = e._content[p.ph.offset:p.ph.offset + p.ph.filesz] addr_o = p.ph.vaddr 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: #print hex(a), hex(b) vm.add_memory_page(a, PAGE_READ | PAGE_WRITE, "\x00"*(b+2-a)) #vm.dump_memory_page_pool() for r_vaddr, data in all_data.items(): vm.set_mem(r_vaddr, data) return e
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 updt_automod_code(self, vm): """Remove code jitted in range self.addr_mod @vm: VmMngr instance """ for addr_start, addr_stop in self.addr_mod: self.del_bloc_in_range(addr_start, addr_stop + 1) self.__updt_jitcode_mem_range(vm) self.addr_mod = interval()
def resolve_symbol(blockChains, symbol_pool, dst_interval=None): """Place @blockChains in the @dst_interval""" log_asmbloc.info('resolve_symbol') if dst_interval is None: dst_interval = interval([(0, 0xFFFFFFFFFFFFFFFF)]) forbidden_interval = interval( [(-1, 0xFFFFFFFFFFFFFFFF + 1)]) - dst_interval allocated_interval = get_blockchains_address_interval(blockChains, dst_interval) log_asmbloc.debug('allocated interval: %s', allocated_interval) pinned_chains = [chain for chain in blockChains if chain.pinned] # Add wedge in forbidden intervals for start, stop in forbidden_interval.intervals: wedge = BlockChainWedge( symbol_pool, offset=start, size=stop + 1 - start) pinned_chains.append(wedge) # Try to place bigger blockChains first pinned_chains.sort(key=lambda x: x.offset_min) blockChains.sort(key=lambda x: -x.max_size) fixed_chains = list(pinned_chains) log_asmbloc.debug("place chains") for chain in blockChains: if chain.pinned: continue fixed = False for i in xrange(1, len(fixed_chains)): prev_chain = fixed_chains[i - 1] next_chain = fixed_chains[i] if prev_chain.offset_max + chain.max_size < next_chain.offset_min: new_chains = prev_chain.merge(chain) fixed_chains[i - 1:i] = new_chains fixed = True break if not fixed: raise RuntimeError('Cannot find enough space to place blocks') return [chain for chain in fixed_chains if isinstance(chain, BlockChain)]
def brk(self, addr, vmmngr): """Stub for 'brk' syscall""" if addr == 0: addr = self.brk_current else: all_mem = vmmngr.get_all_memory() mapped = interval([(start, start + info["size"] - 1) for start, info in all_mem.iteritems()]) # Alloc missing and override missing = interval([(self.brk_current, addr)]) - mapped for start, stop in missing: vmmngr.add_memory_page(start, PAGE_READ|PAGE_WRITE, "\x00" * (stop - start + 1), "BRK") self.brk_current = addr return addr
def ret_func(self, target): if isinstance(target, (int, long)): target = ModularIntervals(self.size, interval([(target, target)])) if not isinstance(target, ModularIntervals): raise TypeError("Unsupported operation with %s" % target.__class__) if target.size != self.size: raise TypeError("Size are not the same: %s vs %s" % (self.size, target.size)) return func(self, target)
def _range_and(self, x_min, x_max, y_min, y_max): """Interval bounds for x & y, with - x, y of size @size - @x_min <= x <= @x_max - @y_min <= y <= @y_max - operations are considered unsigned From Hacker's Delight: Chapter 4 """ return interval([(self._range_and_min(x_min, x_max, y_min, y_max), self._range_and_max(x_min, x_max, y_min, y_max))])
def add_breakpoint(self, addr, callback): """Add a callback associated with addr. @addr: breakpoint address @callback: function with definition (jitter instance) """ self.breakpoints_handler.add_callback(addr, callback) self.jit.add_disassembly_splits(addr) # De-jit previously jitted blocks self.jit.addr_mod = interval([(addr, addr)]) self.jit.updt_automod_code(self.vm)
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, "\x00" * (b + 2 - a), repr(name)) for r_vaddr, data in all_data.items(): 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 _range_add(self, x_min, x_max, y_min, y_max): """Bounds interval for x + y, with - x, y of size 'self.size' - @x_min <= x <= @x_max - @y_min <= y <= @y_max - operations are considered unsigned From Hacker's Delight: Chapter 4 """ max_bound = self.mask if (x_min + y_min <= max_bound and x_max + y_max >= max_bound + 1): # HD returns 0, max_bound; but this is because it cannot handle multiple # interval. # x_max + y_max can only overflow once, so returns # [result_min, overflow] U [0, overflow_rest] return interval([(x_min + y_min, max_bound), (0, (x_max + y_max) & max_bound)]) else: return interval([((x_min + y_min) & max_bound, (x_max + y_max) & max_bound)])
def __init__(self, size, intervals=None): """Instanciate a ModularIntervals of size @size @size: maximum size of elements @intervals: (optional) interval instance, or any type supported by interval initialisation; element of the current instance """ # Create or cast @intervals argument if intervals is None: intervals = interval() if not isinstance(intervals, interval): intervals = interval(intervals) self.intervals = intervals self.size = size # Sanity check start, end = intervals.hull() if start is not None: assert start >= 0 if end is not None: assert end <= self.mask
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 xrange(1 << nb_elements): # Bit vector: if bit i is on, i is in the interval to_ret = interval() for i in xrange(nb_elements): if bvec & i == i: to_ret += [(i, i)] yield to_ret
def step(self): "Step in jit" self.myjit.jit.set_options(jit_maxline=1) self.myjit.jit.addr_mod = interval([(self.myjit.pc, self.myjit.pc)]) self.myjit.jit.updt_automod_code(self.myjit.vm) res = self.myjit.continue_run(step=True) self.handle_exception(res) self.myjit.jit.set_options(jit_maxline=50) self.on_step() return res
def substract_mems(self, arg1, arg2): """ Return the remaining memory areas of @arg1 - @arg2 @arg1, @arg2: ExprMem """ ptr_diff = self.expr_simp(arg2.arg - arg1.arg) ptr_diff = int(int32(ptr_diff.arg)) zone1 = interval([(0, arg1.size/8-1)]) zone2 = interval([(ptr_diff, ptr_diff + arg2.size/8-1)]) zones = zone1 - zone2 out = [] for start, stop in zones: ptr = arg1.arg + m2_expr.ExprInt(start, arg1.arg.size) ptr = self.expr_simp(ptr) value = self.expr_simp(self.symbols[arg1][start*8:(stop+1)*8]) mem = m2_expr.ExprMem(ptr, (stop - start + 1)*8) assert mem.size == value.size out.append((mem, value)) return out
def _interval_rotate(self, operation, shifter): """Apply the rotate operation @operation with a shifting ModularIntervals @shifter on the current instance""" # Consider only rotation without repetition, and enumerate # -> apply a '% size' on shifter shifter %= self.size ret = interval() for shift_range in shifter: for shift in xrange(shift_range[0], shift_range[1] + 1): for x_min, x_max in self.intervals: ret += self._range_rotate_uniq(x_min, x_max, shift, operation) return self.__class__(self.size, ret)
def _range_xor(self, x_min, x_max, y_min, y_max): """Interval bounds for x ^ y, with - x, y of size self.size - @x_min <= x <= @x_max - @y_min <= y <= @y_max - operations are considered unsigned From Hacker's Delight: Chapter 4 """ not_size = lambda x: x ^ self.mask min_xor = self._range_and_min(x_min, x_max, not_size(y_max), not_size(y_min)) | self._range_and_min(not_size(x_max), not_size(x_min), y_min, y_max) max_xor = self._range_or_max(0, self._range_and_max(x_min, x_max, not_size(y_max), not_size(y_min)), 0, self._range_and_max(not_size(x_max), not_size(x_min), y_min, y_max)) return interval([(min_xor, max_xor)])
def _range_xor(self, x_min, x_max, y_min, y_max): """Interval bounds for x ^ y, with - x, y of size self.size - @x_min <= x <= @x_max - @y_min <= y <= @y_max - operations are considered unsigned From Hacker's Delight: Chapter 4 """ not_size = lambda x: x ^ self.mask min_xor = self._range_and_min(x_min, x_max, not_size(y_max), not_size(y_min)) | self._range_and_min( not_size(x_max), not_size(x_min), y_min, y_max) max_xor = self._range_or_max( 0, self._range_and_max(x_min, x_max, not_size(y_max), not_size(y_min)), 0, self._range_and_max(not_size(x_max), not_size(x_min), y_min, y_max)) return interval([(min_xor, max_xor)])
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 __init__(self, ir_arch, bs=None): """Initialise a JitCore instance. @ir_arch: ir instance for current architecture @bs: bitstream """ self.ir_arch = ir_arch self.arch_name = "%s%s" % (self.ir_arch.arch.name, self.ir_arch.attrib) self.bs = bs self.known_blocs = {} self.loc_key_to_jit_block = BoundedDict( self.jitted_block_max_size, delete_cb=self.jitted_block_delete_cb) self.lbl2bloc = {} self.log_mn = False self.log_regs = False self.log_newbloc = False self.segm_to_do = set() self.jitcount = 0 self.addr2obj = {} self.addr2objref = {} self.blocs_mem_interval = interval() self.disasm_cb = None self.split_dis = set() self.options = { "jit_maxline": 50, # Maximum number of line jitted "max_exec_per_call": 0 # 0 means no limit } self.mdis = 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_block_callback=self.disasm_cb)
try: addrs.append(int(addr, 0)) except ValueError: # Second chance, try with symbol addrs.append(mdis.symbol_pool.getby_name(addr).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 # 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) allblocks = mdis.dis_multibloc(ad) log.info('func ok %.16x (%d)' % (ad, len(all_funcs))) all_funcs.add(ad) all_funcs_blocks[ad] = allblocks
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)
def automod_cb(self, addr=0, size=0): self.addr_mod += interval([(addr, addr + size / 8 - 1)]) return None
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 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()
from miasm2.core import asmblock from miasm2.arch.x86 import arch from miasm2.core import parse_asm from miasm2.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 clear_jitted_blocks(self): "Reset all jitted blocks" self.loc_key_to_jit_block.clear() self.lbl2bloc.clear() self.blocs_mem_interval = interval()
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() blocks, symbol_pool = parse_asm.parse_txt(machine.mn, attrib, source) # Fix shellcode addrs symbol_pool.set_offset(symbol_pool.getby_name("main"), addr_main)