In this section
ES9.5 DeviceLogonEvents and DeviceImageLoadEvents
The previous section covered devicefileevents and deviceregistryevents. This section covers devicelogonevents and deviceimageloadevents.
Figure ES9.5 DeviceLogonEvents and DeviceImageLoadEvents. Production hunting queries with annotated KQL, expected results, and escalation criteria.
Hunting approach
Each query in this subsection follows the hunting methodology from ES9.1: hypothesis (what we expect to find), query (the KQL that tests the hypothesis), expected results (what the baseline looks like on a clean fleet), and escalation criteria (what constitutes a finding vs noise). The queries are designed for weekly execution against 7 days of endpoint data. Each query should return a manageable result set (under 50 results per week after baseline exclusions). Queries that return hundreds of results need tighter filtering, add exclusions for the dominant legitimate patterns or narrow the time window.
Anti-Pattern
Configuring without validating
The devicelogonevents and deviceimageloadevents configuration is deployed based on documentation or vendor guidance, but nobody verifies it works in your environment. Deploy, then validate with a test that confirms the expected behavior. Every configuration has a verification query or test procedure, if you cannot verify it, you cannot trust it.
The queries in this subsection complement the detection rules from ES8. Where ES8 detections fire automatically on known-bad patterns, these hunting queries search for patterns that are suspicious but not confident enough for automated alerting: the gray area between definitely legitimate and definitely malicious where human judgment is required.
At NE, the hunting library is executed weekly by the security analyst on duty. Each query is saved in MDE Advanced Hunting as a shared query with a naming convention: HUNT-[TABLE]-[NUMBER] (e.g., HUNT-PROC-001, HUNT-NET-001). The results are logged in the hunting journal: date, query name, result count, findings (if any), and exclusion updates. Over time, the journal builds a behavioral baseline for the NE environment: the analyst knows what "normal" looks like and can spot deviations faster.
The hunt-to-detection pipeline works in both directions. Successful hunts produce detection rules (ES8). Detection rule tuning produces improved hunting queries (exclusions discovered during detection tuning are applied to the corresponding hunting query). The two activities, hunting and detection engineering, reinforce each other.
- Run this query to see the Kerberos vs NTLM ratio across your fleet:
DeviceLogonEvents
| where Timestamp > ago(7d) and ActionType == "LogonSuccess"
| where LogonType == "Network"
| summarize Count = count() by Protocol
| sort by Count desc
- If NTLM exceeds 20% of network logons: identify the sources:
DeviceLogonEvents
| where Timestamp > ago(7d) and Protocol == "NTLM" and LogonType == "Network"
| summarize Count = count() by DeviceName, AccountName
| sort by Count desc
| take 20
- For each high-NTLM source: determine why, is the device accessing resources by IP instead of hostname? Is there a legacy application forcing NTLM? Can it be reconfigured for Kerberos?
- Run the pass-the-hash hunt query: NTLM logons from non-DC sources to 3+ devices. Each result is a potential pass-the-hash indicator
- Run the unsigned DLL query: system processes loading unsigned DLLs from non-system paths. Each result is a potential DLL side-loading indicator, check the DLL hash on VirusTotal
Authentication and DLL hunting: the high-value tables
DeviceLogonEvents is the primary table for detecting credential abuse. The logon type field distinguishes legitimate authentication from attack techniques: Type 2 (Interactive) is a user at the keyboard. Type 3 (Network) is a remote authentication (file share, WMI, PsExec). Type 10 (RemoteInteractive) is RDP. Type 9 (NewCredentials) is pass-the-hash (the user's credentials are used without interactive logon).
Hands-on: build the NE authentication baseline:
DeviceLogonEvents
| where Timestamp > ago(7d) and ActionType == "LogonSuccess"
| summarize LogonCount = count() by LogonType, Protocol, DeviceName
| sort by LogonCount desc
The baseline reveals: which logon types are normal for each device type (workstations should see mostly Type 2, servers should see mostly Type 3 and Type 10), which authentication protocols are in use (Kerberos for domain, NTLM for legacy), and which devices receive the most remote authentications (servers, domain controllers).
DeviceImageLoadEvents is valuable but volume-managed. MDE may drop events on busy devices to manage cloud processing costs. For comprehensive DLL visibility: deploy Sysmon Event ID 7 (ES11.4) which captures every DLL load without volume management. Use DeviceImageLoadEvents for hunting (accept that some events may be missing) and Sysmon for forensic completeness.
The pass-the-hash detection through logon events relies on understanding NTLM versus Kerberos authentication patterns. In a properly configured Active Directory environment, Kerberos is the default authentication protocol for domain-joined devices accessing domain resources. NTLM is used as a fallback when Kerberos is not available: when accessing a resource by IP address rather than hostname, when accessing a non-domain-joined resource, or when the domain controller is unreachable. An environment where the majority of network logons use NTLM (rather than Kerberos) has either a configuration issue or an active pass-the-hash attack.
The NE-specific baseline for authentication protocols: domain-joined workstations authenticating to domain resources should use Kerberos almost exclusively. NTLM authentication from a domain-joined workstation to a domain-joined server is anomalous and warrants investigation. NTLM from non-domain-joined devices (BYOD, manufacturing floor devices) to domain resources is expected if those devices access file shares or internal web applications. Build the authentication protocol baseline from the thirty-day historical data and flag deviations.
DeviceImageLoadEvents hunting for DLL side-loading requires understanding the DLL search order: when a process loads a DLL, Windows searches directories in a specific order (application directory, system directories, PATH directories). An attacker who places a malicious DLL with the name of a legitimate DLL in a directory that is searched before the legitimate location hijacks the load. The hunting query identifies this pattern by finding DLLs loaded from non-standard paths that share names with legitimate system DLLs. Each finding requires investigation: is the DLL a legitimate application component installed to a non-standard location, or is it a malicious hijack?
Authentication and DLL hunting
Hunt 1: Brute force detection. 20+ failed logons from a single IP or 5+ targeted accounts indicate credential attacks.
DeviceLogonEvents
| where Timestamp > ago(1d) and ActionType == "LogonFailed"
| summarize FailCount = count(), Targets = dcount(AccountName) by RemoteIP, DeviceName
| where FailCount > 20 or Targets > 5
| sort by FailCount desc
Hunt 2: Pass-the-hash indicators. NTLM network logons from non-DC sources to multiple devices suggest credential reuse.
DeviceLogonEvents
| where Timestamp > ago(7d)
| where LogonType == "Network" and Protocol == "NTLM"
| where AccountName !in ("svc-sccm", "svc-backup")
| summarize DevicesAccessed = dcount(DeviceName) by AccountName, RemoteIP
| where DevicesAccessed > 3
Hunt 3: Unsigned DLLs loaded by system processes. System processes (svchost, lsass) loading unsigned DLLs from non-system paths indicates DLL side-loading or injection.
DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in ("svchost.exe", "lsass.exe", "services.exe")
| where not(FolderPath startswith "C:\\Windows\\System32")
| where SignatureState != "SignedValid"
| project Timestamp, DeviceName, FileName, FolderPath, InitiatingProcessFileName, SignatureState
Hunt 4: DLLs from temp directories. Legitimate DLLs are installed to Program Files. DLLs loaded from temp suggest dropped payloads.
DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where FolderPath has_any ("\\Temp\\", "\\Downloads\\", "\\AppData\\")
| summarize LoadCount = count(), Devices = dcount(DeviceName) by FileName, FolderPath, SHA256
| where Devices < 3
DLL hunting is volume-managed by MDE on busy devices. For comprehensive DLL visibility, deploy Sysmon Event ID 7 (ES11.4).
Troubleshooting
Query returns too many results: Add baseline exclusions for the dominant legitimate patterns. If the top 80% of results come from a known-good source (e.g., SCCM, Windows Update, a specific LOB application), exclude that source and review the remaining 20%.
Query returns zero results: Broaden the criteria. Remove one filter at a time until results appear. If broadening to the maximum (e.g., just searching for the process name without any command-line or parent filters) still returns zero, the technique is not present in the data, which is a valid finding (no evidence of this technique in the last 7 days).
The DLL side-loading detection is particularly relevant for NE because several of the NE attack chains use DLL-based execution. In the CHAIN-ENDPOINT scenario, the attacker loaded a malicious DLL into a legitimate signed process using DLL search order hijacking. The DeviceImageLoadEvents hunt query that identifies unsigned DLLs loaded by system processes from non-standard paths would have detected this technique. The limitation is that DeviceImageLoadEvents is volume-managed by MDE on busy devices, meaning some DLL load events may be dropped. For devices where DLL visibility is critical (domain controllers, high-value servers), deploy Sysmon Event ID 7 to capture every DLL load without volume management.
The DLL side-loading hunt from this sub should be prioritized for the weekly hunt rotation because DLL-based attacks are increasingly common in sophisticated threat campaigns. Unlike executable-based attacks (which are caught by AV signatures, WDAC policies, and process creation detections), DLL-based attacks operate within legitimate signed processes and may not trigger any process-level detection. The DLL hunt query identifies the loading of unsigned or anomalous DLLs into system processes, catching the technique at the DLL load level rather than the process level. This is a detection layer that process-focused detections do not cover, making the DLL hunt a unique and valuable contribution to the overall detection posture.
The authentication and DLL hunting queries from this sub complement the process-focused hunts by targeting techniques that operate at the logon and library-loading level rather than the process creation level.
When hunting for DLL side-loading: focus on unsigned DLLs loaded by signed processes from non-standard paths. Legitimate DLLs are signed and loaded from System32 or Program Files. An unsigned DLL loaded from AppData by svchost.exe is a strong indicator of DLL side-loading or injection, investigate the DLL hash and the loading process context.
The authentication baseline construction is essential for pass-the-hash detection accuracy. Without understanding the normal ratio of Kerberos to NTLM authentication in NE's environment, the analyst cannot distinguish a pass-the-hash attack (NTLM logon from a non-DC) from legitimate NTLM fallback (a device accessing a resource by IP address rather than hostname). The baseline query from this sub reveals the current authentication protocol distribution across the fleet. If NTLM constitutes more than twenty percent of domain logons, investigate: which devices and applications are forcing NTLM fallback, and can they be reconfigured to use Kerberos? Reducing legitimate NTLM usage reduces the false positive rate for pass-the-hash detections, making the detection more actionable.
The authentication hunting baseline should be refreshed quarterly alongside the network baseline and the parent-child process baseline. Each baseline reflects the current state of NE's environment. As applications change, as new servers are provisioned, and as authentication patterns evolve, the baselines drift from reality. The quarterly refresh keeps the baselines current, ensuring hunting queries produce meaningful results rather than false positives from outdated exclusions or false negatives from missing new baseline patterns.