Reputation: 4656
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
?
Upvotes: 1
Views: 1332
Reputation: 9007
The Core Functionality for this API is implemented in kernel32.dll and Named K32EnumProcessModules
in paspi.h header this API is ifdeffed based on PSAPI_VERSION
#ifndef PSAPI_VERSION
#if (NTDDI_VERSION >= NTDDI_WIN7)
#define PSAPI_VERSION 2
#else
#define PSAPI_VERSION 1
#endif
#endif
#if (PSAPI_VERSION > 1)
#define EnumProcessModules K32EnumProcessModules
if you GetProcAddress in psapi.dll you get a stub which gets transferred to kernel32.dll
0:001> u PSAPI!EnumProcessModulesStub l 5
PSAPI!EnumProcessModulesStub:
762d1408 8bff mov edi,edi
762d140a 55 push ebp
762d140b 8bec mov ebp,esp
762d140d 5d pop ebp
762d140e eb05 jmp PSAPI!K32EnumProcessModules (762d1415)
0:001> u 762d1415 l1
PSAPI!K32EnumProcessModules:
762d1415 ff2504102d76 jmp dword ptr [PSAPI!_imp__K32EnumProcessModules (762d1004)]
0:001> u poi(762d1004) l1
kernel32!K32EnumProcessModules:
7668cc52 8bff mov edi,edi
you can use dumpbin /exports on the dll to see if there is any correlation or if there is a name change (see the Stub@16 )
:\>dumpbin /exports c:\windows\System32\psapi.dll | grep -w EnumProcessModules
5 4 00001408 EnumProcessModules = _EnumProcessModulesStub@16
you could also find the same info from the export table of psapi.dll using some thing like below
0:001> .shell -ci "!dh psapi" grep Export
1088 [ 359] address [size] of Export Directory
.shell: Process exited
0:001> dt ole32!_IMAGE_EXPORT_DIRECTORY (psapi + 1088)
+0x000 Characteristics : 0
+0x004 TimeDateStamp : 0x4a5bc026
+0x008 MajorVersion : 0
+0x00a MinorVersion : 0
+0x00c Name : 0x11be
+0x010 Base : 1
+0x014 NumberOfFunctions : 0x1b
+0x018 NumberOfNames : 0x1b
+0x01c AddressOfFunctions : 0x10b0
+0x020 AddressOfNames : 0x111c
+0x024 AddressOfNameOrdinals : 0x1188
0:001> r? $t0 = (int *) @@(psapi + 10b0)
0:001> r? $t1 = (int *) @@(psapi + 111c)
0:001> r? $t2 = (short *) @@(psapi + 1188)
0:001> .printf "%x %ma %y\n" , @@(@$t2[4]) , (@@(@$t1[4]) + psapi) , (@@(@$t0[4]) + psapi)
4 EnumProcessModules PSAPI!EnumProcessModulesStub (762d1408)
Upvotes: 0
Reputation: 180205
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
.
Upvotes: 2