码迷,mamicode.com
首页 > 其他好文 > 详细

通过修改CR0寄存器绕过SSDT驱动保护

时间:2015-05-16 23:19:13      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

为了安全起见,Windows XP及其以后的系统将一些重要的内存页设置为只读属性,这样就算有权力访问该表也不能随意对其修改,例如SSDT、IDT等。但这种方法很容易被绕过,我们只要将这些部分修改为可写属性就可以了,不过当我们的事情做完后记得把它们恢复为只读属性,不然会造成一些很难预料到的后果。

  cr0是系统内的控制寄存器之一。控制寄存器是一些特殊的寄存器,它们可以控制CPU的一些重要特性。

  控制寄存器最初出现于低级的286处理器中,以前称之为机器状态字(machine status word),在386以后它们被重命名为控制寄存器(control register)。

  cr0寄存器直到486的处理器版本才被加入了“写保护”(Write Protect,WP)位,WP位控制是否允许处理器向标记为只读属性的内存页写入数据。

  WP位0:禁用写保护的功能

  WP位1:开启写保护的功能

cr0的第16位是WP位,只要将这一位置0就可以禁用写保护,置1则可将其恢复。

禁用写保护的操作步骤:

1 shl 16(1左移16位)//结果:10000000000000000

对结果取反 not (1 shl 16)//结果:FFFEFFFF=01111111111111111

对cr0的值进行“逻辑与”运算:and cr0,  01111111111111111 //即将第17位置0,其余位不变

启用写保护的操作步骤:

直接对CR0的值进行“逻辑或”运算:or cr0,10000000000000000//即将第17位置1,其余位不变

禁用和启用写保护的内联汇编代码如下所示:

// 关闭写保护
__asm
{
    cli ;//将处理器标志寄存器的中断标志位清0,不允许中断
    mov eax, cr0
    and  eax, ~0x10000
    mov cr0, eax
}

// 恢复写保护
__asm
{
    mov  eax, cr0
    or     eax, 0x10000
    mov  cr0, eax
    sti ;//将处理器标志寄存器的中断标志置1,允许中断
}

注意:cli和sti都是特权指令,必须在ring0才能使用的。

核心代码如下:

 1 PJMPCODE pCurAddr;//指向SSDT表中"当前地址"的指针
 2 JMPCODE oleCode;//用来保存前5字节,以便恢复
 3 
 4 //驱动程序的入口函数
 5 #pragma INITCODE//将DriverEntry设在分页内存中,当驱动加载成功,此函数在内存中移除。
 6 extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
 7 {
 8     ULONG curAddr,oldAddr;
 9     JMPCODE jmpCode;
10 
11     // __asm int 3;//断点
12     DbgPrint("驱动加载成功……\n");
13     curAddr = Get_NTCurAddr();
14     oldAddr = Get_NTOldAddr();
15     if (curAddr!=oldAddr)
16     {
17         //保存前5字节
18         pCurAddr=(PJMPCODE)curAddr;//初始化指针
19         oleCode.jmpStyle=pCurAddr->jmpStyle;//跳转方式的机器码(1字节)
20         oleCode.jmpAddr=pCurAddr->jmpAddr;//跳转的目的地址机器码(4字节)
21         
22         jmpCode.jmpStyle = 0xE9;//近跳转
23         jmpCode.jmpAddr = oldAddr-curAddr-5;
24 
25         DbgPrint("要写入的地址:%X",jmpCode.jmpAddr);
26         //写入JMP指令
27         //关闭写保护
28         _asm
29         {
30             cli ;//将处理器标志寄存器的中断标志位清0,不允许中断
31             mov eax, cr0
32             and  eax, ~0x10000
33             mov cr0, eax
34         }
35 
36         pCurAddr->jmpStyle=0xE9;//近跳转
37         pCurAddr->jmpAddr=jmpCode.jmpAddr;//要跳转到的地址
38         // 恢复写保护
39         _asm
40         {
41             mov  eax, cr0
42             or     eax, 0x10000
43             mov  cr0, eax
44             sti ;//将处理器标志寄存器的中断标志置1,允许中断
45         }
46         DbgPrint("NtOpenProcess被Hook了");
47     }
48     CreateMyDevice(pDriverObject);//创建设备
49     pDriverObject->DriverUnload = DDK_UnLoad;    
50     return STATUS_SUCCESS;
51 }
 1 //卸载例程
 2 void DDK_UnLoad(IN PDRIVER_OBJECT pDriverObject)
 3 {    
 4     //关闭写保护
 5     _asm
 6     {
 7         cli ;//将处理器标志寄存器的中断标志位清0,不允许中断
 8         mov eax, cr0
 9         and  eax, ~0x10000
10         mov cr0, eax
11     }
12     pCurAddr->jmpStyle=oleCode.jmpStyle;//近跳转
13     pCurAddr->jmpAddr=oleCode.jmpAddr;//要跳转到的地址
14     // 恢复写保护
15     _asm
16     {
17         mov  eax, cr0
18         or     eax,0x10000
19         mov  cr0, eax
20         sti ;//将处理器标志寄存器的中断标志置1,允许中断
21     }
22     DbgPrint("驱动卸载成功……\n");
23 }

转自:http://www.cnblogs.com/hongfei/

技术分享

通过修改CR0寄存器绕过SSDT驱动保护

标签:

原文地址:http://www.cnblogs.com/Chameleon/p/4508725.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!