经由过程批改CR0存放器绕过SSDT驱动保护

    添加时间:2013-6-18 点击量:

      为了安然起见,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, ~0 x10000
        mov cr0, eax
    }


    // 恢复写保护
    __asm
    {
        mov  eax, cr0
        or     eax, 0 x10000
        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(驱动加载成功……\n);
    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
    = 0 xE9;//近跳转
    jmpCode.jmpAddr = oldAddr-curAddr-5;

    DbgPrint(
    要写入的地址:%X,jmpCode.jmpAddr);
    //写入JMP指令
    //封闭写保护
    _asm
    {
    cli ;
    //将处理惩罚器标记存放器的中断标记位清0,不容许中断
    mov eax, cr0
    and eax,
    ~0 x10000
    mov cr0, eax
    }

    pCurAddr
    ->jmpStyle=0 xE9;//近跳转
    pCurAddr->jmpAddr=jmpCode.jmpAddr;//要跳转到的地址
    // 恢复写保护
    _asm
    {
    mov eax, cr0
    or eax,
    0 x10000
    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,
    ~0 x10000
    mov cr0, eax
    }
    pCurAddr
    ->jmpStyle=oleCode.jmpStyle;//近跳转
    pCurAddr->jmpAddr=oleCode.jmpAddr;//要跳转到的地址
    // 恢复写保护
    _asm
    {
    mov eax, cr0
    or eax,
    0 x10000
    mov cr0, eax
    sti ;
    //将处理惩罚器标记存放器的中断标记置1,容许中断
    }
    DbgPrint(驱动卸载成功……\n);
    }


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

    我所有的自负皆来自我的自卑,所有的英雄气概都来自于我的软弱。嘴里振振有词是因为心里满是怀疑,深情是因为痛恨自己无情。这世界没有一件事情是虚空而生的,站在光里,背后就会有阴影,这深夜里一片寂静,是因为你还没有听见声音。—— 马良《坦白书》
    分享到: