Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions queries/com_hijacking_per_user_clsid_server.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# --- Query Metadata ---
# Human-readable name for the query. Will be displayed as the title.
name: COM Hijacking via Per-User CLSID Server Registration

# MITRE ATT&CK technique IDs
mitre_ids:
- T1546.015

# Description of what the query does and its purpose.
description: |
Finds per-user (HKCU) writes to a COM CLSID server key (InprocServer32, LocalServer32 or TreatAs). A user-hive registration shadows the machine-wide COM object, so an attacker-controlled binary loads in place of the legitimate one whenever the CLSID is instantiated, with no admin rights required. This is a common persistence and defense-evasion route.

# The author or team that created the query.
author: Caio Lopes

# The required log sources to run this query successfully in Next-Gen SIEM.
log_sources:
- Endpoint

# The CrowdStrike modules required to run this query.
cs_required_modules:
- Insight

# Tags for filtering and categorization.
tags:
- Hunting

# --- Query Content ---
# The actual CrowdStrike Query Language (CQL) code.
# Using the YAML block scalar `|` allows for multi-line strings.
cql: |
// Registry value writes. Different tenants surface these under AsepValueUpdate
// or RegGenericValueUpdate; both are included so the hunt does not depend on
// which one your sensor emits.
in(#event_simpleName, values=["AsepValueUpdate", "RegGenericValueUpdate"])
| event_platform=Win

// Optional scoping for testing on a single host (leave unset for fleet-wide)
| ComputerName=?ComputerName

// The COM server keys an attacker overwrites to gain execution
| RegObjectName=/\\CLSID\\\{[0-9a-f-]+\}\\(InprocServer32|LocalServer32|TreatAs)/i

// Per-user hive shadows HKLM, which is the hijack pattern. Match a real user
// SID (S-1-5-21-...), not SYSTEM (S-1-5-18) or the service accounts (S-1-5-19/20).
| RegObjectName=/\\REGISTRY\\USER\\S-1-5-21-/i

// Raise fidelity on where the new server points
| case {
RegStringValue=/^(script:|https?:|\\\\)/i
| Reason := "COM server is a script moniker or remote path" ;
RegStringValue=/(\\appdata\\|\\users\\public\\|\\temp\\|\\windows\\temp\\|\\programdata\\|%temp%|%appdata%)/i
| Reason := "COM server in a user-writable path" ;
*
| Reason := "Per-user COM server registration (review against baseline)" ;
}

| table([@timestamp, ComputerName, aid, RegObjectName, RegValueName, RegStringValue, Reason], limit=200)
| sort(@timestamp, order=desc)

# Explanation of the query.
# Using the YAML block scalar `|` allows for multi-line strings.
# Uses markdown for formatting on the webpage.
explanation: |
## What it looks for

COM objects resolve their server binary through `HKCR\CLSID\{GUID}\InprocServer32`
(in-process DLL), `LocalServer32` (out-of-process EXE) or `TreatAs` (redirection to
another CLSID). `HKCR` is a merged view of `HKLM\Software\Classes` and
`HKCU\Software\Classes`, and the per-user copy wins. Writing the server key under the
user hive therefore reassigns a COM object to an attacker binary without touching the
machine hive and without admin rights, and the code runs whenever something
instantiates that CLSID.

The query keys on registry value writes whose `RegObjectName` is a `CLSID\{GUID}`
server key **under a real user SID** (`\REGISTRY\USER\S-1-5-21-...`), then classifies
the value the server now points at: a script moniker or remote path, a user-writable
or temp path, or otherwise a plain per-user registration to review.

## Telemetry and modules

- Log source: Endpoint (registry telemetry), Falcon Insight.
- Registry value updates arrive as `AsepValueUpdate` or `RegGenericValueUpdate`
depending on tenant configuration; both are queried. If your environment records
registry writes under a different `event_simpleName`, adjust the first filter.

## Tuning and false positives

- Some legitimate software registers per-user COM servers. Baseline your fleet and
add an exclusion on the known-good `RegStringValue` paths or publisher directories.
The `Reason` field lets you triage the moniker/remote and user-writable cases first,
which are the ones worth chasing.
- `TreatAs` and `LocalServer32` are included because both are valid hijack points, not
only `InprocServer32`.

## Note

This is a hunting query built against CrowdStrike's documented registry event schema.
It has not been run against a live Falcon tenant, so validate the `event_simpleName`
values and field names against your own registry telemetry before relying on it.
100 changes: 100 additions & 0 deletions queries/typelib_hijacking_per_user_registration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# --- Query Metadata ---
# Human-readable name for the query. Will be displayed as the title.
name: TypeLib Hijacking via Per-User Registration

# MITRE ATT&CK technique IDs
mitre_ids:
- T1574.008

# Description of what the query does and its purpose.
description: |
Finds per-user (HKCU) writes to a TypeLib platform key (win32/win64), where an attacker repoints a type library at a scriptlet, moniker or attacker-controlled path. When a program resolves that type library the attacker content runs. The Explorer TypeLib variant is a well-documented, low-noise persistence route.

# The author or team that created the query.
author: Caio Lopes

# The required log sources to run this query successfully in Next-Gen SIEM.
log_sources:
- Endpoint

# The CrowdStrike modules required to run this query.
cs_required_modules:
- Insight

# Tags for filtering and categorization.
tags:
- Hunting

# --- Query Content ---
# The actual CrowdStrike Query Language (CQL) code.
# Using the YAML block scalar `|` allows for multi-line strings.
cql: |
// Registry value writes. Different tenants surface these under AsepValueUpdate
// or RegGenericValueUpdate; both are included so the hunt does not depend on
// which one your sensor emits.
in(#event_simpleName, values=["AsepValueUpdate", "RegGenericValueUpdate"])
| event_platform=Win

// Optional scoping for testing on a single host (leave unset for fleet-wide)
| ComputerName=?ComputerName

// A per-user TypeLib platform key (win32/win64/win16) is where the library path lives
| RegObjectName=/\\TypeLib\\\{[0-9a-f-]+\}\\.+\\(win32|win64|win16)/i

// Per-user hive; match a real user SID, not SYSTEM or the service accounts
| RegObjectName=/\\REGISTRY\\USER\\S-1-5-21-/i

// Classify what the type library now resolves to
| case {
RegStringValue=/^(script:|https?:|moniker:|\\\\)/i
| Reason := "TypeLib points at a script moniker or remote path" ;
RegStringValue=/(\.sct|\.wsc|\.hta|\.js|\.vbs|scrobj\.dll)/i
| Reason := "TypeLib points at a scriptlet or script host" ;
RegStringValue=/(\\appdata\\|\\users\\public\\|\\temp\\|\\programdata\\|%temp%|%appdata%)/i
| Reason := "TypeLib points at a user-writable path" ;
*
| Reason := "Per-user TypeLib platform key modified (review against baseline)" ;
}

| table([@timestamp, ComputerName, aid, RegObjectName, RegValueName, RegStringValue, Reason], limit=200)
| sort(@timestamp, order=desc)

# Explanation of the query.
# Using the YAML block scalar `|` allows for multi-line strings.
# Uses markdown for formatting on the webpage.
explanation: |
## What it looks for

A type library registration lives under `HKCR\TypeLib\{GUID}\<version>\<lcid>\win32`
(or `win64`/`win16`), whose default value is the path to the library that backs a COM
interface. Because `HKCR` merges the machine and user hives with the user copy winning,
writing that platform key under the user hive redirects the type library to
attacker-chosen content. When any program resolves the type library, that content is
loaded, which is why the technique is used for stealthy persistence. The Explorer
TypeLib hijack is the best-known instance.

The query keys on registry writes whose `RegObjectName` is a `TypeLib\{GUID}\...\win32`
(or `win64`/`win16`) key **under a real user SID** (`\REGISTRY\USER\S-1-5-21-...`), then
classifies the value it now resolves to: a script moniker or remote path, a scriptlet or
script host, a user-writable path, or otherwise a plain per-user modification to review.

## Telemetry and modules

- Log source: Endpoint (registry telemetry), Falcon Insight.
- Registry value updates arrive as `AsepValueUpdate` or `RegGenericValueUpdate`
depending on tenant configuration; both are queried. Adjust the first filter if your
environment records registry writes under a different `event_simpleName`.

## Tuning and false positives

- Software installers and language-pack updates can legitimately touch TypeLib keys.
The high-confidence rows are the script-moniker/remote and scriptlet cases; triage
those first via the `Reason` field, and baseline the user-writable-path case before
alerting on it.
- `win16` is included for completeness; drop it if it adds only noise in your fleet.

## Note

This is a hunting query built against CrowdStrike's documented registry event schema.
It has not been run against a live Falcon tenant, so validate the `event_simpleName`
values and field names against your own registry telemetry before relying on it.