def symbol(ty, name): if ty == 'Ity_F32': return claripy.FPS(name, claripy.FSORT_FLOAT) elif ty == 'Ity_F64': return claripy.FPS(name, claripy.FSORT_DOUBLE) else: return claripy.BVS(name, pyvex.get_type_size(ty))
def run(self, thing, *args): # mMark object as symbolic if isinstance(thing, SimSootValue_ThisRef): this_ref = thing if args: method_descriptor = args[-1] else: # if args is empty, method is static and has no params method_descriptor = thing # return the appropriate value based on the return type of the method if method_descriptor is None or method_descriptor.ret is None or method_descriptor.ret == 'void': return elif method_descriptor.ret in ['byte', 'char', 'short', 'int', 'boolean']: return claripy.BVS('unc_{}_{}'.format(method_descriptor.ret, method_descriptor.name), 32) elif method_descriptor.ret == 'long': return claripy.BVS('unc_long_{}'.format(method_descriptor.name), 64) elif method_descriptor.ret == 'float': return claripy.FPS('unc_float_{}'.format(method_descriptor.name), claripy.FSORT_FLOAT) elif method_descriptor.ret == 'double': return claripy.FPS('unc_double_{}'.format(method_descriptor.name), claripy.FSORT_DOUBLE) elif method_descriptor.ret == 'java.lang.String': str_ref = SimSootValue_StringRef.new_string( self.state, claripy.StringS("unc_string_{}".format(method_descriptor.name), 1000)) return str_ref elif method_descriptor.ret.endswith('[][]'): raise NotImplementedError elif method_descriptor.ret.endswith('[]'): # TODO here array size should be symbolic return SimSootExpr_NewArray.new_array(self.state, method_descriptor.ret[:-2], claripy.BVV(2, 32)) else: obj_ref = SimSootValue_ThisRef.new_object( self.state, method_descriptor.ret, symbolic=True, init_object=False) return obj_ref
def run_manyfloatsum_symbolic(arch): global type_cache if type_cache is None: type_cache = parse_defns( open(os.path.join(location, 'tests_src', 'manyfloatsum.c')).read()) p = angr.Project(os.path.join(location, 'tests', arch, 'manyfloatsum')) function = 'sum_doubles' cc = p.factory.cc(func_ty=type_cache[function]) args = [ claripy.FPS('arg_%d' % i, claripy.FSORT_DOUBLE) for i in range(len(type_cache[function].args)) ] addr = p.loader.main_object.get_symbol(function).rebased_addr my_callable = p.factory.callable(addr, cc=cc) result = my_callable(*args) nose.tools.assert_true(result.symbolic) s = claripy.Solver() for arg in args: s.add(arg > claripy.FPV(1.0, claripy.FSORT_DOUBLE)) s.add(result == claripy.FPV(27.7, claripy.FSORT_DOUBLE)) args_conc = s.batch_eval(args, 1)[0] nose.tools.assert_equal(s.eval(result, 1)[0], 27.7) # not almost equal!! totally equal!!! z3 is magic, if kinda slow!!!!! for arg_conc in args_conc: nose.tools.assert_greater(arg_conc, 1.0) nose.tools.assert_equal(sum(args_conc), 27.7)
def run_manyfloatsum_symbolic(self, arch): global type_cache if type_cache is None: with open(os.path.join(location, 'tests_src', 'manyfloatsum.c')) as fp: type_cache = parse_defns(fp.read()) p = angr.Project(os.path.join(location, 'tests', arch, 'manyfloatsum')) function = 'sum_doubles' args = [ claripy.FPS('arg_%d' % i, claripy.FSORT_DOUBLE) for i in range(len(type_cache[function].args)) ] addr = p.loader.main_object.get_symbol(function).rebased_addr my_callable = p.factory.callable(addr, prototype=type_cache[function]) result = my_callable(*args) assert result.symbolic s = claripy.Solver(timeout=15 * 60 * 1000) for arg in args: s.add(arg > claripy.FPV(1.0, claripy.FSORT_DOUBLE)) s.add(result == claripy.FPV(27.7, claripy.FSORT_DOUBLE)) args_conc = s.batch_eval(args, 1)[0] assert s.eval(result, 1)[0] == 27.7 # not almost equal!! totally equal!!! z3 is magic, if kinda slow!!!!! for arg_conc in args_conc: assert arg_conc > 1.0 assert sum(args_conc) == 27.7
def test_nan(): a = claripy.FPS('a', claripy.FSORT_FLOAT) b = claripy.BVS('b', 32) s1 = claripy.Solver() s1.add((a + 1).isNaN()) res = s1.eval(a, 1)[0] assert math.isnan(res) s2 = claripy.Solver() s2.add(b.raw_to_fp().isNaN()) res = s2.eval(b, 1)[0] assert res & 0xff800000 == 0x7f800000 and res & 0x007fffff != 0 s3 = claripy.Solver() s3.add(a.isNaN()) res = s3.eval(a.raw_to_bv(), 1)[0] assert res & 0xff800000 == 0x7f800000 and res & 0x007fffff != 0
def handle_expression(self, expr, tyenv, path): size = expr.result_size( tyenv) if not expr.tag.startswith('Ico_') else expr.size ty = expr.result_type( tyenv) if not expr.tag.startswith('Ico_') else expr.type addr = self.addr if expr.tag == 'Iex_Get': return self.get_reg(expr.offset, ty) elif expr.tag == 'Iex_RdTmp': return self.get_tmp(expr.tmp) elif expr.tag == 'Iex_Load': addr_expression = self.handle_expression(expr.addr, tyenv, path + ['addr']) self.access(addr_expression, ACCESS_READ) return self.get_mem(addr_expression, ty) elif expr.tag == 'Iex_Const' or expr.tag.startswith('Ico_'): if expr.tag == 'Iex_Const': expr = expr.con if 'F' in ty: if size == 32: values = BiHead( claripy.FPV(expr.value, claripy.fp.FSORT_FLOAT), claripy.FPS('%x_%d' % (addr, path[1]), claripy.fp.FSORT_FLOAT)) elif size == 64: values = BiHead( claripy.FPV(expr.value, claripy.fp.FSORT_DOUBLE), claripy.FPS('%x_%d' % (addr, path[1]), claripy.fp.FSORT_DOUBLE)) else: raise FidgetUnsupportedError( "Why is there a FP const of size %d" % size) else: values = BiHead(claripy.BVV(expr.value, size), claripy.BVS('%x_%d' % (addr, path[1]), size)) values.taints['deps'].append( PendingBinaryData(self.project, self.addr, values, path)) values.taints['concrete'] = True values.taints['concrete_root'] = True return values elif expr.tag == 'Iex_ITE': false_expr = self.handle_expression(expr.iffalse, tyenv, path + ['iffalse']) truth_expr = self.handle_expression(expr.iftrue, tyenv, path + ['iftrue']) values = truth_expr if truth_expr.taints['pointer'] else false_expr cond_expr = self.handle_expression(expr.cond, tyenv, path + ['cond']) if not cond_expr.taints['it']: values.taints['concrete'] = false_expr.taints[ 'concrete'] and truth_expr.taints['concrete'] values.taints[ 'it'] = false_expr.taints['it'] or truth_expr.taints['it'] return values elif expr.tag in ('Iex_Unop', 'Iex_Binop', 'Iex_Triop', 'Iex_Qop'): args = [] for i, sub_expr in enumerate(expr.args): arg = self.handle_expression(sub_expr, tyenv, path + ['args', i]) if expr.op.startswith('Iop_Mul') or expr.op.startswith('Iop_And') \ or (i == 0 and expr.op in ROUNDING_IROPS): if arg.taints['concrete_root']: arg = BiHead(arg.cleanval, arg.cleanval) arg.taints['concrete'] = True args.append(arg) try: values = BiHead( operations[expr.op].calculate(*(x.cleanval for x in args)), operations[expr.op].calculate(*(x.dirtyval for x in args))) except SimOperationError: l.exception( "SimOperationError while running op '%s', returning null", expr.op) return BiHead.default(ty) except KeyError: l.error("Unsupported operation '%s', returning null", expr.op) return BiHead.default(ty) else: # propogate the taints correctly values.taints['concrete'] = True for arg in args: values.taints['deps'].extend(arg.taints['deps']) values.taints['concrete'] = values.taints[ 'concrete'] and arg.taints['concrete'] values.taints[ 'it'] = values.taints['it'] or arg.taints['it'] if expr.op.startswith('Iop_Add') or expr.op.startswith('Iop_And') or \ expr.op.startswith('Iop_Or') or expr.op.startswith('Iop_Xor'): t1 = args[0].taints['pointer'] t2 = args[1].taints['pointer'] values.taints['pointer'] = (t1 if t1 else t2) if ( bool(t1) ^ bool(t2)) else False elif expr.op.startswith('Iop_Sub'): t1 = args[0].taints['pointer'] t2 = args[1].taints['pointer'] values.taints['pointer'] = t1 if t1 and not t2 else False return values elif expr.tag == 'Iex_CCall': values = BiHead.default(ty) for i, expr in enumerate(expr.args): arg = self.handle_expression(expr, tyenv, path + ['args', i]) values.taints['it'] = values.taints['it'] or arg.taints['it'] return values elif expr.tag == 'Iex_GetI': return BiHead.default(ty) else: raise FidgetUnsupportedError( 'Unknown expression tag ({:#x}): {!r}'.format(addr, expr.tag))
def run(self, thing, *args): this_ref = thing if isinstance(thing, SimSootValue_ThisRef) else None if args: method_descriptor = args[-1] args = args[:-1] else: # if args is empty, method is static and has no params method_descriptor = thing # return the appropriate value based on the return type of the method if method_descriptor is None or method_descriptor.ret is None or method_descriptor.ret == 'void': ret_value = None elif method_descriptor.ret in [ 'byte', 'char', 'short', 'int', 'boolean' ]: ret_value = claripy.BVS( 'unc_{}_{}'.format(method_descriptor.ret, method_descriptor.name), 32) elif method_descriptor.ret == 'long': ret_value = claripy.BVS( 'unc_long_{}'.format(method_descriptor.name), 64) elif method_descriptor.ret == 'float': ret_value = claripy.FPS( 'unc_float_{}'.format(method_descriptor.name), claripy.FSORT_FLOAT) elif method_descriptor.ret == 'double': ret_value = claripy.FPS( 'unc_double_{}'.format(method_descriptor.name), claripy.FSORT_DOUBLE) elif method_descriptor.ret == 'java.lang.String': str_ref = SimSootValue_StringRef.new_string( self.state, claripy.StringS("unc_string_{}".format(method_descriptor.name), 1000)) ret_value = str_ref elif method_descriptor.ret.endswith('[][]'): raise NotImplementedError elif method_descriptor.ret.endswith('[]'): # TODO here array size should be symbolic ret_value = SimSootExpr_NewArray.new_array( self.state, method_descriptor.ret[:-2], claripy.BVV(2, 32)) else: ret_value = SimSootValue_ThisRef.new_object(self.state, method_descriptor.ret, symbolic=True, init_object=False) # Simple heuristic to infer if the unknown method we are trying to execute is a getter or a setter # Must be improved. This would work only if the method follows the Java naming convention. # If the application is obfuscated this won't work. if this_ref is not None and options.JAVA_IDENTIFY_GETTER_SETTER in self.state.options: if method_descriptor.name.startswith("get"): field_name = method_descriptor.name.replace("get", "") field_name = field_name[0].lower() + field_name[1:] return this_ref.get_field(self.state, field_name, method_descriptor.ret) # We define a setter as a method that starts with set # and has only one parameter (other than 'this' reference) elif method_descriptor.name.startswith("set") and len( method_descriptor.params) == 1 and len(args) == 1: field_name = method_descriptor.name.replace("set", "") field_name = field_name[0].lower() + field_name[1:] this_ref.set_field(self.state, field_name, method_descriptor.params[0], args[0]) return return ret_value
val = claripy.BVS('val', 64) val = val.reversed ptr_val = angr.PointerWrapper(val) size = claripy.BVS('size', 32) char_val = claripy.BVS("char_val", 8) struct_val = claripy.BVS('struct', 128) struct_val_ptr = angr.PointerWrapper(struct_val) array_size = 32 * 4 array = claripy.BVS('arr', array_size) foo0 = claripy.BVS('foo0', 64) foo1 = claripy.BVS('foo1', 64) floatarg = claripy.FPS('float1', claripy.FSORT_DOUBLE) array_ptr = angr.PointerWrapper(array) val2 = claripy.BVS('val2', 32) ptr_val2 = angr.PointerWrapper(val2) enum = claripy.BVS('val2', 32) enum2 = claripy.BVS('val2', 32) ptr_val2 = angr.PointerWrapper(enum2) val3 = claripy.BVS('val3', 32) #args = [ptr_val, val2] cs = proj.factory.call_state(cfg.kb.functions["_Z16ecall_type_floatf"].addr, floatarg) csm = proj.factory.simgr(cs) while len(csm.active) == 1: proj.factory.block(csm.active[0].addr).pp()
def run(self): log.debug('Called SimProcedure java.lang.Math.random with args') return claripy.FPS('rand_int', claripy.FSORT_DOUBLE)