NIK C2: AI-Enabled Command-and-Control Framework
Executive Summary
Attacker objective. NIK C2 is a remote access framework for Windows. Once the implant runs, the operator can dump browser credentials, cookies, Discord tokens, cryptocurrency wallets and saved Wi-Fi passwords, stream every keystroke, capture the screen, camera and microphone, tunnel into the internal network through an embedded SOCKS5/HTTP proxy, and deploy a screen-locking ransom screen that demands Bitcoin or USDT. [#1]
Why it is different. The implant embeds an OpenAI client behind an ai_generate command. The operator's prompt travels over the C2, the victim machine calls api.openai.com/v1/chat/completions and the answer goes back encrypted. If the operator supplies no API key, the implant uses the victim's OPENAI_API_KEY environment variable, so the victim pays for the operator's inference and the provider's logs show the victim's key. The default model string is gpt-4. Talos argues that collection and analysis now happen in one live session, which removes the offline delay defenders used to rely on. [#1]
What is not known. Talos names no actor and describes no delivery vector. It saw at least three versions, all built with Go 1.23.4, and describes a technically proficient team with prior malware experience. It assesses with moderate confidence that this is a functional framework and not a proof of concept, because it saw active infrastructure. The public indicator set is small: 8 sample hashes, 1 domain and 2 IP addresses. [#1] [#2]
What this pack does. Because the indicator list is short and perishable, most of the pack is behavioral: the screen-lock launch chain, the SystemLock Run value, the fodhelper registry key, the raw MBR read, the chcp 65001 recon prefix, netsh Wi-Fi key extraction, system-process names running from the wrong folder, and the boot-firmware survey. The indicators ship as detect. None ships as prevent, because every value comes from one vendor.
Source Review & Web Hunter Notes
One primary vendor source was fetched and saved verbatim as text, with its IOC repository files. A second independent vendor report was searched for and not found: the only other coverage located is an automated aggregator page that restates the Talos post. Every value in this pack therefore rests on one research team, which is why nothing ships as prevent. The Talos blog page itself returned a bot-challenge page to a direct fetch, so snapshot 01 is the full article text taken from the blog's own RSS feed (tags stripped, nothing summarised).
| # | Tier | Source | Key finding | Carry forward |
|---|---|---|---|---|
| 1 | T1 | Cisco Talos: NIK C2: The new AI-enabled command-and-control framework, 2026-10-29 (snapshot 01) | Primary vendor report. Implant architecture, C2 protocol and endpoints, AI handler, ransomware and bootkit modules, theft targets, evasion, build path, Go 1.23.4, infrastructure IP, domain, certificate CN, serial and JARM, ClamAV signature. Names no actor. | yes |
| 2 | T1 | Cisco-Talos/IOCs, 2026/10, nik-c2-new-ai-enabled-framework.txt (snapshot 02) | Plain-text IOC list: 8 SHA-256 hashes, 1 domain, 2 IPs, the six C2 paths and one URL on port 4443. | yes |
| 3 | T1 | Cisco-Talos/IOCs, 2026/10, nik-c2-new-ai-enabled-framework.json (STIX bundle, snapshot 03) | Same indicators as snapshot 02, typed as file SHA-256, domain, IPv4 and URL; hashes labelled NIKC2 implant. Same publisher as source 1, so it is not independent corroboration. | yes (cross-check) |
| 4 | T3 | OffSeq Threat Radar page for the Talos post (snapshot 04) | Automated aggregator summary of source 1; no new indicators. Not cited for any value. | no |
Decisions and discrepancies
- Single vendor. Sources 1 to 3 are one publisher. No indicator is corroborated by an independent team, so no row ships as prevent and nothing is marked critical. [#1] [#2] [#3]
- Second IP. The IP
2.26.51.12and the URL on port 4443 appear in the IOC repository and not in the article text. They are Talos-published and for the same report, so they ship as detect with that caveat. The URL is not shipped as a separate row because its host is already covered. [#2] [#3] - Link spelling. The article text prints the OpenAI URL with a stray space after the scheme. The endpoint is
https://api.openai.com/v1/chat/completions; the query matches only the host name because DNS carries no path. [#1] - Build identifier. The build path
/opt/nik_panel/data/build_52b79724a1fc4b8f/main.gois in the article. The article says an eight-byte hex token matching the build identifier is embedded in the implant; the value is not listed separately, so it is carried only as part of the path. [#1] - Published cryptographic material. The article prints the decoded AES seed and the derived 32-byte key. These are useful for memory or traffic decryption in an analysis lab and are not endpoint-log indicators, so they are not in the CSV.
- Not in any source. Delivery method, victims, actor, panel pricing or sale model. The pack does not assume any. Related-cluster indicators from other reports are deliberately excluded.
Hunt Brief & Attack Chain
Nine hypotheses, ordered by fidelity. Telemetry is named in plain terms first, then by platform where the name is certain.
- H1 (high): the host contacted the published C2 domain or addresses (Q1, Q2). T1071.001, T1041. FP: none expected. DNS lookup with the requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse); outbound network connection (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents).
- H2 (high): a published implant hash ran or was written (Q3). T1204.002. FP: none expected. Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); executable written (CrowdStrike: PeFileWritten, NewExecutableWritten. SentinelOne: File Creation. Defender: DeviceFileEvents).
- H3 (high): a system-process name ran from outside System32 (Q12). T1036.005. FP: near none. Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents).
- H4 (high): the screen-lock module launched mshta on
lock_screen.htmlor ranlock_start.bat, and aSystemLockautostart value was written (Q4, Q5). T1218.005, T1547.001, T1491.001. FP: near none. Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents). - H5 (high): PowerShell read the raw physical drive or named
mbr_backup.bin(Q7). T1006, T1542.003. FP: low. - H6 (medium): a UAC bypass key was written under ms-settings (Q6). T1548.002. FP: low. registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents).
- H7 (high/medium): the recon prefix
chcp 65001, Wi-Fi key extraction and the boot-firmware survey ran on one host (Q8, Q9, Q10). T1082, T1555, T1542.003. FP: low to medium. - H8 (medium): an AMSI bypass string appeared in a command line (Q11). T1562.001. FP: medium; script-block logs are the stronger source (native hunt N4).
- H9 (low, hunt): an unexpected host resolved the OpenAI API name, or staged
browserdata.zip(Q13, Q14). T1071.001, T1560. FP: high for Q13; baseline before alerting.
Attack chain
| Step | Behavior | Telemetry | Hunt angle |
|---|---|---|---|
| 1. Execution | Implant runs; argument watchdog or copywatchdog selects a helper mode, otherwise primary agent. Named mutex, log line [NIK] Starting. Delivery unknown. | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents) | Q3, Q12; N5 |
| 2. Evasion at start | Hides its console, renames to csrss.exe in temp, masquerades as svchost.exe or simvol.exe, sets ProcessBreakOnTermination (0x1D), checks for debuggers, disables Recent Documents telemetry. | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); API calls in memory are outside endpoint telemetry | Q12; gap for the API calls |
| 3. Persistence | Copies to %appdata%\Roaming\Microsoft\Network with changed ACLs, writes Run-key autostart, COM hijack option. | registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents); executable written (CrowdStrike: PeFileWritten, NewExecutableWritten. SentinelOne: File Creation. Defender: DeviceFileEvents) | Q5 (lock screen value); Q12; N2 |
| 4. Privilege and AMSI | On command: fodhelper COM hijack under ms-settings, removed in about 2 seconds; PowerShell patch of AmsiInitFailed. | registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents); Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); PowerShell script-block log (Windows event 4104) | Q6, Q11; N4 |
| 5. C2 | TLS WebSocket on 443 to /api/c2/ws, HTTP fallback every 250 ms to /api/c2/update, results to /api/c2/result; certificate pinned, CN nik-panel. | DNS lookup with the requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse); outbound network connection (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents); proxy, TLS and network sensor logs | Q1, Q2; N1, N2 |
| 6. Recon | chcp 65001 wrapped systeminfo, wmic lastbootuptime, SecurityCenter2 AV query, process list. | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents) | Q8 |
| 7. Theft | Browser databases and Local State (DPAPI key unwrapped with CryptUnprotectData), Firefox key4.db and logins.json, Discord tokens, wallet folders and extension data, seed and key file name search, Wi-Fi keys through netsh, keylogger polling 256 key codes, archived to browserdata.zip. | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); archive written (CrowdStrike: ZipFileWritten); file reads by the implant are outside endpoint telemetry unless file-open events are enabled | Q9, Q14; gap for reads and keylogging |
| 8. AI analysis | ai_generate posts the prompt to api.openai.com/v1/chat/completions from the victim host; falls back to OPENAI_API_KEY; default model gpt-4. | DNS lookup with the requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse) | Q13 (hunt); N3 |
| 9. Destructive modules | MBR backup via PowerShell to mbr_backup.bin; HTML lock screen written to lock_screen.html; lock_start.bat loops mshta every 5 seconds; bootkit.bin 16-byte placeholder after a bcdedit and Secure Boot survey. | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents) | Q4, Q5, Q7, Q10 |
Consolidated IOC Table
No row is prevent. Every value comes from the Cisco Talos article or its IOC repository, which is one research team. The legitimate Windows binaries the implant imitates or abuses (csrss.exe, svchost.exe, mshta.exe, bcdedit.exe, netsh.exe, powershell.exe, fodhelper.exe) are never indicators here; they are behavioral detections only. The two IPv4 rows are real addresses copied from the saved snapshot, not version numbers.
| Type | Value | Confidence | Action | Context |
|---|---|---|---|---|
| SHA-256 | ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | 6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5 | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | 30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | 1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402 | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | 99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00 | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | 5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1 | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| SHA-256 | 2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9 | medium | detect | NIKC2 implant sample in the Talos IOC repository. [#2] [#3] |
| Domain | total-sitevv[.]lol | medium | detect | C2 domain; the C2 server at 87.120.196[.]120 resolved it. [#1] [#2] |
| IPv4 | 87.120.196[.]120 | medium | detect | C2 server seen in the wild with certificate CN nik-panel. [#1] [#2] |
| IPv4 | 2.26.51[.]12 | medium | detect | Listed in the Talos IOC repository with a URL on port 4443; not named in the article text. [#2] [#3] |
| Cert CN | nik-panel | medium | hunt | TLS certificate common name on the C2; matches strings in the implant. Network-sensor or Censys style hunt, not an endpoint IOC. [#1] |
| Cert serial | 7d16381a9de823943b5a0987dbd0f26edf22052b | medium | hunt | Serial of the C2 certificate. [#1] |
| JARM | 28d28d28d00000000042d42d0000001f361a1bf80ed39a1e352adeb016a07b | low | hunt | JARM of the C2 TLS stack; JARM values are shared by many servers on the same software, so use it only to find candidates. [#1] |
| URI path | /api/c2/update, /api/c2/result, /api/c2/screen, /api/c2/file_chunk, /api/c2/rproxy_up, /api/c2/ws | medium | hunt | C2 endpoints. Generic enough to need the destination and cadence as context. [#1] [#2] |
| Build path | /opt/nik_panel/data/build_52b79724a1fc4b8f/main.go | medium | hunt | Go build path embedded in the implant; useful for YARA or string search on samples, not endpoint logs. [#1] |
| File name | lock_screen.html, lock_start.bat, mbr_backup.bin, bootkit.bin, browserdata.zip | medium | hunt | Dropped into the temp directory. Behavioral, see Q4, Q7, Q14. [#1] |
| Registry | SystemLock (Run value), HKCU\Software\Classes\ms-settings\Shell\Open\command | medium | hunt | Persistence and UAC bypass. Q5, Q6. [#1] |
| AV signature | Win.Trojan.GoDiscorder-10060526-0 | low | enrich | ClamAV detection name for the threat. [#1] |
Affected Surface & Telemetry Matrix
| Surface | Telemetry | Priority | Gap risk |
|---|---|---|---|
| Windows endpoints and servers where a user can run unsigned code | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); executable written (CrowdStrike: PeFileWritten, NewExecutableWritten. SentinelOne: File Creation. Defender: DeviceFileEvents); registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents) | Critical | Delivery is unknown, so there is no early-stage detection. A rebuilt sample with a new hash and new name will miss Q3. |
| Browser profiles, wallets, Discord, Wi-Fi profiles on the host | Process creation for netsh (as above); archive written (CrowdStrike: ZipFileWritten) | High | Reads of browser databases and wallet folders, DPAPI calls and the keylogger run inside the implant and are outside endpoint telemetry unless file-open events are enabled. |
| C2 traffic on 443 | DNS lookup with the requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse); outbound network connection (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents); proxy, TLS-inspection and network sensor logs (certificate CN, JARM, WebSocket upgrade to /api/c2/ws) | High | The channel is TLS with a pinned certificate. Without inspection only the domain, address, cadence and certificate are visible. Hosts with no sensor are covered only by DNS or proxy logs. |
| Boot chain: MBR, UEFI and Secure Boot state | Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents) (PowerShell, bcdedit); Windows Secure Boot and boot integrity state from inventory | Medium | The bootkit module in the report only stages a 16-byte placeholder. Real boot tampering is outside endpoint telemetry and needs firmware or boot-integrity checks. |
OpenAI and other AI-provider accounts whose key sits in OPENAI_API_KEY | Provider usage, billing and key logs; host environment audit (section 13, P6) | Medium | Outside endpoint telemetry. Charges and request logs will name the victim's key, not the operator. |
| Internal network behind a compromised host | Network connection and proxy logs for a host acting as a SOCKS5 or reverse-proxy relay | Medium | The embedded proxy and RDP operations show up only as new internal connections from the host; no specific query is written for them (gap). |
ATT&CK Mapping
| Tactic | Technique | Observed behavior | Query or control |
|---|---|---|---|
| Execution | T1059.001 PowerShell; T1059.003 Windows Command Shell | PowerShell for MBR read, Secure Boot check and AMSI patch; cmd for recon and the lock batch file | Q4, Q7, Q8, Q11; Hardening T3 |
| Defense Evasion | T1218.005 Mshta | mshta.exe opens lock_screen.html in a loop | Q4; Hardening T4 |
| Defense Evasion | T1036.005 Match Legitimate Name or Location | Renamed csrss.exe, masquerade as svchost.exe or simvol.exe | Q12; Hardening T5 |
| Defense Evasion | T1562.001 Impair Defenses: Disable or Modify Tools | AMSI patch on AmsiInitFailed; critical-process flag (no single ATT&CK ID; closest is T1562) | Q11; Hardening T3 |
| Defense Evasion | T1622 Debugger Evasion | IsDebuggerPresent and CheckRemoteDebuggerPresent, exit on detection | Gap: in-process API calls |
| Defense Evasion / Privilege Escalation | T1055.012 Process Hollowing | Listed in the evasion capability | Gap: no technique detail published |
| Privilege Escalation | T1548.002 Bypass User Account Control | fodhelper.exe with ms-settings Shell Open command key | Q6; Hardening T1 |
| Persistence | T1547.001 Registry Run Keys; T1546.015 COM Hijacking | SystemLock Run value; autostart and COM hijack options | Q5; Hardening T5 |
| Credential Access | T1555.003 Credentials from Web Browsers; T1539 Steal Web Session Cookie; T1528 Steal Application Access Token | Chrome, Edge, Brave, Opera, Firefox databases, Discord tokens, DPAPI unwrap | Q14; Hardening T6 |
| Credential Access | T1555 Credentials from Password Stores | Wi-Fi profiles with key=clear | Q9 |
| Credential Access / Collection | T1056.001 Keylogging; T1113 Screen Capture; T1125 Video Capture; T1123 Audio Capture; T1115 Clipboard Data | Keylogger, screen stream, camera, microphone, clipboard replacement | Gap: in-process |
| Collection | T1005 Data from Local System; T1560 Archive Collected Data | Seed and key file name regexes, wallet folders, browserdata.zip | Q14 |
| Discovery | T1082 System Information Discovery; T1518.001 Security Software Discovery; T1057 Process Discovery; T1016.002 Wi-Fi Discovery | systeminfo, wmic, SecurityCenter2, process list, netsh | Q8, Q9 |
| Command and Control | T1071.001 Web Protocols; T1573.001 Symmetric Cryptography; T1090 Proxy | TLS WebSocket, HTTP polling, AES-256-GCM with a hardcoded seed, embedded SOCKS5/HTTP proxy | Q1, Q2; N1, N2 |
| Exfiltration | T1041 Exfiltration Over C2 Channel | Results over WebSocket or POST to /api/c2/result, /api/c2/file_chunk | Q1, Q2 |
| Lateral Movement | T1021.001 Remote Desktop Protocol; T1563.002 RDP Hijacking | RDP session interaction and hijacking | Gap: no detail published |
| Impact | T1491.001 Internal Defacement; T1657 Financial Theft | Screen-lock HTML with Bitcoin and USDT wallet addresses; no file encryption | Q4, Q5 |
| Persistence / Impact | T1542.003 Bootkit; T1006 Direct Volume Access | MBR raw read, UEFI and Secure Boot survey, 16-byte bootkit.bin placeholder | Q7, Q10; Hardening T7 |
Native Audit-Log Hunts
| ID | Source | What to look for | Pass condition |
|---|---|---|---|
| N1 | Proxy, firewall or TLS-inspection logs | Connections to total-sitevv[.]lol, 87.120.196[.]120 or 2.26.51[.]12; a WebSocket upgrade or POST to a path ending /api/c2/ws, /api/c2/update, /api/c2/result, /api/c2/screen, /api/c2/file_chunk or /api/c2/rproxy_up; a client posting to /api/c2/update roughly every 250 ms. Last 90 days. | No match. Any hit: identify the source host and run the containment runbook. |
| N2 | Network sensor (Zeek, Suricata or similar) and external scan data | TLS certificates with subject CN nik-panel, serial 7d16381a9de823943b5a0987dbd0f26edf22052b, or JARM 28d28d28d00000000042d42d0000001f361a1bf80ed39a1e352adeb016a07b on any server your hosts contact. Treat JARM as a candidate list only. | No match. A JARM-only hit needs the certificate or domain to confirm. |
| N3 | OpenAI organisation usage and billing, API key audit log | Requests you cannot account for, a spike in tokens from a key stored on workstations, requests from IP addresses of endpoints that should not run AI tools, the model string gpt-4 from unexpected keys. | Usage matches approved applications. Any unexplained key use: rotate the key and check OPENAI_API_KEY on the hosts (P6). |
| N4 | Windows PowerShell Operational log, event 4104 (script block logging) | Script blocks containing AmsiInitFailed, System.Management.Automation reflection that sets a static field, Confirm-SecureBootUEFI, or a raw read of \\.\PhysicalDrive0. | No match outside an approved red-team window. Requires P3 to be deployed. |
| N5 | Windows Sysmon (event 1 process create, 11 file create, 13 registry value set) | Event 11 or 1 for csrss.exe, svchost.exe or simvol.exe outside System32; event 11 for lock_screen.html, lock_start.bat, mbr_backup.bin or bootkit.bin in the temp directory; event 13 for a SystemLock value or the ms-settings Shell Open command key. | No match. |
| N6 | Endpoint file system sweep (EDR file search or a script) | Files named lock_screen.html, lock_start.bat, mbr_backup.bin, bootkit.bin or browserdata.zip in a user's temp directory; files with filesystem timestamps of 1979-11-29; a copy under %appdata%\Roaming\Microsoft\Network that is not a Windows component. | No match. Preserve any file found before removal. |
| N7 | Crypto exchange, wallet and Discord account logs for affected users | Sign-ins or withdrawals from new locations after a possible infection date; new Discord sessions. | No unexplained activity between first possible infection and rotation. |
Hunt Queries: CrowdStrike CQL, SentinelOne PowerQuery and Defender XDR KQL
Use your tenant's own address. SentinelOne does not document a link that pre-fills a query, so each "Copy & open SentinelOne" button copies the query and opens this console: paste it into PowerQuery.
Pick your portal. Microsoft documents a Share link in advanced hunting but not its URL format, so each "Copy & open Defender" button copies the query and opens Advanced hunting: paste it into the editor.
Looks for: a DNS lookup of the one C2 domain Talos names, or any subdomain of it. The requesting process id is collected so the next step is a process pivot. Single-sourced to Talos, so this ships as detect.
Known limitations and deployment notes
- PowerQuery: The querying process id is not collected as it is on the CQL tab.
- PowerQuery assumes: event.dns.request is the populated DNS name field; some schema versions use dns.request instead.
- KQL – Defender XDR: Advanced Hunting retains 30 days, so lookups from days 31 to 90 are visible only on the CQL tab.
- KQL – Defender XDR: The querying process id is not collected.
- KQL – Defender XDR assumes: The queried name is stored under DnsQueryString or QueryName in AdditionalFields; the readiness test shows which key the tenant populates.
// HUNT: NIK C2 C2 domain resolution // MITRE: T1071.001, T1573.001 // CONF: high FP: low COST: low | REQUIRES: DnsRequest (DomainName, ContextProcessId) // FALSE POSITIVES: none expected. Malware sandboxes and research hosts that detonate samples will also resolve it. // LOOKBACK: 90d (set in the time picker) #event_simpleName=DnsRequest | DomainName=/(^|\.)total-sitevv\.lol$/i | groupBy([aid, ComputerName, DomainName], function=[count(as=Lookups), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen), collect(ContextProcessId, limit=10)], limit=1000) | sort(LastSeen, order=desc, limit=1000)
3 required fields · View requirements
Required telemetry
- DNS Resolved
Required fields
event.type: Event typeevent.dns.request: DNS nameevent.time: Event time
Recommended fields
endpoint.name: Host
Fallbacks
event.dns.request→dns.request: Same value under the older field name.
Readiness test
event.type = 'DNS Resolved' event.dns.request = * | limit 5 | columns event.time, event.type, event.dns.request
// HUNT: NIK C2 C2 domain resolution
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1071.001, T1573.001
// CONF: high | FP: low
// FALSE POSITIVES: none expected. Malware sandboxes and research hosts that detonate samples will also resolve it.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same DNS-resolution predicate: the exact apex or any subdomain of the C2 domain, grouped per host with a count and first and last seen. The DNS request field name is the pySigma-attested one.
// REQUIRES: SentinelOne Deep Visibility DNS Resolved events
// TUNING: None expected. Sandboxes and research hosts that detonate samples will also resolve the domain.
// LOOKBACK: 90d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: The querying process id is not collected as it is on the CQL tab.
// VALIDATION LEVEL: static-reviewed
event.type = 'DNS Resolved' (event.dns.request in:anycase ('total-sitevv.lol') or event.dns.request matches '^.*\\.total-sitevv\\.lol$')
| group lookups=count(), first_seen=min(event.time), last_seen=max(event.time) by agent.uuid, endpoint.name, event.dns.request
| sort -last_seen
| limit 1000Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: ActionAdditionalFields: DNS name carrier
Recommended fields
DeviceName: Host
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "DnsQueryResponse" | project Timestamp, ActionType, AdditionalFields | take 5
// HUNT: NIK C2 C2 domain resolution // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1071.001, T1573.001 // CONF: high | FP: low // FALSE POSITIVES: none expected. Malware sandboxes and research hosts that detonate samples will also resolve it. // EQUIVALENCE: equivalent-with-schema-assumptions - Same DNS-resolution predicate on the DnsQueryResponse action of DeviceEvents, with the name read from AdditionalFields. Advanced Hunting keeps 30 days, the CQL covers 90. // REQUIRES: Defender for Endpoint network telemetry with DNS response events (DeviceEvents) // TUNING: None expected. Sandboxes and research hosts that detonate samples will also resolve the domain. // LOOKBACK: 30d (Advanced Hunting retention; the CQL tab covers 90d) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Advanced Hunting retains 30 days, so lookups from days 31 to 90 are visible only on the CQL tab. The querying process id is not collected. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceEvents | where Timestamp >= ago(30d) | where ActionType == "DnsQueryResponse" | extend DnsName = tostring(coalesce(parse_json(AdditionalFields)["DnsQueryString"], parse_json(AdditionalFields)["QueryName"])) | where DnsName =~ "total-sitevv.lol" or DnsName endswith ".total-sitevv.lol" | summarize Lookups = count(), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by DeviceId, DeviceName, DnsName | sort by LastSeen desc | take 1000
Looks for: an outbound connection to either C2 address in the Talos IOC list. 87.120.196.120 is named in the article and the IOC repository; 2.26.51.12 (with a URL on port 4443) appears only in the IOC repository. Both are single-vendor, so detect.
Known limitations and deployment notes
- PowerQuery: The connecting process id is not collected as it is on the CQL tab.
- PowerQuery assumes: dst.ip.address and dst.port.number are populated on IP Connect events.
- KQL – Defender XDR: Advanced Hunting retains 30 days, so connections from days 31 to 90 are visible only on the CQL tab.
- KQL – Defender XDR: The connecting process id is not collected.
- KQL – Defender XDR assumes: RemoteIP holds the destination address for outbound connections.
// HUNT: NIK C2 C2 IP connection // MITRE: T1071.001, T1041 // CONF: high FP: low COST: low | REQUIRES: NetworkConnectIP4 (RemoteAddressIP4, RemotePort) // FALSE POSITIVES: none expected. Address reuse after the operator abandons it is possible; check the first-seen date against the report (2026-10-29). // LOOKBACK: 90d (set in the time picker) #event_simpleName=NetworkConnectIP4 | RemoteAddressIP4=/^(87\.120\.196\.120|2\.26\.51\.12)$/ | groupBy([aid, ComputerName, RemoteAddressIP4, RemotePort], function=[count(as=Connections), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen), collect(ContextProcessId, limit=10)], limit=1000) | sort(LastSeen, order=desc, limit=1000)
4 required fields · View requirements
Required telemetry
- IP Connect
Required fields
event.type: Event typedst.ip.address: Remote addressdst.port.number: Remote portevent.time: Event time
Recommended fields
endpoint.name: Host
Readiness test
event.type = 'IP Connect' dst.ip.address = * | limit 5 | columns event.time, event.type, dst.ip.address, dst.port.number
// HUNT: NIK C2 C2 IP connection
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1071.001, T1041
// CONF: high | FP: low
// FALSE POSITIVES: none expected. Address reuse after the operator abandons it is possible; check the first-seen date against the report (2026-10-29).
// EQUIVALENCE: equivalent-with-schema-assumptions - Same outbound-connection predicate on the two C2 addresses, grouped per host and port with a count and first and last seen.
// REQUIRES: SentinelOne Deep Visibility IP Connect events
// TUNING: None expected. Address reuse after the operator abandons it is possible; check the first-seen date against the report.
// LOOKBACK: 90d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: The connecting process id is not collected as it is on the CQL tab.
// VALIDATION LEVEL: static-reviewed
event.type = 'IP Connect' dst.ip.address in ('87.120.196.120', '2.26.51.12')
| group connections=count(), first_seen=min(event.time), last_seen=max(event.time) by agent.uuid, endpoint.name, dst.ip.address, dst.port.number
| sort -last_seen
| limit 1000Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceNetworkEvents
Required fields
Timestamp: Event timeRemoteIP: Remote addressRemotePort: Remote port
Recommended fields
DeviceName: Host
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceNetworkEvents | where Timestamp > ago(1d) | project Timestamp, RemoteIP, RemotePort | take 5
// HUNT: NIK C2 C2 IP connection
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1071.001, T1041
// CONF: high | FP: low
// FALSE POSITIVES: none expected. Address reuse after the operator abandons it is possible; check the first-seen date against the report (2026-10-29).
// EQUIVALENCE: equivalent-with-schema-assumptions - Same outbound-connection predicate on DeviceNetworkEvents, grouped per host and port. Advanced Hunting keeps 30 days, the CQL covers 90.
// REQUIRES: Defender for Endpoint network telemetry (DeviceNetworkEvents)
// TUNING: None expected. Address reuse after the operator abandons it is possible; check the first-seen date against the report.
// LOOKBACK: 30d (Advanced Hunting retention; the CQL tab covers 90d)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Advanced Hunting retains 30 days, so connections from days 31 to 90 are visible only on the CQL tab. The connecting process id is not collected.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0
DeviceNetworkEvents
| where Timestamp >= ago(30d)
| where RemoteIP in ("87.120.196.120", "2.26.51.12")
| summarize Connections = count(), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by DeviceId, DeviceName, RemoteIP, RemotePort
| sort by LastSeen desc
| take 1000Looks for: a process start or an executable write whose SHA-256 matches one of the 8 implant hashes in the Talos IOC repository. Later builds will not match; the behavioral queries below are the durable layer.
Known limitations and deployment notes
- PowerQuery: Rows are not grouped per host and hash as on the CQL tab.
- PowerQuery: Hash population varies by event type and tenant.
- PowerQuery assumes: tgt.process.image.sha256 and tgt.file.sha256 are populated on the tenant; an unpopulated hash field returns nothing.
- KQL – Defender XDR: Process launches are not covered: DeviceProcessEvents is a second table and its SHA256 is usually unpopulated.
- KQL – Defender XDR: Advanced Hunting retains 30 days, so hits from days 31 to 90 are visible only on the CQL tab.
- KQL – Defender XDR assumes: SHA256 is populated on DeviceFileEvents rows; Microsoft notes it is often empty and SHA1 is the safer pivot, but the CQL supplies only SHA-256 values.
// HUNT: NIK C2 implant SHA-256 match // MITRE: T1204.002, T1036.005 // CONF: high FP: low COST: low | REQUIRES: ProcessRollup2, PeFileWritten, NewExecutableWritten (SHA256HashData) // FALSE POSITIVES: none expected. Analysis hosts that store samples will match on write events. // LOOKBACK: 90d (set in the time picker) #event_simpleName=/^(ProcessRollup2|PeFileWritten|NewExecutableWritten)$/ | SHA256HashData=/^(ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c|6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5|30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba|1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a|bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402|99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00|5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1|2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9)$/i | groupBy([aid, ComputerName, SHA256HashData, FileName], function=[count(as=Events), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)], limit=1000) | sort(LastSeen, order=desc, limit=1000)
3 required fields · View requirements
Required telemetry
- Process Creation
- File Creation
Required fields
tgt.process.image.sha256: Process image hashtgt.file.sha256: File hashevent.time: Event time
Recommended fields
endpoint.name: Host
Readiness test
tgt.process.image.sha256 = * or tgt.file.sha256 = * | limit 5 | columns event.time, tgt.process.image.sha256, tgt.file.sha256
// HUNT: NIK C2 implant SHA-256 match
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1204.002, T1036.005
// CONF: high | FP: low
// FALSE POSITIVES: none expected. Analysis hosts that store samples will match on write events.
// EQUIVALENCE: approximate-analytic - Matches the eight SHA-256 values on the launched process image and on the written file, which covers the CQL's process-start and file-write events. Rows are listed, not grouped, and only Process Creation populates the process hash.
// REQUIRES: SentinelOne Deep Visibility Process Creation and File Creation events with SHA-256 populated
// TUNING: None expected. Analysis hosts that store samples will match on file events.
// LOOKBACK: 90d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Rows are not grouped per host and hash as on the CQL tab. Hash population varies by event type and tenant.
// VALIDATION LEVEL: static-reviewed
tgt.process.image.sha256 in:anycase ('ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c', '6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5', '30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba', '1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a', 'bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402', '99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00', '5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1', '2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9') or tgt.file.sha256 in:anycase ('ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c', '6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5', '30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba', '1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a', 'bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402', '99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00', '5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1', '2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9')
| columns event.time, event.type, endpoint.name, src.process.user, tgt.process.name, tgt.process.image.sha256, tgt.file.path, tgt.file.sha256
| sort -event.time
| limit 1000Automated validation: static-passed
2 required fields · View requirements
Required telemetry
- DeviceFileEvents
Required fields
Timestamp: Event timeSHA256: File hash
Recommended fields
FileName: File name
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceFileEvents | where Timestamp > ago(1d) | where isnotempty(SHA256) | project Timestamp, FileName, SHA256 | take 5
// HUNT: NIK C2 implant SHA-256 match
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1204.002, T1036.005
// CONF: high | FP: low
// FALSE POSITIVES: none expected. Analysis hosts that store samples will match on write events.
// EQUIVALENCE: telemetry-gap - Partial pivot on written files only: DeviceFileEvents carries the SHA-256, but the process-start half of the CQL needs DeviceProcessEvents, where SHA256 is usually unpopulated, and a query reads one table.
// REQUIRES: Defender for Endpoint file telemetry (DeviceFileEvents) with SHA256 populated
// TUNING: None expected. Analysis hosts that store samples will match on write events.
// LOOKBACK: 30d (Advanced Hunting retention; the CQL tab covers 90d)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Process launches are not covered: DeviceProcessEvents is a second table and its SHA256 is usually unpopulated. Advanced Hunting retains 30 days, so hits from days 31 to 90 are visible only on the CQL tab.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceFileEvents
| where Timestamp >= ago(30d)
| where SHA256 in~ ("ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c", "6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5", "30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba", "1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a", "bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402", "99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00", "5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1", "2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9")
| project Timestamp, ReportId, DeviceId, DeviceName, ActionType, FileName, FolderPath, SHA256, InitiatingProcessFileName, InitiatingProcessAccountName
| sort by Timestamp desc
| take 1000Looks for: the screen-lock module launching: mshta.exe opening lock_screen.html, or cmd running lock_start.bat. Talos says the batch file loops with a five-second timeout so the lock screen reopens if the user closes it. mshta.exe and cmd.exe are legitimate Windows binaries: this is a behavioral detection on the file names in the command line, never a block on the binaries.
Known limitations and deployment notes
- PowerQuery: A process the agent did not observe starting is not captured.
- PowerQuery assumes: Both file names are matched as case-insensitive substrings of the command line.
- KQL – Defender XDR: A process the sensor did not observe starting is not captured.
- KQL – Defender XDR assumes: Both file names are matched as plain substrings of the command line.
// HUNT: NIK C2 screen-lock launch via mshta and lock_start.bat // MITRE: T1218.005, T1059.003, T1491.001 // CONF: high FP: low COST: low | REQUIRES: ProcessRollup2 (FileName, CommandLine, ParentBaseFileName) // FALSE POSITIVES: near none. A kiosk or lock-screen product that uses the same two file names would match; confirm the parent process. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^(mshta|cmd)\.exe$/i | CommandLine=/(lock_screen\.html|lock_start\.bat)/i | table([@timestamp, aid, ComputerName, UserName, FileName, CommandLine, ParentBaseFileName, ImageFileName], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.name: Created process nametgt.process.cmdline: Created command lineevent.time: Event time
Recommended fields
src.process.name: Creating process
Readiness test
event.type = 'Process Creation' tgt.process.name = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.cmdline
// HUNT: NIK C2 screen-lock launch via mshta and lock_start.bat
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1218.005, T1059.003, T1491.001
// CONF: high | FP: low
// FALSE POSITIVES: near none. A kiosk or lock-screen product that uses the same two file names would match; confirm the parent process.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: mshta or cmd whose command line names lock_screen.html or lock_start.bat. The created process is tgt.process.* and its creator src.process.*.
// REQUIRES: SentinelOne Deep Visibility Process Creation events
// TUNING: A kiosk or lock-screen product using the same file names would match; confirm the creating process in src.process.name.
// LOOKBACK: 30d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A process the agent did not observe starting is not captured.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.name in:anycase ('mshta.exe', 'cmd.exe') (tgt.process.cmdline contains 'lock_screen.html' or tgt.process.cmdline contains 'lock_start.bat')
| columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.cmdline, src.process.name, tgt.process.image.path
| sort -event.time
| limit 200Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, ProcessCommandLine | take 5
// HUNT: NIK C2 screen-lock launch via mshta and lock_start.bat
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1218.005, T1059.003, T1491.001
// CONF: high | FP: low
// FALSE POSITIVES: near none. A kiosk or lock-screen product that uses the same two file names would match; confirm the parent process.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate on DeviceProcessEvents. The parent is InitiatingProcessFileName; contains is case-insensitive, matching the CQL intent.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: A kiosk or lock-screen product using the same file names would match; confirm the creating process.
// LOOKBACK: 30d
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A process the sensor did not observe starting is not captured.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceProcessEvents
| where Timestamp >= ago(30d)
| where FileName in~ ("mshta.exe", "cmd.exe")
| where ProcessCommandLine contains "lock_screen.html" or ProcessCommandLine contains "lock_start.bat"
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc
| take 200Looks for: a registry value named SystemLock written to an autostart location. Talos says the module runs reg add to create a SystemLock Run value under the current user that calls cmd /c on the batch file. The registry value data is returned so you can confirm it points at lock_start.bat.
Known limitations and deployment notes
- PowerQuery: The lock_start.bat check on the value data is a manual triage step, not part of the filter.
- PowerQuery assumes: Registry Value Modified covers both the autostart-key and generic value updates of the CQL.
- KQL – Defender XDR: The lock_start.bat check on the value data is a manual triage step, not part of the filter.
- KQL – Defender XDR assumes: RegistryValueSet is the action recorded for a value write.
// HUNT: NIK C2 SystemLock autostart value // MITRE: T1547.001 // CONF: high FP: low COST: low | REQUIRES: AsepValueUpdate, RegGenericValueUpdate (RegValueName, RegObjectName, RegStringValue) // FALSE POSITIVES: low. A product that names its own Run value SystemLock would match; check RegStringValue for lock_start.bat. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(AsepValueUpdate|RegGenericValueUpdate)$/ | RegValueName=/^SystemLock$/i | table([@timestamp, aid, ComputerName, UserName, RegObjectName, RegValueName, RegStringValue, ContextBaseFileName], limit=200)
3 required fields · View requirements
Required telemetry
- Registry Value Modified
Required fields
event.type: Event typeregistry.valueName: Value nameevent.time: Event time
Recommended fields
registry.keyPath: Key pathregistry.value: Value data
Readiness test
event.type = 'Registry Value Modified' registry.valueName = * | limit 5 | columns event.time, event.type, registry.valueName
// HUNT: NIK C2 SystemLock autostart value
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1547.001
// CONF: high | FP: low
// FALSE POSITIVES: low. A product that names its own Run value SystemLock would match; check RegStringValue for lock_start.bat.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same registry-value predicate: a value named SystemLock was set. On a registry event the writer is src.process.*.
// REQUIRES: SentinelOne Deep Visibility Registry Value Modified events
// TUNING: A product that names its own Run value SystemLock would match; check registry.value for lock_start.bat.
// LOOKBACK: 30d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: The lock_start.bat check on the value data is a manual triage step, not part of the filter.
// VALIDATION LEVEL: static-reviewed
event.type = 'Registry Value Modified' registry.valueName in:anycase ('SystemLock')
| columns event.time, endpoint.name, src.process.user, registry.keyPath, registry.valueName, registry.value, src.process.name
| sort -event.time
| limit 200Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceRegistryEvents
Required fields
Timestamp: Event timeActionType: ActionRegistryValueName: Value name
Recommended fields
RegistryKey: KeyRegistryValueData: Value data
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceRegistryEvents | where Timestamp > ago(1d) | where ActionType == "RegistryValueSet" | project Timestamp, ActionType, RegistryValueName | take 5
// HUNT: NIK C2 SystemLock autostart value // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1547.001 // CONF: high | FP: low // FALSE POSITIVES: low. A product that names its own Run value SystemLock would match; check RegStringValue for lock_start.bat. // EQUIVALENCE: equivalent-with-schema-assumptions - Same registry-value predicate on DeviceRegistryEvents RegistryValueSet. // REQUIRES: Defender for Endpoint registry telemetry (DeviceRegistryEvents) // TUNING: A product that names its own Run value SystemLock would match; check RegistryValueData for lock_start.bat. // LOOKBACK: 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: The lock_start.bat check on the value data is a manual triage step, not part of the filter. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceRegistryEvents | where Timestamp >= ago(30d) | where ActionType == "RegistryValueSet" | where RegistryValueName =~ "SystemLock" | project Timestamp, ReportId, DeviceId, DeviceName, InitiatingProcessAccountName, RegistryKey, RegistryValueName, RegistryValueData, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: a write under HKCU\Software\Classes\ms-settings\Shell\Open\command. Talos says the implant writes its own path there, triggers fodhelper.exe and removes the key within about two seconds. The write is logged even though the key is short-lived. The technique is shared by other tooling, so a hit proves a UAC bypass, not NIK C2 by itself.
Known limitations and deployment notes
- PowerQuery: A key created without a value write is not captured.
- PowerQuery assumes: registry.keyPath holds the full key path with backslash separators.
- KQL – Defender XDR: A key created without a value write is not captured.
- KQL – Defender XDR assumes: RegistryKey holds the full key path with backslash separators.
// HUNT: ms-settings Shell Open command write (fodhelper UAC bypass, NIK C2) // MITRE: T1548.002, T1546.015 // CONF: medium FP: low COST: low | REQUIRES: RegGenericValueUpdate, AsepValueUpdate (RegObjectName, RegStringValue) // FALSE POSITIVES: near none; a legitimate app rarely registers a handler under ms-settings Shell Open command. Red-team exercises use the same key. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(AsepValueUpdate|RegGenericValueUpdate)$/ | RegObjectName=/\\Software\\Classes\\ms-settings\\Shell\\Open\\command/i | table([@timestamp, aid, ComputerName, UserName, RegObjectName, RegValueName, RegStringValue, ContextBaseFileName], limit=200)
3 required fields · View requirements
Required telemetry
- Registry Value Modified
Required fields
event.type: Event typeregistry.keyPath: Key pathevent.time: Event time
Recommended fields
registry.value: Value data
Readiness test
event.type = 'Registry Value Modified' registry.keyPath = * | limit 5 | columns event.time, event.type, registry.keyPath
// HUNT: ms-settings Shell Open command write (fodhelper UAC bypass, NIK C2) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1548.002, T1546.015 // CONF: medium | FP: low // FALSE POSITIVES: near none; a legitimate app rarely registers a handler under ms-settings Shell Open command. Red-team exercises use the same key. // EQUIVALENCE: equivalent-with-schema-assumptions - Same registry predicate: a value written under the ms-settings Shell Open command key. The key path is matched as a case-insensitive substring. // REQUIRES: SentinelOne Deep Visibility Registry Value Modified events // TUNING: Near none; red-team exercises use the same key. Confirm the writing process in src.process.name. // LOOKBACK: 30d (set in the time picker) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A key created without a value write is not captured. // VALIDATION LEVEL: static-reviewed event.type = 'Registry Value Modified' registry.keyPath contains 'Software\\Classes\\ms-settings\\Shell\\Open\\command' | columns event.time, endpoint.name, src.process.user, registry.keyPath, registry.valueName, registry.value, src.process.name | sort -event.time | limit 200
Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceRegistryEvents
Required fields
Timestamp: Event timeActionType: ActionRegistryKey: Key path
Recommended fields
RegistryValueData: Value data
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceRegistryEvents | where Timestamp > ago(1d) | where ActionType == "RegistryValueSet" | project Timestamp, ActionType, RegistryKey | take 5
// HUNT: ms-settings Shell Open command write (fodhelper UAC bypass, NIK C2) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1548.002, T1546.015 // CONF: medium | FP: low // FALSE POSITIVES: near none; a legitimate app rarely registers a handler under ms-settings Shell Open command. Red-team exercises use the same key. // EQUIVALENCE: equivalent-with-schema-assumptions - Same registry predicate on DeviceRegistryEvents: a value set under the ms-settings Shell Open command key. // REQUIRES: Defender for Endpoint registry telemetry (DeviceRegistryEvents) // TUNING: Near none; red-team exercises use the same key. Confirm the writing process. // LOOKBACK: 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A key created without a value write is not captured. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceRegistryEvents | where Timestamp >= ago(30d) | where ActionType == "RegistryValueSet" | where RegistryKey contains "\\Software\\Classes\\ms-settings\\Shell\\Open\\command" | project Timestamp, ReportId, DeviceId, DeviceName, InitiatingProcessAccountName, RegistryKey, RegistryValueName, RegistryValueData, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: PowerShell reading \\.\PhysicalDrive0 or naming mbr_backup.bin. Talos says the boot-ransomware module runs PowerShell to copy the first sector to mbr_backup.bin in the temp directory before the lock screen is deployed. powershell.exe is a legitimate binary: this is a command-line behavior, not a block.
Known limitations and deployment notes
- PowerQuery: A script file that opens the drive without naming it on the command line is not captured.
- PowerQuery assumes: Both strings are matched as case-insensitive substrings of the command line.
- KQL – Defender XDR: A script file that opens the drive without naming it on the command line is not captured.
- KQL – Defender XDR assumes: Both strings are matched as plain substrings of the command line.
// HUNT: PowerShell raw read of PhysicalDrive0 or mbr_backup.bin (NIK C2 boot ransomware) // MITRE: T1006, T1059.001, T1542.003 // CONF: high FP: low COST: low | REQUIRES: ProcessRollup2 (FileName, CommandLine, ParentBaseFileName) // FALSE POSITIVES: low. Disk imaging, forensic and backup scripts that open the physical drive from PowerShell. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^(powershell|pwsh)\.exe$/i | CommandLine=/(PhysicalDrive0|mbr_backup\.bin)/i | table([@timestamp, aid, ComputerName, UserName, FileName, CommandLine, ParentBaseFileName, ImageFileName], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.name: Created process nametgt.process.cmdline: Created command lineevent.time: Event time
Recommended fields
src.process.name: Creating process
Readiness test
event.type = 'Process Creation' tgt.process.name = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.cmdline
// HUNT: PowerShell raw read of PhysicalDrive0 or mbr_backup.bin (NIK C2 boot ransomware)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1006, T1059.001, T1542.003
// CONF: high | FP: low
// FALSE POSITIVES: low. Disk imaging, forensic and backup scripts that open the physical drive from PowerShell.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: PowerShell whose command line names PhysicalDrive0 or mbr_backup.bin. The created process is tgt.process.*.
// REQUIRES: SentinelOne Deep Visibility Process Creation events
// TUNING: Disk imaging, forensic and backup scripts that open the physical drive from PowerShell will match; confirm the creating process.
// LOOKBACK: 30d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A script file that opens the drive without naming it on the command line is not captured.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.name in:anycase ('powershell.exe', 'pwsh.exe') (tgt.process.cmdline contains 'PhysicalDrive0' or tgt.process.cmdline contains 'mbr_backup.bin')
| columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.cmdline, src.process.name, tgt.process.image.path
| sort -event.time
| limit 200Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, ProcessCommandLine | take 5
// HUNT: PowerShell raw read of PhysicalDrive0 or mbr_backup.bin (NIK C2 boot ransomware)
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1006, T1059.001, T1542.003
// CONF: high | FP: low
// FALSE POSITIVES: low. Disk imaging, forensic and backup scripts that open the physical drive from PowerShell.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate on DeviceProcessEvents. contains is case-insensitive, matching the CQL intent.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: Disk imaging, forensic and backup scripts that open the physical drive from PowerShell will match; confirm the creating process.
// LOOKBACK: 30d
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A script file that opens the drive without naming it on the command line is not captured.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceProcessEvents
| where Timestamp >= ago(30d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine contains "PhysicalDrive0" or ProcessCommandLine contains "mbr_backup.bin"
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc
| take 200Looks for: the exact recon pattern Talos lists: chcp 65001 >nul 2>&1 & systeminfo, the same prefix on wmic os get lastbootuptime, on the SecurityCenter2 AntiVirusProduct query, and on a Get-Process | ConvertTo-Json call. The UTF-8 prefix on a recon command is uncommon in administrator scripts.
Known limitations and deployment notes
- PowerQuery: Recon commands issued in a later separate process are not linked to the chcp call.
- PowerQuery assumes: The regex is unanchored and the engine's matches is assumed to search within the command line.
- KQL – Defender XDR: Recon commands issued in a later separate process are not linked to the chcp call.
- KQL – Defender XDR assumes: The regex dot does not cross a line break in a multi-line command line.
// HUNT: chcp 65001 prefixed recon commands (NIK C2 host survey) // MITRE: T1082, T1518.001, T1057 // CONF: high FP: low COST: low | REQUIRES: ProcessRollup2 (CommandLine, ParentBaseFileName) // FALSE POSITIVES: low. Some inventory scripts set the code page before systeminfo; check the parent process and whether the other recon commands follow. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/chcp\s+65001.*(systeminfo|lastbootuptime|SecurityCenter2|ConvertTo-Json)/i | table([@timestamp, aid, ComputerName, UserName, FileName, CommandLine, ParentBaseFileName, ImageFileName], limit=200)
3 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.cmdline: Created command lineevent.time: Event time
Recommended fields
src.process.name: Creating process
Readiness test
event.type = 'Process Creation' tgt.process.cmdline = * | limit 5 | columns event.time, event.type, tgt.process.cmdline
// HUNT: chcp 65001 prefixed recon commands (NIK C2 host survey) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1082, T1518.001, T1057 // CONF: high | FP: low // FALSE POSITIVES: low. Some inventory scripts set the code page before systeminfo; check the parent process and whether the other recon commands follow. // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: a command line with chcp 65001 followed later by a host-survey token. matches is case-insensitive by default, reproducing the CQL /i intent. // REQUIRES: SentinelOne Deep Visibility Process Creation events // TUNING: Some inventory scripts set the code page before systeminfo; check the creating process and whether the other recon commands follow. // LOOKBACK: 30d (set in the time picker) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Recon commands issued in a later separate process are not linked to the chcp call. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' tgt.process.cmdline matches 'chcp\\s+65001.*(systeminfo|lastbootuptime|SecurityCenter2|ConvertTo-Json)' | columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.cmdline, src.process.name, tgt.process.image.path | sort -event.time | limit 200
Automated validation: static-passed
2 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, ProcessCommandLine | take 5
// HUNT: chcp 65001 prefixed recon commands (NIK C2 host survey) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1082, T1518.001, T1057 // CONF: high | FP: low // FALSE POSITIVES: low. Some inventory scripts set the code page before systeminfo; check the parent process and whether the other recon commands follow. // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation regex on ProcessCommandLine with the (?i) prefix to keep the CQL case-insensitive intent. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents) // TUNING: Some inventory scripts set the code page before systeminfo; check the creating process and whether the other recon commands follow. // LOOKBACK: 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Recon commands issued in a later separate process are not linked to the chcp call. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(30d) | where ProcessCommandLine matches regex @"(?i)chcp\s+65001.*(systeminfo|lastbootuptime|SecurityCenter2|ConvertTo-Json)" | project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: netsh wlan show profile with key=clear, the command Talos lists for the wifi_steal handler. The implant calls netsh directly with discrete arguments, so the parent is the implant and not a shell. netsh.exe is a legitimate binary: detection only. FP: Help-desk and wireless-troubleshooting scripts run the same command. A parent of cmd.exe or powershell.exe under a named technician session is the usual benign case.
Known limitations and deployment notes
- PowerQuery: Help-desk and wireless-troubleshooting scripts will match until tuned.
- PowerQuery assumes: The regex is unanchored and the engine's matches is assumed to search within the command line.
- KQL – Defender XDR: Help-desk and wireless-troubleshooting scripts will match until tuned.
- KQL – Defender XDR assumes: The regex dot does not cross a line break in a multi-line command line.
// HUNT: netsh wlan show profile key=clear (NIK C2 Wi-Fi theft) // MITRE: T1555, T1016.002 // CONF: medium FP: medium COST: low | REQUIRES: ProcessRollup2 (FileName, CommandLine, ParentBaseFileName) // FALSE POSITIVES: help-desk and wireless-troubleshooting scripts; IT onboarding tools that export Wi-Fi profiles. // TUNING: exclude approved IT tooling by ParentBaseFileName (for example your remote-support agent) and review hits where the parent is a binary running from a user temp or profile path. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^netsh\.exe$/i | CommandLine=/wlan\s+show\s+profile.*key\s*=\s*clear/i | table([@timestamp, aid, ComputerName, UserName, CommandLine, ParentBaseFileName, ImageFileName], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.name: Created process nametgt.process.cmdline: Created command lineevent.time: Event time
Recommended fields
src.process.name: Creating process
Readiness test
event.type = 'Process Creation' tgt.process.name = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.cmdline
// HUNT: netsh wlan show profile key=clear (NIK C2 Wi-Fi theft)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1555, T1016.002
// CONF: medium | FP: medium
// FALSE POSITIVES: help-desk and wireless-troubleshooting scripts; IT onboarding tools that export Wi-Fi profiles.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: netsh showing a wlan profile with key=clear.
// REQUIRES: SentinelOne Deep Visibility Process Creation events
// TUNING: Exclude approved IT tooling by src.process.name and review hits where the creating process runs from a user temp or profile path.
// LOOKBACK: 30d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Help-desk and wireless-troubleshooting scripts will match until tuned.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.name in:anycase ('netsh.exe') tgt.process.cmdline matches 'wlan\\s+show\\s+profile.*key\\s*=\\s*clear'
| columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.cmdline, src.process.name, tgt.process.image.path
| sort -event.time
| limit 200Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, ProcessCommandLine | take 5
// HUNT: netsh wlan show profile key=clear (NIK C2 Wi-Fi theft) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1555, T1016.002 // CONF: medium | FP: medium // FALSE POSITIVES: help-desk and wireless-troubleshooting scripts; IT onboarding tools that export Wi-Fi profiles. // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate on DeviceProcessEvents, with the (?i) prefix keeping the CQL case-insensitive intent. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents) // TUNING: Exclude approved IT tooling by InitiatingProcessFileName and review hits where the initiating process runs from a user temp or profile path. // LOOKBACK: 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Help-desk and wireless-troubleshooting scripts will match until tuned. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(30d) | where FileName =~ "netsh.exe" | where ProcessCommandLine matches regex @"(?i)wlan\s+show\s+profile.*key\s*=\s*clear" | project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: one host running both bcdedit /enum and Confirm-SecureBootUEFI in the search window, which is the bootkit-preparation survey Talos describes (UEFI versus BIOS, then Secure Boot state). Either command alone is routine; the pair on one host is the signal. bcdedit.exe is a legitimate binary: detection only. FP: Endpoint inventory, compliance and imaging tools run both checks. Boot-time health scripts do as well.
Known limitations and deployment notes
- PowerQuery: The creating process list collected on the CQL tab is not collected here.
- PowerQuery assumes: The regex is unanchored and matches is assumed to search within the command line.
- PowerQuery assumes: A single command line naming both checks satisfies both counts.
- KQL – Defender XDR: The initiating process list collected on the CQL tab is not collected here.
- KQL – Defender XDR assumes: The regex dot does not cross a line break in a multi-line command line.
- KQL – Defender XDR assumes: A single command line naming both checks satisfies both counts.
// HUNT: bcdedit enum plus Confirm-SecureBootUEFI on one host (NIK C2 bootkit preparation) // MITRE: T1542.003, T1082 // CONF: medium FP: medium COST: medium | REQUIRES: ProcessRollup2 (CommandLine) // FALSE POSITIVES: inventory, compliance and imaging tools that check boot mode and Secure Boot state. // TUNING: exclude hosts and parent processes belonging to your inventory or compliance agent; keep the hit when the same host also matches Q7 or Q4. // LOOKBACK: 7d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/(bcdedit.*enum|Confirm-SecureBootUEFI)/i | case { CommandLine=/Confirm-SecureBootUEFI/i | Check := "secureboot"; * | Check := "bcdedit"; } | groupBy([aid, ComputerName], function=[count(Check, distinct=true, as=DistinctChecks), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen), collect(ParentBaseFileName, limit=10)], limit=1000) | DistinctChecks >= 2 | sort(LastSeen, order=desc, limit=1000)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.cmdline: Created command lineagent.uuid: Host identityevent.time: Event time
Recommended fields
endpoint.name: Host
Readiness test
event.type = 'Process Creation' tgt.process.cmdline = * | limit 5 | columns event.time, agent.uuid, tgt.process.cmdline
// HUNT: bcdedit enum plus Confirm-SecureBootUEFI on one host (NIK C2 bootkit preparation) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1542.003, T1082 // CONF: medium | FP: medium // FALSE POSITIVES: inventory, compliance and imaging tools that check boot mode and Secure Boot state. // EQUIVALENCE: approximate-analytic - Counts a bcdedit enum call and a Confirm-SecureBootUEFI call per host and keeps hosts with both. The CQL counts distinct checks with a case that gives Confirm-SecureBootUEFI precedence, so one command line naming both counts once there and twice here. // REQUIRES: SentinelOne Deep Visibility Process Creation events // TUNING: Exclude hosts and creating processes belonging to your inventory or compliance agent; keep the hit when the same host also matches the raw disk read or screen-lock cards. // LOOKBACK: 7d (set in the time picker) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: The creating process list collected on the CQL tab is not collected here. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' (tgt.process.cmdline matches 'bcdedit.*enum' or tgt.process.cmdline contains 'Confirm-SecureBootUEFI') | group bcdedit_checks=count(tgt.process.cmdline matches 'bcdedit.*enum'), secureboot_checks=count(tgt.process.cmdline contains 'Confirm-SecureBootUEFI'), first_seen=min(event.time), last_seen=max(event.time) by agent.uuid, endpoint.name | filter bcdedit_checks > 0 and secureboot_checks > 0 | sort -last_seen | limit 1000
Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeProcessCommandLine: Created command lineDeviceId: Host identity
Recommended fields
DeviceName: Host
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, DeviceId, ProcessCommandLine | take 5
// HUNT: bcdedit enum plus Confirm-SecureBootUEFI on one host (NIK C2 bootkit preparation) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1542.003, T1082 // CONF: medium | FP: medium // FALSE POSITIVES: inventory, compliance and imaging tools that check boot mode and Secure Boot state. // EQUIVALENCE: approximate-analytic - Counts a bcdedit enum call and a Confirm-SecureBootUEFI call per host with countif and keeps hosts with both. One command line naming both counts for both checks, where the CQL counts it once. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents) // TUNING: Exclude hosts and initiating processes belonging to your inventory or compliance agent; keep the hit when the same host also matches the raw disk read or screen-lock cards. // LOOKBACK: 7d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: The initiating process list collected on the CQL tab is not collected here. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(7d) | where ProcessCommandLine matches regex @"(?i)(bcdedit.*enum|Confirm-SecureBootUEFI)" | summarize BcdeditChecks = countif(ProcessCommandLine matches regex @"(?i)bcdedit.*enum"), SecureBootChecks = countif(ProcessCommandLine contains "Confirm-SecureBootUEFI"), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by DeviceId, DeviceName | where BcdeditChecks > 0 and SecureBootChecks > 0 | sort by LastSeen desc | take 1000
Looks for: AmsiInitFailed in a command line. Talos says the implant runs an embedded PowerShell script that patches the AmsiInitFailed field in System.Management.Automation.dll. The script is embedded, so the string appears in a command line only if it is passed there; script-block logging (section 13, P3) is the stronger source and this query is the endpoint-telemetry fallback. FP: Penetration testers and security-training labs use the same field name; legitimate software does not.
Known limitations and deployment notes
- PowerQuery: An AMSI patch delivered without the string on a command line is not captured.
- PowerQuery assumes: contains is case-insensitive by default.
- KQL – Defender XDR: An AMSI patch delivered without the string on a command line is not captured.
- KQL – Defender XDR assumes: The string is matched as a plain substring of the command line.
// HUNT: AmsiInitFailed in a command line (AMSI patch, NIK C2) // MITRE: T1562.001, T1059.001 // CONF: medium FP: medium COST: low | REQUIRES: ProcessRollup2 (CommandLine) // FALSE POSITIVES: red-team and training labs that demonstrate AMSI bypasses; security tools that scan for the string. // TUNING: exclude known red-team hosts by ComputerName and approved security-scanner parents by ParentBaseFileName. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/AmsiInitFailed/i | table([@timestamp, aid, ComputerName, UserName, FileName, CommandLine, ParentBaseFileName], limit=200)
3 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.cmdline: Created command lineevent.time: Event time
Recommended fields
src.process.name: Creating process
Readiness test
event.type = 'Process Creation' tgt.process.cmdline = * | limit 5 | columns event.time, event.type, tgt.process.cmdline
// HUNT: AmsiInitFailed in a command line (AMSI patch, NIK C2) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1562.001, T1059.001 // CONF: medium | FP: medium // FALSE POSITIVES: red-team and training labs that demonstrate AMSI bypasses; security tools that scan for the string. // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: AmsiInitFailed anywhere in a command line, matched case-insensitively. // REQUIRES: SentinelOne Deep Visibility Process Creation events // TUNING: Exclude known red-team hosts by endpoint.name and approved security-scanner creating processes by src.process.name. // LOOKBACK: 30d (set in the time picker) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: An AMSI patch delivered without the string on a command line is not captured. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' tgt.process.cmdline contains 'AmsiInitFailed' | columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.cmdline, src.process.name | sort -event.time | limit 200
Automated validation: static-passed
2 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, ProcessCommandLine | take 5
// HUNT: AmsiInitFailed in a command line (AMSI patch, NIK C2) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1562.001, T1059.001 // CONF: medium | FP: medium // FALSE POSITIVES: red-team and training labs that demonstrate AMSI bypasses; security tools that scan for the string. // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate on ProcessCommandLine; contains is case-insensitive, matching the CQL intent. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents) // TUNING: Exclude known red-team hosts by DeviceName and approved security-scanner initiating processes by InitiatingProcessFileName. // LOOKBACK: 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: An AMSI patch delivered without the string on a command line is not captured. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceProcessEvents | where Timestamp >= ago(30d) | where ProcessCommandLine contains "AmsiInitFailed" | project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: a process named csrss.exe, svchost.exe or simvol.exe whose image path is not under System32 or SysWOW64. Talos says the implant renames itself csrss.exe in the temp directory, sets its masquerade name to svchost.exe or simvol.exe, and copies itself to %appdata%\Roaming\Microsoft\Network. csrss.exe and svchost.exe are legitimate binaries: the detection is the wrong path, never the name.
Known limitations and deployment notes
- PowerQuery: A process with an empty image path is not returned.
- PowerQuery assumes: tgt.process.image.path holds the full path with backslash separators.
- PowerQuery assumes: The hash column assumes tgt.process.image.sha256 is populated.
- KQL – Defender XDR: A process with an empty folder path would also be returned.
- KQL – Defender XDR assumes: FolderPath holds the folder or full image path of the created process.
// HUNT: csrss, svchost or simvol running outside System32 (NIK C2 masquerade) // MITRE: T1036.005 // CONF: high FP: low COST: low | REQUIRES: ProcessRollup2 (FileName, ImageFileName) // FALSE POSITIVES: near none for csrss.exe and simvol.exe. svchost.exe copies appear in some servicing and recovery paths under WinSxS. // LOOKBACK: 30d (set in the time picker) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^(csrss|svchost|simvol)\.exe$/i | ImageFileName!=/\\Windows\\(System32|SysWOW64|WinSxS)\\/i | table([@timestamp, aid, ComputerName, UserName, FileName, ImageFileName, CommandLine, ParentBaseFileName, SHA256HashData], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.type: Event typetgt.process.name: Created process nametgt.process.image.path: Created process pathevent.time: Event time
Recommended fields
src.process.name: Creating process
Optional fields
tgt.process.image.sha256: Hash. Population varies by tenant.
Readiness test
event.type = 'Process Creation' tgt.process.image.path = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.image.path
// HUNT: csrss, svchost or simvol running outside System32 (NIK C2 masquerade)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1036.005
// CONF: high | FP: low
// FALSE POSITIVES: near none for csrss.exe and simvol.exe. svchost.exe copies appear in some servicing and recovery paths under WinSxS.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: csrss, svchost or simvol whose image path is outside System32, SysWOW64 and WinSxS. The created process is tgt.process.*.
// REQUIRES: SentinelOne Deep Visibility Process Creation events with the image path populated
// TUNING: Near none for csrss.exe and simvol.exe. svchost.exe copies appear in some servicing and recovery paths under WinSxS, which the query already excludes.
// LOOKBACK: 30d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A process with an empty image path is not returned.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.name in:anycase ('csrss.exe', 'svchost.exe', 'simvol.exe') tgt.process.image.path = * !(tgt.process.image.path contains '\\Windows\\System32\\' or tgt.process.image.path contains '\\Windows\\SysWOW64\\' or tgt.process.image.path contains '\\Windows\\WinSxS\\')
| columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.image.path, tgt.process.cmdline, src.process.name, tgt.process.image.sha256
| sort -event.time
| limit 200Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameFolderPath: Created process path
Recommended fields
InitiatingProcessFileName: Initiating process
Optional fields
SHA1: Hash. SHA256 is often unpopulated in this table; SHA1 is the safer pivot.
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, FolderPath | take 5
// HUNT: csrss, svchost or simvol running outside System32 (NIK C2 masquerade)
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1036.005
// CONF: high | FP: low
// FALSE POSITIVES: near none for csrss.exe and simvol.exe. svchost.exe copies appear in some servicing and recovery paths under WinSxS.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate on DeviceProcessEvents: the created process name is in the list and its folder is outside System32, SysWOW64 and WinSxS.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: Near none for csrss.exe and simvol.exe. svchost.exe copies appear in some servicing and recovery paths under WinSxS, which the query already excludes.
// LOOKBACK: 30d
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A process with an empty folder path would also be returned.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceProcessEvents
| where Timestamp >= ago(30d)
| where FileName in~ ("csrss.exe", "svchost.exe", "simvol.exe")
| where not(FolderPath contains "\\Windows\\System32\\" or FolderPath contains "\\Windows\\SysWOW64\\" or FolderPath contains "\\Windows\\WinSxS\\")
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, SHA1, SHA256
| sort by Timestamp desc
| take 200Looks for: hosts that resolve api.openai.com. NIK C2 sends operator prompts to /v1/chat/completions from the victim machine, but so does every legitimate AI tool. This is a hunt and baseline query, not an alert: it shows which hosts and process ids talk to the endpoint so an unexpected one stands out. DNS carries no URL path, so the path in the snapshot cannot be matched here. FP: Developers, browsers with AI features, office suites and approved AI applications resolve this name all day. Expect high volume.
Known limitations and deployment notes
- PowerQuery: The querying process id is not collected as it is on the CQL tab.
- PowerQuery: Every approved AI tool and browser will match until baselined.
- PowerQuery assumes: event.dns.request is the populated DNS name field; some schema versions use dns.request instead.
- KQL – Defender XDR: The querying process id is not collected.
- KQL – Defender XDR: Every approved AI tool and browser will match until baselined.
- KQL – Defender XDR assumes: The queried name is stored under DnsQueryString or QueryName in AdditionalFields; the readiness test shows which key the tenant populates.
// HUNT: api.openai.com resolution by host (NIK C2 ai_generate baseline) // MITRE: T1071.001 // CONF: low FP: high COST: low | REQUIRES: DnsRequest (DomainName, ContextProcessId) // FALSE POSITIVES: every approved AI tool, browser and developer workstation. // TUNING: baseline for 14 days, then exclude approved hosts by ComputerName and keep servers, kiosks and hosts with no AI software; pivot unexpected process ids with P1. // LOOKBACK: 14d (set in the time picker) #event_simpleName=DnsRequest | DomainName=/^api\.openai\.com$/i | groupBy([aid, ComputerName], function=[count(as=Lookups), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen), collect(ContextProcessId, limit=10)], limit=2000) | sort(Lookups, order=asc, limit=500)
3 required fields · View requirements
Required telemetry
- DNS Resolved
Required fields
event.type: Event typeevent.dns.request: DNS nameevent.time: Event time
Recommended fields
endpoint.name: Host
Fallbacks
event.dns.request→dns.request: Same value under the older field name.
Readiness test
event.type = 'DNS Resolved' event.dns.request = * | limit 5 | columns event.time, event.type, event.dns.request
// HUNT: api.openai.com resolution by host (NIK C2 ai_generate baseline)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1071.001
// CONF: low | FP: high
// FALSE POSITIVES: every approved AI tool, browser and developer workstation.
// EQUIVALENCE: equivalent-with-schema-assumptions - Same DNS-resolution predicate for api.openai.com, grouped per host and sorted so the hosts with the fewest lookups come first.
// REQUIRES: SentinelOne Deep Visibility DNS Resolved events
// TUNING: Baseline for 14 days, then exclude approved hosts by endpoint.name and keep servers, kiosks and hosts with no AI software.
// LOOKBACK: 14d (set in the time picker)
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: The querying process id is not collected as it is on the CQL tab. Every approved AI tool and browser will match until baselined.
// VALIDATION LEVEL: static-reviewed
event.type = 'DNS Resolved' event.dns.request in:anycase ('api.openai.com')
| group lookups=count(), first_seen=min(event.time), last_seen=max(event.time) by agent.uuid, endpoint.name
| sort +lookups
| limit 500Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: ActionAdditionalFields: DNS name carrier
Recommended fields
DeviceName: Host
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "DnsQueryResponse" | project Timestamp, ActionType, AdditionalFields | take 5
// HUNT: api.openai.com resolution by host (NIK C2 ai_generate baseline) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1071.001 // CONF: low | FP: high // FALSE POSITIVES: every approved AI tool, browser and developer workstation. // EQUIVALENCE: equivalent-with-schema-assumptions - Same DNS-resolution predicate on the DnsQueryResponse action of DeviceEvents, with the name read from AdditionalFields. // REQUIRES: Defender for Endpoint network telemetry with DNS response events (DeviceEvents) // TUNING: Baseline for 14 days, then exclude approved hosts by DeviceName and keep servers, kiosks and hosts with no AI software. // LOOKBACK: 14d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: The querying process id is not collected. Every approved AI tool and browser will match until baselined. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceEvents | where Timestamp >= ago(14d) | where ActionType == "DnsQueryResponse" | extend DnsName = tostring(coalesce(parse_json(AdditionalFields)["DnsQueryString"], parse_json(AdditionalFields)["QueryName"])) | where DnsName =~ "api.openai.com" | summarize Lookups = count(), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by DeviceId, DeviceName | sort by Lookups asc | take 500
Looks for: an archive named browserdata.zip. Talos says matched seed-phrase and key-file candidates plus staged browser databases are archived into browserdata.zip before exfiltration. The name is generic enough that a hit needs the writing process checked.
Known limitations and deployment notes
- PowerQuery: An archive created under another name or renamed into place is not captured.
- PowerQuery assumes: tgt.file.path holds the full path with backslash separators; the name is matched as a case-insensitive substring so a longer name ending the same way also matches.
- KQL – Defender XDR: An archive created under another name or renamed into place is not captured.
- KQL – Defender XDR assumes: FileCreated is the action recorded for a new file.
// HUNT: browserdata.zip archive written (NIK C2 staging) // MITRE: T1560, T1005 // CONF: medium FP: low COST: low | REQUIRES: ZipFileWritten (TargetFileName) // FALSE POSITIVES: low. A browser-export or backup tool that uses the same archive name. // LOOKBACK: 30d (set in the time picker) #event_simpleName=ZipFileWritten | TargetFileName=/\\browserdata\.zip$/i | table([@timestamp, aid, ComputerName, UserName, TargetFileName, ContextBaseFileName], limit=200)
3 required fields · View requirements
Required telemetry
- File Creation
Required fields
event.type: Event typetgt.file.path: File pathevent.time: Event time
Recommended fields
src.process.name: Writing process
Readiness test
event.type = 'File Creation' tgt.file.path = * | limit 5 | columns event.time, event.type, tgt.file.path
// HUNT: browserdata.zip archive written (NIK C2 staging) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1560, T1005 // CONF: medium | FP: low // FALSE POSITIVES: low. A browser-export or backup tool that uses the same archive name. // EQUIVALENCE: equivalent-with-schema-assumptions - Same file-write predicate: browserdata.zip created. On a file event the writer is src.process.*. // REQUIRES: SentinelOne Deep Visibility File Creation events // TUNING: A browser-export or backup tool that uses the same archive name will match; confirm the writing process in src.process.name. // LOOKBACK: 30d (set in the time picker) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: An archive created under another name or renamed into place is not captured. // VALIDATION LEVEL: static-reviewed event.type = 'File Creation' tgt.file.path contains '\\browserdata.zip' | columns event.time, endpoint.name, src.process.user, tgt.file.path, src.process.name | sort -event.time | limit 200
Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceFileEvents
Required fields
Timestamp: Event timeActionType: ActionFileName: File name
Recommended fields
FolderPath: Folder
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceFileEvents | where Timestamp > ago(1d) | where ActionType == "FileCreated" | project Timestamp, ActionType, FileName | take 5
// HUNT: browserdata.zip archive written (NIK C2 staging) // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1560, T1005 // CONF: medium | FP: low // FALSE POSITIVES: low. A browser-export or backup tool that uses the same archive name. // EQUIVALENCE: equivalent-with-schema-assumptions - Same file-write predicate on DeviceFileEvents: FileCreated for a file named browserdata.zip. // REQUIRES: Defender for Endpoint file telemetry (DeviceFileEvents) // TUNING: A browser-export or backup tool that uses the same archive name will match; confirm the initiating process. // LOOKBACK: 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: An archive created under another name or renamed into place is not captured. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceFileEvents | where Timestamp >= ago(30d) | where ActionType == "FileCreated" | where FileName =~ "browserdata.zip" | project Timestamp, ReportId, DeviceId, DeviceName, InitiatingProcessAccountName, FileName, FolderPath, InitiatingProcessFileName | sort by Timestamp desc | take 200
Detection Rules by Platform
No rule is prevent. Every indicator comes from one vendor, and the behavioral rules sit on legitimate binaries (csrss.exe, svchost.exe, mshta.exe, cmd.exe, powershell.exe, netsh.exe, bcdedit.exe) whose names are never the match.
CrowdStrike: Custom IOA
| IOA name | Rule type | Pattern | Exclusions | Promotes | Deployment path |
|---|---|---|---|---|---|
| System-process name outside System32 | Process Creation | Image file name is csrss.exe, svchost.exe or simvol.exe and the image path is not under Windows System32, SysWOW64 or WinSxS | None; add approved servicing paths only after review | Promote Q12 | DETECT. High confidence, single vendor. Not a prevent on the legitimate binaries. |
| Screen-lock launch chain | Process Creation | Command line contains lock_screen.html or lock_start.bat and the image is mshta.exe or cmd.exe | None expected | Promote Q4 | DETECT. mshta.exe and cmd.exe are legitimate; behavioral only. |
| SystemLock autostart and fodhelper key | Registry (value set) | Value name SystemLock; or key path ending ms-settings\Shell\Open\command | Red-team hosts for the second pattern | Promote Q5, Q6 | DETECT. |
| Raw MBR read from PowerShell | Process Creation | Image powershell.exe or pwsh.exe with command line containing PhysicalDrive0 or mbr_backup.bin | Approved imaging and forensic hosts | Promote Q7 | DETECT. |
| NIK C2 published network indicators | Domain Name and Network Connection | Domain total-sitevv[.]lol; remote address 87.120.196[.]120 or 2.26.51[.]12 | None | Promote Q1, Q2 | DETECT only. Single vendor; move to prevent only after a second independent source or your own sample analysis. |
| Known sample hashes (Falcon IOC Management, not an IOA) | Custom IOC | 8 SHA-256 values from the CSV in section 10 | None | Promote Q3 | DETECT. |
Alert package: Q1 to Q4 and Q12
ALERT PACKAGE (Q3, Q4, Q12 and Q1, Q2 as scheduled searches) SCHEDULED SEARCH NAME: DETECT - NIK C2 implant behavior or infrastructure DESCRIPTION: Fires when an endpoint runs a published NIK C2 sample, runs a system-process name from outside System32, launches the mshta screen-lock chain, or contacts the published C2 domain or addresses. A hit means browser, wallet, Wi-Fi and Discord secrets on that host may already be stolen and a ransom screen may follow. SCHEDULE / WINDOW: every 15 minutes, last 30 minutes (Q1, Q2); hourly, last 90 minutes (Q3, Q4, Q12) ALERT EMAIL SUBJECT: [HIGH] Detection: NIK C2 - implant behavior or C2 contact on <ComputerName> ALERT EMAIL BODY: What fired: query <Q1|Q2|Q3|Q4|Q12> matched on <ComputerName> (aid <aid>) at <FirstSeen>. What it means: NIK C2 steals browser credentials, cookies, Discord tokens, wallets and Wi-Fi keys, logs keystrokes, can capture the screen, camera and microphone, and can lock the screen for ransom. Assume the data left the host. Immediate actions: network-contain the host; do NOT reimage yet; run pivots P1 and P2; start credential rotation for the user (runbook section 14). Escalation: SOC lead and IR on call within 30 minutes; notify the owner of any OpenAI or cloud account whose key was on the host. TRIAGE CHECKLIST (L1): 1. Confirm host and user from the alert; check whether it is a known malware-analysis host. 2. Run pivot P1 for the process, its path and its parent. 3. Run pivot P2 for the first sighting of the same hash or file name (delivery clue). 4. Network-contain the host in Falcon. 5. Check for lock_screen.html, lock_start.bat and a SystemLock Run value (P5 in section 13 collects them read-only). 6. List browsers, wallets, Discord and AI tools installed for the user. 7. Run N1, N3 and N5 for the same user and window. 8. Hand user and host to IR with the list from step 6 and record everything in the ticket (section 16).
Hunt package: Q5 to Q11, Q13, Q14
HUNT DESCRIPTION (investigate only, no alert email): Q5 and Q6 registry values, Q7 raw MBR read, Q8 recon prefix, Q9 Wi-Fi key extraction, Q10 boot survey, Q11 AMSI string, Q13 OpenAI DNS baseline, Q14 browserdata.zip. Why not an alert: Q9, Q10, Q11 and Q13 are medium or high FP until tuned; Q5 to Q8 and Q14 are high fidelity and may be promoted to alerts after one clean 14-day baseline. INVESTIGATION NOTES: run Q9, Q10 and Q13 weekly for 4 weeks, exclude approved IT tooling by image name, then decide whether to promote.
Pivot queries (placeholders in angle brackets, not runnable until replaced)
// P1: who ran it. Replace <AID> and <PID> with aid and TargetProcessId from the hit. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | aid="<AID>" TargetProcessId="<PID>" | table([@timestamp, ComputerName, UserName, FileName, ImageFileName, CommandLine, ParentBaseFileName, SHA256HashData], limit=20) // P2: first sight of the same hash across the environment. Replace <SHA256>. #event_simpleName=/^(ProcessRollup2|PeFileWritten|NewExecutableWritten)$/ | SHA256HashData="<SHA256>" | groupBy([aid, ComputerName, FileName], function=[min(@timestamp, as=FirstSeen), count(as=Events)], limit=1000) | sort(FirstSeen, order=asc, limit=200) // P3: everything the host ran in the 10 minutes around the hit (host-scoped; drop the aid filter for an environment-wide variant) #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | aid="<AID>" | table([@timestamp, FileName, CommandLine, ParentBaseFileName], limit=500) | sort(@timestamp, order=asc, limit=500)
SentinelOne: custom detection rules
| Rule | Source query | Run as | Notes |
|---|---|---|---|
| System-process name outside System32 | Q12, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device". This pack's own text mentions a baseline or pilot; follow it as written |
| Screen-lock launch chain | Q4, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device". This pack's own text mentions a baseline or pilot; follow it as written |
| SystemLock autostart and fodhelper key | Q5, Q6, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device". This pack's own text mentions a baseline or pilot; follow it as written |
| Raw MBR read from PowerShell | Q7, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device". This pack's own text mentions a baseline or pilot; follow it as written |
| NIK C2 published network indicators | Q1, Q2, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device". This pack's own text mentions a baseline or pilot; follow it as written |
Create the rule with POST /web/api/v2.1/cloud-detection/rules, queryType: "scheduled" and queryLang: "2.0", with the query in data.scheduledParams.query. Use 2.0 operator spellings: a rule written with the 1.0 token ContainsCIS was accepted and never fired on a tenant. The API does not warn, so lint the body before deploying.
Microsoft Defender: custom detection rules
| Rule | Source query | Run as | Notes |
|---|---|---|---|
| System-process name outside System32 | Q12, KQL – Defender XDR tab | Custom detection rule, alert only, every hour | The query returns Timestamp, ReportId and DeviceId, which Microsoft recommends for Defender for Endpoint tables so alerts carry the device group scope and the process tree. Remove the Timestamp filter and the final sort and take before saving the rule: the service applies the rule's lookback itself. This pack's own text mentions a baseline or pilot; follow it as written |
| Screen-lock launch chain | Q4, KQL – Defender XDR tab | Custom detection rule, alert only, every hour | The query returns Timestamp, ReportId and DeviceId, which Microsoft recommends for Defender for Endpoint tables so alerts carry the device group scope and the process tree. Remove the Timestamp filter and the final sort and take before saving the rule: the service applies the rule's lookback itself. This pack's own text mentions a baseline or pilot; follow it as written |
| SystemLock autostart and fodhelper key | Q5, Q6, KQL – Defender XDR tab | Custom detection rule, alert only, every hour | The query returns Timestamp, ReportId and DeviceId, which Microsoft recommends for Defender for Endpoint tables so alerts carry the device group scope and the process tree. Remove the Timestamp filter and the final sort and take before saving the rule: the service applies the rule's lookback itself. This pack's own text mentions a baseline or pilot; follow it as written |
| Raw MBR read from PowerShell | Q7, KQL – Defender XDR tab | Custom detection rule, alert only, every hour | The query returns Timestamp, ReportId and DeviceId, which Microsoft recommends for Defender for Endpoint tables so alerts carry the device group scope and the process tree. Remove the Timestamp filter and the final sort and take before saving the rule: the service applies the rule's lookback itself. This pack's own text mentions a baseline or pilot; follow it as written |
| NIK C2 published network indicators | Q1, Q2, KQL – Defender XDR tab | Custom detection rule, alert only, every hour | Make the final result include Timestamp, ReportId and DeviceId: Microsoft recommends them for Defender for Endpoint tables so alerts carry the device group scope and the process tree. Remove the Timestamp filter and the final sort and take before saving the rule: the service applies the rule's lookback itself. This pack's own text mentions a baseline or pilot; follow it as written |
Q3, Q8, Q9, Q10, Q11, Q13 and Q14 stay a hunt in this pack, not a rule. A rule can generate only 150 alerts per run. Continuous (NRT) frequency needs a single table and no comment lines, so delete the generated comment header from the query first.
Machine-Readable IOC Appendix
11 atomic indicators ship, all detect: 8 SHA-256 hashes, 1 domain and 2 IPv4 addresses. Every value was parsed from the saved Talos IOC snapshot by script, not typed. No prevent rows: one vendor is the only source. The URL, certificate, JARM, paths and file names are in the other blocks because Falcon IOC Management does not take them as atomic rows or they are behavioral.
type,value,action,severity,expiration,description,tags sha256,ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 sha256,2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9,detect,high,2027-04-29,NIK C2 implant sample (Talos IOC repository),campaign:NIK-C2 domain,total-sitevv.lol,detect,high,2027-04-29,NIK C2 C2 domain (Talos),campaign:NIK-C2 ipv4,87.120.196.120,detect,high,2027-04-29,NIK C2 C2 server (Talos),campaign:NIK-C2 ipv4,2.26.51.12,detect,high,2027-04-29,NIK C2 C2 address (Talos IOC repository only),campaign:NIK-C2
indicatorType,indicatorValue,action,title,description,expirationTime,severity,recommendedActions,rbacGroups,category,mitretechniques,GenerateAlert FileSha256,ae38f1181c9dd0db7224d6023e335eb2cdabb0f441906d14ffba8602b7abca3c,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,6583eb22ca554e749b647d68ae76f7279a8dc538196ebde1412669357a027de5,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,30817712277bba54e4cb8640f4005aad35f5172f88cf046aea545d029e12ccba,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,1fee4cd8d3560e6c60ba50451860adf6e705f26fd3fe1c1ccc058f4e8b13073a,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,bf83345ca66bdc4bd45ade608a06361d18927dd80351e9a1d8cbe8eda5d78402,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,99573a79f393299049216237d0d23761d67f6a8507a7a0cfe17cb30837f68f00,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,5d25efba2119f52d08214a590fedb45a5c9fe5e2850fd87e7bca24c92745e6d1,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True FileSha256,2a01056369cc691f5bed6bd2654930a81d1bc240a568a0d5b209aceef3b5c9c9,Audit,NIK C2 implant sample,NIK C2 implant sample (Talos IOC repository),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True DomainName,total-sitevv.lol,Audit,NIK C2 C2 domain,NIK C2 C2 domain (Talos),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True IpAddress,87.120.196.120,Audit,NIK C2 C2 server,NIK C2 C2 server (Talos),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True IpAddress,2.26.51.12,Audit,NIK C2 C2 address,NIK C2 C2 address (Talos IOC repository only),2027-04-29T00:00:00.0Z,High,Investigate the device and pivot into the pack's queries,,,,True
Column names and allowed values are from Microsoft's documented parameter table. Check each expirationTime before importing: an indicator whose date has passed is already expired. Download the sample CSV from the Import page to confirm the column order before a bulk import. Each file takes at most 500 indicators. Learn describes the import per entity type, so if a mixed file is rejected, split it by indicatorType. An imported indicator does nothing unless the matching Advanced features are on (for example Custom network indicators and Allow or block file).
This pack does not ship a SentinelOne import block: the import format could not be verified against SentinelOne's own documentation. Export a sample from your console and the block can be added with confidence.
# Network signatures (hunt in proxy, TLS and sensor logs; not Falcon IOC rows) ports: 443 TLS WebSocket (primary); HTTP fallback polling about every 250 ms cert CN: nik-panel cert serial: 7d16381a9de823943b5a0987dbd0f26edf22052b JARM: 28d28d28d00000000042d42d0000001f361a1bf80ed39a1e352adeb016a07b (candidate finder only) URI paths: /api/c2/update /api/c2/result /api/c2/screen /api/c2/file_chunk /api/c2/rproxy_up /api/c2/ws also listed: https://2.26.51.12:4443/api/c2/update (IOC repository only) AI traffic: POST https://api.openai.com/v1/chat/completions from an endpoint with no approved AI tool; default model string gpt-4; 60 second timeout
# Behavioral signatures (host)
[NIK] Starting log string in the implant
NIK_BOOTKIT_PREP 16-byte content of bootkit.bin (temp)
build path /opt/nik_panel/data/build_52b79724a1fc4b8f/main.go
files (temp) csrss.exe mbr_backup.bin lock_screen.html lock_start.bat bootkit.bin browserdata.zip
copy path %appdata%\Roaming\Microsoft\Network
masquerade svchost.exe simvol.exe (outside System32)
registry HKCU Run value SystemLock -> cmd /c <lock_start.bat>
registry HKCU\Software\Classes\ms-settings\Shell\Open\command (fodhelper bypass, removed in about 2 s)
commands powershell raw read of \\.\PhysicalDrive0 ; bcdedit /enum ; Confirm-SecureBootUEFI
netsh wlan show profiles ; netsh wlan show profile name="<SSID>" key=clear
chcp 65001 >nul 2>&1 & systeminfo | wmic os get lastbootuptime /value | wmic /namespace:\\root\SecurityCenter2 path AntiVirusProduct get displayName
AMSI patch of AmsiInitFailed in System.Management.Automation.dll
process NtSetInformationProcess 0x1D (ProcessBreakOnTermination); IsDebuggerPresent; CheckRemoteDebuggerPresent
timestamps PE TimeDateStamp zeroed; file system times 1979-11-29
toolchain Go 1.23.4, 64-bit Windows PE
ClamAV Win.Trojan.GoDiscorder-10060526-0# Data the implant targets (hunt surface and rotation scope; these are legitimate products, never block them) Browsers: Chrome, Edge, Brave, Opera, Firefox (key4.db, logins.json, places.sqlite, formhistory.sqlite) Desktop wallets: Exodus (exodus.wallet), Electrum (wallets), Ethereum keystore, Ledger Live, Bitcoin Core wallet.dat, Atomic Extension IDs: MetaMask (Chrome, Brave, Edge) nkbihfbeogaeaoehlefnkodbefgpgknn Coinbase Wallet hnbohgpbmfldddohgoiefkeifpjficbk Phantom (Chrome) lnbcamaoebkogjmdnaofbeemigaalhlp Brave Wallet odbfpeeihodbihlmhbnhakoadhilfibh Other: Discord tokens and cookies (LevelDB), saved Wi-Fi profiles, files whose names match seed, mnemonic, wallet, private, privkey or secret Rotation order: wallets (move funds to a new seed generated on a clean device), exchange and Discord sessions, browser-saved passwords, Wi-Fi pre-shared keys, OpenAI and other AI-provider keys
Detection Validation Gates
| Gate | Check | Pass condition |
|---|---|---|
| Telemetry ready | DNS lookup with the requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse); outbound network connection (CrowdStrike: NetworkConnectIP4. SentinelOne: IP Connect. Defender: DeviceNetworkEvents); Process creation with command line, image path and parent (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents); registry value set, autostart (CrowdStrike: AsepValueUpdate, RegGenericValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents); archive written (CrowdStrike: ZipFileWritten). | Q1 to Q12 depend on common events and should return rows for a test host. For Q14, create a harmless file named browserdata.zip in a test profile and confirm an archive-written row arrives; if none does, Q14 is blind in that tenant. |
| Benign baseline | Run Q9, Q10, Q11 and Q13 for 14 days in investigate mode before alerting. Run Q1 to Q8, Q12 and Q14 over 90 days. | Q1 to Q8, Q12 and Q14 return only test or sandbox hosts. Q9 to Q11 and Q13 hits are all explained by named tools, which are then excluded by image name. |
| Positive tests | Q4, Q5, Q12: on an isolated lab VM, create a harmless HTML file called lock_screen.html and open it with mshta, add a harmless Run value named SystemLock, and copy a benign binary named csrss.exe to a temp folder and run it. Q1, Q2: resolve the domain from a lab host with a local DNS override; do not contact the real infrastructure from a production host. Q8: run a chcp 65001 prefixed systeminfo. | Each test appears in the matching query within the schedule window. Remove the artifacts afterward. |
| Promotion | Promote Q1 to Q8 and Q12 to scheduled alerts after the baseline. Keep Q9 to Q11 as scheduled hunts until tuned. Keep Q13 as a periodic baseline review only. | No prevent action on any indicator until a second independent source or your own sample analysis confirms it. |
Hardening: Tiered & Deployable
- T1. Close the silent UAC bypass. The fodhelper hijack works when a local administrator runs with the default UAC level. Set the administrator prompt to consent on the secure desktop (the Always notify behavior) and, longer term, remove daily-use local admin rights. Framework: ATT&CK T1548.002 and M1052 User Account Control, M1026 Privileged Account Management; CIS Microsoft Windows 11 Enterprise Benchmark, Security Options (UAC elevation prompt for administrators). Verify: Playbook P1 and Q6.
- T2. Turn on PowerShell script-block logging. The AMSI patch and the raw MBR read run in PowerShell; script-block events (4104) catch them even when the command line is clean. Framework: T1059.001, T1562.001 and M1047 Audit, M1049 Antivirus/Antimalware; Microsoft PowerShell logging guidance. Verify: Playbook P3 and native hunt N4.
- T3. Alert, do not block, on the single-source indicators. Add the domain, two IPs and 8 hashes to detect-only watchlists (section 10). Do not sinkhole or block yet: a second independent source or your own analysis should come first. Framework: M1037 Filter Network Traffic. Verify: Q1 to Q3.
- T4. Audit where OpenAI API keys live. The implant falls back to the victim's
OPENAI_API_KEY. Find and remove keys held in environment variables on workstations, use a secrets manager, and set spend limits on the provider side. Framework: M1027 Password Policies, M1041 Encrypt Sensitive Information; ATT&CK T1552.001. Verify: Playbook P6 and N3.
- T5. Attack Surface Reduction rules in audit, then block. Start with obfuscated-script blocking and the prevalence/age/trusted-list rule for new executables; both hit a temp-folder implant that renames itself. Framework: M1038 Execution Prevention, M1049; Microsoft Security Baseline and Defender ASR guidance. Verify: Playbook P2 and ASR audit events.
- T6. Stop browsers saving passwords and cards on managed machines. The theft modules read Login Data, Cookies and key4.db. Disabling the built-in password manager removes the stored secrets (it does not remove existing ones). Framework: T1555.003 and M1027, M1054 Software Configuration; Chrome and Edge enterprise policy documentation. Verify: Playbook P4.
- T7. Restrict mshta and script hosts to those who need them. mshta opens the lock screen. Use AppLocker or WDAC to deny mshta.exe for standard users, in audit mode first. Framework: T1218.005 and M1038, M1042 Disable or Remove Feature or Program; Microsoft WDAC and AppLocker guidance. Verify: audit events for mshta, then Q4 still firing in a test.
- T8. Application control that stops user-writable folders running binaries. A WDAC or AppLocker policy that denies execution from temp and profile folders defeats the
csrss.exe-in-temp and Roaming\Microsoft\Network copies. Framework: T1036.005, T1547.001 and M1038; CIS Controls v8 control 2.5. Verify: Q12 returns nothing after enforcement. - T9. Boot integrity. Keep Secure Boot on, enable BitLocker with TPM and PIN where practical, and monitor boot-configuration changes. The report's bootkit module only stages a placeholder, but raw MBR access shows the intent. Framework: T1542.003 and M1046 Boot Integrity; Microsoft Secure Boot and BitLocker guidance. Verify: Playbook P3 step 3 and a Secure Boot report from inventory.
- T10. Egress control for AI services. Allow the OpenAI API only from approved hosts or through a proxy that logs the account. It is not a defense against this implant on an approved host, but it turns Q13 from a baseline into an alert. Framework: M1037, M1031 Network Intrusion Prevention. Best practice, no formal benchmark.
Deployable Playbooks
P1 · UAC always notify
Playbook P1: UAC always notify for administrators (blocks silent fodhelper auto-elevation) Prerequisites: local admin or GPO rights. Users who are local administrators will see more consent prompts; pilot on a ring first. Standard users are unaffected. Reboot required: no (applies at the next elevation) 1. Apply: reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 2 /f reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v PromptOnSecureDesktop /t REG_DWORD /d 1 /f 2. Verify: reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin # Expect 0x2 3. In production use the GPO setting "User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode" = "Prompt for consent on the secure desktop". Rollback: reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 5 /f # 5 is the Windows default (prompt for consent for non-Windows binaries).
P2 · ASR rules in audit mode
Playbook P2: Attack Surface Reduction rules in audit mode
Prerequisites: Microsoft Defender Antivirus active and cloud protection on; local admin. Audit mode logs and does not block, so there is no user impact.
Reboot required: no
1. Apply (audit):
$ids = @('5BEB7EFE-FD9A-4556-801D-275E5FFC04CC', # block execution of potentially obfuscated scripts
'01443614-CD74-433A-B99E-2ECDC07BFC25') # block executables unless prevalence, age or trusted-list criteria are met
foreach ($id in $ids) { Add-MpPreference -AttackSurfaceReductionRules_Ids $id -AttackSurfaceReductionRules_Actions AuditMode }
2. Verify:
(Get-MpPreference).AttackSurfaceReductionRules_Ids
(Get-MpPreference).AttackSurfaceReductionRules_Actions # 2 = Audit
3. After 14 days of review of Microsoft-Windows-Windows Defender/Operational events 1122, move reviewed rules to block (action 1).
Rollback:
foreach ($id in $ids) { Remove-MpPreference -AttackSurfaceReductionRules_Ids $id }
# Removes the rules. Do this if audit events show a business application is affected.P3 · Script-block logging and boot-state check
Playbook P3: PowerShell script-block logging and boot-state check Prerequisites: local admin or GPO rights; the PowerShell Operational log sized for the extra volume (for example 256 MB). Script text will be logged, so restrict access to the log. Reboot required: no 1. Enable script-block logging: $k = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' New-Item -Path $k -Force | Out-Null Set-ItemProperty -Path $k -Name EnableScriptBlockLogging -Value 1 -Type DWord 2. Verify: Get-ItemProperty $k | Select-Object EnableScriptBlockLogging # Then run a harmless command and look for event 4104 in Microsoft-Windows-PowerShell/Operational. 3. Read-only boot-state check (UEFI hosts): Confirm-SecureBootUEFI # Expect True. An error on a BIOS-mode host is normal. bcdedit /enum | Select-String -Pattern 'path' Rollback: Remove-ItemProperty -Path $k -Name EnableScriptBlockLogging # Stops the extra logging. Step 3 changes nothing; Rollback: none required for it.
P4 · Browser password and card storage policy
Playbook P4: stop managed Chrome and Edge from saving passwords and cards
Prerequisites: local admin or GPO rights; confirm users have an approved password manager first. Existing saved passwords are not removed by these policies.
Reboot required: no (browsers read policy at next start)
1. Apply:
foreach ($p in @('HKLM:\SOFTWARE\Policies\Google\Chrome','HKLM:\SOFTWARE\Policies\Microsoft\Edge')) {
New-Item -Path $p -Force | Out-Null
Set-ItemProperty -Path $p -Name PasswordManagerEnabled -Value 0 -Type DWord
Set-ItemProperty -Path $p -Name AutofillCreditCardEnabled -Value 0 -Type DWord
}
2. Verify: open chrome://policy and edge://policy and confirm both values show as set.
Rollback:
foreach ($p in @('HKLM:\SOFTWARE\Policies\Google\Chrome','HKLM:\SOFTWARE\Policies\Microsoft\Edge')) {
Remove-ItemProperty -Path $p -Name PasswordManagerEnabled,AutofillCreditCardEnabled -ErrorAction SilentlyContinue
}P5 · Read-only artifact triage
Playbook P5: read-only triage for NIK C2 artifacts on a suspect host
Prerequisites: run in an elevated PowerShell on the isolated host; do not delete anything found, copy it to evidence storage first.
Reboot required: no
1. Files in the temp directory and the Roaming copy path:
$names = 'csrss.exe','lock_screen.html','lock_start.bat','mbr_backup.bin','bootkit.bin','browserdata.zip'
Get-ChildItem -Path $env:TEMP -Recurse -Force -ErrorAction SilentlyContinue | Where-Object { $names -contains $_.Name } | Select-Object FullName, Length, CreationTime, LastWriteTime
Get-ChildItem "$env:APPDATA\Microsoft\Network" -Force -ErrorAction SilentlyContinue | Select-Object Name, Length, LastWriteTime
2. Registry:
Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' | Select-Object SystemLock
Test-Path 'HKCU:\Software\Classes\ms-settings\Shell\Open\command'
3. System-process names outside System32:
Get-Process csrss,svchost,simvol -ErrorAction SilentlyContinue | Where-Object { $_.Path -and $_.Path -notmatch '\\Windows\\(System32|SysWOW64)\\' } | Select-Object Id, Path
Rollback: none required, this playbook reads state only and changes nothing.P6 · OPENAI_API_KEY audit
Playbook P6: find OPENAI_API_KEY on endpoints (the implant's fallback key)
Prerequisites: run as admin for the machine scope; run through your RMM or EDR as a script. The value is never printed, only whether it is set.
Reboot required: no
1. Audit:
foreach ($s in 'Machine','User') {
$v = [Environment]::GetEnvironmentVariable('OPENAI_API_KEY',$s)
'{0}: OPENAI_API_KEY set = {1}' -f $s, [bool]$v
}
2. For every host that reports True: record the owner, confirm the key is needed, move it to a secrets manager, and rotate it in the provider console. Check the provider's usage log for unexplained requests (native hunt N3).
Rollback: none required for the audit. If you later remove the variable, restore it from your secrets manager; the audit never reads the value.P7 · AppLocker audit rule for mshta.exe
Playbook P7: AppLocker audit-only rule for mshta.exe Prerequisites: Windows Enterprise or Education with the Application Identity service running; local admin. Audit-only: events are written, nothing is blocked. Export the current policy first. Reboot required: no 1. Back up the current policy: Get-AppLockerPolicy -Local -Xml | Out-File "$env:USERPROFILE\applocker-backup.xml" -Encoding utf8 2. Apply the audit rule: $xml = @' <AppLockerPolicy Version="1"><RuleCollection Type="Exe" EnforcementMode="AuditOnly"> <FilePathRule Id="921cc481-6e17-4653-8f75-050b80acca20" Name="Allow Windows" Description="" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%WINDIR%\*"/></Conditions></FilePathRule> <FilePathRule Id="a61c8b2c-a319-4cd0-9690-d2177cad7b51" Name="Allow Program Files" Description="" UserOrGroupSid="S-1-1-0" Action="Allow"><Conditions><FilePathCondition Path="%PROGRAMFILES%\*"/></Conditions></FilePathRule> <FilePathRule Id="b7c5a1d2-3f4e-4a6b-8c9d-0e1f2a3b4c5d" Name="Deny mshta" Description="" UserOrGroupSid="S-1-1-0" Action="Deny"><Conditions><FilePathCondition Path="%SYSTEM32%\mshta.exe"/></Conditions></FilePathRule> </RuleCollection></AppLockerPolicy> '@ $xml | Out-File "$env:TEMP\mshta-audit.xml" -Encoding utf8 Set-AppLockerPolicy -XmlPolicy "$env:TEMP\mshta-audit.xml" 3. Review Microsoft-Windows-AppLocker/EXE and DLL events 8003 for mshta use before enforcing. Rollback: Set-AppLockerPolicy -XmlPolicy "$env:USERPROFILE\applocker-backup.xml" # Restores the policy exported in step 1.
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Network-contain the host in Falcon. Do not power off (memory and temp files hold evidence). Do not reimage yet. If a lock screen is showing, do not try to dismiss it by killing mshta first: the batch loop and watchdog relaunch it, and the host must be isolated before cleanup. | SOC / IR | Containment timestamp, host and user |
| Isolate: by platform | CrowdStrike: network-contain the host. SentinelOne: network quarantine (Disconnect from Network; confirm the label in your console version). Microsoft Defender: Isolate device (full network isolation). Keep the host powered on for memory capture on all of them. | SOC / IR | Containment timestamp, host and user |
| Scope | Run pivots P1 to P3 and playbook P5. Run N1, N3 and N5 for other hosts that contacted the same infrastructure. List browsers, wallets, Discord, AI tools and Wi-Fi networks on the host (section 10 targeted-data block). | IR | Process tree, first-seen file, host software list |
| Revoke and rotate | Work the rotation order in section 10: move wallet funds to a new seed created on a clean device, end exchange and Discord sessions and reset passwords, reset browser-saved passwords, change Wi-Fi pre-shared keys the host knew, rotate every OpenAI and other AI-provider key on the host, then review provider usage (N3) and wallet or exchange activity (N7). | IR / Identity / Finance owners | Rotation checklist with timestamps, provider log extracts |
| Remove lock screen | After memory and artifact capture: stop the lock process and its watchdog from an administrative session, delete the SystemLock Run value and lock_start.bat, then confirm the screen no longer relaunches at logon. Do not pay the ransom; the module encrypts nothing. | IR / Endpoint | Copies of lock_screen.html and lock_start.bat, wallet addresses shown (for reporting) |
| Eradicate | Collect the sample and any dropped file, record hashes (add new ones to the CSV), then reimage. Do not clean in place: the implant has a watchdog, COM hijack and boot-survey capability. After the rebuild, verify the MBR against the host's known-good image and confirm Secure Boot state (P3 step 3). Compare mbr_backup.bin to the live MBR if the file was captured. | IR / Endpoint | Sample hashes, image build record, boot-state check |
| Recover | Restore from a clean image, re-enroll the sensor, apply T1 to T4 before the user returns. Watch Q1 to Q14 for the host and user for 30 days. | Endpoint / SOC | Post-rebuild query results |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | CrowdStrike coverage | SentinelOne | Defender XDR |
|---|---|---|---|---|---|---|
| T1071.001 / T1041 | Published C2 domain and addresses | Q1, Q2 | Yes (detect) | Good | Good, with assumptions | Good, with assumptions |
| T1204.002 | Published implant hashes (later builds will not match) | Q3 | Yes (detect) | Partial | Partial: Q3 approximate | Partial: Q3 telemetry gap |
| T1036.005 | System-process names outside System32 | Q12 | Yes (detect) | Good | Good, with assumptions | Good, with assumptions |
| T1218.005 / T1491.001 | Screen-lock launch via mshta and lock_start.bat | Q4 | Yes (detect) | Good | Good, with assumptions | Good, with assumptions |
| T1547.001 | SystemLock Run value | Q5 | Yes (detect) | Good | Good, with assumptions | Good, with assumptions |
| T1548.002 | fodhelper ms-settings key write | Q6 | Yes (detect) | Partial | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| T1006 / T1542.003 | Raw MBR read through PowerShell | Q7 | Yes (detect) | Good | Good, with assumptions | Good, with assumptions |
| T1082 / T1518.001 | chcp 65001 wrapped recon | Q8 | No | Good | Good, with assumptions | Good, with assumptions |
| T1555 / T1016.002 | Wi-Fi key extraction | Q9 | No | Partial | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| T1542.003 | Boot firmware survey | Q10 | No | Partial | Partial: Q10 approximate | Partial: Q10 approximate |
| T1562.001 | AMSI bypass string in a command line | Q11 | No | Partial | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| T1071.001 | Operator prompts to the OpenAI API (hunt only) | Q13 | No | Partial | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| T1560 / T1005 | browserdata.zip staging | Q14 | No | Partial | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| T1056.001 / T1113 / T1125 / T1123 / T1115 | Keylogger, screen, camera, microphone, clipboard | None | No | GAP | GAP | GAP |
| T1555.003 / T1539 / T1528 | Browser database, cookie, Discord token and wallet reads, DPAPI unwrap | None | No | GAP | GAP | GAP |
| T1055.012 / T1622 / T1562 | Process hollowing, debugger checks, critical-process flag | None | No | GAP | GAP | GAP |
| T1021.001 / T1563.002 / T1090 | RDP hijacking and the embedded proxy relay | None | No | GAP | GAP | GAP |
Validation gates are in section 11. The four gap rows are outside endpoint telemetry or run inside the implant process; the report publishes no technique detail for process hollowing or RDP hijacking, so no query is written for them. Network, proxy and provider logs (N1 to N3) are the compensating controls.
Hunt Summary Ticket
TITLE: NIK C2 AI-enabled C2 framework with OpenAI API client and screen-lock module (Cisco Talos, 2026-10-29) SEVERITY: High. Credential, wallet and keystroke theft plus a ransom screen; stolen secrets can be abused outside the endpoint SCOPE: Windows endpoints that run unsigned code from user-writable folders; every browser, wallet, Discord, Wi-Fi and AI-provider account the host knew HYPOTHESIS: The implant runs from a temp folder renamed csrss.exe or svchost.exe, talks to a nik-panel TLS server on 443, steals browser, wallet and Wi-Fi secrets, can ask a model to analyse them through the OpenAI API, and can lock the screen for a Bitcoin or USDT ransom. Delivery is not established. QUERIES: 14 CQL queries (Q1-Q14). Q1-Q8 and Q12 high confidence; Q6, Q9, Q10, Q11, Q14 medium; Q13 low hunt-only. N1-N7 cover proxy, TLS sensor, provider, PowerShell, Sysmon, file and account logs. DO FIRST: 1) Run Q12 and Q4-Q7 over 30 days and Q1-Q3 over 90 days. 2) Run N1 and N3. 3) On any hit: contain, rotate wallets and credentials, then reimage (runbook section 14). FINDINGS: [fill in after the hunt] GAPS: Keylogging, screen, camera and clipboard collection, browser and wallet file reads, DPAPI calls, process hollowing and RDP hijacking are outside endpoint telemetry or inside the implant process. Later builds will not match the 8 published hashes. ACTIONS: Detect-only watchlists for the single-source indicators; UAC always notify; script-block logging; ASR audit; browser password policy; OPENAI_API_KEY audit; mshta audit rule. OWNER: REPLACE_WITH_OWNER VERSION: v0.1 (Draft) 2026-10-29
Changelog
References
| Tier | Source | Used for | Access date |
|---|---|---|---|
| T1 | Cisco Talos: NIK C2: The new AI-enabled command-and-control framework (2026-10-29) | Architecture, C2 protocol and endpoints, AI handler, ransomware and bootkit modules, theft targets, evasion, build path, infrastructure, ClamAV signature. | 2026-10-29 |
| T1 | Cisco-Talos/IOCs: 2026/10/nik-c2-new-ai-enabled-framework.txt | 8 SHA-256 hashes, 1 domain, 2 IPs, C2 paths. | 2026-10-29 |
| T1 | Cisco-Talos/IOCs: 2026/10/nik-c2-new-ai-enabled-framework.json (STIX) | Indicator types cross-check. | 2026-10-29 |
| T3 | OffSeq Threat Radar: NIK C2 page | Confirmed that coverage is a restatement of the Talos post. No value taken. | 2026-10-29 |
Generated 2026-10-29 by HuntPack. Defensive content only.