什么是系统调用
- 系统调用是内核提供给应用层的接口,比如在 win10x64 应用层打开一个应用,其实就是 explorer 调用了 CreateProcess,这个函数通过 NTDLL 调用表的 0xC8 号服务,执行 SYSCALL 进入内核。
- 内核从 SSDT 服务表确定了函数参数个数,复制到内核栈中,取出对应内核函数地址,再 CALL 这个地址。
- 执行创建进程的一系列操作后,用 SYSRET 返回到应用层,返回到调用 SYSCALL 的地方,这就完成了一次系统调用。
VT如何拦截系统调用
- VT 不需要修改任何系统代码,只修改 MSR 寄存器,就可以达到 Hook 的目的。
- MSR_LSTAR 这个特殊寄存器里存放的是 SYSCALL 的入口地址,我们只需要写个替换函数,把地址写入这个 MSR 即可完成挂钩,同时也要保存旧的 SYSCALL 地址。
- PatchGuard 是微软的用来保护内核的模块,它会检查这个 MSR 是否被修改过,修改过会给个 109 蓝屏。
- 我们可以利用VT技术对读 MSR 进行拦截,如果它读取了这个 MSR 我们给它返回旧的 SYSCALL 地址,就可以欺骗 PatchGuard。
代码流程如下:
- 我们要在 VT 基础框架上加些代码
- 申请用来 保存MSR 的内存,和 MSR位图 的内存,写入到 VMCS 对应的字段中。
- 设置读取 MSR_LSTAR 的 MSR位图 监控。
- 编写一个用来替换 MSR_LSTAR 的汇编函数。
- 读取并保存旧的 MSR_LSTAR。
- 将替换函数按照格式写入 保存MSR 的内存。
- 设置 VMCS 的 VM进入控制 加载MSR个数为1。
- 在 VMM 的 VM退出 事件处理例程里处理 读取 MSR_LSATR 的事件,返回保存的旧 SYSCALL 地址。
- 卸载的时候,只需要把旧的 SYSCALL 地址按格式写回到 保存MSR 的地方。
- 取消读取 MSR_LSTAR 的 MSR位图 监控。
注意事项:
如果拦截所有系统调用的话,不要打印,调用非常频繁,所有的核都在忙着打印,windbg 在不停输出。
推荐只打印同一个进程的系统调用,感受一下时间切片,核心切换