在内核态下,数据段受到写保护,并非可以直接修改,控制写保护的就是一个比特位,其位于CR0寄存器的第17位(即索引为16)。
在x86下可以通过内联汇编来修改该位。但是在64位下无法使用内联汇编了。还是有办法可以实现对WP位的控制。
// 关闭CR0控制寄存器内的WP位
KIRQL WriteProtectOff()
{
KIRQL OldIrql = 0;
ULONG_PTR cr0 = 0;
// 提升IRQL等级到Dispatch Level
OldIrql = KeRaiseIrqlToDpcLevel();
// 读取读cr0控制寄存器内容
cr0 = __readcr0();
// 关闭WP位
#ifdef _X86_
cr0 &= 0xfffeffff;
#else
cr0 &= 0xfffffffffffeffff;
#endif
// 关闭中断
_disable();
// 写回cr0寄存器
__writecr0(cr0);
return(OldIrql);
}
// 打开CR0控制寄存器内的WP位
VOID WriteProtectOn(KIRQL irql)
{
KIRQL OldIrql = 0;
ULONG_PTR cr0 = 0;
// 读取读cr0控制寄存器内容
cr0 = __readcr0();
// 打开WP位
#ifdef _X86_
cr0 |= 0x00010000;
#else
cr0 |= 0x0000000000010000;
#endif
// 写回cr0寄存器
__writecr0(cr0);
// 打开中断
_enable();
// 恢复IRQL等级
KeLowerIrql(irql);
}
汇编指令sti和cli 分别使用_enable()和_disable()代替。汇编可以直接操作cr0寄存器,但C语言需要调用对应的封装函数__readcr0()和__writecr0()来进行。
(完)
更多推荐
内核模式下关闭/开启写保护(WriteProtect)
发布评论