源码防护-FORTIFY-SOURCE
源码防护-fortify_source 由于第一篇FORTIFY刚接触也没咋碰到,了解的也不多 现在回过头来发现当时写的糊里糊涂, 所以本篇继续深入FORTIFY防护 Fortify Source 是什么 本质:GCC 的编译时/运行时缓冲区溢出检测机制,属于源码级保护(不是二进制层面的 NX/Canary 那种) 保护对象:标准库中的高风险函数(strcpy、memcpy、sprintf、gets 等),一般主要是和字符串相关的函数。 FORTIFY_SOURCE 是 GCC/glibc 提供的一种编译时 + 运行时联合防护机制,通过将危险的 C 库函数替换为带边界检查的安全版本(__*_chk 后缀函数),在编译期和运行期检测缓冲区溢出。 核心思想: 编译器在编译时尽可能推断出缓冲区大小,如果能在编译期判定溢出就直接报错;如果编译期无法确定,就插入运行时检查代码,在溢出发生的瞬间终止程序。 Fortify Source干了什么 要想知道Fortify Source干了什么,那就要先看看如果没有Fortify Source会发生什么 char buf[32]; strcpy(buf, user_input); //① memcpy(buf, src, len); //② sprintf(buf, "%s", str); //③ read(fd, buf, 1024); //④ 先来看这段源码,毫无疑问的,①②③④这四条语句都有安全漏洞: ①完全没有长度检查,溢出 ②len作为变量可能会>32 ③str也可能长度>32 ④1024>32毫无疑问的溢出 而编译器对这些代码没有任何反应,也就是说,对生成的代码不会做任何的边界检查 Fortify Source的工作机制 工作流程: 源代码:strcpy(buf, src) │ ▼ ┌───────────────────────────┐ │ 预处理阶段(宏替换) │ │ #include <string.h> │ │ FORTIFY 宏将 strcpy 替换为 │ │ __builtin___strcpy_chk() │ └───────────┬───────────────┘ │ ▼ ┌───────────────────────────────────┐ │ 编译阶段(GCC 内置函数处理) │ │ │ │ GCC 尝试用 __builtin_object_size() │ │ 推断 buf 的大小 │ │ │ ├──── 能确定大小 ────────────────────┤ │ │ │ │ ├─ 编译期可判定溢出 │ │ │ → 编译错误/警告 │ │ │ │ │ ├─ 编译期可判定安全 │ │ │ → 优化为普通 strcpy(零开销) │ │ │ │ │ └─ 编译期无法确定 │ │ → 插入运行时检查 │ │ → 调用 __strcpy_chk() │ │ │ ├──── 不能确定大小 ──────────────────┤ │ → 退化为普通 strcpy(无法保护) │ └──────────────────────────────────┘ 而工作流程中的三个关键组件: ...