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
Detection Gaps & Validation
- Autoruns doesn't cover every ASEP. COM hijacking, certain WMI event-consumer subscriptions, and fully fileless/in-memory persistence may not surface. Corroborate with Sysmon (Event IDs 12-13, 19-21),
wmic/Get-WmiObject for __EventConsumer, and Volatility for memory-only implants.
- Live runs can be lied to. A rootkit on the running host can hide its own autostart entry; prefer offline analysis with
autorunsc -z against a mounted disk image, then diff against a clean baseline.
- Signed != trusted. Malware abuses signed LOLBins (
regsvr32, mshta, rundll32) and can sit behind a valid Microsoft signature; "Hide Microsoft entries" can mask a binary masquerading from System32. Verify the signature is valid (not just present) and that the path/name match the real product.
- Confirm a hit: check the hash on VirusTotal, validate the digital-signature state, confirm the launch string/path against a known-good baseline, and corroborate the entry from a second source (Sysmon, raw registry hive, scheduled-task XML) rather than Autoruns alone.
- False positives: legitimate line-of-business apps, OEM utilities, and dev tools are often unsigned, run from odd paths, or use script launchers. Require corroborating indicators before flagging an unsigned entry.
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 identify and analyze malware persistence mechanisms across registry keys, scheduled tasks, services, drivers, and startup locations on Windows systems.4license: Apache-2.05---6# Analyzing Malware Persistence with Autoruns78## Overview910Sysinternals 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.111213## When to Use1415- When investigating security incidents that require analyzing malware persistence with autoruns16- When building detection rules or threat hunting queries for this domain17- When SOC analysts need structured procedures for this analysis type18- When validating security monitoring coverage for related attack techniques1920## Detection Gaps & Validation2122- **Autoruns doesn't cover every ASEP.** COM hijacking, certain WMI event-consumer subscriptions, and fully fileless/in-memory persistence may not surface. Corroborate with Sysmon (Event IDs 12-13, 19-21), `wmic`/`Get-WmiObject` for `__EventConsumer`, and Volatility for memory-only implants.23- **Live runs can be lied to.** A rootkit on the running host can hide its own autostart entry; prefer offline analysis with `autorunsc -z` against a mounted disk image, then diff against a clean baseline.24- **Signed != trusted.** Malware abuses signed LOLBins (`regsvr32`, `mshta`, `rundll32`) and can sit behind a valid Microsoft signature; "Hide Microsoft entries" can mask a binary masquerading from `System32`. Verify the signature is *valid* (not just present) and that the path/name match the real product.25- **Confirm a hit:** check the hash on VirusTotal, validate the digital-signature state, confirm the launch string/path against a known-good baseline, and corroborate the entry from a second source (Sysmon, raw registry hive, scheduled-task XML) rather than Autoruns alone.26- **False positives:** legitimate line-of-business apps, OEM utilities, and dev tools are often unsigned, run from odd paths, or use script launchers. Require corroborating indicators before flagging an unsigned entry.2728## Prerequisites2930- Sysinternals Autoruns (GUI) and Autorunsc (CLI)31- Administrative privileges on target system32- Python 3.9+ for automated analysis33- VirusTotal API key for reputation checks34- Clean baseline export for comparison3536## Workflow3738### Step 1: Automated Persistence Scanning3940```python41#!/usr/bin/env python342"""Automate Autoruns-based persistence analysis."""43import subprocess44import csv45import json46import sys474849def scan_and_analyze(autorunsc_path="autorunsc64.exe", csv_path="scan.csv"):50 cmd = [autorunsc_path, "-a", "*", "-c", "-h", "-s", "-nobanner", "*"]51 result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)52 with open(csv_path, 'w') as f:53 f.write(result.stdout)54 return parse_and_flag(csv_path)555657def parse_and_flag(csv_path):58 suspicious = []59 with open(csv_path, 'r', errors='replace') as f:60 for row in csv.DictReader(f):61 reasons = []62 signer = row.get("Signer", "")63 if not signer or signer == "(Not verified)":64 reasons.append("Unsigned binary")65 if not row.get("Description") and not row.get("Company"):66 reasons.append("Missing metadata")67 path = row.get("Image Path", "").lower()68 for sp in ["\temp\\", "\appdata\local\temp", "\users\public\\"]:69 if sp in path:70 reasons.append(f"Suspicious path")71 launch = row.get("Launch String", "").lower()72 for kw in ["powershell", "cmd /c", "wscript", "mshta", "regsvr32"]:73 if kw in launch:74 reasons.append(f"LOLBin: {kw}")75 if reasons:76 row["reasons"] = reasons77 suspicious.append(row)78 return suspicious798081if __name__ == "__main__":82 if len(sys.argv) > 1:83 results = parse_and_flag(sys.argv[1])84 print(f"[!] {len(results)} suspicious entries")85 for r in results:86 print(f" {r.get('Entry','')} - {r.get('Image Path','')}")87 for reason in r.get('reasons', []):88 print(f" - {reason}")89```9091## Validation Criteria9293- All ASEP categories scanned and cataloged94- Unsigned entries flagged for investigation95- Suspicious paths and LOLBin launch strings highlighted96- Baseline comparison identifies new persistence mechanisms9798## References99100- [Sysinternals Autoruns](https://learn.microsoft.com/en-us/sysinternals/downloads/autoruns)101- [SANS - Offline Autoruns Revisited](https://www.sans.org/blog/offline-autoruns-revisited-auditing-malware-persistence/)102- [Hunting Malware with Autoruns](https://nasbench.medium.com/hunting-malware-with-windows-sysinternals-autoruns-19cbfe4103c2)103- [MITRE ATT&CK T1547 - Boot or Logon Autostart](https://attack.mitre.org/techniques/T1547/)