首页
论坛
专栏
课程

[系统底层] [讨论]x64中无法通过cr0来关闭内存写保护?!

2016-8-29 23:39 5426

[系统底层] [讨论]x64中无法通过cr0来关闭内存写保护?!

2016-8-29 23:39
5426
要修改内核某处,在X86中,往往会通过关闭cr0的WP位来关闭内存写保护,如cli; mov eax, cr0; and eax, 0xfffeffff; mov cr0,eax;

我发现这个方法在x64下无效了, 百度了一下,网上都是一大堆的 WPOFFx64, WPONx64, 都是老样子,先Raise Irql,  cli, 然后清除cr0的WP位。  我不明白,我测试到明明这种方法在x64下是无效的, 为什么网上还煞有其事地讲来讲去,到处是例子代码, 是专坑新手的吗?故意的吗?

不要谈 Patch Guard,  这个不关Patch Guard 的事,因为操作cr0后,试图修改内存时,立即KiPageFault , KiBugCheckDispatch, KeBugCheckEx ...   不要告诉我这是 Patch Guard , 并且当时系统是调试模式。  蓝屏是因为 Page Fault 啊,PageFault ....  明显关闭cr0的WP位根本不起作用。

难道是与目标内存有关?不太可能,因为我换了好几处无关痛痒的地方来测试(比如, 函数尾部的nop),哪怕只动1字节,也是一样的KiPageFault

x64中无法通过cr0来关闭内存写保护?哪要怎么做?重新映射什么的?

[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最新回复 (7)
hzqst 3 2016-8-29 23:48
2
0
MDL映射一下
JmpNext 2016-8-29 23:49
3
0
我又查了一下cr0的WP的定义,来自<软件调试>-张银奎, 第44页,是这样定义 cr0 的WP位的:

为 1 时,禁止 内核级代码 写 用户级 的只读内存页;
为 0 时允许

为什么在 32位中,关闭cr0的WP又是有效的呢。
cvcvxk 10 2016-8-30 00:40
4
0
正统应该使用MDL
CR0这玩意动它干啥
lingganai 2016-8-30 07:32
5
0
x64内核不可以用汇编了吧
有专门的函数可以改写cr0
dsjflw 2016-9-4 02:05
6
0
char sz_关闭[15]=
                "\xFA"                     //0
                "\x0F\x20\xC0"             //3
                "\x48\x25\xFF\xFF\xFE\xFF" //9
                "\x0F\x22\xC0"             //12
                "\xC3";                    //13
        char sz_开启[15]=
                "\x0F\x20\xC0"             //2
                "\x48\x0D\x00\x00\x01\x00" //8
                "\x0F\x22\xC0"             //11
                "\xFB"                     //12
                "\xC3";                    //13
你自己分配内存直接调用就用
是你的问题x64是没有问题的
我是哥布林 2016-9-4 10:35
7
0
可以的,我之前写过的

/*cli
cli
mov rax,cr0
mov rcx,rax
and eax,0fffeffffh
mov cr0,rax
mov rax,rcx
ret

*/
UCHAR shellcode[20] =
"\xFA"                 //0
"\x0F\x20\xC0"         //3
"\x48\x8B\xC8"         //6
"\x25\xFF\xFF\xFE\xFF" //11
"\x0F\x22\xC0"         //14
"\x48\x8B\xC1"         //17
"\xC3";                //18
/*
mov cr0,rcx
sti
ret
*/
UCHAR shellcode1[6] =
"\x0F\x22\xC1" //2
"\xFB"         //3
"\xC3";        //4

ULONG closeinterupt()
{
        ULONG old_cr0;
        CLOSEINTERUPT func = ExAllocatePool(NonPagedPool, 20);
        memcpy(func, shellcode, 20);
        old_cr0 = func();
        ExFreePool(func);
        return old_cr0;
}
void startinteript(ULONG old_cr0)
{
        OPENINTERUPT func = ExAllocatePool(NonPagedPool, 6);
        memcpy(func, shellcode1, 6);
        func(old_cr0);
        ExFreePool(func);
}
YZJClear 2018-6-26 16:39
8
0
KIRQL  WPOFFx64()
{
       KIRQL  irql=KeRaiseIrqlToDpcLevel();
       UINT64  cr0=__readcr0();
       cr0  &=  0xfffffffffffeffff;
       __writecr0(cr0);
       _disable();
       return  irql;
}

void  WPONx64(KIRQL  irql)
{
       UINT64  cr0=__readcr0();
       cr0  |=  0x10000;
       _enable();
       __writecr0(cr0);
       KeLowerIrql(irql);
}


别人的代码,很好用,_enable  是  sti  指令,  _disable是  cli  指令,不懂为什么要这样
游客
登录 | 注册 方可回帖
返回