这两个位都在cr4寄存器上
一、SMEP位
不允许0环执行用户层代码页
二、SMAP位
不允许内核权限读写用户代码页
三、实验SMEP
两个文件
x64asm.asm属性:
ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm
$(IntDir)%(fileName).obj
项目属性:
构造中断门描述符挂idt表
idt表中第21个位置没有使用,我们导入自己的中断描述符
!idt
运行代码
我门这里直接蓝屏了,原因是发生了三重错误
这就是SMEP存在的原因
查看cr4的值
修改cr4的值
3改成2即可
再次运行程序
能正常运行且不蓝屏
四、实验(SMAP)
代码
我们运行后,任然会蓝屏,这时候我们可以同时修改smap标志位为0
但还有另一种办法,也就是系统的办法
系统难面也要从用户层读写到特权级
有一条指令叫stac指令,STAC指令相当于Set AC,用于设置AC标志位(eflag),能暂时解除系统的一些保护,包括SMAP保护。
这里我们使用 stac指令测试
代码:
我们挂上idt表,再把smep置零,再次实验,也是成功读取
注意
我们读取 KVASCODE中的代码是没问题的, 但要读text是会发生三重错误的
这是页表隔离机制引起的(KPTI),如果要读取text段的代码,需要修改页属性
目前暂时知道可读区域为 gdt表,idt表和KVACODE
代码如下:
x64asm.asm
option casemap:none
EXTERN x:qword
.DATA
.CODE
IntEntry PROC
mov rax, qword ptr [0fffff8056166efd0h]
db 0fh,01h,0cbh
;stac
mov x, rax
iretq
IntEntry ENDP
go PROC
int 21h
ret
go ENDP
END
main.cpp:
#include
#include
extern "C" void IntEntry();
extern "C" void go();
extern "C" ULONG64 x;
ULONG64 x;
void main()
{
if ((ULONG64)IntEntry != 0x0000000100001000)
{
printf("wrong IntEntry at %p \n", IntEntry);
system("pause");
exit(-1);
}
go();
printf("%p \n", x);
system("pause");
}