如何使用WinDbg

时间:2018-04-04 09:35:08

标签: c++ windbg getprocaddress

我想使用GetProcAddress在加载的DLL中获取一些函数地址。我在PSAPI库上运行了一些尝试,我可以看到预期的proc名称与我在WinDbg x语句中找到的符号名称不同。例如,我使用GetProcAddress查找" EnumProcessModules"(x psapi!*EnumProcessModules*方法所需的名称),我找到了

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>

当我向GetProcAddress方法提供任何上面找到的符号(带或不带#34; PSAPI!&#34;作为前缀)作为第二个参数(procName)时 - 它返回NULL,但是当我使用方法名称&#34; EnumProcessModules&#34; - 它返回0xfe111030,这是&#34; PSAPI!EnumProcessModulesStub&#34;的地址。

我怎么能提前知道预期的procName?如果我在一个DLL中有2个不同的类或名称空间具有相同的方法名称,该怎么办?当我调用GetProcAddress时,如何区分这两个方法名称?

2 个答案:

答案 0 :(得分:3)

PSAPI!只是一个前缀,它是WinDbg打印的DLL名称。这用于消除名称的歧义。一个明确的例子,说明这有用的原因:您的流程中会有很多DllMain个。

GetProcAddress的预期名称是该功能的已记录名称,如MSDN中所述。请注意,当MSDN声明两个版本都可用时,您需要添加AW后缀。例如。您无法使用GetProcAddress致电"GetDeviceDriverFileName",您需要"GetDeviceDriverFileNameA"L"GetDeviceDriverFileNameW"

对于非系统DLL,您需要输出地址表中的函数名称。

背景:您在WinDbg中看到的是.PDB中的名称,您发现的名称可能与导出的名称不同。没有什么可以强制两者之间的关系。例如,技术上可以使用PDB名称FooBar,并将它们交换到导出地址表中。更现实的是,Microsoft可能会在内部随时添加_wrapper_EnumProcessModules,但记录和导出的名称将保留EnumProcessModules

答案 1 :(得分:1)

此API的核心功能在 kernel32.dll 中实现 并命名为 K32EnumProcessModules

在paspi.h头文件中,此API基于PSAPI_VERSION

进行ifdeffed
#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 

如果您在psapi.dll中使用GetProcAddress,则会获得一个存根,该存根将被传输到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

您可以在dll上使用dumpbin / exports来查看是否存在任何关联 或者如果名称发生变化(参见Stub @ 16)

:\>dumpbin /exports c:\windows\System32\psapi.dll | grep -w EnumProcessModules
          5    4 00001408 EnumProcessModules = _EnumProcessModulesStub@16

您也可以使用下面的内容

从psapi.dll的导出表中找到相同的信息
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)