Shared Rust crate for malware and IOC detection across the MarlinSpike suite.
marlinspike-malware is one of the Rust engines in the
MarlinSpike repo family, alongside
marlinspike-dpi. It loads YAML rule packs, evaluates generic observed events
against them, and emits structured findings. The engine is intentionally
product-neutral so both MarlinSpike and Fathom can adapt their own telemetry
into the same rule surface.
Runtime operation is fully local. Appliances remain functional when air-gapped. Public feeds (ThreatFox, URLhaus, MalwareBazaar) can be normalized into the YAML schema offline via the sibling marlinspike-malware-rules repo.
marlinspike-dpi
|
Bronze events
|
marlinspike-malware
/ \
YAML rule packs ObservedEvent stream
\ /
MalwareFinding[]
|
MarlinSpike report
(analysis block)
marlinspike-malware scan
--rules-dir → load + compile YAML packs
--events → ObservedEvent[] JSON (from _ms_engine.py)
--output → MalwareFinding[] JSON (back to _ms_engine.py)
The engine sits in the MarlinSpike pipeline between DPI event emission and
report assembly. It consumes Bronze-style observed events (DNS queries, HTTP
hosts/URIs, TLS SNI, artifact hashes, IP addresses, protocol metadata) and
evaluates them against compiled rule packs to produce MalwareFinding records.
This engine follows the Extensibility Contracts defined for the MarlinSpike suite:
| Surface | Role |
|---|---|
| Rust engine | Packet/event-facing, high-throughput IOC matching |
| YAML rule packs | Declarative IOC and signature content |
| Python plugin | Report-facing enrichment (handled by other modules) |
The engine accepts a rules directory, compiles it into a normalized bundle, and
processes batches of ObservedEvent structs. It does not own topology scoring,
ATT&CK mapping, or UI behavior.
marlinspike-malware consumes the same Bronze event surface as the core
MarlinSpike engine. It can evaluate events from:
protocol_transaction— network conversations with extracted observablesextracted_artifact— file hashes, binary signatures, artifact keysasset_observation— host-level indicators
See bronze-consumer-contract.md for the full consumer rules.
Rules match against these observable fields extracted from Bronze events:
| Field | Description | Example |
|---|---|---|
dns_query |
DNS query domain | evil.example.com |
dns_answer |
DNS response data | 185.215.113.x |
http_host |
HTTP Host header | c2.badactor.invalid |
http_uri |
HTTP request URI | /api/v1/beacon |
tls_sni |
TLS Server Name Indication | update.malware.invalid |
artifact_sha256 |
SHA-256 hash of extracted artifact | a1b2c3d4... |
artifact_key |
Named artifact identifier (mutex, registry key, file path) | HKLM\Software\Malware |
src_ip |
Source IP address | 10.0.0.50 |
dst_ip |
Destination IP address | 45.33.32.156 |
src_mac |
Source MAC address | aa:bb:cc:dd:ee:ff |
dst_mac |
Destination MAC address | ff:ee:dd:cc:bb:aa |
hostname |
Device hostname | ENG-WS-014 |
protocol |
Protocol identifier | modbus, s7comm |
any_text |
Matches against all text fields | Catch-all for protocol artifacts |
| Operator | Behavior |
|---|---|
equals |
Exact string match (default) |
contains |
Substring match |
prefix |
String starts with value |
suffix |
String ends with value |
All operators support case_sensitive: true/false (default: false).
| Mode | Behavior |
|---|---|
any |
Fire if any condition matches (default, OR logic) |
all |
Fire only if all conditions match (AND logic) |
info | low | medium | high | critical
Each MalwareFinding emitted by the scan command has the following fields:
| Field | Type | Description |
|---|---|---|
finding_id |
string | Unique identifier for this finding |
rule_id |
string | ID of the rule that matched |
rule_name |
string | Human-readable rule name |
family |
string | Malware family (e.g. cobaltstrike, emotet) |
severity |
string | info | low | medium | high | critical |
confidence |
float | Confidence score (0.0–1.0) |
summary |
string | Human-readable description of the match |
observable_field |
string | The field that matched (e.g. dns_query, tls_sni) |
observable_value |
string | The value that triggered the match |
event_id |
string | ID of the source event |
capture_id |
string | Capture session ID |
timestamp |
string | ISO 8601 UTC timestamp of the event |
src_ip |
string? | Source IP address, if present |
dst_ip |
string? | Destination IP address, if present |
src_mac |
string? | Source MAC address, if present |
dst_mac |
string? | Destination MAC address, if present |
references |
string[] | URLs to advisories, ATT&CK techniques, etc. |
tags |
string[] | Classification tags (e.g. apt, c2, dns) |
source_feed |
string? | Attribution feed name, if applicable |
metadata |
object | Arbitrary key-value metadata from the rule or event |
version: v1
name: "Pack Name"
source:
name: "attribution source"
url: "https://..."
license: "Apache-2.0"
description: "Source description"
rules:
- id: unique-rule-id
name: "Human-readable rule name"
family: "malware-family"
severity: critical
confidence: 0.90
description: "What this rule detects and why"
tags: [apt, c2, dns]
references:
- "https://attack.mitre.org/techniques/T1071/"
- "https://www.cisa.gov/..."
match_mode: any
conditions:
- field: dns_query
op: suffix
value: ".malware.invalid"
case_sensitive: false
- field: tls_sni
op: contains
value: "beacon"The rules/ directory ships 29 curated packs with 919 detection rules across
the full threat landscape.
| Pack | Rules | Coverage |
|---|---|---|
| Malware Loaders | 24 | BazarLoader, Emotet, QakBot, IcedID, Bumblebee, SocGholish, Gootloader, Raspberry Robin, Pikabot, GuLoader |
| C2 Frameworks | 18 | Cobalt Strike, Metasploit, Sliver, Havoc, Brute Ratel, Mythic, PoshC2, Covenant, Empire, Nighthawk |
| RATs | 32 | AsyncRAT, DarkComet, njRAT, Remcos, QuasarRAT, Agent Tesla, NanoCore, Warzone, DcRAT, XWorm, NetWire, Gh0st RAT |
| Ransomware | 34 | LockBit, BlackCat/ALPHV, Royal/BlackSuit, Cl0p, Black Basta, Akira, Play, Rhysida, Medusa, BianLian, Hive, Conti |
| Infostealers | 24 | RedLine, Raccoon, Vidar, LummaC2, Rhadamanthys, StealC, META, Aurora, Mystic, Titan, FormBook/XLoader |
| ICS/OT Threats | 32 | TRITON, Industroyer 1+2, PIPEDREAM, BlackEnergy, Havex, Stuxnet-derived, FrostyGoop, CosmicEnergy, IRONGATE |
| Suspicious Patterns | 38 | DNS tunneling, DGA, dynamic DNS abuse, encoded payloads, cryptomining, Tor, phishing lookalikes, exfiltration |
| APT Tooling | 40 | APT28, APT29, APT41, Lazarus, Turla, Kimsuky, Sandworm, MuddyWater (SUNBURST, ShadowPad, PlugX, Snake, etc.) |
| Wipers | 27 | WhisperGate, HermeticWiper, CaddyWiper, AcidRain, Shamoon, ZeroCleare, Dustman, Meteor, Agrius |
| Botnets | 31 | Mirai variants, TrickBot, Dridex, ZLoader, Qakbot, Androxgh0st, Volt Typhoon, Emotet, Phorpiex, Amadey |
| Webshells | 36 | China Chopper, Godzilla, Behinder, AntSword, ASPXSpy, HAFNIUM/ProxyShell drops, IIS backdoors, generic patterns |
| Backdoors & Implants | 31 | ShadowPad, PlugX, MATA, Daxin, BPFDoor, Symbiote, BlackLotus, CosmicStrand, Derusbi, GoldMax |
| Exploit Delivery | 35 | Log4Shell, ProxyShell/Logon/NotShell, MOVEit, Confluence, Citrix Bleed, FortiGate, Ivanti, Spring4Shell, exploit kits |
| Proxy & Tunneling | 31 | Chisel, frp, ngrok, Cloudflare Tunnel, reGeorg, Ligolo, Plink, GOST, residential proxies, Shadowsocks |
| Credential Theft | 30 | Mimikatz, LSASS dumps, Kerberoasting, Rubeus, Impacket, Responder, BloodHound, Evilginx, CrackMapExec |
| Data Exfiltration | 31 | Cloud storage, Rclone, DNS exfil, ICMP tunneling, Telegram/Discord/Slack webhooks, paste sites, file hosting |
| Mobile & Spyware | 34 | Pegasus, Predator, FinFisher, Hermit, Candiru, stalkerware, FluBot, SharkBot, Xenomorph, Cerberus, TeaBot |
| Cryptocurrency Threats | 33 | Wallet drainers, clipbankers, fake exchanges, cryptojacking, DPRK crypto theft, mixers, fake wallet apps |
| Lateral Movement | 34 | PsExec, WMI, WinRM, DCOM, RDP tunneling, EternalBlue, PrintNightmare, SCShell, CobaltStrike lateral |
| Supply Chain | 37 | 3CX, SolarWinds, Kaseya, Codecov, Polyfill.io, npm/PyPI typosquatting, dependency confusion, CDN compromise |
| Recon & Scanning | 41 | Nmap, Masscan, Nuclei, Shodan, ADFind, BloodHound, Gobuster, SQLMap, WPScan, cloud enumeration |
| Defense Evasion | 41 | Certutil, mshta, bitsadmin, AMSI bypass, ETW patching, LOLBins, PowerShell cradles, reflective injection |
| Phishing-as-a-Service | 39 | Tycoon 2FA, EvilProxy, Greatness, W3LL Panel, Rockstar 2FA, FlowerStorm, OAuth phishing, quishing |
| Cloud & SaaS Threats | 35 | TeamTNT, Kinsing, Denonia, SCARLETEEL, SCATTERED SPIDER, container escapes, K8s exploitation, cloud C2 |
| DNS Abuse | 35 | DoH C2, DNS rebinding, subdomain takeover, IDN homograph, sinkholes, malicious nameservers, fast-flux |
| Email Threats | 35 | BEC infrastructure, malspam, HTML smuggling, callback phishing, OneNote/ISO abuse, OAuth consent phishing |
| IoT Threats | 34 | Camera/router exploitation, Moobot, Fodcha, RapperBot, Zerobot, AVrecon, UPnP/SSDP/MQTT/CWMP abuse |
| Ransomware Ecosystem | 35 | IAB marketplaces, OFAC-sanctioned exchanges, SystemBC, affiliate tools, loader handoffs, payment infra |
| Adware & PUPs | 32 | Fireball, DealPly, Conduit, Superfish, BADBOX, tech support scams, SocGholish distribution, click fraud |
| Severity | Rules |
|---|---|
| Critical | ~380 |
| High | ~380 |
| Medium | ~110 |
| Low | ~30 |
| Info | ~19 |
| Total | 919 |
All rules are sourced from published threat intelligence:
- Government advisories: CISA, NSA, FBI, NCSC-UK, CERT-UA
- MITRE: ATT&CK Enterprise + ICS frameworks
- Vendor research: Mandiant, CrowdStrike, ESET, Kaspersky, Unit 42, SentinelOne, Sophos, ThreatFabric, Cleafy
- Civil society: Amnesty International, Citizen Lab
- Community: MalwareBazaar, abuse.ch, stalkerware-indicators
- Standards bodies: OFAC sanctions designations
The crate includes a CLI for rule-pack validation and compilation:
# Validate all rule packs
cargo run -- validate --rules-dir rules/
# Validate with JSON output
cargo run -- validate --rules-dir rules/ --json
# Compile to a normalized JSON bundle
cargo run -- compile --rules-dir rules/ --output build/bundle.json --pretty
# Scan observed events against rules
cargo run -- scan --rules-dir rules/ --events events.json --output findings.jsonThe scan subcommand reads an ObservedEvent[] JSON array, evaluates every
event against all loaded rules, and writes the resulting MalwareFinding[]
JSON to the output path.
Validation checks:
- Pack and rule field completeness
- Confidence range (0.0-1.0)
- At least one condition per rule
- No duplicate rule IDs across all packs
- Valid field names and operators
The engine is invoked as a subprocess by MarlinSpike's Python engine
(_ms_engine.py) during Stage 4b of the analysis pipeline.
MarlinSpike locates the marlinspike-malware binary by checking, in order:
MARLINSPIKE_MALWARE_BINenvironment variablePATH~/marlinspike-malware/target/release/~/marlinspike-malware/target/debug/
Rule packs are located by checking, in order:
MARLINSPIKE_MALWARE_RULESenvironment variable~/marlinspike-malware/rules/~/marlinspike-malware-rules/packs/
_ms_engine.py converts MarlinSpike conversation objects into ObservedEvent
JSON before passing them to the engine. The following observables are extracted:
- DNS queries and answers
- IP addresses (source and destination)
- MAC addresses
- Protocol identifiers
- Bronze passthrough attributes (HTTP hosts/URIs, TLS SNI, artifact hashes, etc.)
The engine's MalwareFinding[] output is converted back into MarlinSpike
report structures:
c2_indicatorswith typeMALWARE_IOC_MATCHrisk_findingsattached to the analysis report
Stage 4b is optional. If the binary or rules directory cannot be found,
analysis continues without malware matching. When --fast is passed to
MarlinSpike, malware matching is skipped entirely.
use marlinspike_malware::{MalwareEngine, ObservedEvent, ObservedValue, MatchField};
// Load rules from a directory
let engine = MalwareEngine::from_rule_dir("rules/")?;
println!("Loaded {} rules", engine.rule_count());
// Process observed events
let findings = engine.process_observed_batch("bronze-dpi", &events);
for finding in &findings {
println!(
"[{}] {} — {} (confidence: {:.0}%)",
finding.severity.as_str(),
finding.rule_name,
finding.summary,
finding.confidence * 100.0,
);
}| Type | Description |
|---|---|
MalwareEngine |
Compiled rule set, processes event batches |
ObservedEvent |
Single network event with metadata and observables |
ObservedValue |
One observable field+value pair within an event |
MalwareFinding |
Detection result with rule metadata, severity, evidence |
RulePack |
Deserialized YAML rule pack |
CompiledRuleBundle |
Serializable compiled bundle (for JSON export) |
| Repo | Purpose |
|---|---|
| marlinspike | Suite repo — engine, workbench, plugins |
| marlinspike-dpi | Rust DPI engine — packet parsing, Bronze event emission |
| marlinspike-malware-rules | Published rule content — manual packs + public feed imports |
| marlinspike-mitre | Python plugin — ATT&CK mapping from report findings |
This repo (marlinspike-malware) is the engine. The sibling
marlinspike-malware-rules repo is the published content:
marlinspike-malware marlinspike-malware-rules
├── src/ ├── packs/
│ ├── engine.rs │ ├── manual/ ← curated rules
│ ├── rules.rs │ └── public/ ← ThreatFox, URLhaus, MalwareBazaar
│ ├── finding.rs ├── manifests/
│ └── observed.rs │ └── index.yaml
├── rules/ └── scripts/
│ └── (dev/bundled rules) ├── build_index.py
└── Cargo.toml └── update_public_feeds.py
The rules/ directory in this repo ships bundled detection content for
development and standalone use. For production deployments, rule content is
managed in marlinspike-malware-rules and compiled into bundles via the CLI.
# Build
cargo build
# Test
cargo test
# Validate bundled rules
cargo run -- validate --rules-dir rules/
# Compile a production bundle
cargo run -- compile --rules-dir rules/ --output build/marlinspike-malware-bundle.json --pretty- Choose the appropriate pack under
rules/(or create a new directory) - Add rules following the YAML schema above
- Run
cargo run -- validate --rules-dir rules/to check for errors - Ensure rule IDs are globally unique across all packs
Rule IDs follow the pattern {category}-{family}-{description}:
c2-cobaltstrike-default-beacon-uri
rat-asyncrat-default-mutex
ics-triton-triconex-udp
loader-emotet-epoch4-c2
ransomware-lockbit-leak-site
marlinspike-malware is licensed under the GNU Affero General Public License
v3.0 only. See LICENSE.