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?
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