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

为了安全起见,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/

时间: 2024-10-14 19:24:22

通过修改CR0寄存器绕过SSDT驱动保护的相关文章

YJX_Driver_021_绕过驱动保护

1. 绕过SSDT驱动保护 A.去掉页面保护 B.写入In Line HOOK代码 C.用OD附加测试效果 D.反HOOK代码 [190]复制 第20课 的代码 [315]涉及到 页面的保护 ==> 涉及到 一个特殊的寄存器 cr0,32位寄存器 ==> 其中的第17位(从第0位开始) ==> CW位 [480]CW位: 置1 --> 开启 页面保护 置0 --> 去掉 页面保护 [530]这只是一种方法(修改cr0的CW位),还有一种是修改内存描述符(MDL)(相关函数前面

修改寄存器绕过保护

为了安全起见,Windows XP及其以后的系统将一些重要的内存页设置为只读属性,这样就算有权力访问该表也不能随意对其修改,例如SSDT.IDT等.但这种方法很容易被绕过,我们只要将这些部分修改为可写属性就可以了,不过当我们的事情做完后记得把它们恢复为只读属性,不然会造成一些很难预料到的后果. cr0是系统内的控制寄存器之一.控制寄存器是一些特殊的寄存器,它们可以控制CPU的一些重要特性. 控制寄存器最初出现于低级的286处理器中,以前称之为机器状态字(machine status word),

x86CPU 实模式 保护模式 傻傻分不清楚? 基于Xv6-OS 分析CR0 寄存器

基于Xv6-OS 分析CR0 寄存器 之前一直觉得晕乎乎的...啥?什么时候切换real model,怎么切换,为什么要切换? ------------------------------------------------------------------------------------------------------------------------------------------- 下面这段代码来自Xv6的boot/boot.S 这就是CPU real model 和 pr

若水软件论坛过游戏驱动保护视频教程

课程分四个大章节:?1.初级篇,2.中级篇,3.进阶篇,4.高级篇 初级篇1.VS2003/2008/VC6.0编译驱动A.VS2003驱动编译环境配置B.VS2003集成环境下编译一个简单的驱动2.创建一个卸载例程A.认识PDRIVER_OBJECT结构B.卸载例程回调函数构建C.查看卸载例程调试信息3.添加设备例程A.认识驱动对象DRIVER_OBJECTB.认识设备对象DEVICE_OBJECTC.添加创建设备的例程D.用工具查看驱动及驱动设备4.添加删除设备例程A.删除符号链接B.删除设

YJX_Driver_032_自写驱动保护XX进程

1. 自写驱动保护XX进程(HOOK SSDT) A.构建自己的内核函数(用来替换对应的内核函数) C.Hook和UnHook函数构建 D.修改EXE和SYS对应源代码实现所谓保护 E.测试效果 2. 一.以28课的代码为例 新建一个hook.h单元 #pragma once#ifdef __cplusplusextern "C"{#endif #include <NTDDK.h> //这里包含需要用C方式编译的头文件 #ifdef __cplusplus}#endif /

过 DNF TP 驱动保护(一)

文章目录:                   01. 博文简介: 02. 环境及工具准备: 03. 分析 TP 所做的保护: 04. 干掉 NtOpenProcess 中的 Deep InLine Hook: 05. 干掉 NtOpenThread 中的 Deep InLine Hook: 06. 干掉 NtReadVirtualMemory 中的 InLine Hook: 07. 干掉 NtWriteVirtualMemory 中的 InLine Hook: 08. 干掉 KiAttachP

使用ret2libc攻击方法绕过数据执行保护

前面介绍的攻击方法大量使用Shellcode,核心思想是修改EIP和注入Shellcode,在函数返回时跳到Shellcode去执行.要防止这种攻击,最有效的办法就是让攻击者注入的Shellcode无法执行,这就是数据执行保护(Data Execution Prevention, DEP)安全机制的初衷. 数据执行保护机制 DEP述语是微软公司提出来的,在window XP操作系统开始支持该安全特性.DEP特性需要硬件页表机制来提供支持. X86 32位架构页表上没有NX(不可执行)位,只有X8

通过修改EIP寄存器实现32位程序的DLL注入

功能:通过修改EIP寄存器实现32位程序的DLL注入 <如果是64位 记得自己对应修改汇编代码部分> 原理:挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器码和数据拷贝到里面去,然后修改目标进程EIP使其强行跳转到我们拷贝进去的相关机器码位置,执行相关,然后跳转回来.下面的例子是实现DLL注入,但是和平时说的远程代码注入在注入的逻辑上不同,但是同时都是用到了一个重要的结论就是:很多系统dll的导出函数地址在不同进程中,是一样的. 思路 : 修改EID实现代码注入

Lab_1:练习3——分析bootloader进入保护模式的过程

文章链接:https://www.cnblogs.com/cyx-b/p/11809742.html 作者:chuyaoxin 一.实验内容 BIOS将通过读取硬盘主引导扇区到内存,并转跳到对应内存中的位置执行bootloader.请分析bootloader是如何完成从实模式进入保护模式的. 提示:需要阅读小节"保护模式和分段机制"和lab1/boot/bootasm.S源码,了解如何从实模式切换到保护模式,需要了解: 为何开启A20,以及如何开启A20 如何初始化GDT表 如何使能和