Exemple #1
0
    def _soot_create_invoke_successors(self, stmt, addr, invoke_expr):

        method_class = invoke_expr.class_name
        method_name = invoke_expr.method_name
        method_params = invoke_expr.method_params
        method_desc = SootMethodDescriptor(method_class, method_name,
                                           method_params)

        callee_soot_method = self.project.loader.main_object.get_soot_method(
            method_desc, none_if_missing=True)
        caller_soot_method = self.project.loader.main_object.get_soot_method(
            addr.method)

        if callee_soot_method is None:
            # this means the called method is external
            return [(stmt.label, addr,
                     SootAddressDescriptor(method_desc, 0, 0), 'Ijk_Call')]

        targets = self._soot_class_hierarchy.resolve_invoke(
            invoke_expr, callee_soot_method, caller_soot_method)

        successors = []
        for target in targets:
            target_desc = SootMethodDescriptor(target.class_name, target.name,
                                               target.params)
            successors.append(
                (stmt.label, addr, SootAddressDescriptor(target_desc, 0,
                                                         0), 'Ijk_Call'))

        return successors
Exemple #2
0
    def _pre_analysis(self):

        # Call _initialize_cfg() before self.functions is used.
        self._initialize_cfg()

        # Initialize variables used during analysis
        self._pending_jobs = PendingJobs(self.functions, self._deregister_analysis_job)
        self._traced_addresses = set()
        self._changed_functions = set()
        self._updated_nonreturning_functions = set()

        self._nodes = {}
        self._nodes_by_addr = defaultdict(list)

        self._function_returns = defaultdict(set)

        entry = self.project.entry  # type:SootAddressDescriptor
        entry_func = entry.method

        obj = self.project.loader.main_object

        if entry_func is not None:
            method_inst = obj.get_soot_method(
                entry_func.name, class_name=entry_func.class_name, params=entry_func.params)
        else:
            l.warning('The entry method is unknown. Try to find a main method.')
            method_inst = next(obj.main_methods, None)
            if method_inst is not None:
                entry_func = SootMethodDescriptor(method_inst.class_name, method_inst.name, method_inst.params)
            else:
                l.warning('Cannot find any main methods. Start from the first method of the first class.')
                for cls in obj.classes.values():
                    method_inst = next(iter(cls.methods), None)
                    if method_inst is not None:
                        break
                if method_inst is not None:
                    entry_func = SootMethodDescriptor(method_inst.class_name, method_inst.name,
                                                      method_inst.params)
                else:
                    raise AngrCFGError('There is no method in the Jar file.')

        # project.entry is a method
        # we should get the first block
        if method_inst.blocks:
            block_idx = method_inst.blocks[0].idx
            self._insert_job(CFGJob(SootAddressDescriptor(entry_func, block_idx, 0), entry_func, 'Ijk_Boring'))

        total_methods = 0

        # add all other methods as well
        for cls in self.project.loader.main_object.classes.values():
            for method in cls.methods:
                total_methods += 1
                if method.blocks:
                    method_des = SootMethodDescriptor(cls.name, method.name, method.params)
                    # TODO shouldn't this be idx?
                    block_idx = method.blocks[0].label
                    self._insert_job(CFGJob(SootAddressDescriptor(method_des, block_idx, 0), method_des, 'Ijk_Boring'))

        self._total_methods = total_methods
Exemple #3
0
def get_entry_state_of_method(project, method_fullname):
    # get SootAddressDescriptor of method entry
    soot_method = project.loader.main_object.get_soot_method(method_fullname)
    method = SootMethodDescriptor.from_soot_method(soot_method)
    addr = SootAddressDescriptor(method, 0, 0)
    # create call state
    return project.factory.blank_state(addr=addr)
Exemple #4
0
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
Exemple #5
0
    def _resolve_invoke_target(self, expr, state):
        # get the type of the base object
        base = translate_expr(self.expr.base, self.state).expr
        if base is not None:
            base_type = base.type
        else:
            # the base is not set, for example if we process an invocation of an
            # unloaded library function
            # => fallback: use the statically retrieved type
            base_type = self.expr.class_name

        # based on the class of the base object, we resolve the invoke target
        try:
            return resolve_method(state=self.state,
                                  method_name=self.expr.method_name,
                                  class_name=base_type,
                                  params=self.expr.method_params,
                                  ret_type=self.expr.type,
                                  raise_exception_if_not_found=True)
        except SootMethodNotLoadedException:
            # in case that the method is not loaded, continue with the infos
            # available from the invoke expression
            return SootMethodDescriptor(self.expr.class_name,
                                        self.expr.method_name,
                                        self.expr.method_params,
                                        ret_type=self.expr.type)
Exemple #6
0
def resolve_method(state, method_name, class_name, params=(), ret_type=None,
                   include_superclasses=True, init_class=True,
                   raise_exception_if_not_found=False):
    """
    Resolves the method based on the given characteristics (name, class and
    params) The method may be defined in one of the superclasses of the given
    class (TODO: support interfaces).

    :rtype: archinfo.arch_soot.SootMethodDescriptor
    """
    base_class = state.javavm_classloader.get_class(class_name)
    if include_superclasses:
        class_hierarchy = state.javavm_classloader.get_class_hierarchy(base_class)
    else:
        class_hierarchy = [base_class]
    # walk up in class hierarchy, until method is found
    for class_descriptor in class_hierarchy:
        java_binary = state.project.loader.main_object
        soot_method = java_binary.get_soot_method(method_name, class_descriptor.name,
                                                  params, none_if_missing=True)
        if soot_method is not None:
            # init the class
            if init_class:
                state.javavm_classloader.init_class(class_descriptor)
            return SootMethodDescriptor.from_soot_method(soot_method)

    # method could not be found
    # => we are executing code that is not loaded (typically library code)
    # => fallback: continue with infos available from the invocation, so we
    #              still can use SimProcedures
    if raise_exception_if_not_found:
        raise SootMethodNotLoadedException()
    else:
        return SootMethodDescriptor(class_name, method_name, params, ret_type=ret_type)
Exemple #7
0
def get_entry_state_of_method(project, method_fullname):
    # get SootAddressDescriptor of method entry
    soot_method = project.loader.main_object.get_soot_method(method_fullname)
    method = SootMethodDescriptor.from_soot_method(soot_method)
    addr = SootAddressDescriptor(method, 0, 0)
    # create call state
    return project.factory.blank_state(addr=addr)
Exemple #8
0
def test_java_simple4():
    binary_path = os.path.join(self_dir, "simple4.jar")

    proj = angr.Project(binary_path)
    print proj.loader.main_object._classes['simple4.Class1']

    simgr = proj.factory.simgr()
    main_method = next(proj.loader.main_object.main_methods)
    simgr.active[0].ip = SootAddressDescriptor(
        SootMethodDescriptor.from_method(main_method), 0, 0)

    simgr.explore()

    paths = simgr.deadended
    assert len(paths) == 2

    winnning_paths = []
    for pp in paths:
        pp.state.posix.set_pos(0, 0)
        pp.state.posix.set_pos(1, 0)
        oo = pp.state.posix.read_from(1, 1)
        # a winning path is printing 'W'
        pp.state.add_constraints(oo == pp.state.se.BVV(ord('W'), 8))
        if pp.satisfiable():
            winnning_paths.append(pp)
    assert len(winnning_paths) == 1
    winning_path = winnning_paths[0]

    # on the winning path, we ask for the input
    ii = winning_path.state.posix.read_from(0, 1)
    solution = chr(winning_path.state.se.eval(ii))
    print repr(solution)
    assert solution == 'F'
Exemple #9
0
def get_entry_state_of_method(project, method_fullname):
    # get SootAddressDescriptor of method entry
    soot_method = project.loader.main_object.get_soot_method(method_fullname)
    method = SootMethodDescriptor.from_soot_method(soot_method)
    addr = SootAddressDescriptor(method, 0, 0)
    # create call state
    return project.factory.blank_state(addr=addr, add_options={angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY})
Exemple #10
0
def resolve_method(state,
                   method_name,
                   class_name,
                   params=(),
                   ret_type=None,
                   include_superclasses=True,
                   init_class=True,
                   raise_exception_if_not_found=False):
    """
    Resolves the method based on the given characteristics (name, class and
    params) The method may be defined in one of the superclasses of the given
    class (TODO: support interfaces).

    :rtype: archinfo.arch_soot.SootMethodDescriptor
    """
    base_class = state.javavm_classloader.get_class(class_name)
    if include_superclasses:
        class_hierarchy = state.javavm_classloader.get_class_hierarchy(
            base_class)
    else:
        class_hierarchy = [base_class]
    # walk up in class hierarchy, until method is found
    for class_descriptor in class_hierarchy:
        java_binary = state.project.loader.main_object
        soot_method = java_binary.get_soot_method(method_name,
                                                  class_descriptor.name,
                                                  params,
                                                  none_if_missing=True)
        if soot_method is not None:
            # init the class
            if init_class:
                state.javavm_classloader.init_class(class_descriptor)
            return SootMethodDescriptor.from_soot_method(soot_method)

    # method could not be found
    # => we are executing code that is not loaded (typically library code)
    # => fallback: continue with infos available from the invocation, so we
    #              still can use SimProcedures
    if raise_exception_if_not_found:
        raise SootMethodNotLoadedException()
    else:
        return SootMethodDescriptor(class_name,
                                    method_name,
                                    params,
                                    ret_type=ret_type)
Exemple #11
0
    def run(self, ptr_env, class_, ptr_method_name, ptr_method_sig):

        method_class = self.state.jni_references.lookup(class_)
        method_name = self._load_string_from_native_memory(ptr_method_name)
        method_sig = self._load_string_from_native_memory(ptr_method_sig)

        # derive parameter type from signature
        params, _ = ArchSoot.decode_method_signature(method_sig)

        # create method ID and return reference to it
        method_id = SootMethodDescriptor(method_class.name, method_name, params)
        return self.state.jni_references.create_new_reference(method_id)
Exemple #12
0
Fichier : soot.py Projet : angr/cle
    def __init__(self, path, entry_point=None, entry_point_params=(), input_format=None,
                 additional_jars=None, additional_jar_roots=None,
                 jni_libs_ld_path=None, jni_libs=None,
                 android_sdk=None, **kwargs):

        if not pysoot:
            raise ImportError('Cannot import PySoot. The Soot backend requires PySoot.')

        if kwargs.get('has_memory', False):
            raise CLEError('The parameter "has_memory" must be False for Soot backend.')

        super(Soot, self).__init__(path, has_memory=False, **kwargs)

        # load the classes
        l.debug("Lifting to Soot IR ...")
        start_time = time.time()
        pysoot_lifter = Lifter(path,
                               input_format=input_format,
                               android_sdk=android_sdk,
                               additional_jars=additional_jars,
                               additional_jar_roots=additional_jar_roots)
        end_time = time.time()
        l.debug("Lifting completed in %ds", round(end_time - start_time, 2))
        self._classes = pysoot_lifter.classes

        # find entry method
        if entry_point:
            try:
                ep_method = self.get_soot_method(entry_point, params=entry_point_params)
                ep_method_descriptor = SootMethodDescriptor.from_soot_method(ep_method)
                self._entry = SootAddressDescriptor(ep_method_descriptor, 0, 0)
                l.debug("Entry point set to %s", self._entry)
            except CLEError:
                l.warning("Couldn't find entry point %s.", entry_point)
                self._entry = None

        self.os = 'javavm'
        self.rebase_addr = None
        self.set_arch(ArchSoot())

        if jni_libs:
            # native libraries are getting loaded by adding them as a dependency of this object
            self.deps += [jni_libs] if type(jni_libs) in (str, bytes) else jni_libs
            # if available, add additional load path(s)
            if jni_libs_ld_path:
                path_list = [jni_libs_ld_path] if type(jni_libs_ld_path) in (str, bytes) else jni_libs_ld_path
                self.extra_load_path += path_list
            self.jni_support = True
        else:
            self.jni_support = False
Exemple #13
0
    def setup_caller(self, caller):
        # returns true if the caller itself adds entropy
        params = tuple(caller[2])
        method_name = caller[0] + '.' + caller[1]
        soot_method = self.angr_p.loader.main_object.get_soot_method(
            method_name, params=params)
        target_method = SootMethodDescriptor.from_soot_method(soot_method)
        base_state = self.angr_p.factory.blank_state()
        base_state.ip = SootAddressTerminator()
        args_target_method, caller_args = self._get_initialized_method_args(
            base_state, soot_method)

        return self.angr_p.factory.call_state(
            target_method.addr, *args_target_method,
            base_state=base_state), caller_args
Exemple #14
0
 def _get_next_linear_instruction(state, stmt_idx):
     addr = state.addr.copy()
     addr.stmt_idx = stmt_idx
     method = state.regs._ip_binary.get_soot_method(addr.method)
     current_bb = method.blocks[addr.block_idx]
     new_stmt_idx = addr.stmt_idx + 1
     if new_stmt_idx < len(current_bb.statements):
         return SootAddressDescriptor(addr.method, addr.block_idx, new_stmt_idx)
     else:
         new_bb_idx = addr.block_idx + 1
         if new_bb_idx < len(method.blocks):
             return SootAddressDescriptor(addr.method, new_bb_idx, 0)
         else:
             l.warning("falling into a non existing bb: %d in %s",
                       new_bb_idx, SootMethodDescriptor.from_soot_method(method))
             raise IncorrectLocationException()
Exemple #15
0
def test_fauxware():
    # create project
    binary_path = os.path.join(test_location, "fauxware_java_jni", "fauxware.jar")
    jni_options = {'jni_libs': ['libfauxware.so']}
    project = angr.Project(binary_path, main_opts=jni_options)
    entry = project.factory.entry_state()
    simgr = project.factory.simgr(entry)

    # find path to `accepted()` method
    accepted_method = SootMethodDescriptor.from_string('Fauxware.accepted()').address()
    simgr.explore(find=lambda s: s.addr == accepted_method)
    state = simgr.found[0]

    # eval password
    cmd_line_args = project.simos.get_cmd_line_args(state)
    password = state.solver.eval(cmd_line_args[0])
    assert password == "SOSNEAKY"
Exemple #16
0
    def __init__(self,
                 path,
                 additional_jars=None,
                 additional_jar_roots=None,
                 main_class=None,
                 **kwargs):

        if not pysoot:
            raise ImportError(
                'Cannot import PySoot. The Soot backend requires PySoot to function. '
                'Please install PySoot first.')

        if kwargs.get('has_memory', False):
            raise CLEError(
                'The parameter "has_memory" must be False for Soot backend.')

        super(Soot, self).__init__(path, has_memory=False, **kwargs)

        if not main_class:
            # parse main_class from the manifest
            self.manifest = self.get_manifest()
            main_class = self.manifest.get('Main-Class', None)

        # load the classes
        pysoot_lifter = Lifter(
            path,
            additional_jars=additional_jars,
            additional_jar_roots=additional_jar_roots,
            # main_class=main_class,
        )
        self._classes = pysoot_lifter.classes

        # find entry method
        try:
            main_method_descriptor = SootMethodDescriptor.from_method(
                next(self.get_method("main", main_class)))
            entry = SootAddressDescriptor(main_method_descriptor, 0, 0)
        except CLEError:
            _l.warning(
                'Failed to identify the entry (the Main method) of this JAR.')
            entry = None
        self._entry = entry
        self.os = 'javavm'
        self.rebase_addr = None
        self.set_arch(archinfo.arch_from_id('soot'))
Exemple #17
0
 def _get_next_linear_instruction(state, stmt_idx):
     addr = state.addr.copy()
     addr.stmt_idx = stmt_idx
     method = state.regs._ip_binary.get_soot_method(addr.method)
     current_bb = method.blocks[addr.block_idx]
     new_stmt_idx = addr.stmt_idx + 1
     if new_stmt_idx < len(current_bb.statements):
         return SootAddressDescriptor(addr.method, addr.block_idx,
                                      new_stmt_idx)
     else:
         new_bb_idx = addr.block_idx + 1
         if new_bb_idx < len(method.blocks):
             return SootAddressDescriptor(addr.method, new_bb_idx, 0)
         else:
             l.warning("falling into a non existing bb: %d in %s",
                       new_bb_idx,
                       SootMethodDescriptor.from_soot_method(method))
             raise IncorrectLocationException()
Exemple #18
0
def test_java_simple3():
    binary_path = os.path.join(self_dir, "simple3.jar")
    proj = angr.Project(binary_path)
    print proj.loader.main_object._classes['simple3.Class1']

    simgr = proj.factory.simgr()
    main_method = next(proj.loader.main_object.main_methods)
    simgr.active[0].ip = SootAddressDescriptor(
        SootMethodDescriptor.from_method(main_method), 0, 0)

    simgr.explore()

    pp = simgr.deadended[0]
    pp.state.posix.set_pos(0, 0)
    pp.state.posix.set_pos(1, 0)
    ii = pp.state.posix.read_from(0, 1)
    oo = pp.state.posix.read_from(1, 1)
    pp.state.add_constraints(oo == pp.state.se.BVV(ord('c'), 8))

    print ii, "-->", oo
    cinput = chr(pp.state.se.eval(ii))
    print repr(cinput)
    assert cinput == "b"
Exemple #19
0
    def __init__(self,
                 path,
                 entry_point=None,
                 entry_point_params=(),
                 input_format=None,
                 additional_jars=None,
                 additional_jar_roots=None,
                 jni_libs_ld_path=None,
                 jni_libs=None,
                 android_sdk=None,
                 **kwargs):

        if not pysoot:
            raise ImportError(
                'Cannot import PySoot. The Soot backend requires PySoot.')

        if kwargs.get('has_memory', False):
            raise CLEError(
                'The parameter "has_memory" must be False for Soot backend.')

        super(Soot, self).__init__(path, has_memory=False, **kwargs)

        # load the classes
        l.debug("Lifting to Soot IR ...")
        start_time = time.time()
        pysoot_lifter = Lifter(path,
                               input_format=input_format,
                               android_sdk=android_sdk,
                               additional_jars=additional_jars,
                               additional_jar_roots=additional_jar_roots)
        end_time = time.time()
        l.debug("Lifting completed in %ds", round(end_time - start_time, 2))
        self._classes = pysoot_lifter.classes

        # find entry method
        if entry_point:
            try:
                ep_method = self.get_soot_method(entry_point,
                                                 params=entry_point_params)
                ep_method_descriptor = SootMethodDescriptor.from_soot_method(
                    ep_method)
                self._entry = SootAddressDescriptor(ep_method_descriptor, 0, 0)
                l.debug("Entry point set to %s", self._entry)
            except CLEError:
                l.warning("Couldn't find entry point %s.", entry_point)
                self._entry = None

        self.os = 'javavm'
        self.rebase_addr = None
        self.set_arch(ArchSoot())

        if jni_libs:
            # native libraries are getting loaded by adding them as a dependency of this object
            self.deps += [jni_libs] if type(jni_libs) in (str,
                                                          bytes) else jni_libs
            # if available, add additional load path(s)
            if jni_libs_ld_path:
                path_list = [jni_libs_ld_path] if type(jni_libs_ld_path) in (
                    str, bytes) else jni_libs_ld_path
                self.extra_load_path += path_list
            self.jni_support = True
        else:
            self.jni_support = False
Exemple #20
0
def solve_given_numbers_angr(numbers):
    global fake_input_fd, fake_output_fd

    binary_path = os.path.join(self_dir, "bin/service.jar")
    jni_options = {'jni_libs': ['libnotfun.so']}
    project = angr.Project(binary_path, main_opts=jni_options)

    # hooks
    project.hook(
        SootMethodDescriptor(class_name="java.util.Random",
                             name="nextInt",
                             params=('int', )).address(), Random_nextInt())
    project.hook(
        SootMethodDescriptor(class_name="java.lang.Integer",
                             name="valueOf",
                             params=('int', )).address(), Dummy_valueOf())
    project.hook(
        SootMethodDescriptor(class_name="NotFun",
                             name="print",
                             params=('java.lang.Object', )).address(),
        Custom_Print())
    project.hook(
        SootMethodDescriptor(class_name="NotFun", name="getInt",
                             params=()).address(), Custom_getInt())

    # set entry point to the 'game' method
    game_method = [
        m for m in project.loader.main_object.classes['NotFun'].methods
        if m.name == "game"
    ][0]
    game_entry = SootMethodDescriptor.from_soot_method(game_method).address()
    entry = project.factory.blank_state(addr=game_entry)
    simgr = project.factory.simgr(entry)

    # Create a fake file with what it is going to be printed to the user (concrete)
    fake_output_fd = entry.posix.open(b"/fake/output", Flags.O_RDWR)
    ff = entry.posix.fd[fake_output_fd]
    tstr = b"".join([bytes(str(n), 'utf-8') + b"\n" for n in numbers])
    ff.write_data(tstr, len(tstr))
    ff.seek(0)

    # Create a fake file with what the user as to insert (symbolic)
    fake_input_fd = entry.posix.open(b"/fake/input", Flags.O_RDWR)
    ff = entry.posix.fd[fake_input_fd]
    solutions = [claripy.BVS("solution%d" % (i), 32) for i in range(3)]
    for s in solutions:
        ff.write_data(s, 4)
    ff.seek(0)

    print("=" * 10 + " SYMBOLIC EXECUTION STARTED")
    while (len(simgr.active) > 0):
        simgr.step()
        print("===== " + str(simgr))
        print("===== " + ",".join([
            str(a.addr)
            for a in simgr.active if type(a.addr) == SootAddressDescriptor
        ]))

        # If we reach block_idx 30, it means that we solved 1 round of the game --> we stash the state
        # If we reach the gameFail() method, it means that we failed --> we prune the state
        simgr.move(
            'active', 'stashed',
            lambda a: type(a.addr) == SootAddressDescriptor and a.addr.method
            == SootMethodDescriptor("NotFun", "game",
                                    ()) and a.addr.block_idx == 30)
        simgr.move(
            'active', 'pruned', lambda a: type(a.addr) == SootAddressDescriptor
            and a.addr.method == SootMethodDescriptor("NotFun", "gameFail",
                                                      ()))

    print("=" * 10 + " SYMBOLIC EXECUTION ENDED")
    assert len(simgr.stashed) == 1
    win_state = simgr.stashed[0]
    numeric_solutions = []
    for s in solutions:
        es = win_state.solver.eval_atmost(s, 2)
        assert len(es) == 1
        numeric_solutions.append(es[0])
    return numeric_solutions