def test_arm_postprocess_ret(): for i in xrange(3): # e91ba8f0 # ldmdb R11, {R4,R11,SP,PC} irsb = pyvex.IRSB(data=b'\xe9\x1b\xa8\xf0', mem_addr=0xed4028, arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE), num_inst=1, opt_level=i) nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret') # e91badf0 # ldmdb R11, {R4-R8,R10,R11,SP,PC} irsb = pyvex.IRSB(data=b'\xe9\x1b\xa8\xf0', mem_addr=0x4d4028, arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE), num_inst=1, opt_level=i) nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret') # 00a89de8 # ldmfd SP, {R11,SP,PC} # Fixed by Fish in the VEX fork, commit 43c78f608490f9a5c71c7fca87c04759c1b93741 irsb = pyvex.IRSB(data=b'\x00\xa8\x9d\xe8', mem_addr=0xc800b57c, arch=archinfo.ArchARMEL(endness=archinfo.Endness.LE), num_inst=1, opt_level=1) nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')
def test_memory(): arches = ['VexArchX86', 'VexArchPPC32', 'VexArchAMD64', 'VexArchARM'] # we're not including VexArchMIPS32 cause it segfaults sometimes for i in xrange(10000): try: s = hex(random.randint(2**100, 2**100 * 16))[2:] a = random.choice(arches) p = pyvex.IRSB(bytes=s, arch=a) except pyvex.PyVEXError: pass kb_start = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss for i in xrange(20000): try: s = hex(random.randint(2**100, 2**100 * 16))[2:] a = random.choice(arches) p = pyvex.IRSB(bytes=s, arch=a) except pyvex.PyVEXError: pass del p gc.collect() kb_end = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # allow a 2mb leeway nose.tools.assert_less(kb_end - kb_start, 2000)
def test_arm_postprocess_ret(): for i in range(3): # e91ba8f0 # ldmdb R11, {R4,R11,SP,PC} irsb = pyvex.IRSB( data=b"\xe9\x1b\xa8\xf0", mem_addr=0xED4028, arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE), num_inst=1, opt_level=i, ) assert irsb.jumpkind == "Ijk_Ret" # e91badf0 # ldmdb R11, {R4-R8,R10,R11,SP,PC} irsb = pyvex.IRSB( data=b"\xe9\x1b\xa8\xf0", mem_addr=0x4D4028, arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE), num_inst=1, opt_level=i, ) assert irsb.jumpkind == "Ijk_Ret" # 00a89de8 # ldmfd SP, {R11,SP,PC} # Fixed by Fish in the VEX fork, commit 43c78f608490f9a5c71c7fca87c04759c1b93741 irsb = pyvex.IRSB( data=b"\x00\xa8\x9d\xe8", mem_addr=0xC800B57C, arch=archinfo.ArchARMEL(endness=archinfo.Endness.LE), num_inst=1, opt_level=1, ) assert irsb.jumpkind == "Ijk_Ret"
def test_two_irsb(self): irsb1 = pyvex.IRSB(bytes='\x5d\xc3') irsb2 = pyvex.IRSB(bytes='\x5d\x5d\x5d\x5d') stmts1 = irsb1.statements() stmts2 = irsb2.statements() self.assertNotEqual(len(stmts1), len(stmts2))
def test_two_irsb(): irsb1 = pyvex.IRSB(bytes='\x5d\xc3') irsb2 = pyvex.IRSB(bytes='\x5d\x5d\x5d\x5d') stmts1 = irsb1.statements stmts2 = irsb2.statements nose.tools.assert_not_equal(len(stmts1), len(stmts2))
def test_two_irsb(): irsb1 = pyvex.IRSB(data=b'\x5d\xc3', mem_addr=0, arch=ArchAMD64()) irsb2 = pyvex.IRSB(data=b'\x5d\x5d\x5d\x5d', mem_addr=0, arch=ArchAMD64()) stmts1 = irsb1.statements stmts2 = irsb2.statements nose.tools.assert_not_equal(len(stmts1), len(stmts2))
def test_irsb_tyenv(): irsb = pyvex.IRSB(bytes='\x5d\xc3') print irsb.tyenv print "Orig" print irsb.tyenv print "Copy" print irsb.tyenv.deepCopy() print "Empty" irsb2 = pyvex.IRSB() print irsb2.tyenv print "Unwrapped" irsb2.tyenv = irsb.tyenv.deepCopy() print irsb2.tyenv
def get_irsbs(self, code, address): irsbs = [] code_address = address while code_address <= address + len( code) - self.arch.instruction_alignment: try: irsb = pyvex.IRSB(code[code_address - address:], code_address, self.arch, opt_level=0) irsbs.append(irsb) except: # If decoding fails, we can't use this gadget traceback.print_exc() return [] # So just return an empty list if (self.arch.name not in extra_archinfo.ENDS_EARLY_ARCHS or irsb.jumpkind != 'Ijk_Boring' or not self.irsb_ends_with_constant_pc(irsb)): break # Find the last address that was translated (For some architectures, pyvex stops before the end of a block) last_addr = None for stmt in irsb.statements: if stmt.tag == 'Ist_IMark': last_addr = stmt.addr # If we couldn't get any statements from the instructions, there was a problem. if last_addr == None: # So just return an empty list return [] # And move the code address forward to the next untranslated instruction code_address = last_addr + self.arch.instruction_alignment return irsbs
def test_irsb_deepCopy(self): irsb = pyvex.IRSB(bytes='\x5d\xc3') stmts = irsb.statements() irsb2 = irsb.deepCopy() stmts2 = irsb2.statements() self.assertEqual(len(stmts), len(stmts2))
def test_irstmt_pp(self): irsb = pyvex.IRSB(bytes='\x5d\xc3') stmts = irsb.statements() for i in stmts: print "STMT: ", i.pp() print
def ret(self, expr=None): if expr is not None: self.set_return_expr(expr) if self.arguments is not None: l.debug("Returning without setting exits due to 'internal' call.") return elif self.ret_to is not None: self.state.log.add_action(SimActionExit(self.state, self.ret_to)) self.add_successor(self.state, self.ret_to, self.state.se.true, 'Ijk_Ret') else: if self.cleanup: self.state.options.discard(o.AST_DEPS) self.state.options.discard(o.AUTO_REFS) ret_irsb = pyvex.IRSB(arch=self.state.arch, bytes=self.state.arch.ret_instruction, mem_addr=self.addr) ret_simirsb = SimIRSB(self.state, ret_irsb, inline=True, addr=self.addr) if not ret_simirsb.flat_successors + ret_simirsb.unsat_successors: ret_state = ret_simirsb.default_exit else: ret_state = (ret_simirsb.flat_successors + ret_simirsb.unsat_successors)[0] if self.cleanup: self.state.options.add(o.AST_DEPS) self.state.options.add(o.AUTO_REFS) self.add_successor(ret_state, ret_state.scratch.target, ret_state.scratch.guard, ret_state.scratch.jumpkind)
def ret(self, expr=None): if expr is not None: self.set_return_expr(expr) if self.arguments is not None: l.debug("Returning without setting exits due to 'internal' call.") return elif self.ret_to is not None: self.state.log.add_action(SimActionExit(self.state, self.ret_to)) self.add_successor(self.state, self.ret_to, self.state.se.true, 'Ijk_Ret') else: if self.cleanup: self.state.options.discard(o.AST_DEPS) self.state.options.discard(o.AUTO_REFS) if o.KEEP_IP_SYMBOLIC in self.state.options and isinstance(self.addr, claripy.ast.Base): # TODO maybe i want to keep address symbolic s = claripy.Solver() addrs = s.eval(self.state.regs.ip, 257, extra_constraints=tuple(self.state.ip_constraints)) if len(addrs) > 256: addrs = self.state.se.any_n_int(self.state.regs.ip, 1) self.addr = addrs[0] ret_irsb = pyvex.IRSB(self.state.arch.ret_instruction, self.addr, self.state.arch) ret_simirsb = SimIRSB(self.state, ret_irsb, inline=True, addr=self.addr) if not ret_simirsb.flat_successors + ret_simirsb.unsat_successors: ret_state = ret_simirsb.default_exit else: ret_state = (ret_simirsb.flat_successors + ret_simirsb.unsat_successors)[0] if self.cleanup: self.state.options.add(o.AST_DEPS) self.state.options.add(o.AUTO_REFS) self._add_successor_state(ret_state, ret_state.scratch.target)
def _block(self, addr): # for sanity checking. we live in the world of heuristics now. thumb = self.arch.name.startswith("ARM") and addr % 2 == 1 realaddr = addr if thumb: realaddr -= 1 dat = ''.join(self.memory.read_bytes(realaddr, 40)) return pyvex.IRSB(dat, addr, self.arch, bytes_offset=1 if thumb else 0)
def _block(self, addr, skip_stmts=False): # for sanity checking. we live in the world of heuristics now. thumb = self.arch.name.startswith("ARM") and addr % 2 == 1 realaddr = addr if thumb: realaddr -= 1 dat = self._block_bytes(realaddr, 40) return pyvex.IRSB(dat, addr, self.arch, bytes_offset=1 if thumb else 0, opt_level=1, skip_stmts=skip_stmts)
def test_irexpr_rdtmp(): m = pyvex.IRExpr.RdTmp.get_instance(123) nose.tools.assert_equal(m.tag, "Iex_RdTmp") nose.tools.assert_equal(m.tmp, 123) irsb = pyvex.IRSB(b'\x90\x5d\xc3', mem_addr=0x0, arch=ArchAMD64()) print("TMP:",irsb.next.tmp)
def test_inspect_exit(): class counts: #pylint:disable=no-init exit_before = 0 exit_after = 0 def handle_exit_before(state): counts.exit_before += 1 exit_target = state.inspect.exit_target nose.tools.assert_equal(state.solver.eval(exit_target), 0x3f8) # change exit target state.inspect.exit_target = 0x41414141 nose.tools.assert_equal(state.inspect.exit_jumpkind, "Ijk_Boring") nose.tools.assert_true(state.inspect.exit_guard.is_true()) def handle_exit_after(state): #pylint:disable=unused-argument counts.exit_after += 1 s = SimState(arch="AMD64", mode="symbolic") irsb = pyvex.IRSB(b"\x90\x90\x90\x90\xeb\x0a", mem_addr=1000, arch=archinfo.ArchAMD64()) # break on exit s.inspect.b('exit', BP_BEFORE, action=handle_exit_before) s.inspect.b('exit', BP_AFTER, action=handle_exit_after) # step it succ = SimEngineVEX().process(s, irsb).flat_successors # check nose.tools.assert_equal(succ[0].solver.eval(succ[0].ip), 0x41414141) nose.tools.assert_equal(counts.exit_before, 1) nose.tools.assert_equal(counts.exit_after, 1)
def test_irsb_deepCopy(): irsb = pyvex.IRSB(data=b'\x5d\xc3', mem_addr=0, arch=ArchAMD64()) stmts = irsb.statements irsb2 = copy.deepcopy(irsb) stmts2 = irsb2.statements nose.tools.assert_equal(len(stmts), len(stmts2))
def test_irsb_deepCopy(): irsb = pyvex.IRSB(bytes='\x5d\xc3') stmts = irsb.statements irsb2 = irsb.deepCopy() stmts2 = irsb2.statements nose.tools.assert_equal(len(stmts), len(stmts2))
def _block(self, addr): # for sanity checking. we live in the world of heuristics now. thumb = self.arch.name.startswith("ARM") and addr % 2 == 1 realaddr = addr if thumb: realaddr -= 1 dat = self.memory.load(AT.from_lva(realaddr, self).to_rva(), 40) return pyvex.IRSB(dat, addr, self.arch, bytes_offset=1 if thumb else 0, opt_level=1)
def lift(self, insn): try: self.irsb = pyvex.IRSB(insn.decode('hex'), self.addr, self.arch) if self.irsb.instructions != 1: raise InvalidInstruction if self.irsb.jumpkind == 'Ijk_NoDecode': return JSONize(Uninterpretable().to_JSON()) self.tyenv = self.irsb.tyenv except pyvex.errors.PyVEXError: return JSONize(Uninterpretable().to_JSON()) try: for stmt in self.irsb.statements: parsed = self.fetch_stmt(stmt) self.deal_stmt(parsed) if isinstance(self.irsb.next, pyvex.expr.RdTmp): tmp = self.irsb.next.tmp name = Basic('t%d' % tmp) size = Basic(self._get_size(self.irsb.next)) addr = Var(name, size) else: addr = Number(self.irsb.next.con.value, 32) self.statements.append(End(addr)) return JSONize(Stmts(self.statements).to_JSON()) except IncapableError: return JSONize(Incapable().to_JSON())
def test_memory(): try: import resource except ImportError: print( "Cannot import the resource package. Are you using Windows? Skip test_memory()." ) return arches = [ArchX86(), ArchPPC32(endness=Endness.BE), ArchAMD64(), ArchARM()] # we're not including ArchMIPS32 cause it segfaults sometimes # disable logging, as that may fill up log buffers somewhere logging.disable(logging.ERROR) for _ in range(10000): try: s = os.urandom(32) a = random.choice(arches) p = pyvex.IRSB(data=s, mem_addr=0, arch=a) except pyvex.PyVEXError: pass kb_start = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss for _ in range(20000): try: s = os.urandom(32) a = random.choice(arches) p = pyvex.IRSB(data=s, mem_addr=0, arch=a) except pyvex.PyVEXError: pass del p gc.collect() logging.disable(logging.NOTSET) kb_end = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss pyvex.pvc.clear_log() pyvex.pvc.LibVEX_ShowAllocStats() print(LibVEXLifter.get_vex_log()) # allow a 5mb leeway nose.tools.assert_less(kb_end - kb_start, 5000)
def __init__(self, bytes, address=0x0, arch_str='x64'): if arch_str == 'x64': arch = archinfo.ArchAMD64() else: pass #TODO: self.Address = address self.irsb = pyvex.IRSB(bytes, address, arch)
def test_irstmt_noop(): irsb = pyvex.IRSB(bytes='\x90\x5d\xc3') irnop = irsb.statements[0] irnop2 = pyvex.IRStmt.NoOp() irnop3 = irnop2.deepCopy() nose.tools.assert_equal(irnop.tag, "Ist_NoOp") nose.tools.assert_equal(type(irnop), type(irnop2)) nose.tools.assert_equal(type(irnop), type(irnop3))
def test_irstmt_noop(self): irsb = pyvex.IRSB(bytes='\x90\x5d\xc3') irnop = irsb.statements()[0] irnop2 = pyvex.IRStmt.NoOp() irnop3 = irnop2.deepCopy() self.assertEqual(irnop.tag, "Ist_NoOp") self.assertEqual(type(irnop), type(irnop2)) self.assertEqual(type(irnop), type(irnop3))
def vex(self): if not self._vex: offset = 1 if self._thumb else 0 self._vex = pyvex.IRSB(self.bytes, self.addr, self._arch, bytes_offset=offset) self._parse_vex_info() return self._vex
def translate_to_irsb(block_bytes, block_dsm, start_index, end_index, start_address, arch, file_path, opt_level): end_is_fake = False if not end_index: end_index = len(block_bytes) end_is_fake = True assert isinstance(block_bytes[start_index:end_index], (str, bytes)) end_address = start_address + (end_index - start_index) instruction_size = len(arch.nop_instruction) if isinstance(arch, archinfo.ArchMIPS32): end_address -= instruction_size assert 0 <= start_index < end_index try: # we need to get the real (inside the indexes) last dsm instruction, unless its fake then we -1 it. irsb = pyvex.IRSB(block_bytes[start_index:end_index], start_address, arch, opt_level=opt_level) succs = irsb.constant_jump_targets except pyvex.PyVEXError as e: logging.warning( 'Error `{}` when trying to translate:\n {}\nBytes: {}\nArch: {}\nPath={}' .format( e, '\n'.join([ '{} {} {}'.format(hex(a_d_s[0]), a_d_s[1], a_d_s[2]) for a_d_s in block_dsm ]), [hex(ord(c)) for c in block_bytes[start_index:end_index]], arch, file_path)) return if irsb.jumpkind == 'Ijk_NoDecode': logging.debug("Block at {} is NoDecode, dropping.".format( hex(start_address))) return # remove the cluttering NoOp that the VEX translation adds irsb.statements = [ s for s in irsb.statements if type(s) is not pyvex.stmt.NoOp ] if irsb.jumpkind == 'Ijk_Boring' and irsb.direct_next and len(succs) == 1: next_block_addr = succs.pop() if start_address < next_block_addr < end_address: logging.debug('\n'.join([ '{} {} {}'.format(hex(a_d_s2[0]), a_d_s2[1], a_d_s2[2]) for a_d_s2 in block_dsm ])) logging.debug(irsb._pp_str()) logging.debug({'binary': block_bytes[start_index:end_index]}) logging.error("Block at [{},{}] cut off at {}.".format( hex(start_address), hex(end_address), hex(next_block_addr))) assert False return irsb
def test_irexpr_rdtmp(): m = pyvex.IRExpr.RdTmp(123) nose.tools.assert_equal(m.tag, "Iex_RdTmp") nose.tools.assert_equal(m.tmp, 123) m.tmp = 1337 nose.tools.assert_equal(m.tmp, 1337) nose.tools.assert_raises(Exception, pyvex.IRExpr.RdTmp) irsb = pyvex.IRSB('\x90\x5d\xc3', mem_addr=0x0, arch=ArchAMD64()) print("TMP:", irsb.next.tmp)
def test_store_simplification(): state = SimState(arch='X86') state.regs.esp = state.solver.BVS('stack_pointer', 32) state.regs.ebp = state.solver.BVS('base_pointer', 32) state.regs.eax = state.solver.BVS('base_eax', 32) irsb = pyvex.IRSB(b'PT]\xc2\x10\x00', 0x4000, state.arch) sim_successors = HeavyVEXMixin(None).process(state.copy(), irsb=irsb) exit_state = sim_successors.all_successors[0] nose.tools.assert_true(claripy.backends.z3.is_true(exit_state.regs.ebp == state.regs.esp - 4))
def test_arm_postprocess_ret(): for i in xrange(3): # e91ba8f0 # ldmdb R11, {R4,R11,SP,PC} irsb = pyvex.IRSB(data='\xe9\x1b\xa8\xf0', mem_addr=0xed4028, arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE), num_inst=1, opt_level=i) nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret') # e91badf0 # ldmdb R11, {R4-R8,R10,R11,SP,PC} irsb = pyvex.IRSB(data='\xe9\x1b\xa8\xf0', mem_addr=0x4d4028, arch=archinfo.ArchARMEL(endness=archinfo.Endness.BE), num_inst=1, opt_level=i) nose.tools.assert_equal(irsb.jumpkind, 'Ijk_Ret')
def test_convert_from_vex_irsb(): arch = archinfo.arch_from_id('AMD64') manager = ailment.Manager(arch=arch) irsb = pyvex.IRSB(block_bytes, block_addr, arch, opt_level=0) ablock = ailment.IRSBConverter.convert(irsb, manager) print(str(ablock))