Jump to content
Tuts 4 You

Resolve forwarded import???


CodeExplorer

Recommended Posts

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 by CodeExplorer
  • Like 1
Link to comment
  • The title was changed to Resolve fowarded import???

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

 

Link to comment

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.

  • Like 1
Link to comment

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. ;)

  • Like 2
Link to comment
  • The title was changed to Resolve forwarded import???

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?
 

Link to comment

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

Link to comment

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.
 

Link to comment

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 by CodeExplorer
  • Like 1
Link to comment
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
 

  • Like 1
  • Thanks 1
Link to comment

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 by CodeExplorer
Link to comment

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...