我不清楚你的用例是什么,如果它只是从一个 pdb 文件中获取一个 api 的地址,你可以在批处理模式下使用 windbg 包附带的dbh.exe工具
它在默认基址(通常为 0x10000000)加载 pdb,并为您提供 api 相对于该基址的地址
例子
:\>dbh e:\SYMBOLS\ntkrpamp.pdb\E4AF624F009A4D99A4F85690E0164DBC2\ntkrpamp.pdb n ntopenfile
name : NtOpenFile
addr : 1232d81
size : 0
flags : 400000
type : 0
modbase : 1000000
value : 0
reg : 0
scope : SymTagPublicSymbol (a)
tag : SymTagPublicSymbol (a)
index : 1
您也可以使用 sysinternals livekd.exe 进行确认
:\>livekd -b -c \"? nt!NtOpenFile;? nt; ? (nt!NtOpenFile-nt);q\" | grep -B 3 quit:
Evaluate expression: -2096693887 = 8306fd81
Evaluate expression: -2098999296 = 82e3d000
Evaluate expression: 2305409 = 00232d81
quit:
:\>dbh e:\SYMBOLS\ntkrpamp.pdb\E4AF624F009A4D99A4F85690E0164DBC2\ntkrpamp.pdb n ntopenfile
name : NtOpenFile
addr : 1232d81
size : 0
flags : 400000
type : 0
modbase : 1000000
value : 0
reg : 0
scope : SymTagPublicSymbol (a)
tag : SymTagPublicSymbol (a)
index : 1
:\>
至于从所有加载的模块中查找 api,您可以使用通配符,如 *. ETC
kd> x *!*ntgdiflu*
76cc5fd2 GDI32!NtGdiFlush (<no parameter info>)
98257991 win32k!NtGdiFlush (<no parameter info>)
9824c664 win32k!NtGdiFlushUserBatch (<no parameter info>)
kd> x Win*!*ntgdiflu*
98257991 win32k!NtGdiFlush (<no parameter info>)
9824c664 win32k!NtGdiFlushUserBatch (<no parameter info>)
kd>
它似乎并不像将 cvdump 为符号吐出的 S_PUB32 值添加到段偏移量那么简单
似乎 S_PUB32 值是在优化函数分块等发生之前写入的
cvdump 在它的 headers 中有两个不同的 header 信息
一个似乎是嵌入在最终可执行文件中的实际标头 一个似乎是原始标头预优化?或者写完这个标题后会做的任何事情
E:\cvdump>cvdump.exe -headers ntkrpamp.pdb | grep -i original -A 500 | grep -i #8 -A 10 | grep -i virtual
1A604E virtual size
166000 virtual address
E:\cvdump>cvdump.exe -headers ntkrpamp.pdb | grep -i #8 -A 10 | grep -i virtual
1AD618 virtual size
16C000 virtual address
1A604E virtual size
166000 virtual address
在这种情况下,S_PUB32 值被添加到原始段偏移量
E:\cvdump>cvdump.exe -p ntkrpamp.pdb | grep -i ntopenfile
S_PUB32: [0008:000620C8], Flags: 00000002, _NtOpenFile@24
0x620c8添加到0x166000的虚拟地址original header's section #8
(这没有反映在 dumpbin.exe /headers 所以 dumpbin 有点没用)
现在 omapf 似乎显示了最终可执行文件中的实际函数偏移量
E:\cvdump>cvdump.exe -omapf ntkrpamp.pdb | grep -i 1c80c8
001C80C8 00232D81
对于我尝试过的一些功能,该模式似乎是一致的
检查一些随机的api
E:\cvdump>cvdump.exe -p ntkrpamp.pdb | grep -i rtlfreehot
S_PUB32: [0008:0011C32E], Flags: 00000002, _RtlFreeHotPatchData@4
E:\cvdump>cvdump.exe -headers ntkrpamp.pdb | grep -i original -A 500 | grep -i #8 -A 10 | grep -i virtual
1A604E virtual size
166000 virtual address
E:\cvdump>python -c "print \"%x\" % (0x11c32e+0x166000)"
28232e
E:\cvdump>cvdump.exe -omapf ntkrpamp.pdb | grep -i 28232e
0028232E 002E88C0
E:\cvdump>dbh ntkrpamp.pdb n RtlFreeHotPatchData
name : RtlFreeHotPatchData
addr : 12e88c0
size : 0
flags : 400000
type : 0
modbase : 1000000
value : 0
reg : 0
scope : SymTagPublicSymbol (a)
tag : SymTagPublicSymbol (a)
index : 1
E:\cvdump>
如果 fpo 数据可用,您也可以获得函数大小 prolog no of params no locals 等
E:\cvdump>cvdump.exe -fpo ntkrpamp.pdb | grep -i 28232e
0028232E 2E 1 3 0 N N fpo 0
这与 windbg .fnent 函数输出完全匹配
kd> .fnent nt!RtlFreeHotPatchData
Debugger function entry 030b5b70 for:
(831258c0) nt!RtlFreeHotPatchData | (831258
Exact matches:
nt!RtlFreeHotPatchData (<no parameter info>)
OffStart: 002e88c0
ProcSize: 0x2e
Prologue: 0x3
Params: 0n0 (0x0 bytes)
Locals: 0n1 (0x4 bytes)
Registers: 0n0
kd>