win内核初探-PTEhook坑总结

Posted by Qmeimei10086 on February 28, 2026

前言

CTF已经毁了!
meme
当然这只是个笑话,但是CTF圈子现状确实非常令人担忧,大量的AI使CTF失去了学习知识初衷,为了分数和抢血,CTFer疯了一般往里面砸钱,ctf已然变成财力于AI调教水平的对决
这种情况下,真正要毁了的是我,还有那些刚入门的新手
所以我希望抽身出来,认真学习一些知识,身为re手,我便挑选了内核作为学习方向

PTEhook

请看:
https://xz.aliyun.com/news/18999
讲的很好了,根本不需要我(
好吧我还是多水一点

寻址

我们都知道,我在ida,od所见到的都是虚拟地址,那么他和物理地址有什么关系呢
在64 位下 虚拟地址经过9 9 9 9 12拆分,得到pml4e_index,pdpte_index,pde_index,pte_index,页内偏移
每个进程的环境下,有个唯一的cr3,指向pml4表的物理基地址(注意是物理),然后就像多维数组一样,pml4e_index找到pdpt表的物理基地址(注意是物理),最后一级一级来到一个页,最后加上业内偏移就是虚拟地址了

页表自映射

首先其实“指向pml4表的物理基地址”,其实不太准确
其实我们拿到的是一个指向pml4表的物理基地址 + 一堆属性的一个64位整数
作为进程,我们只能通过访问虚拟地址来访问内核空间,那么我们怎么访问页表项呢?
即使使驱动,内核,他也像我们一样只能访问虚拟地址,那他们怎么访问页表项呢?

这就引出页表自映射了,巧妙地利用寻址规则把一个页表用来映射自己,这样我们就可以通过访问这个页表来访问页表项了
具体请看https://xz.aliyun.com/news/18999
(毕竟讲的比我好,只不过你们带着问题去看会更好理解

pte hook原理

虽然页表是共享地,但是不完全共享,每个进程享有独立地pml4表,其他的pdpt啥都是共享,毕竟那么大
正常情况下内核空间的pml4t是一样的,也就是即使是不同进程有不同的cr3,但是相同的,指向内核空间数据的地址,经过层层拆分寻址最终会来到同样的地方
那么我们假如我们想隔离一块内存,伪造一个pml4e,指向我们伪造的pdpt,然后其中一项我们又偷偷修改,指向我们的pdt。。。以此类推
这样子不是偷梁换柱,即使是相同的虚拟地址,而经过层层拆分寻址,因为表都不一样了,最终来到的物理地址也是不同的了
更加nb的是,我们只改一个进程的pml4t,而大家的pml4t都是独立的,尤其是不会影响内核的pml4,这样子不是就可以实现偷偷的值把一个进程的某个页隔离了,我们怎么改都是只和他有关,这样子就可以无视patch guard
具体请看https://xz.aliyun.com/news/18999
最后我们在这个隔离出来的地方搞个hook,跳到我们自己的去,这样子不是就实现完美hook内核函数啦

代码 & 坑

https://github.com/Qmeimei10086/PTE_hook
代码在这,不理解叫ai教你,给个star谢谢喵
这个例子里,我把explorer进程的NtCreateFile(这个函数主要是打开文件的时候会用到哦)给hook了,如果检查到参数是tips.txt,就会返回无权限
也就是我们无法打开tips.txt了

  • 坑1 pte的g位记得要改成0,并且要刷新tlb,不然会失效
    因为g位如果位1,系统在切换进程时就不会重新去算,而是利用tlb(会记录一些我们换算过的虚拟地址),那不就还是拿我们动过手脚的那个虚拟地址和物理地址的对应关系,达不到隔离的效果
  • 坑2 虚拟机内存一定要大,至少4g,不然会蓝屏(我哭哭了,找了好久原因竟然时这个
  • 坑3 做测试的时候,会发现一个诡异的现象
    我们隔离了exploere.exe,用他打开tips.txt。。。打不开,超级正常
    但是我们在桌面双击启动我安装好的notpad++,然后把tips.exe打开。。。打不开????
    我们在windbg里切换到notpad++的上下文,使用命令u NtCreateFile,竟然第一条时jmp!这不是明显给hook过了
    原因是pml4t的继承关系,注意我们“在桌面”启动,这时候其实就是explorer启动了notpad++,操作系统为了速度,直接复制了启动者的pml4e给他,导致他的也被hook了
    假如你在hook前提前启动一个cmd,然后装载驱动,然后用cmd启动notpad++,欸嘿,正常打开

后继

大概要离开ctf一段时间了,当我在内核学成归来,必然酱味大鸡所有的反调试(依旧做梦