CodeExplorer Posted December 19, 2023 Posted December 19, 2023 (edited) How to resolve forwarded import programmatically? I need general concept. They are some forwarded imports: [4274]=773D3660 ntdll.dll NtdllDefWindowProc_A user32.DefWindowProcA ->ntdll.dll NtdllDefWindowProc_A I need to get it back ntdll.dll NtdllDefWindowProc_A -> user32.DefWindowProcA Scylla does a quite great job on this, I've looked at source code but I can't understand it. Edited December 20, 2023 by CodeExplorer 1
Nacho_dj Posted December 20, 2023 Posted December 20, 2023 Basically: You have to analyze the export table of the forwarder module (user32.dll in your case). If the exported function address points to an internal routine, that routine is the exported function. If the exported function address is a pointer to a string (NTDLL.NtdllDefWindowProc_A in your case), it is indicating the system to search in the module NTDLL.DLL the exported function NtdllDefWindowProc_A. So, this is a forwarded function. Cheers! Nacho_dj
jackyjask Posted December 20, 2023 Posted December 20, 2023 when loader resolve for example kernel32.DecodePointer from some PE import - it views that it points to some address inside IMAGE_EXPORT_DIRECTORY of kernel32.dll - this is so called forwarded export. loader in this case understands that kernel32.DecodePointer point not to code, but to string in form somedll.somefunction or in form somedll.#someordinal as result loader is try load somedll and search for somefunction by name or for someordinal by ordinal. this search how you can view can (and in case forward exports was) recursive. it stops when we finally got function address not inside IMAGE_EXPORT_DIRECTORY - this address and will be stored in IAT or process fail - we not found dll/or export in this dll. 1
CodeExplorer Posted December 20, 2023 Author Posted December 20, 2023 I have a question: should we always resolve Api as fowarded import?
Nacho_dj Posted December 20, 2023 Posted December 20, 2023 Theoretically, you could build an import table without resolving forwarding. Probably you would get more modules in the import table than original executable/dll had. In the older systems previous to NT, such as W98, NTDLL.DLL couldn't appear in any import table, so you had to resolve forwarding to get a compliant import table. If you are rebuilding any dumped file (executable/dll) trying to get the most similar rebuilt file to the original unprotected, resolving forwarding should be perfomed for sure. 2
CodeExplorer Posted December 20, 2023 Author Posted December 20, 2023 I've also notice the presence of: [82A0]=7721B29D combase.dll CoCreateInstance https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance So this has to be ole32.CoCreateInstance is forwarded back to api-ms-win-core-com-l1-1-0.CoCreateInstance not combase.dll CoCreateInstance Scylla doesn't resolve this import to ole32.CoCreateInstance [82A4]=7722B378 combase.dll IIDFromString ole32.IIDFromString -> api-ms-win-core-com-l1-1-0.IIDFromString Scylla resolve this import to ole32.IIDFromString Know somebody what's going on? Or how to fix this issue?
atom0s Posted December 20, 2023 Posted December 20, 2023 Things like combase.dll are a newer lower-level binary that Micorosft introduced in Windows 7. You can read about that here: https://learn.microsoft.com/en-us/windows/win32/win7appqual/new-low-level-binaries?redirectedfrom=MSDN Basically it creates a forwarding chain with the additional other newer libraries such as the ones that start with "api-ms-win" and so on. There's a blog post series that covers that new change since Windows 7 here: https://blog.quarkslab.com/runtime-dll-name-resolution-apisetschema-part-i.html https://blog.quarkslab.com/runtime-dll-name-resolution-apisetschema-part-ii.html And another here: https://www.geoffchappell.com/studies/windows/win32/apisetschema/index.htm And some other additional readings on the newer umbrella libraries here: https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets https://www.nirsoft.net/articles/windows_7_kernel_architecture_changes.html Here's a tool to help view the API sets as well: https://github.com/zodiacon/ApiSetView
CodeExplorer Posted December 20, 2023 Author Posted December 20, 2023 Thank you. It seems to be Api Set: https://www.unknowncheats.me/forum/general-programming-and-reversing/601629-resolve-apiset-dll-import.html Unfortunately https://github.com/zodiacon/ApiSetView give access violation on running.
atom0s Posted December 20, 2023 Posted December 20, 2023 1 hour ago, CodeExplorer said: Thank you. It seems to be Api Set: https://www.unknowncheats.me/forum/general-programming-and-reversing/601629-resolve-apiset-dll-import.html Unfortunately https://github.com/zodiacon/ApiSetView give access violation on running. Here's ApiSetView compiled with latest VS2022. Fresh clone of the repo, no modifications. ApiSetView.zip 1
CodeExplorer Posted December 21, 2023 Author Posted December 21, 2023 Thanks for trying to help me. The exe you shared is x64, I am running 32 bit version of Windows. Anyway won't work since I am running Windows 8.1. For what version of Windows this suppose to work? What version of Windows are you running? For Windows 8.1 is this structure: https://www.unknowncheats.me/forum/general-programming-and-reversing/102204-win8-1-api-set-map.html There is a strange thing: OSVERSIONINFO os; ZeroMemory(&os, sizeof(OSVERSIONINFO)); os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&os); will return minor version as 2 not 3 like a have. Checked with command prompt Ver command and I have windows version 6.3. https://learn.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version Crap: Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). I've solved it by calling RtlGetVersion api.
jackyjask Posted December 21, 2023 Posted December 21, 2023 yeah, same thing over here - x64, silently crashing on start some dump zoom in: 1
CodeExplorer Posted December 21, 2023 Author Posted December 21, 2023 (edited) I found target OS for the ApiSetView it is Windows 10 API_SET_NAMESPACE* apiSetNamespace = static_cast<API_SET_NAMESPACE*>(peb_addr->ApiSetMap); ULONG Version = apiSetNamespace->Version; else if (Version==6) GetApiSetWindows10(peb_addr); Version = 4 is for Windows 8.1. here is API_SET_SCHEMA versions: https://github.com/ajkhoury/ApiSet/blob/master/apiset.h Edited December 21, 2023 by CodeExplorer 1
Sean Park - Lovejoy Posted December 21, 2023 Posted December 21, 2023 (edited) The attachment runs well in windows x64 10. Edited December 21, 2023 by windowbase editing some words. 1
jackyjask Posted December 21, 2023 Posted December 21, 2023 the bug resides inside the void ApiSets::Build() method
CodeExplorer Posted December 22, 2023 Author Posted December 22, 2023 15 hours ago, jackyjask said: the bug resides inside the void ApiSets::Build() method the bug is that they are trying to read ApiSet version 6 in any operating system not just on Windows 10. So they aren't checking OS version nor ApiSet version. ApiSet are available starting with Windows 7; Windows 7 ApiSet version is 2. https://github.com/ajkhoury/ApiSet/blob/master/apiset.h they are mistaken on ApiSet Version 4 - Windows 8.1 I can't find in https://github.com/ajkhoury/ApiSet/blob/master/apiset.h any difference between ApiSet version 3 and ApiSet version 2 1 1
CodeExplorer Posted December 22, 2023 Author Posted December 22, 2023 (edited) Windows 8 has same ApiSet Version as Windows 7 - version 2 Not as I thought. In Windows 10 is something strange: api-ms-win-core-com-l1-1-0 -> forwarded dll name is in fact: api-ms-win-core-com-l1-1-1 -> dll name from Api Set Edited December 22, 2023 by CodeExplorer
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now