在本章中,将会为大家讲解关于linux中用户态程序保护机制的内容,首先我们要了解什么是用户态:
图:用户空间、内核空间和硬件示意图01用户态
linux有内核空间和用户空间这两类空间。
内核空间:由系统来操作的一块空间,存放着系统内核函数、接口,控制着计算机的硬件等资源。
用户空间:即用户可以操作和访问的空间,一般我们运行的程序就在这一空间。
而在用户空间下执行的程序的这种状态,我们称之为用户态。简单来说,本章中讲解的就是我们正常运行的程序其保护机制。
图:调用do_signal过程示意图02保护机制
linux下用户态的保护机制可分为四种:NX、PIE、Canary、RELRO,下面将对这四种保护机制进行讲解。
//NX
NX全称noexecute,即不可执行的意思,NX的基本原理是通过将内存页的写权限跟执行权限分离,从而避免shellcode注入。这样当程序尝试执行存放在不可执行内存地址处的指令时,会抛出异常,避免被shellcode提权。gcc默认开启了NX选项,可以通过-zexecstack参数关闭:
-zexecstack#禁用NX保护-znoexecstack#开启NX保护
//Canary
Canary即stackcanary,即堆栈保护技术,是缓解栈溢出的一种手段。它通过在栈上的返回地址跟ebp之间加上一个标志位canary(该标志位在程序运行时生成,存放在TLS中,通过fs寄存器指向该结构),返回时通过验证这个canary是否被改写,从而判断程序是否被栈溢出攻击。gcc编译时,可以用以下参数来设置:
-fstack-protector#启用保护,不过只为局部变量中含有数组的函数插入保护-fstack-protector-all#启用保护,为所有函数插入保护-fstack-protector-explicit#只对有明确stack_protectattribute的函数开启保护-fno-stack-protector#禁用保护
//PIE
PIE全称position-independentexecutable,即地址无关可执行文件。该技术是一个针对代码段(.text)、数据段(.data)、未初始化全局变量段(.bss)等固定地址的一个防护技术,如果程序开启了PIE保护的话,在每次加载程序时都变换加载地址。gcc编译时,可以用以下参数来设置:
-fpie-pie#开启PIE,此时强度为1-fPIE-pie#开启PIE,此时为最高强度2-fpic#开启PIC,此时强度为1,不会开启PIE-fPIC#开启PIC,此时为最高强度2,不会开启PIE
值得注意的是,PIC、PIE两者有别,PIC一般用于共享库,而PIE则是我们的程序。另外,只有在系统随机化功能开启的时候,PIE才真正的开启。否则,每次运行程序时,程序的装载地址都是固定不变的。可以通过如下命令查看当前系统随机化功能的状态:
cat/proc/sys/kernel/randomize_va_space
其中,返回值有如下含义:
0=关闭
1=半随机。共享库、栈、mmap()以及VDSO将被随机化。
2=全随机。除了1中所述,还有heap。
可以通过如下命令修改为全随机化:
sudosysctl-wkernel.randomize_va_space=2
//RELRO
RELRO全称readonlyrelocation,是用来保护重定向表的(该表中存放着动态编译的程序所需要的动态库函数的地址,一般称为.got表)。该保护机制分为两种,即PartialRELRO和FullRELRO。
PartialRELRO:这是gcc默认的模式,在该模式下具有对.got表写入的权限,而程序也会在第一次运行对应函数时才加载地址。这样做的好处是可以节省程序启动开销,但缺点是其内容可以被改写,用户可以通过修改.got表等的函数指针从而劫持程序。
FullRELRO:这一模式开启后,程序会在载入时将动态库的函数等地址写入相应位置,并将其设置为只读状态。这样就避免了被劫持函数指针的风险,但相应的程序启动时消耗的资源就会变多。
这两个模式在gcc中可以通过以下参数设置:
-zrelro#PartialRELRO-zrelro-znow#FullRELRO
03小结
用户态中程序的保护机制有NX、PIE、Canary、RELRO四种,它们能在一定程度上保证程序不被攻破。但是,这些机制能提供的保护还是有限的,现在也有各种绕过保护的方法,所以最好的是在开发过程中就要做好安全保护,而不是单纯依赖于其他保护机制的防护。
-END--扫码
本文编辑:佚名
转载请注明出地址 http://www.smartcarf.com/smartcartd/8633.html