コード例 #1
0
    def _translate_args(self):
        args = []
        # for instance method calls, add the 'this' reference
        if isinstance(self, SimSootExpr_VirtualInvoke) or \
           isinstance(self, SimSootExpr_SpecialInvoke):
            this_ref_base = self._translate_value(self.expr.base)
            this_ref = self.state.memory.load(this_ref_base,
                                              none_if_missing=True)
            this_ref_type = this_ref.type if this_ref is not None else None
            args += [SootArgument(this_ref, this_ref_type, is_this_ref=True)]

        # translate function arguments
        for arg in self.expr.args:
            if "Constant" in arg.__class__.__name__:
                # argument is a constant
                # => translate the expr to get the value
                arg_value = self._translate_expr(arg).expr
            else:
                # argument is a variable
                # => load value from memory
                arg_value = self.state.memory.load(self._translate_value(arg),
                                                   none_if_missing=True)
            args += [SootArgument(arg_value, arg.type)]

        return args
コード例 #2
0
ファイル: method_calls.py プロジェクト: ohyeah521/angr-1
    def _setup_java_args(self, arg_values, method_id, this_ref=None):
        args = []

        # if available, add 'this' reference
        if this_ref:
            args += [SootArgument(this_ref, this_ref.type, is_this_ref=True)]

        # function arguments
        for arg_value_, arg_type in zip(arg_values, method_id.params):

            if arg_type in ArchSoot.primitive_types:
                # argument has a primitive integral type
                # => cast native value to java type
                arg_value = self.project.simos.cast_primitive(self.state,
                                                              value=arg_value_,
                                                              to_type=arg_type)

            else:
                # argument has a relative type
                # => lookup java object
                arg_value = self.state.jni_references.lookup(arg_value_)

            args += [SootArgument(arg_value, arg_type)]

        return args
コード例 #3
0
    def _setup_native_callsite(cls, state, native_addr, java_method, args,
                               ret_addr, ret_var):
        # Step 1: setup java callsite, but w/o storing arguments in memory
        cls.setup_callsite(state, None, ret_addr, ret_var)

        # Step 2: add JNI specific arguments to *args list

        # get JNI environment pointer
        jni_env = SootArgument(state.project.simos.jni_env, "JNIEnv")

        # get reference to the current object or class
        if args and args[0].is_this_ref:
            # instance method call
            # => pass 'this' reference to native code
            ref = args.pop(0)
        else:
            # static method call
            # => pass 'class' reference to native code
            class_ = state.javavm_classloader.get_class(java_method.class_name,
                                                        init_class=True)
            ref = SootArgument(class_, "Class")

        # add to args
        final_args = [jni_env, ref] + args

        # Step 3: create native invoke state
        return state.project.simos.state_call(native_addr,
                                              *final_args,
                                              base_state=state,
                                              ret_type=java_method.ret)
コード例 #4
0
ファイル: test_java.py プロジェクト: zyc1314/angr
def test_apk_loading():
    sdk_path = os.path.join(os.path.expanduser("~"), "Android/Sdk/platforms/")
    if not os.path.exists(sdk_path):
        print("cannot run test_apk_loading since there is no Android SDK folder")
        return

    loading_opts = {'android_sdk': sdk_path,
                    'entry_point': 'com.example.antoniob.android1.MainActivity.onCreate',
                    'entry_point_params': ('android.os.Bundle', )}
    project = angr.Project(os.path.join(test_location, "android1.apk"), main_opts=loading_opts)

    blank_state = project.factory.blank_state()
    a1 = SimSootValue_ThisRef.new_object(blank_state, 'com.example.antoniob.android1.MainActivity')
    a2 = SimSootValue_ThisRef.new_object(blank_state, 'android.os.Bundle', symbolic = True)
    args = [SootArgument(arg, arg.type) for arg in [a1, a2]]
    entry = project.factory.entry_state(args = args)

    simgr = project.factory.simgr(entry)
    simgr.step()
    simgr.step()
    assert simgr.active[0].addr.block_idx == 0
    assert simgr.active[0].addr.stmt_idx == 3
    simgr.run()
    assert len(simgr.deadended) == 1
    assert type(simgr.deadended[0].addr) is SootAddressTerminator
コード例 #5
0
ファイル: solve.py プロジェクト: 90819081y/angr-doc
def test_androidnative1():
    sdk_path = os.path.join(os.path.expanduser("~"), "Android/Sdk/platforms/")
    if not os.path.exists(sdk_path):
        print(
            "cannot run test_apk_loading since there is no Android SDK folder")
        return

    apk_location = os.path.join(file_dir, "androidnative1.apk")
    loading_opts = {
        'android_sdk': sdk_path,
        'entry_point': 'com.angr.nativetest1.MainActivity.onCreate',
        'entry_point_params': ('android.os.Bundle', ),
        'supported_jni_archs': ['x86']
    }
    project = angr.Project(apk_location, main_opts=loading_opts)
    project.hook(
        SootMethodDescriptor(class_name="java.lang.String",
                             name="valueOf",
                             params=('int', )).address(),
        Dummy_String_valueOf())

    blank_state = project.factory.blank_state()
    a1 = SimSootValue_ThisRef.new_object(
        blank_state, 'com.angr.androidnative1.MainActivity')
    a2 = SimSootValue_ThisRef.new_object(blank_state,
                                         'android.os.Bundle',
                                         symbolic=True)
    args = [SootArgument(arg, arg.type) for arg in [a1, a2]]
    entry = project.factory.entry_state(args=args)
    simgr = project.factory.simgr(entry)

    simgr.run()

    int_result = simgr.deadended[0].solver.eval(result)
    assert int_result == 221
コード例 #6
0
ファイル: thisref.py プロジェクト: AOS002/angr-fork
    def new_object(cls, state, type_, symbolic=False, init_object=False, init_class=False):
        """
        Creates a new object reference.
        :param state: State associated to the object.
        :param type_: Class of the object.
        :param init_object: Whether the objects initializer method should be run.
        :param init_class: Whether the class initializer method should be run.
        :return: Reference to the new object.
        """
        # create reference
        obj_ref = cls(heap_alloc_id=state.memory.get_new_uuid(), type_=type_, symbolic=symbolic)
        # run initializer
        if init_object:
            l.info(">" * 15 + " Initialize object %r ... " + ">" * 15, obj_ref)
            # find initializer method
            # TODO: add support for non-default initializing methods
            init_method = resolve_method(state, '<init>', type_, init_class=init_class).address()

            # setup init state
            args = [SootArgument(obj_ref, obj_ref.type, is_this_ref=True)]
            init_state = state.project.simos.state_call(init_method, *args,
                                                        base_state=state,
                                                        ret_addr=SootAddressTerminator())
            # run init state
            simgr = state.project.factory.simgr(init_state)
            simgr.run()
            # copy results from initialization to the state
            state.memory.vm_static_table = simgr.deadended[0].memory.vm_static_table.copy()
            state.memory.heap = simgr.deadended[0].memory.heap.copy()
            l.debug("<" * 15 + " Initialize object %r ... done " + "<" * 15, obj_ref)
        return obj_ref
コード例 #7
0
def get_new_primitive_arg(value, type_):
    """
    Wraps a primitive value so it so it can be used as a parameter for a method

    :param value: the value of the primitiva value.
    :type BV
    :param value: the type of the primitive value (int, boolean, etc.)
    :type str
    :return SootArgument
    """
    return SootArgument(value, type_)
コード例 #8
0
def get_new_object_arg(obj_ref, is_this_ref=False):
    """
    Wraps an object reference so it can be passed as a method parameter

    :param obj_ref: the reference to the object we want to pass as parameter
    :type SimSootValue_ThisRef
    :param is_this_ref: indicates if the object reference is a 'this' reference or not
    :type bool
    :return SootArgument
    """
    return SootArgument(obj_ref, obj_ref.type, is_this_ref)
コード例 #9
0
ファイル: test_java.py プロジェクト: zyt755/angr
def test_object_tracking():
    binary_dir = os.path.join(test_location, "object_tracking")
    project = create_project(binary_dir, load_native_libs=False)
    bootstrap_state = project.factory.blank_state(addr=SootAddressTerminator())
    mylib_object = SimSootValue_ThisRef.new_object(bootstrap_state, "MyLib", symbolic=True, init_object=False)

    soot_method = resolve_method(
        bootstrap_state, 'testGetterAndSetterConcrete', "MixedJava", ("mylib.MyLib",), init_class=False).address()

    call_state = project.factory.call_state(
        soot_method,
        SootArgument(mylib_object, mylib_object.type, is_this_ref=False),
        base_state=bootstrap_state,
        ret_addr=SootAddressTerminator())

    call_state.options.add(angr.options.JAVA_IDENTIFY_GETTER_SETTER)
    call_state.options.add(angr.options.JAVA_TRACK_ATTRIBUTES)

    simgr = project.factory.simgr(call_state)
    simgr.run()

    assert len(simgr.deadended) == 1

    final_state = simgr.deadended[0]

    assert final_state.solver.eval(mylib_object.get_field(final_state, 'myInt', 'int')) == 1
    assert final_state.solver.eval(mylib_object.get_field(final_state, 'myShort', 'short')) == 1
    assert final_state.solver.eval(mylib_object.get_field(final_state, 'myChar', 'char')) == ord('c')
    assert final_state.solver.eval(mylib_object.get_field(final_state, 'myLong', 'long')) == 2
    assert final_state.solver.eval(mylib_object.get_field(final_state, 'myFloat', 'float')) == 1.5
    assert final_state.solver.eval(mylib_object.get_field(final_state, 'myDouble', 'double')) == 1.5
    string_ref = mylib_object.get_field(final_state, 'myString', 'java.lang.String')
    assert final_state.solver.eval(final_state.memory.load(string_ref)) == 'Hello!'
    array_ref = mylib_object.get_field(final_state, 'myArray', 'int[]')
    assert final_state.solver.eval(array_ref.size) == 3
    object_ref = mylib_object.get_field(final_state, 'myObject', 'java.lang.Object')
    assert final_state.solver.eval(object_ref.get_field(final_state, 'a', 'int')) == 1

    assert ('myInt', 'int') in mylib_object.attributes
    assert ('myChar', 'char') in mylib_object.attributes
    assert ('myShort', 'short') in mylib_object.attributes
    assert ('myLong', 'long') in mylib_object.attributes
    assert ('myFloat', 'float') in mylib_object.attributes
    assert ('myDouble', 'double') in mylib_object.attributes
    assert ('myString', 'java.lang.String') in mylib_object.attributes
    assert ('myArray', 'int[]') in mylib_object.attributes
    assert ('myObject', 'java.lang.Object') in mylib_object.attributes
コード例 #10
0
ファイル: javavm.py プロジェクト: twizmwazin/angr
    def state_entry(self, *args, **kwargs): # pylint: disable=arguments-differ
        """
        Create an entry state.

        :param args: List of SootArgument values (optional).
        """
        state = self.state_blank(**kwargs)
        # for the Java main method `public static main(String[] args)`,
        # we add symbolic cmdline arguments
        if not args and state.addr.method.name == 'main' and \
                        state.addr.method.params[0] == 'java.lang.String[]':
            cmd_line_args = SimSootExpr_NewArray.new_array(state, "java.lang.String", BVS('argc', 32))
            cmd_line_args.add_default_value_generator(self.generate_symbolic_cmd_line_arg)
            args = [SootArgument(cmd_line_args, "java.lang.String[]")]
            # for referencing the Java array, we need to know the array reference
            # => saves it in the globals dict
            state.globals['cmd_line_args'] = cmd_line_args
        # setup arguments
        SimEngineSoot.setup_arguments(state, args)
        return state
コード例 #11
0
ファイル: javavm.py プロジェクト: twizmwazin/angr
    def state_call(self, addr, *args, **kwargs):
        """
        Create a native or a Java call state.

        :param addr:    Soot or native addr of the invoke target.
        :param args:   List of SootArgument values.
        """
        state = kwargs.pop('base_state', None)
        # check if we need to setup a native or a java callsite
        if isinstance(addr, SootAddressDescriptor):
            # JAVA CALLSITE
            # ret addr precedence: ret_addr kwarg > base_state.addr > terminator
            ret_addr = kwargs.pop('ret_addr', state.addr if state else SootAddressTerminator())
            cc = kwargs.pop('cc', SimCCSoot(self.arch))
            if state is None:
                state = self.state_blank(addr=addr, **kwargs)
            else:
                state = state.copy()
                state.regs.ip = addr
            cc.setup_callsite(state, ret_addr, args)
            return state

        else:
            # NATIVE CALLSITE
            # setup native argument values
            native_arg_values = []
            for arg in args:
                if arg.type in ArchSoot.primitive_types or \
                   arg.type == "JNIEnv":
                    # the value of primitive types and the JNIEnv pointer
                    # are just getting copied into the native memory
                    native_arg_value = arg.value
                    if self.arch.bits == 32 and arg.type == "long":
                        # On 32 bit architecture, long values (w/ 64 bit) are copied
                        # as two 32 bit integer
                        # TODO is this correct?
                        upper = native_arg_value.get_bytes(0, 4)
                        lower = native_arg_value.get_bytes(4, 4)
                        idx = args.index(arg)
                        args = args[:idx] \
                               + (SootArgument(upper, 'int'), SootArgument(lower, 'int')) \
                               + args[idx+1:]
                        native_arg_values += [upper, lower]
                        continue
                else:
                    # argument has a relative type
                    # => map Java reference to an opaque reference, which the native code
                    #    can use to access the Java object through the JNI interface
                    native_arg_value = state.jni_references.create_new_reference(obj=arg.value)
                native_arg_values += [native_arg_value]

            # setup native return type
            ret_type = kwargs.pop('ret_type')
            native_ret_type = self.get_native_type(ret_type)

            # setup function prototype, so the SimCC know how to init the callsite
            arg_types = [self.get_native_type(arg.type) for arg in args]
            prototype = SimTypeFunction(args=arg_types, returnty=native_ret_type)
            native_cc = self.get_native_cc(func_ty=prototype)

            # setup native invoke state
            return self.native_simos.state_call(addr, *native_arg_values,
                                                base_state=state,
                                                ret_addr=self.native_return_hook_addr,
                                                cc=native_cc, **kwargs)
コード例 #12
0
    def state_call(self, addr, *args, **kwargs):
        """
        Create a native or a Java call state.

        :param addr:    Soot or native addr of the invoke target.
        :param args:   List of SootArgument values.
        """
        state = kwargs.pop('base_state', None)
        # check if we need to setup a native or a java callsite
        if isinstance(addr, SootAddressDescriptor):
            # JAVA CALLSITE
            # ret addr precedence: ret_addr kwarg > base_state.addr > terminator
            ret_addr = kwargs.pop(
                'ret_addr', state.addr if state else SootAddressTerminator())
            cc = kwargs.pop('cc', SimCCSoot(self.arch))
            if state is None:
                state = self.state_blank(addr=addr, **kwargs)
            else:
                state = state.copy()
                state.regs.ip = addr
            cc.setup_callsite(state, ret_addr, args,
                              kwargs.pop('prototype', None))
            return state

        else:
            # NATIVE CALLSITE

            # setup native return type
            # TODO roll this into protytype
            ret_type = kwargs.pop('ret_type')
            native_ret_type = self.get_native_type(ret_type)

            # setup function prototype, so the SimCC know how to init the callsite
            prototype = kwargs.pop('prototype', None)
            if prototype is None:
                arg_types = [self.get_native_type(arg.type) for arg in args]
                prototype = SimTypeFunction(args=arg_types,
                                            returnty=native_ret_type)
            native_cc = kwargs.pop('cc', None)
            if native_cc is None:
                native_cc = self.get_native_cc()

            # setup native argument values
            native_arg_values = []
            for arg, arg_ty in zip(args, prototype.args):
                if arg.type in ArchSoot.primitive_types or \
                   arg.type == "JNIEnv":
                    # the value of primitive types and the JNIEnv pointer
                    # are just getting copied into the native memory
                    native_arg_value = arg.value
                    if self.arch.bits == 32 and arg.type == "long":
                        # On 32 bit architecture, long values (w/ 64 bit) are copied
                        # as two 32 bit integer
                        # TODO I _think_ all this logic can go away as long as the cc knows how to store large values
                        # TODO this has been mostly implemented 11 Dec 2021
                        # unfortunately no test cases hit this branch so I don't wanna touch it :(
                        upper = native_arg_value.get_bytes(0, 4)
                        lower = native_arg_value.get_bytes(4, 4)
                        idx = args.index(arg)
                        args = args[:idx] \
                               + (SootArgument(upper, 'int'), SootArgument(lower, 'int')) \
                               + args[idx+1:]
                        native_arg_values += [upper, lower]
                        continue
                    if type(arg.value) is BV and len(arg.value) > arg_ty.size:
                        # hack??? all small primitives are passed around as 32bit but cc won't like that
                        native_arg_value = native_arg_value[arg_ty.size - 1:0]
                else:
                    # argument has a relative type
                    # => map Java reference to an opaque reference, which the native code
                    #    can use to access the Java object through the JNI interface
                    native_arg_value = state.jni_references.create_new_reference(
                        obj=arg.value)
                native_arg_values += [native_arg_value]

            # setup native invoke state
            return self.native_simos.state_call(
                addr,
                *native_arg_values,
                base_state=state,
                ret_addr=self.native_return_hook_addr,
                cc=native_cc,
                prototype=prototype,
                **kwargs)