Skip to content

Releases: cooparo/runtime-attacks

v0.2.0 — CFG attestation, JOP detection & evaluation harness

Choose a tag to compare

@cooparo cooparo released this 03 Jun 12:26

What's new since v0.1.0

Detector

  • CFG-edge validation — every direct/conditional branch is checked against the statically recovered CFG; off-graph edges are flagged immediately.
  • Hash-chain attestation (C-FLAT style) — each transfer is folded into a running FNV-1a 64-bit hash; the token is printed at exit for offline comparison against a known-good baseline.

Attacks

  • 03-jop/ — JOP PoC: a blr-pivot chain caught at the first illegal indirect-call target (100% detection, 2.23× overhead).
  • 04-data-only/ — Non-control-data PoC: flips an adjacent is_admin flag without touching any return address. Documents the L1 gap.

Evaluation harness (tools/run_eval.py)

  • Repeats each case N times, writes per-run CSVs to eval/raw/<date>/, and renders a summary with detection rate, FPR, overhead, and time-to-detection.
  • Payload pre-generation decouples pwntools startup from timing; --measure-pwn-startup measures it separately.

Headline results (N=50, Raspberry Pi 4 / Cortex-A72)

Attack Detection FPR Overhead
Stack BOF 100% 0% 2.41×
ROP 100% 0% 2.65×
JOP 100% 0% 2.23×
Non-control-data (L1 gap) 0% ✓ 0% 3.13×

Next

L2 data-provenance tracking and L3 object-bounds checking.

v0.1.0 — Shadow-stack detector + 3 attack PoCs

Choose a tag to compare

@cooparo cooparo released this 11 May 10:47

First tagged release of the AAU runtime-attacks research project.

What this is

A research repo with three things:

  1. A runtime attack detector (detector/tracer) — a user-space shadow call stack on AArch64 Linux, built on ptrace. It enforces the call/return contract: every ret must return to the address recorded by its matching bl/blr. Any deviation is flagged as [!!! ATTACK DETECTED] and the tracee is killed.
  2. Three attack PoCs — small vulnerable C programs paired with auto-generating pwntools-based exploits, used to exercise the detector and document its coverage.
  3. A test matrix (tools/run_tests.py + make test) — drives detector × {benign, attack} for every attack dir and asserts on tracer exit code, stderr markers, and stdout markers.

Target: AArch64 Linux (Raspberry Pi 4/5 class hardware).

Attacks shipped

Iter Attack Path Detected?
1 Stack buffer overflow (direct return-address overwrite) attacks/01-stack-bof/
2 Return-oriented programming (3-gadget chain) attacks/02-rop/ ✅ (at first hijacked ret)
3a Jump-oriented programming (blr-pivot → br x16 gadget → _exit) attacks/03-jop/ ❌ — see "known gap" below

Known gap (iter-3a)

The shadow call stack catches any control-flow hijack that subverts the call/return contract — any ret to a non-call-site fails immediately. It does not catch indirect-branch hijacks that never execute a ret. The iter-3a JOP PoC is exactly this case: an indirect call (blr Xn) is pivoted to a br x16 gadget which terminates in _exit(), so no ret ever fires and the shadow stack never sees the violation.

The test harness encodes this gap as a tracked case (03-jop :: attack (gap demo)) that is green when the attack succeeds — explicit, not hidden.

Closing this gap requires per-call-site CFG-edge validation; planned in notes/wiki/analyses/cs2-runtime-attacks-project.md as iter-3b.

Detector internals (one-paragraph summary)

Fork + PTRACE_TRACEME, set a one-shot BRK at main to skip the cost of single-stepping ld.so and __libc_start_main. From main onward, peek the next AArch64 instruction at PC and decode: bl/blr push the return site, ret pops and compares against the actual post-step PC, br is currently a no-op (the iter-3a gap). On mismatch: [!!! ATTACK DETECTED] to stderr, PTRACE_KILL, exit code 2.

How to run locally

nix develop --command $SHELL      # enter the flake's dev shell
make build                        # builds detector/ + every attacks/*/
make test                         # runs the 6-case matrix

Dev shell ships gcc (hardening explicitly disabled so binaries are vulnerable by design), pwntools, capstone, pyelftools, gdb, and pwndbg.

CI

GitHub Actions workflow at .github/workflows/test.yml runs the full matrix on every release on an ubuntu-24.04-arm runner, using the same Nix dev shell as local development. Manual trigger available via workflow_dispatch.

What's next

Iter-3b: extend tools/build_cfg.py to emit static target sets for blr/br sites, extend tracer.c to validate the post-step PC of indirect branches against that set. Test case flips from green-when-PWNED to expected exit 2 with the standard [!!! ATTACK DETECTED] marker.

Beyond iter-3b: function reuse attacks, data-only attacks, non-control-data overflows.