Windows符号地址防御

Windows符号地址防御,windows,windbg,system-calls,windows-kernel,dependency-walker,Windows,Windbg,System Calls,Windows Kernel,Dependency Walker,我使用ETW提取了windows中调用的系统调用地址的转储文件。我对地址有些疑惑。我只是在以后的例子中使用NtOpenFile 1- 我使用cvdump转储从MicrosoftSymbolServer(ntkrnlmp.PDB)接收的内核PDB文件。NtOpenfile的条目如下所示: S_PUB32: [000D:000DF320], Flags: 00000002, NtOpenFile 然后,我使用Dependency Walker(DP)打开ntoskrnl.exe。我向下滚动,看到N

我使用ETW提取了windows中调用的系统调用地址的转储文件。我对地址有些疑惑。我只是在以后的例子中使用NtOpenFile

1- 我使用cvdump转储从MicrosoftSymbolServer(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- 为什么win32k.sys中的函数(如NtGdiFlush)不存在于DP打开的.sys文件中?在Windows 10中,另一个名为win32kfull.sys的文件包含这些符号,但在Windows 7中不包含这些符号

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

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

我不清楚您的用例是什么,如果只是从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>
S_PUB32值将添加到原始段偏移 在这种情况下

E:\cvdump>cvdump.exe -p ntkrpamp.pdb | grep -i ntopenfile
S_PUB32: [0008:000620C8], Flags: 00000002, _NtOpenFile@24
0x620c8被添加到0x166000原始头的第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编号、参数编号、局部变量编号等

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>
kd>.fnent nt!RtlFreeHotPatchData
调试器函数项030b5b70用于:
(831258c0)nt!RtlFreeHotPatchData |(831258
精确匹配:
nt!RtlFreeHotPatchData()
OffStart:002e88c0
ProcSize:0x2e
序言:0x3
参数:0n0(0x0字节)
局部变量:0n1(0x4字节)
寄存器:0n0
kd>

000D:000DF320
在一个逻辑段中:偏移地址,其中0x000D是PE段编号。在标题中,我看到段D位于偏移量0x419000,0x419000+0xDF320是0x4F8320。谢谢!但是您能告诉我您是如何从标题中获得地址0x419000的吗?您指的是哪些标题?我在哪里可以找到它们?试试。symfix+然后。重新加载并查看是否会拉下匹配的OS符号。x是一个命令,后跟空格,后跟modulename,或者是一个星号,表示通配符,后跟感叹号,通常称为bang,后跟symbolname,或者是regex,表示partialname,然后像x一样按enter键!*abc是语法论坛正在吞噬评论中的星号它是x星号bang星号regex
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>