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]) if l != 0: my_slices.append(b[:l]) if pos + l != 32: my_slices.append(a[pos + l:]) r = m2_expr.ExprCompose(*my_slices) e.append(m2_expr.ExprAssign(a, r)) return e, []
def compose(cls, size=32, depth=1): """Return an ExprCompose @size: (optional) Operation size @depth: (optional) Expression depth """ # First layer upper_bound = random.randint(1, size) args = [cls._gen(size=upper_bound, depth=depth - 1)] # Next layers while (upper_bound < size): if len(args) == (cls.compose_max_layer - 1): # We reach the maximum size new_upper_bound = size else: new_upper_bound = random.randint(upper_bound + 1, size) args.append(cls._gen(size=new_upper_bound - upper_bound)) upper_bound = new_upper_bound return m2_expr.ExprCompose(*args)
def _set(self, dst, src): """ Special cases: * if dst is an ExprSlice, expand it to assign the full Expression * if dst already known, sources are merged """ if dst.size != src.size: raise RuntimeError("sanitycheck: args must have same size! %s" % ([(str(arg), arg.size) for arg in [dst, src]])) if isinstance(dst, m2_expr.ExprSlice): # Complete the source with missing slice parts new_dst = dst.arg rest = [(m2_expr.ExprSlice(dst.arg, r[0], r[1]), r[0], r[1]) for r in dst.slice_rest()] all_a = [(src, dst.start, dst.stop)] + rest all_a.sort(key=lambda x: x[1]) args = [expr for (expr, _, _) in all_a] new_src = m2_expr.ExprCompose(*args) else: new_dst, new_src = dst, src if new_dst in self._assigns and isinstance(new_src, m2_expr.ExprCompose): if not isinstance(self[new_dst], m2_expr.ExprCompose): # prev_RAX = 0x1122334455667788 # input_RAX[0:8] = 0x89 # final_RAX -> ? (assignment are in parallel) raise RuntimeError("Concurrent access on same bit not allowed") # Consider slice grouping expr_list = [(new_dst, new_src), (new_dst, self[new_dst])] # Find collision e_colision = reduce(lambda x, y: x.union(y), (self.get_modified_slice(dst, src) for (dst, src) in expr_list), set()) # Sort interval collision known_intervals = sorted([(x[1], x[2]) for x in e_colision]) for i, (_, stop) in enumerate(known_intervals[:-1]): if stop > known_intervals[i + 1][0]: raise RuntimeError( "Concurrent access on same bit not allowed") # Fill with missing data missing_i = get_missing_interval(known_intervals, 0, new_dst.size) remaining = ((m2_expr.ExprSlice(new_dst, *interval), interval[0], interval[1]) for interval in missing_i) # Build the merging expression args = list(e_colision.union(remaining)) args.sort(key=lambda x: x[1]) starts = [start for (_, start, _) in args] assert len(set(starts)) == len(starts) args = [expr for (expr, _, _) in args] new_src = m2_expr.ExprCompose(*args) # Sanity check if not isinstance(new_dst, (m2_expr.ExprId, m2_expr.ExprMem)): raise TypeError("Destination cannot be a %s" % type(new_dst)) self._assigns[new_dst] = new_src
def possible_values(expr): """Return possible values for expression @expr, associated with their condition constraint as a ConstrainedValues instance @expr: Expr instance """ consvals = ConstrainedValues() # Terminal expression if (isinstance(expr, m2_expr.ExprInt) or isinstance(expr, m2_expr.ExprId) or isinstance(expr, m2_expr.ExprLoc)): consvals.add(ConstrainedValue(frozenset(), expr)) # Unary expression elif isinstance(expr, m2_expr.ExprSlice): consvals.update( ConstrainedValue(consval.constraints, consval.value[expr.start:expr.stop]) for consval in possible_values(expr.arg)) elif isinstance(expr, m2_expr.ExprMem): consvals.update( ConstrainedValue(consval.constraints, m2_expr.ExprMem(consval.value, expr.size)) for consval in possible_values(expr.ptr)) elif isinstance(expr, m2_expr.ExprAssign): consvals.update(possible_values(expr.src)) # Special case: constraint insertion elif isinstance(expr, m2_expr.ExprCond): src1cond = CondConstraintNotZero(expr.cond) src2cond = CondConstraintZero(expr.cond) consvals.update( ConstrainedValue(consval.constraints.union([src1cond]), consval.value) for consval in possible_values(expr.src1)) consvals.update( ConstrainedValue(consval.constraints.union([src2cond]), consval.value) for consval in possible_values(expr.src2)) # N-ary expression elif isinstance(expr, m2_expr.ExprOp): # For details, see ExprCompose consvals_args = [possible_values(arg) for arg in expr.args] for consvals_possibility in itertools.product(*consvals_args): args_value = [consval.value for consval in consvals_possibility] args_constraint = itertools.chain( *[consval.constraints for consval in consvals_possibility]) consvals.add( ConstrainedValue(frozenset(args_constraint), m2_expr.ExprOp(expr.op, *args_value))) elif isinstance(expr, m2_expr.ExprCompose): # Generate each possibility for sub-argument, associated with the start # and stop bit consvals_args = [list(possible_values(arg)) for arg in expr.args] for consvals_possibility in itertools.product(*consvals_args): # Merge constraint of each sub-element args_constraint = itertools.chain( *[consval.constraints for consval in consvals_possibility]) # Gen the corresponding constraints / ExprCompose args = [consval.value for consval in consvals_possibility] consvals.add( ConstrainedValue(frozenset(args_constraint), m2_expr.ExprCompose(*args))) else: raise RuntimeError("Unsupported type for expr: %s" % type(expr)) return consvals
def test_Variables_Identifier(self): import miasm.expression.expression as m2_expr from miasm.expression.expression_helper import Variables_Identifier # Build a complex expression cst = m2_expr.ExprInt(0x100, 16) eax = m2_expr.ExprId("EAX", 32) ebx = m2_expr.ExprId("EBX", 32) ax = eax[0:16] expr = eax + ebx expr = m2_expr.ExprCompose(ax, expr[16:32]) expr2 = m2_expr.ExprMem((eax + ebx) ^ (eax), size=16) expr2 = expr2 | ax | expr2 | cst exprf = expr - expr + m2_expr.ExprCompose(expr2, cst) # Identify variables vi = Variables_Identifier(exprf) # Use __str__ print(vi) # Test the result new_expr = vi.equation ## Force replace in the variable dependency order for var_id, var_value in reversed(list(viewitems(vi.vars))): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(exprf, new_expr) # Test prefix vi = Variables_Identifier(exprf, var_prefix="prefix_v") ## Use __str__ print(vi) ## Test the result new_expr = vi.equation ### Force replace in the variable dependency order for var_id, var_value in reversed(list(viewitems(vi.vars))): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(exprf, new_expr) # Test an identify on an expression already containing identifier vi = Variables_Identifier(exprf) vi2 = Variables_Identifier(vi.equation) ## Test the result new_expr = vi2.equation ### Force replace in the variable dependency order for var_id, var_value in reversed(list(viewitems(vi2.vars))): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(vi.equation, new_expr) ## Corner case: each sub var depends on itself mem1 = m2_expr.ExprMem(ebx, size=32) mem2 = m2_expr.ExprMem(mem1, size=32) cst2 = m2_expr.ExprInt(-1, 32) expr_mini = ((eax ^ mem2 ^ cst2) & (mem2 ^ (eax + mem2)))[31:32] ## Build vi = Variables_Identifier(expr_mini) vi2 = Variables_Identifier(vi.equation) ## Test the result new_expr = vi2.equation ### Force replace in the variable dependency order for var_id, var_value in reversed(list(viewitems(vi2.vars))): new_expr = new_expr.replace_expr({var_id: var_value}) self.assertEqual(vi.equation, new_expr)
def wsbh(arg1, arg2): arg1 = m2_expr.ExprCompose(arg2[8:16], arg2[0:8], arg2[24:32], arg2[16:24])
def lui(arg1, arg2): """The immediate value @arg2 is shifted left 16 bits and stored in the register @arg1. The lower 16 bits are zeroes.""" arg1 = m2_expr.ExprCompose(i16(0), arg2[:16])