binary-hardening

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Binary Hardening

二进制加固

Purpose

用途

Guide agents through enabling and verifying binary security mitigations: checksec analysis, compiler and linker hardening flags (RELRO, PIE, stack canaries, FORTIFY_SOURCE, CFI), hardware shadow stack, and seccomp-bpf syscall filtering for defense-in-depth.
指导Agent启用和验证二进制安全缓解措施:checksec分析、编译器与链接器加固标志(RELRO、PIE、栈金丝雀、FORTIFY_SOURCE、CFI)、硬件影子栈,以及用于纵深防御的seccomp-bpf系统调用过滤。

Triggers

触发场景

  • "How do I harden my binary against exploits?"
  • "How do I check what security mitigations my binary has?"
  • "What does checksec output mean?"
  • "How do I enable RELRO, PIE, and stack canaries?"
  • "How do I use seccomp to restrict syscalls?"
  • "How do I enable CFI (control flow integrity)?"
  • "如何加固我的二进制文件以抵御漏洞利用?"
  • "如何检查我的二进制文件具备哪些安全缓解措施?"
  • "checksec的输出是什么意思?"
  • "如何启用RELRO、PIE和栈金丝雀?"
  • "如何使用seccomp限制系统调用?"
  • "如何启用Control Flow Integrity (CFI)?"

Workflow

工作流程

1. Analyze existing binary with checksec

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

bash
undefined
bash
undefined

Install checksec

Install checksec

pip install checksec.py # or: apt install checksec
pip install checksec.py # or: apt install checksec

Check a binary

Check a binary

checksec --file=./mybinary checksec --file=/usr/bin/ssh
checksec --file=./mybinary checksec --file=/usr/bin/ssh

Output example

Output example

RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE

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

Full RELRO Canary found NX PIE No RPATH No RUNPATH No Symbols Yes 6 10 ./mybinary

Check all binaries in a directory

Check all binaries in a directory

checksec --dir=/usr/bin

| Protection | Good value | Concern |
|-----------|-----------|---------|
| RELRO | Full RELRO | Partial / No RELRO |
| Stack Canary | Canary found | No canary |
| NX | NX enabled | NX disabled |
| PIE | PIE enabled | No PIE |
| FORTIFY | Yes | No |
checksec --dir=/usr/bin

| 防护机制 | 理想状态 | 需关注情况 |
|-----------|-----------|---------|
| RELRO | Full RELRO | Partial / No RELRO |
| Stack Canary | Canary found | No canary |
| NX | NX enabled | NX disabled |
| PIE | PIE enabled | No PIE |
| FORTIFY | Yes | No |

2. Hardening compiler and linker flags

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

bash
undefined
bash
undefined

Full hardened build (GCC or Clang)

Full hardened build (GCC or 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}

Flag reference:

| Flag | Protection | Notes |
|------|-----------|-------|
| `-fstack-protector-strong` | Stack canary | Stronger than `-fstack-protector` |
| `-fstack-clash-protection` | Stack clash | Prevents huge stack allocations |
| `-fcf-protection` | Intel CET (IBT+SHSTK) | x86 hardware CFI (kernel+CPU required) |
| `-D_FORTIFY_SOURCE=2` | Buffer overflow checks | Adds bounds checks to string/mem functions |
| `-D_FORTIFY_SOURCE=3` | Enhanced FORTIFY | GCC ≥12, Clang ≥12 |
| `-fPIE` + `-pie` | PIE/ASLR | Position independent executable |
| `-Wl,-z,relro` | Partial RELRO | Makes GOT read-only before `main` |
| `-Wl,-z,now` | Full RELRO | Resolves all PLT at startup → GOT fully RO |
| `-Wl,-z,noexecstack` | NX stack | Marks stack non-executable |
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` | Partial RELRO | 在`main`函数前将GOT设为只读 |
| `-Wl,-z,now` | Full RELRO | 启动时解析所有PLT → GOT完全只读 |
| `-Wl,-z,noexecstack` | NX栈 | 将栈标记为不可执行 |

3. Control Flow Integrity (CFI)

3. 控制流完整性(CFI)

Clang's CFI prevents calling virtual functions through wrong types (vtable CFI) and indirect calls to mismatched functions:
bash
undefined
Clang的CFI可防止通过错误类型调用虚函数(vtable CFI),以及调用不匹配的间接函数:
bash
undefined

Clang CFI — requires LTO and visibility

Clang CFI — requires LTO and visibility

clang -fsanitize=cfi -fvisibility=hidden -flto
-O2 -fPIE -pie main.cpp -o prog
clang -fsanitize=cfi -fvisibility=hidden -flto
-O2 -fPIE -pie main.cpp -o prog

Specific CFI checks

Specific CFI checks

clang -fsanitize=cfi-vcall # virtual call type check clang -fsanitize=cfi-icall # indirect call type check clang -fsanitize=cfi-derived-cast # derived-to-base cast clang -fsanitize=cfi-unrelated-cast # unrelated type cast
clang -fsanitize=cfi-vcall # virtual call type check clang -fsanitize=cfi-icall # indirect call type check clang -fsanitize=cfi-derived-cast # derived-to-base cast clang -fsanitize=cfi-unrelated-cast # unrelated type cast

Cross-DSO CFI (across shared libraries — more complex)

Cross-DSO CFI (across shared libraries — more complex)

clang -fsanitize=cfi -fsanitize-cfi-cross-dso -flto -fPIC -shared

```bash
clang -fsanitize=cfi -fsanitize-cfi-cross-dso -flto -fPIC -shared

```bash

Microsoft CFG (Windows equivalent)

Microsoft CFG (Windows equivalent)

cl /guard:cf prog.c link /guard:cf prog.obj
undefined
cl /guard:cf prog.c link /guard:cf prog.obj
undefined

4. Stack canaries in depth

4. 栈金丝雀深入讲解

bash
undefined
bash
undefined

GCC canary options

GCC canary options

-fno-stack-protector # disabled -fstack-protector # protect functions with alloca or buffers > 8 bytes -fstack-protector-strong # protect functions with local arrays/addresses taken -fstack-protector-all # protect all functions (slowest, most complete)
-fno-stack-protector # disabled -fstack-protector # protect functions with alloca or buffers > 8 bytes -fstack-protector-strong # protect functions with local arrays/addresses taken -fstack-protector-all # protect all functions (slowest, most complete)

Verify canary presence

Verify canary presence

objdump -d prog | grep -A5 "__stack_chk" readelf -s prog | grep "stack_chk"
undefined
objdump -d prog | grep -A5 "__stack_chk" readelf -s prog | grep "stack_chk"
undefined

5. FORTIFY_SOURCE

5. FORTIFY_SOURCE

FORTIFY_SOURCE wraps unsafe libc functions (memcpy, strcpy, sprintf) with bounds-checked versions when the buffer size can be determined at compile time:
bash
undefined
FORTIFY_SOURCE会在编译时可确定缓冲区大小的情况下,将不安全的libc函数(memcpy、strcpy、sprintf等)替换为带边界检查的版本:
bash
undefined

Level 2 (GCC/Clang default for hardened builds)

Level 2 (GCC/Clang default for hardened builds)

-D_FORTIFY_SOURCE=2
-D_FORTIFY_SOURCE=2

Runtime check: abort() on overflow

Runtime check: abort() on overflow

Level 3 (GCC ≥12, catches more cases)

Level 3 (GCC ≥12, catches more cases)

-D_FORTIFY_SOURCE=3
-D_FORTIFY_SOURCE=3

Adds dynamic buffer size tracking for more coverage

Adds dynamic buffer size tracking for more coverage

Check FORTIFY coverage

Check FORTIFY coverage

objdump -d prog | grep "__.*_chk" # fortified variants checksec --file=prog | grep FORTIFY
undefined
objdump -d prog | grep "__.*_chk" # fortified variants checksec --file=prog | grep FORTIFY
undefined

6. seccomp-bpf syscall filtering

6. seccomp-bpf系统调用过滤

c
#include <seccomp.h>

void apply_seccomp_filter(void) {
    scmp_filter_ctx ctx;

    // Default: kill process on any non-allowlisted syscall
    ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);

    // Allowlist needed syscalls
    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);

    // Apply filter (irreversible after this point)
    seccomp_load(ctx);
    seccomp_release(ctx);
}

// Call early in main(), after all setup
int main(void) {
    // ... initialization ...
    apply_seccomp_filter();
    // ... restricted operation ...
}
bash
undefined
c
#include <seccomp.h>

void apply_seccomp_filter(void) {
    scmp_filter_ctx ctx;

    // Default: kill process on any non-allowlisted syscall
    ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);

    // Allowlist needed syscalls
    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);

    // Apply filter (irreversible after this point)
    seccomp_load(ctx);
    seccomp_release(ctx);
}

// Call early in main(), after all setup
int main(void) {
    // ... initialization ...
    apply_seccomp_filter();
    // ... restricted operation ...
}
bash
undefined

Test seccomp filter with strace

Test seccomp filter with strace

strace -e trace=all ./prog 2>&1 | grep "killed by SIGSYS"
strace -e trace=all ./prog 2>&1 | grep "killed by SIGSYS"

Profile syscalls to build allowlist

Profile syscalls to build allowlist

strace -c ./prog # count all syscalls used
undefined
strace -c ./prog # count all syscalls used
undefined

7. Shadow stack (Intel CET / Hardware SHSTK)

7. 影子栈(Intel CET / Hardware SHSTK)

bash
undefined
bash
undefined

Enable on supported x86 hardware (Intel Tiger Lake+, kernel ≥6.6)

Enable on supported x86 hardware (Intel Tiger Lake+, kernel ≥6.6)

-fcf-protection=full enables both IBT and SHSTK

-fcf-protection=full enables both IBT and SHSTK

clang -fcf-protection=full -O2 -o prog main.c
clang -fcf-protection=full -O2 -o prog main.c

Check CET support in binary

Check CET support in binary

readelf -n prog | grep "NT_GNU_PROPERTY" objdump -d prog | grep "endbr64" # IBT end-branch instructions
readelf -n prog | grep "NT_GNU_PROPERTY" objdump -d prog | grep "endbr64" # IBT end-branch instructions

Kernel support

Kernel support

cat /proc/cpuinfo | grep shstk # CPU support

For the full hardening flags reference, see [references/hardening-flags.md](references/hardening-flags.md).
cat /proc/cpuinfo | grep shstk # CPU support

完整的加固标志参考,请查看[references/hardening-flags.md](references/hardening-flags.md)。

Related skills

相关技能

  • Use
    skills/runtimes/sanitizers
    for ASan/UBSan during development
  • Use
    skills/observability/ebpf
    for seccomp-bpf program writing with libbpf
  • Use
    skills/rust/rust-security
    for Rust's memory-safety hardening approach
  • Use
    skills/binaries/elf-inspection
    to verify mitigations in ELF binaries
  • 使用
    skills/runtimes/sanitizers
    在开发阶段启用ASan/UBSan
  • 使用
    skills/observability/ebpf
    通过libbpf编写seccomp-bpf程序
  • 使用
    skills/rust/rust-security
    了解Rust的内存安全加固方案
  • 使用
    skills/binaries/elf-inspection
    验证ELF二进制文件中的缓解措施