NanoCore: Scheduled Task Privilege Escalation — Detection

NanoCore Image

Run once with admin rights, NanoCore registers a scheduled task configured to run at the highest available privilege. From then on it can regain admin at will — and across reboots — by simply running that task, with no further prompt.

MITRE ATT&CK: T1053.005

Technique write-up: NanoCore_PrivEscalation

Detection Indicators

Indicator Value
Registration schtasks.exe /create /f /tn "NTFS Manager" /xml <temp file>
Task name masquerades as a Windows component — NTFS Manager here, randomised in the wild
Task XML <RunLevel>HighestAvailable</RunLevel>, <LogonType>InteractiveToken</LogonType>
Task XML <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>, MultipleInstancesPolicy Parallel, no <Triggers>
Action %APPDATA%\<GUID>\NTFS Manager\ntfsmgr.exe
Re-elevation schtasks.exe /run /tn "NTFS Manager"

A task with HighestAvailable, no triggers, and an action under %APPDATA% is the shape to hunt. No triggers means it exists purely to be run on demand — the opposite of what a scheduled task is for.

Log Sources

Detection Engineering with Defender XDR

Task registered from an XML file, and the later on-demand run.

// Registration and re-elevation, in one query
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine has_any ("/create", "/run")
| extend stage = case(ProcessCommandLine has "/create", "register",
                      ProcessCommandLine has "/run",    "elevate", "other")
| where ProcessCommandLine has "/xml" or stage == "elevate"
| project Timestamp, DeviceName, AccountName, stage, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessFolderPath, ProcessIntegrityLevel
| order by Timestamp desc

Detection Engineering with Sysmon

The task action path is the durable half — the binary lives under AppData.

WindowsEvent //(sysmon)
| where EventID == 1
| extend CommandLine = tostring(EventData.CommandLine), Image = tostring(EventData.Image)
| where Image endswith "\schtasks.exe"
| where CommandLine has "/create" and CommandLine has "/xml"
| project TimeGenerated, Computer, Image, CommandLine,
          ParentImage = tostring(EventData.ParentImage)

Detection Engineering with SIGMA

Full rule: sigma_nanocore_schtask_privesc.yml

detection:
    selection_img:
        Image|endswith: '\schtasks.exe'
    selection_create:
        CommandLine|contains|all:
            - '/create'
            - '/xml'
    condition: all of selection_*

Notes and tuning

Registering a task from an XML file is the narrowing condition. Most legitimate task creation on endpoints goes through the GUI or through /tn plus /tr inline, not /xml pointing at a file in %TEMP%.

The stronger, tool-agnostic hunt is on the task definition itself: Security 4698 carries the full XML, so alert on HighestAvailable combined with an action path under AppData and an empty <Triggers> element. That survives the attacker dropping schtasks.exe for the Task Scheduler COM API.

Disclaimer

For educational purposes only!!!