1

我已经提取了一个使用 ETW 在 Windows 中调用的系统调用地址的转储文件。我对地址有些困惑。我只是将 NtOpenFile 用于以后的示例。

1-

我使用 cvdump 转储从 Microsoft 符号服务器 (ntkrnlmp.pdb) 收到的内核 PDB 文件。NtOpenfile 的入口是这样的:

S_PUB32: [000D:000DF320], Flags: 00000002, NtOpenFile

然后我使用 Dependency Walker (DP) 打开 ntoskrnl.exe。我向下滚动并查看 NtOpenFile 的条目:

在此处输入图像描述

然后我使用这段代码收到内核基地址:

hNtdll = GetModuleHandle("ntdll.dll");
NtQuerySystemInformation = (NtQuerySystemInformationFunc)GetProcAddress(hNtdll, "NtQuerySystemInformation");
NtQuerySystemInformation(SystemModuleInformation, &ModuleInfo, sizeof(ModuleInfo), NULL);
KernelBase = (ULONG64)ModuleInfo.Modules[0].ImageBase;

内核基地址为:fffff802f7616000

使用 windbg 提取的 NtOpenFile 的实际地址是fffff802f7b0e320 nt!NtOpenFile

使用从 pdb 文件中提取的地址添加内核基址会给我错误的地址(添加来自 DP 结果的地址是正确的)。为什么?

2-

为什么DP打开的.sys文件中没有像NtGdiFlush这样的win32k.sys中的函数?在 Windows 10 中,还有另一个名为 win32kfull.sys 的文件包含这些符号,但在 Windows 7 中没有。

3-

我根本无法映射像 NtQueryVirtualMemory 这样的函数。它存在于 ntkrnlmp.pdb 转储中,但正如我在第 1 部分中所说,地址似乎错误!并且它也存在于 DP 打开的 ntoskrnl.exe 中作为 ZwQueryVirtualMemory。但它与windbg.exe提取的NtQueryVirtualMemory地址不同,这些是如何相互映射的呢?如何使用 DP 或 PDB 文件提取此函数的地址?

4-

如何使用 windbg 找到 win32k.sys 系统调用地址(如 NtGdiFlush 的地址)?该命令kd> x /D nt!Nt*没有给我这些符号地址。

4

1 回答 1

1

我不清楚你的用例是什么,如果它只是从一个 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>
于 2017-09-21T05:31:29.600 回答