def emul(self, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history Return the values of inputs nodes' elements @ctx: (optional) Initial context as dictionnary @step: (optional) Verbose execution Warning: The emulation is not sound if the inputs nodes depend on loop variant. """ # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) assignblks = [] # Build a single affectation block according to history last_index = len(self.relevant_loc_keys) for index, loc_key in enumerate(reversed(self.relevant_loc_keys), 1): if index == last_index and loc_key == self.initial_state.loc_key: line_nb = self.initial_state.line_nb else: line_nb = None assignblks += self.irblock_slice(self._ira.blocks[loc_key], line_nb).assignblks # Eval the block symbol_pool = AsmSymbolPool() temp_loc = symbol_pool.getby_name_create("Temp") symb_exec = SymbolicExecutionEngine(self._ira, ctx_init) symb_exec.eval_updt_irblock(IRBlock(temp_loc, assignblks), step=step) # Return only inputs values (others could be wrongs) return {element: symb_exec.symbols[element] for element in self.inputs}
def arm_guess_jump_table( mnemo, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool): ira = get_ira(mnemo, attrib) jra = ExprId('jra') jrb = ExprId('jrb') sp = AsmSymbolPool() ir_arch = ira(sp) ir_arch.add_block(cur_bloc) ir_blocks = ir_arch.blocks.values() for irblock in ir_blocks: # print 'X'*40 # print irblock pc_val = None # lr_val = None for exprs in irblock.irs: for e in exprs: if e.dst == ir_arch.pc: pc_val = e.src # if e.dst == mnemo.regs.LR: # lr_val = e.src if pc_val is None: continue if not isinstance(pc_val, ExprMem): continue assert(pc_val.size == 32) print pc_val ad = pc_val.arg ad = expr_simp(ad) print ad res = match_expr(ad, jra + jrb, set([jra, jrb])) if res is False: raise NotImplementedError('not fully functional') print res if not isinstance(res[jrb], ExprInt): raise NotImplementedError('not fully functional') base_ad = int(res[jrb]) print base_ad addrs = set() i = -1 max_table_entry = 10000 max_diff_addr = 0x100000 # heuristic while i < max_table_entry: i += 1 try: ad = upck32(pool_bin.getbytes(base_ad + 4 * i, 4)) except: break if abs(ad - base_ad) > max_diff_addr: break addrs.add(ad) print [hex(x) for x in addrs] for ad in addrs: offsets_to_dis.add(ad) l = symbol_pool.getby_offset_create(ad) c = AsmConstraintTo(l) cur_bloc.addto(c)
def __init__(self, arch, attrib, symbol_pool=None): if symbol_pool is None: symbol_pool = AsmSymbolPool() self.symbol_pool = symbol_pool self.blocks = {} self.pc = arch.getpc(attrib) self.sp = arch.getsp(attrib) self.arch = arch self.attrib = attrib # Lazy structure self._graph = None
def arm_guess_subcall( mnemo, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool): ira = get_ira(mnemo, attrib) sp = AsmSymbolPool() ir_arch = ira(sp) print '###' print cur_bloc ir_arch.add_block(cur_bloc) ir_blocks = ir_arch.blocks.values() # flow_graph = DiGraph() to_add = set() for irblock in ir_blocks: # print 'X'*40 # print irblock pc_val = None lr_val = None for exprs in irblock.irs: for e in exprs: if e.dst == ir_arch.pc: pc_val = e.src if e.dst == mnemo.regs.LR: lr_val = e.src if pc_val is None or lr_val is None: continue if not isinstance(lr_val, ExprInt): continue l = cur_bloc.lines[-1] if lr_val.arg != l.offset + l.l: continue # print 'IS CALL!' l = symbol_pool.getby_offset_create(int(lr_val)) c = AsmConstraintNext(l) to_add.add(c) offsets_to_dis.add(int(lr_val)) # if to_add: # print 'R'*70 for c in to_add: # print c cur_bloc.addto(c)
def miasm_anal(r2_op, r2_address, r2_buffer, r2_length): """Define an instruction behavior using miasm.""" # Cast radare2 variables opcode = ffi.cast("char*", r2_buffer) # Prepare the opcode opcode = ffi.unpack(opcode, r2_length) # Disassemble the opcode try: machine = miasm_machine() mode = machine.dis_engine().attrib instr = machine.mn().dis(opcode, mode) instr.offset = r2_address if instr.dstflow(): # Adjust arguments values using the instruction offset instr.dstflow2label(AsmSymbolPool()) dis_len = instr.l except: # Can't do anything with an invalid instruction return # Cast the RAnalOp structure and fill some fields r2_analop = ffi.cast("RAnalOp_r2m2*", r2_op) r2_analop.mnemonic = alloc_string(instr.name) r2_analop.size = dis_len r2_analop.type = R_ANAL_OP_TYPE_UNK r2_analop.eob = 0 # End Of Block # Convert miasm expressions to ESIL get_esil(r2_analop, instr) ### Architecture agnostic analysis # Instructions that *DO NOT* stop a basic bloc if instr.breakflow() is False: return else: r2_analop.eob = 1 # End Of Block # Assume that an instruction starting with 'RET' is a return # Note: add it to miasm2 as getpc() ? if instr.name[:3].upper().startswith("RET"): r2_analop.type = R_ANAL_OP_TYPE_RET # Instructions that explicitly provide the destination if instr and instr.dstflow(): expr = instr.getdstflow(None)[0] if instr.is_subcall(): r2_anal_subcall(r2_analop, expr) return if r2_analop.type == R_ANAL_OP_TYPE_UNK and instr.splitflow(): r2_anal_splitflow(r2_analop, r2_address, instr, expr) return if isinstance(expr, ExprInt): r2_analop.type = R_ANAL_OP_TYPE_JMP r2_analop.jump = int(expr.arg) & 0xFFFFFFFFFFFFFFFF elif isinstance(expr, ExprId): if isinstance(expr.name, AsmLabel): # Get the miasm2 AsmLabel address r2_analop.type = R_ANAL_OP_TYPE_JMP r2_analop.jump = label2address(expr) & 0xFFFFFFFFFFFFFFFF else: r2_analop.type = R_ANAL_OP_TYPE_UJMP elif isinstance(expr, ExprMem): r2_analop.type = R_ANAL_OP_TYPE_MJMP else: print >> sys.stderr, "miasm_anal(): don't know what to do with: %s" % instr
""" Test cases for dead code elimination""" from miasm2.expression.expression import ExprId, ExprInt, ExprAff, ExprMem from miasm2.core.asmblock import AsmSymbolPool from miasm2.analysis.data_flow import * from miasm2.ir.analysis import ira from miasm2.ir.ir import IRBlock, AssignBlock symbol_pool = AsmSymbolPool() a = ExprId("a", 32) b = ExprId("b", 32) c = ExprId("c", 32) d = ExprId("d", 32) r = ExprId("r", 32) a_init = ExprId("a_init", 32) b_init = ExprId("b_init", 32) c_init = ExprId("c_init", 32) d_init = ExprId("d_init", 32) r_init = ExprId("r_init", 32) # Return register pc = ExprId("pc", 32) sp = ExprId("sp", 32) CST1 = ExprInt(0x11, 32) CST2 = ExprInt(0x12, 32) CST3 = ExprInt(0x13, 32) LBL0 = symbol_pool.add_location("lbl0", 0) LBL1 = symbol_pool.add_location("lbl1", 1) LBL2 = symbol_pool.add_location("lbl2", 2)
def miasm_dis(r2_op, r2_address, r2_buffer, r2_length): """Disassemble an instruction using miasm.""" # Cast radare2 variables rasmop = ffi.cast("RAsmOp_r2m2*", r2_op) opcode = ffi.cast("char*", r2_buffer) # Prepare the opcode opcode = ffi.unpack(opcode, r2_length) # Get the miasm2 machine machine = miasm_machine() if machine is None: return # Disassemble the opcode try: mode = machine.dis_engine().attrib instr = machine.mn().dis(opcode, mode) instr.offset = r2_address if instr.dstflow(): # Remember ExprInt arguments sizes args_size = list() for i in range(len(instr.args)): if isinstance(instr.args[i], ExprInt): args_size.append(instr.args[i].size) else: args_size.append(None) # Adjust arguments values using the instruction offset instr.dstflow2label(AsmSymbolPool()) # Convert label back to ExprInt for i in range(len(instr.args)): if args_size[i] is None: continue if isinstance(instr.args[i], ExprId) and \ isinstance(instr.args[i].name, AsmLabel): addr = str(instr.args[i].name) addr = int(addr.split(":")[1], 16) instr.args[i] = ExprInt(addr, args_size[i]) dis_str = str(instr) dis_len = instr.l except: dis_str = "/!\ Can't disassemble using miasm /!\\" dis_len = 2 # GV: seems fischy ! # Remaining bytes buf_hex = opcode[0:dis_len].encode("hex") # Check buffer sizes if len(dis_str)-1 > 256: dis_str = "/!\ Disassembled instruction is too long /!\\" if len(buf_hex)-1 > 256: buf_hex = buf_hex[:255] # Fill the RAsmOp structure rasmop.size = dis_len rasmop.buf_asm = dis_str rasmop.buf_hex = buf_hex
import time from pdb import pm from miasm2.arch.msp430.arch import * from miasm2.core.asmblock import AsmSymbolPool symbol_pool = AsmSymbolPool() def h2i(s): return s.replace(' ', '').decode('hex') def u16swap(i): return struct.unpack('<H', struct.pack('>H', i))[0] reg_tests_msp = [ ("4456 mov.w SP, R4", "0441"), ("4d4f mov.b R13, R15", "4f4d"), ("49fe mov.w @R13, R9", "294d"), ("4982 mov.w 0x10(R14), R13", "1d4e1000"), ("4972 mov.w R14, 0x0(SP)", "814e0000"), ("46de mov.w 0x2(R14), 0x2(R13)", "9d4e02000200"), ("469e mov.w @0x2400, R11", "1b420024"), ("4c14 mov.w 0x4A96, R15", "3f40964a"), ("47c0 mov.w 0x1, R8", "1843"), ("48fc mov.w 0x2, R10", "2a43"), ("44fe mov.w 0x4, R7", "2742"), ("4a28 mov.w 0xFFFF, R15", "3f43"), ("4416 mov.w R5, @0x15C", "82455c01"), ("4a22 add.w R11, R15", "0f5b"),
import z3 from miasm2.core.asmblock import AsmSymbolPool from miasm2.expression.expression import * from miasm2.ir.translators.z3_ir import Z3Mem, TranslatorZ3 # Some examples of use/unit tests. symbol_pool = AsmSymbolPool() translator1 = TranslatorZ3(endianness="<", symbol_pool=symbol_pool) translator2 = TranslatorZ3(endianness=">", symbol_pool=symbol_pool) def equiv(z3_expr1, z3_expr2): s = z3.Solver() s.add(z3.Not(z3_expr1 == z3_expr2)) return s.check() == z3.unsat def check_interp(interp, constraints, bits=32, valbits=8): """Checks that a list of @constraints (addr, value) (as python ints) match a z3 FuncInterp (@interp). """ constraints = dict((addr, z3.BitVecVal(val, valbits)) for addr, val in constraints) l = interp.as_list() for entry in l: if not isinstance(entry, list) or len(entry) < 2: continue addr, value = entry[0], entry[1] if addr.as_long() in constraints: