From ee697540c3589fbef6fccdd7dd46ad12fe043141 Mon Sep 17 00:00:00 2001 From: Glenn Washburn Date: Sun, 15 Aug 2021 10:23:56 +0000 Subject: [PATCH] Relocate import symbol addresses for loaded PE files Before only the imported symbols of the main PE file were relocated. This mostly worked because the common Windows dlls (eg. kernel32.dll and user32.dll) normally have imported symbols which are already bound, and thus do not need relocating. --- examples/scripts/dllscollector.bat | 12 +++++- qiling/loader/pe.py | 59 +++++++++++++++++++----------- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/examples/scripts/dllscollector.bat b/examples/scripts/dllscollector.bat index 40c9e307c..55117cb73 100644 --- a/examples/scripts/dllscollector.bat +++ b/examples/scripts/dllscollector.bat @@ -22,7 +22,7 @@ reg save hklm\SAM examples\rootfs\x8664_windows\Windows\registry\SAM xcopy /d /y examples\rootfs\x8664_windows\Windows\registry\* examples\rootfs\x86_windows\Windows\registry\ REM -REM Dlls +REM Dlls for x86 tests REM if exist %WINDIR%\SysWOW64\advapi32.dll xcopy /f /y %WINDIR%\SysWOW64\advapi32.dll "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\SysWOW64\rpcrt4.dll xcopy /f /y %WINDIR%\SysWOW64\rpcrt4.dll "examples\rootfs\x86_windows\Windows\System32\" @@ -64,11 +64,17 @@ if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-core-synch-l1-2-0.dll xcopy /f / if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-core-fibers-l1-1-1.dll xcopy /f /y %WINDIR%\SysWOW64\downlevel\api-ms-win-core-fibers-l1-1-1.dll "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-core-localization-l1-2-1.dll xcopy /f /y %WINDIR%\SysWOW64\downlevel\api-ms-win-core-localization-l1-2-1.dll "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-core-sysinfo-l1-2-1.dll xcopy /f /y %WINDIR%\SysWOW64\downlevel\api-ms-win-core-sysinfo-l1-2-1.dll "examples\rootfs\x86_windows\Windows\System32\" +if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll xcopy /f /y %WINDIR%\SysWOW64\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll "examples\rootfs\x86_windows\Windows\System32\" +if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll echo f | xcopy /f /y %WINDIR%\SysWOW64\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll "examples\rootfs\x86_windows\Windows\System32\api-ms-win-core-rtlsupport-l1-2-0.dll" +if exist %WINDIR%\SysWOW64\downlevel\api-ms-win-eventing-provider-l1-1-0.dll xcopy /f /y %WINDIR%\SysWOW64\downlevel\api-ms-win-eventing-provider-l1-1-0.dll "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\SysWOW64\shlwapi.dll xcopy /f /y %WINDIR%\SysWOW64\shlwapi.dll "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\SysWOW64\setupapi.dll xcopy /f /y %WINDIR%\SysWOW64\setupapi.dll "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\System32\ntoskrnl.exe xcopy /f /y %WINDIR%\System32\ntoskrnl.exe "examples\rootfs\x86_windows\Windows\System32\" if exist %WINDIR%\winsxs\amd64_microsoft-windows-printing-xpsprint_31bf3856ad364e35_10.0.17763.194_none_20349c5a971eb293\XpsPrint.dll xcopy /f /y %WINDIR%\winsxs\amd64_microsoft-windows-printing-xpsprint_31bf3856ad364e35_10.0.17763.194_none_20349c5a971eb293\XpsPrint.dll "examples\rootfs\x86_windows\Windows\System32\" +REM +REM Dlls for x8664 tests +REM if exist %WINDIR%\System32\ntoskrnl.exe xcopy /f /y %WINDIR%\System32\ntoskrnl.exe "examples\rootfs\x8664_windows\Windows\System32\" if exist %WINDIR%\System32\advapi32.dll xcopy /f /y %WINDIR%\System32\advapi32.dll "examples\rootfs\x8664_windows\Windows\System32\" if exist %WINDIR%\System32\kernel32.dll xcopy /f /y %WINDIR%\System32\kernel32.dll "examples\rootfs\x8664_windows\Windows\System32\" @@ -84,6 +90,10 @@ if exist %WINDIR%\System32\downlevel\api-ms-win-crt-runtime-l1-1-0.dll xcopy /f if exist %WINDIR%\System32\downlevel\api-ms-win-crt-math-l1-1-0.dll xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-crt-math-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\" if exist %WINDIR%\System32\downlevel\api-ms-win-crt-locale-l1-1-0.dll xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-crt-locale-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\" if exist %WINDIR%\System32\downlevel\api-ms-win-crt-heap-l1-1-0.dll xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-crt-heap-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\" +if exist %WINDIR%\System32\downlevel\api-ms-win-core-apiquery-l1-1-0.dll xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-core-apiquery-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\" +if exist %WINDIR%\System32\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\" +if exist %WINDIR%\System32\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll echo f | xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-core-rtlsupport-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\api-ms-win-core-rtlsupport-l1-2-0.dll" +if exist %WINDIR%\System32\downlevel\api-ms-win-eventing-provider-l1-1-0.dll xcopy /f /y %WINDIR%\System32\downlevel\api-ms-win-eventing-provider-l1-1-0.dll "examples\rootfs\x8664_windows\Windows\System32\" if exist %WINDIR%\System32\vcruntime140d.dll xcopy /f /y %WINDIR%\System32\vcruntime140d.dll "examples\rootfs\x8664_windows\Windows\System32\" if exist %WINDIR%\System32\ucrtbased.dll xcopy /f /y %WINDIR%\System32\ucrtbased.dll "examples\rootfs\x8664_windows\Windows\System32\" diff --git a/qiling/loader/pe.py b/qiling/loader/pe.py index a292c591e..fc13b1b09 100644 --- a/qiling/loader/pe.py +++ b/qiling/loader/pe.py @@ -193,6 +193,10 @@ def load_dll(self, name: bytes, driver: bool = False) -> int: # add DLL to coverage images self.images.append(Image(dll_base, dll_base + dll_len, path)) + if not cached or not loaded: + # parse directory entry import + self.init_imports(dll, driver) + self.ql.log.info(f'Done with loading {path}') return dll_base @@ -339,6 +343,39 @@ def add_ldr_data_table_entry(self, dll_name): self.ldr_list.append(ldr_table_entry) + def init_imports(self, pe, driver): + if pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']].VirtualAddress != 0: + self.pe.full_load() + else: + return + + for entry in pe.DIRECTORY_ENTRY_IMPORT: + dll_loaded = False + dll_name = str(entry.dll.lower(), 'utf-8', 'ignore') + for imp in entry.imports: + if imp.bound: + continue + + # Only load dll if encounter unbound symbol + if not dll_loaded: + self.load_dll(entry.dll, driver) + dll_loaded == True + + if imp.name: + try: + addr = self.import_address_table[dll_name][imp.name] + except KeyError: + self.ql.log.debug(f"Error in loading function {dll_name}.{imp.name.decode()}") + continue + else: + addr = self.import_address_table[dll_name][imp.ordinal] + + if self.ql.archtype == QL_ARCH.X86: + address = self.ql.pack32(addr) + else: + address = self.ql.pack64(addr) + self.ql.mem.write(imp.address, address) + def init_exports(self): if self.ql.code: return @@ -628,27 +665,7 @@ def load(self): for each in sys_dlls: super().load_dll(each, self.is_driver) # parse directory entry import - if self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']].VirtualAddress != 0: - for entry in self.pe.DIRECTORY_ENTRY_IMPORT: - dll_name = str(entry.dll.lower(), 'utf-8', 'ignore') - super().load_dll(entry.dll, self.is_driver) - for imp in entry.imports: - # fix IAT - # ql.log.info(imp.name) - # ql.log.info(self.import_address_table[imp.name]) - if imp.name: - try: - addr = self.import_address_table[dll_name][imp.name] - except KeyError: - self.ql.log.debug("Error in loading function %s" % imp.name.decode()) - else: - addr = self.import_address_table[dll_name][imp.ordinal] - - if self.ql.archtype == QL_ARCH.X86: - address = self.ql.pack32(addr) - else: - address = self.ql.pack64(addr) - self.ql.mem.write(imp.address, address) + super().init_imports(self.pe, self.is_driver) self.ql.log.debug("Done with loading %s" % self.path) self.ql.os.entry_point = self.entry_point