GCC 4.1 中三个与堆栈保护有关的编译选项
-fstack-protector:
启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码。
-fstack-protector-all:
启用堆栈保护,为所有函数插入保护代码。
-fno-stack-protector:
禁用堆栈保护。
GCC 中的 Canaries 探测
下面通过一个例子分析 GCC 堆栈保护所生成的代码。分别使用 -fstack-protector 选项和 -fno-stack-protector 编译清单2中的代码得到可执行文件 demo_sp (-fstack-protector),demo_nosp (-fno-stack-protector)。
清单 2. demo.c
int main() {
int i;
char buffer[64];
i = 1;
buffer[0] = 'a';
return 0;
}
清单 3. demo_nosp 的汇编代码
(gdb) disas main
Dump of assembler code for function main:
0x08048344 <main+0>: lea 0x4(%esp),%ecx
0x08048348 <main+4>: and $0xfffffff0,%esp
0x0804834b <main+7>: pushl 0xfffffffc(%ecx)
0x0804834e <main+10>: push %ebp
0x0804834f <main+11>: mov %esp,%ebp
0x08048351 <main+13>: push %ecx
0x08048352 <main+14>: sub $0x50,%esp
0x08048355 <main+17>: movl $0x1,0xfffffff8(%ebp)
0x0804835c <main+24>: movb $0x61,0xffffffb8(%ebp)
0x08048360 <main+28>: mov $0x0,%eax
0x08048365 <main+33>: add $0x50,%esp
0x08048368 <main+36>: pop %ecx
0x08048369 <main+37>: pop %ebp
0x0804836a <main+38>: lea 0xfffffffc(%ecx),%esp
0x0804836d <main+41>: ret
End of assembler dump.
清单 4. demo_sp 的汇编代码
(gdb) disas main
Dump of assembler code for function main:
0x08048394 <main+0>: lea 0x4(%esp),%ecx
0x08048398 <main+4>: and $0xfffffff0,%esp
0x0804839b <main+7>: pushl 0xfffffffc(%ecx)
0x0804839e <main+10>: push %ebp
0x0804839f <main+11>: mov %esp,%ebp
0x080483a1 <main+13>: push %ecx
0x080483a2 <main+14>: sub $0x54,%esp
0x080483a5 <main+17>: mov %gs:0x14,%eax
0x080483ab <main+23>: mov %eax,0xfffffff8(%ebp)
0x080483ae <main+26>: xor %eax,%eax
0x080483b0 <main+28>: movl $0x1,0xffffffb4(%ebp)
0x080483b7 <main+35>: movb $0x61,0xffffffb8(%ebp)
0x080483bb <main+39>: mov $0x0,%eax
0x080483c0 <main+44>: mov 0xfffffff8(%ebp),%edx
0x080483c3 <main+47>: xor %gs:0x14,%edx
0x080483ca <main+54>: je 0x80483d1 <main+61>
0x080483cc <main+56>: call 0x80482fc <__stack_chk_fail@plt>
0x080483d1 <main+61>: add $0x54,%esp
0x080483d4 <main+64>: pop %ecx
0x080483d5 <main+65>: pop %ebp
0x080483d6 <main+66>: lea 0xfffffffc(%ecx),%esp
0x080483d9 <main+69>: ret
End of assembler dump. |