SMEP和SMAP

@lzeroyuee  October 3, 2020

SMEP和SMAP

SMEP在CR4寄存器的第20位,SMAP在CR4寄存器的第21位

1.png

简单来说

  • 当SMEP启用时,内核不能执行来自用户层地址的指令
  • 当SMAP启用时,内核不能读写来自用户层地址

    • EFLAGS.AC标志位置位,则SMAP失效

验证SMEP

/********************* main.cpp *****************************/
#include <stdio.h>
#include <Windows.h>

extern "C" void Message();  // 0x00000001400010E0
extern "C" void int21();    // 21号中断基本没用

extern "C" ULONG64 x;
ULONG64 x;

int main(void)
{
    printf("Func: 0x%p\n", Message);
    if(ULONG64(Message) != 0x00000001400010E0) {    // Message函数的地址
        printf("Message Func Address Error\n");
        exit(1);
    }
    int21();
    system("pause");
    return 0;
}

/********************* myasm.asm *****************************/
option casemap:none
extern MessageBoxA:proc
extern ExitProcess:Proc
includelib user32.lib
includelib kernel32.lib

extern x:qword

.const
MYMSG1 db "Hello World", 0
TITLE1 db "x64 asm", 0
.code
Message proc
    iretq
Message endp


int21 proc
    int 21h
    ret
int21 endp

end

修改idt 21,指向函数Message,接着运行,直接崩溃蓝屏

然后将CR4的第20位置0,然后重复实验,正常运行

2.png

验证SMAP

修改验证代码,关闭SMEP的前提下在Message函数中,读取R0地址,赋给变量x,然后打印出来,这里读取idtr的第一项

3.png

...
int21();
printf("idtr[0]: %#x\n", x);        // 打印
system("pause");
...
    
...
Message proc
    ; stac
    mov rax, qword ptr [0fffff80342672000h]
    mov x, rax
    iretq
Message endp
...

再次运行,依然会崩溃蓝屏

然后将CR4的第21位置0,然后重复实验,正常运行

4.png

除了修改CR4的第21位,还可以利用stac指令来开启SMAP许可(在内核中就是这么做的,因为在内核中,有些时候是需要读写R3的地址,例如参数返回值的拷贝工作)

5.png

其原理是:EFLAGS寄存器中有个AC标志位,当AC标志位置位时,SMAP就不再检测

clac指令用于清除EFLAGSAC标志位


添加新评论