-
-
[原创][分享]逆向win10 1909的MmIsAddressValidEx分析 999912分页
-
2020-9-27 16:58
4800
-
[原创][分享]逆向win10 1909的MmIsAddressValidEx分析 999912分页
通过逆向win10 1909的MmIsAddressValidEx函数,对windows内存分页管理的理解上有很大帮助。通过win7和xp下对比 win10 1909下此函数对自映射的体现非常明显。废话不对说,直接开始:
简单聊下函数原理
这个函数是通过判断物理页的P为是否为1来判断是否存在物理页,从而判断虚拟地址是否有效。
因为个人表达能力有限,怕后面逆向的时候一笔带过,对他人不友好,特从Intel白皮和潘爱民老师的windows内核原理与实现里摘出来自映射和分页结构图(大佬们请忽略)
windows分页

自映射
就从自映射的资料,供参考:



接下来我们逆向分析
MmIsAddressValid函数原型如下:
1 2 3 4 5 | NTKERNELAPI
BOOLEAN
MmIsAddressValid (
_In_ PVOID VirtualAddress
);
|

可以从上图看出 MmIsAddressValid调用了MmIsAddressValidEx,通过x64和上图可以看出调用约定是fastcall,那么我们得参数VirtualAddress在rcx中。MmIsAddressValid函数并没有做什么事,那我们开始分析MmIsAddressValidEx。

接下来我截图一块块分析

从我红框处可以看出 rax就是我们传入的参数VirtualAddress,右移0x2F(47位)+1 这里在验证我们传入的地址是否有效,但是我们知道x64地址是否有效是判断前面16位是否是FFFF或者0000,那么按理来说应该右移48位,为何只右移了47位?
这里我不得不提windows的三环和0环地址,X64 地址空间分开成2部分
用户模式地址的范围:0x0000000000000000~0x00007FFF
FFFFFFFF;
内核模式地址的范围:0xFFFF800000000000~0xFFFFFFFF
FFFFFFFF。
从上面可以看出 算数右移47位 如果地址是有效的那么我们得到的结果一定是内核:0xFFFFFFFFFFFFFFFF,用户:0,所以+1之后要么就是0要么就是1,如果大于1 地址一定无效,比如0xffff7000
00000000,这个地址既不在内核地址范围,也不在用户地址范围,右移47位的结果是0xFFFFFFFFFFFFFFFE,如果这个值+1等于0xFFFFFFFF
FFFFFFFF,ja是无符号大于跳转,所以就跳转直接返回了。
过滤完上述情况后

这里我们可以看到rdi这个值就是PTEBASE,(在x64上这个PTEBASE的值每次重启都会随机生成),通过从PTEBASE来寻找到对应得物理页的PTE,shr rdx,9这句意思是相当于得到虚拟地址的PTE索引再8,也就是先右移12位然后8。
接下来我们就看到自映射的原理了

这段代码似曾相识,其实是通过pte映射的虚拟地址,得到PTE的物理页,也就是PDE。然后接下来我们看到的其实也是相似的。

通过PDE映射的虚拟地址得到PPE

通过PPE映射的虚拟地址得到PML4也有人成为PXE

接下来通过这段来循环判断是否是大页,物理页的P为是否为1。
因个人表达能力有限,敬请谅解
冰蝎,蚁剑Java内存马查杀防御技术
最后于 2020-9-27 23:28
被墨瑾萱编辑
,原因: 内容补充