Skip to content

quantumsequrity/heimdall

Repository files navigation

Heimdall

Kernel-level entropy-based ransomware detection for Linux servers.

Heimdall uses eBPF probes to intercept filesystem writes at the kernel level, computes Shannon entropy on write buffers in real time, and compares observations against per-process, per-path statistical baselines. When a process starts writing data that looks encrypted — high entropy, abnormal frequency — Heimdall flags it.

No signatures. No cloud. No auto-remediation opinions. Think htop, not antivirus.

Built for hospital server deployments where false positives are a patient safety issue and visibility matters more than magic.

Runs fully offline. No network dependencies at runtime. No telemetry, no cloud, no signature updates.

Quick Start | Installation Guide | Usage Guide | Configuration Reference

How It Works

  Kernel Space                     User Space
 ┌──────────────┐         ┌──────────────────────────────┐
 │  eBPF Probes │         │       heimdall-daemon        │
 │              │  ring    │                              │
 │  vfs_write ──┼─buffer──▶  entropy analysis            │
 │  vfs_writev  │         │  EMA baseline comparison     │
 │  do_renameat2│         │  anomaly scoring             │
 │              │         │  policy evaluation           │──▶ sinks
 └──────────────┘         │  enforcement (if enabled)    │   (file/syslog/http)
                          └──────┬───────────────┬───────┘
                                 │               │
                            unix socket     broadcast
                                 │               │
                          ┌──────┴──┐     ┌──────┴──┐
                          │   CLI   │     │   TUI   │
                          └─────────┘     └─────────┘

Detection model:

  1. eBPF kprobes on vfs_write, vfs_writev, and do_renameat2 capture write events with the first 4KB of each write buffer
  2. Shannon entropy is computed on the buffer sample (0.0 = identical bytes, 8.0 = perfectly random)
  3. Each (process, directory) pair maintains an Exponential Moving Average (EMA) baseline of normal entropy and write frequency
  4. Deviation from baseline is scored: anomaly = 0.7 * entropy_score + 0.3 * frequency_score
  5. Severity is classified: Low (<0.3), Medium (0.3-0.6), High (0.6-0.85), Critical (>=0.85)
  6. In enforcing mode, the policy engine maps (process tag, severity) to an action: alert, freeze (SIGSTOP), or kill (SIGKILL)

Ransomware-encrypted data typically scores >7.0 entropy. Normal text is ~4.0. Normal binaries are ~5.5. The baseline learns what's normal for each process on each machine.

Quick Start (30 minutes)

See QUICKSTART.md -- get Heimdall running on your server in 30 minutes. Written for hospital IT staff who know Linux basics but don't need to know Rust, eBPF, or entropy math.

Architecture

Crate Description
heimdall-daemon Core detection engine, eBPF bridge, IPC server, policy enforcement, pluggable sinks
heimdall-ebpf eBPF probes via Aya -- pure Rust, no libbpf-sys
heimdall-cli Command-line interface with plain English + verbose modes
heimdall-tui Real-time ratatui dashboard
heimdall-common Shared event types, IPC protocol, severity/tag/mode enums
heimdall-test-harness Ransomware simulation harness for safe detection validation

Requirements

  • Linux kernel 5.8+ (BTF support)
  • Rust 1.75+ (stable)
  • Rust nightly toolchain (for eBPF compilation only)
  • Root privileges (for eBPF probe attachment)

Building

# Build userspace components
cargo build --release --workspace --exclude heimdall-ebpf

# Build eBPF probes (requires nightly)
cd heimdall-ebpf
cargo +nightly build -Z build-std=core --target bpfel-unknown-none --release

Installation

# Copy binaries
sudo cp target/release/heimdalld /usr/local/bin/
sudo cp target/release/heimdall /usr/local/bin/
sudo cp target/release/heimdall-tui /usr/local/bin/

# Create directories
sudo mkdir -p /etc/heimdall /var/lib/heimdall /var/log/heimdall /run/heimdall

# Copy config
sudo cp heimdall.toml /etc/heimdall/heimdall.toml
sudo chmod 640 /etc/heimdall/heimdall.toml

# Run the daemon
sudo heimdalld /etc/heimdall/heimdall.toml

For production deployments, use the systemd service unit. See INSTALL.md for the full walkthrough including air-gapped builds.

Operating Modes

Heimdall has three modes, designed to be used sequentially:

Mode What it does When to use
Learning Observes all writes, builds per-process baselines. No alerts, no enforcement. First 48+ hours after deployment. After major software changes.
Monitoring Compares live writes against baselines. Generates alerts. No enforcement. After baselines stabilize. Safe for production.
Enforcing Same as monitoring, plus executes policy actions (freeze/kill) on anomalous processes. After thorough testing. Requires process tagging.

Start in learning mode. Always. The first 48+ hours build trust -- operators can see what the system would have flagged before any enforcement is turned on.

# Check current mode
heimdall mode

# Switch modes
sudo heimdall mode monitoring
sudo heimdall mode enforcing

CLI Usage

# Daemon status
heimdall status
heimdall status --verbose

# Recent detection verdicts
heimdall logs
heimdall logs --limit 50 --verbose

# Live event stream
heimdall watch
heimdall watch --verbose

# Process/path tagging
heimdall tag set mysqld critical
heimdall tag set /opt/ehr/ critical
heimdall tag set /tmp/ watched
heimdall tag list

# Custom socket path
heimdall --socket /path/to/heimdall.sock status

Default output is plain English:

14:23:01 [CRITICAL] java is writing scrambled data to /data/patient_records/db.mdf, this is highly unusual. Confidence: very high.
         Action: freeze

Verbose mode shows raw numbers:

14:23:01 [CRITICAL] pid=4821 comm=java path=/data/patient_records/db.mdf
         entropy=7.9312  deviation=14.2σ  freq_ratio=23.1x  anomaly=0.9847  size=65536B
         entropy=7.93 baseline_mean=4.12 baseline_stddev=0.27 deviation=14.2σ write_size=65536 freq_ratio=23.1x samples=4821
         Action: freeze

TUI Dashboard

heimdall-tui

Real-time terminal dashboard showing:

  • Connection status, operating mode, uptime, events/sec
  • Live event feed with severity color coding
  • Top processes leaderboard sorted by anomaly score

Keybindings:

Key Action
q Quit
v Toggle verbose/plain English
m Cycle operating mode
/ Filter events
Up/Down Scroll event feed

Process Tagging

Tags tell Heimdall how to handle anomalies from specific processes or paths. This is where your team's knowledge of what runs on your servers becomes the policy.

Tag Meaning Policy behavior
critical Must never be interrupted. EHR, database engines, life-critical services. Alert only, never freeze or kill.
trusted Known good. Backup software, system services. Alert only.
watched Under active monitoring. New software, recently updated services. Freeze on high/critical severity.
untrusted Unknown or suspicious. Default for untagged processes. Kill on critical, freeze on high.
# Tag your critical hospital applications
heimdall tag set mysqld critical
heimdall tag set java critical           # EHR application server
heimdall tag set /opt/ehr/ critical      # All processes writing to EHR data
heimdall tag set /data/pacs/ critical    # PACS imaging archive

# Tag known-good infrastructure
heimdall tag set sshd trusted
heimdall tag set systemd-journal trusted

# Watch new or recently updated software
heimdall tag set /opt/newapp/ watched

Path patterns ending with / match as directory prefixes. Process names are matched exactly.

Configuration

Configuration is TOML at /etc/heimdall/heimdall.toml. See CONFIG_REFERENCE.md for every option with type, range, default, and hospital-specific recommendations.

Key settings:

[daemon]
mode = "learning"                          # Start here
db_path = "/var/lib/heimdall/baselines.db" # SQLite baseline storage
socket_path = "/run/heimdall/heimdall.sock"
log_level = "info"

[engine]
alpha = 0.05              # EMA smoothing factor (lower = slower adaptation)
entropy_threshold = 3.0   # Stddev threshold for anomaly flagging
frequency_threshold = 5.0 # Write frequency multiplier threshold
min_samples = 100         # Samples before baseline is trusted
sample_size = 4096        # Bytes captured per write event

[watch]
exclude_paths = ["/proc", "/sys", "/dev", "/tmp", "/run"]

Configuration validation is strict -- the daemon will refuse to start with invalid values (alpha outside (0,1), zero thresholds, world-writable config file).

Sinks

Events are dispatched to all configured sinks concurrently. Sink failures are logged but never block detection.

# Local JSON file (recommended minimum)
[[sinks]]
type = "file"
path = "/var/log/heimdall/events.json"

# Syslog (UDP, RFC 5424)
[[sinks]]
type = "syslog"
address = "udp://10.0.1.5:514"

# HTTP POST (Splunk, Elasticsearch, any JSON endpoint)
[[sinks]]
type = "http"
url = "https://splunk.hospital.local:8088/services/collector/event"
[sinks.headers]
Authorization = "Splunk YOUR-HEC-TOKEN-HERE"

Testing

Unit Tests

cargo test --workspace --exclude heimdall-ebpf
# 151 tests across 9 modules: detector, baseline, config, tags, policy,
# dispatcher, protocol, entropy, ebpf bridge

Formal Verification (Kani)

5 Kani proofs verify critical mathematical invariants:

  • Anomaly score is always in [0.0, 1.0]
  • Severity classification has no gaps or overlaps
  • Shannon entropy is always in [0.0, 8.0]
  • Entropy deviation is always non-negative
  • Entropy standard deviation is always non-negative
cargo kani --harness verify_anomaly_score_bounds
cargo kani --harness verify_classify_severity_complete
cargo kani --harness verify_shannon_entropy_bounds
cargo kani --harness verify_entropy_deviation_non_negative
cargo kani --harness verify_entropy_stddev_non_negative

Fuzz Testing (libFuzzer)

5 fuzz targets cover untrusted input surfaces:

cd heimdall-daemon
cargo +nightly fuzz run fuzz_sanitize_event
cargo +nightly fuzz run fuzz_config_toml
cargo +nightly fuzz run fuzz_daemon_request
cargo +nightly fuzz run fuzz_tag_store
cargo +nightly fuzz run fuzz_file_sink_path

Test Harness

The test harness (heimdall-test-harness) safely simulates ransomware write patterns without any actual encryption or destruction. It generates synthetic write events that trigger Heimdall's detection pipeline, allowing you to validate that the system works before relying on it.

# Build the harness
cargo build --release -p heimdall-test-harness

# Run all simulation scenarios
heimdall-harness all

Security

Heimdall is designed to run on hospital servers protecting patient data. Security is not optional.

Hardening measures in the codebase:

  • No .unwrap() on any Mutex or RwLock -- all lock operations return recoverable errors instead of panicking the daemon
  • PID verification via /proc/<pid>/comm before sending SIGKILL/SIGSTOP -- prevents TOCTOU attacks from PID reuse
  • Path sanitization on all eBPF-provided data -- rejects null bytes, control characters, oversized paths
  • Config file permission check -- refuses to start if heimdall.toml is world-writable
  • Config value validation -- rejects out-of-range alpha, zero thresholds, insufficient min_samples
  • IPC connection limiting -- max 32 concurrent connections via semaphore
  • IPC message size limiting -- max 64KB per message, prevents memory exhaustion
  • Concurrent non-blocking sink dispatch -- a hung SIEM endpoint never stalls detection
  • Graceful shutdown -- SIGINT + SIGTERM handled, 10-second drain timeout, clean SQLite close
  • File sink path traversal rejection -- rejects paths containing ..
  • EMA calculation in Rust, not SQL -- avoids mid-update reference bugs in SQLite expressions
  • Baseline table bounded -- periodic cleanup of stale entries, 100K row cap with LRU eviction
  • Compile-time size assertion on eBPF event struct -- layout mismatch between kernel and userspace is a build error, not a runtime bug

Operational security recommendations:

  • Run the daemon as root only for eBPF probe attachment, then consider privilege separation for future versions
  • Set config file permissions to 640 owned by root
  • Use HTTPS for HTTP sinks -- API keys are stored in the config file
  • Back up the baseline database regularly -- a corrupted baseline means restarting from learning mode
  • Monitor /var/log/heimdall/events.json for disk usage -- consider log rotation

Project Status

This is v0.1.0. The full detection pipeline is implemented and wired end-to-end.

What works now:

  • Full eBPF-to-detector pipeline: vfs_write, vfs_writev, do_renameat2 kprobes attach at daemon startup, events flow through the ring buffer, are converted to WriteEvent structs, and feed into entropy analysis, EMA baseline comparison, anomaly scoring, severity classification, and policy enforcement
  • Graceful degradation: if eBPF probes fail to load (wrong kernel, missing BTF, permissions), the daemon logs the error and continues running -- it won't crash
  • Policy engine with tag-based enforcement (SIGSTOP/SIGKILL with PID verification)
  • IPC server with unix socket, connection limiting (32 max), idle timeouts, message size limits (64KB), subscription streaming
  • CLI with status, logs, tag, mode, and watch commands
  • TUI with live dashboard, event feed, process leaderboard
  • Three pluggable sinks: file, syslog, HTTP -- all dispatched concurrently, failures never block detection
  • Test harness for safe ransomware behavior simulation
  • 151 tests (73 unique) across detector, baseline, config, tags, policy, dispatcher, protocol, entropy, and eBPF bridge modules
  • 5 Kani formal verification proofs on mathematical invariants
  • 5 libFuzzer fuzz targets on untrusted input surfaces
  • systemd service unit with security hardening

What's next:

  • Write frequency tracking (currently hardcoded to 1.0 -- frequency ratio is computed but not yet populated from timing data)
  • E2E integration test suite
  • Packaging (deb/rpm)
  • Baseline import/export for fleet deployment
  • eBPF-side path filtering (watch.include_paths / watch.exclude_paths are parsed but not yet enforced in the eBPF probes)

License

GPL-3.0

About

Kernel-level entropy-based ransomware detection for hospital servers. eBPF + Rust.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors