def call_effects(self, ad, instr): call_assignblk = AssignBlock( [ ExprAff( self.ret_reg, ExprOp( 'call_func_ret', ad, self.arch.regs.R0, self.arch.regs.R1, self.arch.regs.R2, self.arch.regs.R3, ) ), ExprAff( self.sp, ExprOp('call_func_stack', ad, self.sp) ), ], instr ) cond = instr.additional_info.cond if cond == 14: # COND_ALWAYS: return [call_assignblk], [] # Call is a conditional instruction cond = tab_cond[cond] loc_next = self.get_next_loc_key(instr) loc_next_expr = ExprLoc(loc_next, 32) loc_do = self.loc_db.add_location() loc_do_expr = ExprLoc(loc_do, 32) dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr) call_assignblks = [ call_assignblk, AssignBlock([ExprAff(self.IRDst, loc_next_expr)], instr), ] e_do = IRBlock(loc_do, call_assignblks) assignblks_out = [ AssignBlock([ExprAff(self.IRDst, dst_cond)], instr) ] return assignblks_out, [e_do]
def _convert_phi(self): """Inserts corresponding phi functions inplace into IRBlock at the beginning""" for loc_key in self._phinodes: irblock = self.get_block(loc_key) assignblk = AssignBlock(self._phinodes[loc_key]) # insert at the beginning new_irs = IRBlock(loc_key, [assignblk] + list(irblock.assignblks)) self.ircfg.blocks[loc_key] = new_irs
def as_assignblock(self): """Return the current state as an AssignBlock""" warnings.warn( 'DEPRECATION WARNING: use "modified(ids=True, mems=True)" instead of as_assignblock' ) out = [] for dst, src in self.modified(ids=True, mems=True): out.append((dst, src)) return AssignBlock(dict(out))
def gen_irblock(label, exprs_list): irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = IRBlock(label, irs) return irbl
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([ ExprAssign(self.ret_reg, ExprOp('call_func_ret', ad)), ExprAssign(self.sp, self.sp + ExprInt(stk_diff, self.sp.size)) ], instr) return [call_assignblk], []
def gen_irblock(label, exprs_list): lines = [None for _ in xrange(len(exprs_list))] irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = IRBlock(label, irs, lines) return irbl
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): 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 call_effects(self, addr, instr): assignblks, extra = super(IRADelModCallStack, self).call_effects(addr, instr) if not args.calldontmodstack: return assignblks, extra out = [] for assignblk in assignblks: dct = dict(assignblk) dct = { dst:src for (dst, src) in dct.iteritems() if dst != self.sp } out.append(AssignBlock(dct, assignblk.instr)) return out, extra
def apply_expr(self, expr): """Evaluate @expr and apply side effect if needed (ie. if expr is an assignment). Return the evaluated value""" # Update value if needed if isinstance(expr, m2_expr.ExprAff): ret = self.eval_expr(expr.src) self.eval_ir(AssignBlock([expr])) else: ret = self.eval_expr(expr) return ret
def insert_parallel_copy(self): """ Naive Out-of-SSA from CSSA (without coalescing for now) - Replace Phi - Create room for parallel copies in Phi's parents """ ircfg = self.ssa.graph for irblock in ircfg.blocks.values(): if not irblock_has_phi(irblock): continue # Replace Phi with Phi's dst = new_var parallel_copies = {} for dst in self.phi_destinations[irblock.loc_key]: new_var = self.phi_new_var[dst] parallel_copies[dst] = new_var assignblks = list(irblock) assignblks[0] = AssignBlock(parallel_copies, irblock[0].instr) new_irblock = IRBlock(irblock.loc_key, assignblks) ircfg.blocks[irblock.loc_key] = new_irblock # Insert new_var = src in each Phi's parent, at the end of the block parent_to_parallel_copies = {} parallel_copies = {} for dst in irblock[0]: new_var = self.phi_new_var[dst] for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src for parent, parallel_copies in parent_to_parallel_copies.iteritems( ): parent = ircfg.blocks[parent] assignblks = list(parent) assignblks.append( AssignBlock(parallel_copies, parent[-1].instr)) new_irblock = IRBlock(parent.loc_key, assignblks) ircfg.blocks[parent.loc_key] = new_irblock
def gen_irblock(label, exprs_list): """ Returns an IRBlock. Used only for tests purpose """ irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = IRBlock(label, irs) return irbl
def casp(ir, instr, arg1, arg2, arg3): # XXX TODO: memory barrier e = [] if arg1.size == 32: regs = gpregs32_expr else: regs = gpregs64_expr index1 = regs.index(arg1) index2 = regs.index(arg2) # TODO endianness comp_value = ExprCompose(regs[index1], regs[index1 + 1]) new_value = ExprCompose(regs[index2], regs[index2 + 1]) assert arg3.is_op('preinc') ptr = arg3.args[0] data = ExprMem(ptr, comp_value.size) loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) e.append( ExprAssign( ir.IRDst, ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do, loc_store))) e_store = [] e_store.append(ExprAssign(data, new_value)) e_store.append(ExprAssign(ir.IRDst, loc_do)) blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)]) e_do = [] e_do.append(ExprAssign(regs[index1], data[:data.size / 2])) e_do.append(ExprAssign(regs[index1 + 1], data[data.size / 2:])) e_do.append(ExprAssign(ir.IRDst, loc_next)) blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)]) return e, [blk_store, blk_do]
def assignblk_to_irbloc(self, instr, assignblk): """ Ensure IRDst is always set in the head @assignblk of the @instr @instr: an instruction instance @assignblk: Assignblk instance """ new_assignblk = dict(assignblk) if self.ir_arch.IRDst not in assignblk: offset = instr.offset + instr.l dst = m2_expr.ExprInt(offset, self.ir_arch.IRDst.size) new_assignblk[self.ir_arch.IRDst] = dst irs = [AssignBlock(new_assignblk, instr)] return IRBlock(self.ir_arch.get_instr_label(instr), irs)
def apply_expr(self, expr): """Evaluate @expr and apply side effect if needed (ie. if expr is an assignment). Return the evaluated value""" # Eval expression to_eval = expr.src if isinstance(expr, m2_expr.ExprAff) else expr ret = self.expr_simp(self.eval_expr(to_eval)) # Update value if needed if isinstance(expr, m2_expr.ExprAff): self.eval_ir(AssignBlock([m2_expr.ExprAff(expr.dst, ret)])) return ret
def add_out_reg_end(ir_arch_a, ircfg_a): # Add dummy dependency to uncover out regs affectation for loc in ircfg_a.leaves(): irblock = ircfg_a.blocks.get(loc) if irblock is None: continue regs = {} for reg in ir_arch_a.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) new_assiblk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(new_assiblk) new_irblock = IRBlock(irblock.loc_key, assignblks) ircfg_a.blocks[loc] = new_irblock
def remove_assign_eq(self): """ Remove trivial expressions (a=a) in the current graph """ for irblock in self.ssa.graph.blocks.values(): assignblks = list(irblock) for i, assignblk in enumerate(assignblks): out = {} for dst, src in assignblk.iteritems(): if dst == src: continue out[dst] = src assignblks[i] = AssignBlock(out, assignblk.instr) self.ssa.graph.blocks[irblock.loc_key] = IRBlock(irblock.loc_key, assignblks)
def gen_irbloc(label, exprs_list): """ Returns an IRBlock with empty lines. Used only for tests purpose """ lines = [None for _ in xrange(len(exprs_list))] irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = irbloc(label, irs, lines) return irbl
def eval_updt_expr(self, expr): """ Evaluate @expr and apply side effect if needed (ie. if expr is an assignment). Return the evaluated value """ # Update value if needed if expr.is_aff(): ret = self.eval_expr(expr.src) self.eval_updt_assignblk(AssignBlock([expr])) else: ret = self.eval_expr(expr) return ret
def assignblk_to_irbloc(self, instr, assignblk): """ Ensure IRDst is always set in the head @assignblk of the @instr @instr: an instruction instance @assignblk: Assignblk instance """ new_assignblk = dict(assignblk) if self.ir_arch.IRDst not in assignblk: offset = instr.offset + instr.l loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset) dst = ExprLoc(loc_key, self.ir_arch.IRDst.size) new_assignblk[self.ir_arch.IRDst] = dst irs = [AssignBlock(new_assignblk, instr)] return IRBlock(self.ir_arch.get_loc_key_for_instr(instr), irs)
def call_effects(self, ad, instr): call_assignblk = AssignBlock([ ExprAff( self.ret_reg, ExprOp( 'call_func_ret', ad, self.arch.regs.A0, self.arch.regs.A1, self.arch.regs.A2, self.arch.regs.A3, )), ], instr) return [call_assignblk], []
def gen_equations(self): for irb in self.blocks.values(): symbols_init = dict(self.arch.regs.all_regs_ids_init) sb = SymbolicExecutionEngine(self, dict(symbols_init)) sb.emulbloc(irb) eqs = [] for n_w in sb.symbols: v = sb.symbols[n_w] if n_w in symbols_init and symbols_init[n_w] == v: continue eqs.append(ExprAff(n_w, v)) print '*' * 40 print irb irb.irs = [AssignBlock(eqs)]
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 call_effects(self, ad, instr): call_assignblks = AssignBlock([ ExprAssign( self.ret_reg, ExprOp( 'call_func_ret', ad, self.sp, self.arch.regs.R3, self.arch.regs.R4, self.arch.regs.R5, )), ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)), ], instr) return [call_assignblks], []
def del_dst_zr(self, instr, instr_ir, extra_ir): "Writes to zero register are discarded" regs_to_fix = [WZR, XZR] instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix] new_irblocks = [] for irblock in extra_ir: irs = [] for assignblk in irblock.irs: new_dsts = {dst:src for dst, src in assignblk.iteritems() if dst not in regs_to_fix} irs.append(AssignBlock(new_dsts, assignblk.instr)) new_irblocks.append(IRBlock(irblock.label, irs)) return instr_ir, new_irblocks
def remove_phi(self): """ Remove phi operators in @ifcfg @ircfg: IRDiGraph instance """ for irblock in self.ssa.graph.blocks.values(): assignblks = list(irblock) out = {} for dst, src in assignblks[0].iteritems(): if src.is_op('Phi'): assert set([dst]) == set(src.args) continue out[dst] = src assignblks[0] = AssignBlock(out, assignblks[0].instr) self.ssa.graph.blocks[irblock.loc_key] = IRBlock(irblock.loc_key, assignblks)
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 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 load_from_int(ir_arch, bs, is_addr_ro_variable): """ Replace memory read based on constant with static value @ir_arch: ira instance @bs: binstream instance @is_addr_ro_variable: callback(addr, size) to test memory candidate """ modified = False for label, block in ir_arch.blocks.iteritems(): assignblks = list() for assignblk in block: out = {} for dst, src in assignblk.iteritems(): # Test src mems = get_memlookup(src, bs, is_addr_ro_variable) src_new = src if mems: replace = {} for mem in mems: value = read_mem(bs, mem) replace[mem] = value src_new = src.replace_expr(replace) if src_new != src: modified = True # Test dst pointer if dst is mem if dst.is_mem(): ptr = dst.arg mems = get_memlookup(ptr, bs, is_addr_ro_variable) ptr_new = ptr if mems: replace = {} for mem in mems: value = read_mem(bs, mem) replace[mem] = value ptr_new = ptr.replace_expr(replace) if ptr_new != ptr: modified = True dst = ExprMem(ptr_new, dst.size) out[dst] = src_new out = AssignBlock(out, assignblk.instr) assignblks.append(out) block = IRBlock(block.loc_key, assignblks) ir_arch.blocks[block.loc_key] = block return modified
def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del (new_assignblk[dst]) # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if (isinstance(dst, ExprId) and dst.size == 32 and dst in replace_regs): src = src.zeroExtend(64) dst = replace_regs[dst].arg dst = self.expr_fix_regs_for_mode(dst) src = self.expr_fix_regs_for_mode(src) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs)
from miasm2.expression.expression import * from miasm2.ir.ir import AssignBlock from miasm2.expression.simplifications import expr_simp id_a = ExprId("a", 32) id_b = ExprId("b", 32) int0 = ExprInt(0, id_a.size) # Test AssignBlock ## Constructors assignblk1 = AssignBlock([ExprAssign(id_a, id_b)]) assignblk2 = AssignBlock({id_a: id_b}) ## Equality assignblk1_bis = AssignBlock([ExprAssign(id_a, id_b)]) assert assignblk1 == assignblk1_bis assert assignblk1 == assignblk2 ## Immutability try: assignblk1[id_a] = id_a except RuntimeError: pass else: raise RuntimeError("An error was expected") try: del assignblk1[id_a] except RuntimeError: pass else: raise RuntimeError("An error was expected")
def test_ClassDef(self): from miasm2.expression.expression import ExprInt32, ExprId, ExprMem, \ ExprCompose, ExprAff from miasm2.arch.x86.sem import ir_x86_32 from miasm2.ir.symbexec import symbexec from miasm2.ir.ir import AssignBlock addrX = ExprInt32(-1) addr0 = ExprInt32(0) addr1 = ExprInt32(1) addr8 = ExprInt32(8) addr9 = ExprInt32(9) addr20 = ExprInt32(20) addr40 = ExprInt32(40) addr50 = ExprInt32(50) mem0 = ExprMem(addr0) mem1 = ExprMem(addr1, 8) mem8 = ExprMem(addr8) mem9 = ExprMem(addr9) mem20 = ExprMem(addr20) mem40v = ExprMem(addr40, 8) mem40w = ExprMem(addr40, 16) mem50v = ExprMem(addr50, 8) mem50w = ExprMem(addr50, 16) id_x = ExprId('x') id_y = ExprId('y', 8) id_a = ExprId('a') id_eax = ExprId('eax_init') e = symbexec(ir_x86_32(), {mem0: id_x, mem1: id_y, mem9: id_x, mem40w: id_x[:16], mem50v: id_y, id_a: addr0, id_eax: addr0}) self.assertEqual(e.find_mem_by_addr(addr0), mem0) self.assertEqual(e.find_mem_by_addr(addrX), None) self.assertEqual(e.eval_expr(ExprMem(addr1 - addr1)), id_x) self.assertEqual(e.eval_expr(ExprMem(addr1, 8)), id_y) self.assertEqual(e.eval_expr(ExprMem(addr1 + addr1)), ExprCompose( id_x[16:32], ExprMem(ExprInt32(4), 16))) self.assertEqual(e.eval_expr(mem8), ExprCompose( id_x[0:24], ExprMem(ExprInt32(11), 8))) self.assertEqual(e.eval_expr(mem40v), id_x[:8]) self.assertEqual(e.eval_expr(mem50w), ExprCompose( id_y, ExprMem(ExprInt32(51), 8))) self.assertEqual(e.eval_expr(mem20), mem20) e.func_read = lambda x: x self.assertEqual(e.eval_expr(mem20), mem20) self.assertEqual(set(e.modified()), set(e.symbols)) self.assertRaises( KeyError, e.symbols.__getitem__, ExprMem(ExprInt32(100))) self.assertEqual(e.apply_expr(id_eax), addr0) self.assertEqual(e.apply_expr(ExprAff(id_eax, addr9)), addr9) self.assertEqual(e.apply_expr(id_eax), addr9) # apply_change / eval_ir / apply_expr ## x = a (with a = 0x0) assignblk = AssignBlock() assignblk[id_x] = id_a e.eval_ir(assignblk) self.assertEqual(e.apply_expr(id_x), addr0) ## x = a (without replacing 'a' with 0x0) e.apply_change(id_x, id_a) self.assertEqual(e.apply_expr(id_x), id_a) ## x = a (with a = 0x0) self.assertEqual(e.apply_expr(assignblk.dst2ExprAff(id_x)), addr0) self.assertEqual(e.apply_expr(id_x), addr0)
def test_ClassDef(self): from miasm2.expression.expression import ExprInt, ExprId, ExprMem, \ ExprCompose, ExprAff from miasm2.arch.x86.sem import ir_x86_32 from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.ir.ir import AssignBlock id_x = ExprId('x', 32) id_a = ExprId('a', 32) id_b = ExprId('b', 32) id_c = ExprId('c', 32) id_d = ExprId('d', 32) id_e = ExprId('e', 64) sb = SymbolicExecutionEngine(ir_x86_32(), { ExprMem(ExprInt(0x4, 32), 8): ExprInt(0x44, 8), ExprMem(ExprInt(0x5, 32), 8): ExprInt(0x33, 8), ExprMem(ExprInt(0x6, 32), 8): ExprInt(0x22, 8), ExprMem(ExprInt(0x7, 32), 8): ExprInt(0x11, 8), ExprMem(ExprInt(0x20, 32), 32): id_x, ExprMem(ExprInt(0x40, 32), 32): id_x, ExprMem(ExprInt(0x44, 32), 32): id_a, ExprMem(ExprInt(0x54, 32), 32): ExprInt(0x11223344, 32), ExprMem(id_a, 32): ExprInt(0x11223344, 32), id_a: ExprInt(0, 32), id_b: ExprInt(0, 32), ExprMem(id_c, 32): ExprMem(id_d + ExprInt(0x4, 32), 32), ExprMem(id_c + ExprInt(0x4, 32), 32): ExprMem(id_d + ExprInt(0x8, 32), 32), }) self.assertEqual(sb.eval_expr(ExprInt(1, 32)-ExprInt(1, 32)), ExprInt(0, 32)) ## Test with unknown mem + integer self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0, 32), 32)), ExprMem(ExprInt(0, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(1, 32), 32)), ExprCompose(ExprMem(ExprInt(1, 32), 24), ExprInt(0x44, 8))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(2, 32), 32)), ExprCompose(ExprMem(ExprInt(2, 32), 16), ExprInt(0x3344, 16))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(3, 32), 32)), ExprCompose(ExprMem(ExprInt(3, 32), 8), ExprInt(0x223344, 24))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 32)), ExprInt(0x11223344, 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(5, 32), 32)), ExprCompose(ExprInt(0x112233, 24), ExprMem(ExprInt(8, 32), 8))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(6, 32), 32)), ExprCompose(ExprInt(0x1122, 16), ExprMem(ExprInt(8, 32), 16))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(7, 32), 32)), ExprCompose(ExprInt(0x11, 8), ExprMem(ExprInt(8, 32), 24))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(8, 32), 32)), ExprMem(ExprInt(8, 32), 32)) ## Test with unknown mem + integer self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x50, 32), 32)), ExprMem(ExprInt(0x50, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x51, 32), 32)), ExprCompose(ExprMem(ExprInt(0x51, 32), 24), ExprInt(0x44, 8))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x52, 32), 32)), ExprCompose(ExprMem(ExprInt(0x52, 32), 16), ExprInt(0x3344, 16))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x53, 32), 32)), ExprCompose(ExprMem(ExprInt(0x53, 32), 8), ExprInt(0x223344, 24))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x54, 32), 32)), ExprInt(0x11223344, 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x55, 32), 32)), ExprCompose(ExprInt(0x112233, 24), ExprMem(ExprInt(0x58, 32), 8))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x56, 32), 32)), ExprCompose(ExprInt(0x1122, 16), ExprMem(ExprInt(0x58, 32), 16))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x57, 32), 32)), ExprCompose(ExprInt(0x11, 8), ExprMem(ExprInt(0x58, 32), 24))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x58, 32), 32)), ExprMem(ExprInt(0x58, 32), 32)) ## Test with unknown mem + id self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1D, 32), 32)), ExprCompose(ExprMem(ExprInt(0x1D, 32), 24), id_x[:8])) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1E, 32), 32)), ExprCompose(ExprMem(ExprInt(0x1E, 32), 16), id_x[:16])) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1F, 32), 32)), ExprCompose(ExprMem(ExprInt(0x1F, 32), 8), id_x[:24])) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x20, 32), 32)), id_x) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x21, 32), 32)), ExprCompose(id_x[8:], ExprMem(ExprInt(0x24, 32), 8))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x22, 32), 32)), ExprCompose(id_x[16:], ExprMem(ExprInt(0x24, 32), 16))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x23, 32), 32)), ExprCompose(id_x[24:], ExprMem(ExprInt(0x24, 32), 24))) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x24, 32), 32)), ExprMem(ExprInt(0x24, 32), 32)) ## Partial read self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 8)), ExprInt(0x44, 8)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x20, 32), 8)), id_x[:8]) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x23, 32), 8)), id_x[24:]) ## Merge self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x40, 32), 64)), ExprCompose(id_x, id_a)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x42, 32), 32)), ExprCompose(id_x[16:], id_a[:16])) # Merge memory self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x100, 32), 32)), ExprMem(ExprInt(0x100, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(id_c + ExprInt(0x2, 32), 32)), ExprMem(id_d + ExprInt(0x6, 32), 32)) ## Func read def custom_func_read(mem): if mem == ExprMem(ExprInt(0x1000, 32), 32): return id_x return mem sb.func_read = custom_func_read ## Unmodified read self.assertEqual(sb.eval_expr(ExprMem(ExprInt(4, 32), 8)), ExprInt(0x44, 8)) ## Modified read self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x1000, 32), 32)), id_x) ## Apply_change / eval_ir / apply_expr ## x = a (with a = 0x0) assignblk = AssignBlock({id_x:id_a}) sb.eval_updt_assignblk(assignblk) self.assertEqual(sb.eval_expr(id_x), ExprInt(0, 32)) ## x = a (without replacing 'a' with 0x0) sb.apply_change(id_x, id_a) self.assertEqual(sb.eval_expr(id_x), id_a) ## x = a (with a = 0x0) self.assertEqual(sb.eval_updt_expr(assignblk.dst2ExprAff(id_x)), ExprInt(0, 32)) self.assertEqual(sb.eval_expr(id_x), ExprInt(0, 32)) self.assertEqual(sb.eval_updt_expr(id_x), ExprInt(0, 32)) sb.dump() ## state reads = set() for dst, src in sb.modified(): reads.update(ExprAff(dst, src).get_r()) self.assertEqual(reads, set([ id_x, id_a, ExprMem(id_d + ExprInt(0x4, 32), 32), ExprMem(id_d + ExprInt(0x8, 32), 32), ])) # Erase low id_x byte with 0xFF sb.apply_change(ExprMem(ExprInt(0x20, 32), 8), ExprInt(0xFF, 8)) state = dict(sb.modified(ids=False)) self.assertEqual(state[ExprMem(ExprInt(0x20, 32), 8)], ExprInt(0xFF, 8)) self.assertEqual(state[ExprMem(ExprInt(0x21, 32), 24)], id_x[8:32]) # Erase high id_x byte with 0xEE sb.apply_change(ExprMem(ExprInt(0x23, 32), 8), ExprInt(0xEE, 8)) state = dict(sb.modified(ids=False)) self.assertEqual(state[ExprMem(ExprInt(0x20, 32), 8)], ExprInt(0xFF, 8)) self.assertEqual(state[ExprMem(ExprInt(0x21, 32), 16)], id_x[8:24]) self.assertEqual(state[ExprMem(ExprInt(0x23, 32), 8)], ExprInt(0xEE, 8)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x22, 32), 32)), ExprCompose(id_x[16:24], ExprInt(0xEE, 8), ExprMem(ExprInt(0x24, 32), 16))) # Erase low byte of 0x11223344 with 0xFF at 0x54 sb.apply_change(ExprMem(ExprInt(0x54, 32), 8), ExprInt(0xFF, 8)) # Erase low byte of 0x11223344 with 0xFF at id_a sb.apply_change(ExprMem(id_a + ExprInt(0x1, 32), 8), ExprInt(0xFF, 8)) state = dict(sb.modified(ids=False)) self.assertEqual(state[ExprMem(id_a + ExprInt(0x1, 32), 8)], ExprInt(0xFF, 8)) self.assertEqual(state[ExprMem(id_a + ExprInt(0x2, 32), 16)], ExprInt(0x1122, 16)) # Write uint32_t at 0xFFFFFFFE sb.apply_change(ExprMem(ExprInt(0xFFFFFFFE, 32), 32), ExprInt(0x11223344, 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0, 32), 16)), ExprInt(0x1122, 16)) # Revert memory to original value at 0x42 sb.apply_change(ExprMem(ExprInt(0x42, 32), 32), ExprMem(ExprInt(0x42, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0x42, 32), 32)), ExprMem(ExprInt(0x42, 32), 32)) # Revert memory to original value at c + 0x2 sb.apply_change(ExprMem(id_c + ExprInt(0x2, 32), 32), ExprMem(id_c + ExprInt(0x2, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(id_c + ExprInt(0x2, 32), 32)), ExprMem(id_c + ExprInt(0x2, 32), 32)) # Test del symbol del sb.symbols[id_a] sb.dump() del sb.symbols[ExprMem(id_a, 8)] print "*"*40, 'Orig:' sb.dump() sb_cp = sb.symbols.copy() print "*"*40, 'Copy:' sb_cp.dump() # Add symbol at address limit sb.apply_change(ExprMem(ExprInt(0xFFFFFFFE, 32), 32), id_c) sb.dump() found = False for dst, src in sb.symbols.iteritems(): if dst == ExprMem(ExprInt(0xFFFFFFFE, 32), 32) and src == id_c: found = True assert found # Add symbol at address limit sb.apply_change(ExprMem(ExprInt(0x7FFFFFFE, 32), 32), id_c) sb.dump() found = False for dst, src in sb.symbols.iteritems(): if dst == ExprMem(ExprInt(0x7FFFFFFE, 32), 32) and src == id_c: found = True assert found # Add truncated symbol at address limit sb.apply_change(ExprMem(ExprInt(0xFFFFFFFC, 32), 64), id_e) # Revert parts of memory sb.apply_change(ExprMem(ExprInt(0xFFFFFFFC, 32), 16), ExprMem(ExprInt(0xFFFFFFFC, 32), 16)) sb.apply_change(ExprMem(ExprInt(0x2, 32), 16), ExprMem(ExprInt(0x2, 32), 16)) sb.dump() found = False for dst, src in sb.symbols.iteritems(): if dst == ExprMem(ExprInt(0xFFFFFFFE, 32), 32) and src == id_e[16:48]: found = True assert found sb_empty = SymbolicExecutionEngine(ir_x86_32(), {}) sb_empty.dump() # Test memory full print 'full' arch_addr8 = ir_x86_32() # Hack to obtain tiny address space arch_addr8.addrsize = 5 sb_addr8 = SymbolicExecutionEngine(arch_addr8, {}) sb_addr8.dump() # Fulfill memory sb_addr8.apply_change(ExprMem(ExprInt(0, 5), 256), ExprInt(0, 256)) sb_addr8.dump() variables = sb_addr8.symbols.items() assert variables == [(ExprMem(ExprInt(0, 5), 256), ExprInt(0, 256))] print sb_addr8.symbols.symbols_mem sb_addr8.apply_change(ExprMem(ExprInt(0x5, 5), 256), ExprInt(0x123, 256)) sb_addr8.dump() variables = sb_addr8.symbols.items() assert variables == [(ExprMem(ExprInt(0x5, 5), 256), ExprInt(0x123, 256))] print sb_addr8.symbols.symbols_mem print 'dump' sb_addr8.symbols.symbols_mem.dump() sb.dump() try: del sb.symbols.symbols_mem[ExprMem(ExprInt(0xFFFFFFFF, 32), 32)] except KeyError: # ok pass else: raise RuntimeError("Should raise error!") del sb.symbols.symbols_mem[ExprMem(ExprInt(0xFFFFFFFF, 32), 16)] sb.dump() self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0xFFFFFFFE, 32), 32)), ExprCompose(id_e[16:24], ExprMem(ExprInt(0xFFFFFFFF, 32), 16), id_e[40:48])) sb.symbols.symbols_mem.delete_partial(ExprMem(ExprInt(0xFFFFFFFF, 32), 32)) self.assertEqual(sb.eval_expr(ExprMem(ExprInt(0xFFFFFFFE, 32), 32)), ExprCompose(id_e[16:24], ExprMem(ExprInt(0xFFFFFFFF, 32), 24))) sb.dump() assert ExprMem(ExprInt(0xFFFFFFFE, 32), 8) in sb.symbols assert ExprMem(ExprInt(0xFFFFFFFE, 32), 32) not in sb.symbols assert sb.symbols.symbols_mem.contains_partial(ExprMem(ExprInt(0xFFFFFFFE, 32), 32)) assert not sb.symbols.symbols_mem.contains_partial(ExprMem(ExprInt(0xFFFFFFFF, 32), 8)) assert sb_addr8.symbols.keys() == [ExprMem(ExprInt(0x5, 5), 256)]