Chronos-DFIR features a 100% offline detection engine with 86 Sigma rules and 7 YARA rule sets covering the full MITRE ATT&CK matrix. All detection happens in real-time during file ingestion with zero external dependencies.
Zero Performance Penalty: Sigma rules compile to native Polars expressions using SIMD vectorization. Evaluation of 86 rules against 100K events takes < 2 seconds.
YARA rules scan file contents and memory dumps for IOCs:
# From app.py:706-766 - YARA scan during forensic analysisimport yaradef _load_yara_rules(): """Load all .yar files from rules/yara/ directory.""" yara_dir = os.path.join(BASE_DIR, "rules", "yara") rule_files = {} for root, dirs, files in os.walk(yara_dir): for file in files: if file.endswith('.yar'): namespace = os.path.splitext(file)[0] rule_files[namespace] = os.path.join(root, file) return yara.compile(filepaths=rule_files)# Scan during forensic report generationyara_rules = _load_yara_rules()with open(csv_path, "r", errors="replace") as yf: yara_text = yf.read(5 * 1024 * 1024) # First 5MByara_matches = yara_rules.match(data=yara_text)yara_hits = [{ "rule": m.rule, "namespace": m.namespace, "tags": list(m.tags), "strings_matched": len(m.strings), "meta": {k: str(v) for k, v in (m.meta or {}).items()}} for m in yara_matches]
YARA Scope: YARA scans the first 5MB of the ingested CSV file content. For memory dumps or large binaries, pre-process with dedicated YARA tools before ingestion.
All detections are automatically mapped to MITRE techniques:
# From engine/sigma_engine.py:541-567raw_tags = rule.get("tags", []) or []tags = []for t in raw_tags: t_lower = str(t).lower().strip() # Normalize "mitre.tXXXX" → "attack.tXXXX" if t_lower.startswith("mitre.t"): t_lower = "attack." + t_lower[6:] tags.append(t_lower)hits.append({ "title": rule.get("title", "Unknown Rule"), "level": rule.get("level", "unknown"), "mitre_technique": custom.get("mitre_technique", next((t for t in tags if t.startswith("attack.t")), "") ), "mitre_tactic": custom.get("mitre_tactic", next((t for t in tags if t.startswith("attack.") and not t.startswith("attack.t")), "") ),})
# From engine/forensic.py - calculate_smart_risk_m4()def calculate_smart_risk_m4(df: pl.DataFrame, sigma_hits: list = None) -> dict: """Unified risk calculation from Sigma hits, EventIDs, and anomalies.""" score = 0 justifications = [] # Sigma detections (weighted by level) if sigma_hits: critical = sum(1 for h in sigma_hits if h['level'] == 'critical') high = sum(1 for h in sigma_hits if h['level'] == 'high') medium = sum(1 for h in sigma_hits if h['level'] == 'medium') score += critical * 50 # Critical = 50 points each score += high * 30 # High = 30 points score += medium * 10 # Medium = 10 points if critical > 0: justifications.append(f"{critical} Critical Sigma detections") # High-risk EventIDs (4625=Failed logon, 4720=Account created) high_risk_events = [4625, 4720, 4728, 4732, 4756] event_col = next((c for c in df.columns if 'eventid' in c.lower()), None) if event_col: risk_count = df.filter( pl.col(event_col).cast(pl.Int32, strict=False).is_in(high_risk_events) ).height score += risk_count * 2 # Determine risk level if score >= 100: level = "Critical" elif score >= 50: level = "High" elif score >= 20: level = "Medium" else: level = "Low" return { "level": level, "score": score, "justification": "; ".join(justifications) }
Risk Level Homologation: The same risk calculation is used in the dashboard, forensic modal, HTML report, and PDF export to ensure consistency (fixed in v177).
Interactive Drill-Down: Click a Sigma detection in the forensic modal to see the evidence table. Click “View all in Grid” to filter the main timeline to matching events.