def initenv(self): from amoco.cas.mapper import mapper m = mapper() m.setmemory(self.mmap) m[cpu.stack_elt] = cst(0, 6) return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for r in self.cpu.R: m[r] = self.cpu.cst(0, 16) m[self.cpu.pc] = self.cpu.cst(0x4400, 16) return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() m[cpu.pc] = cpu.cst(self.bin.entrypoints[0], 32) for r in cpu.R: m[r] = cpu.cst(0, 32) return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k,v in ((cpu.pc, cpu.cst(self.bin.entrypoints[0],64)), ): m[k] = v return m
def map(self): if self._map: return self._map else: if self.data._is_block: self._map = mapper(self.data.instr) return self._map
def evaluate_lines(instr, lines, in_str): # Run the emulation of the basic bloc machine = mapper() def print_machine(machine): return sorted(str(machine).split("\n")) # Emulation with amoco is too slow # For 'movsd' tests depending of 'df' are not simplified, therefore there # are too many nested tests # For 'cmovXX' tests are not simplified either perf_count = {'movsd': 0, 'cmov': 0} for line in lines: # rip is kept symbolic if line.opname in ('call', 'jmp'): machine[env.rip] = env.rip else: machine[env.rip] = env.rip - line.bytelen if line.opname == 'movsd': perf_count['movsd'] += 1 if perf_count['movsd'] >= 3: return (('Emulated too slow (movsd)', line, print_machine(machine)), [None]) if line.opname.startswith('cmov'): perf_count['cmov'] += 1 if perf_count['cmov'] >= 3: return (('Emulated too slow (cmov)', line, print_machine(machine)), [None]) try: log.debug("EVAL %-20r %s", line.amoco.bytes, line) line.amoco(machine) except NotImplementedError: return (('Not implemented', line, print_machine(machine)), [None]) except NameError: return (('Cannot be emulated (name)', line, print_machine(machine)), [None]) except amoco.arch.core.InstructionError: return (('Cannot be emulated', line, print_machine(machine)), [None]) except TypeError: return (('Not callable', line, print_machine(machine)), [None]) if line.opname == 'call': # amoco emulation pushes rip+i.length # we prefer to push the label of the next basic bloc label = instr.symbols.find_symbol(section=line.section, address=line.offset + line.amoco.length) machine[env.mem(env.rsp, cpu_addrsize)] = expressions.lab(label, size=cpu_addrsize) retval = machine[env.rip] msg, val = evaluate(retval, machine, instr.symbols.find_symbols, instr, in_str) if val is None: return ((str(retval.__class__), retval, print_machine(machine)), [None]) elif val == [None]: return ((msg, retval, print_machine(machine)), [None]) else: return (msg, val)
def step_instruction(self, vaddr, **kargs): """execute instruction at virtual address, updating the mmap memory state and returning the instruction's mapper""" i = self.read_instruction(vaddr, **kargs) m = mapper().use(**kargs) m.setmemory(self.mmap) i(m) self.mmap.merge(m.memory()) return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() e = self.bin.entrypoints[0] for k, v in ((cpu.pc, cpu.cst(e, 32)), (cpu.npc, cpu.cst(e + 4, 32)), (cpu.sp, cpu.cst(0xc0000000, 32)), (cpu.fp, cpu.cst(0xc0000000, 32))): m[k] = v return m
def relocate(self, vaddr): from amoco.cas.mapper import mapper m = mapper() mz = self.mmap._zones[None] for z in mz._map: z.vaddr += vaddr pc = self.cpu.PC() m[pc] = self.cpu.cst(vaddr, pc.size) self._initmap = m self.initenv = lambda: self._initmap
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k, v in ((cpu.eip, cpu.cst(self.bin.entrypoints[0], 32)), (cpu.ebp, cpu.cst(0, 32)), (cpu.eax, cpu.cst(0, 32)), (cpu.ebx, cpu.cst(0, 32)), (cpu.ecx, cpu.cst(0, 32)), (cpu.edx, cpu.cst(0, 32)), (cpu.esi, cpu.cst(0, 32)), (cpu.edi, cpu.cst(0, 32))): m[k] = v return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() e = self.bin.entrypoints[0] for k,v in ((cpu.pc , cpu.cst(e,32)), (cpu.npc, cpu.cst(e+4,32)), (cpu.sp , cpu.cst(0xc0000000,32)), (cpu.fp , cpu.cst(0xc0000000,32))): m[k] = v return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k, v in ((cpu.rip, cpu.cst(self.bin.entrypoints[0], 64)), (cpu.rbp, cpu.cst(0, 64)), (cpu.rax, cpu.cst(0, 64)), (cpu.rbx, cpu.cst(0, 64)), (cpu.rcx, cpu.cst(0, 64)), (cpu.rdx, cpu.cst(0, 64)), (cpu.rsi, cpu.cst(0, 64)), (cpu.rdi, cpu.cst(0, 64))): m[k] = v return m
def pcnpc(i, fmap): fmap[pc] = fmap[pc] + i.length if len(fmap.conds) > 0: cond = fmap.conds.pop() m = mapper() f(i, m) for l, v in m: fmap[l] = tst(cond, v, fmap(l)) else: f(i, fmap)
def model_to_mapper(r,locs): m = mapper() mlocs = [] for l in locs: if l._is_mem: mlocs.append(l) else: m[l] = cst(r.eval(l.to_smtlib()).as_long(),l.size) for l in mlocs: m[l] = cst(r.eval(l.to_smtlib()).as_long(),l.size) return m
def relocate(self,vaddr): from amoco.cas.mapper import mapper m = mapper() mz = self.mmap._zones[None] for z in mz._map: z.vaddr += vaddr # force mmap cache update: self.mmap.restruct() # create _initmap with new pc as vaddr: pc = self.cpu.opt_ptr m[pc] = self.cpu.cst(vaddr,pc.size) self._initmap = m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k,v in ((cpu.pc, cpu.cst(self.bin.entrypoints[0],32)), ): if v&1: # switch to Thumb mode if pc&1: self.cpu.internals['isetstate'] = 1 v = (v>>1)<<1 m[k] = v return m
def setstack(self, *args): m0 = mapper() m0.setmemory(self.mmap) m0[self.cpu.stack_elt] = cst(0, 6) for x in args: if isinstance(x, str): x = reg(x, 64) elif isinstance(x, int): x = cst(x, 64) self.cpu._push_(m0, x) return m0
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k,v in ((cpu.pc, cpu.cst(self.card.entrypoints[0],16)), (cpu.sp, cpu.cst(0xFFFE,16)), (cpu.a , cpu.cst(0x11 if self.card.colorgb() else 0x01, 8)), (cpu.f , cpu.cst(0xb0,8)), (cpu.bc, cpu.cst(0x0013,16)), (cpu.de, cpu.cst(0x00d8,16)), (cpu.hl, cpu.cst(0x014d,16))): m[k] = v return m
def _set_rw(self): if self.opname in ['save', 'restore']: r = set([env.psr, env.sp]) r.update([reg for reg in env.r if not str(reg).startswith('g')]) w = set([env.psr, env.sp]) #self.mapper = None self.rw = (r, w) return m = mapper() self.amoco(m) #self.mapper = m self.rw = get_rw(m)
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k, v in ((cpu.pc, cpu.cst(self.card.entrypoints[0], 16)), (cpu.sp, cpu.cst(0xFFFE, 16)), (cpu.a, cpu.cst(0x11 if self.card.colorgb() else 0x01, 8)), (cpu.f, cpu.cst(0xb0, 8)), (cpu.bc, cpu.cst(0x0013, 16)), (cpu.de, cpu.cst(0x00d8, 16)), (cpu.hl, cpu.cst(0x014d, 16))): m[k] = v return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k,v in ((cpu.rip, cpu.cst(self.bin.entrypoints[0],64)), (cpu.rbp, cpu.cst(0,64)), (cpu.rax, cpu.cst(0,64)), (cpu.rbx, cpu.cst(0,64)), (cpu.rcx, cpu.cst(0,64)), (cpu.rdx, cpu.cst(0,64)), (cpu.rsi, cpu.cst(0,64)), (cpu.rdi, cpu.cst(0,64))): m[k] = v return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k,v in ((cpu.eip, cpu.cst(self.bin.entrypoints[0],32)), (cpu.ebp, cpu.cst(0,32)), (cpu.eax, cpu.cst(0,32)), (cpu.ebx, cpu.cst(0,32)), (cpu.ecx, cpu.cst(0,32)), (cpu.edx, cpu.cst(0,32)), (cpu.esi, cpu.cst(0,32)), (cpu.edi, cpu.cst(0,32))): m[k] = v return m
def test_mapper_000(): # create two instructions # movq %rcx, (%rip) # movq (%rip), %rcx i0 = cpu.disassemble(b"\x48\x89\x0d\x00\x00\x00\x00") i1 = cpu.disassemble(b"\x48\x8b\x0d\x00\x00\x00\x00") # modify the first instruction to insert a label, e.g. because # there is a relocation # movq %rcx, foo(%rip) i0.operands[0].a.disp = expressions.lab('foo', size=64) # evaluate those two instructions m = mapper() i0(m) i1(m) assert str(m[rcx]) == 'M64(rip+14)'
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for r in cpu.R: m[r] = p.cpu.cst(0, 32) m[cpu.pc] = p.cpu.cst(0xFFF80000, 32) m[cpu.sp] = p.cpu.cst(0xFFF90000, 32) m[cpu.SR] = p.cpu.cst(0, 32) m[cpu.IMASK] = p.cpu.cst(0xF, 4) m[cpu.VBR] = p.cpu.cst(0, 32) m[cpu.FPSCR] = p.cpu.cst(0, 32) m[cpu.DN] = p.cpu.bit1 m[cpu.RM] = p.cpu.cst(1, 2) m[cpu.IBCR] = p.cpu.cst(0, 16) m[cpu.IBNR] = p.cpu.cst(0, 16) return m
def sym_exec_path(bb: block, input_values: Any, output_addrs_amoco_ops: Any) -> Any: """ Executes a given basic block symbolically and returns the created mapper. :param bb: amoco basic block. :param input_values: TODO :return: a map that contains the results of the symbolic execution, """ # Ignore aliasing in order to simplify final mapper. mapper.assume_no_aliasing = True base_map = mapper() # type: mapper output_addrs_eval_ops = list() # Set beginning input values if exist. for addr, op_amoco, value_amoco in input_values: if addr == 0x0: base_map[op_amoco] = value_amoco # Execute basic block. for instr in bb.instr: # Set input values for corresponding instruction if exist. for addr, op_amoco, value_amoco in input_values: if addr == instr.address: # Evaluate current left hand expression before inserting the given value. op_amoco_eval = op_amoco.eval(base_map) base_map[op_amoco_eval] = value_amoco break base_map.update(instr) # If the defining instruction of the memory/pointer output is executed, # extract the evaluated form of this expression to extract the final result # at the end. for addr, _, op_amoco in output_addrs_amoco_ops: if instr.address == addr: output_addrs_eval_ops.append( (addr, op_amoco, op_amoco.eval(base_map))) break return base_map, output_addrs_eval_ops
def get_targets(self, node, parent): """Computes expression of target address in the given node, based on its address and the architecture's program counter (PC). Arguments: node: the current node, not yet added to the cfg. parent: the parent node in the cfg that has targeted the current node. (Unused by :class:`fforward` but required as a generic API for parent classes). Returns: :class:`target`: the evaluated PC expression. """ m = mapper() pc = self.prog.cpu.PC() m[pc] = node.data.address pc = (node.map(pc)).eval(m) return target(pc, node).expand()
def model_to_mapper(r, locs): m = mapper() mlocs = [] for l in set(locs): if l._is_mem: mlocs.append(l) else: x = r.eval(l.to_smtlib()) try: m[l] = cst(x.as_long(), l.size) except AttributeError: pass for l in mlocs: x = r.eval(l.to_smtlib()) try: m[l] = cst(x.as_long(), l.size) except AttributeError: pass return m
def test_mapper_001(): # create three instructions # movq %rax, (%rip) # movl %eax, (%rip) # movq -16(%rbp), %rcx i0 = cpu.disassemble(b"\x48\x89\x05\x00\x00\x00\x00") i1 = cpu.disassemble(b"\x89\x05\x00\x00\x00\x00") i2 = cpu.disassemble(b"\x48\x8b\x4d\xf0") # modify the first two instructions to insert a label # movq %rax, foo(%rip) i0.operands[0].a.disp = expressions.lab('foo', size=64) # movb %eax, bar(%rip) i1.operands[0].a.disp = expressions.lab('bar', size=64) # evaluate those three instructions m = mapper() i0(m) i1(m) i2(m) assert str(m[rcx]) == 'M64(rbp-16)'
def _set_rw(self): if self.opname in ( 'psllw', 'pslld', 'psllq', 'psrlw', 'psrld', 'psrlq', ): # Workaround until amoco corrects this bug # https://github.com/bdcht/amoco/issues/65 w = get_touched(self.amoco.operands[0]) r = get_touched(self.amoco.operands[0]) r.update(get_touched(self.amoco.operands[1])) r.update(get_touched(self.amoco.operands[1], True)) self.rw = r, w return m = mapper() self.amoco(m) r, w = get_rw(m) add_semantics_missing(self, r, w, env, get_touched) r.add(env.rip) w.add(env.rip) self.rw = r, w
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for r in self.cpu.R: m[r] = self.cpu.cst(0,16) m[self.cpu.pc] = self.cpu.cst(0x4400,16) return m
def initenv(self): m = mapper() m[cpu.pc] = cpu.cst(0, 64) return m
def initenv(self): from amoco.cas.mapper import mapper m = mapper() m[self.cpu.pc] = self.cpu.cst(0,21) return m
def m(): '''return a aliasing mapper with function scope''' from amoco.cas.mapper import mapper mapper.assume_no_aliasing = False return mapper()
def map(): '''return a no_aliasing mapper with module scope''' from amoco.cas.mapper import mapper mapper.assume_no_aliasing = True return mapper()
def evaluate_lines(instr, lines, in_str): # Run the emulation of the basic bloc m = mapper() def print_machine(machine): return sorted(str(machine).split("\n")) for line in lines: try: line.amoco(m) except NotImplementedError: return (('Not implemented', line, print_machine(m)), [None]) except NameError: return (('Cannot be emulated (name)', line, print_machine(m)), [None]) except amoco.arch.core.InstructionError: return (('Cannot be emulated', line, print_machine(m)), [None]) except TypeError: return (('Not callable', line, print_machine(m)), [None]) instr.amoco(m) # Register %g0 contains always zero m2 = mapper() m2[env.g0] = env.cst(0) pc = m[env.pc].eval(m2) pc = merge_slices(pc) log.debug("PC %s:%s", pc.__class__.__name__, pc) if pc._is_lab: return 'ID', [pc.ref] elif pc._is_mem and pc.a.base._is_lab: label = pc.a.base.ref if len(getattr(label, 'lines', [])) > 0 \ and getattr(label.lines[0], 'type', None) == 'long': value = label.lines[0].value[0] if hasattr(value, 'name'): # Symbol return ('MEM_ID', [value]) return (('MEM_ID', pc.a.base.ref, print_machine(m)), [None]) elif pc._is_mem and pc.a.base._is_eqn: # Is it an element of an array? # Find the array index t = get_touched(pc, indirect=True) t.discard(env.fp) if len(t) == 1: t = t.pop() dst_lst = [] pointer_len = 4 log.debug(" ARRAY of %d-byte items", pointer_len) invalid_indexes = 0 index_in_array = -1 while invalid_indexes < 4 and index_in_array < 4: index_in_array += 1 m2 = mapper() m2[t] = env.cst(index_in_array) z = pc.eval(m2) z = merge_slices(z) if not z._is_lab: invalid_indexes += 1 continue log.debug(" MEM[%d]=%s", pointer_len * index_in_array, z.ref) if not z.ref in dst_lst: dst_lst.append(z.ref) if dst_lst == []: return (('MEM_EXP', pc, print_machine(m)), [None]) return ('ARRAY', dst_lst) return (('MEM_EXP', pc, print_machine(m)), [None]) else: return (('', pc, print_machine(m)), [None])
def initenv(self): from amoco.cas.mapper import mapper m = mapper() m[cpu.pc] = cpu.cst(0, 64) return m