threat hunting

Building Threat Hunt Hypothesis Framework

Build a systematic threat hunt hypothesis framework that transforms threat intelligence, attack patterns, and environmental data into testable hunting hypotheses.

hunting-frameworkhypothesismethodologyproactive-detectionthreat-huntingthreat-intelligence
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • When proactively hunting for indicators of building threat hunt hypothesis framework in the environment
  • After threat intelligence indicates active campaigns using these techniques
  • During incident response to scope compromise related to these techniques
  • When EDR or SIEM alerts trigger on related indicators
  • During periodic security assessments and purple team exercises

Prerequisites

  • EDR platform with process and network telemetry (CrowdStrike, MDE, SentinelOne)
  • SIEM with relevant log data ingested (Splunk, Elastic, Sentinel)
  • Sysmon deployed with comprehensive configuration
  • Windows Security Event Log forwarding enabled
  • Threat intelligence feeds for IOC correlation

Workflow

  1. Formulate Hypothesis: Define a testable hypothesis based on threat intelligence or ATT&CK gap analysis.
  2. Identify Data Sources: Determine which logs and telemetry are needed to validate or refute the hypothesis.
  3. Execute Queries: Run detection queries against SIEM and EDR platforms to collect relevant events.
  4. Analyze Results: Examine query results for anomalies, correlating across multiple data sources.
  5. Validate Findings: Distinguish true positives from false positives through contextual analysis.
  6. Correlate Activity: Link findings to broader attack chains and threat actor TTPs.
  7. Document and Report: Record findings, update detection rules, and recommend response actions.

Key Concepts

Concept Description
TA0001 Initial Access
TA0003 Persistence
TA0008 Lateral Movement
TA0010 Exfiltration

Tools & Systems

Tool Purpose
CrowdStrike Falcon EDR telemetry and threat detection
Microsoft Defender for Endpoint Advanced hunting with KQL
Splunk Enterprise SIEM log analysis with SPL queries
Elastic Security Detection rules and investigation timeline
Sysmon Detailed Windows event monitoring
Velociraptor Endpoint artifact collection and hunting
Sigma Rules Cross-platform detection rule format

Common Scenarios

  1. Scenario 1: Intelligence-driven hunt based on APT campaign report
  2. Scenario 2: ATT&CK coverage gap analysis driving hypothesis creation
  3. Scenario 3: Anomaly-driven hypothesis from UEBA alert investigation
  4. Scenario 4: Situational awareness hunt based on industry sector threats

Output Format

Hunt ID: TH-BUILDI-[DATE]-[SEQ]
Technique: TA0001
Host: [Hostname]
User: [Account context]
Evidence: [Log entries, process trees, network data]
Risk Level: [Critical/High/Medium/Low]
Confidence: [High/Medium/Low]
Recommended Action: [Containment, investigation, monitoring]
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md2.1 KB

API Reference: Threat Hunt Hypothesis Framework

Hypothesis Structure

Field Description
hypothesis_id Unique identifier (HYP-XXXXXXXX)
technique_id MITRE ATT&CK technique (e.g. T1059.001)
hypothesis_statement Natural language hypothesis
data_sources Required log sources
priority high / medium / low
status planned / in_progress / completed

MITRE ATT&CK Data Sources

# Download ATT&CK STIX bundle
curl -O https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json
 
# Filter attack-pattern objects for technique data sources
python3 -c "
import json
bundle = json.load(open('enterprise-attack.json'))
for obj in bundle['objects']:
    if obj.get('type') == 'attack-pattern' and not obj.get('x_mitre_deprecated'):
        eid = obj['external_references'][0]['external_id']
        ds = [d['source_name'] for d in obj.get('x_mitre_data_sources', [])]
        print(f'{eid}: {ds}')
"

Hunt Maturity Model (HMM)

Level Name Description
HM0 Initial Ad hoc, no documented procedures
HM1 Minimal Basic procedures, limited data sources
HM2 Procedural Documented hypotheses, repeatable hunts
HM3 Innovative Custom analytics, TI-driven hypotheses
HM4 Leading Automated, ML-assisted, continuous hunting

Key Windows Event IDs for Hunting

Event ID Source Use Case
4104 PowerShell Script block logging
4688 Security Process creation
4624/4625 Security Logon success/failure
4698 Security Scheduled task created
1 (Sysmon) Sysmon Process create with hashes
3 (Sysmon) Sysmon Network connection
10 (Sysmon) Sysmon Process access (LSASS)
11 (Sysmon) Sysmon File create

Sigma Rule Integration

title: Suspicious PowerShell Execution
status: experimental
logsource:
    product: windows
    service: powershell
detection:
    selection:
        EventID: 4104
        ScriptBlockText|contains:
            - 'Invoke-Mimikatz'
            - 'Invoke-Expression'
    condition: selection
level: high
standards.md1.6 KB

Standards and References - Building Threat Hunt Hypothesis Framework

MITRE ATT&CK Mappings

Technique Name Description
TA0001 Initial Access See attack.mitre.org/techniques/TA0001
TA0003 Persistence See attack.mitre.org/techniques/TA0003
TA0008 Lateral Movement See attack.mitre.org/techniques/TA0008
TA0010 Exfiltration See attack.mitre.org/techniques/TA0010

Detection Data Sources

Source Event ID Purpose
Sysmon 1 Process creation with command line
Sysmon 3 Network connection initiated
Sysmon 7 Image loaded (DLL)
Sysmon 10 Process access (LSASS)
Sysmon 11 File creation
Sysmon 12/13 Registry create/set
Sysmon 22 DNS query
Sysmon 25 Process tampering
Windows Security 4624 Successful logon
Windows Security 4625 Failed logon
Windows Security 4648 Explicit credential logon
Windows Security 4672 Special privileges assigned
Windows Security 4688 Process creation
Windows Security 4697 Service installed
Windows Security 4698 Scheduled task created
Windows Security 4769 Kerberos TGS requested
Windows Security 5140 Network share accessed

References

workflows.md3.1 KB

Detailed Hunting Workflow - Building Threat Hunt Hypothesis Framework

Phase 1: Data Collection and Querying

Splunk SPL Query

| makeresults
| eval hypothesis="Adversaries may be using [TECHNIQUE] to [OBJECTIVE] against [TARGET] via [VECTOR]"
| eval data_sources="[List required data sources]"
| eval queries="[Specific SPL queries to test hypothesis]"
| eval success_criteria="[What constitutes confirming/refuting hypothesis]"

KQL Query (Microsoft Defender for Endpoint)

let HuntHypothesis = datatable(Component:string, Description:string)
[
    "Technique", "MITRE ATT&CK technique being hunted",
    "Target", "Systems or accounts in scope",
    "Data Sources", "Logs and telemetry required",
    "Indicators", "Observable evidence of technique",
    "Success Criteria", "What confirms or refutes hypothesis"
];
HuntHypothesis

Phase 2: Baseline and Anomaly Detection

Step 2.1 - Establish Normal Behavior Baseline

  • Collect 30 days of historical data for the targeted technique
  • Document expected patterns, frequencies, and legitimate use cases
  • Identify known false positive sources and document exceptions
  • Build statistical baseline (mean, standard deviation) for key metrics

Step 2.2 - Identify Anomalies

  • Compare current activity against the 30-day baseline
  • Flag events exceeding 3 standard deviations from normal
  • Prioritize anomalies by risk score and potential business impact
  • Cross-reference with threat intelligence for known IOCs

Phase 3: Investigation and Correlation

Step 3.1 - Deep Dive Analysis

  • For each anomaly, collect full process tree context
  • Correlate with network activity, file operations, and authentication events
  • Check binary signatures, file hashes, and certificate validity
  • Review user account context and access patterns

Step 3.2 - Attack Chain Reconstruction

  • Map findings to MITRE ATT&CK kill chain stages
  • Identify initial access vector if applicable
  • Trace lateral movement and privilege escalation paths
  • Determine data access and potential exfiltration

Phase 4: Validation and Response

Step 4.1 - True/False Positive Determination

  • Verify findings with system owners and IT operations
  • Check change management records for authorized activities
  • Validate user context (authorized actions vs. compromised account)
  • Document determination rationale for each finding

Step 4.2 - Response Actions

  • For confirmed threats: initiate incident response procedures
  • For detection gaps: create or update detection rules
  • For false positives: tune existing rules and update exclusions
  • Update threat hunting playbook with lessons learned

Phase 5: Documentation and Reporting

Step 5.1 - Hunt Report

  • Summarize hypothesis, methodology, and findings
  • Include all queries executed and their results
  • Document IOCs discovered and detection rules created
  • Provide recommendations for security improvements

Step 5.2 - Knowledge Base Update

  • Add findings to threat intelligence platform
  • Update MITRE ATT&CK coverage heatmap
  • Share detection rules via Sigma format
  • Schedule follow-up hunts for related techniques

Scripts 2

agent.py6.6 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Threat hunt hypothesis framework builder.

Generates structured threat hunting hypotheses from MITRE ATT&CK techniques,
maps data sources, defines detection logic, and tracks hunt outcomes.
"""

import sys
import json
import datetime
import hashlib

try:
    import requests
    HAS_REQUESTS = True
except ImportError:
    HAS_REQUESTS = False


HUNT_MATURITY_LEVELS = {
    0: "Initial - ad hoc, no documentation",
    1: "Minimal - basic procedures, limited data",
    2: "Procedural - documented hypotheses, repeatable",
    3: "Innovative - custom analytics, threat intel driven",
    4: "Leading - automated, ML-assisted, continuous",
}

DATA_SOURCE_MAP = {
    "T1059.001": {"name": "PowerShell", "sources": ["Script Block Logging (4104)", "Module Logging (4103)",
                   "Process Creation (4688/Sysmon 1)"], "log_channel": "Microsoft-Windows-PowerShell/Operational"},
    "T1053.005": {"name": "Scheduled Task", "sources": ["Task Scheduler (4698/4702)", "Sysmon Event 1"],
                   "log_channel": "Microsoft-Windows-TaskScheduler/Operational"},
    "T1078": {"name": "Valid Accounts", "sources": ["Logon Events (4624/4625)", "Kerberos (4768/4769)"],
               "log_channel": "Security"},
    "T1003.001": {"name": "LSASS Memory", "sources": ["Sysmon Event 10 (ProcessAccess)", "Windows Defender alerts"],
                   "log_channel": "Microsoft-Windows-Sysmon/Operational"},
    "T1071.001": {"name": "Web Protocols C2", "sources": ["Proxy logs", "DNS query logs", "Zeek http.log"],
                   "log_channel": "Proxy/DNS"},
    "T1486": {"name": "Data Encrypted for Impact", "sources": ["File creation burst (Sysmon 11)",
               "Canary file triggers", "VSS deletion (Sysmon 1)"], "log_channel": "Sysmon"},
    "T1021.001": {"name": "Remote Desktop Protocol", "sources": ["Logon Type 10 (4624)",
                   "RDP connection (1149)"], "log_channel": "Security / TerminalServices-RemoteConnectionManager"},
}


def generate_hypothesis(technique_id, threat_actor=None, environment=None):
    """Generate a structured threat hunting hypothesis."""
    ds = DATA_SOURCE_MAP.get(technique_id, {})
    technique_name = ds.get("name", technique_id)
    hyp_id = "HYP-" + hashlib.md5(
        (technique_id + str(datetime.datetime.utcnow())).encode()
    ).hexdigest()[:8].upper()

    hypothesis = {
        "hypothesis_id": hyp_id,
        "created": datetime.datetime.utcnow().isoformat() + "Z",
        "technique_id": technique_id,
        "technique_name": technique_name,
        "hypothesis_statement": (
            "An adversary{} may be using {} ({}) within our environment{}. "
            "Evidence of this activity can be found in {}.".format(
                " (" + threat_actor + ")" if threat_actor else "",
                technique_name,
                technique_id,
                " targeting " + environment if environment else "",
                ", ".join(ds.get("sources", ["endpoint telemetry"])),
            )
        ),
        "data_sources": ds.get("sources", []),
        "log_channel": ds.get("log_channel", "Unknown"),
        "priority": "high" if technique_id in ["T1003.001", "T1486", "T1059.001"] else "medium",
        "status": "planned",
    }
    return hypothesis


def build_hunt_plan(hypotheses, analyst="SOC Analyst"):
    """Build a hunt plan from a list of hypotheses."""
    plan = {
        "plan_id": "PLAN-" + datetime.datetime.utcnow().strftime("%Y%m%d"),
        "created": datetime.datetime.utcnow().isoformat() + "Z",
        "analyst": analyst,
        "maturity_level": 2,
        "maturity_description": HUNT_MATURITY_LEVELS[2],
        "hypothesis_count": len(hypotheses),
        "hypotheses": hypotheses,
        "data_coverage": list(set(
            src for h in hypotheses for src in h.get("data_sources", [])
        )),
        "estimated_hours": len(hypotheses) * 4,
    }
    return plan


def evaluate_hunt_results(hypothesis, findings_count, true_positives, false_positives):
    """Evaluate hunt execution results and update hypothesis."""
    hypothesis["status"] = "completed"
    hypothesis["results"] = {
        "total_findings": findings_count,
        "true_positives": true_positives,
        "false_positives": false_positives,
        "precision": round(true_positives / max(findings_count, 1), 3),
        "outcome": "confirmed" if true_positives > 0 else "not_confirmed",
        "recommendation": (
            "Create detection rule" if true_positives > 0
            else "Refine hypothesis and re-hunt with broader data"
        ),
    }
    return hypothesis


def fetch_attack_techniques():
    """Fetch MITRE ATT&CK technique list."""
    if not HAS_REQUESTS:
        return list(DATA_SOURCE_MAP.keys())
    try:
        url = "https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json"
        resp = requests.get(url, timeout=30)
        bundle = resp.json()
        techniques = [
            obj["external_references"][0]["external_id"]
            for obj in bundle.get("objects", [])
            if obj.get("type") == "attack-pattern"
            and obj.get("external_references")
            and not obj.get("x_mitre_deprecated", False)
        ]
        return techniques[:50]
    except Exception:
        return list(DATA_SOURCE_MAP.keys())


if __name__ == "__main__":
    print("=" * 60)
    print("Threat Hunt Hypothesis Framework")
    print("Hypothesis generation, hunt planning, result tracking")
    print("=" * 60)

    techniques = sys.argv[1:] if len(sys.argv) > 1 else ["T1059.001", "T1078", "T1003.001", "T1486"]
    actor = "APT29"

    hypotheses = []
    for t in techniques:
        h = generate_hypothesis(t, threat_actor=actor)
        hypotheses.append(h)

    plan = build_hunt_plan(hypotheses)
    print("\nHunt Plan: {} ({} hypotheses, ~{} hours)".format(
        plan["plan_id"], plan["hypothesis_count"], plan["estimated_hours"]))
    print("Maturity: {}".format(plan["maturity_description"]))

    print("\n--- Hypotheses ---")
    for h in hypotheses:
        print("  [{}] {} - {}".format(h["priority"].upper(), h["technique_id"], h["technique_name"]))
        print("    {}".format(h["hypothesis_statement"][:120] + "..."))
        print("    Sources: {}".format(", ".join(h["data_sources"][:3])))

    evaluated = evaluate_hunt_results(hypotheses[0], findings_count=12, true_positives=3, false_positives=9)
    print("\n--- Sample Result ---")
    print("  {} precision: {} -> {}".format(
        evaluated["technique_id"],
        evaluated["results"]["precision"],
        evaluated["results"]["recommendation"]))

    print("\n" + json.dumps({"hypotheses_generated": len(hypotheses)}, indent=2))
process.py3.5 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Threat Hunt Hypothesis Detection - Analyzes logs for TA0001 indicators."""

import json, csv, argparse, datetime, re
from collections import defaultdict
from pathlib import Path

DETECTION_PATTERNS = [
    # Framework skill - no detection patterns
]

def parse_logs(path):
    p = Path(path)
    if p.suffix == ".json":
        with open(p, encoding="utf-8") as f:
            data = json.load(f)
            return data if isinstance(data, list) else data.get("events", [])
    elif p.suffix == ".csv":
        with open(p, encoding="utf-8-sig") as f:
            return [dict(r) for r in csv.DictReader(f)]
    return []

def analyze_event(event):
    cmd = event.get("CommandLine", event.get("command_line", event.get("ProcessCommandLine", "")))
    content = event.get("Task_Content", event.get("Parameters", event.get("RawEventData", "")))
    search_text = f"{cmd} {content}"
    risk = 0
    indicators = []
    for pattern in DETECTION_PATTERNS:
        if re.search(pattern, search_text, re.IGNORECASE):
            risk += 25
            indicators.append(f"Pattern match: {pattern}")
    if not indicators:
        return None
    risk = min(risk, 100)
    return {
        "technique": "TA0001",
        "command_line": cmd[:500] if cmd else content[:500],
        "hostname": event.get("Computer", event.get("DeviceName", event.get("hostname", "unknown"))),
        "user": event.get("User", event.get("AccountName", event.get("UserId", "unknown"))),
        "timestamp": event.get("_time", event.get("timestamp", event.get("UtcTime", event.get("Timestamp", "")))),
        "risk_score": risk,
        "risk_level": "CRITICAL" if risk >= 75 else "HIGH" if risk >= 50 else "MEDIUM" if risk >= 25 else "LOW",
        "indicators": indicators,
    }

def run_hunt(input_path, output_dir):
    print(f"[*] Threat Hunt Hypothesis Hunt - {datetime.datetime.now().isoformat()}")
    events = parse_logs(input_path)
    findings = [f for f in (analyze_event(e) for e in events) if f]
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    slug = "building_threat_hunt"
    with open(Path(output_dir) / f"{slug}_findings.json", "w", encoding="utf-8") as f:
        json.dump({"hunt_id": f"TH-{datetime.date.today()}", "total_events": len(events), "findings": findings}, f, indent=2)
    with open(Path(output_dir) / "hunt_report.md", "w", encoding="utf-8") as f:
        f.write(f"# Threat Hunt Hypothesis Hunt Report\n\n")
        f.write(f"**Date**: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        f.write(f"**Findings**: {len(findings)}\n\n")
        for finding in sorted(findings, key=lambda x: x["risk_score"], reverse=True)[:20]:
            f.write(f"### [{finding['risk_level']}] {finding['technique']}\n")
            f.write(f"- **Host**: {finding['hostname']}\n")
            f.write(f"- **Indicators**: {', '.join(finding['indicators'])}\n\n")
    print(f"[+] {len(findings)} findings written to {output_dir}")

def main():
    p = argparse.ArgumentParser(description="Threat Hunt Hypothesis Detection")
    sp = p.add_subparsers(dest="cmd")
    h = sp.add_parser("hunt"); h.add_argument("--input", "-i", required=True); h.add_argument("--output", "-o", default="./building_threat_output")
    sp.add_parser("queries")
    args = p.parse_args()
    if args.cmd == "hunt": run_hunt(args.input, args.output)
    elif args.cmd == "queries":
        print("=== Detection Queries ===")
        print("See references/workflows.md for platform-specific queries")
    else: p.print_help()

if __name__ == "__main__": main()

Assets 1

template.mdtext/markdown · 2.6 KB
Keep exploring