【问题标题】:Windows Symbol Address DefenitionWindows 符号地址定义
【发布时间】:2018-03-01 23:03:08
【问题描述】:

我已经提取了一个使用 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* 没有给我这些符号地址。

【问题讨论】:

  • 000D:000DF320 位于逻辑段:偏移地址中,其中 0x000D 是 PE 段号。在标题中,我看到 D 部分的偏移量为 0x419000,而 0x419000 + 0xDF320 为 0x4F8320。
  • 谢谢!但是您能告诉我您是如何从标头中获取地址 0x419000 的吗?你指的是哪个标题?我在哪里可以找到它们?
  • 尝试 .symfix+ 然后 .reload 看看是否会拉下匹配的操作系统符号。
  • x 是一个命令,后跟空格,后跟模块名,或者星号表示通配符,后跟感叹号,通常称为 bang,后跟符号名或部分名称的正则表达式,然后按 x !*abc 是语法
  • 论坛正在吃掉 cmets 中的星号,它是 x asterisk bang asterisk regex

标签: windows windbg system-calls windows-kernel dependency-walker


【解决方案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,您可以使用通配符,如 *.等等

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在它的header中有两个不同的header信息

one 似乎是嵌入在最终可执行文件中的实际标头 一个似乎是原始标题预优化?或者写完这个标题后会做什么

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 被添加到 0x166000original 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 数据可用,您也可以获得函数大小序言数参数数本地数等

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 2015-05-05
    • 1970-01-01
    • 2015-10-29
    相关资源
    最近更新 更多