コード例 #1
0
 def read_libraries(self):
     for path in os.scandir(self.basedir):
         if not path.is_file():
             continue
         fullpath = os.path.join(self.basedir, path.name)
         try:
             lib = Library(fullpath)
         except (ELFError, OSError) as err:
             logging.error('\'%s\' => %s', path, err)
             continue
         lib.parse_functions(release=True)
         logging.debug('Adding %s', lib.fullname)
         self.libraries.append(lib)
コード例 #2
0
ファイル: test_library.py プロジェクト: rupran/librarytrader
    def test_6_propagate_calls_loaderlike(self):
        store = LibraryStore()
        bin1 = Library(os.path.abspath(TEST_LL))
        bin1a = Library(os.path.abspath(TEST_LL1A))
        bin2 = Library(os.path.abspath(TEST_LL2))

        # Save possibly set LD_LIBRARY_PATH
        backup = None
        if 'LD_LIBRARY_PATH' in os.environ:
            backup = os.environ['LD_LIBRARY_PATH']

        # Set LD_LIBRARY_PATH and resolve libraries
        os.environ['LD_LIBRARY_PATH'] = '$ORIGIN/'
        for binary in (bin1, bin1a, bin2):
            store.resolve_libs_recursive(binary)

        resolve_calls(store)
        store.resolve_all_functions_from_binaries()

        # Possibly restore LD_LIBRARY_PATH
        if backup:
            os.environ['LD_LIBRARY_PATH'] = backup
        else:
            del os.environ['LD_LIBRARY_PATH']

        lib1 = bin1.needed_libs['lib1.so']
        lib2 = store[lib1].needed_libs['lib2.so']
        # Check if the weak definition of 'wfunc' in 'lib2.so' is not used by
        # 'lib1.so' but overridden by the strong definition in 'bin'
        self.assertIn(lib1, store[bin1.fullname].get_users_by_name('wfunc'))
        self.assertNotIn(bin1.fullname, store[lib2].get_users_by_name('wfunc'))
        self.assertNotIn(lib1, store[lib2].get_users_by_name('wfunc'))
        # However, 'bin1a' and 'lib1a.so' should appear for 'wfunc' in 'lib2.so'
        # as bin1a does not override 'wfunc' itself
        lib1a = bin1a.needed_libs['lib1a.so']
        self.assertIn(bin1a.fullname, store[lib2].get_users_by_name('wfunc'))
        self.assertIn(lib1a, store[lib2].get_users_by_name('wfunc'))
        # Check that the weak definition in 'bin2' is only marked as external
        # but the use is actually overriden by the one in 'lib2.so'
        self.assertSetEqual(store[bin2.fullname].get_users_by_name('one_more'),
                            set(['TOPLEVEL']))
        # Check if the deepest transitively called functions has all binaries
        # as their user
        lib3 = store[lib2].needed_libs['lib3.so']
        for binary in (bin1, bin1a, bin2):
            self.assertIn(binary.fullname,
                          store[lib3].get_users_by_name('deeper'))
コード例 #3
0
ファイル: test_library.py プロジェクト: rupran/librarytrader
def create_store_and_lib(libpath=TEST_LIBRARY,
                         parse=False,
                         resolve_libs_recursive=False,
                         call_resolve=False):
    store = LibraryStore(ldconfig_file=LDCONFIG_FILE)
    lib = Library(os.path.abspath(libpath), parse=parse)
    if resolve_libs_recursive:
        store.resolve_libs_recursive(lib)
    if call_resolve:
        resolve_calls(store)
    return store, lib
コード例 #4
0
def map_wrapper(input_tuple):
    path, start, size = input_tuple
    try:
        if isinstance(path, str):
            lib = Library(path, parse=True)
        else:
            lib = path
            lib.fd = open(lib.fullname, 'rb')
    except Exception as err:
        logging.error('%s: %s', lib.fullname, err)
        return (None, -1, None, None, None, None, None, None, None, None, None,
                0)

    internal_calls, external_calls, local_calls, indirect_calls, \
        imported_uses, exported_uses, local_uses, dlsym_refs, \
        dlopen_refs, duration = resolve_calls_in_library(lib, start, size)
    lib.fd.close()
    del lib.fd
    return (lib.fullname, start, internal_calls, external_calls, local_calls,
            indirect_calls, imported_uses, exported_uses, local_uses,
            dlsym_refs, dlopen_refs, duration)
コード例 #5
0
ファイル: test_library.py プロジェクト: rupran/librarytrader
    def test_7_store_load(self):
        store, binary = create_store_and_lib(TEST_BINARY,
                                             resolve_libs_recursive=True,
                                             call_resolve=True)
        lib = Library(os.path.abspath(TEST_LIBRARY))

        resolved_functions = store.resolve_all_functions(all_entries=True)
        store.propagate_call_usage(all_entries=True)

        # Create a temporary file, close it (we only need the path) and dump
        fd, name = tempfile.mkstemp()
        os.close(fd)
        store.dump(name)

        # Reload into an empty store
        new_store = LibraryStore(ldconfig_file=LDCONFIG_FILE)
        new_store.load(name)

        # The file is no longer needed, delete it
        os.remove(name)

        # Assert restoration of store
        self.assertEqual(store.keys(), new_store.keys())
        self.assertIn(lib.fullname, new_store.keys())
        self.assertIn(binary.fullname, new_store.keys())

        # Assert restoration of needed_libs
        self.assertIn(lib.fullname,
                      new_store[binary.fullname].needed_libs.values())

        lib = new_store[lib.fullname]
        # Assert restoration of calls
        self.assertIn(binary.fullname, lib.get_users_by_name('external'))
        self.assertIn(binary.fullname,
                      lib.get_users_by_name('external_caller'))
        self.assertIn(binary.fullname,
                      lib.get_users_by_name('second_level_caller'))
コード例 #6
0
ファイル: librarystore.py プロジェクト: rupran/librarytrader
    def _get_or_create_library(self, path):
        link_path = None

        try:
            if os.path.islink(path) or \
                    os.path.abspath(os.path.dirname(path)) != \
                    os.path.realpath(os.path.abspath(os.path.dirname(path))):
                link_path = path
                path = os.path.realpath(path)

            path = os.path.abspath(path)
            if path in self:
                return (self.get_from_path(path), link_path)

            return (Library(path), link_path)
        except (ELFError, OSError) as err:
            logging.error('\'%s\' => %s', path, err)
            return (None, None)
コード例 #7
0
ファイル: test_library.py プロジェクト: rupran/librarytrader
    def test_6_propagate_calls_exec_only(self):
        store, binary = create_store_and_lib(TEST_BINARY,
                                             resolve_libs_recursive=True,
                                             call_resolve=True)
        libpath = os.path.abspath(TEST_LIBRARY)
        not_imported = Library(os.path.abspath(TEST_EXECONLY))
        store.resolve_libs_recursive(not_imported)

        store.resolve_all_functions(all_entries=False)
        store.propagate_call_usage(all_entries=False)
        # Check if all transitively called functions have the binary as their user
        self.assertIn(binary.fullname,
                      store[libpath].get_users_by_name('external'))
        self.assertIn(binary.fullname,
                      store[libpath].get_users_by_name('external_caller'))
        self.assertIn(binary.fullname,
                      store[libpath].get_users_by_name('second_level_caller'))
        # In this case, the library not imported from TEST_BINARY should not
        # show up as a user of TEST_LIBRARY
        self.assertNotIn(not_imported.fullname,
                         store[libpath].get_users_by_name('external'))
コード例 #8
0
ファイル: test_library.py プロジェクト: rupran/librarytrader
    def test_6_propagate_calls_all_entries(self):
        store, binary = create_store_and_lib(TEST_BINARY,
                                             resolve_libs_recursive=True,
                                             call_resolve=True)
        libpath = os.path.abspath(TEST_LIBRARY)
        not_imported = Library(os.path.abspath(TEST_EXECONLY))
        store.resolve_libs_recursive(not_imported)

        store.resolve_all_functions(all_entries=True)
        store.propagate_call_usage(all_entries=True)
        # Check if all transitively called functions have the binary as their user
        self.assertIn(binary.fullname,
                      store[libpath].get_users_by_name('external'))
        self.assertIn(binary.fullname,
                      store[libpath].get_users_by_name('external_caller'))
        self.assertIn(binary.fullname,
                      store[libpath].get_users_by_name('second_level_caller'))
        # If we use all libraries in the store as entry points for the
        # resolution, TEST_EXECONLY should show up as a user of 'external' in
        # TEST_LIBRARY
        self.assertIn(not_imported.fullname,
                      store[libpath].get_users_by_name('external'))
コード例 #9
0
ファイル: test_library.py プロジェクト: rupran/librarytrader
 def test_0_find_export(self):
     libc = Library(os.path.abspath(TEST_LIBC), parse=True)
     versioned_addr = libc.find_export('malloc@@GLIBC_2.2.5')
     unversioned_addr = libc.find_export('malloc')
     self.assertEqual(versioned_addr, unversioned_addr)
コード例 #10
0
ファイル: librarystore.py プロジェクト: rupran/librarytrader
    def load(self, input_file):
        self.reset()

        logging.debug('loading input from \'%s\'...', input_file)
        with open(input_file, 'r') as infd:
            in_dict = json.load(infd)
            for path, content in in_dict.items():
                logging.debug("loading %s -> %s", path, content["type"])
                if content["type"] == "link":
                    self._add_library(path, content["target"])
                else:
                    library = Library(path, load_elffile=False)
                    def load_dict_with_set_values(from_dict, library, name, convert_key=None):
                        for key, value in from_dict.get(name, {}).items():
                            key = convert_key(key) if convert_key else key
                            getattr(library, name)[key] = set(value)
                    def load_ordered_dict_from_list(from_dict, library, name):
                        # Recreate order from list
                        for key, value in from_dict.get(name, []):
                            getattr(library, name)[key] = value

                    library.entrypoint = content["entrypoint"]
                    library.e_machine = content.get("e_machine", None)
                    library.ei_class = content.get("ei_class", None)
                    library.imports = content.get("imports", {})
                    load_ordered_dict_from_list(content, library, "exported_names")
                    library.exported_addrs = collections.defaultdict(list)
                    for name, addr in library.exported_names.items():
                        library.exported_addrs[addr].append(name)
                    library.export_bind = content["export_bind"]
                    load_dict_with_set_values(content, library, "export_users", int)
                    for key in library.exported_addrs.keys():
                        if key not in library.export_users:
                            library.export_users[key] = set()
                    load_ordered_dict_from_list(content, library, "imports_plt")
                    load_ordered_dict_from_list(content, library, "exports_plt")
                    load_ordered_dict_from_list(content, library, "needed_libs")
                    load_ordered_dict_from_list(content, library, "all_imported_libs")
                    library.rpaths = content.get("rpaths", [])
                    library.runpaths = content.get("runpaths", [])
                    load_dict_with_set_values(content, library, "internal_calls", int)
                    load_dict_with_set_values(content, library, "external_calls", int)
                    library.local_functions = collections.defaultdict(list)
                    for addr, names in content.get("local_functions", {}).items():
                        library.local_functions[int(addr)] = names
                    load_dict_with_set_values(content, library, "local_calls", int)
                    load_dict_with_set_values(content, library, "local_users", int)

                    load_ordered_dict_from_list(content, library, "exported_objs")
                    load_ordered_dict_from_list(content, library, "exported_obj_names")
                    load_ordered_dict_from_list(content, library, "imported_objs")
                    load_ordered_dict_from_list(content, library, "imported_objs_locations")
                    load_ordered_dict_from_list(content, library, "local_objs")
                    load_dict_with_set_values(content, library, "object_to_functions", int)
                    load_dict_with_set_values(content, library, "object_to_objects", int)
                    load_dict_with_set_values(content, library, "export_object_refs", int)
                    load_dict_with_set_values(content, library, "local_object_refs", int)
                    load_dict_with_set_values(content, library, "import_object_refs", int)
                    load_dict_with_set_values(content, library, "object_users", int)
                    load_ordered_dict_from_list(content, library, "reloc_to_local")
                    load_ordered_dict_from_list(content, library, "reloc_to_exported")
                    load_dict_with_set_values(content, library, "dlsym_refs", int)
                    load_dict_with_set_values(content, library, "dlopen_refs", int)
                    library.init_functions = content.get("init_functions", [])
                    library.fini_functions = content.get("fini_functions", [])

                    library.ranges = {int(key):value for key, value in content.get("ranges", {}).items()}
                    library.object_ranges = {int(key):value for key, value in content.get("object_ranges", {}).items()}
                    #print('{}: {}'.format(path, sorted(["calls"].items())))
                    library.defines_versions = content.get("defines_versions", False)
                    library.version_descriptions = content.get("version_descriptions", {})
                    library.parse_time = float(content.get("parse_time", 0))
                    library.total_disas_time = float(content.get("total_disas_time", 0))
                    library.external_debug_file = content.get("external_debug_file", None)
                    library.interpreter = content.get("interpreter", None)
                    self._add_library(path, library)

        logging.debug('... done with %s entries', len(self))