Skip to content

Repository files navigation

Wraith — a spectral form crossed by a slow provenance trace; execution leaves a trace

Runtime security, through a different lens.
Observe execution. Inspect its origin. Understand the anomaly.

Quickstart   /   Real demo   /   Design   /   Threat model   /   Contribute

CI status Platform: Linux x86-64 MIT license

Concept artwork, not telemetry. Still version · Art direction & motion

Wraith

A small Rust runtime sensor that inspects where Linux syscalls come from.

Injected code can change its bytes. It still has to execute somewhere. Wraith uses ptrace and /proc/<pid>/maps to flag sensitive syscalls from suspicious executable memory, inspect W^X requests, and correlate signals across threads. No payload signatures, cloud service, or model required. Only two direct Rust dependencies: nix and libc.

Continuously developed, not a finalized endpoint product. The focus is reproducible Linux security investigation with honest coverage and workload evidence—not an antivirus or Nmap replacement. See the development program and Linux/Kali tool comparison.

Inspect the origin
Executable mappings and syscall provenance. No payload signature required.
Follow the execution
Shared process state across worker threads, with explicit exec lifecycle handling.
Keep the evidence
JSONL detections, a live terminal view, and opt-in response after baselining.

For: security researchers, focused service monitoring, exploit-behavior experiments, and fuzzing triage. Not: a complete EDR, a vulnerability scanner, or proof that a process is uncompromised. Read the threat model before enforcing.

Observe-only by default. Linux x86-64. Controlled deployments should start with a representative benign baseline. Zero false positives and universal exploit coverage are not promised.

See the evidence

Actual Wraith fixture session: benign control, injection detection and syscall blocking

Recorded from real local fixture runs; paths abbreviated. PIDs, addresses and counts vary. Recreate with python3 scripts/record_demo.py. Replayable terminal recording. The older scan dashboard illustration is illustrative, not a benchmark.

Try it in two minutes

Prerequisites: Linux 5.3+ on x86-64, Rust 1.74+, mounted procfs, and permission to trace your own child process. WSL2 works; restricted containers may deny ptrace.

git clone https://github.com/grloper/Wraith.git
cd Wraith
cargo build --release --locked
./target/release/wraith doctor
bash demo.sh

The demo checks six outcomes, rather than merely printing expected results:

Local fixture Required outcome
benign No detections, sensor exit 0
benign-threads No detections across worker threads, exit 0
shellcode-sim RWX staging + sensitive syscall from that page, exit 3
mt-shellcode-sim Same behavior on a worker thread, exit 3
shellcode-sim --block Syscall returns -ENOSYS; fixture survives, exit 3
shellcode-sim --kill Traced tree terminated before payload syscall, exit 3

These are safe local behavior simulators, not exploitation of a real vulnerability: the payload opens a socket and closes it; it does not connect or exfiltrate data.

Install a Linux package

On a Debian-family amd64 development machine, build and validate a sensor-only package:

bash scripts/test_deb.sh
sudo apt install ./target/dist/wraith_0.2.0-1_amd64.deb
wraith doctor --json

Building requires dpkg-dev, Python 3 and the Rust toolchain. Installation uses the ELF dependencies derived from the build system; incompatible older distributions must rebuild locally. No service, setuid bit, capability grant or security-policy change is installed. The validation gate inspects/extracts/executes the self-built package without changing the host package database. This is not official Kali inclusion or evidence of installation on every Linux distribution. See Debian package guidance.

Use it

# Launch and observe one program and its future children.
./target/release/wraith run -- /usr/bin/your-service --foreground

# Attach to an existing process (ownership / Yama policy applies).
sudo ./target/release/wraith attach 4242

# Observe a selected set, never start with an entire busy host.
sudo ./target/release/wraith scan --match nginx --max-targets 4

# Human-readable output on stderr; append JSONL evidence to a file.
./target/release/wraith run --json events.jsonl -- ./your-target

# Live terminal dashboard.
sudo ./target/release/wraith scan --ui --match nginx

Sensor exit status: 0 no HIGH/CRITICAL events; 1 HIGH activity; 2 operational or usage error; 3 CRITICAL activity. This is not the target's exit status. A failed program can have a clean sensor verdict. --min filters output, not detection or exit status.

Detection policy

Signal Default interpretation
Sensitive syscall from RWX, executable heap or stack CRITICAL provenance anomaly
Syscall from anonymous RX code, including named anonymous mappings WARN; legitimate JIT is possible
mmap / mprotect requests RWX HIGH staging request, not proof the kernel accepted it
Writable→executable transition WARN by default (normal W^X JIT behavior); HIGH with explicit no-JIT policy
Unregistered stack pointer in heap or a file mapping HIGH heuristic; successfully observed per-thread signal-stack registrations affect placement only
Missing / non-executable origin in a usable map Coverage uncertainty, not proof of injection
Required map refresh fails Visible coverage gap; no enforcement from stale maps; sensor exit 2
Correlated anomalous sensitive execution and staging CRITICAL under the current-origin policy; completed staging must cover that address, context expires by syscall budget/time; not proof of data flow
Fatal target signal HIGH crash indicator; crashes are not automatically attacks

Anonymous RX is not automatically CRITICAL. --jit-critical is an explicit no-JIT policy: it raises ordinary anonymous-origin calls to HIGH and sensitive ones to CRITICAL. Use it only when that assumption fits the workload.

--trust-region START-END exempts operator-vouched half-open hexadecimal address ranges from provenance and fully covered, page-rounded protection requests. Trust is an explicit blind spot, not automatic JIT attestation. ASLR makes static ranges fragile; never trust broad ranges merely to make alerts disappear.

--no-stack-pivot disables the custom-stack-sensitive heuristic. --audit-sensitive adds INFO breadcrumbs for sensitive calls from accepted code. --correlation-window N sets the evidence budget (default 64 syscall entries, also expiring after 30 seconds); --max-history N caps retired dashboard rows (default 128, with live rows preserved). Failed/zero-byte input does not count as completed input evidence; protection requests may still be reported even if they fail. See wraith --help and operator guidance.

JSONL events carry schema and sensor versions. A strict, bounded triage helper and investigation workflows validate complete logs without treating a quiet/filtered stream as proof of complete coverage.

Optional enforcement

# On a CRITICAL event only: skip the current syscall, returning -ENOSYS.
./target/release/wraith run --block -- ./your-target

# On a CRITICAL event only: SIGKILL the traced process tree.
./target/release/wraith run --kill -- ./your-target

Enforcement can break a legitimate application if its memory policy resembles injection. Baseline first, review evidence, then opt in. It is not a substitute for sandboxing.

How it works

Linux ptrace syscall stop → registers + cached /proc maps
                         → origin / W^X / stack checks
                         → per-address-space correlation
                         → JSONL + terminal reporter
                         → observe (default) / block / kill
  • Transport-independent engine: src/engine.rs owns policy, maps and statistics; src/tracer.rs owns Linux tracing and enforcement.
  • Sorted interval lookup: provenance uses binary search over parsed mappings.
  • Shared process state: worker threads share map and correlation state.
  • Small supply chain: no async runtime, TUI framework or serialization dependency.

Every syscall still pays the ptrace stop/resume cost. This is focused monitoring, not low-overhead whole-host telemetry. Measure your own workload:

python3 scripts/benchmark.py --iterations 20000 --samples 5
python3 scripts/benchmark_workloads.py --help

Actual five-pair WSL wall timings (startup/import/shutdown included):

Owned workload Baseline median Traced median Slowdown
Loopback HTTP, 20 requests 125.537 ms 421.720 ms 3.359×
SQLite, 200 transactions 564.563 ms 1696.223 ms 3.004×

Raw samples and fingerprints and benign runtime controls preserve target and sensor outcomes separately. Python was clean; Java completed with four HIGH RWX-policy findings, not fatal crashes; native Node was unavailable. This is no population false-positive or native-production performance claim. The historical 140.338× syscall-loop result is a different workload, not a before/after speedup comparison.

The script reports raw timings, kernel and median slowdown; it does not manufacture a performance claim. An eBPF backend is not implemented. Observation and synchronous syscall blocking require different kernel mechanisms; see research notes.

Build, test, contribute

bash scripts/verify.sh        # formatting, Clippy, strict real-ptrace tests, docs
cargo build --release --locked
./target/release/wraith doctor
bash demo.sh                 # asserted detection + enforcement demo

CI requires actual ptrace execution (WRAITH_REQUIRE_PTRACE=1) rather than silently accepting skipped integration tests. The verification notes distinguish measured evidence from untested environments.

Start with CONTRIBUTING.md, the architecture, or small, testable contribution ideas. Report security issues using SECURITY.md. Changes are tracked in CHANGELOG.md.

Want to help? Reproduce a benign false positive, add a regression fixture, or measure an actual service workload. Those contributions matter more than a badge or star count. Launch kit and resume-ready project summary.

MIT · LICENSE

About

Wraith is a low-level Rust security sensor that answers a question most tools can't: "is this process being exploited right now?" By focusing entirely on anomalous runtime behavior rather than known signatures or payloads, Wraith detects live exploits and uncovers zero-day vulnerabilities completely in advance of a patch.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages