SMAP
这个其实就不用太多说了,SMAP(Supervisor Mode Access Prevention,管理模式访问保护),其作用旨在防止内核访问用户空间的数据,和SMEP(Supervisor Mode Execution Prevention)是一对好基友
绕过
一般来说,我们绕过它的办法大多是将数据拷贝至内核栈/堆中,防止直接访问ring3数据
但有的时候,利用条件比较苛刻的情况下,这个拷贝的操作也许根本无法触发
还有一种大家用的比较多的方法就是尝试在内核空间中找到类似mov cr4,xxx
这种语句,将cr4寄存器的第21,22位置零来分别绕过smep/smap
不过实战中,这种语句还是比较难找(欧洲人请绕道
新的绕过方式?
实际上,对比smap的好基友smep,内核访问用户态数据实际上还是一个比较大的需求,如果开启了smap,那么有一个疑问就出现了,系统是如何防止出现内核必须访问用户态数据的情况呢?换句话说,系统是如何bypass smap的呢?
先回ring3利用寄存器暂存数据后再回ring0?想想也不太现实,真这么干,内核效率将会极其低下,切换开销将会很大
那么就来看看系统是如何做的
经过网上冲浪后,找到了一种比较小众的办法
那就是利用intel指令集中的stac
指令(与其相对的是clac
指令)
贴一段wiki的解释
1 | Processors indicate support for Supervisor Mode Access Prevention through the Extended Features CPUID leaf. |
利用stac
指令就可以暂时“关闭”smap,从而使得内核可以访问ring3的数据
附一张图
可以看到,在检查了eflag后,调用了stac
暂时“关闭”smap