(self, obj, sim_proc_arch)
This scans through an objects imports and hooks them with simprocedures from our library whenever possible
This scans through an objects imports and hooks them with simprocedures from our library whenever possible
This scans through an objects imports and hooks them with simprocedures from our library whenever possible
def _register_object(self, obj, sim_proc_arch):
        """
        This scans through an objects imports and hooks them with simprocedures from our library whenever possible
        """

        # Step 1: get the set of libraries we are allowed to use to resolve unresolved symbols
        missing_libs = []
        for lib_name in self.loader.missing_dependencies:
            try:
                missing_libs.append(SIM_LIBRARIES[lib_name])
            except KeyError:
                l.info("There are no simprocedures for missing library %s :(", lib_name)
        # additionally provide libraries we _have_ loaded as a fallback fallback
        # this helps in the case that e.g. CLE picked up a linux arm libc to satisfy an android arm binary
        for lib in self.loader.all_objects:
            if lib.provides in SIM_LIBRARIES:
                simlib = SIM_LIBRARIES[lib.provides]
                if simlib not in missing_libs:
                    missing_libs.append(simlib)

        # Step 2: Categorize every "import" symbol in each object.
        # If it's IGNORED, mark it for stubbing
        # If it's blacklisted, don't process it
        # If it matches a simprocedure we have, replace it
        for reloc in obj.imports.values():
            # Step 2.1: Quick filter on symbols we really don't care about
            func = reloc.symbol
            if func is None:
                continue
            if not func.is_function and func.type != cle.backends.symbol.SymbolType.TYPE_NONE:
                continue
            if func.resolvedby is None:
                # I don't understand the binary which made me add this case. If you are debugging and see this comment,
                # good luck.
                # ref: https://github.com/angr/angr/issues/1782
                # (I also don't know why the TYPE_NONE check in the previous clause is there but I can't find a ref for
                # that. they are probably related.)
                continue
            if not reloc.resolved:
                # This is a hack, effectively to support Binary Ninja, which doesn't provide access to dependency
                # library names. The backend creates the Relocation objects, but leaves them unresolved so that
                # we can try to guess them here. Once the Binary Ninja API starts supplying the dependencies,
                # The if/else, along with Project._guess_simprocedure() can be removed if it has no other utility,
                # just leave behind the 'unresolved' debug statement from the else clause.
                if reloc.owner.guess_simprocs:
                    l.debug("Looking for matching SimProcedure for unresolved %s from %s with hint %s",
                            func.name, reloc.owner, reloc.owner.guess_simprocs_hint)
                    self._guess_simprocedure(func, reloc.owner.guess_simprocs_hint)
                else:
                    l.debug("Ignoring unresolved import '%s' from %s ...?", func.name, reloc.owner)
                continue
            export = reloc.resolvedby
            if self.is_hooked(export.rebased_addr):
                l.debug("Already hooked %s (%s)", export.name, export.owner)
                continue

            # Step 2.2: If this function has been resolved by a static dependency,
            # check if we actually can and want to replace it with a SimProcedure.
            # We opt out of this step if it is blacklisted by ignore_functions, which
            # will cause it to be replaced by ReturnUnconstrained later.
            if export.owner is not self.loader._extern_object and \
                    export.name not in self._ignore_functions:
                if self._check_user_blacklists(export.name):
                    continue
                owner_name = export.owner.provides
                if isinstance(self.loader.main_object, cle.backends.pe.PE):
                    owner_name = owner_name.lower()
                if owner_name not in SIM_LIBRARIES:
                    continue
                sim_lib = SIM_LIBRARIES[owner_name]
                if not sim_lib.has_implementation(export.name):
                    continue
                l.info("Using builtin SimProcedure for %s from %s", export.name, sim_lib.name)
                self.hook_symbol(export.rebased_addr, sim_lib.get(export.name, sim_proc_arch))

            # Step 2.3: If 2.2 didn't work, check if the symbol wants to be resolved
            # by a library we already know something about. Resolve it appropriately.
            # Note that _check_user_blacklists also includes _ignore_functions.
            # An important consideration is that even if we're stubbing a function out,
            # we still want to try as hard as we can to figure out where it comes from
            # so we can get the calling convention as close to right as possible.
            elif reloc.resolvewith is not None and reloc.resolvewith in SIM_LIBRARIES:
                sim_lib = SIM_LIBRARIES[reloc.resolvewith]
                if self._check_user_blacklists(export.name):
                    if not func.is_weak:
                        l.info("Using stub SimProcedure for unresolved %s from %s", func.name, sim_lib.name)
                        self.hook_symbol(export.rebased_addr, sim_lib.get_stub(export.name, sim_proc_arch))
                else:
                    l.info("Using builtin SimProcedure for unresolved %s from %s", export.name, sim_lib.name)
                    self.hook_symbol(export.rebased_addr, sim_lib.get(export.name, sim_proc_arch))

            # Step 2.4: If 2.3 didn't work (the symbol didn't request a provider we know of), try
            # looking through each of the SimLibraries we're using to resolve unresolved
            # functions. If any of them know anything specifically about this function,
            # resolve it with that. As a final fallback, just ask any old SimLibrary
            # to resolve it.
            elif missing_libs:
                for sim_lib in missing_libs:
                    if sim_lib.has_metadata(export.name):
                        if self._check_user_blacklists(export.name):
                            if not func.is_weak:
                                l.info("Using stub SimProcedure for unresolved %s from %s", export.name, sim_lib.name)
                                self.hook_symbol(export.rebased_addr, sim_lib.get_stub(export.name, sim_proc_arch))
                        else:
                            l.info("Using builtin SimProcedure for unresolved %s from %s", export.name, sim_lib.name)
                            self.hook_symbol(export.rebased_addr, sim_lib.get(export.name, sim_proc_arch))
                        break
                else:
                    if not func.is_weak:
                        l.info("Using stub SimProcedure for unresolved %s", export.name)
                        the_lib = missing_libs[0]
                        if export.name and export.name.startswith("_Z"):
                            # GNU C++ name. Use a C++ library to create the stub
                            if 'libstdc++.so' in SIM_LIBRARIES:
                                the_lib = SIM_LIBRARIES['libstdc++.so']
                            else:
                                l.critical("Does not find any C++ library in SIM_LIBRARIES. We may not correctly "
                                           "create the stub or resolve the function prototype for name %s.", export.name)

                        self.hook_symbol(export.rebased_addr, the_lib.get(export.name, sim_proc_arch))

            # Step 2.5: If 2.4 didn't work (we have NO SimLibraries to work with), just
            # use the vanilla ReturnUnconstrained, assuming that this isn't a weak func
            elif not func.is_weak:
                l.info("Using stub SimProcedure for unresolved %s", export.name)
                self.hook_symbol(export.rebased_addr, SIM_PROCEDURES['stubs']['ReturnUnconstrained'](display_name=export.name, is_stub=True))
def _register_object ( self , obj , sim_proc_arch ) : # Step 1: get the set of libraries we are allowed to use to resolve unresolved symbols missing_libs = [ ] for lib_name in self . loader . missing_dependencies : try : missing_libs . append ( SIM_LIBRARIES [ lib_name ] ) except KeyError : l . info ( "There are no simprocedures for missing library %s :(" , lib_name ) # additionally provide libraries we _have_ loaded as a fallback fallback # this helps in the case that e.g. CLE picked up a linux arm libc to satisfy an android arm binary for lib in self . loader . all_objects : if lib . provides in SIM_LIBRARIES : simlib = SIM_LIBRARIES [ lib . provides ] if simlib not in missing_libs : missing_libs . append ( simlib ) # Step 2: Categorize every "import" symbol in each object. # If it's IGNORED, mark it for stubbing # If it's blacklisted, don't process it # If it matches a simprocedure we have, replace it for reloc in obj . imports . values ( ) : # Step 2.1: Quick filter on symbols we really don't care about func = reloc . symbol if func is None : continue if not func . is_function and func . type != cle . backends . symbol . SymbolType . TYPE_NONE : continue if func . resolvedby is None : # I don't understand the binary which made me add this case. If you are debugging and see this comment, # good luck. # ref: https://github.com/angr/angr/issues/1782 # (I also don't know why the TYPE_NONE check in the previous clause is there but I can't find a ref for # that. they are probably related.) continue if not reloc . resolved : # This is a hack, effectively to support Binary Ninja, which doesn't provide access to dependency # library names. The backend creates the Relocation objects, but leaves them unresolved so that # we can try to guess them here. Once the Binary Ninja API starts supplying the dependencies, # The if/else, along with Project._guess_simprocedure() can be removed if it has no other utility, # just leave behind the 'unresolved' debug statement from the else clause. if reloc . owner . guess_simprocs : l . debug ( "Looking for matching SimProcedure for unresolved %s from %s with hint %s" , func . name , reloc . owner , reloc . owner . guess_simprocs_hint ) self . _guess_simprocedure ( func , reloc . owner . guess_simprocs_hint ) else : l . debug ( "Ignoring unresolved import '%s' from %s ...?" , func . name , reloc . owner ) continue export = reloc . resolvedby if self . is_hooked ( export . rebased_addr ) : l . debug ( "Already hooked %s (%s)" , export . name , export . owner ) continue # Step 2.2: If this function has been resolved by a static dependency, # check if we actually can and want to replace it with a SimProcedure. # We opt out of this step if it is blacklisted by ignore_functions, which # will cause it to be replaced by ReturnUnconstrained later. if export . owner is not self . loader . _extern_object and export . name not in self . _ignore_functions : if self . _check_user_blacklists ( export . name ) : continue owner_name = export . owner . provides if isinstance ( self . loader . main_object , cle . backends . pe . PE ) : owner_name = owner_name . lower ( ) if owner_name not in SIM_LIBRARIES : continue sim_lib = SIM_LIBRARIES [ owner_name ] if not sim_lib . has_implementation ( export . name ) : continue l . info ( "Using builtin SimProcedure for %s from %s" , export . name , sim_lib . name ) self . hook_symbol ( export . rebased_addr , sim_lib . get ( export . name , sim_proc_arch ) ) # Step 2.3: If 2.2 didn't work, check if the symbol wants to be resolved # by a library we already know something about. Resolve it appropriately. # Note that _check_user_blacklists also includes _ignore_functions. # An important consideration is that even if we're stubbing a function out, # we still want to try as hard as we can to figure out where it comes from # so we can get the calling convention as close to right as possible. elif reloc . resolvewith is not None and reloc . resolvewith in SIM_LIBRARIES : sim_lib = SIM_LIBRARIES [ reloc . resolvewith ] if self . _check_user_blacklists ( export . name ) : if not func . is_weak : l . info ( "Using stub SimProcedure for unresolved %s from %s" , func . name , sim_lib . name ) self . hook_symbol ( export . rebased_addr , sim_lib . get_stub ( export . name , sim_proc_arch ) ) else : l . info ( "Using builtin SimProcedure for unresolved %s from %s" , export . name , sim_lib . name ) self . hook_symbol ( export . rebased_addr , sim_lib . get ( export . name , sim_proc_arch ) ) # Step 2.4: If 2.3 didn't work (the symbol didn't request a provider we know of), try # looking through each of the SimLibraries we're using to resolve unresolved # functions. If any of them know anything specifically about this function, # resolve it with that. As a final fallback, just ask any old SimLibrary # to resolve it. elif missing_libs : for sim_lib in missing_libs : if sim_lib . has_metadata ( export . name ) : if self . _check_user_blacklists ( export . name ) : if not func . is_weak : l . info ( "Using stub SimProcedure for unresolved %s from %s" , export . name , sim_lib . name ) self . hook_symbol ( export . rebased_addr , sim_lib . get_stub ( export . name , sim_proc_arch ) ) else : l . info ( "Using builtin SimProcedure for unresolved %s from %s" , export . name , sim_lib . name ) self . hook_symbol ( export . rebased_addr , sim_lib . get ( export . name , sim_proc_arch ) ) break else : if not func . is_weak : l . info ( "Using stub SimProcedure for unresolved %s" , export . name ) the_lib = missing_libs [ 0 ] if export . name and export . name . startswith ( "_Z" ) : # GNU C++ name. Use a C++ library to create the stub if 'libstdc++.so' in SIM_LIBRARIES : the_lib = SIM_LIBRARIES [ 'libstdc++.so' ] else : l . critical ( "Does not find any C++ library in SIM_LIBRARIES. We may not correctly " "create the stub or resolve the function prototype for name %s." , export . name ) self . hook_symbol ( export . rebased_addr , the_lib . get ( export . name , sim_proc_arch ) ) # Step 2.5: If 2.4 didn't work (we have NO SimLibraries to work with), just # use the vanilla ReturnUnconstrained, assuming that this isn't a weak func elif not func . is_weak : l . info ( "Using stub SimProcedure for unresolved %s" , export . name ) self . hook_symbol ( export . rebased_addr , SIM_PROCEDURES [ 'stubs' ] [ 'ReturnUnconstrained' ] ( display_name = export . name , is_stub = True ) )