Detection rules › Kusto
ADWS Connection from Process Injection Target
The query first collects all network connections to the Active Directory Web Services (ADWS) service. It then searches for processes that inject into a process that makes a connection to ADWS. This can be used to detect process injection into a process that is used to query Active Directory.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Stealth | T1055.002 Process Injection: Portable Executable Injection |
| Discovery | T1087.002 Account Discovery: Domain Account |
| Collection | T1119 Automated Collection |
References
Event coverage
Rule body kusto
let timeframe = 2*1h;
let ADWSConnections=(
DeviceNetworkEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType == "ConnectionSuccess"
| where RemotePort == 9389
| extend InitiatingProcessFileName=tolower(InitiatingProcessFileName)
);
let ADWSFileNames=materialize(
ADWSConnections
| distinct InitiatingProcessFileName
);
// Look for processes that inject into a process that makes an ADWS connection.
let InjectorProcesses=materialize(
DeviceEvents
| where ingestion_time() >= ago(timeframe)
| where not(isempty(FileName))
// Look for actions associated with process injection.
| where ActionType in~ ("CreateRemoteThreadApiCall", "MemoryRemoteProtect","NtAllocateVirtualMemoryApiCall", "NtAllocateVirtualMemoryRemoteApiCall", "NtMapViewOfSectionRemoteApiCall", "NtProtectVirtualMemoryApiCall", "SetThreadContextRemoteApiCall", "QueueUserApcRemoteApiCall")
| where FileName in~ (ADWSFileNames)
| where not(InitiatingProcessFolderPath startswith @"c:\program files\vmware\vmware tools" and InitiatingProcessFileName =~ "vmtoolsd.exe")
| where not(InitiatingProcessFolderPath =~ @"C:\Windows\System32" and InitiatingProcessFileName =~ "csrss.exe")
| where not(InitiatingProcessFolderPath =~ @"C:\Windows\System32\csrss.exe")
| where not(InitiatingProcessFolderPath startswith @"c:\program files\microsoft azure ad sync\" and InitiatingProcessFileName =~ "miiserver.exe")
| extend FileName=tolower(FileName)
| lookup kind=inner ADWSConnections on DeviceId, $left.ProcessId == $right.InitiatingProcessId, $left.FileName == $right.InitiatingProcessFileName
// Begin environment-specific filter.
// End environment-specific filter.
| project DeviceId, ProcessId, FileName, InjectorProcessId=InitiatingProcessId, InjectorFileName=InitiatingProcessFileName, InjectorActionType=ActionType
);
// Find ADWS connections from processes that were injected into by another process.
ADWSConnections
| lookup kind=inner InjectorProcesses on DeviceId, $left.InitiatingProcessId == $right.ProcessId, $left.InitiatingProcessFileName == $right.FileName
| summarize arg_min(Timestamp,*), InjectionMethods=make_set(InjectorActionType) by DeviceId, DeviceName, InitiatingProcessId, InitiatingProcessFileName
| extend HostName=tostring(split(DeviceName,".")[0]),DnsDomain=iif(DeviceName contains ".", substring(DeviceName, indexof(DeviceName, ".") + 1, strlen(DeviceName)),"")
// Begin environment-specific filter.
// End environment-specific filter.
Stages and Predicates
Parameters
let timeframe = 2*1h;
Let binding: ADWSFileNames
let ADWSFileNames = materialize(
ADWSConnections
| distinct InitiatingProcessFileName
);
Derived from ADWSConnections.
Let binding: InjectorProcesses
let InjectorProcesses = materialize(
DeviceEvents
| where ingestion_time() >= ago(timeframe)
| where not(isempty(FileName))
| where ActionType in~ ("CreateRemoteThreadApiCall", "MemoryRemoteProtect","NtAllocateVirtualMemoryApiCall", "NtAllocateVirtualMemoryRemoteApiCall", "NtMapViewOfSectionRemoteApiCall", "NtProtectVirtualMemoryApiCall", "SetThreadContextRemoteApiCall", "QueueUserApcRemoteApiCall")
| where FileName in~ (ADWSFileNames)
| where not(InitiatingProcessFolderPath startswith @"c:\program files\vmware\vmware tools" and InitiatingProcessFileName =~ "vmtoolsd.exe")
| where not(InitiatingProcessFolderPath =~ @"C:\Windows\System32" and InitiatingProcessFileName =~ "csrss.exe")
| where not(InitiatingProcessFolderPath =~ @"C:\Windows\System32\csrss.exe")
| where not(InitiatingProcessFolderPath startswith @"c:\program files\microsoft azure ad sync\" and InitiatingProcessFileName =~ "miiserver.exe")
| extend FileName=tolower(FileName)
| lookup kind=inner ADWSConnections on DeviceId, $left.ProcessId == $right.InitiatingProcessId, $left.FileName == $right.InitiatingProcessFileName
| project DeviceId, ProcessId, FileName, InjectorProcessId=InitiatingProcessId, InjectorFileName=InitiatingProcessFileName, InjectorActionType=ActionType
);
Derived from timeframe, ADWSConnections, ADWSFileNames.
The stages below define let ADWSConnections (the rule's main pipeline source).
Stage 1: source
DeviceNetworkEvents
Stage 2: where
| where ingestion_time() >= ago(timeframe)
Stage 3: where
| where ActionType == "ConnectionSuccess"
Stage 4: where
| where RemotePort == 9389
Stage 5: extend
| extend InitiatingProcessFileName=tolower(InitiatingProcessFileName)
The stages below run on ADWSConnections (the outer pipeline).
Stage 6: kusto:lookup
ADWSConnections
| lookup kind=inner InjectorProcesses on DeviceId, $left.InitiatingProcessId == $right.ProcessId, $left.InitiatingProcessFileName == $right.FileName
Stage 7: summarize
| summarize arg_min(Timestamp,*), InjectionMethods=make_set(InjectorActionType) by DeviceId, DeviceName, InitiatingProcessId, InitiatingProcessFileName
Stage 8: extend
| extend HostName=tostring(split(DeviceName,".")[0]),DnsDomain=iif(DeviceName contains ".", substring(DeviceName, indexof(DeviceName, ".") + 1, strlen(DeviceName)),"")
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.
| Field | Kind | Values |
|---|---|---|
ActionType | eq |
|
RemotePort | eq |
|
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.
| Field | Source |
|---|---|
DeviceId | summarize |
DeviceName | summarize |
InitiatingProcessFileName | summarize |
InitiatingProcessId | summarize |
InjectionMethods | summarize |
DnsDomain | extend |
HostName | extend |