PWN-栈保护机制
PWN-栈保护机制
一、CANARY(栈溢出保护)
栈溢出保护是一种缓解缓冲区溢出攻击的手段。当函数存在缓冲区溢出攻击漏洞时,攻击者可以通过覆盖栈上的返回地址来让shellcode能够执行。当启用栈保护后,函数开始执行的时候会往栈中插入cookie信息,当函数真正返回时验证cookie信息是否合法,如果不合法就会停止程序运行,从而防止攻击者覆盖返回地址的行为。攻击者在覆盖返回地址的时候往往也会讲cookie信息覆盖掉,导致栈保护检查失败,所以会终止程序来阻止shellcode的执行,在Linux中将cookie信息称为canary。开启栈溢出保护时,虽然不能覆盖canary信息,但是可以对canary的前面进行溢出。
GCC编译时的用法:
1 | gcc -o test test.c // 默认情况下,不开启Canary保护 |
二、FORTIFY
fortify可以用于检查缓冲区溢出、格式化字符串等类型的漏洞。适用于程序采用大量字符串或者内存操作的函数
比如:
memcpy
[https://baike.baidu.com/item/memcpy/659918?fr=aladdin]:
memset
[https://baike.baidu.com/item/memset?fromModule=lemma_search-box]:
strcpy
[https://baike.baidu.com/item/strcpy?fromModule=lemma_search-box]:
stpcpy
[https://baike.baidu.com/item/stpcpy?fromModule=lemma_search-box]:
strncpy
[https://baike.baidu.com/item/strncpy?fromModule=lemma_search-box]:
strcat
[https://baike.baidu.com/item/strcat?fromModule=lemma_search-box]:
strncat
[https://baike.baidu.com/item/strncat?fromModule=lemma_search-box]:
sprintf
[https://baike.baidu.com/item/sprintf?fromModule=lemma_search-box]:
snprintf
vsprintf
[https://baike.baidu.com/item/vsprintf?fromModule=lemma_search-box]:
vsnprintf
[https://baike.baidu.com/item/_vsnprintf/5395011?fromModule=search-result_lemma-recommend]:
gets
[https://baike.baidu.com/item/gets?fromModule=lemma_search-box]:
GCC编译时的用法:
1 | gcc -D_FORTIFY_SOURCE=1 //仅仅只在编译时进行检查(尤其是#include<string.h>这种头文件 |
程序执行时检查是对数组大小进行判断替换strcpy、memcpy、memset等函数名,从而达到防止缓冲区溢出的作用
三、NX(DEP)
NX即No-eXecute(不可执行)的意思,NX(DEP)是一种内存保护技术,它的基本原理是将数据所在内存页标识为不可执行,当程序成功溢出转入shellcode时,程序会尝试在数据页面执行命令,此时CPU就会抛出异常,而不去执行恶意指令,主要防止在数据区溢出。
GCC用法:
1 | gcc -o test test.c // 默认情况下,开启NX保护 |
NX(DEP)保护机制会阻止程序在数据页面上执行指令,从而防止攻击者通过执行恶意代码来获得shell
四、PIE(ASLR)
ASLR(地址空间分布随机化)是一种内存保护技术,它通过随机化程序在内存中的位置来防止缓冲区溢出攻击。一般情况下会和NX(windows平台称为DEP)同时工作。
分为三种情况
1 | 0 - 表示关闭进程地址随机化 |
当ASLR设置为2时,操作系统不仅会随机化栈和库的地址,还会随机化堆的地址,从而增强系统的安全性。
可以防止Ret2lic方式(Ret2libc攻击是攻击者用来绕过DEP(数据执行防护)保护的一种技术。在Ret2libc攻击中,攻击者将程序流重定向到C标准库中的函数)针对DEP的攻击。ALSR和DEP的配合使用,能有效阻止攻击者在堆栈上运行恶意代码
Linux下关闭PIE的命令:
1 | sudo -s echo 0 > /proc/sys/kernel/randomize_va_space |
GCC编译时用法:
1 | gcc -o test test.c // 默认情况下,不开启PIE |
五、RELRO
在Linux系统安全领域数据可以写的存储区就会是攻击的目标,尤其是存储函数指针的区域。所以在安全防护的角度应尽量减少可写的存储区域。
RELRO有两种模式:部分和完整。部分RELRO是GCC的默认设置,几乎所有的二进制文件都至少具有部分RELRO。完整的RELRO使整个全局偏移表(GOT)只读,从而消除了执行“GOT覆盖”攻击的能力 。
GCC用法:
1 | gcc -o test test.c // 默认情况下,是Partial RELRO |