NanoCore: Registry Run Key Persistence — Detection
NanoCore copies itself into a GUID-named folder under %APPDATA% using a masquerading
service name, then points a CurrentVersion\\Run value at that copy. The run key write and
the self-copy are separate, and either one alone is worth an alert.
MITRE ATT&CK: T1547.001
Technique write-up: NanoCore_PersistenceRegKeys
Detection Indicators
| Indicator | Value |
|---|---|
| Registry key | HKCU\Software\Microsoft\Windows\CurrentVersion\Run |
| Value name | empty — the sample writes the key’s (Default) value, not a named one |
| Value data | a path under %APPDATA%\<GUID>\ ending in .exe |
| Payload path | %APPDATA%\{GUID}\<masqueraded service name>\<name>.exe |
| Behaviour | the writing process is the same image the value points at, MD5-compared before copying |
Writing the (Default) value of a Run key is the sharpest of these. Legitimate software
registers a named value; the default value of ...\CurrentVersion\Run is normally empty.
Log Sources
- Microsoft Defender XDR (
DeviceRegistryEvents) - Sysmon EID 12, 13, 14 (registry)
- Windows Security 4657 (registry value modified)
- Microsoft Defender XDR (
DeviceFileEvents) - Sysmon EID 11 (file create), EID 23/26 (file delete)
Detection Engineering with Defender XDR
Run key written with a value pointing into a GUID-named AppData folder.
DeviceRegistryEvents
| where ActionType in ("RegistryValueSet", "RegistryKeyCreated")
| where RegistryKey has @"CurrentVersion\Run"
| where RegistryValueData has_any (@"\AppData\Roaming\", @"\AppData\Local\")
| where RegistryValueData matches regex @"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
| project Timestamp, DeviceName, AccountName, RegistryKey, RegistryValueName,
RegistryValueData, InitiatingProcessFileName, InitiatingProcessFolderPath
| order by Timestamp desc
Detection Engineering with Sysmon
The same write seen through Sysmon registry events, plus the empty value name.
WindowsEvent //(sysmon)
| where EventID in (12, 13, 14)
| extend TargetObject = tostring(EventData.TargetObject), Details = tostring(EventData.Details)
| where TargetObject has @"CurrentVersion\Run"
| where Details has @"\AppData\" or TargetObject endswith @"\Run\"
| project TimeGenerated, Computer, EventID, Image = tostring(EventData.Image), TargetObject, Details
Detection Engineering with SIGMA
Full rule: sigma_nanocore_runkey_persistence.yml
detection:
selection_key:
TargetObject|contains: '\Software\Microsoft\Windows\CurrentVersion\Run'
selection_appdata:
Details|contains:
- '\AppData\Roaming\'
- '\AppData\Local\'
condition: all of selection_*
Notes and tuning
Baseline the Run key in your estate first — installers and updaters write here constantly.
The two narrowing conditions that carry the fidelity are the AppData target and the
GUID-shaped folder name; a Run value pointing at Program Files is almost always benign.
Pair with the file-create side: a process copying itself to
%APPDATA%\<GUID>\...\*.exe immediately before the registry write is the full sequence.
Disclaimer
For educational purposes only!!!