代码中出现栈溢出的问题是程序员特别头疼的问题,gcc 提供了栈保护的选项能够在一定程度上帮助我们发现程序中存在的栈溢出的问题。# x- k9 m% R4 h7 i+ ] 4 F) G- ~1 J% r0 v( }, pgcc 提供了如下的编译选项:. ]) [. o7 `: y7 E http://www.cnblogs.com/napoleon_liu/archive/2011/02/14/1953983.html d- V. `/ W/ w e-fstack-protector/ M; [. ?" q" x$ @) Z+ n+ { Emit extra code to check for buffer overflows, such as stack smashing attacks. $ S* S2 {& D' Y( c }- f yThis is done by adding a guard variable to functions with vulnerable objects. ' Q- c" U% I5 o. G3 a* m' ~' NThis includes functions that call alloca, and functions with buffers larger than 9 \. N8 v$ F* R0 a8 bytes. The guards are initialized when a function is entered and then checked 4 [ D7 e7 G1 |( @/ Q. Dwhen the function exits. If a guard check fails, an error message is printed and 4 u. S D+ [& _the program exits.复制代码$ H8 Z1 `) T6 p, Q a& ] 编译时加上上述的编译选项,会在栈空间中额外追加8个字节保护变量(guard variable),函数退出的时候会check该guard variable,如果值被修改了,则会输出error message 并退出程序。 ' `+ J3 n" E& ^8 }1 Q" [按照上述的描述,编译选项也不是完全保证检测出栈溢出的问题,如果跳过了描述的规则也是无法检出的,如果正好避开了检查规则的话也是无法检出问题的。" i6 R4 {$ H, i7 f $ d& k. @' u8 h; X8 [( {9 W8 I8 t $ o2 f# @8 I& g- Y: h/ t测试代码如下:5 H1 ~9 A* \$ G0 E& F //gcc -fno-stack-protector fno-stack-protector_test.c -o fno-stack-protector_test9 j. I5 Q x# r1 n //gcc fno-stack-protector_test.c -o fno-stack-protector_test; H+ ^8 `: w' d ///sdk/4.3.2/bin/arm-linux-gcc-4.3.2 -fno-stack-protector -fomit-frame-pointer fno-stack-protector_test.c -o fno-stack-protector_test; v) R' c% j/ ] Z8 f. \) m ///sdk/4.3.2/bin/arm-linux-gcc-4.3.2 -fstack-protector-all -fomit-frame-pointer fno-stack-protector_test.c -o fno-stack-protector_test ' @4 w" T6 S9 A) f6 o; |///sdk/4.3.2/bin/arm-linux-objdump -S fno-stack-protector_test > fno-stack-protector_test.dis / z) x* U$ Y5 s$ i" R4 X- o- J# l#include <stdio.h>. s: z$ M2 t$ \1 N1 p! N' ^: m int main(void)) R* D) h3 M2 W# n { 7 l1 X0 n/ B7 \/ C. c9 [ char buffer[2]; k9 ~' e1 \2 q; d& Z" A& w; x int i; 1 j. [4 l$ o, L7 H. B i = 1;( [8 a& n8 d; P' f1 H; S buffer[0] = 'a';7 k7 V& |8 B8 |! H buffer[9] = 'b'; 9 p A: B* S4 h7 Z printf("hello.world\n"); * C" v6 y$ y: i/ h8 @/ g) [; B //while(1);; f& a& [6 \* z- m0 D( _* D( k return 0;' ]- N( q' s2 B# K- j }复制代码上述代码加上栈保护选项和去除时的代码比较会发现,加上编译选项的代码会在函数栈中额外多开辟8个字节的溢出检出空间,并在函数退出的时候追加固定值的比较,一旦发生变化则跳到对应的栈溢出处理函数中,从而产生core 文件让程序员解析问题。通过反汇编的代码可以看出来,实际比较的长度为四个字节,这个应该时跟编译器有关系,回头在用别的编译器在验证下。0 v; z1 W0 u/ d3 ~ G/ P7 \5 o& a+ m# G / b6 X( B/ Y' p9 `& K 9 k- D2 \4 @2 Z' V# h, K( T