def test_replacement_solver(): sr = claripy.SolverReplacement() x = claripy.BVS('x', 32) nose.tools.assert_equal(len(sr.eval(x, 10)), 10) sr.add_replacement(x, claripy.BVV(0x101, 32)) nose.tools.assert_equal(sr.eval(x, 10), (0x101, )) y = claripy.BVS('y', 32) sr.add([y + 1 == 200]) assert (y + 1).cache_key in sr._replacements assert sr._replacement(y + 1) is claripy.BVV(200, 32) srb = sr.branch() assert len(srb.constraints) == len(sr.constraints) #pylint:disable=no-member assert (y + 1).cache_key in sr._replacements assert sr._replacement(y + 1) is claripy.BVV(200, 32) sr = claripy.SolverReplacement() b = claripy.BoolS('b') assert sr._replacement(b) is b sr.add(claripy.Not(b)) assert sr._replacement(b) is claripy.false sr = claripy.SolverReplacement(claripy.SolverVSA(), complex_auto_replace=True) x = claripy.BVS('x', 64) sr.add([x + 8 <= 0xffffffffffffffff]) sr.add([x + 8 >= 0]) assert sr._replacement(x) is not x
def test_replacement_solver(): sr = claripy.ReplacementFrontend(claripy.FullFrontend(claripy.backends.z3)) x = claripy.BVS('x', 32) nose.tools.assert_equals(len(sr.eval(x, 10)), 10) sr.result = None sr.add_replacement(x, claripy.BVV(0x101, 32)) nose.tools.assert_items_equal(sr.eval(x, 10), [0x101]) y = claripy.BVS('y', 32) sr.add([y+1 == 200]) assert (y+1).cache_key in sr._replacements assert sr._replacement(y+1) is claripy.BVV(200, 32) srb = sr.branch() assert len(srb.constraints) == len(sr.constraints) assert (y+1).cache_key in sr._replacements assert sr._replacement(y+1) is claripy.BVV(200, 32) sr = claripy.ReplacementFrontend(claripy.FullFrontend(claripy.backends.z3)) b = claripy.BoolS('b') assert sr._replacement(b) is b sr.add(claripy.Not(b)) assert sr._replacement(b) is claripy.false sr = claripy.ReplacementFrontend(claripy.LightFrontend(claripy.backends.vsa), complex_auto_replace=True) x = claripy.BVS('x', 64) sr.add([x + 8 <= 0xffffffffffffffff]) sr.add([x + 8 >= 0]) assert sr._replacement(x) is not x
def test_canonical(): x1 = claripy.BVS('x', 32) b1 = claripy.BoolS('b') c1 = claripy.BoolS('c') x2 = claripy.BVS('x', 32) b2 = claripy.BoolS('b') c2 = claripy.BoolS('c') y1 = claripy.If(claripy.And(b1, c1), x1, ((x1+x1)*x1)+1) y2 = claripy.If(claripy.And(b2, c2), x2, ((x2+x2)*x2)+1) one_names = frozenset.union(x1.variables, b1.variables, c1.variables) two_names = frozenset.union(x2.variables, b2.variables, c2.variables) assert frozenset.union(*[a.variables for a in y1.recursive_leaf_asts]) == one_names assert frozenset.union(*[a.variables for a in y2.recursive_leaf_asts]) == two_names assert y1.canonicalize()[-1] is y2.canonicalize()[-1]
def perf_boolean_and_simplification_1(): # Create a gigantic And AST with many operands, many variables at a time bool_vars = [claripy.BoolS("b%d" % i) for i in range(500)] v = bool_vars[0] for i in range(1, len(bool_vars)): if v.op == "And": v = claripy.And(*(v.args + (bool_vars[i] == False, ))) # pylint:disable=singleton-comparison else: v = claripy.And(v, bool_vars[i])
def run(self, this_ref, key_ref): log.debug('Called SimProcedure java.util.Map.containsKey with args: {} {}'.format(this_ref, key_ref)) if this_ref.symbolic: return claripy.BoolS('contains_key') try: this_ref.load_field(self.state, get_map_key(self.state, key_ref), 'java.lang.Object') return claripy.BoolV(1) except (KeyError, AttributeError): return claripy.BoolV(0)
def _bool_variable_from_ail_condition(self, condition): # Unpack a condition all the way to the leaves _mapping = { 'LogicalAnd': lambda expr, conv: claripy.And(conv(expr.operands[0]), conv(expr.operands[1])), 'LogicalOr': lambda expr, conv: claripy.Or(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpEQ': lambda expr, conv: conv(expr.operands[0]) == conv(expr.operands[1] ), 'CmpLE': lambda expr, conv: conv(expr.operands[0]) <= conv(expr.operands[1] ), 'Not': lambda expr, conv: claripy.Not(conv(expr.operand)), 'Xor': lambda expr, conv: conv(expr.operands[0]) ^ conv(expr.operands[1]), } if isinstance(condition, (ailment.Expr.Load, ailment.Expr.Register, ailment.Expr.DirtyExpression)): var = claripy.BVS('ailexpr_%s' % repr(condition), condition.bits, explicit_name=True) self._condition_mapping[var] = condition return var elif isinstance(condition, ailment.Expr.Convert): # convert is special. if it generates a 1-bit variable, it should be treated as a BVS if condition.to_bits == 1: var = claripy.BoolS('ailcond_%s' % repr(condition), explicit_name=True) else: var = claripy.BVS('ailexpr_%s' % repr(condition), condition.to_bits, explicit_name=True) self._condition_mapping[var] = condition return var elif isinstance(condition, ailment.Expr.Const): var = claripy.BVV(condition.value, condition.bits) return var lambda_expr = _mapping.get(condition.op, None) if lambda_expr is None: raise NotImplementedError( "Unsupported AIL expression operation %s. Consider implementing." % condition.op) return lambda_expr(condition, self._bool_variable_from_ail_condition)
def run(self, this_ref): log.debug( 'Called SimProcedure java.util.Iterator.hasNext with args: {}'. format(this_ref)) if this_ref.symbolic: return claripy.BoolS('iterator.hasNext') iterator_size = this_ref.load_field(self.state, SIZE, 'int') iterator_index = this_ref.load_field(self.state, INDEX, 'int') has_next = self.state.solver.eval( iterator_index) < self.state.solver.eval(iterator_size) return claripy.BoolV(has_next)
def test_bool_simplification(): def assert_correct(a, b): nose.tools.assert_true( claripy.backends.z3.identical(claripy.simplify(a), b)) a, b, c = (claripy.BoolS(name) for name in ('a', 'b', 'c')) assert_correct(claripy.And(a, claripy.Not(a)), claripy.false) assert_correct(claripy.Or(a, claripy.Not(a)), claripy.true) complex_true_expression = claripy.Or( claripy.And(a, b), claripy.Or(claripy.And(a, claripy.Not(b)), claripy.And(claripy.Not(a), c)), claripy.Or(claripy.And(a, claripy.Not(b)), claripy.And(claripy.Not(a), claripy.Not(c)))) assert_correct(complex_true_expression, claripy.true)
def run(self, this_ref, obj_ref): log.debug( 'Called SimProcedure java.util.List.add with args: {} {}'.format( this_ref, obj_ref)) if this_ref.symbolic: return claripy.BoolS('list.append') try: array_ref = this_ref.load_field(self.state, ELEMS, 'java.lang.Object[]') array_len = this_ref.load_field(self.state, SIZE, 'int') self.state.javavm_memory.store_array_element( array_ref, array_len, obj_ref) # Update size new_array_len = claripy.BVV( self.state.solver.eval(array_len) + 1, 32) this_ref.store_field(self.state, SIZE, 'int', new_array_len) except KeyError: log.warning('Could not add element to list {}'.format(this_ref)) return claripy.BoolV(1)
def claripy_ast_from_ail_condition(self, condition) -> claripy.ast.Base: # Unpack a condition all the way to the leaves if isinstance(condition, claripy.ast.Base): # pylint:disable=isinstance-second-argument-not-valid-type return condition def _op_with_unified_size(op, conv, operand0, operand1): # ensure operand1 is of the same size as operand0 if isinstance(operand1, ailment.Expr.Const): # amazing - we do the eazy thing here return op(conv(operand0), operand1.value) if operand1.bits == operand0.bits: return op(conv(operand0), conv(operand1)) # extension is required assert operand1.bits < operand0.bits operand1 = ailment.Expr.Convert(None, operand1.bits, operand0.bits, False, operand1) return op(conv(operand0), conv(operand1)) _mapping = { 'LogicalAnd': lambda expr, conv: claripy.And(conv(expr.operands[0]), conv(expr.operands[1])), 'LogicalOr': lambda expr, conv: claripy.Or(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpEQ': lambda expr, conv: conv(expr.operands[0]) == conv(expr.operands[1]), 'CmpNE': lambda expr, conv: conv(expr.operands[0]) != conv(expr.operands[1]), 'CmpLE': lambda expr, conv: conv(expr.operands[0]) <= conv(expr.operands[1]), 'CmpLEs': lambda expr, conv: claripy.SLE(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpLT': lambda expr, conv: conv(expr.operands[0]) < conv(expr.operands[1]), 'CmpLTs': lambda expr, conv: claripy.SLT(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpGE': lambda expr, conv: conv(expr.operands[0]) >= conv(expr.operands[1]), 'CmpGEs': lambda expr, conv: claripy.SGE(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpGT': lambda expr, conv: conv(expr.operands[0]) > conv(expr.operands[1]), 'CmpGTs': lambda expr, conv: claripy.SGT(conv(expr.operands[0]), conv(expr.operands[1])), 'Add': lambda expr, conv: conv(expr.operands[0]) + conv(expr.operands[1]), 'Sub': lambda expr, conv: conv(expr.operands[0]) - conv(expr.operands[1]), 'Mul': lambda expr, conv: conv(expr.operands[0]) * conv(expr.operands[1]), 'Not': lambda expr, conv: claripy.Not(conv(expr.operand)), 'Xor': lambda expr, conv: conv(expr.operands[0]) ^ conv(expr.operands[1]), 'And': lambda expr, conv: conv(expr.operands[0]) & conv(expr.operands[1]), 'Or': lambda expr, conv: conv(expr.operands[0]) | conv(expr.operands[1]), 'Shr': lambda expr, conv: _op_with_unified_size(claripy.LShR, conv, expr.operands[0], expr.operands[1]), 'Shl': lambda expr, conv: _op_with_unified_size(operator.lshift, conv, expr.operands[0], expr.operands[1]), 'Sar': lambda expr, conv: _op_with_unified_size(operator.rshift, conv, expr.operands[0], expr.operands[1]), } if isinstance(condition, (ailment.Expr.Load, ailment.Expr.DirtyExpression, ailment.Expr.BasePointerOffset, ailment.Expr.ITE, ailment.Stmt.Call)): var = claripy.BVS('ailexpr_%s' % repr(condition), condition.bits, explicit_name=True) self._condition_mapping[var.args[0]] = condition return var elif isinstance(condition, ailment.Expr.Register): var = claripy.BVS('ailexpr_%s-%d' % (repr(condition), condition.idx), condition.bits, explicit_name=True) self._condition_mapping[var.args[0]] = condition return var elif isinstance(condition, ailment.Expr.Convert): # convert is special. if it generates a 1-bit variable, it should be treated as a BVS if condition.to_bits == 1: var_ = self.claripy_ast_from_ail_condition(condition.operands[0]) name = 'ailcond_Conv(%d->%d, %s)' % (condition.from_bits, condition.to_bits, repr(var_)) var = claripy.BoolS(name, explicit_name=True) else: var_ = self.claripy_ast_from_ail_condition(condition.operands[0]) name = 'ailexpr_Conv(%d->%d, %s)' % (condition.from_bits, condition.to_bits, repr(var_)) var = claripy.BVS(name, condition.to_bits, explicit_name=True) self._condition_mapping[var.args[0]] = condition return var elif isinstance(condition, ailment.Expr.Const): var = claripy.BVV(condition.value, condition.bits) return var elif isinstance(condition, ailment.Expr.Tmp): l.warning("Left-over ailment.Tmp variable %s.", condition) if condition.bits == 1: var = claripy.BoolV('ailtmp_%d' % condition.tmp_idx) else: var = claripy.BVS('ailtmp_%d' % condition.tmp_idx, condition.bits, explicit_name=True) self._condition_mapping[var.args[0]] = condition return var lambda_expr = _mapping.get(condition.verbose_op, None) if lambda_expr is None: raise NotImplementedError("Unsupported AIL expression operation %s. Consider implementing." % condition.op) r = lambda_expr(condition, self.claripy_ast_from_ail_condition) if r is NotImplemented: r = claripy.BVS("ailexpr_%r" % condition, condition.bits, explicit_name=True) self._condition_mapping[r.args[0]] = condition else: # don't lose tags r = r.annotate(TagsAnnotation(**condition.tags)) return r
def perf_boolean_and_simplification_0(): # Create a gigantic And AST with many operands, one variable at a time bool_vars = [claripy.BoolS("b%d" % i) for i in range(1500)] v = bool_vars[0] for i in range(1, len(bool_vars)): v = claripy.And(v, bool_vars[i])
def claripy_ast_from_ail_condition(self, condition): # Unpack a condition all the way to the leaves if isinstance(condition, claripy.ast.Base): return condition _mapping = { 'LogicalAnd': lambda expr, conv: claripy.And(conv(expr.operands[0]), conv(expr.operands[1])), 'LogicalOr': lambda expr, conv: claripy.Or(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpEQ': lambda expr, conv: conv(expr.operands[0]) == conv(expr.operands[1] ), 'CmpNE': lambda expr, conv: conv(expr.operands[0]) != conv(expr.operands[1] ), 'CmpLE': lambda expr, conv: conv(expr.operands[0]) <= conv(expr.operands[1] ), 'CmpLEs': lambda expr, conv: claripy.SLE(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpLT': lambda expr, conv: conv(expr.operands[0]) < conv(expr.operands[1]), 'CmpLTs': lambda expr, conv: claripy.SLT(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpGE': lambda expr, conv: conv(expr.operands[0]) >= conv(expr.operands[1] ), 'CmpGEs': lambda expr, conv: claripy.SGE(conv(expr.operands[0]), conv(expr.operands[1])), 'CmpGT': lambda expr, conv: conv(expr.operands[0]) > conv(expr.operands[1]), 'CmpGTs': lambda expr, conv: claripy.SGT(conv(expr.operands[0]), conv(expr.operands[1])), 'Add': lambda expr, conv: conv(expr.operands[0]) + conv(expr.operands[1]), 'Sub': lambda expr, conv: conv(expr.operands[0]) - conv(expr.operands[1]), 'Not': lambda expr, conv: claripy.Not(conv(expr.operand)), 'Xor': lambda expr, conv: conv(expr.operands[0]) ^ conv(expr.operands[1]), 'And': lambda expr, conv: conv(expr.operands[0]) & conv(expr.operands[1]), 'Or': lambda expr, conv: conv(expr.operands[0]) | conv(expr.operands[1]), 'Shr': lambda expr, conv: claripy.LShR(conv(expr.operands[0]), expr. operands[1].value) } if isinstance(condition, (ailment.Expr.Load, ailment.Expr.DirtyExpression, ailment.Expr.BasePointerOffset)): var = claripy.BVS('ailexpr_%s' % repr(condition), condition.bits, explicit_name=True) self._condition_mapping[var] = condition return var elif isinstance(condition, ailment.Expr.Register): var = claripy.BVS('ailexpr_%s-%d' % (repr(condition), condition.idx), condition.bits, explicit_name=True) self._condition_mapping[var] = condition return var elif isinstance(condition, ailment.Expr.Convert): # convert is special. if it generates a 1-bit variable, it should be treated as a BVS if condition.to_bits == 1: var_ = self.claripy_ast_from_ail_condition( condition.operands[0]) name = 'ailcond_Conv(%d->%d, %s)' % ( condition.from_bits, condition.to_bits, repr(var_)) var = claripy.BoolS(name, explicit_name=True) else: var_ = self.claripy_ast_from_ail_condition( condition.operands[0]) name = 'ailexpr_Conv(%d->%d, %s)' % ( condition.from_bits, condition.to_bits, repr(var_)) var = claripy.BVS(name, condition.to_bits, explicit_name=True) self._condition_mapping[var] = condition return var elif isinstance(condition, ailment.Expr.Const): var = claripy.BVV(condition.value, condition.bits) return var elif isinstance(condition, ailment.Expr.Tmp): l.warning("Left-over ailment.Tmp variable %s.", condition) if condition.bits == 1: var = claripy.BoolV('ailtmp_%d' % condition.tmp_idx) else: var = claripy.BVS('ailtmp_%d' % condition.tmp_idx, condition.bits) self._condition_mapping[var] = condition return var lambda_expr = _mapping.get(condition.verbose_op, None) if lambda_expr is None: raise NotImplementedError( "Unsupported AIL expression operation %s. Consider implementing." % condition.op) r = lambda_expr(condition, self.claripy_ast_from_ail_condition) if r is NotImplemented: r = claripy.BVS("ailexpr_%r" % condition, condition.bits, explicit_name=True) self._condition_mapping[r] = condition return r
def _bool_variable_from_ail_condition(self, block, condition): var = claripy.BoolS('structurer-cond_%#x_%s' % (block.addr, repr(condition)), explicit_name=True) self._condition_mapping[var] = condition return var
def _bool_variable_from_ail_condition(block, condition): return claripy.BoolS('structurer-cond_%#x_%s' % (block.addr, repr(condition)), explicit_name=True)
def eof(self): return claripy.BoolS("duplex_eof")