ID: 0xFF-0222-Suspicious_Named_Pipes-Win
OS: WindowsEndpoint, WindowsServer
| Tactic | Technique | Subtechnique | Technique Name |
|---|---|---|---|
| TA0002 - Execution | T1559 | Inter-Process Communication | |
| TA0005 - Defense Evasion | T1055 | Process Injection |
| Log Provider | Table Name | Event ID | Event Name | ATT&CK Data Source | ATT&CK Data Component |
|---|---|---|---|---|---|
| MicrosoftThreatProtection | DeviceEvents | NamedPipeEvent | Named Pipe | Named Pipe Metadata |
This rule looks for Named Pipe events that either contain one of the known IOCs or use patterns that can be linked to CobaltStrike usage.
User
CobaltStrike is used as a post-exploitation tool with various malware droppers responsible for the initial infection stage. Named pipes are used to send the output of the post-exploitation tools to the beacon. CobaltStrike is using default unique pipe names, which defenders can use for detection. However, CobaltStrike allows the operators to change the name of the pipes to any name of their choosing by configuring the malleable C2 profile accordingly.
None.
None expected.
Evaluate named pipe instances against historical usage baselines to identify rare or non-conforming names that may align with customizable C2 infrastructure or evasion techniques.
In case of a suspected breach or insider threat:
- Investigate the parent and child process relationship, including executable names, command-line arguments, and execution paths for characteristics indicative of post-exploitation frameworks or unauthorized privilege escalation.
- Review inbound and outbound connections from the host to identify suspicious or unauthorized external destinations and consider isolating the system to prevent further later movement activities.
Pipe names outside of the queried names.
- https://gist.github.com/MHaggis/6c600e524045a6d49c35291a21e10752
- https://labs.f-secure.com/blog/detecting-cobalt-strike-default-modules-via-named-pipe-analysis/
Language: Kusto
Platform: M365 Security
Query:
let timeframe = 2*1h;
let CobaltStrikeDefaults= dynamic([@"msagent_", @"MSSE-", @"postex_", @"status_", @"mypipe-f", @"mypipe-h",@"ntsvcs_",@"scerpc_", @"mojo.5688.8052."]);
let CobaltStrikeMallable= dynamic([@"win_svc", @"ntsvcs", @"scerpc", @"status_", @"SearchTextHarvester", @"DserNamePipe",@"wkssvc_",@"scerpc_", @"spoolss_",@"CatalogChangeListener",@"fullduplex_",@"demoagent_",@"PGMessagePipe",@"MsFteWds",@"postex_ssh_",@"windows.update.manager",@"\f4c3",@"\f53f",@"halfduplex_"]);
DeviceEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType == "NamedPipeEvent"
| extend AdditionalFields=parse_json(AdditionalFields)
| extend ThreadId=tostring(AdditionalFields.ThreadId)
| extend PipeName=tostring(AdditionalFields.PipeName)
// Creating string based variants of the processIDs for matching several times later.
| extend InitiatingPID=tostring(InitiatingProcessId)
| extend InitiatingParentPID=tostring(InitiatingProcessParentId)
// Begin environment-specific filter.
// End environment-specific filter.
| where PipeName has_any (CobaltStrikeDefaults) or
// Mojo is generated by Chrome(ium) browsers and teams and have distinct pattern including the (parent)ProcessId and ThreadId plus a random character string, CobaltStrike generates hex.
(PipeName matches regex @"\\mojo\.\d+\.\d+\." and not(PipeName matches regex @"\\mojo\.\d+\.\d+\.\d+$" or PipeName has InitiatingPID or PipeName has InitiatingParentPID or PipeName has ThreadId)) or
// Chromium browsers sync processes have distinct pattern including the (parent)ProcessId and ThreadId plus a random character string, CobaltStrike generates hex.
(PipeName matches regex @"\\(edge|chrome)\.sync\.\d+\.\d+\." and not(PipeName matches regex @"\\(edge|chrome|edge\.sync|chrome\.sync)\.\d+\.\d+\.\d+$" or PipeName has InitiatingPID or PipeName has InitiatingParentPID or PipeName has ThreadId)) or
// PSHost is generated by PowerShell and has a distinct pattern including the (parent)ProcessId.
(PipeName matches regex @"\\PSHost\.\d+\." and not(PipeName matches regex @"\\PSHost\.\d+\.\d+\." or PipeName has InitiatingPID or PipeName has InitiatingParentPID)) or
// Crashpad pipes have a distinct pattern including the ProcessId and a string of upper case characters.
(PipeName matches regex @"\\crashpad_" and not(PipeName matches regex @"\\crashpad_\d+_[A-Z]+" or PipeName has InitiatingPID or PipeName has InitiatingParentPID)) or
// Firefox pipes have a distinct pattern including the ProcessId and 1-3 digits which are sequential for each new pipe.
(PipeName matches regex @"\\cubeb-pipe-" and not(PipeName matches regex @"\\cubeb-pipe-\d+_[0-9]{1-3}+" or PipeName has InitiatingPID)) or
// Based on a list of public mallable profiles and a suffix that is a random HEX string.
(PipeName has_any (CobaltStrikeMallable) and PipeName matches regex @"[a-fA-F0-9]{2,10}$") or
(PipeName matches regex @"\\pipe\\[0-9a-f]{7,10}" or PipeName matches regex @"\\pipe\\[0-9a-f]{8}")| Version | Date | Impact | Notes |
|---|---|---|---|
| 1.3 | 2025-05-20 | minor | Enhanced response plan actions. |
| 1.2 | 2022-02-22 | minor | Use ingestion_time for event selection and include de-duplication logic. |
| 1.1 | 2022-01-14 | minor | Additional pipe and big performance tweaks |
| 1.0 | 2021-12-24 | major | Initial version |