浅谈EPT无痕HOOK的方法

前言

目前过pg的主流方法

在进入VMX操作,一个很有用的功能就是在开启EPT机制后,进行1:1身份映射后HOST GUEST

进行EPT HOOK,通常作用有两种

  • 无痕监控读写,类似调试器的内存读写断点
  • 无痕Hook,类似调试器的调试断点

对于第一种实现起来很简单,方法也基本一致

通常是EPT Entry属性修改为不可读写,触发EPT Violation在其中进行MTF位

同时设置可读写,让这行代码可以执行。MTF Handler中设置为不可执行

从而实现无痕监控读写

而对于第二种EPT的应用方法,目前来说大概有三种

无需MTF置位的无痕Hook

方式和周壑的VT一样,思路如下

  • 设置EPT页级Hook,使整读和写页无效,而只留下可执行属性
  • 分配一个新的物理内存(P2),EPT中的EPT Pml1Entry的PhyFrameNumber(原来的P1)替换成新分配的
  • 修改P2,使其变成一个绝对跳转,跳转到Hook的地方去执行
  • 页面受到读写访问,EPT Violation,此时将此页面为可读写,不可执行
  • 下次执行的时候,遇到不可执行内存,EPT Violation再次恢复可执行,不可读写

缺点

此Hook有个很大的缺陷,考虑如下。

1
2
hook_4kb_addr:
mov rax, ds:[hook_4kb_addr]

这样就会无限MTF,不断的切换不可读写,可读写,导致CPU卡死

仿内存执行断点的无痕Hook

方法如下:

  • 设置页面HOOK,全程可读写,不可执行
  • 这样有可能就会某一次到要HOOK的地方,但是页可能不到
  • 如果没到,而是其他地址,恢复可执行,并设置MTF,在MTF Handler中恢复不可执行
  • 直到遇到要Hook的地方,HOST中直接VMWRITE,修改GUEST_RIP

缺点

遇到4kb页面访问次数多的,会巨卡无比。

MTF置位全程可执行的无痕Hook

  • 设置EPT页级Hook,使整读和写页无效,而只留下可执行属性
  • 分配一个新的物理内存(P2),EPT中的EPT Pml1Entry的PhyFrameNumber(原来的P1)替换成新分配的
  • 修改P2,使其变成一个绝对跳转,跳转到Hook的地方去执行
  • 页面受到读写访问,EPT Violation,此时将此页面可读/写,并设置MTF位
  • MTF VM Exit,判断是否是EPT Hook导致的,是则设置不可读写,并替换回P2物理内存。

缺点

缺点不太明显,适合Hook内核函数,而对于高频CRC校验的函数,不太适合,总的来说是最适合的EPT无痕Hook了。