binary-hardening

Installation
SKILL.md

二进制加固(Binary Hardening)

用途

引导代理启用和验证二进制安全缓解措施:checksec 分析、编译器和链接器加固标志(RELRO、PIE、栈金丝雀、FORTIFY_SOURCE、CFI)、硬件影子栈,以及用于纵深防御的 seccomp-bpf 系统调用过滤。

触发场景

  • "如何加固我的二进制文件以防止漏洞利用?"
  • "如何检查我的二进制文件具有哪些安全缓解措施?"
  • "checksec 输出的含义是什么?"
  • "如何启用 RELRO、PIE 和栈金丝雀?"
  • "如何用 seccomp 限制系统调用?"
  • "如何启用 CFI(控制流完整性)?"

工作流程

1. 用 checksec 分析现有二进制文件

# 安装 checksec
pip install checksec.py   # 或:apt install checksec

# 检查一个二进制文件
checksec --file=./mybinary
checksec --file=/usr/bin/ssh

# 输出示例
# RELRO          STACK CANARY   NX    PIE    RPATH  RUNPATH  Symbols  FORTIFY  Fortified  Fortifiable  FILE
# Full RELRO     Canary found   NX    PIE    No RPATH  No RUNPATH  No Symbols  Yes   6   10   ./mybinary

# 检查目录中的所有二进制文件
checksec --dir=/usr/bin
保护措施 良好值 需关注
RELRO Full RELRO(完全 RELRO) Partial / No RELRO
Stack Canary(栈金丝雀) Canary found(发现金丝雀) No canary
NX NX enabled(NX 已启用) NX disabled
PIE PIE enabled(PIE 已启用) No PIE
FORTIFY Yes No

2. 加固编译器和链接器标志

# 完整加固构建(GCC 或 Clang)
CFLAGS="-O2 -pipe \
  -fstack-protector-strong \
  -fstack-clash-protection \
  -fcf-protection \
  -D_FORTIFY_SOURCE=3 \
  -D_GLIBCXX_ASSERTIONS \
  -fPIE \
  -Wformat -Wformat-security -Werror=format-security"

LDFLAGS="-pie \
  -Wl,-z,relro \
  -Wl,-z,now \
  -Wl,-z,noexecstack \
  -Wl,-z,separate-code"

gcc ${CFLAGS} -o prog main.c ${LDFLAGS}

标志参考:

标志 保护措施 说明
-fstack-protector-strong 栈金丝雀 -fstack-protector 更强
-fstack-clash-protection 栈碰撞 防止大型栈分配
-fcf-protection Intel CET(IBT+SHSTK) x86 硬件 CFI(需要内核+CPU 支持)
-D_FORTIFY_SOURCE=2 缓冲区溢出检查 为字符串/内存函数添加边界检查
-D_FORTIFY_SOURCE=3 增强 FORTIFY GCC ≥12,Clang ≥12
-fPIE + -pie PIE/ASLR 位置无关可执行文件
-Wl,-z,relro 部分 RELRO main 前使 GOT 只读
-Wl,-z,now 完全 RELRO 启动时解析所有 PLT → GOT 完全只读
-Wl,-z,noexecstack NX 栈 将栈标记为不可执行

3. 控制流完整性(CFI)

Clang 的 CFI 防止通过错误类型调用虚函数(vtable CFI)以及对类型不匹配函数的间接调用:

# Clang CFI——需要 LTO 和可见性控制
clang -fsanitize=cfi -fvisibility=hidden -flto \
      -O2 -fPIE -pie main.cpp -o prog

# 特定 CFI 检查
clang -fsanitize=cfi-vcall          # 虚调用类型检查
clang -fsanitize=cfi-icall          # 间接调用类型检查
clang -fsanitize=cfi-derived-cast   # 派生到基类的转换
clang -fsanitize=cfi-unrelated-cast # 无关类型转换

# 跨 DSO 的 CFI(跨共享库——更复杂)
clang -fsanitize=cfi -fsanitize-cfi-cross-dso -flto -fPIC -shared
# Microsoft CFG(Windows 等价方案)
cl /guard:cf prog.c
link /guard:cf prog.obj

4. 栈金丝雀详解

# GCC 金丝雀选项
-fno-stack-protector       # 禁用
-fstack-protector          # 保护有 alloca 或缓冲区 > 8 字节的函数
-fstack-protector-strong   # 保护有本地数组或取地址的函数
-fstack-protector-all      # 保护所有函数(最慢,最全面)

# 验证金丝雀是否存在
objdump -d prog | grep -A5 "__stack_chk"
readelf -s prog | grep "stack_chk"

5. FORTIFY_SOURCE

FORTIFY_SOURCE 在编译时能确定缓冲区大小时,将不安全的 libc 函数(memcpy、strcpy、sprintf)替换为带边界检查的版本:

# 级别 2(加固构建的 GCC/Clang 默认值)
-D_FORTIFY_SOURCE=2
# 运行时检查:溢出时 abort()

# 级别 3(GCC ≥12,覆盖更多情况)
-D_FORTIFY_SOURCE=3
# 添加动态缓冲区大小跟踪,提高覆盖率

# 检查 FORTIFY 覆盖情况
objdump -d prog | grep "__.*_chk"     # 加固变体
checksec --file=prog | grep FORTIFY

6. seccomp-bpf 系统调用过滤

#include <seccomp.h>

void apply_seccomp_filter(void) {
    scmp_filter_ctx ctx;

    // 默认:对任何非白名单系统调用杀死进程
    ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);

    // 白名单所需的系统调用
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);

    // 应用过滤器(此后不可逆)
    seccomp_load(ctx);
    seccomp_release(ctx);
}

// 在 main() 中尽早调用,完成所有初始化之后
int main(void) {
    // ... 初始化 ...
    apply_seccomp_filter();
    // ... 受限操作 ...
}
# 用 strace 测试 seccomp 过滤器
strace -e trace=all ./prog 2>&1 | grep "killed by SIGSYS"

# 分析系统调用以构建白名单
strace -c ./prog    # 统计所有使用的系统调用

7. 影子栈(Intel CET / 硬件 SHSTK)

# 在支持的 x86 硬件上启用(Intel Tiger Lake+,内核 ≥6.6)
# -fcf-protection=full 同时启用 IBT 和 SHSTK
clang -fcf-protection=full -O2 -o prog main.c

# 检查二进制中的 CET 支持
readelf -n prog | grep "NT_GNU_PROPERTY"
objdump -d prog | grep "endbr64"   # IBT 末端分支指令

# 内核支持
cat /proc/cpuinfo | grep shstk     # CPU 支持

完整的加固标志参考,参见 references/hardening-flags.md

相关技能

  • 使用 skills/runtimes/sanitizers 在开发期间使用 ASan/UBSan
  • 使用 skills/observability/ebpf 通过 libbpf 编写 seccomp-bpf 程序
  • 使用 skills/rust/rust-security 了解 Rust 的内存安全加固方法
  • 使用 skills/binaries/elf-inspection 验证 ELF 二进制文件中的缓解措施
Related skills

More from killvxk/low-level-dev-skills-zh

Installs
1
First Seen
Mar 21, 2026