Skip to content

Rust Windows EDR (user-mode, no driver): ETW → Sysmon-style normalization → Sigma/Yara/IOC detection → ECS NDJSON alerts.

License

Notifications You must be signed in to change notification settings

Karib0u/rustinel

Repository files navigation

Rustinel

High-performance, user-mode Windows EDR in Rust

Docs Platform Windows Language Rust License Status

Rustinel is a high-throughput Windows EDR agent written in Rust. It collects kernel telemetry via ETW, normalizes events into a Sysmon-compatible schema, detects threats using Sigma + YARA, and outputs alerts as ECS NDJSON for straightforward SIEM ingestion.

✅ No kernel driver
✅ User-mode ETW pipeline
✅ Sigma behavioral detection + YARA scanning
✅ ECS NDJSON alerts + operational logs

Rustinel Demo


Why Rustinel?

Rustinel is built for defenders who want:

  • Kernel-grade telemetry without kernel risk (ETW, user-mode)
  • Performance under volume (async pipeline + caching + noise reduction)
  • Detection compatibility (Sysmon-style normalization for Sigma)
  • Operational simplicity (NDJSON alerts on disk, easy to ship to a SIEM)

What it does

Rustinel monitors Windows endpoints by:

  • Collecting kernel events via ETW (process, network, file, registry, DNS, PowerShell, WMI, services, tasks)
  • Normalizing ETW events into Sysmon-compatible fields
  • Detecting threats using Sigma rules and YARA scanning
  • Detecting atomic IOCs (hashes, IP/CIDR, domains, path regex)
  • Writing alerts in ECS NDJSON format

Key features

  • User-mode only: no kernel driver required
  • Dual detection engines:
    • Sigma for behavioral detection
    • YARA for file scanning on process start
  • Atomic IOC detection: hashes, IP/CIDR, domains, path regex
  • Noise reduction:
    • keyword filtering at the ETW session
    • router-level filtering for high-volume network events
    • optional network connection aggregation
  • Hot-path optimizations:
    • Sigma rules are filtered at load time (category/product/service)
    • Sigma conditions are transpiled + precompiled at startup
    • process-context enrichment is attached on alerts, not every event
  • Enrichment:
    • NT → DOS path normalization
    • PE metadata extraction (OriginalFileName/Product/Description)
    • parent process correlation
    • SID → DOMAIN\User resolution
    • DNS caching and reverse mapping
  • Windows service support (install/start/stop/uninstall)
  • ECS NDJSON alerts for SIEM ingestion
  • Optional active response (dry-run or terminate on critical alerts)

Requirements

  • Windows 10/11 or Server 2016+
  • Administrator privileges (ETW + service management)
  • Rust 1.92+ (build from source)

Quick start

Run from an elevated PowerShell.

Option 1: Download Release (Recommended)

  1. Download the latest release from GitHub Releases.
  2. Extract the archive.
  3. Run from an elevated PowerShell:
    .\rustinel.exe run --console

Option 2: Build from Source

# Build
cargo build --release

# Run (console output)
.\target\release\rustinel.exe run --console

Running without arguments is equivalent to rustinel run.


2-minute demo

Sigma demo

This repo ships with an example rule: rules/sigma/example_whoami.yml

  1. Start Rustinel (admin shell):
cargo run -- run --console
  1. Trigger the rule:
whoami /all
  1. Verify an alert was written:
  • logs/alerts.json.YYYY-MM-DD

YARA demo

This repo ships with an example rule: rules/yara/example_test_string.yar

  1. Build the demo binary:
rustc .\examples\yara_demo.rs -o .\examples\yara_demo.exe
  1. Run it:
.\examples\yara_demo.exe
  1. Verify an alert includes the rule name:
  • ExampleMarkerString

Note: The demo binary runs in a loop to demonstrate active response. With response enabled and prevention_enabled = true, the process will be automatically terminated when the YARA rule triggers (YARA matches are treated as critical severity).


Service mode

.\target\release\rustinel.exe service install
.\target\release\rustinel.exe service start
.\target\release\rustinel.exe service stop
.\target\release\rustinel.exe service uninstall

Notes

  • service install registers the current executable path — run it from the final location.
  • Config and rules paths resolve from the working directory; for services, prefer absolute paths or env overrides.
  • Service runtime does not receive CLI flags; set log level via config.toml or EDR__LOGGING__LEVEL.

Configuration

Configuration precedence:

  1. CLI flags (highest, run mode only)
  2. Environment variables
  3. config.toml
  4. Built-in defaults

Example config.toml:

[scanner]
sigma_enabled = true
sigma_rules_path = "rules/sigma"
yara_enabled = true
yara_rules_path = "rules/yara"

[allowlist]
paths = [
  "C:\\Windows\\",
  "C:\\Program Files\\",
  "C:\\Program Files (x86)\\",
]

[logging]
level = "info"
directory = "logs"
filename = "rustinel.log"
console_output = true

[alerts]
directory = "logs"
filename = "alerts.json"
match_debug = "off" # off | summary | full

[response]
enabled = false
prevention_enabled = false
min_severity = "critical"
channel_capacity = 128
allowlist_images = []

[network]
aggregation_enabled = true
aggregation_max_entries = 20000
aggregation_interval_buffer_size = 50

[ioc]
enabled = true
hashes_path = "rules/ioc/hashes.txt"
ips_path = "rules/ioc/ips.txt"
domains_path = "rules/ioc/domains.txt"
paths_regex_path = "rules/ioc/paths_regex.txt"
default_severity = "high"
max_file_size_mb = 50

allowlist.paths is shared by default across:

  • response.allowlist_paths
  • ioc.hash_allowlist_paths
  • scanner.yara_allowlist_paths

If a module-specific list is explicitly set, it overrides the shared list for that module only.

Match debug output:

  1. alerts.match_debug = "off" disables match details in alerts (default).
  2. alerts.match_debug = "summary" adds rule condition + matched fields/patterns.
  3. alerts.match_debug = "full" adds matched values and YARA string snippets.

Environment overrides:

set EDR__LOGGING__LEVEL=debug
set EDR__SCANNER__SIGMA_RULES_PATH=C:\rules\sigma
set EDR__ALLOWLIST__PATHS=["C:\\Windows\\","C:\\Program Files\\"]
# optional module-specific override:
set EDR__SCANNER__YARA_ALLOWLIST_PATHS=["C:\\Windows\\","D:\\Trusted\\"]

CLI override (highest precedence, run mode only):

rustinel run --log-level debug

Note: rule logic evaluation errors are only logged at warn, debug, or trace levels (suppressed at info).

Active response

Option Default Description
enabled false Enable active response engine
prevention_enabled false If false, logs dry-run actions only
min_severity critical Minimum severity to respond to (Sigma uses rule level, YARA is always treated as critical)
channel_capacity 128 Queue size for response tasks (drops on overflow)
allowlist_images [] Image basenames or full paths to skip
allowlist_paths inherits allowlist.paths Prefix paths to skip (case-insensitive). Optional module-specific override

More details: docs/active-response.md.

Atomic IOC detection

Option Default Description
enabled true Enable atomic IOC detection
hashes_path rules/ioc/hashes.txt Hash IOC file (MD5/SHA1/SHA256)
ips_path rules/ioc/ips.txt IP and CIDR IOC file
domains_path rules/ioc/domains.txt Domain IOC file
paths_regex_path rules/ioc/paths_regex.txt Path/filename regex IOC file
default_severity high Severity assigned to IOC alerts
max_file_size_mb 50 Skip hashing files larger than this (MB)
hash_allowlist_paths inherits allowlist.paths Prefix paths to skip hashing (case-insensitive). Optional module-specific override

Rules

Sigma

  • Place .yml / .yaml files under rules/sigma/
  • Supported categories include: process_creation, network_connection, file_event, registry_event, dns_query, image_load, ps_script, wmi_event, service_creation, task_creation

YARA

  • Place .yar / .yara files under rules/yara/
  • Rules compile at startup
  • Scans trigger on process creation (runs in a background worker)
  • Files under allowlisted path prefixes are skipped (allowlist.paths by default or scanner.yara_allowlist_paths override)

Atomic IOCs

Place indicator files under rules/ioc/:

  • hashes.txt — MD5, SHA1, SHA256 hashes (auto-detected by length)
  • ips.txt — IP addresses and CIDR ranges
  • domains.txt — exact domains or *./. prefix for suffix matching
  • paths_regex.txt — case-insensitive regexes matched against file paths

Hash checking runs in a dedicated background worker on process creation. Files under allowlisted paths (shared allowlist.paths by default, or ioc.hash_allowlist_paths override) and files exceeding max_file_size_mb are skipped automatically. Domain, IP, and path checks run inline with negligible overhead.


Output

Rustinel produces:

  • Operational logs: logs/rustinel.log.YYYY-MM-DD
  • Security alerts (ECS NDJSON): logs/alerts.json.YYYY-MM-DD

Example alert (one JSON object per line):

{
  "@timestamp": "2025-01-15T14:32:10Z",
  "event.kind": "alert",
  "event.category": "process",
  "event.action": "process_creation",
  "rule.name": "Whoami Execution",
  "rule.severity": "low",
  "rule.engine": "Sigma",
  "process.executable": "C:\\Windows\\System32\\whoami.exe",
  "process.command_line": "whoami /all",
  "user.name": "DOMAIN\\username"
}

Development

# Unit tests
cargo test

# Format + lint
cargo fmt
cargo clippy

# Validate Sigma + YARA rules
cargo run --bin validate_rules

Project layout (high level):

src/
├── collector/     # ETW collection + routing
├── normalizer/    # Sysmon-style normalization + enrichment
├── engine/        # Sigma engine
├── scanner/       # YARA scanning worker
├── ioc/           # Atomic IOC detection (hashes, IPs, domains, paths)
├── state/         # caches (process/sid/dns/aggregation)
└── bin/validate_rules.rs

Roadmap

Short roadmap:

  • YARA expansion (memory scanning + periodic scans).
  • Resource governor (Windows Job Objects CPU limits).
  • Self-defense hardening (DACL/ACL restrictions + anti-injection).
  • Watchdog sidecar to restart the service if the main process dies.
  • ETW integrity checks to detect blinding/tampering.
  • Deep inspection via stack tracing for "floating code".

Status

Rustinel is Alpha. It’s usable for experimentation, lab deployments, and iterative hardening. Expect breaking changes while the schema + engines mature.


License

Apache 2.0 — see LICENSE.

Packages

 
 
 

Contributors 2

  •  
  •  

Languages