MSR_HOOK
32 位下 HOOk SYSENTER 实现进程保护。
OpenProcess的调用过程如下:
kernel32.OpenProcess -> kernelBa.OpenProcess -> ntdll.ZwOpenProcess -> ntdll.KiFastSystemCall ->(Ring0) _KiFastCallEntry -> (Ring0)NtOpenProcess
ZwOpenProcess中的代码如下:
mov eax,0xeb //调用号
mov edx,KUSER_SHARED_SYSCALL
// cpu初始化时,根据架构不同,KUSER_SHARED_SYSCALL里面的实现的内核函数指针接口也不同,可能是 KiIntSystemCall中断式系统调用 也可能是 KiFastSystemCall快速系统调用
call [edx]
ret 0x10这里edx保存的是KiFastSystemCall函数,继续跟进KiFastSystemCall函数
mov edx,esp
sysenter
retn简单的三条指令,mov edx,esp 因为下一条指令SYSENTER就是进入内核层,由于每个线程都有一套线程上下文,都有一个独立的栈.。进入到内核后,内核也会使用自己的内核栈,所以这里先用edx保存栈顶esp。
SYSENTER 执行的时候,会读取三个特殊寄存器,从这三个特殊寄存器中取出内核栈的栈顶( esp ) ,内核代码段段选择子( cs ) ,以及代码的首地址( eip ),保存这三个值得寄存器是MSR寄存器组。这组寄存器没有名字,只有编号,由于没有名字,无法通过正常的汇编指令来存取值,Intel提供了两条指令来读写这些寄存器:
rdmsr 读取MSR寄存器 其中高32位存放在EDX 低32位存放在EAX(64位和32位是一样,只是64位时rdx和rcx的高32位会被清零),使用ECX传递寄存器编号
wrmsr 写入MSR寄存器,和读取一样写入时是用EDX表示高32位,EAX表示低32位,使用ECX传递寄存器编号
也就是说, Windows在启动,进行初始化的时候会将内核栈栈顶,内核CS段选择子,以及代码段地址(KiFastCallEntry 函数)的地址一一存放到MSR寄存器组的这几个编号的寄存器中。当 SYSENTER 被执行,,CPU就直接使用这些寄存器的值来初始化真正的CS , EIP , ESP 寄存器。因此, SYSENTER 执行之后, 就跑到内核的 KiFastCallEntry 函数中执行代码了。
而进行SYSENTER-HOOK时我们只需要关注代码的地址( SYSENTER_EIP_MSR )即可,它的编号是0x176。用类似于3环的Inline-Hook的方法,直接把该地址改为我们自己的函数地址,过滤检查传入的参数,这样就能实现HOOK保护进程了。具体用法如下:
Last updated
Was this helpful?