zoukankan      html  css  js  c++  java
  • 通过修改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才能使用的。

    核心代码如下:

    PJMPCODE pCurAddr;//指向SSDT表中"当前地址"的指针
    JMPCODE oleCode;//用来保存前5字节,以便恢复
    
    //驱动程序的入口函数
    #pragma INITCODE//将DriverEntry设在分页内存中,当驱动加载成功,此函数在内存中移除。
    extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
    {
        ULONG curAddr,oldAddr;
        JMPCODE jmpCode;
    
        // __asm int 3;//断点
        DbgPrint("驱动加载成功……
    ");
        curAddr = Get_NTCurAddr();
        oldAddr = Get_NTOldAddr();
        if (curAddr!=oldAddr)
        {
            //保存前5字节
            pCurAddr=(PJMPCODE)curAddr;//初始化指针
            oleCode.jmpStyle=pCurAddr->jmpStyle;//跳转方式的机器码(1字节)
            oleCode.jmpAddr=pCurAddr->jmpAddr;//跳转的目的地址机器码(4字节)
            
            jmpCode.jmpStyle = 0xE9;//近跳转
            jmpCode.jmpAddr = oldAddr-curAddr-5;
    
            DbgPrint("要写入的地址:%X",jmpCode.jmpAddr);
            //写入JMP指令
            //关闭写保护
            _asm
            {
                cli ;//将处理器标志寄存器的中断标志位清0,不允许中断
                mov eax, cr0
                and  eax, ~0x10000
                mov cr0, eax
            }
    
            pCurAddr->jmpStyle=0xE9;//近跳转
            pCurAddr->jmpAddr=jmpCode.jmpAddr;//要跳转到的地址
            // 恢复写保护
            _asm
            {
                mov  eax, cr0
                or     eax, 0x10000
                mov  cr0, eax
                sti ;//将处理器标志寄存器的中断标志置1,允许中断
            }
            DbgPrint("NtOpenProcess被Hook了");
        }
        CreateMyDevice(pDriverObject);//创建设备
        pDriverObject->DriverUnload = DDK_UnLoad;    
        return STATUS_SUCCESS;
    }
    //卸载例程
    void DDK_UnLoad(IN PDRIVER_OBJECT pDriverObject)
    {    
        //关闭写保护
        _asm
        {
            cli ;//将处理器标志寄存器的中断标志位清0,不允许中断
            mov eax, cr0
            and  eax, ~0x10000
            mov cr0, eax
        }
        pCurAddr->jmpStyle=oleCode.jmpStyle;//近跳转
        pCurAddr->jmpAddr=oleCode.jmpAddr;//要跳转到的地址
        // 恢复写保护
        _asm
        {
            mov  eax, cr0
            or     eax,0x10000
            mov  cr0, eax
            sti ;//将处理器标志寄存器的中断标志置1,允许中断
        }
        DbgPrint("驱动卸载成功……
    ");
    }

    原创文章,转载请注明出处:http://www.cnblogs.com/hongfei/

  • 相关阅读:
    Docker 安装及使用
    明明白白学 同步、异步、阻塞与非阻塞
    ArrayList 并发操作 ConcurrentModificationException 异常
    shell 脚本防止ddos
    shell 脚本备份数据库
    shell 脚本猜数字
    shell 脚本检测主从状态
    tomcat 结合apache 动静分离
    shell 脚本检测网站存活
    zabbix 4.0 版本 yum安装
  • 原文地址:https://www.cnblogs.com/hongfei/p/3142162.html
Copyright © 2011-2022 走看看