def ands(ir, instr, arg1, arg2, arg3): e = [] arg3 = extend_arg(arg2, arg3) res = arg2 & arg3 e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg2, arg3))] e += update_flag_nf(res) e.append(ExprAff(arg1, res)) return e, []
def stp(ir, instr, arg1, arg2, arg3): e = [] addr, updt = get_mem_access(arg3) e.append(ExprAff(ExprMem(addr, arg1.size), arg1)) e.append( ExprAff(ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size), arg2)) if updt: e.append(updt) return e, []
def call_effects(self, ad): """ Default simulation of a function call to @ad @ad: (Expr) address of the called function """ return [ AssignBlock([ ExprAff(self.ret_reg, ExprOp('call_func_ret', ad, self.sp)), ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)), ]) ]
def call_effects(self, ad, instr): new_sp = ExprOp("+", self.sp, ExprOp("-", ExprInt(0x4, 32))) next_addr = instr.offset + len(instr.b) next_label = self.symbol_pool.getby_offset(next_addr) block1 = AssignBlock([ ExprAff(self.sp, new_sp), ExprAff(ExprMem(new_sp, 32), ExprId(next_label, 32)) ]) block2 = AssignBlock([ExprAff(self.IRDst, ad)]) return [block1, block2]
def bics(ir, instr, arg1, arg2, arg3): e = [] tmp1, tmp2 = arg2, (~extend_arg(arg2, arg3)) e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', tmp1, tmp2))] e += update_flag_nf(res) e.append(ExprAff(arg1, res)) e += null_flag_co() return e, []
def movk(ir, instr, arg1, arg2): e = [] if isinstance(arg2, ExprOp): assert (arg2.op == 'slice_at' and isinstance(arg2.args[0], ExprInt) and isinstance(arg2.args[1], ExprInt)) value, shift = int(arg2.args[0].arg), int(arg2.args[1]) e.append(ExprAff(arg1[shift:shift + 16], ExprInt(value, 16))) else: e.append(ExprAff(arg1[:16], ExprInt(int(arg2), 16))) return e, []
def call_effects(self, ad, instr): print hex(instr.offset), instr stk_before = idc.GetSpd(instr.offset) stk_after = idc.GetSpd(instr.offset + instr.l) stk_diff = stk_after - stk_before print hex(stk_diff) call_assignblk = AssignBlock([ ExprAff(self.ret_reg, ExprOp('call_func_ret', ad)), ExprAff(self.sp, self.sp + ExprInt(stk_diff, self.sp.size)) ], instr) return [call_assignblk], []
def call_effects(self, ad, instr): return [AssignBlock([ExprAff(self.ret_reg, ExprOp('call_func_ret', ad, self.sp, self.arch.regs.R3, self.arch.regs.R4, self.arch.regs.R5, )), ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)), ], instr )]
def bfm(ir, instr, arg1, arg2, arg3, arg4): e = [] rim, sim = int(arg3.arg), int(arg4) + 1 if sim > rim: res = arg2[rim:sim] e.append(ExprAff(arg1[:sim - rim], res)) else: shift_i = arg2.size - rim shift = ExprInt(shift_i, arg2.size) res = arg2[:sim] e.append(ExprAff(arg1[shift_i:shift_i + sim], res)) return e, []
def msr(ir, instr, arg1, arg2, arg3, arg4, arg5): e = [] if arg1.is_int(3) and arg2.is_id("c4") and arg3.is_id( "c2") and arg4.is_int(0): e.append(ExprAff(nf, arg5[31:32])) e.append(ExprAff(zf, arg5[30:31])) e.append(ExprAff(cf, arg5[29:30])) e.append(ExprAff(of, arg5[28:29])) else: raise NotImplementedError("MSR not implemented") return e, []
def call_effects(self, ad, instr): """Default modelisation of a function call to @ad. This may be used to: * insert dependencies to arguments (stack base, registers, ...) * add some side effects (stack clean, return value, ...) @ad: (Expr) address of the called function @instr: native instruction which is responsible of the call """ return [AssignBlock( [ExprAff(self.ret_reg, ExprOp('call_func_ret', ad, self.sp)), ExprAff(self.sp, ExprOp( 'call_func_stack', ad, self.sp)), ])]
def l_str(ir, instr, arg1, arg2): e = [] addr, updt = get_mem_access(arg2) e.append(ExprAff(ExprMem(addr, arg1.size), arg1)) if updt: e.append(updt) return e, []
def ldrs_size(ir, instr, arg1, arg2, size): e = [] addr, updt = get_mem_access(arg2) e.append(ExprAff(arg1, ExprMem(addr, size).signExtend(arg1.size))) if updt: e.append(updt) return e, []
def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): IntermediateRepresentation.post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks) new_irblocks = [] for irb in ir_blocks: pc_val = None lr_val = None for assignblk in irb: pc_val = assignblk.get(self.arch.regs.PC, pc_val) lr_val = assignblk.get(self.arch.regs.RA, lr_val) if pc_val is None or lr_val is None: new_irblocks.append(irb) continue if lr_val.is_loc(): offset = self.loc_db.get_location_offset(lr_val.loc_key) if offset is not None: lr_val = ExprInt(offset, 32) if not lr_val.is_int(): continue instr = block.lines[-2] if int(lr_val) != instr.offset + 8: raise ValueError("Wrong arg") # CALL lbl = block.get_next() new_lbl = self.gen_label() call_assignblks, extra_irblocks = self.call_effects(pc_val, instr) ir_blocks += extra_irblocks irs.append(AssignBlock([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))], instr)) new_irblocks.append(IRBlock(new_lbl, call_assignblks)) new_irblocks.append(irb.set_dst(ExprId(new_lbl, size=self.pc.size))) return new_irblocks
def call_effects(self, ad, instr): call_assignblk = AssignBlock([ ExprAff( self.ret_reg, ExprOp( 'call_func_ret', ad, self.sp, self.arch.regs.RCX, self.arch.regs.RDX, self.arch.regs.R8, self.arch.regs.R9, )), ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)), ], instr) return [call_assignblk], []
def post_add_bloc(self, block, ir_blocks): IntermediateRepresentation.post_add_bloc(self, block, ir_blocks) for irb in ir_blocks: pc_val = None lr_val = None for assignblk in irb.irs: pc_val = assignblk.get(self.arch.regs.PC, pc_val) lr_val = assignblk.get(self.arch.regs.RA, lr_val) if pc_val is None or lr_val is None: continue if not expr_is_int_or_label(lr_val): continue if expr_is_label(lr_val): lr_val = ExprInt32(lr_val.name.offset) line = block.lines[-2] if lr_val.arg != line.offset + 8: raise ValueError("Wrong arg") # CALL lbl = block.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val, line) irs.append(AssignBlock([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nblock = IRBlock(new_lbl, irs) nblock.lines = [line] * len(irs) self.blocks[new_lbl] = nblock irb.dst = ExprId(new_lbl, size=self.pc.size)
def _gen_path_constraints(self, translator, expr, expected): """Generate path constraint from @expr. Handle special case with generated loc_keys """ out = [] expected = self._ira.loc_db.canonize_to_exprloc(expected) expected_is_loc_key = expected.is_loc() for consval in possible_values(expr): value = self._ira.loc_db.canonize_to_exprloc(consval.value) if expected_is_loc_key and value != expected: continue if not expected_is_loc_key and value.is_loc_key(): continue conds = z3.And(*[ translator.from_expr(cond.to_constraint()) for cond in consval.constraints ]) if expected != value: conds = z3.And(conds, translator.from_expr(ExprAff(value, expected))) out.append(conds) if out: conds = z3.Or(*out) else: # Ex: expr: lblgen1, expected: 0x1234 # -> Avoid unconsistent solution lblgen1 = 0x1234 conds = translator.from_expr(self.unsat_expr) return conds
def strh(ir, instr, arg1, arg2): e = [] addr, updt = get_mem_access(arg2) e.append(ExprAff(ExprMem(addr, 16), arg1[:16])) if updt: e.append(updt) return e, []
def m2instruction_to_r2esil(instruction): """Convert a miasm2 instruction to a radare2 ESIL""" # Get the IR try: machine = miasm_machine() ir = machine.ir() iir, eiir = ir.get_ir(instruction) except: iir, eiir = [], [] # Remove IRDst for i in iir: if isinstance(i, ExprAff) and isinstance(i.dst, ExprId) \ and i.dst.name == "IRDst": iir.remove(i) # Convert IRs result = list() if iir: result += [m2expr_to_r2esil(ir) for ir in m2_filter_IRDst(iir)] for irbloc in eiir: for ir_list in irbloc.irs: aff = (ExprAff(dst, src) for dst, src in ir_list.iteritems()) result += (m2expr_to_r2esil(ir) for ir in m2_filter_IRDst(aff)) if not len(result): return None return ",".join(result)
def post_add_block(self, block, ir_blocks): IntermediateRepresentation.post_add_block(self, block, ir_blocks) new_irblocks = [] for irb in ir_blocks: pc_val = None lr_val = None for assignblk in irb.irs: pc_val = assignblk.get(self.arch.regs.PC, pc_val) lr_val = assignblk.get(self.arch.regs.RA, lr_val) if pc_val is None or lr_val is None: new_irblocks.append(irb) continue if not expr_is_int_or_label(lr_val): new_irblocks.append(irb) continue if expr_is_label(lr_val): lr_val = ExprInt(lr_val.name.offset, 32) instr = block.lines[-2] if lr_val.arg != instr.offset + 8: raise ValueError("Wrong arg") # CALL lbl = block.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val, instr) irs.append( AssignBlock( [ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))], instr)) new_irblocks.append(IRBlock(new_lbl, irs)) new_irblocks.append(irb.set_dst(ExprId(new_lbl, size=self.pc.size))) return new_irblocks
def call_effects(self, ad): irs = [[ ExprAff( self.ret_reg, ExprOp( 'call_func_ret', ad, self.sp, self.arch.regs.RCX, self.arch.regs.RDX, self.arch.regs.R8, self.arch.regs.R9, )), ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)), ]] return irs
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) if not bloc.lines: return l = bloc.lines[-1] sub_call_dst = None if not l.is_subcall(): return sub_call_dst = l.args[0] if expr_is_label(sub_call_dst): sub_call_dst = sub_call_dst.name for irb in ir_blocs: l = irb.lines[-1] sub_call_dst = None if not l.is_subcall(): continue sub_call_dst = l.args[0] if expr_is_label(sub_call_dst): sub_call_dst = sub_call_dst.name lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(l.args[0]) irs.append( AssignBlock( [ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size) return
def jmp(ir, instr, reg_or_imm): """JMP - Change PC to a register content or an immediate. Note: the behavior in VLIW mode is not implemented""" take_jmp = ExprInt(1, 32) if isinstance(reg_or_imm, ExprId): # PC <- Rm31..1||0 new_PC = ExprAff(PC, reg_or_imm) else: # PC <- PC31..28||0000||(target24)23..1||0 new_PC = ExprAff( PC, ExprOp("+", ExprOp("&", PC, ExprInt(0xF0000000, 32)), reg_or_imm)) return [new_PC, ExprAff(ir.IRDst, new_PC)], []
def cset(ir, instr, arg1, arg2): e = [] cond_expr = cond2expr[arg2.name] e.append( ExprAff( arg1, ExprCond(cond_expr, ExprInt(1, arg1.size), ExprInt(0, arg1.size)))) return e, []
def update_flag_arith_addwc_zn(arg1, arg2, arg3): """ Compute znp flags for (arg1 + arg2 + cf) """ e = [] e += update_flag_zfaddwc_eq(arg1, arg2, arg3) e += [ExprAff(nf, ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))] return e
def call_effects(self, ad): return [ AssignBlock([ ExprAff( self.ret_reg, ExprOp( 'call_func_ret', ad, self.sp, self.arch.regs.RCX, self.arch.regs.RDX, self.arch.regs.R8, self.arch.regs.R9, )), ExprAff(self.sp, ExprOp('call_func_stack', ad, self.sp)), ]) ]
def update_flag_arith_subwc_zn(arg1, arg2, arg3): """ Compute znp flags for (arg1 - (arg2 + cf)) """ e = [] e += update_flag_zfsubwc_eq(arg1, arg2, arg3) e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))] return e
def update_flag_arith_sub_zn(arg1, arg2): """ Compute zf and nf flags for (arg1 - arg2) """ e = [] e += update_flag_zf_eq(arg1, arg2) e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, arg2))] return e
def sbcs(ir, instr, arg1, arg2, arg3): arg3 = extend_arg(arg2, arg3) e = [] r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size)) e.append(ExprAff(arg1, r)) e += update_flag_arith_subwc_zn(arg2, arg3, ~cf) e += update_flag_arith_subwc_co(arg2, arg3, ~cf) return e, []
def adcs(ir, instr, arg1, arg2, arg3): arg3 = extend_arg(arg2, arg3) e = [] r = arg2 + arg3 + cf.zeroExtend(arg3.size) e.append(ExprAff(arg1, r)) e += update_flag_arith_addwc_zn(arg2, arg3, cf) e += update_flag_arith_addwc_co(arg2, arg3, cf) return e, []