CC_STACKPROTECT补丁是Tejun Heo在09年给主线kernel提交的一个用来防止内核堆栈溢出的补丁。默认的config是将这个选项关闭的,可以在编译内核的时候,
修改.config文件为CONFIG_CC_STACKPROTECTOR=y来启用。未来飞天内核可以将这个选项开启来防止利用内核stack溢出的0day攻击。
这个补丁的防溢出原理是: 在进程启动的时候, 在每个buffer的后面放置一个预先设置好的stack canary,你可以
把它理解成一个哨兵, 当buffer发生缓冲区溢出的时候, 肯定会破坏stack canary的值, 当stack canary的值被破坏的时候, 内核就会直接当机。那么是怎么判断stack canary
被覆盖了呢? 其实这个事情是gcc来做的,内核在编译的时候给gcc加了个-fstack-protector参数, 我们先来研究下这个参数是做什么用的。
先写个简单的有溢出的程序:
[wzt@localhost csaw]$ cat test.c
#include <stdio.h>
#include <stdlib.h>
void test(void)
{
char buff[64];
memset(buff, 0x41, 128); //向64大小的buffer拷贝128字节, 肯定会发生缓冲区溢出。
}
int main(void)
{
test();
return 0;
}
[wzt@localhost csaw]$ gcc -o test test.c
[wzt@localhost csaw]$ ./test
段错误
反汇编看看:
[wzt@localhost csaw]$ objdump -d test > hex
08048384 <test>:
8048384: 55 push %ebp
8048385: 89 e5 mov %esp,%ebp
8048387: 83 ec 58 sub $0x58,%esp
804838a: c7 44 24 08 80 00 00 movl $0x80,0x8(%esp)
8048391: 00
8048392: c7 44 24 04 41 00 00 movl $0x41,0x4(%esp)
8048399: 00
804839a: 8d 45 c0 lea 0xffffffc0(%ebp),%eax
804839d: 89 04 24 mov %eax,(%esp)
80483a0: e8 e3 fe ff ff call 8048288 <memset@plt>
80483a5: c9 leave
80483a6: c3 ret
没什么特别的,我们在加上-fstack-protector参数看看:
[wzt@localhost csaw]$ gcc -o test test.c -fstack-protector
[wzt@localhost csaw]$ ./test
*** stack smashing detected ***: ./test terminated
已放弃
这次程序打印了一条堆栈被溢出的信息,然后就自动退出了。
在反汇编看下:
[wzt@localhost csaw]$ objdump -d test > hex1
080483d4 <test>:
80483d4: 55 push %ebp
80483d5: 89 e5 mov %esp,%ebp
80483d7: 83 ec 68 sub $0x68,%esp
80483da: 65 a1 14 00 00 00 mov %gs:0x14,%eax
80483e0: 89 45 fc mov %eax,0xfffffffc(%ebp)
80483e3: 31 c0 xor %eax,%eax
80483e5: c7 44 24 08 80 00 00 movl $0x80,0x8(%esp)
80483ec: 00
80483ed: c7 44 24 04 41 00 00 movl $0x41,0x4(%esp)
80483f4: 00
80483f5: 8d 45 bc lea 0xffffffbc(%ebp),%eax
80483f8: 89 04 24 mov %eax,(%esp)
80483fb: e8 cc fe ff ff call 80482cc <memset@plt>
8048400: 8b 45 fc mov 0xfffffffc(%ebp),%eax
8048403: 65 33 05 14 00 00 00 xor %gs:0x14,%eax
804840a: 74 05 je 8048411 <test+0x3d>
804840c: e8 db fe ff ff call 80482ec <__stack_chk_fail@plt>
8048411: c9 leave
8048412: c3 ret
使用-fstack-protector参数后, gcc在函数的开头放置了几条汇编代码:
80483d7: 83 ec 68 sub $0x68,%esp
80483da: 65 a1 14 00 00 00 mov %gs:0x14,%eax
80483e0: 89 45 fc mov %eax,0xfffffffc(%ebp)
将代码段gs偏移0x14内存处的值赋值给了ebp-4, 也就是第一个变量值的后面。
在call完memeset后,有如下汇编代码:
80483fb: e8 cc fe ff ff &nb