gcc 编译基本姿势

2022-04-11

PS:更新于2024-10-3

1. 保护参数

NX:-z execstack / -z noexecstack (关闭 / 开启)    不让执行栈上的数据,于是JMP ESP就不能用了

Canary:-fno-stack-protector /-fstack-protector / -fstack-protector-all (关闭 / 开启(局部变量里有数组的函数) / 全开启(全部函数))  

PIE:-no-pie / -pie (关闭 / 开启)   生成位置无关代码,针对 .text, .data, .bss段

RELRO:-z norelro / -z lazy / -z now (关闭 / 部分开启 / 完全开启)  对GOT表具有写权限

2. aslr 开启与关闭

sudo sysctl -w kernel.randomize_va_space=0 #关闭
sudo sysctl -w kernel.randomize_va_space=1 #随机化 stack、mmap、library 地址,如果elf是pie的话,也会随机化elf的.text .data .bss段地址
sudo sysctl -w kernel.randomize_va_space=2 #在1的基础上,随机化heap地址

原文链接

3. 编译选项

gcc -E test.c -o test.e  # 仅预处理
gcc -S test.c -o test.s  # 仅到编译阶段生成汇编文件
gcc -c test.c -o test.o  # 仅到汇编阶段,生成目标文件,但还没有链接
gcc -v test.c -o test    # 仅到链接阶段,生成可执行文件

gcc -I../include -L../lib -lmylib main.c -o my_program
# -I 告诉gcc,去../include目录中找所需头文件
# -L 告诉gcc,去../lib找所需的库文件(so)
# -l 告诉gcc,链接libmylib.a或libmylib.so文件,(注意要把前缀的lib和后缀.a .so去掉)

4. 生成静态库

静态库文件其实是在链接阶段时被链接进入目标程序中,目标程序含有静态库的所有代码,在生成目标文件后,即使删除静态库文件,也不影响其正确运行

gcc -c xxx.c -o xxx.o
ar rcs libxxx.a xxx.o
gcc -o target target.o -L . -lxxx

5. 生成动态库

动态库在 程序运行时,碰到执行动态库中函数的情景之后,才会加载动态库到程序的内存空间当中。

gcc -shared -fPIC -o libxxx.so xxx.c 
gcc -o target target.o -L . -lxxx

另外,需要把编译后的so库放到/usr/lib64/这种系统库的路径,这样程序执行的时候才能搜索到该so