def teq(ir, instr, arg1, arg2): e = [] loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) do_except = [] do_except.append( m2_expr.ExprAssign( exception_flags, m2_expr.ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) blk_except = IRBlock(loc_except.index, [AssignBlock(do_except, instr)]) cond = arg1 - arg2 e = [] e.append( m2_expr.ExprAssign( ir.IRDst, m2_expr.ExprCond(cond, loc_next_expr, loc_except_expr))) return e, [blk_except]
def ins(ir, instr, a, b, c, d): e = [] pos = int(c) l = int(d) my_slices = [] if pos != 0: my_slices.append((a[:pos], 0, pos)) if l != 0: my_slices.append((b[:l], pos, pos + l)) if pos + l != 32: my_slices.append((a[pos + l:], pos + l, 32)) r = m2_expr.ExprCompose(my_slices) e.append(m2_expr.ExprAssign(a, r)) return e, []
def get_ir(self, instr): args = instr.args instr_ir, extra_ir = get_mnemo_expr(self, instr, *args) fixed_regs = { self.pc: m2_expr.ExprInt(instr.offset + 4, 32), ZERO: m2_expr.ExprInt(0, 32) } instr_ir = [ m2_expr.ExprAssign(expr.dst, expr.src.replace_expr(fixed_regs)) for expr in instr_ir ] new_extra_ir = [ irblock.modify_exprs( mod_src=lambda expr: expr.replace_expr(fixed_regs)) for irblock in extra_ir ] return instr_ir, new_extra_ir
def dst2ExprAssign(self, dst): """Return an ExprAssign corresponding to @dst equation @dst: Expr instance""" return m2_expr.ExprAssign(dst, self[dst])
def to_constraint(self): cst1, cst2 = m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1) return m2_expr.ExprAssign(cst1, m2_expr.ExprCond(self.expr, cst1, cst2))
def to_constraint(self): return m2_expr.ExprAssign(self.expr, m2_expr.ExprInt(0, self.expr.size))
def callback(self, jitter): # Check previous state # When it is possible, consider only elements modified in the last run # -> speed up to avoid browsing the whole memory to_consider = self.symb.modified_expr for symbol in to_consider: # Do not consider PC if symbol == self.ira.pc: continue # Read from ... @NN[... argX ...] ... symb_value = self.symb.eval_expr(symbol) to_replace = {} for expr in m2_expr.ExprAssign(symbol, symb_value).get_r(mem_read=True): if self.is_symbolic(expr): if expr.is_mem(): # Consider each byte individually # Case: @32[X] with only @8[X+1] to replace addr_expr = expr.ptr new_expr = [] consider = False for offset in xrange(expr.size / 8): sub_expr = m2_expr.ExprMem( self.symb.expr_simp( addr_expr + m2_expr.ExprInt( offset, size=addr_expr.size)), 8) if not self.is_pointer(sub_expr): # Not a PTR, we have to replace with the real value original_sub_expr = sub_expr.replace_expr( self.init_values) new_expr.append( self.symb.eval_expr(original_sub_expr)) consider = True else: new_expr.append(sub_expr) # Rebuild the corresponding expression if consider: assert len(new_expr) == expr.size / 8 to_replace[expr] = m2_expr.ExprCompose(*new_expr) if expr not in self.memories_write: # Do not consider memory already written during the run self.memories_read.add(expr) # Write to @NN[... argX ...] # Must be after Read, case: @[X] = f(@[X]) if self.is_symbolic(symbol): self.memories_write.add(symbol) # Replace with real value for non-pointer symbols if to_replace: symb_value = self.symb.expr_simp( symb_value.replace_expr(to_replace)) if isinstance(symbol, m2_expr.ExprMem): # Replace only in ptr (case to_replace: @[arg] = 8, expr: # @[arg] = @[arg]) symbol = m2_expr.ExprMem( self.symb.expr_simp( symbol.ptr.replace_expr(to_replace)), symbol.size) self.symb.apply_change(symbol, symb_value) # Check computed values against real ones # TODO idem memory if (isinstance(symbol, m2_expr.ExprId) and isinstance(symb_value, m2_expr.ExprInt)): if hasattr(jitter.cpu, symbol.name): value = m2_expr.ExprInt(getattr(jitter.cpu, symbol.name), symbol.size) assert value == self.symb.symbols[symbol] cur_addr = jitter.pc self.logger.debug("Current address: %s", hex(cur_addr)) if cur_addr == 0x1337BEEF or cur_addr == self.return_addr: # End reached if self.logger.isEnabledFor(logging.DEBUG): print "In:" for x in self.memories_read: print "\t%s (%s)" % ( x, self.c_handler.expr_to_c(x), ) print "Out:" for x in self.memories_write: print "\t%s (%s)" % ( x, self.c_handler.expr_to_c(x), ) return True # Update state self.symb.reset_modified() asm_block = self.mdis.dis_block(cur_addr) ircfg = self.symb_ir.new_ircfg() self.symb_ir.add_asmblock_to_ircfg(asm_block, ircfg) self.symb.run_at(ircfg, cur_addr) return True