BlackX UEFI Bootkit: Baton Drop Secure Boot Bypass Against Central Asian Diplomatic Agencies
Executive Summary
BlackX is a UEFI bootkit that Kaspersky GReAT found in early 2026 on the networks of diplomatic agencies in Tajikistan, Uzbekistan and Turkmenistan. It closely copies the BlackLotus bootkit, exploits Baton Drop (CVE-2022-21894) to enrol attacker Machine Owner Keys and bypass Secure Boot, and then loads a kernel driver that blinds security products. Kaspersky attributes it to APT41 with medium confidence. The report was published 2026-10-22.
The twist is that the victims were fully patched. Microsoft's Baton Drop fix only revokes the vulnerable "Windows Production PCA 2011" signer after an administrator sets a registry flag and runs the Secure-Boot-Update task, and the automatic Enforcement Phase that would do it for everyone has not shipped. The pack therefore has two jobs: hunt the BlackX tradecraft that is visible to endpoint telemetry, and find the hosts where the revocation was never activated.
The strongest endpoint angles are the installer command line, the googleupdate.exe sideload host, the C2 lookups and the cloud-storage channel. The bootkit and kernel driver themselves act before or beneath the sensor, so the pack states plainly what it cannot see and routes those checks to native hunts.
Source Review & Web Hunter Notes
| Tier | Source | Key finding | Carry forward |
|---|---|---|---|
| 1 | Securelist (Kaspersky GReAT), 2026-10-22, snapshot 01 | Primary report: installer and command line, Baton Drop MOK enrolment, driver signed with a revoked certificate, cloud-storage RAT, OxiDLLRunner sideload, C2 host, patch gap, attribution reasoning | YES |
| 3 | SecurityOnline, snapshot 02 | Restates the Kaspersky report. Adds only the advice to block the C2 host and watch inst.exe and cloud-drive traffic. Not independent of Securelist | PARTIAL |
| 1 | Microsoft Support, revocation guidance, snapshot 03 | The documented procedure: registry value, Secure-Boot-Update task, DB then DBX then SVN steps, recovery procedure, Enforcement Phase still "date to be announced" when fetched on 2026-10-23 | YES |
Decisions and limits
- Dropped source. The SecurityBrief Asia URL in the request returned an older article about the MoonBounce firmware bootkit, not BlackX. It contains no BlackX content, so it is neither cited nor snapshotted.
- Microsoft's page is filed under CVE-2023-24932 (the BlackLotus boot manager revocation). It describes the exact registry flag and task that Kaspersky calls the Baton Drop activation step, but the CVE number on Microsoft's page is 2023-24932, not 2022-21894. The pack keeps both numbers and does not merge them.
- No IOC appendix. The Securelist page carries its indicators in the text only: one C2 host, one file hash, one certificate serial. No installer, driver or Rust payload hash is published, so those ship as labelled placeholders, never as invented values.
- Single-source indicators ship detect. SecurityOnline restates Securelist rather than corroborating it, so nothing here qualifies for prevent. The MD5 belongs to a legitimate helper and is never prevent in any case.
- Not obtained. Microsoft's April 2023 BlackLotus investigation blog (the CDN returned HTTP 403) and ESET's June 2026 report that Kaspersky cites. Related-cluster indicators from ESET's reporting are deliberately not imported.
- Attribution is Kaspersky's, medium confidence. Basis: the identifier "xdd" appearing in BlackX payloads and in a PDB path from ESET's report, sideloading plus an encrypted file, and OLLVM obfuscation. All three are patterns shared by several Chinese-speaking actors.
Hunt Brief & Attack Chain
Hunt hypotheses (highest fidelity first)
| # | Hypothesis | MITRE | Queries | Confidence |
|---|---|---|---|---|
| H1 | An installer named inst.exe is run from ProgramData with an extensionless blob and a key argument | T1542.003, T1140 | Q1, Q2 | HIGH |
| H2 | A copy of the Chromium helper runs as googleupdate.exe outside a Google Update directory and sideloads a DLL | T1574.002, T1036 | Q3, Q4 | HIGH |
| H3 | The sideloaded Rust payload resolves the C2 host, and the sideload host resolves non-Google names | T1071.001 | Q5, Q6 | HIGH |
| H4 | A process that is not a browser or sync client talks to Drive, OneDrive or Yandex.Disk APIs (RAT C2) | T1102.002, T1567.002 | Q7 | MEDIUM |
| H5 | EFI partition or boot configuration is manipulated from a running Windows host | T1542.003, T1553 | Q10, N4, N6 | MEDIUM |
| H6 | A rare kernel driver loads, possibly signed with the revoked certificate | T1014, T1547.006 | Q11, N3 | MEDIUM |
| H7 | Hosts have not triggered the PCA 2011 revocation, and a lookalike Secure-Boot-Update task exists | T1112, T1053.005 | Q8, Q9, N1, N7 | MEDIUM |
Attack chain
| Step | Behaviour | Telemetry (plain terms, then platform) | Hunt angle |
|---|---|---|---|
| 1 | Attackers already hold administrator rights on the network (method not published) | Outside endpoint telemetry for this pack | Gap: handled by identity and lateral-movement hunts |
| 2 | Drop inst.exe and PVMDIJGKAX2 in C:\ProgramData\Intel; run with the RC4 key as last argument | Process creation with command line (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents) | Q1, Q2 |
| 3 | Installer writes files to the system and UEFI partitions; Baton Drop enrols custom MOK keys to load arbitrary EFI files | Process creation with command line (as above). ESP file writes are outside endpoint telemetry | Q10, N4, N6 |
| 4 | On reboot the bootkit injects a kernel driver signed with a certificate since revoked | Driver load (CrowdStrike: DriverLoad. SentinelOne and Defender: confirm on tenant). Signer serial needs a native check | Q11, N3 |
| 5 | Driver removes security process, thread and registry callbacks, tampers with ETW, hides files by returning a calc.exe handle | Registry value set (CrowdStrike: RegGenericValueUpdate, AsepValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents). Kernel actions are invisible | Q12 (adjacent only), gap |
| 6 | User-mode payloads: cloud-storage RAT, and OxiDLLRunner via googleupdate.exe decrypting v8_context_snapshot.bin | Process creation (as above); DNS lookup with requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse) | Q3, Q4, Q6, Q7 |
| 7 | Rust PE beacons to the C2 host and receives plugin DLLs exporting create_plugin | DNS lookup with requesting process (as above) | Q5, Q6 |
| 8 | Plugins run in separate threads (in memory) | Outside endpoint telemetry unless memory scanning is enabled | Gap |
| Meta | Revocation never activated, so the vulnerable signer stays trusted | Registry value set (as above); scheduled task registered (CrowdStrike: ScheduledTaskRegistered. Defender: DeviceEvents ScheduledTaskCreated) | Q8, Q9, N1, N7 |
Consolidated IOC Table
| Type | Value | Confidence | Action | Context |
|---|---|---|---|---|
| Domain | www[.]archivetj[.]com | MEDIUM | detect | Rust payload C2. Securelist, restated by SecurityOnline (not independent) |
| MD5 | AF8A983B9ADA07EAE1259BF2953ABD40 | LOW | detect | The legitimate Chromium helper jcef_helper.exe, run by BlackX as googleupdate.exe. Stock binary: hunt the rename (Q4), never block |
| Cert serial | 0bcdf5e0da32d68900b8b7638459d072 | MEDIUM | hunt | Driver signing certificate, issued to Wenjiang District Mingyu Network Technology Service Studio and since revoked by its issuer. Not importable as a Falcon IOC; check natively (N3) |
| File | inst.exe, PVMDIJGKAX2 | HIGH | hunt | Installer and RC4-encrypted blob in C:\ProgramData\Intel |
| Argument | Q46F6MDLI3RX2KV1 | MEDIUM | hunt | RC4 key, last command-line argument. Likely changes per build |
| File | googleupdate.exe, v8_context_snapshot.bin | MEDIUM | hunt | Sideload host and encrypted payload in the same folder. The snapshot file name is also used by genuine Chromium and Electron apps |
| Name | OxiDLLRunner, export create_plugin | HIGH | hunt | Kaspersky's name for the OLLVM-obfuscated loader DLL; plugin export name |
| Registry / task | HKLM\SYSTEM\CurrentControlSet\Control\Secureboot, task Secure-Boot-Update | MEDIUM | hunt | Revocation activation flag and task. Defender-side remediation, not attacker tradecraft |
| Cloud suffix | 0X01 0X02 0X03 0X04 0X05 0X06 SSSR | MEDIUM | hunt | RAT task and result file suffixes in the cloud drive (cloud-side hunt N8) |
| String | xdd | LOW | enrich | Identifier inside BlackX payloads that ties it to an ESET PDB path. Weak alone |
| Hash | REPLACE_WITH_INST_EXE_SHA256, REPLACE_WITH_OXIDLLRUNNER_SHA256 | n/a | pending | Not published in any fetched source |
Affected Surface & Telemetry Matrix
| Surface | Telemetry (plain terms, then platform) | Priority | Gap |
|---|---|---|---|
| Windows endpoints with administrator access | Process creation with command line (CrowdStrike: ProcessRollup2. SentinelOne: Process Creation. Defender: DeviceProcessEvents) | Critical | Low |
| Name resolution by the sideload host and the cloud RAT | DNS lookup with requesting process (CrowdStrike: DnsRequest. SentinelOne: DNS Resolved. Defender: DeviceEvents DnsQueryResponse) | Critical | Low. Encrypted DNS bypasses it |
| Kernel driver loads | Driver load (CrowdStrike: DriverLoad. SentinelOne and Defender: confirm the event on your tenant) | High | Medium. Bootkit-injected load may precede the sensor; signer serial not exposed |
| Registry (Secureboot key, ETW autologgers) | Registry value set (CrowdStrike: RegGenericValueUpdate, AsepValueUpdate. SentinelOne: Registry Value Modified. Defender: DeviceRegistryEvents) | High | Low for user-mode writes |
| Scheduled tasks | Scheduled task registered (CrowdStrike: ScheduledTaskRegistered. Defender: DeviceEvents ScheduledTaskCreated. SentinelOne: Task Register, confirm spelling) | High | Low |
| EFI system partition and firmware variables (MOK, DB, DBX) | Native checks only | Critical | High: outside endpoint telemetry |
| Kernel callbacks and ETW | None | High | High: tampering is in kernel mode, outside endpoint telemetry |
| Cloud storage accounts used as C2 | Provider audit logs (Google Workspace, Microsoft 365, Yandex) | High | Outside endpoint telemetry; needs provider logs and legal reach |
ATT&CK Mapping
| Tactic | Technique | Observed or inferred behaviour | Query or control |
|---|---|---|---|
| Persistence / Defense Evasion | T1542.003 Bootkit | UEFI bootkit injects a kernel driver at boot (observed) | Q1, Q2, Q10, N1, N4 |
| Defense Evasion | T1553 Subvert Trust Controls | Baton Drop used to enrol MOK keys and bypass Secure Boot (observed) | Q8, Q9, hardening T1 |
| Defense Evasion | T1014 Rootkit | Driver returns a calc.exe handle on open requests for bootkit files (observed) | N3, N4, gap |
| Defense Evasion | T1562.001 Impair Defenses: Disable or Modify Tools | Process, thread and registry callbacks of security products removed (observed) | Gap (kernel) |
| Defense Evasion | T1562.006 Indicator Blocking | ETW providers tampered (observed in kernel; registry cousin inferred) | Q12 |
| Defense Evasion | T1574.002 DLL Side-Loading | googleupdate.exe loads OxiDLLRunner (observed) | Q3, Q4, N2 |
| Defense Evasion | T1027 / T1140 Obfuscation, Deobfuscation | RC4 blob with key on command line; OLLVM; decrypted v8_context_snapshot.bin (observed) | Q1, Q2, N2 |
| Command and Control | T1071.001 Web Protocols | Rust payload communicates with the C2 host (observed) | Q5, Q6 |
| Command and Control | T1102.002 Bidirectional Communication | RAT reads task files from Drive, OneDrive, Yandex.Disk (observed) | Q7, N8 |
| Exfiltration / Ingress | T1567.002, T1105 | Upload and download task suffixes 0X03, 0X05 (observed) | Q7, N8 |
| Execution | T1129 Shared Modules | DLLs exporting create_plugin run in separate threads (observed) | Gap (memory) |
| Discovery | T1082 System Information Discovery | SSSR file carries initial system info (observed) | N8 |
| Defense Evasion | T1112 Modify Registry; T1053.005 Scheduled Task | Secureboot flag and Secure-Boot-Update task: the revocation activation (defender step) | Q8, Q9 |
Native Audit-Log Hunts
These checks run outside the sensor. They cover what the bootkit does below the operating system.
| ID | Check | How | Expected result |
|---|---|---|---|
| N1 | Secure Boot posture | Run playbook P1 on each host class | Secure Boot on; DB holds "Windows UEFI CA 2023"; DBX holds "Microsoft Windows Production PCA 2011" once revoked |
| N2 | Sideload pair on disk | Playbook P3: look for googleupdate.exe outside Google Update beside v8_context_snapshot.bin in ProgramData, Users and Temp | No hit. A v8_context_snapshot.bin beside a genuine Chromium or Electron app is normal; beside googleupdate.exe in a user-writable folder is not |
| N3 | Driver signer serial | Playbook P3 second block: compare loaded driver signer serials with 0bcdf5e0da32d68900b8b7638459d072 | No driver signed with that serial |
| N4 | EFI system partition contents | Mount read-only for inspection, list \EFI subfolders and compare with a known-good host of the same image | Only Microsoft and OEM boot files. Unexpected EFI binaries, extra boot entries or key-enrolment tooling are findings |
| N5 | Code Integrity operational log | Review Microsoft-Windows-CodeIntegrity/Operational for drivers loaded with revoked or unusual signatures | No unexplained driver signature events |
| N6 | Boot configuration | bcdedit /enum all and compare against the image baseline | No test-signing, integrity-check or unexpected loader options |
| N7 | Secure-Boot-Update task location | Get-ScheduledTask -TaskName Secure-Boot-Update and read TaskPath | One task, path \Microsoft\Windows\PI\ |
| N8 | Cloud-drive C2 artefacts | Search corporate and suspected accounts in Google Workspace, Microsoft 365 and any Yandex use for file names ending 0X01 to 0X06 or SSSR | No such files. Treat as provider-log work needing the account owner |
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.
// LOOKBACK line is the intent). Q11 uses DriverLoad: validate its field names on your sensor build before relying on it. Q7, Q10 and Q12 are inferred behavioural hunts and are labelled as such in their headers.Looks for: inst.exe launched with the blob name PVMDIJGKAX2 or the RC4 key argument the Securelist report shows. FP: very low; both strings are campaign constants. They may change per build, so Q2 matches the shape without them.
Known limitations and deployment notes
- PowerQuery: A launch the agent did not observe is not captured.
- PowerQuery assumes: tgt.process.cmdline holds the full command line of the created process.
- PowerQuery assumes: The literal-name match is case-insensitive through in:anycase.
- KQL – Defender XDR: A process the sensor did not observe starting is not captured.
- KQL – Defender XDR assumes: ProcessCommandLine holds the full command line of the created process.
// HUNT: BlackX installer inst.exe with the encrypted blob name or RC4 key argument // MITRE: T1542.003, T1140, T1027 | CONF: high FP: low COST: low // REQUIRES: process creation with command line (ProcessRollup2) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: very low; PVMDIJGKAX2 and the key are constants from the Securelist report #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | FileName=/^inst\.exe$/i | CommandLine=/PVMDIJGKAX2|Q46F6MDLI3RX2KV1/i | table([@timestamp, aid, ComputerName, UserName, ImageFileName, CommandLine, ParentBaseFileName, SHA256HashData], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timeevent.type: Event typetgt.process.name: Created process nametgt.process.cmdline: Created command line
Recommended fields
src.process.name: Creator process
Optional fields
tgt.process.image.sha256: Hash. Population varies by agent version.
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Process Creation' tgt.process.cmdline = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.cmdline
// HUNT: BlackX installer inst.exe with the encrypted blob name or RC4 key argument
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1542.003, T1140, T1027
// CONF: high | FP: low
// FALSE POSITIVES: very low; PVMDIJGKAX2 and the key are constants from the Securelist report
// EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate: the created process is inst.exe and its command line carries the blob name or the RC4 key. On a Process Creation event the created process is tgt.process.*. matches is case-insensitive, which reproduces the CQL /i intent.
// REQUIRES: SentinelOne Process Creation events with the command line populated
// TUNING: None expected: both strings are constants from the report. Exclude nothing without a confirmed benign installer.
// LOOKBACK: 30d; set in the console time picker
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A launch the agent did not observe is not captured.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.name in:anycase ('inst.exe') tgt.process.cmdline matches 'PVMDIJGKAX2|Q46F6MDLI3RX2KV1'
| sort -event.time
| limit 200
| columns event.time, endpoint.name, src.process.user, tgt.process.image.path, tgt.process.cmdline, src.process.name, tgt.process.image.sha256Automated 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
Optional fields
SHA256: Hash. SHA256 is often unpopulated in DeviceProcessEvents; SHA1 is the safer pivot.
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, ProcessCommandLine | take 5
// HUNT: BlackX installer inst.exe with the encrypted blob name or RC4 key argument // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1542.003, T1140, T1027 // CONF: high | FP: low // FALSE POSITIVES: very low; PVMDIJGKAX2 and the key are constants from the Securelist report // EQUIVALENCE: equivalent-with-schema-assumptions - Same process-creation predicate on DeviceProcessEvents: the created process is inst.exe and its command line carries the blob name or the RC4 key. contains is case-insensitive, which reproduces the CQL /i intent. // REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents) // TUNING: None expected: both strings are constants from the report. // LOOKBACK: 30d; Advanced Hunting retention is 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 =~ "inst.exe" | where ProcessCommandLine contains "PVMDIJGKAX2" or ProcessCommandLine contains "Q46F6MDLI3RX2KV1" | project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, SHA1, SHA256 | sort by Timestamp desc | take 200
Looks for: Catches a renamed blob or a rotated key: inst.exe run from a ProgramData path with exactly two alphanumeric arguments, the second 12 or more characters (the RC4 key position). FP: low; few installers take a bare blob plus key. The two-argument shape is inferred from the single observed command line.
Known limitations and deployment notes
- PowerQuery: A launch the agent did not observe is not captured.
- PowerQuery assumes: tgt.process.image.path holds the full image path.
- PowerQuery assumes: tgt.process.cmdline holds the full command line of the created process.
- KQL – Defender XDR: A process the sensor did not observe starting is not captured.
- KQL – Defender XDR assumes: FolderPath holds the full image path of the created process.
- KQL – Defender XDR assumes: ProcessCommandLine holds the full command line of the created process.
// HUNT: inst.exe in ProgramData launched with a blob argument and a long key argument // MITRE: T1542.003, T1036.005 | CONF: medium FP: low COST: low // REQUIRES: process creation with command line (ProcessRollup2) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: software installers that stage inst.exe under ProgramData and pass an ID plus a licence key #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | FileName=/^inst\.exe$/i | ImageFileName=/\\ProgramData\\/i | CommandLine=/inst\.exe"?\s+"?[A-Za-z0-9]{6,}"?\s+"?[A-Za-z0-9]{12,}"?\s*$/i | table([@timestamp, aid, ComputerName, UserName, ImageFileName, CommandLine, ParentBaseFileName, SHA256HashData], limit=200)
5 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timeevent.type: Event typetgt.process.name: Created process nametgt.process.image.path: Created process pathtgt.process.cmdline: Created command line
Recommended fields
src.process.name: Creator process
Optional fields
tgt.process.image.sha256: Hash. Population varies by agent version.
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Process Creation' tgt.process.cmdline = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.image.path, tgt.process.cmdline
// HUNT: inst.exe in ProgramData launched with a blob argument and a long key argument
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1542.003, T1036.005
// CONF: medium | FP: low
// FALSE POSITIVES: software installers that stage inst.exe under ProgramData and pass an ID plus a licence key
// EQUIVALENCE: equivalent-with-schema-assumptions - Same shape: inst.exe created from a ProgramData path with a short ID argument and a long key argument as the last two tokens. The created process is tgt.process.*. matches is case-insensitive, which reproduces the CQL /i intent.
// REQUIRES: SentinelOne Process Creation events with the image path and command line populated
// TUNING: Exclude software installers that stage inst.exe under ProgramData after a baseline review.
// LOOKBACK: 30d; set in the console time picker
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A launch the agent did not observe is not captured.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.name in:anycase ('inst.exe') tgt.process.image.path matches '\\\\ProgramData\\\\' tgt.process.cmdline matches 'inst\\.exe"?\\s+"?[A-Za-z0-9]{6,}"?\\s+"?[A-Za-z0-9]{12,}"?\\s*$'
| sort -event.time
| limit 200
| columns event.time, endpoint.name, src.process.user, tgt.process.image.path, tgt.process.cmdline, src.process.name, tgt.process.image.sha256Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameFolderPath: Created process pathProcessCommandLine: Created command line
Recommended fields
InitiatingProcessFileName: Initiating process
Optional fields
SHA256: Hash. SHA256 is often unpopulated in DeviceProcessEvents; 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, ProcessCommandLine | take 5
// HUNT: inst.exe in ProgramData launched with a blob argument and a long key argument
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1542.003, T1036.005
// CONF: medium | FP: low
// FALSE POSITIVES: software installers that stage inst.exe under ProgramData and pass an ID plus a licence key
// EQUIVALENCE: equivalent-with-schema-assumptions - Same shape on DeviceProcessEvents: inst.exe created from a ProgramData path with a short ID argument and a long key argument as the last two tokens. contains and the (?i) prefix reproduce the CQL /i intent.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: Exclude software installers that stage inst.exe under ProgramData after a baseline review.
// LOOKBACK: 30d; Advanced Hunting retention is 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 =~ "inst.exe"
| where FolderPath contains "\\ProgramData\\"
| where ProcessCommandLine matches regex @"(?i)inst\.exe\x22?\s+\x22?[A-Za-z0-9]{6,}\x22?\s+\x22?[A-Za-z0-9]{12,}\x22?\s*$"
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, SHA1, SHA256
| sort by Timestamp desc
| take 200Looks for: A process named googleupdate whose image path is not under a Google\Update directory. BlackX drops its copy (original name jcef_helper.exe) beside a malicious DLL and v8_context_snapshot.bin. FP: low; the genuine updater lives under Google\Update. Hunt this sideload context, never block the stock binary.
Known limitations and deployment notes
- PowerQuery: A launch the agent did not observe is not captured.
- PowerQuery assumes: tgt.process.image.path holds the full image path.
- KQL – Defender XDR: A process the sensor did not observe starting is not captured.
- KQL – Defender XDR assumes: FolderPath holds the full image path of the created process.
// HUNT: googleupdate.exe executing from a path other than a Google Update directory (DLL sideload host) // MITRE: T1574.002, T1036.005 | CONF: medium FP: low COST: low // REQUIRES: process creation with command line and image path (ProcessRollup2) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: portable or repackaged Google software run from a custom folder // TUNING: if a managed Chrome fleet installs Update to a custom root, add that root to the ImageFileName exclusion #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | FileName=/^googleupdate(\.exe)?$/i | ImageFileName!=/\\Google\\Update\\/i | table([@timestamp, aid, ComputerName, UserName, ImageFileName, CommandLine, ParentBaseFileName, MD5HashData, SHA256HashData], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timeevent.type: Event typetgt.process.name: Created process nametgt.process.image.path: Created process path
Recommended fields
src.process.name: Creator process
Optional fields
tgt.process.image.md5: Hash. Population varies by agent version.
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
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: googleupdate.exe executing from a path other than a Google Update directory (DLL sideload host) // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1574.002, T1036.005 // CONF: medium | FP: low // FALSE POSITIVES: portable or repackaged Google software run from a custom folder // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: the created process is googleupdate and its image path is not under a Google Update directory. The created process is tgt.process.*. A null path also passes the negation, as in the CQL. // REQUIRES: SentinelOne Process Creation events with the image path populated // TUNING: If a managed Chrome fleet installs Update to a custom root, add that root to the path exclusion. // LOOKBACK: 30d; set in the console time picker // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A launch the agent did not observe is not captured. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' tgt.process.name matches '^googleupdate(\\.exe)?$' !(tgt.process.image.path matches '\\\\Google\\\\Update\\\\') | sort -event.time | limit 200 | columns event.time, endpoint.name, src.process.user, tgt.process.image.path, tgt.process.cmdline, src.process.name, tgt.process.image.md5, tgt.process.image.sha256
Automated 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
MD5: Hash. Hash columns are a pivot only; this hunt does not depend on them.
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, FolderPath | take 5
// HUNT: googleupdate.exe executing from a path other than a Google Update directory (DLL sideload host)
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1574.002, T1036.005
// CONF: medium | FP: low
// FALSE POSITIVES: portable or repackaged Google software run from a custom folder
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate on DeviceProcessEvents: the created process is googleupdate and its path is not under a Google Update directory. !contains is case-insensitive, which reproduces the CQL /i intent.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: If a managed Chrome fleet installs Update to a custom root, add that root to the path exclusion.
// LOOKBACK: 30d; Advanced Hunting retention is 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~ ("googleupdate.exe", "googleupdate")
| where FolderPath !contains "\\Google\\Update\\"
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, MD5, SHA1
| sort by Timestamp desc
| take 200Looks for: Any process whose MD5 matches the helper Kaspersky names, but whose file name is not jcef_helper. The hash alone is the stock helper bundled with Chromium Embedded Framework apps, so the rename is the signal. FP: low; vendors rarely rename it. A match on the unrenamed name means only that the helper is present, not that it is malicious.
Known limitations and deployment notes
- PowerQuery: Where the agent does not populate MD5 on process creation, this hunt returns nothing.
- PowerQuery assumes: tgt.process.image.md5 is populated on the tenant's agent version.
- KQL – Defender XDR: Where the sensor does not populate MD5 the hunt returns nothing; hash columns are not guaranteed.
- KQL – Defender XDR assumes: MD5 is populated in DeviceProcessEvents on the tenant.
// HUNT: jcef_helper.exe hash executing under a different file name (googleupdate.exe in BlackX) // MITRE: T1574.002, T1036.003 | CONF: high FP: low COST: low // REQUIRES: process creation with MD5 hash (ProcessRollup2) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: a vendor that ships the same helper under a product-specific name // NOTE: the hash is the legitimate helper. Never block it by hash; hunt the rename and the directory it sits in. #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | MD5HashData=/^AF8A983B9ADA07EAE1259BF2953ABD40$/i | FileName!=/^jcef_helper(\.exe)?$/i | table([@timestamp, aid, ComputerName, UserName, FileName, ImageFileName, CommandLine, ParentBaseFileName, MD5HashData], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timeevent.type: Event typetgt.process.image.md5: Created process MD5tgt.process.name: Created process name
Recommended fields
tgt.process.image.path: Created process path
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Process Creation' tgt.process.image.md5 = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.image.md5
// HUNT: jcef_helper.exe hash executing under a different file name (googleupdate.exe in BlackX)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1574.002, T1036.003
// CONF: high | FP: low
// FALSE POSITIVES: a vendor that ships the same helper under a product-specific name
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a created process whose MD5 is the legitimate jcef_helper hash but whose name is not jcef_helper. The created process is tgt.process.*.
// REQUIRES: SentinelOne Process Creation events with the MD5 populated
// TUNING: Exclude a vendor that ships the same helper under a product-specific name. Never block this hash: it is the legitimate helper.
// LOOKBACK: 30d; set in the console time picker
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Where the agent does not populate MD5 on process creation, this hunt returns nothing.
// VALIDATION LEVEL: static-reviewed
event.type = 'Process Creation' tgt.process.image.md5 in:anycase ('AF8A983B9ADA07EAE1259BF2953ABD40') !(tgt.process.name matches '^jcef_helper(\\.exe)?$')
| sort -event.time
| limit 200
| columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.image.path, tgt.process.cmdline, src.process.name, tgt.process.image.md5Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeMD5: Created process MD5FileName: Created process name
Recommended fields
FolderPath: Created process path
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, MD5 | take 5
// HUNT: jcef_helper.exe hash executing under a different file name (googleupdate.exe in BlackX)
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1574.002, T1036.003
// CONF: high | FP: low
// FALSE POSITIVES: a vendor that ships the same helper under a product-specific name
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate on DeviceProcessEvents: the created process carries the legitimate jcef_helper MD5 but not that name. MD5 is a documented column of the table.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: Exclude a vendor that ships the same helper under a product-specific name. Never block this hash: it is the legitimate helper.
// LOOKBACK: 30d; Advanced Hunting retention is 30d
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Where the sensor does not populate MD5 the hunt returns nothing; hash columns are not guaranteed.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceProcessEvents
| where Timestamp >= ago(30d)
| where MD5 =~ "AF8A983B9ADA07EAE1259BF2953ABD40"
| where FileName !in~ ("jcef_helper.exe", "jcef_helper")
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessFileName, MD5
| sort by Timestamp desc
| take 200Looks for: Any DNS lookup for the C2 host the Securelist report names, including subdomains. FP: low; no benign use is known. Single-sourced, so the matching IOC row ships as detect.
Known limitations and deployment notes
- PowerQuery: Lookups made by a process the agent does not attribute are still returned but show no process name.
- PowerQuery assumes: event.dns.request is the populated DNS name field; some schema versions use dns.request instead.
- KQL – Defender XDR: Advanced Hunting keeps 30 days; the CQL tab covers 90d.
- KQL – Defender XDR: DnsQueryResponse coverage depends on the sensor build.
- KQL – Defender XDR assumes: The DnsQueryResponse action records the looked-up name under DnsQueryString or QueryName in AdditionalFields.
// HUNT: DNS lookups for the BlackX Rust payload C2 domain // MITRE: T1071.001, T1105 | CONF: high FP: low COST: low // REQUIRES: DNS lookup with requesting process (DnsRequest) // LOOKBACK: 90d (set in the console time picker, not in the query) // FALSE POSITIVES: researchers and sinkhole traffic #event_simpleName=DnsRequest | DomainName=/(^|\.)archivetj\.com$/i | table([@timestamp, aid, ComputerName, UserName, DomainName, ContextBaseFileName], limit=200)
3 required fields · View requirements
Required telemetry
- DNS Resolved
Required fields
event.time: Event timeevent.type: Event typeevent.dns.request: DNS request name
Recommended fields
src.process.name: Requesting process
Fallbacks
event.dns.request→dns.request: Some schema versions populate only the shorter name.
Readiness test
event.type = 'DNS Resolved' event.dns.request = * | limit 5 | columns event.time, event.type, event.dns.request, src.process.name
// HUNT: DNS lookups for the BlackX Rust payload C2 domain
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1071.001, T1105
// CONF: high | FP: low
// FALSE POSITIVES: researchers and sinkhole traffic
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a DNS lookup for archivetj.com or any subdomain of it. The acting process on a DNS event is src.process.*.
// REQUIRES: SentinelOne DNS Resolved events with the request name populated
// TUNING: Expect researchers and sinkhole traffic; confirm the requesting process before escalating.
// LOOKBACK: 90d; set in the console time picker
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Lookups made by a process the agent does not attribute are still returned but show no process name.
// VALIDATION LEVEL: static-reviewed
event.type = 'DNS Resolved' (event.dns.request in:anycase ('archivetj.com') or event.dns.request matches '\\.archivetj\\.com$')
| sort -event.time
| limit 200
| columns event.time, endpoint.name, src.process.user, event.dns.request, src.process.nameAutomated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: Action typeAdditionalFields: DNS details
Recommended fields
InitiatingProcessFileName: Requesting process
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: DNS lookups for the BlackX Rust payload C2 domain // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1071.001, T1105 // CONF: high | FP: low // FALSE POSITIVES: researchers and sinkhole traffic // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a DNS lookup for archivetj.com or any subdomain of it. Defender has no endpoint DNS table, so the name is read from the DnsQueryResponse action in DeviceEvents. // REQUIRES: Defender for Endpoint network telemetry with DnsQueryResponse actions in DeviceEvents // TUNING: Expect researchers and sinkhole traffic; confirm the requesting process before escalating. // LOOKBACK: 30d (Advanced Hunting retention; the CQL tab covers 90d) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Advanced Hunting keeps 30 days; the CQL tab covers 90d. DnsQueryResponse coverage depends on the sensor build. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; 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 =~ "archivetj.com" or DnsName endswith ".archivetj.com" | project Timestamp, ReportId, DeviceId, DeviceName, DnsName, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: The genuine updater talks only to Google hosts. A googleupdate process resolving anything else is the sideload host beaconing. FP: low; the exclusion covers the common Google domains.
Known limitations and deployment notes
- PowerQuery: A lookup the agent does not attribute to a process is not captured.
- PowerQuery assumes: event.dns.request is the populated DNS name field; some schema versions use dns.request instead.
- KQL – Defender XDR: DnsQueryResponse coverage depends on the sensor build.
- KQL – Defender XDR assumes: The DnsQueryResponse action records the looked-up name under DnsQueryString or QueryName in AdditionalFields.
// HUNT: googleupdate process resolving names outside Google-owned domains // MITRE: T1071.001, T1574.002 | CONF: medium FP: low COST: low // REQUIRES: DNS lookup with requesting process (DnsRequest) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: captive-portal or proxy-discovery lookups made by the genuine updater // TUNING: add any internal proxy or PAC hostnames your Chrome fleet resolves to the DomainName exclusion #event_simpleName=DnsRequest | ContextBaseFileName=/^googleupdate(\.exe)?$/i | DomainName!=/(^|\.)(google|googleapis|gvt1|gvt2|gstatic|googleusercontent)\.com$/i | table([@timestamp, aid, ComputerName, UserName, DomainName, ContextBaseFileName], limit=200)
4 required fields · View requirements
Required telemetry
- DNS Resolved
Required fields
event.time: Event timeevent.type: Event typesrc.process.name: Requesting processevent.dns.request: DNS request name
Fallbacks
event.dns.request→dns.request: Some schema versions populate only the shorter name.
Readiness test
event.type = 'DNS Resolved' event.dns.request = * | limit 5 | columns event.time, event.type, src.process.name, event.dns.request
// HUNT: googleupdate process resolving names outside Google-owned domains // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1071.001, T1574.002 // CONF: medium | FP: low // FALSE POSITIVES: captive-portal or proxy-discovery lookups made by the genuine updater // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a DNS lookup made by a googleupdate process for a name outside the Google-owned domains. The requesting process on a DNS event is src.process.*. // REQUIRES: SentinelOne DNS Resolved events with the requesting process populated // TUNING: Add internal proxy or PAC hostnames the Chrome fleet resolves to the name exclusion. // LOOKBACK: 30d; set in the console time picker // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A lookup the agent does not attribute to a process is not captured. // VALIDATION LEVEL: static-reviewed event.type = 'DNS Resolved' src.process.name matches '^googleupdate(\\.exe)?$' !(event.dns.request matches '(^|\\.)(google|googleapis|gvt1|gvt2|gstatic|googleusercontent)\\.com$') | sort -event.time | limit 200 | columns event.time, endpoint.name, src.process.user, event.dns.request, src.process.name
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: Action typeInitiatingProcessFileName: Requesting processAdditionalFields: DNS details
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "DnsQueryResponse" | project Timestamp, ActionType, InitiatingProcessFileName, AdditionalFields | take 5
// HUNT: googleupdate process resolving names outside Google-owned domains
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1071.001, T1574.002
// CONF: medium | FP: low
// FALSE POSITIVES: captive-portal or proxy-discovery lookups made by the genuine updater
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a DNS lookup made by a googleupdate process for a name outside the Google-owned domains. The name is read from the DnsQueryResponse action in DeviceEvents.
// REQUIRES: Defender for Endpoint network telemetry with DnsQueryResponse actions in DeviceEvents
// TUNING: Add internal proxy or PAC hostnames the Chrome fleet resolves to the name exclusion.
// LOOKBACK: 30d; Advanced Hunting retention is 30d
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: DnsQueryResponse coverage depends on the sensor build.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceEvents
| where Timestamp >= ago(30d)
| where ActionType == "DnsQueryResponse"
| where InitiatingProcessFileName in~ ("googleupdate.exe", "googleupdate")
| extend DnsName = tostring(coalesce(parse_json(AdditionalFields)["DnsQueryString"], parse_json(AdditionalFields)["QueryName"]))
| where not(DnsName matches regex @"(?i)(^|\.)(google|googleapis|gvt1|gvt2|gstatic|googleusercontent)\.com$")
| project Timestamp, ReportId, DeviceId, DeviceName, DnsName, InitiatingProcessFileName
| sort by Timestamp desc
| take 200Looks for: The BlackX RAT uses Google Drive, OneDrive and Yandex.Disk as its C2 channel. This groups lookups for the storage API hosts by requesting process and drops browsers and the sync clients. The hostnames are inferred from the three service names; the report does not list them. FP: medium; many line-of-business apps call the Google and Microsoft APIs. Rank by rarity of the process across hosts, not by volume.
Known limitations and deployment notes
- PowerQuery: A lookup the agent does not attribute to a process is grouped under an empty process name.
- PowerQuery assumes: event.dns.request is the populated DNS name field; some schema versions use dns.request instead.
- PowerQuery assumes: The hostnames are inferred from the service names in the report.
- KQL – Defender XDR: DnsQueryResponse coverage depends on the sensor build.
- KQL – Defender XDR assumes: The DnsQueryResponse action records the looked-up name under DnsQueryString or QueryName in AdditionalFields.
- KQL – Defender XDR assumes: The hostnames are inferred from the service names in the report.
// HUNT: Non-client processes resolving Google Drive, OneDrive or Yandex.Disk API hosts // MITRE: T1102.002, T1567.002 | CONF: medium FP: medium COST: medium // REQUIRES: DNS lookup with requesting process (DnsRequest) // LOOKBACK: 14d (set in the console time picker, not in the query) // FALSE POSITIVES: line-of-business apps, backup agents and scripts that use Google or Microsoft storage APIs // TUNING: after a one-week baseline, exclude the signed business apps that show up on many hosts and keep the rare ones // NOTE: the hostnames are inferred (the report names the services, not the hosts); validate against your proxy logs #event_simpleName=DnsRequest | DomainName=/^(drive\.google\.com|www\.googleapis\.com|api\.onedrive\.com|onedrive\.live\.com|graph\.microsoft\.com|cloud-api\.yandex\.net|disk\.yandex\.(com|ru)|webdav\.yandex\.(com|ru))$/i | ContextBaseFileName!=/^(chrome|msedge|firefox|brave|opera|iexplore|msedgewebview2|onedrive|googledrivefs|yandexdisk|yandex|ms-teams|teams|outlook|winword|excel|powerpnt|olk)(\.exe)?$/i | groupBy([ComputerName, ContextBaseFileName, DomainName], function=[count(as=Lookups), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)], limit=1000) | sort(Lookups, order=desc, limit=200)
4 required fields · View requirements
Required telemetry
- DNS Resolved
Required fields
event.time: Event timeevent.type: Event typeevent.dns.request: DNS request namesrc.process.name: Requesting process
Recommended fields
endpoint.name: Host
Fallbacks
event.dns.request→dns.request: Some schema versions populate only the shorter name.
Readiness test
event.type = 'DNS Resolved' event.dns.request = * | limit 5 | columns event.time, event.type, src.process.name, event.dns.request
// HUNT: Non-client processes resolving Google Drive, OneDrive or Yandex.Disk API hosts // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1102.002, T1567.002 // CONF: medium | FP: medium // FALSE POSITIVES: line-of-business apps, backup agents and scripts that use Google or Microsoft storage APIs // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: lookups for the Google Drive, OneDrive and Yandex.Disk API hosts by a process outside the list of known clients, counted per host, process and name. The requesting process on a DNS event is src.process.*. The CQL anchors the host list on both ends, so an exact in:anycase match is equivalent. // REQUIRES: SentinelOne DNS Resolved events with the requesting process populated // TUNING: After a one-week baseline, exclude the signed business apps that show up on many hosts and keep the rare ones. The hostnames are inferred from the report, so validate them against proxy logs. // LOOKBACK: 14d; set in the console time picker // CONFIGURATION: No lookup objects required. // KNOWN GAPS: A lookup the agent does not attribute to a process is grouped under an empty process name. // VALIDATION LEVEL: static-reviewed event.type = 'DNS Resolved' event.dns.request matches '^(drive\\.google\\.com|www\\.googleapis\\.com|api\\.onedrive\\.com|onedrive\\.live\\.com|graph\\.microsoft\\.com|cloud-api\\.yandex\\.net|disk\\.yandex\\.(com|ru)|webdav\\.yandex\\.(com|ru))$' !(src.process.name matches '^(chrome|msedge|firefox|brave|opera|iexplore|msedgewebview2|onedrive|googledrivefs|yandexdisk|yandex|ms-teams|teams|outlook|winword|excel|powerpnt|olk)(\\.exe)?$') | group lookups=count(), first_seen=min(event.time), last_seen=max(event.time) by endpoint.name, src.process.name, event.dns.request | sort -lookups | limit 200
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: Action typeInitiatingProcessFileName: Requesting processAdditionalFields: DNS details
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, InitiatingProcessFileName, AdditionalFields | take 5
// HUNT: Non-client processes resolving Google Drive, OneDrive or Yandex.Disk API hosts // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1102.002, T1567.002 // CONF: medium | FP: medium // FALSE POSITIVES: line-of-business apps, backup agents and scripts that use Google or Microsoft storage APIs // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: lookups for the Google Drive, OneDrive and Yandex.Disk API hosts by a process outside the list of known clients, counted per host, process and name. The name is read from the DnsQueryResponse action in DeviceEvents. // REQUIRES: Defender for Endpoint network telemetry with DnsQueryResponse actions in DeviceEvents // TUNING: After a one-week baseline, exclude the signed business apps that show up on many hosts and keep the rare ones. The hostnames are inferred from the report, so validate them against proxy logs. // LOOKBACK: 14d; extend to 30d for the incident window // CONFIGURATION: No lookup objects required. // KNOWN GAPS: DnsQueryResponse coverage depends on the sensor build. // 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 matches regex @"(?i)^(drive\.google\.com|www\.googleapis\.com|api\.onedrive\.com|onedrive\.live\.com|graph\.microsoft\.com|cloud-api\.yandex\.net|disk\.yandex\.(com|ru)|webdav\.yandex\.(com|ru))$" | where not(InitiatingProcessFileName matches regex @"(?i)^(chrome|msedge|firefox|brave|opera|iexplore|msedgewebview2|onedrive|googledrivefs|yandexdisk|yandex|ms-teams|teams|outlook|winword|excel|powerpnt|olk)(\.exe)?$") | summarize Lookups = count(), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by DeviceName, InitiatingProcessFileName, DnsName | sort by Lookups desc | take 200
Looks for: Microsoft's revocation steps start the built-in Secure-Boot-Update task. The Securelist text says a task of that name is created; this flags any registration of that name other than the native \Microsoft\Windows\PI\ task. FP: low. If your sensor reports the task name without its folder, the exclusion will not match and the genuine task will show; pivot on TaskExecutable then.
Known limitations and deployment notes
- PowerQuery: SentinelOne cannot show a scheduled task registered outside its native path here.
- KQL – Defender XDR: Servicing that re-registers the native task under another path would match; the CQL has the same property.
- KQL – Defender XDR assumes: The ScheduledTaskCreated action records the full task path under TaskName in AdditionalFields.
- KQL – Defender XDR assumes: ScheduledTaskCreated is attested in Microsoft-owned hunting repositories, not on the Learn table page.
// HUNT: scheduled task named Secure-Boot-Update registered outside the native Microsoft path // MITRE: T1053.005, T1036.004 | CONF: medium FP: low COST: low // REQUIRES: scheduled task registration (ScheduledTaskRegistered) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: servicing that re-registers the native task // TUNING: if TaskName carries no folder on your sensor build, drop the second filter and instead exclude the genuine TaskExecutable #event_simpleName=ScheduledTaskRegistered | TaskName=/Secure-Boot-Update/i | TaskName!=/^\\Microsoft\\Windows\\PI\\Secure-Boot-Update$/i | table([@timestamp, aid, ComputerName, UserName, TaskName, TaskExecutable, TaskAuthor], limit=200)
1 required field · View requirements
Required telemetry
- none
Required fields
event.type: Event type
Readiness test
event.type = 'Process Creation' | limit 5 | columns event.type
// HUNT: scheduled task named Secure-Boot-Update registered outside the native Microsoft path // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1053.005, T1036.004 // CONF: medium | FP: low // FALSE POSITIVES: servicing that re-registers the native task // EQUIVALENCE: unsupported-without-redesign - The hunt reads the scheduled-task registration event and its task name. The field model attests no SentinelOne event type or task name field for scheduled-task registration, so any query written here would evaluate to null and read as a clean estate. // REQUIRES: A SentinelOne scheduled-task event with a task name field, confirmed on the tenant // TUNING: Use the CQL tab for this card, or the Defender KQL tab if that platform is deployed. // LOOKBACK: 30d on the CQL tab // CONFIGURATION: Use the CQL tab for this card. // KNOWN GAPS: SentinelOne cannot show a scheduled task registered outside its native path here. // VALIDATION LEVEL: static-reviewed
Automated validation: static-passed
3 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: Action typeAdditionalFields: Task details
Recommended fields
InitiatingProcessFileName: Registering process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "ScheduledTaskCreated" | project Timestamp, ActionType, AdditionalFields | take 5
// HUNT: scheduled task named Secure-Boot-Update registered outside the native Microsoft path // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1053.005, T1036.004 // CONF: medium | FP: low // FALSE POSITIVES: servicing that re-registers the native task // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a scheduled task whose name contains Secure-Boot-Update but is not the native task path. The task name is read from the ScheduledTaskCreated action in DeviceEvents. // REQUIRES: Defender for Endpoint telemetry with ScheduledTaskCreated actions in DeviceEvents // TUNING: If TaskName carries no folder on your sensor build, drop the exact-path filter and instead exclude the genuine task by its action. // LOOKBACK: 30d; Advanced Hunting retention is 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Servicing that re-registers the native task under another path would match; the CQL has the same property. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceEvents | where Timestamp >= ago(30d) | where ActionType == "ScheduledTaskCreated" | extend TaskName = tostring(parse_json(AdditionalFields)["TaskName"]) | where TaskName contains "Secure-Boot-Update" | where TaskName !~ "\\Microsoft\\Windows\\PI\\Secure-Boot-Update" | project Timestamp, ReportId, DeviceId, DeviceName, TaskName, InitiatingProcessFileName, InitiatingProcessCommandLine | sort by Timestamp desc | take 200
Looks for: Writes to the AvailableUpdates value under Control\Secureboot, the flag Microsoft's procedure uses to trigger the DB and DBX updates. This is a posture and change-control signal, not an attacker signature: the same write is the defender's remediation. Hosts that never show it are the exposed ones. FP: medium; every legitimate rollout writes this value.
Known limitations and deployment notes
- PowerQuery: A host with no write in the window shows no row, so exposure tracking needs a host inventory to compare against.
- PowerQuery assumes: registry.keyPath holds the full key path including the control set segment.
- PowerQuery assumes: registry.value holds the written data.
- KQL – Defender XDR: Advanced Hunting keeps 30 days; the CQL tab covers 90d.
- KQL – Defender XDR: A host with no write in the window shows no row, so exposure tracking needs a device inventory to compare against.
- KQL – Defender XDR assumes: RegistryKey holds the full key path including the control set segment.
// HUNT: Writes to Secureboot AvailableUpdates (certificate revocation trigger), for change control and exposure tracking // MITRE: T1112, T1542.003 | CONF: medium FP: medium COST: low // REQUIRES: registry value writes (RegGenericValueUpdate, AsepValueUpdate) // LOOKBACK: 90d (set in the console time picker, not in the query) // FALSE POSITIVES: the sanctioned Secure Boot certificate rollout, Windows servicing, imaging tools // TUNING: join the host list to your change ticket for the rollout; alert only on writers outside the approved deployment tool // NOTE: absence is the finding. Hosts with no write in 90 days have not triggered the revocation steps. #event_simpleName=/RegGenericValueUpdate|AsepValueUpdate/ | RegObjectName=/\\Control\\SecureBoot(\\|$)/i | RegValueName=/^AvailableUpdates$/i | table([@timestamp, aid, ComputerName, UserName, RegObjectName, RegValueName, RegStringValue, ContextBaseFileName], limit=200)
4 required fields · View requirements
Required telemetry
- Registry Value Modified
Required fields
event.time: Event timeevent.type: Event typeregistry.keyPath: Registry keyregistry.valueName: Registry value name
Recommended fields
src.process.name: Writing process
Optional fields
registry.value: Registry data
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Registry Value Modified' registry.keyPath = * | limit 5 | columns event.time, event.type, registry.keyPath, registry.valueName
// HUNT: Writes to Secureboot AvailableUpdates (certificate revocation trigger), for change control and exposure tracking
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1112, T1542.003
// CONF: medium | FP: medium
// FALSE POSITIVES: the sanctioned Secure Boot certificate rollout, Windows servicing, imaging tools
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a write of the AvailableUpdates value under the SecureBoot control key. The acting process on a registry event is src.process.*. matches and in:anycase reproduce the CQL /i intent.
// REQUIRES: SentinelOne Registry Value Modified events
// TUNING: Join the host list to your change ticket for the rollout and alert only on writers outside the approved deployment tool. Absence of a write is the finding for exposure tracking.
// LOOKBACK: 90d; set in the console time picker
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: A host with no write in the window shows no row, so exposure tracking needs a host inventory to compare against.
// VALIDATION LEVEL: static-reviewed
event.type = 'Registry Value Modified' registry.keyPath matches '\\\\Control\\\\SecureBoot(\\\\|$)' registry.valueName in:anycase ('AvailableUpdates')
| sort -event.time
| limit 200
| columns event.time, endpoint.name, src.process.user, registry.keyPath, registry.valueName, registry.value, src.process.nameAutomated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceRegistryEvents
Required fields
Timestamp: Event timeActionType: Action typeRegistryKey: Registry keyRegistryValueName: Registry value name
Recommended fields
InitiatingProcessFileName: Writing process
Optional fields
RegistryValueData: Registry data
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceRegistryEvents | where Timestamp > ago(1d) | where ActionType == "RegistryValueSet" | project Timestamp, ActionType, RegistryKey, RegistryValueName | take 5
// HUNT: Writes to Secureboot AvailableUpdates (certificate revocation trigger), for change control and exposure tracking // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1112, T1542.003 // CONF: medium | FP: medium // FALSE POSITIVES: the sanctioned Secure Boot certificate rollout, Windows servicing, imaging tools // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate on DeviceRegistryEvents: a value set of AvailableUpdates under the SecureBoot control key. The (?i) prefix and =~ reproduce the CQL /i intent. // REQUIRES: Defender for Endpoint registry telemetry (DeviceRegistryEvents) // TUNING: Join the host list to your change ticket for the rollout and alert only on writers outside the approved deployment tool. Absence of a write is the finding for exposure tracking. // LOOKBACK: 30d (Advanced Hunting retention; the CQL tab covers 90d) // CONFIGURATION: No lookup objects required. // KNOWN GAPS: Advanced Hunting keeps 30 days; the CQL tab covers 90d. A host with no write in the window shows no row, so exposure tracking needs a device inventory to compare against. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0 DeviceRegistryEvents | where Timestamp >= ago(30d) | where ActionType == "RegistryValueSet" | where RegistryKey matches regex @"(?i)\\Control\\SecureBoot(\\|$)" | where RegistryValueName =~ "AvailableUpdates" | project Timestamp, ReportId, DeviceId, DeviceName, InitiatingProcessAccountName, RegistryKey, RegistryValueName, RegistryValueData, InitiatingProcessFileName | sort by Timestamp desc | take 200
Looks for: Command lines that mount the EFI system partition, rewrite boot files or alter boot-manager and integrity settings. BlackX writes files to the system and UEFI partitions; the report does not list the commands it uses, so this is an inferred behavioural hunt. FP: high; imaging, recovery and OS servicing use these tools, including Microsoft's own recovery steps.
Known limitations and deployment notes
- PowerQuery: High false-positive risk on imaging and recovery workflows; expect tuning.
- PowerQuery assumes: tgt.process.cmdline holds the full command line of the created process.
- PowerQuery assumes: The command-line patterns are inferred behaviour, not named in the report.
- KQL – Defender XDR: High false-positive risk on imaging and recovery workflows; expect tuning.
- KQL – Defender XDR assumes: ProcessCommandLine holds the full command line of the created process.
- KQL – Defender XDR assumes: The command-line patterns are inferred behaviour, not named in the report.
// HUNT: EFI system partition mounts, boot file rewrites and boot-integrity changes by command line // MITRE: T1542.003, T1553 | CONF: medium FP: high COST: medium // REQUIRES: process creation with command line (ProcessRollup2) // LOOKBACK: 14d (set in the console time picker, not in the query) // FALSE POSITIVES: imaging and recovery workflows, Windows servicing, OEM tools // TUNING: exclude OS servicing parents (applied below) and your imaging server accounts; keep interactive admin sessions on servers // NOTE: inferred behaviour. The Securelist report names the partitions, not the tools. #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | FileName=/^(mountvol|bcdboot|bcdedit|bootsect|powershell|pwsh)\.exe$/i | CommandLine=/mountvol(\.exe)?"?\s+\S+\s+\/s\b|bcdboot(\.exe)?"?\s+\S+\s+\/s\b|bcdedit(\.exe)?"?\s+.*(bootmgr|nointegritychecks|testsigning|loadoptions|\\EFI\\)|bootsect(\.exe)?"?\s+.*\/nt|Set-SecureBootUEFI|Format-SecureBootUEFI/i | ParentBaseFileName!=/^(TiWorker|TrustedInstaller)\.exe$/i | table([@timestamp, aid, ComputerName, UserName, FileName, CommandLine, ParentBaseFileName], limit=200)
4 required fields · View requirements
Required telemetry
- Process Creation
Required fields
event.time: Event timeevent.type: Event typetgt.process.name: Created process nametgt.process.cmdline: Created command line
Recommended fields
src.process.name: Creator process
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Process Creation' tgt.process.cmdline = * | limit 5 | columns event.time, event.type, tgt.process.name, tgt.process.cmdline
// HUNT: EFI system partition mounts, boot file rewrites and boot-integrity changes by command line // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1542.003, T1553 // CONF: medium | FP: high // FALSE POSITIVES: imaging and recovery workflows, Windows servicing, OEM tools // EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: the boot tooling or PowerShell as the created process with a command line that mounts the EFI partition, rewrites boot files or changes boot integrity, excluding OS servicing parents. On a Process Creation event the created process is tgt.process.* and its creator is src.process.*. // REQUIRES: SentinelOne Process Creation events with the command line populated // TUNING: Exclude your imaging server accounts and keep interactive admin sessions on servers. The behaviour is inferred: the report names the partitions, not the tools. // LOOKBACK: 14d; set in the console time picker // CONFIGURATION: No lookup objects required. // KNOWN GAPS: High false-positive risk on imaging and recovery workflows; expect tuning. // VALIDATION LEVEL: static-reviewed event.type = 'Process Creation' tgt.process.name matches '^(mountvol|bcdboot|bcdedit|bootsect|powershell|pwsh)\\.exe$' tgt.process.cmdline matches 'mountvol(\\.exe)?"?\\s+\\S+\\s+/s\\b|bcdboot(\\.exe)?"?\\s+\\S+\\s+/s\\b|bcdedit(\\.exe)?"?\\s+.*(bootmgr|nointegritychecks|testsigning|loadoptions|\\\\EFI\\\\)|bootsect(\\.exe)?"?\\s+.*/nt|Set-SecureBootUEFI|Format-SecureBootUEFI' !(src.process.name matches '^(TiWorker|TrustedInstaller)\\.exe$') | sort -event.time | limit 200 | columns event.time, endpoint.name, src.process.user, tgt.process.name, tgt.process.cmdline, src.process.name
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceProcessEvents
Required fields
Timestamp: Event timeFileName: Created process nameProcessCommandLine: Created command lineInitiatingProcessFileName: Initiating process
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceProcessEvents | where Timestamp > ago(1d) | project Timestamp, FileName, ProcessCommandLine, InitiatingProcessFileName | take 5
// HUNT: EFI system partition mounts, boot file rewrites and boot-integrity changes by command line
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1542.003, T1553
// CONF: medium | FP: high
// FALSE POSITIVES: imaging and recovery workflows, Windows servicing, OEM tools
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate on DeviceProcessEvents: the boot tooling or PowerShell as the created process with a command line that mounts the EFI partition, rewrites boot files or changes boot integrity, excluding OS servicing parents. The (?i) prefix reproduces the CQL /i intent.
// REQUIRES: Defender for Endpoint process-creation telemetry (DeviceProcessEvents)
// TUNING: Exclude your imaging server accounts and keep interactive admin sessions on servers. The behaviour is inferred: the report names the partitions, not the tools.
// LOOKBACK: 14d; extend to 30d for the incident window
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: High false-positive risk on imaging and recovery workflows; expect tuning.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceProcessEvents
| where Timestamp >= ago(14d)
| where FileName in~ ("mountvol.exe", "bcdboot.exe", "bcdedit.exe", "bootsect.exe", "powershell.exe", "pwsh.exe")
| where ProcessCommandLine matches regex @"(?i)mountvol(\.exe)?\x22?\s+\S+\s+/s\b|bcdboot(\.exe)?\x22?\s+\S+\s+/s\b|bcdedit(\.exe)?\x22?\s+.*(bootmgr|nointegritychecks|testsigning|loadoptions|\\EFI\\)|bootsect(\.exe)?\x22?\s+.*/nt|Set-SecureBootUEFI|Format-SecureBootUEFI"
| where InitiatingProcessFileName !in~ ("TiWorker.exe", "TrustedInstaller.exe")
| project Timestamp, ReportId, DeviceId, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc
| take 200Looks for: Kernel drivers loading from a path other than System32\drivers or the DriverStore, kept to those seen on three or fewer hosts. The BlackX driver is injected by the bootkit at boot, so the sensor may not see its load; this catches the loaded-later and fallback cases. Falcon does not expose the signer serial, so the revoked certificate is checked natively in N3. FP: medium; vendor tools and games load their own signed drivers. Validate the DriverLoad fields on your sensor build.
Known limitations and deployment notes
- PowerQuery: SentinelOne cannot show rare kernel drivers loaded from outside the driver store here.
- KQL – Defender XDR: The revoked signer serial is not queried here; check it separately.
- KQL – Defender XDR assumes: DriverLoad is recorded in DeviceEvents and FolderPath holds the driver image path.
- KQL – Defender XDR assumes: DriverLoad is not on the list of action types attested in Microsoft sources; confirm it in the portal.
// HUNT: Rare kernel drivers loaded from outside the Windows driver locations // MITRE: T1014, T1547.006 | CONF: medium FP: medium COST: medium // REQUIRES: driver load (DriverLoad). Validate field names on your sensor build. // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: vendor utilities, anti-cheat and virtualisation drivers // TUNING: baseline for a week, then exclude signed vendor drivers present on many hosts; keep the long tail // NOTE: the revoked signer serial is not queryable in Falcon; check it with native hunt N3 #event_simpleName=DriverLoad | ImageFileName!=/\\Windows\\System32\\(drivers|DriverStore)\\/i | groupBy([ImageFileName], function=[count(aid, distinct=true, as=Hosts), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)], limit=1000) | Hosts <= 3 | sort(Hosts, order=asc, limit=200)
1 required field · View requirements
Required telemetry
- none
Required fields
event.type: Event type
Readiness test
event.type = 'Process Creation' | limit 5 | columns event.type
// HUNT: Rare kernel drivers loaded from outside the Windows driver locations // SCHEMA PROFILE: sentinelone-endpoint-ocsf // MITRE: T1014, T1547.006 // CONF: medium | FP: medium // FALSE POSITIVES: vendor utilities, anti-cheat and virtualisation drivers // EQUIVALENCE: unsupported-without-redesign - The hunt reads kernel driver-load events and counts distinct hosts per driver path. The field model attests no SentinelOne driver-load event type or driver path field, so any query written here would evaluate to null and read as a clean estate. // REQUIRES: A SentinelOne driver-load event with an image path field, confirmed on the tenant // TUNING: Use the CQL tab for this card, or the Defender KQL tab if that platform is deployed. // LOOKBACK: 30d on the CQL tab // CONFIGURATION: Use the CQL tab for this card. // KNOWN GAPS: SentinelOne cannot show rare kernel drivers loaded from outside the driver store here. // VALIDATION LEVEL: static-reviewed
Automated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceEvents
Required fields
Timestamp: Event timeActionType: Action typeFolderPath: Driver pathDeviceId: Host identity
Fallbacks
DeviceId→DeviceName: Distinct counts may differ if host names are reused.
Readiness test
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "DriverLoad" | project Timestamp, ActionType, FolderPath, DeviceId | take 5
// HUNT: Rare kernel drivers loaded from outside the Windows driver locations // SCHEMA PROFILE: microsoft-defender-xdr // MITRE: T1014, T1547.006 // CONF: medium | FP: medium // FALSE POSITIVES: vendor utilities, anti-cheat and virtualisation drivers // EQUIVALENCE: equivalent-with-schema-assumptions - Same analytic: driver loads from outside the Windows driver locations, counted per distinct host and kept when three or fewer hosts loaded the driver. The load is read from the DriverLoad action in DeviceEvents. // REQUIRES: Defender for Endpoint telemetry with DriverLoad actions in DeviceEvents // TUNING: Baseline for a week, then exclude signed vendor drivers present on many hosts and keep the long tail. // LOOKBACK: 30d; Advanced Hunting retention is 30d // CONFIGURATION: No lookup objects required. // KNOWN GAPS: The revoked signer serial is not queried here; check it separately. // VALIDATION LEVEL: schema-aligned // AUTOMATED VALIDATION: static-passed; static=passed-with-warnings; fixtures=0/0 DeviceEvents | where Timestamp >= ago(30d) | where ActionType == "DriverLoad" | where FolderPath !contains "\\Windows\\System32\\drivers\\" and FolderPath !contains "\\Windows\\System32\\DriverStore\\" | summarize Hosts = dcount(DeviceId), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by FolderPath | where Hosts <= 3 | sort by Hosts asc | take 200
Looks for: BlackX's driver tampers with ETW providers from kernel mode, which the sensor cannot see. This covers only the registry-level cousin: autologger session values under Control\WMI\Autologger being changed. It is an adjacent control, not a BlackX signature. FP: medium; security tools and Windows update autologger settings.
Known limitations and deployment notes
- PowerQuery: Kernel-mode ETW tampering is not observable through registry events.
- PowerQuery assumes: registry.keyPath holds the full key path including the control set segment.
- PowerQuery assumes: registry.value holds the written data.
- KQL – Defender XDR: Kernel-mode ETW tampering is not observable through registry events.
- KQL – Defender XDR assumes: RegistryKey holds the full key path including the control set segment.
// HUNT: ETW autologger session values changed in the registry (adjacent to BlackX ETW tampering) // MITRE: T1562.006 | CONF: low FP: medium COST: low // REQUIRES: registry value writes (RegGenericValueUpdate) // LOOKBACK: 30d (set in the console time picker, not in the query) // FALSE POSITIVES: security tooling, Windows servicing, diagnostics tools // TUNING: exclude the writer processes your EDR, SIEM agent and Windows servicing use; keep unsigned or user-writable-path writers // NOTE: kernel-mode ETW tampering by the BlackX driver is not observable here; see the coverage map gap #event_simpleName=/RegGenericValueUpdate|AsepValueUpdate/ | RegObjectName=/\\Control\\WMI\\Autologger\\/i | RegValueName=/^(Start|Enabled)$/i | table([@timestamp, aid, ComputerName, UserName, RegObjectName, RegValueName, RegStringValue, ContextBaseFileName], limit=200)
4 required fields · View requirements
Required telemetry
- Registry Value Modified
Required fields
event.time: Event timeevent.type: Event typeregistry.keyPath: Registry keyregistry.valueName: Registry value name
Recommended fields
src.process.name: Writing process
Optional fields
registry.value: Registry data
Fallbacks
endpoint.name→agent.uuid: Changes the displayed host identifier only.
Readiness test
event.type = 'Registry Value Modified' registry.keyPath = * | limit 5 | columns event.time, event.type, registry.keyPath, registry.valueName
// HUNT: ETW autologger session values changed in the registry (adjacent to BlackX ETW tampering)
// SCHEMA PROFILE: sentinelone-endpoint-ocsf
// MITRE: T1562.006
// CONF: low | FP: medium
// FALSE POSITIVES: security tooling, Windows servicing, diagnostics tools
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate: a write of the Start or Enabled value under an ETW autologger key. The acting process on a registry event is src.process.*. contains and in:anycase reproduce the CQL /i intent.
// REQUIRES: SentinelOne Registry Value Modified events
// TUNING: Exclude the writer processes your EDR, SIEM agent and Windows servicing use; keep unsigned or user-writable-path writers.
// LOOKBACK: 30d; set in the console time picker
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Kernel-mode ETW tampering is not observable through registry events.
// VALIDATION LEVEL: static-reviewed
event.type = 'Registry Value Modified' registry.keyPath contains '\\Control\\WMI\\Autologger\\' registry.valueName in:anycase ('Start', 'Enabled')
| sort -event.time
| limit 200
| columns event.time, endpoint.name, src.process.user, registry.keyPath, registry.valueName, registry.value, src.process.nameAutomated validation: static-passed
4 required fields · View requirements
Required telemetry
- DeviceRegistryEvents
Required fields
Timestamp: Event timeActionType: Action typeRegistryKey: Registry keyRegistryValueName: Registry value name
Recommended fields
InitiatingProcessFileName: Writing process
Optional fields
RegistryValueData: Registry data
Fallbacks
DeviceName→DeviceId: Changes the displayed host identifier only.
Readiness test
DeviceRegistryEvents | where Timestamp > ago(1d) | where ActionType == "RegistryValueSet" | project Timestamp, ActionType, RegistryKey, RegistryValueName | take 5
// HUNT: ETW autologger session values changed in the registry (adjacent to BlackX ETW tampering)
// SCHEMA PROFILE: microsoft-defender-xdr
// MITRE: T1562.006
// CONF: low | FP: medium
// FALSE POSITIVES: security tooling, Windows servicing, diagnostics tools
// EQUIVALENCE: equivalent-with-schema-assumptions - Same predicate on DeviceRegistryEvents: a value set of Start or Enabled under an ETW autologger key. contains and in~ are case-insensitive, which reproduces the CQL /i intent.
// REQUIRES: Defender for Endpoint registry telemetry (DeviceRegistryEvents)
// TUNING: Exclude the writer processes your EDR, SIEM agent and Windows servicing use; keep unsigned or user-writable-path writers.
// LOOKBACK: 30d; Advanced Hunting retention is 30d
// CONFIGURATION: No lookup objects required.
// KNOWN GAPS: Kernel-mode ETW tampering is not observable through registry events.
// VALIDATION LEVEL: schema-aligned
// AUTOMATED VALIDATION: static-passed; static=passed; fixtures=0/0
DeviceRegistryEvents
| where Timestamp >= ago(30d)
| where ActionType == "RegistryValueSet"
| where RegistryKey contains "\\Control\\WMI\\Autologger\\"
| where RegistryValueName in~ ("Start", "Enabled")
| project Timestamp, ReportId, DeviceId, DeviceName, InitiatingProcessAccountName, RegistryKey, RegistryValueName, RegistryValueData, InitiatingProcessFileName
| sort by Timestamp desc
| take 200Detection Rules by Platform
Every IOA candidate ships as Detect. The sideload host is a legitimate binary, the C2 domain is single-sourced, and the boot tooling is also used by administrators. None is recommended for Prevent.
CrowdStrike: Custom IOA
| IOA name | Pattern | Exclusions | Path |
|---|---|---|---|
| BlackX installer launch | Promote Q1, Q2: image name inst.exe with command line containing PVMDIJGKAX2, or a ProgramData path with a blob argument and a 12+ character key | None expected | Detect |
| Google updater sideload host | Promote Q3, Q4: image name googleupdate outside a Google\Update path, or the helper hash under another name | Custom Chrome update roots | Detect only (legitimate binary) |
| Lookalike Secure-Boot-Update task | Promote Q8: scheduled task named Secure-Boot-Update outside \Microsoft\Windows\PI\ | None expected | Detect |
| Rust payload and sideload host DNS | Promote Q5, Q6: DNS lookup for the C2 domain, or googleupdate resolving non-Google names | Proxy and PAC hostnames | Detect |
prevent. No second independent source corroborates any BlackX indicator, and the one hash belongs to a legitimate product binary.SentinelOne: custom detection rules
| Rule | Source query | Run as | Notes |
|---|---|---|---|
| BlackX installer launch | Q1, Q2, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device" |
| Google updater sideload host | Q3, Q4, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device" |
| Rust payload and sideload host DNS | Q5, Q6, PowerQuery tab | Scheduled custom detection rule | Bind entities so the alert names the host instead of "Unknown Device" |
No SentinelOne query exists for: Lookalike Secure-Boot-Update task.
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 |
|---|---|---|---|
| BlackX installer launch | Q1, Q2, 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 |
| Google updater sideload host | Q3, 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 |
| Lookalike Secure-Boot-Update task | Q8, 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 |
| Rust payload and sideload host DNS | 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 |
Q7, Q9, Q10, Q11 and Q12 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
Grouped IOC Quick-Copy
One-click blocks. Every atomic indicator traces to a saved source snapshot. No row is set to prevent: nothing is corroborated by a second independent source. Placeholder rows hold hashes no source published; delete them before importing.
type,value,action,severity,expiration,description,tags domain,www.archivetj.com,detect,high,2027-04-23,BlackX Rust payload C2 (Securelist; SecurityOnline restates it),campaign:BlackX md5,af8a983b9ada07eae1259bf2953abd40,detect,low,2027-04-23,Stock jcef_helper.exe Chromium helper abused as googleupdate.exe: match means present only so validate the rename (Q4) and never prevent,campaign:BlackX sha256,REPLACE_WITH_INST_EXE_SHA256,detect,high,2027-04-23,inst.exe installer hash not published in any fetched source,campaign:BlackX sha256,REPLACE_WITH_OXIDLLRUNNER_SHA256,detect,high,2027-04-23,OxiDLLRunner DLL hash not published in any fetched source,campaign:BlackX
indicatorType,indicatorValue,action,title,description,expirationTime,severity,recommendedActions,rbacGroups,category,mitretechniques,GenerateAlert DomainName,www.archivetj.com,Audit,BlackX Rust payload C2,BlackX Rust payload C2 (Securelist; SecurityOnline restates it),2027-04-23T00: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. Left out because this block maps only SHA-1, SHA-256, IPv4, domain and URL indicators: md5 1. Left out because the value is a placeholder, defanged or not valid for its type (fix it in the pack's CSV first): placeholder 2. 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.
inst.exe in a ProgramData path, command line: <blob> <16-character key> (observed: PVMDIJGKAX2 Q46F6MDLI3RX2KV1) googleupdate.exe (original name jcef_helper.exe) running outside a Google\Update directory (legitimate binary: hunt the context, never block the stock file) v8_context_snapshot.bin in the same folder as googleupdate.exe, outside a browser or Electron app install googleupdate.exe resolving or connecting to anything that is not a Google domain DNS lookup for www.archivetj.com or any subdomain Non-browser, non-sync-client process resolving Google Drive, OneDrive or Yandex.Disk API hosts Scheduled task named Secure-Boot-Update outside \Microsoft\Windows\PI\ Writes to HKLM\SYSTEM\CurrentControlSet\Control\Secureboot value AvailableUpdates outside the approved rollout tool mountvol <letter>: /s, bcdboot ... /s, bcdedit loader or integrity options, Set-SecureBootUEFI from an interactive admin session Kernel driver loaded from outside System32\drivers and the DriverStore, seen on 3 or fewer hosts Kernel driver whose signer certificate serial matches the value in the Named Tooling block
inst.exe # installer, C:\ProgramData\Intel\inst.exe PVMDIJGKAX2 # RC4-encrypted extensionless blob holding all install files and strings Q46F6MDLI3RX2KV1 # RC4 key, last command-line argument (likely changes per build) googleupdate.exe # legitimate Chromium helper, original name jcef_helper.exe jcef_helper.exe MD5 AF8A983B9ADA07EAE1259BF2953ABD40 # stock helper hash (legitimate: never block) v8_context_snapshot.bin # encrypted payload: shellcode followed by a Rust PE OxiDLLRunner # OLLVM-obfuscated loader DLL create_plugin # export the Rust payload expects from downloaded plugin DLLs www[.]archivetj[.]com # Rust payload C2 Signer certificate serial 0bcdf5e0da32d68900b8b7638459d072 Signer organisation Wenjiang District Mingyu Network Technology Service Studio (revoked by issuer) Secure-Boot-Update # native task name; lookalikes outside \Microsoft\Windows\PI\ are suspect TEST.Class1.RunCMD # method the RAT runs from a 0X01 .NET module Cloud task suffixes 0X01 0X02 0X03 0X04 0X05 0X06 SSSR xdd # identifier inside BlackX payloads (weak alone)
# Read-only Secure Boot posture checks (run elevated). Full version: playbook P1. Confirm-SecureBootUEFI [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match 'Windows UEFI CA 2023' [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI dbx).bytes) -match 'Microsoft Windows Production PCA 2011' (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing").UEFICA2023Status Get-ScheduledTask -TaskName Secure-Boot-Update | Select-Object TaskName, TaskPath, State
Detection Validation Gates
| Gate | Check | Pass condition |
|---|---|---|
| Telemetry ready | Confirm process creation with command line, DNS lookup with requesting process, registry value set, scheduled task registered and driver load (CrowdStrike: ProcessRollup2, DnsRequest, RegGenericValueUpdate, ScheduledTaskRegistered, DriverLoad. SentinelOne: Process Creation, DNS Resolved, Registry Value Modified. Defender: DeviceProcessEvents, DeviceEvents, DeviceRegistryEvents) | Each source returns rows for a test host in the last hour |
| Benign baseline | Run Q7, Q9, Q10, Q11 and Q12 for 7 days with no alerting | Writers and processes are listed and either excluded or owned; Q9 matches the approved rollout tool |
| Positive tests | In a lab, copy a benign signed executable to C:\ProgramData\Intel\inst.exe and run it with two dummy arguments (Q2). Copy another to a temp folder named googleupdate.exe and run it (Q3). Register a scheduled task named Secure-Boot-Update in the root folder (Q8). Replay Q5 against a test domain you control, not the real C2 | Each query fires on its test and stays quiet on the unmodified originals |
| Promotion | Promote Q1, Q2, Q3, Q4, Q5, Q6 and Q8 to Custom IOA at Detect after a clean 7-day baseline | Zero unexplained matches; owners named for Q7, Q9, Q10, Q11 |
Hardening: Tiered
- H1. Inventory Secure Boot state, read-only. Run playbook P1 across device classes to find hosts whose DBX does not hold "Microsoft Windows Production PCA 2011". Those are the BlackX-exposed hosts. MITRE M1046 Boot Integrity; source: Microsoft revocation guidance (snapshot 03). Verify: P1 output.
- H2. Shrink the pool of administrator accounts. BlackX is deployed after administrator rights are obtained (Securelist), and Microsoft says the exploit needs administrator or physical access. Remove standing local admin, tier admin accounts, and require just-in-time elevation. M1026 Privileged Account Management; CIS Controls 5 and 6. Verify: CQL spot-check of
inst.exestyle installers running as admin (Q1, Q2). - H3. Back up BitLocker recovery keys before any Secure Boot change. Microsoft says some devices enter BitLocker recovery. Verify:
manage-bde -protectors -get %systemdrive%on a pilot host. - H4. Alert-only monitoring for the C2 host and the sideload context. Add the domain to DNS and proxy logging as detect, not block, until a second independent source exists. Posture is the same as the Falcon CSV.
- H5. Pilot Microsoft's revocation sequence on one device per hardware class. Order: add the 2023 certificate to the DB, verify, add PCA 2011 to the DBX, verify event 1037, then optionally the SVN update. Update install and recovery media first, and patch every Windows installation on dual-boot hosts to July 9, 2024 or later. M1046; Microsoft KB steps (snapshot 03). Playbook P2 has prerequisites, reboot and rollback. Verify: DBX string match in P1.
- H6. Restrict consumer cloud storage egress from servers and sensitive enclaves. Permit sanctioned tenants of Google Workspace and Microsoft 365 only, and block Yandex.Disk unless there is a business need. M1021 Restrict Web-Based Content; M1031 Network Intrusion Prevention. best-practice, no formal benchmark cited here Verify: Q7 falls to the sanctioned-app baseline.
- H7. Turn on memory integrity (HVCI) and the Microsoft vulnerable driver blocklist. Raises the cost of loading unsigned or known-bad kernel drivers after boot. Not sourced to the BlackX report, and it does not stop a bootkit that runs before the kernel. M1038 Execution Prevention. best-practice, no formal benchmark cited here Verify:
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard.
- H8. Complete the revocation fleet-wide and do not wait for the Enforcement Phase. Microsoft says that phase will revoke automatically with no opt-out, but no date was announced when fetched on 2026-10-23, and Kaspersky confirms it has not shipped. The 2011 certificate's expiry on October 19, 2026 does not stop vulnerable bootloaders from loading; only the DBX entry does. M1046; sources 01 and 03.
- H9. Make boot-chain health an attestation signal. Use measured boot with TPM-backed health attestation in your device management stack so a changed boot chain drops conditional access. M1046. best-practice, no formal benchmark cited here
- H10. Add file-integrity monitoring for the EFI system partition. BlackX writes to it. M1047 Audit. best-practice, no formal benchmark cited here
Deployable Playbooks
Each playbook states Prerequisites, Reboot required and Rollback. P2 changes boot trust and is a pilot-first procedure.
P1. Secure Boot posture audit
# P1 Secure Boot posture audit (read-only, run elevated)
# Prerequisites: local administrator; UEFI firmware (not legacy BIOS).
# Reboot required: no.
# Rollback: none required, nothing is changed.
try { "SecureBoot enabled : " + (Confirm-SecureBootUEFI) } catch { "SecureBoot check failed: " + $_.Exception.Message }
$db = [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes)
$dbx = [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI dbx).bytes)
"DB has Windows UEFI CA 2023 : " + ($db -match 'Windows UEFI CA 2023')
"DBX has Windows Production PCA 2011 : " + ($dbx -match 'Microsoft Windows Production PCA 2011')
"UEFICA2023Status : " + (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -ErrorAction SilentlyContinue).UEFICA2023Status
Get-ScheduledTask -TaskName Secure-Boot-Update -ErrorAction SilentlyContinue | Select-Object TaskName, TaskPath, State
# Revocation events per the Microsoft guidance: 1036 (DB), 1799 (boot manager), 1037 (DBX), 1042 (SVN).
# Confirm the log name in KB5016061 for your build; System is searched here.
Get-WinEvent -LogName System -MaxEvents 5000 -ErrorAction SilentlyContinue | Where-Object { $_.Id -in 1036,1037,1042,1799 } | Select-Object -First 20 TimeCreated, Id, MessageP2. Microsoft revocation sequence (pilot first)
# P2 Microsoft Secure Boot revocation sequence (PILOT: one device per hardware class first) # Prerequisites: # 1. Latest Windows monthly updates installed. Every Windows installation on a dual-boot host patched to July 9, 2024 or later. # 2. BitLocker recovery key backed up: manage-bde -protectors -get %systemdrive% # 3. Recovery flash drive and install media updated for the pilot class (Microsoft "Updating Windows install media"). # 4. Firmware checked for DB and DBX update support on the device class. # Reboot required: possibly. Microsoft notes a restart may be needed when Virtual Secure Mode features are on. # Rollback: see the recovery block at the end. The DBX entry is not undone by a registry change. # Step 1. Add the 2023 certificates to the DB and move to the 2023-signed boot manager reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Secureboot /v AvailableUpdates /t REG_DWORD /d 0x5944 /f Start-ScheduledTask -TaskName "\Microsoft\Windows\PI\Secure-Boot-Update" [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match 'Windows UEFI CA 2023' # expect True (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing").UEFICA2023Status # expect Updated # Step 2. STOP. Confirm the pilot host boots, and that recovery media works, before continuing. # Step 3. Revoke Windows Production PCA 2011 (adds it to the DBX; Microsoft: cannot boot managers signed by it afterwards) reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Secureboot /v AvailableUpdates /t REG_DWORD /d 0x80 /f Start-ScheduledTask -TaskName "\Microsoft\Windows\PI\Secure-Boot-Update" [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI dbx).bytes) -match 'Microsoft Windows Production PCA 2011' # expect True; event 1037 # Step 4 (optional). Apply the SVN update to the firmware reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Secureboot /v AvailableUpdates /t REG_DWORD /d 0x200 /f Start-ScheduledTask -TaskName "\Microsoft\Windows\PI\Secure-Boot-Update" # Recovery (Microsoft-documented), if the device will not start: # a. Turn Secure Boot off in the UEFI menu. # b. Reset (do not Clear) Secure Boot keys to factory defaults if the device supports it. The device is then vulnerable to bootkits. # c. From Windows, restore the EFI boot files (Microsoft's own commands; destructive to the ESP contents): # mountvol s: /s # del s:\*.* /f /s /q # bcdboot %systemroot% /s S: # d. If that fails, reinstall from updated recovery media. # e. Re-enable Secure Boot and restart.
P3. Sideload pair and signer serial sweeps
# P3 Read-only sweeps for the BlackX sideload pair and the revoked signer serial
# Prerequisites: local administrator; PowerShell 5.1 or later.
# Reboot required: no.
# Rollback: none required, nothing is changed.
# Block 1. googleupdate.exe outside a Google Update folder, and v8_context_snapshot.bin beside it
$roots = @("$env:ProgramData", "$env:SystemDrive\Users", "$env:SystemRoot\Temp")
foreach ($r in $roots) {
Get-ChildItem -Path $r -Recurse -Force -Filter googleupdate.exe -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\\Google\\Update\\' } |
ForEach-Object {
$pair = Test-Path (Join-Path $_.DirectoryName 'v8_context_snapshot.bin')
[pscustomobject]@{ Path = $_.FullName; HasSnapshotBin = $pair; MD5 = (Get-FileHash $_.FullName -Algorithm MD5).Hash }
}
}
# Block 2. Loaded drivers whose signer certificate serial matches the BlackX driver certificate
$serial = '0bcdf5e0da32d68900b8b7638459d072'
Get-CimInstance Win32_SystemDriver | Where-Object { $_.PathName } | ForEach-Object {
$p = ($_.PathName -replace '^\\\?\?\\','' -replace '"','')
$sig = Get-AuthenticodeSignature -FilePath $p -ErrorAction SilentlyContinue
if ($sig.SignerCertificate -and $sig.SignerCertificate.SerialNumber -ieq $serial) { "MATCH: $p" }
}P4. Alert-only egress watch
# P4 Alert-only watch on the C2 host and cloud-storage lookups (logging, no blocking) # Prerequisites: DNS or proxy platform that supports a log-only watchlist. # Reboot required: no. # Rollback: remove the watchlist entry; no traffic is affected. Watchlist (log and alert, do NOT block): www.archivetj.com # single-sourced; promote to block only after a second independent source Review weekly: Google Drive, OneDrive and Yandex.Disk API lookups from non-client processes (Q7) Posture matches the Falcon CSV, the IOA table and Q5, Q6: detect only.
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Network-isolate the host through the EDR, keeping the sensor connected. Disable the user and any service accounts that ran the installer. Do not reboot or power off before imaging if memory evidence matters | IR lead | Isolation timestamp; process tree for inst.exe |
| 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. | IR lead | Isolation timestamp; process tree for inst.exe |
| Preserve | Image the disk including the EFI system partition. Capture bcdedit /enum all, the DB and DBX contents (P1), and the list of loaded drivers with signer serials (P3) | Forensics | ESP image, P1 and P3 output, hashes of inst.exe, the blob, googleupdate.exe and v8_context_snapshot.bin |
| Scope | Run Q1 to Q12 fleet-wide for 90 days. Ask cloud providers for audit logs of accounts behind Drive, OneDrive or Yandex.Disk C2 (N8). Review administrator logons that preceded the drop | Threat hunter | Host list, account list, first-seen time |
| Eradicate | Treat the host as untrusted at the boot level: Microsoft says its mitigations are preventive, not corrective, and to contact your security provider for compromised devices. Recommended practice (not stated in the report): reset Secure Boot keys to factory defaults, rebuild the ESP, reimage, then apply the revocation (P2) | Endpoint engineering | Rebuild ticket; P1 clean on the rebuilt host |
| Recover | Rotate credentials of every account that was logged on or administered the host. Rebuild from known-good media updated for the revocation. Complete the revocation on the rest of the fleet | Identity and endpoint teams | Credential rotation log; DBX check across the fleet |
| Learn | Record who held administrator rights when the installer ran, and why the revocation was not activated. Feed the answer into H2 and H5 | Security manager | Post-incident note |
Detection Coverage Map
| Technique / behavior | CQL | IOA | CrowdStrike coverage | SentinelOne | Defender XDR |
|---|---|---|---|---|---|
| Installer launch (T1542.003, T1140) | Q1, Q2 | Yes | Good | Good, with assumptions | Good, with assumptions |
| Sideload host (T1574.002) | Q3, Q4 | Yes | Good | Good, with assumptions | Good, with assumptions |
| Payload DLL and snapshot file on disk | None | No | GAP: non-PE file writes not recorded; use N2 | GAP | GAP |
| C2 lookups (T1071.001) | Q5, Q6 | Yes | Good, perishable | Good, with assumptions | Good, with assumptions |
| Cloud-storage C2 (T1102.002) | Q7 | No | Partial: hostnames inferred | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| Revocation posture, lookalike task (T1112, T1053.005) | Q8, Q9 | Yes (Q8) | Partial: absence is the finding | Partial: Q8 unavailable | Partial: same limit as CrowdStrike |
| EFI partition and boot config (T1542.003, T1553) | Q10 | No | Partial: inferred tools | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| Rare kernel driver load (T1014) | Q11 | No | Partial: bootkit load may precede sensor | GAP | Partial: same limit as CrowdStrike |
| ETW autologger registry (T1562.006) | Q12 | No | Partial: adjacent only | Partial: same limit as CrowdStrike | Partial: same limit as CrowdStrike |
| Baton Drop MOK enrolment, firmware variables | None | No | GAP: outside endpoint telemetry, use N1, N4 | GAP | GAP |
| Kernel callback removal, ETW provider tampering, calc.exe handle trick | None | No | GAP: kernel mode, invisible to sensor | GAP | GAP |
| Revoked signer certificate serial | None | No | GAP: serial not exposed, use N3 | GAP | GAP |
| In-memory plugins (create_plugin) | None | No | GAP: needs memory scanning | GAP | GAP |
| Cloud-drive task files (0X01 to SSSR) | None | No | GAP: provider logs, use N8 | GAP | GAP |
Validation gates (s11) apply: baseline for 7 days before promoting any IOA.
Hunt Summary Ticket
TITLE: BlackX UEFI bootkit (APT41, medium confidence): Windows endpoint hunt and Secure Boot revocation audit
SEVERITY: HIGH (nation-state espionage; boot-level persistence on fully patched hosts)
SCOPE: Windows endpoints and servers with administrator exposure; Secure Boot DB/DBX state; cloud-storage accounts
HYPOTHESIS: An actor with administrator rights drops inst.exe plus an RC4 blob, exploits Baton Drop to enrol MOK keys,
loads a kernel driver, and runs a cloud-storage RAT and a googleupdate.exe sideloaded Rust beacon.
QUERIES RUN: Q1 installer | Q2 installer shape | Q3 sideload host | Q4 renamed helper hash | Q5 C2 DNS |
Q6 updater DNS | Q7 cloud-storage DNS | Q8 task lookalike | Q9 Secureboot writes | Q10 EFI/boot tools |
Q11 rare drivers | Q12 ETW autologger (+8 native hunts)
DO FIRST: Run P1 on each device class to list hosts with no PCA 2011 DBX entry; run Q1, Q3, Q5 fleet-wide.
DATA SOURCES: Process creation with command line, DNS lookup with requesting process, registry value set, scheduled task
registered, driver load (CrowdStrike: ProcessRollup2, DnsRequest, RegGenericValueUpdate, ScheduledTaskRegistered,
DriverLoad); native Secure Boot variables and cloud provider audit logs
FINDINGS: <pending analyst execution>
GAPS: Baton Drop MOK enrolment, kernel callback and ETW tampering, signer serial, in-memory plugins and cloud-drive task
files are outside endpoint telemetry. No installer, driver or Rust payload hash was published.
ACTIONS: Cut standing admin rights; pilot Microsoft's revocation steps per device class; detect-only on all indicators;
promote Q1 to Q6 and Q8 to Custom IOA at Detect after a 7-day baseline.
OWNER: HuntPack
VERSION: v0.1 (Draft) - 2026-10-23Changelog
References
| Tier | Source | Used for | Accessed |
|---|---|---|---|
| 1 | Securelist (Kaspersky GReAT): BlackX UEFI bootkit exploiting Baton Drop | Primary report, all indicators (snapshot 01) | 2026-10-23 |
| 3 | SecurityOnline: BlackX UEFI bootkit and APT41 | Secondary restatement (snapshot 02) | 2026-10-23 |
| 1 | Microsoft Support: Windows Boot Manager revocations for Secure Boot (CVE-2023-24932) | Revocation steps, events, recovery, Enforcement Phase status (snapshot 03) | 2026-10-23 |
HuntPack v0.1 (Draft) · BlackX UEFI Bootkit · Generated 2026-10-23 · Defensive use only. No exploit code. Contains no victim, company or environment-specific identifiers. Validate field names, especially DriverLoad, in your tenant before deploying.