Hunting Volt Typhoon TTPs

montysecurity
4 min readDec 9, 2023

--

At the time of writing (December 2023), Volt Typhoon only has 3 references in MITRE but they are rich with details on procedures. It is also worth calling out that Microsoft released hunting queries with their publication on this group. I will not showcase them in this blog, but they can be found here.

That being said, lets go through what we have and start making hunts. You will see certain filters commented out in the searches, these are to act as guidance in case the search returns too many results to begin with. This mostly applies to renamed/relocated files. I tend to write hunts as broad as possible to account for as many variations of the activity, within reason, and then filter down from there.

Initial Access & Enumeration

SecureWorks
DeviceProcessEvents
| where InitiatingProcessFileName =~ "java.exe"
| where ProcessCommandLine has_any ("net", "net1", "netstat", "whoami", "systeminfo")
// | where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe")
// | where InitiatingProcessFolderPath has "ManageEngine"
CISA
DeviceProcessEvents
| where ProcessCommandLine contains "ip-api.com" or
ProcessCommandLine contains "ipinfo.io"
DeviceProcessEvents
| where ProcessCommandLine has_any ("localgroup", "group")
| where ProcessCommandLine has_any ("Administrators", "Domain Admins")
| where ProcessCommandLine contains " /d"
// | where FileName in~ ("net.exe", "net1.exe", "cmd.exe", "powershell.exe", "pwsh.exe")
DeviceProcessEvents
| where ProcessCommandLine has_all ("netsh", "show") or
(ProcessCommandLine has "dnscmd" and ProcessCommandLine contains " /enum")
DeviceProcessEvents
| where FileName =~ "wmic.exe"
| where ProcessCommandLine has_any ("volume", "service")
DeviceProcessEvents
| where ProcessCommandLine has_any ("arp", "curl", "dnscmd", "ipconfig", "ldifde", "net", "netsh", "netstat", "reg", "systeminfo", "tasklist", "whoami", "wmic")
| summarize Commands=make_set(ProcessCommandLine), Count=dcount(ProcessCommandLine) by InitiatingProcessFolderPath, InitiatingProcessId, DeviceName
| sort by Count desc nulls last

Credential Access

Microsoft
DeviceProcessEvents
| where ProcessCommandLine contains_cs " -exec bypass -W hidden -nop -E "
// | where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe")
// https://lolbas-project.github.io/lolbas/Libraries/comsvcs/
DeviceProcessEvents
| where ProcessCommandLine has_all ("MiniDump", "full")
// | where ProcessCommandLine has "comsvcs.dll"
// | where FileName =~ "rundll32.exe"
Microsoft
// https://lolbas-project.github.io/lolbas/Binaries/Wmic/
DeviceProcessEvents
| where ProcessCommandLine has "process call create"
| where ProcessCommandLine contains "/node:"
| where ProcessCommandLine has "ntdsutil"
// | where FileName in~ ("wmic.exe", "cmd.exe", "powershell.exe", "pwsh.exe")
// https://imphash.medium.com/detecting-lateral-movement-101-part-2-hunting-for-malcode-execution-via-wmi-using-windows-event-f9a5410649c
DeviceProcessEvents
| where InitiatingProcessFileName =~ "wmiprvse.exe"
| where ProcessCommandLine has "ntdsutil"
// | where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe")
SecureWorks
DeviceProcessEvents
| where InitiatingProcessFileName =~ "WmiPrvSE.exe"
| where ProcessCommandLine has "NTDS.dit"
CISA
// https://lolbas-project.github.io/lolbas/OtherMSBinaries/Ntdsutil/
DeviceProcessEvents
| where ProcessCommandLine has_all ("create", "full", "ntds")
| where ProcessCommandLine has_any ("ac i", "activate instance")
CISA
DeviceProcessEvents
| where ProcessCommandLine has_all ("create", "shadow")
// | where ProcessCommandLine has "vssadmin"

Lateral Movement & C2

// https://lolbas-project.github.io/lolbas/Binaries/Wmic/
DeviceProcessEvents
| where ProcessCommandLine has "process call create"
| where ProcessCommandLine contains "/node:"
| where ProcessCommandLine has "netsh"
// | where FileName in~ ("wmic.exe", "cmd.exe", "powershell.exe", "pwsh.exe")
// https://imphash.medium.com/detecting-lateral-movement-101-part-2-hunting-for-malcode-execution-via-wmi-using-windows-event-f9a5410649c
DeviceProcessEvents
| where (InitiatingProcessParentFileName =~ "wmiprvse.exe" or InitiatingProcessFileName =~ "wmiprvse.exe") or // this will be on target device
(ProcessCommandLine has "process call create" and ProcessCommandLine contains "/node:") // this will be on source device
| where ProcessCommandLine has_all ("interface", "portproxy", "listenport", "listenaddress")
CISA
DeviceProcessEvents
| where ProcessCommandLine has_all ("create", "shadow")
// | where ProcessCommandLine has "vssadmin"

Uncategorized

DeviceProcessEvents
| where ProcessCommandLine contains @"\\127.0.0.1\"
DeviceProcessEvents
| where ProcessCommandLine has_any ("rar", "xcopy") or
ProcessCommandLine contains ">"
| where ProcessCommandLine contains @"C:\Windows\Temp"
// Find cmd.exe that has been moved, look at cmdbak.exe above
let CMD_Hashes = DeviceProcessEvents
| where FolderPath =~ @"C:\Windows\System32\cmd.exe"
| where isnotempty(SHA256)
| distinct SHA256;
DeviceProcessEvents
| where SHA256 in~ (CMD_Hashes)
| where FolderPath !~ @"C:\Windows\System32\cmd.exe"

References

--

--