Detecting Malicious Service Persistence via Windows Event 7045 and Systemd Unit Forensics
Theory
Why This Matters
Service-based persistence is one of the most reliable and common post-compromise persistence mechanisms because services start automatically at boot, run under SYSTEM or privileged accounts, and are often overlooked in routine security reviews. The 2020 SolarWinds breach used a malicious service DLL loaded by the legitimate SolarWinds.Orion.Core.BusinessLayer.dll component. Defenders who monitor for new service installation events can detect this technique in near-real-time; defenders who do not may never discover persistence until a re-infection occurs after containment.
Core Concept
Service-based persistence on Windows exploits the Service Control Manager (SCM). A new service is registered by writing to HKLMSYSTEMCurrentControlSetServices<ServiceName> in the registry and notifying the SCM. Windows generates:
- Event 7045 (System log): "A new service was installed in the system." Records: ServiceName, ServiceFileName (binary path), ServiceType, StartType, ServiceAccount.
- Event 7036 (System log): "The
service entered the running/stopped state." Tracks service state transitions.
On Linux, systemd unit files (.service files) are placed in /etc/systemd/system/ (system-wide) or /usr/lib/systemd/system/ (package-installed). Enabling a unit creates symlinks in /etc/systemd/system/multi-user.target.wants/. Legacy init.d scripts appear in /etc/init.d/. SysV-style service registration creates symlinks in /etc/rc*.d/.
Key forensic questions for any discovered service: Who created it? When? What binary does it execute? Does that binary exist? Is it signed? Is the service name plausible for the environment?
Technical Deep-Dive
-- Splunk: detect new service installation (Event 7045)
index=wineventlog EventCode=7045
| table _time ComputerName ServiceName ServiceFileName ServiceType StartType ServiceAccount
| sort _time
-- Splunk: correlate service installation with subsequent service start
index=wineventlog (EventCode=7045 OR EventCode=7036)
| eval evt = case(EventCode=7045, "INSTALL", EventCode=7036, "STATE_CHANGE", true(), "OTHER")
| transaction ServiceName maxspan=10m startswith="INSTALL" endswith="STATE_CHANGE"
| table _time duration ComputerName ServiceName ServiceFileName
| sort _time
# Linux: list systemd units not installed by packages (potential attacker-created)
# Compare against dpkg/rpm database
comm -23
<(find /etc/systemd/system/ /usr/lib/systemd/system/ -name "*.service"
| xargs -I{} basename {} .service | sort)
<(dpkg -l 2>/dev/null | awk '''/^ii/{print $2}'''
| xargs dpkg -L 2>/dev/null | grep ".service$"
| xargs -I{} basename {} .service | sort)
# Examine recently created systemd unit files
find /etc/systemd/system/ /usr/lib/systemd/system/
-name "*.service" -newer /etc/passwd -ls
# Extract binary path from a suspicious systemd service file
grep -E "^ExecStart|^ExecStartPre|^ExecStartPost"
/etc/systemd/system/suspicious.service
# Check if the binary is signed (Linux: no standard signing, but check with file/strings)
file /usr/local/bin/suspicious_binary
strings /usr/local/bin/suspicious_binary | grep -E "(http|https|C2|beacon)"
# Windows: registry-based service enumeration (from offline registry hive)
# Use regripper or python-registry to extract HKLMSYSTEMCurrentControlSetServices
# python-registry example:
# from Registry import Registry
# reg = Registry.Registry("SYSTEM.hiv")
# key = reg.open("ControlSet001\Services")
# for subkey in key.subkeys():
# print(subkey.name(), subkey.timestamp())
Analytical Methodology
- On Windows: pull Event 7045 records across all hosts for the investigation period. Sort by timestamp. Any service installed during or after the suspected compromise time is a finding.
- For each suspicious 7045 event, examine ServiceFileName: the binary path. Does the binary exist? Is it in a standard system directory (C:WindowsSystem32) or an unusual location (C:Users, C:ProgramData, temp directories)?
- Check whether the binary path is a legitimate signed Microsoft or vendor binary. Use Sigcheck or PowerShell
Get-AuthenticodeSignature. Unsigned binaries in System32 or signed binaries with mismatched subject names are red flags. - Examine ServiceAccount: services running as SYSTEM or LocalSystem have the highest privilege. Services running under a specific user account may indicate attacker-controlled credential use.
- Cross-reference with registry artefacts:
HKLMSYSTEMCurrentControlSetServices<name>— check ImagePath, Description, and LastWrite timestamp of the registry key. - On Linux: list all
.servicefiles in systemd directories and compare against the package manager database. Any unit not installed by a recognised package and not present in the pre-incident baseline is suspicious. - Examine the unit file's
ExecStartdirective. Run the binary through static analysis: check file type, strings output, and hash against VirusTotal (if network is available on the analysis workstation). - Check for service start-type:
StartType=2(Automatic) on Windows andWantedBy=multi-user.targeton Linux confirm the service will survive reboots — persistence is established.
Common Analytical Errors
- Assuming System32 location implies legitimacy: Attackers frequently place malicious binaries in System32 because it looks legitimate. Always check the signature and hash, not just the path.
- Missing event 7045 due to System log clearance: Attackers who clear the System log (Event 104) remove 7045 evidence. Check SIEM for the forwarded copy. Also check the registry — the service key persists even after log clearance.
- Overlooking renamed services: Attackers may name malicious services to mimic legitimate ones (e.g.,
Windows Update Serviceinstead ofwuauserv). Check for slight name variations and compare to the expected display name. - Not checking enabled systemd units on Linux: A unit file may be present but disabled.
systemctl is-enabled <unit>andls /etc/systemd/system/multi-user.target.wants/confirm whether persistence is actually active.
NICE Framework Alignment
| Code | Work Role Knowledge / Skill / Task | Relevance |
|---|---|---|
| K0046 | Knowledge of intrusion detection methodologies | Event 7045 monitoring is a core Windows persistence detection control |
| K0145 | Knowledge of security event correlation tools | Correlating Event 7045 with 7036 and registry artefacts in a SIEM timeline |
| K0187 | Knowledge of file type abuse by adversaries | PE service binaries are often disguised with legitimate-looking names and paths |
| S0047 | Skill in preserving evidence integrity | Registry hive export and systemd unit file collection preserve service persistence evidence |
| T0049 | Decrypt seized data / analyze forensic artifacts | Parsing registry hives offline to enumerate historical service installations |
Further Reading
- MITRE ATT&CK T1543.003: Windows Service — detection data sources and sub-techniques
- Microsoft Docs: System Event ID 7045 — field definitions and SCM architecture
- systemd.service(5) man page — unit file syntax and ExecStart semantics
- Velociraptor: Windows.System.Services artifact — automated service enumeration
- SANS FOR508: Advanced DFIR — Windows persistence mechanism catalogue
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.