binary-hardening
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBinary 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
undefinedbash
undefinedInstall 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
undefinedbash
undefinedFull 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"
-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"
-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"
-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"
-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
undefinedClang的CFI可防止通过错误类型调用虚函数(vtable CFI),以及调用不匹配的间接函数:
bash
undefinedClang CFI — requires LTO and visibility
Clang CFI — requires LTO and visibility
clang -fsanitize=cfi -fvisibility=hidden -flto
-O2 -fPIE -pie main.cpp -o prog
-O2 -fPIE -pie main.cpp -o prog
clang -fsanitize=cfi -fvisibility=hidden -flto
-O2 -fPIE -pie main.cpp -o prog
-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
```bashclang -fsanitize=cfi -fsanitize-cfi-cross-dso -flto -fPIC -shared
```bashMicrosoft CFG (Windows equivalent)
Microsoft CFG (Windows equivalent)
cl /guard:cf prog.c
link /guard:cf prog.obj
undefinedcl /guard:cf prog.c
link /guard:cf prog.obj
undefined4. Stack canaries in depth
4. 栈金丝雀深入讲解
bash
undefinedbash
undefinedGCC 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"
undefinedobjdump -d prog | grep -A5 "__stack_chk"
readelf -s prog | grep "stack_chk"
undefined5. 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
undefinedFORTIFY_SOURCE会在编译时可确定缓冲区大小的情况下,将不安全的libc函数(memcpy、strcpy、sprintf等)替换为带边界检查的版本:
bash
undefinedLevel 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
undefinedobjdump -d prog | grep "__.*_chk" # fortified variants
checksec --file=prog | grep FORTIFY
undefined6. 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
undefinedc
#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
undefinedTest 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
undefinedstrace -c ./prog # count all syscalls used
undefined7. Shadow stack (Intel CET / Hardware SHSTK)
7. 影子栈(Intel CET / Hardware SHSTK)
bash
undefinedbash
undefinedEnable 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 for ASan/UBSan during development
skills/runtimes/sanitizers - Use for seccomp-bpf program writing with libbpf
skills/observability/ebpf - Use for Rust's memory-safety hardening approach
skills/rust/rust-security - Use to verify mitigations in ELF binaries
skills/binaries/elf-inspection
- 使用在开发阶段启用ASan/UBSan
skills/runtimes/sanitizers - 使用通过libbpf编写seccomp-bpf程序
skills/observability/ebpf - 使用了解Rust的内存安全加固方案
skills/rust/rust-security - 使用验证ELF二进制文件中的缓解措施
skills/binaries/elf-inspection