Detection¶
Rustinel has three detector paths:
- Sigma for behavioral rules on normalized events
- YARA for executable scans on process-start events
- IOC for inline indicators plus background file hashing
All detection hits are written as ECS NDJSON alerts. The same alerts can also feed the optional response engine.
Runtime Flow¶
| Detector | Input | Execution path | Alert behavior |
|---|---|---|---|
| Sigma | Every normalized event | Inline in SigmaDetectionHandler |
At most one Sigma alert per event |
| YARA | Process-start executable path | Background worker via YaraEventHandler |
One alert per matching YARA rule |
| IOC domains / IPs / paths | Every normalized event | Inline in SigmaDetectionHandler |
Zero or more alerts per event |
| IOC hashes | Process-start executable path | Background worker | Zero or more alerts per file |
Sigma¶
Rule Loading and Classification¶
- Rules load recursively from
scanner.sigma_rules_path. - Multi-document YAML with
action: globalis supported. - Rules are classified at load time by normalized
product,service, andcategory. productmismatches are skipped.- Known Linux service families that are not implemented yet are marked as deferred instead of unknown.
- Unknown logsource shapes are skipped.
- Known but inactive collectors can still load for compatibility, but they will not match until the sensor emits that telemetry family.
Supported Logsource Families¶
| Family | Windows ETW | Linux eBPF | Notes |
|---|---|---|---|
process_creation |
Yes | Yes | Sysmon-style process events |
network_connection |
Yes | Yes | Generic service: connection, category: network is also supported |
file_event |
Yes | Yes | Base file family |
file_create |
Yes | Yes | Derived from file event ID / opcode |
file_delete |
Yes | Yes | Derived from file event ID / opcode |
file_change |
Yes | Yes | Derived from file event ID / opcode |
file_rename |
Yes | Yes | Derived from file event ID / opcode |
dns_query |
Yes | Yes | Generic category: dns and service: dns, category: network are also supported |
registry_event / registry_* |
Yes | No | Windows only |
image_load |
Yes | No | Windows only |
ps_script |
Yes | No | Windows only |
wmi_event |
Yes | No | Windows only |
service_creation |
Yes | No | Windows only |
task_creation |
Yes | No | Windows only |
Field Model¶
- Sigma evaluates the shared
NormalizedEventmodel with Sysmon-style field names. - Shared process fields include
Image,CommandLine,User,ProcessId,ParentImage, andParentCommandLine. - Shared network fields include
DestinationIp,DestinationPort,SourceIp,SourcePort, andDestinationHostname. - Shared file fields include
TargetFilename,Image,ProcessId, andUser. - DNS rules can use either Sysmon-style names such as
QueryNameandQueryResultsor the generic aliasesquery,answer, andrecord_type.
DNS field availability differs by platform:
| Field | Windows ETW | Linux eBPF |
|---|---|---|
QueryName |
Yes | No |
QueryResults |
Yes | No |
QueryStatus |
Yes | No |
RecordType |
Yes | Yes |
Image |
Yes | Yes |
ProcessId |
Yes | Yes |
On Linux, the current eBPF DNS path does not extract QueryName or QueryResults, so generic DNS rules that depend on domain names or resolved answers are much more effective on Windows today.
After a Sigma hit, Rustinel enriches non-process alerts with process_context from the process cache when that context is available.
Supported Modifiers¶
| Modifier | Meaning |
|---|---|
contains |
Substring match |
startswith |
Prefix match |
endswith |
Suffix match |
all |
All values must match |
cased |
Case-sensitive match |
re |
Regular expression |
i, m, s |
Regex flags |
windash |
Windows dash normalization |
fieldref |
Compare against another field |
exists |
Field presence or null check |
cidr |
IP range matching |
base64 |
Base64-encoded match |
base64offset |
Base64 match with offset variations |
wide, utf16, utf16le, utf16be |
UTF-16 transformations |
lt, gt, le, lte, ge, gte |
Numeric comparison |
Wildcard * and ? matching is also supported for string patterns.
Match Debug¶
alerts.match_debug controls how much match metadata is attached to Sigma alerts:
off: nomatch_detailssummary: adds a short summary, the rule condition, selection results, and matched field or keyword descriptors without the matched field valuesfull: adds the matched field values as well
Rustinel truncates long match metadata to keep alerts bounded.
Severity¶
| Sigma Rule Level | Alert Severity |
|---|---|
critical |
Critical |
high |
High |
medium |
Medium |
| anything else | Low |
YARA¶
YARA scanning is shared across both supported platforms.
Behavior¶
- Rules compile from top-level
.yarand.yarafiles inscanner.yara_rules_path. - Rule loading is not recursive.
- Only process-start events queue YARA scans.
- On Windows, raw ETW paths are normalized before scanning so the worker can open the file.
- Trusted path prefixes are skipped before queueing and checked again in the worker.
- Results are cached by file identity with a 10,000-entry cap and a 6-hour TTL.
- Each matching YARA rule emits its own alert.
Match Debug¶
alerts.match_debug also affects YARA alerts:
off: nomatch_detailssummary: includes the matched rule name and structured rule metadata such as tags and namespacefull: also includes matched string IDs, offsets, and snippets
Severity¶
Every YARA match is emitted as a critical alert.
IOC¶
The IOC engine hot reloads indicator files and splits work between inline event checks and a background hash worker.
Indicator Types¶
| Indicator Type | Source File | Checked Against | Execution Path |
|---|---|---|---|
| Hashes | rules/ioc/hashes.txt |
Process-start executable path | Background worker |
| IPs / CIDRs | rules/ioc/ips.txt |
Network source and destination IPs, plus IPs parsed from DNS answers | Inline |
| Domains | rules/ioc/domains.txt |
DNS QueryName, network DestinationHostname, WMI DestinationHostname |
Inline |
| Path regexes | rules/ioc/paths_regex.txt |
ProcessCreation.Image, ProcessCreation.TargetImage, FileEvent.TargetFilename, ImageLoad.ImageLoaded, PowerShellScript.Path, ServiceCreation.ServiceFileName |
Inline |
Runtime Notes¶
- Hashing only runs when at least one hash IOC is loaded.
- Hashing is triggered from process-start events.
- Trusted path prefixes and
ioc.max_file_size_mbare enforced before hashing. - Hash results are cached by file identity with a 10,000-entry cap and a 6-hour TTL.
- Inline IOC matching can emit multiple alerts from a single event.
Windows currently has much better IOC coverage for domains and DNS-answer IPs because its DNS events carry QueryName and QueryResults. Linux eBPF DNS events do not currently populate those fields.
IOC File Format¶
- Lines beginning with
#or//are comments. - Empty lines are ignored.
;commentsuffixes are optional.- Hashes are auto-detected by length as MD5, SHA1, or SHA256.
- Domain entries without a leading
.are exact matches. - Domain entries with a leading
.match the suffix and all subdomains. - Domain entries with a leading
*.are normalized to suffix matching. - Path regexes are compiled case-insensitive.
Example:
Severity¶
ioc.default_severity maps IOC alerts to critical, high, medium, or low. Unknown values fall back to high.
Overall Severity Mapping¶
| Detector | Severity Behavior |
|---|---|
| Sigma | Uses the rule level with critical, high, and medium mapped explicitly; everything else becomes Low |
| YARA | Every match is Critical |
| IOC | Uses ioc.default_severity |