Search code examples
pythonportable-executableimport-table

How can I resolve the forwarded API from the IAT on PE?


Hi I'm trying to make a Import table builder in python script just like MacT's Import Reconstructor.

But I have a trouble to find out the method to get an original API information from the forwarded API.

For instance, I got a "ntdll!RtlDecodePointer" from IAT but It's forwarded from the "kernel32!DecodePointer" and I have no ideas to find it out.

Should I have to search through every single loaded modules' ForwarderChain in Import directory?


Solution

  • no, ForwarderChain in Import directory unrelated to this.

    when loader resolve kernel32.DecodePointer from some PE import - it view that it point to some address inside IMAGE_EXPORT_DIRECTORY of kernel32.dll - this is so called forwarded export. loader in this case understand 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 stopped 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.

    note that deliminator here (between dll and function name - not ! but .) interesting question - what be if somedll containing . in own name - say my.x64.dll. old version of windows incorrect process names like this (my.x64.dll.somefunc) because it search first . in string by strchr - so will be search x64.dll.somefunc in my dll and fail. but now this is fixed - loader use strrchr - he search for last . in string.

    as result yearly we can not specify full dll name with extension -

    #pragma comment(linker, "/export:fn=kernel32.dll.DecodePointer");
    GetProcAddress((HMODULE)&__ImageBase, "fn");
    

    fail say on xp. but now - win10 exactly, may be win8.1 (need check) this is correct and will be work - xp will be search for dll.DecodePointer in kernel32 while win10 search for DecodePointer in kernel32.dll. also from here pointed that early we can not forward export to module without .dll extension, now - no such limitation. (loader by default append .DLL suffix to to loaded library name, if it not containing . - so when call LoadLibrary("my") - actually will be opened and loaded "my.DLL", but for "my." or "my.x64" suffix .DLL will be not appended (. char in name))

    so if return to your concrete example - kernel32.DecodePointer point to something inside IMAGE_EXPORT_DIRECTORY of kernel32.dll . loader read string by this address - NTDLL.RtlDecodePointer - call strrchr (or strchr old versions) on this string for find . and finally load NTDLL -> NTDLL.DLL (suffix added because no . in name) and search for RtlDecodePointer - address found and it not inside IMAGE_EXPORT_DIRECTORY of ntdll.dll - so this is code address. here process stopped and address of RtlDecodePointer stored in initial PE IAT .

    you from own side need repeat loader steps. but here exist one problem in modern os - many strings is begin with API-MS-* dlls names. this is not real dll but The API Set Schema - undocumented and mutable way, how loader resolve this names