From 939db92dd597e0e1e4a3c186bb3db35fd902ca41 Mon Sep 17 00:00:00 2001 From: firmianay Date: Fri, 18 Aug 2017 15:16:30 +0800 Subject: [PATCH] update gcc --- doc/3.3.2_integer_overflow.md | 2 +- doc/4.3_gcc.md | 99 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/doc/3.3.2_integer_overflow.md b/doc/3.3.2_integer_overflow.md index 247d79f..e39375a 100644 --- a/doc/3.3.2_integer_overflow.md +++ b/doc/3.3.2_integer_overflow.md @@ -3,7 +3,7 @@ - [什么是整数溢出](#什么是整数溢出) - [整数溢出](#整数溢出) - [整数溢出示例](#整数溢出示例) -- [CTF 中的整数溢出](#CTF-中的整数溢出) +- [CTF 中的整数溢出](#ctf-中的整数溢出) ## 什么是整数溢出 diff --git a/doc/4.3_gcc.md b/doc/4.3_gcc.md index 0604736..4008592 100644 --- a/doc/4.3_gcc.md +++ b/doc/4.3_gcc.md @@ -11,6 +11,105 @@ Linux 中有各种各样的安全防护,其中 ASLR 是由内核直接提供 #### CANARY 启用 CANARY 后,函数开始执行的时候会先往栈里插入 canary 信息,当函数返回时验证插入的 canary 是否被修改,如果是,就停止运行。 +下面是一个例子: +```c +#include +void main(int argc, char **argv) { + char buf[10]; + scanf("%s", buf); +} +``` +我们先开启 CANARY,来看看执行的结果: +```text +$ gcc -m32 -fstack-protector canary.c -o f.out +$ python -c 'print("A"*20)' | ./f.out +*** stack smashing detected ***: ./f.out terminated +Segmentation fault (core dumped) +``` +接下来关闭 CANARY: +```text +$ gcc -m32 -fno-stack-protector canary.c -o fno.out +$ python -c 'print("A"*20)' | ./fno.out +Segmentation fault (core dumped) +``` +可以看到当开启 CANARY 的时候,提示检测到栈溢出和段错误,而关闭的时候,只有提示段错误。 + +下面对比一下反汇编代码上的差异: + +开启 CANARY 时: +```text +gdb-peda$ disassemble main +Dump of assembler code for function main: + 0x000005ad <+0>: lea ecx,[esp+0x4] + 0x000005b1 <+4>: and esp,0xfffffff0 + 0x000005b4 <+7>: push DWORD PTR [ecx-0x4] + 0x000005b7 <+10>: push ebp + 0x000005b8 <+11>: mov ebp,esp + 0x000005ba <+13>: push ebx + 0x000005bb <+14>: push ecx + 0x000005bc <+15>: sub esp,0x20 + 0x000005bf <+18>: call 0x611 <__x86.get_pc_thunk.ax> + 0x000005c4 <+23>: add eax,0x1a3c + 0x000005c9 <+28>: mov edx,ecx + 0x000005cb <+30>: mov edx,DWORD PTR [edx+0x4] + 0x000005ce <+33>: mov DWORD PTR [ebp-0x1c],edx + 0x000005d1 <+36>: mov ecx,DWORD PTR gs:0x14 ; 将 canary 值存入 ecx + 0x000005d8 <+43>: mov DWORD PTR [ebp-0xc],ecx ; 在栈 ebp-0xc 处插入 canary + 0x000005db <+46>: xor ecx,ecx + 0x000005dd <+48>: sub esp,0x8 + 0x000005e0 <+51>: lea edx,[ebp-0x16] + 0x000005e3 <+54>: push edx + 0x000005e4 <+55>: lea edx,[eax-0x1940] + 0x000005ea <+61>: push edx + 0x000005eb <+62>: mov ebx,eax + 0x000005ed <+64>: call 0x450 <__isoc99_scanf@plt> + 0x000005f2 <+69>: add esp,0x10 + 0x000005f5 <+72>: nop + 0x000005f6 <+73>: mov eax,DWORD PTR [ebp-0xc] ; 从栈中取出 canary + 0x000005f9 <+76>: xor eax,DWORD PTR gs:0x14 ; 检测 canary 值 + 0x00000600 <+83>: je 0x607 + 0x00000602 <+85>: call 0x690 <__stack_chk_fail_local> + 0x00000607 <+90>: lea esp,[ebp-0x8] + 0x0000060a <+93>: pop ecx + 0x0000060b <+94>: pop ebx + 0x0000060c <+95>: pop ebp + 0x0000060d <+96>: lea esp,[ecx-0x4] + 0x00000610 <+99>: ret +End of assembler dump. +``` + +关闭 CANARY 时: +```text +gdb-peda$ disassemble main +Dump of assembler code for function main: + 0x0000055d <+0>: lea ecx,[esp+0x4] + 0x00000561 <+4>: and esp,0xfffffff0 + 0x00000564 <+7>: push DWORD PTR [ecx-0x4] + 0x00000567 <+10>: push ebp + 0x00000568 <+11>: mov ebp,esp + 0x0000056a <+13>: push ebx + 0x0000056b <+14>: push ecx + 0x0000056c <+15>: sub esp,0x10 + 0x0000056f <+18>: call 0x59c <__x86.get_pc_thunk.ax> + 0x00000574 <+23>: add eax,0x1a8c + 0x00000579 <+28>: sub esp,0x8 + 0x0000057c <+31>: lea edx,[ebp-0x12] + 0x0000057f <+34>: push edx + 0x00000580 <+35>: lea edx,[eax-0x19e0] + 0x00000586 <+41>: push edx + 0x00000587 <+42>: mov ebx,eax + 0x00000589 <+44>: call 0x400 <__isoc99_scanf@plt> + 0x0000058e <+49>: add esp,0x10 + 0x00000591 <+52>: nop + 0x00000592 <+53>: lea esp,[ebp-0x8] + 0x00000595 <+56>: pop ecx + 0x00000596 <+57>: pop ebx + 0x00000597 <+58>: pop ebp + 0x00000598 <+59>: lea esp,[ecx-0x4] + 0x0000059b <+62>: ret +End of assembler dump. +``` + #### FORTIFY FORTIFY 的选项 `-D_FORTIFY_SOURCE` 往往和优化 `-O` 选项一起使用,以检测缓冲区溢出的问题。