本帖最后由 LopezBistro 于 2017-3-3 23:55 编辑
打算在 Win64 系统下在 Shadow SSDT 上做点什么的人都知道
- Shadow SSDT 不能直接读取,
- Win64 下 Shadow SSDT 的内容不是真正的函数入口地址
用WinDbg 调试 Win64 下 Shadow SSDT 时候经常需要得到真正的入口地址,有没有简单办法快速计算所有 Shadow SSDT 真正的入口地址呢?
下面用64位 Win8.1 为例说明如何能快速得到 所有Shadow SSDT 的真正入口地址。
Win32k.sys 和Session有关,在任何一个属于Csrss.exe Session的进程空间都可以访问Win32k.sys 中 Shadow SSDT(不一定非要GUI进程), 但 Smss.exe 除外。这里用简单的cmd.exe 进程做例子,因此,在列出所有进程以后,切换到cmd.exe进程 (图1)
切换cmd.exe进程以后,nt!KeServiceDescriptorTableShadow变成可以访问的了,其中的0x40e就是Shadow SSDT的大小,而0xffff960000a9200 就是win32k!W32pServiceTable 的地址了。(图2)
表中每一个需要经过转换(右移4位在与基地址就是win32k!W32pServiceTable地址相加)才能得到真正的入口地址。有人给出了一个计算偏移的算法:
win32k!W32pServiceTable+((poi(win32k!W32pServiceTable+4*n)&0x00000000`ffffffff)>>4)-10000000
这里的 n 是win32k!W32pServiceTable表中元素索引。但需要注意的是这个算法并不完备,因为没有考虑周全右移4位后的符号位问题。因此下面命令
ln win32k!W32pServiceTable+((poi(win32k!W32pServiceTable+4*n)&0x00000000`ffffffff)>>4)-10000000
对索引 n = 7 的时候能得到正确地址,但对索引 n = 11 时就没有办法得到。结果像这个样子(图3)
正确的计算偏移的应该是
.foreach /ps 1 /pS 1 ( offset {dd /c 1win32k!W32pServiceTable L poi(nt!KeServiceDescriptorTableShadow+30)}){ .printf"%y\n", ( offset >>> 4) + win32k!W32pServiceTable }
这个命令给出的结果在(图4)中,Shadow SSDT 表中所有入口地址以及函数名都 列出其中。截图只列前面几个。只要有正确的PDB文件,就应该能显示正确的结果。
|