def _ail_handle_Sar(self, expr: ailment.Expr.BinaryOp) -> MultiValues: expr0: MultiValues = self._expr(expr.operands[0]) expr1: MultiValues = self._expr(expr.operands[1]) bits = expr.bits r = None expr0_v = expr0.one_value() expr1_v = expr1.one_value() if expr0_v is None and expr1_v is None: r = MultiValues(offset_to_values={0: {self.state.top(bits)}}) elif expr0_v is None and expr1_v is not None: # each value in expr0 >> expr1_v if len(expr0.values) == 1 and 0 in expr0.values: vs = {(claripy.LShR(v, expr1_v._model_concrete.value) if v.concrete else self.state.top(bits)) for v in expr0.values[0]} r = MultiValues(offset_to_values={0: vs}) elif expr0_v is not None and expr1_v is None: # expr0_v >> each value in expr1 if len(expr1.values) == 1 and 0 in expr1.values: vs = {(claripy.LShR(expr0_v, v._model_concrete.value) if v.concrete else self.state.top(bits)) for v in expr1.values[0]} r = MultiValues(offset_to_values={0: vs}) else: if expr1_v.concrete: r = MultiValues(offset_to_values={ 0: {expr0_v >> expr1_v._model_concrete.value} }) if r is None: r = MultiValues(offset_to_values={0: {self.state.top(bits)}}) return r
def _shift_shr(e0, e1): if e1.symbolic: return self.state.top(bits) if e1.size() < e0.size(): e1 = e1.sign_extend(e0.size()-e1.size()) else: e0 = e0.sign_extend(e1.size()-e0.size()) return claripy.LShR(e0, e1)
def test_rotate_shift_mask_simplification(): a = claripy.BVS('N', 32, max=0xc, min=0x1) extend_ = claripy.BVS('extend', 32, uninitialized=True) a_ext = extend_.concat(a) expr = ((a_ext << 3) | (claripy.LShR(a_ext, 61))) & 0x7fffffff8 # print(expr) # print(expr._model_vsa) model_vsa = expr._model_vsa nose.tools.assert_equal(model_vsa.lower_bound, 8) nose.tools.assert_equal(model_vsa.upper_bound, 0x60) nose.tools.assert_equal(model_vsa.cardinality, 12)
def test_depth_repr(): x = claripy.BVS("x", 32) y = claripy.LShR(x, 10) y = claripy.LShR(y, 10) y = claripy.LShR(y, 10) y = claripy.LShR(y, 10) y = claripy.LShR(y, 10) y = claripy.LShR(y, 10) y = claripy.LShR(y, 10) print(y.shallow_repr(max_depth=5)) nose.tools.assert_equal(y.shallow_repr(max_depth=5), "<BV32 LShR(LShR(LShR(LShR(LShR(<...>, <...>), 0xa), 0xa), 0xa), 0xa)>")
def genRandLong(rand: MTRand): if rand.index < 0 or rand.index >= STATE_VECTOR_LENGTH: if rand.index < 0 or rand.index >= STATE_VECTOR_LENGTH + 1: m_seedRand(rand, 0x1105) kk = 0 while kk < STATE_VECTOR_LENGTH - STATE_VECTOR_M: y = rand.mt[kk + 1] & 0xffffffff rand.mt[kk] = rand.mt[kk + STATE_VECTOR_M] ^ claripy.LShR( (y & LOWER_MASK | (rand.mt[kk] & 0xffffffff) & UPPER_MASK), 1) ^ mag(y & 1) kk = kk + 1 while kk < STATE_VECTOR_LENGTH - 1: y = rand.mt[kk + 1] & 0xffffffff rand.mt[kk] = rand.mt[ kk + (STATE_VECTOR_M - STATE_VECTOR_LENGTH)] ^ claripy.LShR( (y & LOWER_MASK | (rand.mt[kk] & 0xffffffff) & UPPER_MASK), 1) ^ mag(y & 1) kk = kk + 1 y = rand.mt[0] & 0xffffffff rand.mt[STATE_VECTOR_LENGTH - 1] = rand.mt[STATE_VECTOR_M - 1] ^ claripy.LShR( y & LOWER_MASK | (rand.mt[STATE_VECTOR_LENGTH - 1] & 0xffffffff) & UPPER_MASK, 1) ^ mag(y & 1) rand.index = 0 iVar1 = rand.index rand.index = iVar1 + 1 uVar2 = rand.mt[iVar1] ^ claripy.LShR(rand.mt[iVar1], 0xb) uVar2 ^= ((uVar2 << 7) & 0xffffffff) & 0x9d2c5680 uVar2 ^= ((uVar2 << 0xf) & 0xffffffff) & 0xefc60000 return uVar2 ^ claripy.LShR(uVar2, 0x12)
def _handle_Shr(self, expr): arg0, arg1 = expr.args r0 = self._expr(arg0) r1 = self._expr(arg1) result_size = expr.result_size(self.tyenv) if r0.data.concrete and r1.data.concrete: # constants return RichR(claripy.LShR(r0.data, r1.data._model_concrete.value), typevar=typeconsts.int_type(result_size), type_constraints=None) r = self.state.top(result_size) return RichR(r, typevar=r0.typevar, )
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]), 'CmpLT': lambda expr, conv: conv(expr.operands[0]) < conv(expr.operands[1]), 'Add': 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]), 'Shr': lambda expr, conv: claripy.LShR(conv(expr.operands[0]), 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 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.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 _handle_Shr(self, expr): args, r = self._binop_get_args(expr) if args is None: return r expr_0, expr_1 = args if self._is_top(expr_0) or self._is_top(expr_1): return self._top(expr_0.size()) if isinstance(expr_1, claripy.ast.Base) and expr_1.op == "BVV": # convert it to an int when possible expr_1 = expr_1.args[0] else: # make sure the sizes are the same - VEX does not care about it if expr_1.size() < expr_0.size(): expr_1 = claripy.ZeroExt(expr_0.size() - expr_1.size(), expr_1) elif expr_1.size() > expr_0.size(): expr_1 = claripy.Extract(expr_0.size() - 1, 0, expr_1) return claripy.LShR(expr_0, expr_1)
def _ail_handle_Shr(self, expr): arg0, arg1 = expr.operands r0 = self._expr(arg0) r1 = self._expr(arg1) result_size = arg0.bits if not r1.data.concrete: # we don't support symbolic shiftamount r = self.state.top(result_size) return RichR(r, typevar=r0.typevar, ) shiftamount = r1.data._model_concrete.value return RichR(claripy.LShR(r0.data, shiftamount), typevar=typeconsts.int_type(result_size), type_constraints=None)
def test_expression(): bc = claripy.backends.concrete e = claripy.BVV(0x01020304, 32) nose.tools.assert_equal(len(e), 32) r = e.reversed nose.tools.assert_equal(bc.convert(r), 0x04030201) nose.tools.assert_equal(len(r), 32) nose.tools.assert_equal([bc.convert(i) for i in r.chop(8)], [4, 3, 2, 1]) e1 = r[31:24] nose.tools.assert_equal(bc.convert(e1), 0x04) nose.tools.assert_equal(len(e1), 8) nose.tools.assert_equal(bc.convert(e1[2]), 1) nose.tools.assert_equal(bc.convert(e1[1]), 0) ee1 = e1.zero_extend(8) nose.tools.assert_equal(bc.convert(ee1), 0x0004) nose.tools.assert_equal(len(ee1), 16) ee1 = claripy.BVV(0xfe, 8).sign_extend(8) nose.tools.assert_equal(bc.convert(ee1), 0xfffe) nose.tools.assert_equal(len(ee1), 16) xe1 = [bc.convert(i) for i in e1.chop(1)] nose.tools.assert_equal(xe1, [0, 0, 0, 0, 0, 1, 0, 0]) a = claripy.BVV(1, 1) nose.tools.assert_equal(bc.convert(a + a), 2) x = claripy.BVV(1, 32) nose.tools.assert_equal(x.length, 32) y = claripy.LShR(x, 10) nose.tools.assert_equal(y.length, 32) r = claripy.BVV(0x01020304, 32) rr = r.reversed rrr = rr.reversed #nose.tools.assert_is(bc.convert(r), bc.convert(rrr)) #nose.tools.assert_is(type(bc.convert(rr)), claripy.A) nose.tools.assert_equal(bc.convert(rr), 0x04030201) nose.tools.assert_is(r.concat(rr), claripy.Concat(r, rr)) rsum = r + rr nose.tools.assert_equal(bc.convert(rsum), 0x05050505) r = claripy.BVS('x', 32) rr = r.reversed rrr = rr.reversed nose.tools.assert_is(r, rrr) # test identity nose.tools.assert_is(r, rrr) nose.tools.assert_is_not(r, rr) ii = claripy.BVS('ii', 32) ij = claripy.BVS('ij', 32) nose.tools.assert_is(ii, ii) nose.tools.assert_is_not(ii, ij) si = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100) sj = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=10) sk = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100) nose.tools.assert_true(claripy.backends.vsa.identical(si, si)) nose.tools.assert_false(claripy.backends.vsa.identical(si, sj)) nose.tools.assert_true(claripy.backends.vsa.identical(si, sk)) nose.tools.assert_is_not(si, sj) nose.tools.assert_is_not(sj, sk) nose.tools.assert_is_not(sk, si) # test hash cache nose.tools.assert_is(a + a, a + a) # test replacement old = claripy.BVS('old', 32, explicit_name=True) new = claripy.BVS('new', 32, explicit_name=True) ooo = claripy.BVV(0, 32) old_formula = claripy.If((old + 1) % 256 == 0, old + 10, old + 20) print(old_formula.dbg_repr()) new_formula = old_formula.replace(old, new) print(new_formula.dbg_repr()) ooo_formula = new_formula.replace(new, ooo) print(ooo_formula.dbg_repr()) nose.tools.assert_not_equal(hash(old_formula), hash(new_formula)) nose.tools.assert_not_equal(hash(old_formula), hash(ooo_formula)) nose.tools.assert_not_equal(hash(new_formula), hash(ooo_formula)) nose.tools.assert_equal(old_formula.variables, {'old'}) nose.tools.assert_equal(new_formula.variables, {'new'}) nose.tools.assert_equal(ooo_formula.variables, ooo.variables) nose.tools.assert_true(old_formula.symbolic) nose.tools.assert_true(new_formula.symbolic) nose.tools.assert_true(new_formula.symbolic) nose.tools.assert_equal( str(old_formula).replace('old', 'new'), str(new_formula)) nose.tools.assert_equal(bc.convert(ooo_formula), 20) # test dict replacement old = claripy.BVS('old', 32, explicit_name=True) new = claripy.BVS('new', 32, explicit_name=True) c = (old + 10) - (old + 20) d = (old + 1) - (old + 2) cr = c.replace_dict({ (old + 10).cache_key: (old + 1), (old + 20).cache_key: (old + 2) }) nose.tools.assert_is(cr, d) # test AST collapse s = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10) b = claripy.BVV(20, 32) sb = s + b nose.tools.assert_is_instance(sb.args[0], claripy.ast.Base) bb = b + b # this was broken previously -- it was checking if type(bb.args[0]) == A, # and it wasn't, but was instead a subclass. leaving this out for now # nose.tools.assert_not_is_instance(bb.args[0], claripy.ast.Base) # ss = s+s # (see above) # nose.tools.assert_not_is_instance(ss.args[0], claripy.ast.Base) sob = s | b # for now, this is collapsed. Presumably, Fish will make it not collapse at some point nose.tools.assert_is_instance(sob.args[0], claripy.ast.Base) # make sure the AST collapses for delayed ops like reversing rb = b.reversed #nose.tools.assert_is_instance(rb.args[0], claripy.ast.Base) # TODO: Properly delay reversing: should not be eager nose.tools.assert_is_not(rb, bb) nose.tools.assert_is(rb, rb) # test some alternate bvv creation methods nose.tools.assert_is(claripy.BVV('AAAA'), claripy.BVV(0x41414141, 32)) nose.tools.assert_is(claripy.BVV('AAAA', 32), claripy.BVV(0x41414141, 32)) nose.tools.assert_is(claripy.BVV('AB'), claripy.BVV(0x4142, 16)) nose.tools.assert_is(claripy.BVV('AB', 16), claripy.BVV(0x4142, 16)) nose.tools.assert_raises(claripy.errors.ClaripyValueError, claripy.BVV, 'AB', 8)
def open_session(cls, state): """ start execution with completely symbolic input -when a breakpoint is reached, check the constraints and set the input accordingly (or add complementary constraint to inputs to find new ways) -when errors occur, check what inputs they depend on; (mostly these inputs have to be memref_inputs) -adjust the input parameters and restart the program """ # 1st Lifecycle: TA_OpenSessionEntryPoint lifecylce_cmd_id = claripy.BVV( LifecycleCommandIds.OPEN_SESSION, 32).append_annotation( UserInput("lifecycle_cmd_id")) # cmd_id for OpenSession param0 = cls.create_empty_param("opensession_0", True) param1 = cls.create_empty_param("opensession_1", True) param2 = cls.create_empty_param("opensession_2", True) param3 = cls.create_empty_param("opensession_3", True) param3_len = claripy.BVS( "param3_len_opensession", 32).append_annotation( UserInput("param3_len_open_session")) # -1 because of nullbyte state.solver.add(claripy.And(param3_len >= 0, param3_len <= MAX_STRLEN)) param3_buf = claripy.BVS("param3_buf_opensession", MAX_STRLEN * 8).append_annotation( UserInput("param3_buf_open_session")) param3_type = claripy.BVV(TEECParamType.TEEC_MEMREF_TEMP_INPUT, 16).append_annotation( UserInput("param3_type_open_session")) param2_len = claripy.BVS( "param2_len_opensession", 32).append_annotation( UserInput("param2_len_open_session")) # -1 because of nullbyte state.solver.add(claripy.And(param2_len >= 0, param2_len <= MAX_STRLEN)) param2_buf = claripy.BVS("param2_buf_opensession", MAX_STRLEN * 8).append_annotation( UserInput("param2_buf_open_session")) param2_type = claripy.BVV(TEECParamType.TEEC_MEMREF_TEMP_INPUT, 16).append_annotation( UserInput("param2_type_open_session")) """param3_buf = claripy.BVV(b"/system/bin/tee_test_store\x00", 27 * 8).append_annotation(UserInput("param3_buf_open_session")) param3_len = claripy.BVV(26, 32).append_annotation( UserInput("param3_len_open_session")) # -1 because of nullbyte""" param3 = TCParam(param3_type, param3_buf, param3_len, True) param2 = TCParam(param2_type, param2_buf, param2_len, True) params = TCParams(param0, param1, param2, param3) invoke_cmd_id = 0 cls.store_symbolic_params(state, params) param_types = claripy.ZeroExt( 16, params.get_param_type() ) # param_types has 16 bit, but needs to be extended to architecture size state.solver.add((claripy.LShR(param_types, 0xc) & 0xf) - 0x5 <= 0x2) state.solver.add( claripy.LShR(param3_buf, MAX_STRLEN * 8 - 26 * 8) != 0x2f73797374656d2f62696e2f7465655f746573745f73746f7265) # TODO: store param_types to symbolics here cls.prepare_msg_recv_return(state, lifecylce_cmd_id, invoke_cmd_id, param_types, params)
def _shift_shr(e0, e1): # convert e1 to an integer to prevent claripy from complaining "args' lengths must all be equal" e1 = e1._model_concrete.value return claripy.LShR(e0, e1)
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