Analyzing Malware Persistence with Autoruns
Overview
Sysinternals Autoruns extracts data from hundreds of Auto-Start Extensibility Points (ASEPs) on Windows, scanning 18+ categories including Run/RunOnce keys, services, scheduled tasks, drivers, Winlogon entries, LSA providers, print monitors, WMI subscriptions, and AppInit DLLs. Digital signature verification filters Microsoft-signed entries. The compare function identifies newly added persistence via baseline diffing. VirusTotal integration checks hash reputation. Offline analysis via -z flag enables forensic disk image examination.
When to Use
- When investigating security incidents that require analyzing malware persistence with autoruns
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
Prerequisites
- Sysinternals Autoruns (GUI) and Autorunsc (CLI)
- Administrative privileges on target system
- Python 3.9+ for automated analysis
- VirusTotal API key for reputation checks
- Clean baseline export for comparison
Workflow
Step 1: Automated Persistence Scanning
#!/usr/bin/env python3
"""Automate Autoruns-based persistence analysis."""
import subprocess
import csv
import json
import sys
def scan_and_analyze(autorunsc_path="autorunsc64.exe", csv_path="scan.csv"):
cmd = [autorunsc_path, "-a", "*", "-c", "-h", "-s", "-nobanner", "*"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
with open(csv_path, 'w') as f:
f.write(result.stdout)
return parse_and_flag(csv_path)
def parse_and_flag(csv_path):
suspicious = []
with open(csv_path, 'r', errors='replace') as f:
for row in csv.DictReader(f):
reasons = []
signer = row.get("Signer", "")
if not signer or signer == "(Not verified)":
reasons.append("Unsigned binary")
if not row.get("Description") and not row.get("Company"):
reasons.append("Missing metadata")
path = row.get("Image Path", "").lower()
for sp in ["\temp\\", "\appdata\local\temp", "\users\public\\"]:
if sp in path:
reasons.append(f"Suspicious path")
launch = row.get("Launch String", "").lower()
for kw in ["powershell", "cmd /c", "wscript", "mshta", "regsvr32"]:
if kw in launch:
reasons.append(f"LOLBin: {kw}")
if reasons:
row["reasons"] = reasons
suspicious.append(row)
return suspicious
if __name__ == "__main__":
if len(sys.argv) > 1:
results = parse_and_flag(sys.argv[1])
print(f"[!] {len(results)} suspicious entries")
for r in results:
print(f" {r.get('Entry','')} - {r.get('Image Path','')}")
for reason in r.get('reasons', []):
print(f" - {reason}")
Validation Criteria
- All ASEP categories scanned and cataloged
- Unsigned entries flagged for investigation
- Suspicious paths and LOLBin launch strings highlighted
- Baseline comparison identifies new persistence mechanisms
References
1---2name: analyzing-malware-persistence-with-autoruns3description: Use Sysinternals Autoruns to systematically enumerate and analyze malware persistence mechanisms across Windows registry run keys, scheduled tasks, services, drivers, and startup locations. Use when hunting for persistence during Windows incident response, triaging a compromised endpoint, or validating that malware autostart entries have been fully identified and removed.4license: Apache-2.05---6# Analyzing Malware Persistence with Autoruns
7
8## Overview
9
10Sysinternals Autoruns extracts data from hundreds of Auto-Start Extensibility Points (ASEPs) on Windows, scanning 18+ categories including Run/RunOnce keys, services, scheduled tasks, drivers, Winlogon entries, LSA providers, print monitors, WMI subscriptions, and AppInit DLLs. Digital signature verification filters Microsoft-signed entries. The compare function identifies newly added persistence via baseline diffing. VirusTotal integration checks hash reputation. Offline analysis via -z flag enables forensic disk image examination.
11
12
13## When to Use
14
15- When investigating security incidents that require analyzing malware persistence with autoruns
16- When building detection rules or threat hunting queries for this domain
17- When SOC analysts need structured procedures for this analysis type
18- When validating security monitoring coverage for related attack techniques
19
20## Prerequisites
21
22- Sysinternals Autoruns (GUI) and Autorunsc (CLI)
23- Administrative privileges on target system
24- Python 3.9+ for automated analysis
25- VirusTotal API key for reputation checks
26- Clean baseline export for comparison
27
28## Workflow
29
30### Step 1: Automated Persistence Scanning
31
32```python
33#!/usr/bin/env python3
34"""Automate Autoruns-based persistence analysis."""
35import subprocess
36import csv
37import json
38import sys
39
40
41def scan_and_analyze(autorunsc_path="autorunsc64.exe", csv_path="scan.csv"):
42 cmd = [autorunsc_path, "-a", "*", "-c", "-h", "-s", "-nobanner", "*"]
43 result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
44 with open(csv_path, 'w') as f:
45 f.write(result.stdout)
46 return parse_and_flag(csv_path)
47
48
49def parse_and_flag(csv_path):
50 suspicious = []
51 with open(csv_path, 'r', errors='replace') as f:
52 for row in csv.DictReader(f):
53 reasons = []
54 signer = row.get("Signer", "")
55 if not signer or signer == "(Not verified)":
56 reasons.append("Unsigned binary")
57 if not row.get("Description") and not row.get("Company"):
58 reasons.append("Missing metadata")
59 path = row.get("Image Path", "").lower()
60 for sp in ["\temp\\", "\appdata\local\temp", "\users\public\\"]:
61 if sp in path:
62 reasons.append(f"Suspicious path")
63 launch = row.get("Launch String", "").lower()
64 for kw in ["powershell", "cmd /c", "wscript", "mshta", "regsvr32"]:
65 if kw in launch:
66 reasons.append(f"LOLBin: {kw}")
67 if reasons:
68 row["reasons"] = reasons
69 suspicious.append(row)
70 return suspicious
71
72
73if __name__ == "__main__":
74 if len(sys.argv) > 1:
75 results = parse_and_flag(sys.argv[1])
76 print(f"[!] {len(results)} suspicious entries")
77 for r in results:
78 print(f" {r.get('Entry','')} - {r.get('Image Path','')}")
79 for reason in r.get('reasons', []):
80 print(f" - {reason}")
81```
82
83## Validation Criteria
84
85- All ASEP categories scanned and cataloged
86- Unsigned entries flagged for investigation
87- Suspicious paths and LOLBin launch strings highlighted
88- Baseline comparison identifies new persistence mechanisms
89
90## References
91
92- [Sysinternals Autoruns](https://learn.microsoft.com/en-us/sysinternals/downloads/autoruns)
93- [SANS - Offline Autoruns Revisited](https://www.sans.org/blog/offline-autoruns-revisited-auditing-malware-persistence/)
94- [Hunting Malware with Autoruns](https://nasbench.medium.com/hunting-malware-with-windows-sysinternals-autoruns-19cbfe4103c2)
95- [MITRE ATT&CK T1547 - Boot or Logon Autostart](https://attack.mitre.org/techniques/T1547/)