DEV Community

Cover image for Are You Still Checking Binary Hardening by Hand? I Built bincheck in Rust
Kazuma Koga
Kazuma Koga

Posted on

Are You Still Checking Binary Hardening by Hand? I Built bincheck in Rust

Why I built this

I've worked in embedded development and in security tooling. There was a gap where those two worlds met.

Binary hardening checks — RELRO, PIE, stack protection — are things embedded developers naturally think about. But there's no tool to automate them in CI (at least none I could find). SCA tools check your source code and licenses, but they don't look at the hardening state of the binary you actually ship.

I thought there was demand for something that filled that gap, so I built it.


What are hardening flags?

Hardening flags are security features applied by the compiler or linker at build time. The five main ones for ELF binaries:

  • RELRO (Relocation Read-Only): Makes the GOT read-only. Full RELRO is ideal.
  • Stack Canary: A canary value placed on the stack to detect buffer overflows. If it's been tampered with before the function returns, the process terminates.
  • NX (No eXecute): Marks the stack and heap as non-executable. Basic defense against shellcode injection.
  • PIE (Position Independent Executable): Required for ASLR (address space layout randomization) to work.
  • Fortify Source: When built with _FORTIFY_SOURCE, dangerous functions like strcpy are replaced with safer versions that detect buffer overflows at runtime. bincheck detects this by inspecting fortified symbols in the binary.

For PE binaries (Windows EXE/DLL), the equivalent concepts are DEP, CFG, SafeSEH, and ASLR.

Missing any of these doesn't automatically mean a vulnerability, but it lowers the bar for attackers. IoT devices and firmware tend to have long lifespans with infrequent updates — the cost of shipping without hardening is higher than in typical software.


What bincheck does

bincheck is a CLI tool that checks hardening flags in ELF, PE, and Mach-O binaries. Written in Rust, using the goblin crate for binary parsing.

1. SARIF output for GitHub Code Scanning

bincheck firmware.elf --format sarif > results.sarif
Enter fullscreen mode Exit fullscreen mode

Upload the SARIF output to GitHub Code Scanning and you get hardening results in the Security tab. You can track changes per PR.

2. --strict as a CI gate

bincheck firmware.elf --strict
echo $?  # returns 1 if any hardening flag is missing
Enter fullscreen mode Exit fullscreen mode

With --strict, bincheck exits with code 1 if any flag is absent. Drop it into your CI pipeline as a gate.


Demo

# Install
cargo install bincheck

# Check an ELF binary (table output)
$ bincheck ./firmware.elf

Binary: ./firmware.elf (ELF, x86_64)
┌─────────────────┬──────────┬───────────────────────────────────────┐
│ Check           │ Status   │ Detail                                │
├─────────────────┼──────────┼───────────────────────────────────────┤
│ RELRO           │ FULL     │                                       │
│ Stack Canary    │ ENABLED  │ found __stack_chk_fail in .symtab     │
│ NX              │ ENABLED  │                                       │
│ PIE             │ ENABLED  │                                       │
│ Fortify Source  │ DISABLED │ no fortified symbols found            │
│ RPATH           │ NONE     │                                       │
│ RUNPATH         │ NONE     │                                       │
└─────────────────┴──────────┴───────────────────────────────────────┘

# JSON output
$ bincheck ./firmware.elf --format json

# SARIF output (for GitHub Code Scanning)
$ bincheck ./firmware.elf --format sarif > results.sarif

# CI gate (exit 1 on missing hardening)
$ bincheck ./firmware.elf --strict && echo "OK" || echo "FAILED"
Enter fullscreen mode Exit fullscreen mode

GitHub Actions

- name: Check binary hardening
  uses: kazu11max17/bincheck@v0.2.0
  with:
    files: ./build/firmware.elf
    strict: true
    format: sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: bincheck-results.sarif
Enter fullscreen mode Exit fullscreen mode

Note: the upload-sarif step requires permissions: security-events: write in your workflow.


Closing

bincheck is available here:

If you're using it on embedded Linux, firmware, or anything cross-compiled — feedback and PRs are welcome.

Top comments (0)