c++windbggetprocaddress

How to find the proc name for `GetProcAddress` function using WinDbg


I want to use GetProcAddress to get some functions addresses inside a loaded DLL. I run some attempts on PSAPI library and I can see the the expected proc name is not identical to the symbol names I find with WinDbg x statements. For example, I look for "EnumProcessModules"(which is the name expected by GetProcAddress method) with x psapi!*EnumProcessModules* and I find

00007ff9`fe112210 PSAPI!_imp_K32EnumProcessModulesEx = <no type information>
00007ff9`fe111360 PSAPI!EnumProcessModulesExStub (<no parameter info>)
00007ff9`fe111030 PSAPI!EnumProcessModulesStub (<no parameter info>)
00007ff9`fe1121a8 PSAPI!_imp_K32EnumProcessModules = <no type information>

When I provide any of the found symbols above (with or without "PSAPI!" as a prefix) to the GetProcAddress method as the second parameter (procName) - it returns NULL, but when I use the method name "EnumProcessModules" - it returns 0xfe111030, which is the address of "PSAPI!EnumProcessModulesStub".

How could I know the expected procName in advance? What if I have 2 different classes or namespaces with the same method name in one DLL? How can I distinguish between the two method names when I call GetProcAddress?


Solution

  • PSAPI! is just a prefix, it's the DLL name printed by WinDbg. That's used to disambiguate names. A clear example why this is useful: you will have many DllMain's in your process.

    The expected name for GetProcAddress is the documented name of the function, as stated on MSDN. Keep in mind that you will need to add either the A or W suffix when MSDN states both versions are available. E.g. you can't call GetProcAddress with "GetDeviceDriverFileName", you need either "GetDeviceDriverFileNameA" or L"GetDeviceDriverFileNameW".

    For non-system DLL's, you need the function name from the Export Address Table.

    Background: What you see in WinDbg is the name from the .PDB, which as you have discovered can differ from the exported name. There is nothing which enforces a relation between the two. For instance, it's technically possible to have PDB names Foo and Bar, and have them swapped in the Export Address Table. More realistically, Microsoft may internally add an _wrapper_EnumProcessModules at any time, but the documented and exported name will stay EnumProcessModules.