MCPcopy Create free account
hub / github.com/qilingframework/qiling / init_imports

Method init_imports

qiling/loader/pe.py:616–704  ·  view source on GitHub ↗
(self, pe: pefile.PE, is_driver: bool)

Source from the content-addressed store, hash-verified

614 return pe.OPTIONAL_HEADER.DATA_DIRECTORY[ent].VirtualAddress != 0
615
616 def init_imports(self, pe: pefile.PE, is_driver: bool):
617 if not Process.directory_exists(pe, 'IMAGE_DIRECTORY_ENTRY_IMPORT'):
618 return
619
620 pe.full_load()
621
622 for entry in pe.DIRECTORY_ENTRY_IMPORT:
623 dll_name = entry.dll.decode().casefold()
624 self.ql.log.debug(f'Requesting imports from {dll_name}')
625
626 orig_dll_name = dll_name
627 redirected = False
628
629 if dll_name.startswith('api-ms-win-'):
630 # DLLs starting with this prefix contain no actual code. Instead, the windows loader loads the actual
631 # code from one of the main windows dlls.
632 # see https://github.com/lucasg/Dependencies for correct replacement dlls
633 #
634 # The correct way to find the dll that replaces all symbols from this dll involves using the hashmap
635 # inside of apisetschema.dll (see https://lucasg.github.io/2017/10/15/Api-set-resolution/ ).
636 #
637 # Currently, we use a simpler, more hacky approach, that seems to work in a lot of cases: we just scan
638 # through some key dlls and hope that we find the requested symbols there. some symbols may appear on
639 # more than one dll though; in that case we proceed to the next symbol to see which key dll includes it.
640 #
641 # Note: You might be tempted to load the actual dll (dll_name), because they also contain a reference to
642 # the replacement dll. However, chances are, that these dlls do not exist in the rootfs and maybe they
643 # don't even exist on windows. Therefore this approach is a bad idea.
644
645 # DLLs that seem to contain most of the requested symbols
646 key_dlls = (
647 'kernel32.dll',
648 'ntdll.dll',
649 'kernelbase.dll',
650 'ucrtbase.dll'
651 )
652
653 imports = iter(entry.imports)
654 failed = False
655 fallback = None
656
657 while not redirected and not failed:
658 # find all possible redirection options by scanning key dlls for the current imported symbol
659 imp = next(imports, None)
660 redirection_options = [fallback] if imp is None else [filename for filename in key_dlls if filename in self.import_address_table and imp.name in self.import_address_table[filename]]
661
662 # no redirection options: failed to redirect dll
663 if not redirection_options:
664 failed = True
665
666 # exactly one redirection options: use it
667 elif len(redirection_options) == 1:
668 key_dll = redirection_options[0]
669 redirected = True
670
671 # more than one redirection options: remember one of them and proceed to next symbol
672 else:
673 fallback = redirection_options[-1]

Callers 2

load_dllMethod · 0.95
loadMethod · 0.80

Calls 3

load_dllMethod · 0.95
directory_existsMethod · 0.80
write_ptrMethod · 0.80

Tested by

no test coverage detected