栈保护机制
- Stack Canary
- NX
- ASLR与PIE
- Relro
canary
canary意为金丝雀,作为栈保护技术之一,它的名字源自于17世纪,英国煤矿工人发现金丝雀对瓦斯十分敏感,每次下井都会带一只金丝雀作为“瓦斯检测指标”,从而挽救了很多工人的生命。
canary机制的原理很简单,就是在函数被调用之后,立即在栈帧中插入一个随机数,函数执行完在返回之前,程序通过检查这个随机数是否改变来判断是否存在栈溢出。
如图所示,如果buf数据覆盖了目标地址(红色)处的数据,那canary(黄棕色)处的数据也会改变。
canary机制的绕过
要绕过canary也很简单,就是先通过某些手段如利用格式化字符串漏洞将canary泄露,再利用栈溢出,用垃圾数据覆盖栈上数据时,只要保证canary数据保持不变即可。程序检查canary没有改变,便会继续正常执行。
示例
#include <stdio.h>
void shell(){
system("/bin/sh");
}
void vulnerable(){
char buf[12];
puts("input 1:");
read(0, buf, 100);
puts(buf);
puts("input 2:");
fgets(buf, 0x100, stdin);
}
void main(){
vulnerable();
}
编译链接一下
// gcc编译器默认开启canary保护
// 关闭栈保护 -fno-stack-protector
// 打开栈保护 -fstack-protector-all
gcc main.c -m32 -fstack-protector-all -no-pie -o canary
我们检查一下程序的保护机制:
xxx@xxx-PC:~/Desktop/templates/canary$ checksec canary
[*] '/home/xxx/Desktop/templates/canary/canary'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found // canary保护已生效
NX: NX enabled
PIE: No PIE (0x8048000)
xxx@xxx-PC:~/Desktop/templates/canary$
下面来看一下vulnerable函数的反汇编代码:
080491d7 <vulnerable>:
80491d7: 55 push ebp
80491d8: 89 e5 mov ebp,esp
80491da: 83 ec 18 sub esp,0x18
-------------------------set canary---------------------------
80491dd: 65 a1 14 00 00 00 mov eax,gs:0x14
80491e3: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
------------------------------------------------