Hunting G-G-G-GhostTasks!
Detecting a Spooktacular Persistence Procedure
Introduction
It’s the Saturday before Halloween, and I should be upstairs watching a scary movie or something, but a post from earlier has me thinking about persistence artifacts, and how to find them:
User Kai, aka @adversaryminded, shared a cool tool for generating scheduled tasks (a classic persistence mechanism) without leaving the usual trail of breadcrumbs that we see in the form of Windows security events, process creation events, Powershell cmdlets, or other things. Introducing…GhostTasks!
Yikes! So much of my thinking around scheduled tasks is based on what MITRE ATT&CK and Atomic Red Team very helpfully tell us are the most common procedures to achieve persistence via scheduled tasks. As a detection engineer, it can be intimidating to realize that even with the scope of the attack surface growing constantly, it’s still necessary to maintain an awareness of the bases we thought we had “covered,” detection-wise.
Fortunately for all involved, user Ahmed/@00biwan helpfully asked the most important question of all:
Right on, Ahmed! That is the key question indeed. Responses from industry pros indicated that, while there are some useful detection concepts already for GhostTasks (we’ll get to those in a bit), this was not a technique that has been fully explored. That’s what I hope to do in this short piece!
Objectives (Caution, cheesy metaphors ahead):
👻Create one of these spectral scheduled tasks ourselves, to see how the tool works.
🕯️Search through the catacombs of our logs for the ectoplasm leftover from our ghostly scheduled tasks.
🎃Carve meaningful indicators into the decorative gourds of our raw telemetry until a ghoulish grin spreads across our twisted face.
🕸️Review the existing web of detection concepts available to catch this nefarious activity.
🌕Shine the light of the full moon on these crafty procedures, sharing new and improved detection logic with our fellow detection warlocks so that they might face down the demonic threat actors who seek our doom.
🍫Celebrate with candy!
Ghost Hunting
The first step was to test our GhostTasks.exe in our lab. This was fairly straightforward, as the examples in the GitHub repo are clear and useful. The only challenge I encountered was running the commands as NT AUTHORITY\SYSTEM, a requirement of the tool. I realized that this was not as simple as running the command as an administrator, but after a few minutes of research I am across this helpful blog post which explained how to overcome this minor obstacle, by initiating a SYSTEM CMD session using PsExec:
Using my win10 VM from DetectionLab.network, which has Sysinternals PsExec pre-installed, I initiated an interactive CMD session running as SYSTEM using this command:
C:\Users\vagrant>C:\Tools\Sysinternals\PsExec64.exe -i -s -accepteula cmd.exe
After downloading GhostTask.exe, I ran a command closely mirroring the example from Github, adding a “Ghost Task” called “FlyingDutchmanQuote” which would, I hoped, launch notepad with the text seen below each time a user logged on:
>GhostTask.exe localhost add FlyingDutchmanQuote "cmd.exe" "/c echo \"Insulting a man's ship be worse than insulting his mother!\" > Dutchman.txt && notepad.exe Dutchman.txt" win10\vagrant logon
Before running this command, my task scheduler showed four tasks at the root level of the scheduled task tree:
PS C:\Users\vagrant> Get-ScheduledTask -TaskPath \
TaskPath TaskName State
-------- -------- -----
\ AutorunsToWinEventLog Running
\ GoogleUpdateTaskMachineCore{BF... Running
\ GoogleUpdateTaskMachineUA{93F4... Running
\ OneDrive Reporting Task-S-1-5-... Ready
After, a new task had been added to the result of the Powershell Get-ScheduledTask cmdlet, but it was invisible in the task scheduler GUI utility. Ghostly indeed!
To test the task, I restarted my lab VM, logged on, and to my delight saw that my scheduled task had fired as expected:
I was presented with a classic quote from one of my favorite TV ghost pirates, the Flying Dutchman!
Before moving on to the analysis and detection portion of the test, I decided to run a couple of Atomic Red Team tests for T1053.005: Scheduled Task, to create some tasks and log events that I could use for comparison. Using the documentation below, I chose to run tests 1, 2, 4, and 7:
By the way, I decided to make use of the Invoke-AtomicRedTeam Powershell module for these tests. I really recommend this to folks who have not yet explored it! After some initial setup it was very easy to use.
Now that I had demonstrated the procedure, it was time to delve into the logs to see what trail of evidence had been left behind. Read on, if you dare!
Into the Catacombs
Windows Events
One of the most reliable ways to detect a new scheduled task is with Windows Event ID 4698: A scheduled task was created. Searches for these events in my logs over a time period that I know covers my test activity, I see a number of entries:
The last entry appears to be a normal Windows update-related scheduled task. The other five entries have names which match the output dialog from the Atomic Red Team tests that I ran above. Conspicuously absent was the “FlyingDutchmanQuote” task which I created using GhostTask.exe!
Process Creations
A second MITRE-approved method of detecting suspicious scheduled tasks is with process creation logs. By identifying the processes commonly used by attackers to create scheduled tasks, and monitoring the command-line arguments used for suspicious process parameters, defenders can detect a lot of the malicious tasks used by malware like Gootloader. In my case, I was able to identify the GhostTask.exe command, as well as the Atomic Red Team task commands, but only because I knew that GhostTask.exe was the process name I was looking for.
Remember, GhostTask.exe is only one utility that can perform this procedure, and it could easily be renamed or otherwise obfuscated by a creative attacker to cover their tracks.
Registry Event Logging
With normal Windows security events failing to capture our ghost task, and process creations doing so only in an unreliable way, where does that leave us? By wildcard searching my Sysmon logs for the task “FlyingDutchmanQuote” I got my answer (which was also mentioned in the thread which drew my attention to GhostTasks): The registry!
index=sysmon *flyingdutchmanquote*
| table _time, ComputerName, EventCode, EventType, Image, TargetObject, Details
Ah hah! Here I had a number of “TaskCache” registry values set, which provided a meaningful starting point from which to develop a detection.
Carving the Log-o-Lantern
With the registry events shown above, I had a meaningful “trailhead” from which to begin my investigative journey. Reviewing Sysmon event 13, I can see that this event shows when a registry value is set, with a value written to the registry key specified in the TargetObject field. By researching the TaskCache registry key that appeared in my logs, I learned that the data and settings for scheduled tasks are stored here:
It is worth noting, however, that Sysmon event 13 (and similar events in other endpoint logging/monitoring solutions) will be a very, very common event in your environment. Reviewing these logs in my test lab, I determined that I needed some help with identifying the registry set events which would identify only anomalous scheduled tasks. As any SOC analyst (or anyone who works with SOC analysts) knows, it does no good to find suspicious activity in logs if that activity is buried under a mountain of events that simply represent “business as usual.”
Reviewing the Existing Web of Detection
Thankfully, if you set out to find GhostTasks in your environment, you are not alone, nor do you need to start from scratch. I found three helpful rules in the Sigma rules repository:
- Scheduled Task Created — Registry
- Hide Schedule Task Via Index Value Tamper
- Scheduled TaskCache Change by Uncommon Program
Using https://sigconverter.io/, I converted each of these rules to Splunk query format and tested them out.
😵Option 1 above captured the GhostTask, but also capture many, many other scheduled task-related results. Therefore, I decided this rule was a bit too broad for my purposes.
❌Option 2 above did not capture the registry events that resulted from creation of the GhostTask.
✔️Option 3 worked perfectly! Not only did it isolate the TaskCache registry keys created by the GhostTask utility, it also filtered out any registry updates performed by the scvhost.exe process (the standard process responsible for scheduled task-related registry updates). I found the ideal solution!
Ghostly Evasion
But beware! Even great detection rules like the one above can be bypassed. I consider it a fun and educational exercise to attempt to circumvent the rules I find, with an eye towards making them stronger. In this case, by copying GhostTask.exe to C:\Windows\Temp and renaming it “TiWorker.exe” (excluded from the existing rule) I was able to avoid detection. See the example GhostTask “FlyingDutchmanReturns” created below using a renamed GhostTask.exe:
Illuminating GhostTasks
I want to make clear that, by pointing out how the existing rule “Scheduled TaskCache Change by Uncommon Program” can be evaded by renaming a binary, I by no means wish to dismiss the rule or its creator. In fact, this was the only rule I found which reliably detects GhostTask creation without generating a lot of potential false positives. Since TiWorker.exe normally resides in the “Windows Side by Side”/WinSxS folder, a simple change to the rule will narrow the exclusion and slightly reduce the ease by which an attacker could get around this. See the filter_tiworker detection item below:
title: Scheduled TaskCache Change by Uncommon Program
id: 4720b7df-40c3-48fd-bbdf-fd4b3c464f0d
status: experimental
description: Monitor the creation of a new key under 'TaskCache' when a new scheduled task is registered by a process that is not svchost.exe, which is suspicious
references:
- https://thedfirreport.com/2021/03/29/sodinokibi-aka-revil-ransomware/
- https://labs.f-secure.com/blog/scheduled-task-tampering/
author: Syed Hasan (@syedhasan009) (with minor edit by Micah Babinski)
date: 2021/06/18
modified: 2023/10/29
tags:
- attack.persistence
- attack.t1053
- attack.t1053.005
logsource:
category: registry_set
product: windows
detection:
selection:
TargetObject|contains: 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\'
filter:
TargetObject|contains:
- 'Microsoft\Windows\UpdateOrchestrator'
- 'Microsoft\Windows\SoftwareProtectionPlatform\SvcRestartTask\Index'
- 'Microsoft\Windows\Flighting\OneSettings\RefreshCache\Index'
filter_tiworker:
Image|startswith: 'C:\Windows\WinSxS\' # slightly narrowing this filter
Image|endswith: '\TiWorker.exe'
filter_svchost:
Image: 'C:\WINDOWS\system32\svchost.exe'
filter_ngen:
Image|startswith: 'C:\Windows\Microsoft.NET\Framework' # \Framework\ and \Framework64\
Image|endswith: '\ngen.exe'
TargetObject|contains:
- '\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{B66B135D-DA06-4FC4-95F8-7458E1D10129}'
- '\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\.NET Framework\.NET Framework NGEN'
filter_office_click_to_run:
Image:
- 'C:\Program Files\Microsoft Office\root\Integration\Integrator.exe'
- 'C:\Program Files (x86)\Microsoft Office\root\Integration\Integrator.exe'
filter_msiexec:
Image: 'C:\Windows\System32\msiexec.exe'
filter_dropbox_updater:
Image:
- 'C:\Program Files (x86)\Dropbox\Update\DropboxUpdate.exe'
- 'C:\Program Files\Dropbox\Update\DropboxUpdate.exe'
filter_explorer:
Image: 'C:\Windows\explorer.exe'
TargetObject|contains: '\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\PLA\Server Manager Performance Monitor\'
filter_system:
Image: 'System'
condition: selection and not 1 of filter*
falsepositives:
- Unknown
level: high
Conclusion
To conclude, it is always valuable for Defenders to stay curious and open-minded about new ways of executing on familiar attacker techniques. I had never heard of GhostTasks before today. Having hunted them in my lab I feel armed with a decent understanding of the procedure, and am confident that I have a reliable way to detect them in my environment. It’s important to remember that what exists within MITRE ATT&CK and Atomic Red Team (both amazing sources of information, by the way), is by no means exhaustive!
Maybe next time I will write about trying to get a test added to the Atomic Red Team project for GhostTasks, or some other sneaky procedure that I hear about attackers using in an attempt to harm their victims.
Until then, I wish you a safe and enjoyable Halloween, Samhain, Day of the Dead, or whatever you choose to celebrate. And as always, happy analyzing!
Detectionately Yours,
Micah Babinski