Detection rules › Kusto

Potential Lateral Movement via MSI ODBC Driver Install over DCOM

Group by
InitiatingProcessUniqueId, ProcessUniqueId
Author
Cyb3rMonk
Source
github.com/Cyb3r-Monk/Threat-Hunting-and-Detection

Detects Potential Lateral Movement via MSI Custom Actions to install ODBC Driver over DCOM remotely.

MITRE ATT&CK coverage

TacticTechniques
Lateral MovementNo specific technique

References

Event coverage

Rule body kusto

// Description: Detect Potential Lateral Movement via MSI ODBC Driver Installer over DCOM
// Author: Cyb3rMonk(https://x.com/Cyb3rMonk)
// Website: https://academy.bluraven.io 
// Reference: https://specterops.io/blog/2025/09/29/dcom-again-installing-trouble-lateral-movement-bof/
//
DeviceProcessEvents
| where InitiatingProcessParentFileName == "services.exe"
| where InitiatingProcessFileName == "msiexec.exe"
| where FileName == "msiexec.exe"
| project DeviceId, DeviceName, ProcessUniqueId
| join kind=inner (
    DeviceNetworkEvents
    | where ActionType == "InboundConnectionAccepted"
    | where InitiatingProcessFileName == "msiexec.exe"
    | distinct DeviceId
    ) on DeviceId
    | join kind=inner 
        DeviceImageLoadEvents
        on DeviceId, DeviceName, $left.ProcessUniqueId == $right.InitiatingProcessUniqueId
| project-away DeviceId1, DeviceName1, DeviceId2
| project-reorder TimeGenerated, ActionType, DeviceId, DeviceName, FolderPath, InitiatingProcessFileName

Stages and Predicates

Stage 1: source

DeviceProcessEvents

Stage 2: where

| where InitiatingProcessParentFileName == "services.exe"

Stage 3: where

| where InitiatingProcessFileName == "msiexec.exe"

Stage 4: where

| where FileName == "msiexec.exe"

Stage 5: project

| project DeviceId, DeviceName, ProcessUniqueId

Stage 6: join

| join kind=inner (
    DeviceNetworkEvents
    | where ActionType == "InboundConnectionAccepted"
    | where InitiatingProcessFileName == "msiexec.exe"
    | distinct DeviceId
    ) on DeviceId

Stage 7: join

| join kind=inner 
        DeviceImageLoadEvents
        on DeviceId, DeviceName, $left.ProcessUniqueId == $right.InitiatingProcessUniqueId

Stage 8: project-away

| project-away DeviceId1, DeviceName1, DeviceId2

Stage 9: project-reorder

| project-reorder TimeGenerated, ActionType, DeviceId, DeviceName, FolderPath, InitiatingProcessFileName

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
ActionTypeeq
  • InboundConnectionAccepted transforms: cased corpus 3 (kusto 3)
FileNameeq
  • msiexec.exe transforms: cased
InitiatingProcessFileNameeq
  • msiexec.exe transforms: cased corpus 9 (elastic 4, splunk 3, kusto 2)
InitiatingProcessParentFileNameeq
  • services.exe transforms: cased

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
DeviceIdproject
DeviceNameproject
ProcessUniqueIdproject