Log Enumeration
This detection identifies adversaries enumerating system and service logs to gather intelligence about the environment, including authentication records, security events, software inventory, and network hosts. The detection focuses on the use of native Windows utilities such as wevtutil.exe and PowerShell cmdlets (Get-EventLog, Get-WinEvent) to query or export Windows event logs, Azure VM Agent's CollectGuestLogs.exe for cloud-hosted log collection, and Linux tools like journalctl and ausearch for authentication log enumeration. Suspicious patterns include querying Security and System event logs outside of known administrative context, bulk exporting logs, and log enumeration activity originating from unusual parent processes indicative of post-exploitation. Real-world threat actors including Volt Typhoon, Ember Bear, and Aquatic Panda have used these techniques to identify authenticated sessions, map the environment, and monitor incident response activity in real time.
What is T1654 Log Enumeration?
Log Enumeration (T1654) maps to the Discovery tactic — the adversary is trying to figure out your environment in MITRE ATT&CK.
This page provides production-ready detection logic for Log Enumeration, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. The queries below are rated medium severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Discovery
- Technique
- T1654 Log Enumeration
- Canonical reference
- https://attack.mitre.org/techniques/T1654/
let TimeWindow = 1d;
let SuspiciousParents = dynamic(["cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe", "regsvr32.exe", "rundll32.exe", "msiexec.exe"]);
DeviceProcessEvents
| where TimeGenerated > ago(TimeWindow)
| where (
// wevtutil log enumeration and export
(FileName =~ "wevtutil.exe" and ProcessCommandLine has_any ("qe ", "epl ", "query-events", "export-log", "gl ", "qel ", "get-log"))
// PowerShell native log cmdlets
or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("Get-EventLog", "Get-WinEvent", "Get-WinEvent", "[System.Diagnostics.EventLog]"))
// Azure VM Guest log collection
or FileName =~ "CollectGuestLogs.exe"
)
| extend
LogTarget = case(
ProcessCommandLine has_any ("security", "Security"), "Security",
ProcessCommandLine has_any ("system", "System"), "System",
ProcessCommandLine has_any ("application", "Application"), "Application",
ProcessCommandLine has_any ("powershell", "PowerShell"), "PowerShell Operational",
ProcessCommandLine has "ForwardedEvents", "Forwarded Events",
"Other"
),
IsBulkExport = iff(
ProcessCommandLine has_any ("epl", "export-log", "Out-File", "Export-Csv", "Set-Content", " > ", "Tee-Object"),
true, false
),
SuspiciousParent = iff(
InitiatingProcessFileName in~ (SuspiciousParents),
true, false
),
RiskScore = case(
ProcessCommandLine has_any ("epl", "export-log", "Out-File") and ProcessCommandLine has "security", 9,
ProcessCommandLine has_any ("epl", "export-log", "Out-File"), 7,
InitiatingProcessFileName in~ (SuspiciousParents), 8,
ProcessCommandLine has "security", 6,
true, 3
)
| where RiskScore >= 3
| project
TimeGenerated,
DeviceName,
AccountName,
AccountDomain,
FileName,
ProcessCommandLine,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
LogTarget,
IsBulkExport,
SuspiciousParent,
RiskScore
| order by RiskScore desc, TimeGenerated desc Detects log enumeration activity using wevtutil.exe (query/export operations), PowerShell cmdlets (Get-EventLog, Get-WinEvent), and Azure CollectGuestLogs.exe. Scores results by risk level based on whether Security logs are targeted, whether logs are being bulk-exported, and whether the parent process is suspicious (script interpreters, LOLBins). Aligns with Volt Typhoon and Ember Bear TTPs.
Data Sources
Required Tables
False Positives
- SIEM agents and log forwarders (e.g., Splunk Universal Forwarder, Elastic Winlogbeat) regularly query Windows event logs using wevtutil or WinAPI equivalents
- IT operations teams and sysadmins running wevtutil.exe or Get-WinEvent during troubleshooting, capacity planning, or scheduled log archival
- Backup and compliance solutions (e.g., Veeam, Commvault, Netwrix Auditor) that export Security and System logs as part of audit retention workflows
- Azure Monitor Agent and Microsoft Monitoring Agent (MMA/AMA) using CollectGuestLogs.exe on cloud-hosted VMs as part of normal diagnostics
- Vulnerability scanners and configuration management tools (e.g., Nessus, Qualys, SCCM) that enumerate event log state to assess system health
Sigma rule & cross-platform mapping
The detection logic for Log Enumeration (T1654) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
category: process_creation
product: windows Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1654
References (4)
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Windows Log Enumeration via wevtutil - Query and Export Security Logs
Expected signal: Sysmon Event ID 1 (process create) for wevtutil.exe with CommandLine containing 'qe Security' and 'epl Security'. Security Event ID 4688 if process auditing is enabled. DeviceFileEvents showing creation of .txt and .evtx files in TEMP directory.
- Test 2Windows Log Enumeration via PowerShell Get-WinEvent
Expected signal: Sysmon Event ID 1 for powershell.exe with CommandLine containing 'Get-WinEvent' and 'Export-Csv'. PowerShell ScriptBlock Event ID 4104 showing full script content. DeviceFileEvents for CSV file creation in TEMP.
- Test 3Linux Authentication Log Enumeration
Expected signal: Linux auditd process execution events for journalctl, cat, ausearch, lastb. Syslog entries showing file reads against /var/log/auth.log. File creation events for /tmp/auth_enum.txt and /tmp/ssh_audit.json via auditd OPEN syscall records.
- Test 4Remote Log Enumeration via wevtutil with /remote flag
Expected signal: Sysmon Event ID 1 with wevtutil.exe CommandLine containing '/r:' flag and target hostname. Network connection from wevtutil.exe to target port 135/445 (RPC/SMB for remote EventLog access). Security Event ID 4648 (explicit credentials logon) on source if /u: flag is used.
Response Playbook
Triage
- Step 1: Identify the account context — determine if the process ran under a service account, local admin, domain admin, or interactive user session. Service accounts running wevtutil unexpectedly outside of known windows are a stronger indicator of compromise.
- Step 2: Examine the parent process chain. Use DeviceProcessEvents to walk up the process tree: if the parent chain includes cmd.exe spawned from a web process, Office application, or script interpreter (wscript, mshta), treat as high-confidence post-exploitation.
- Step 3: Determine which logs were targeted. Targeting the Security log specifically (searching for logon events, authentication records) is consistent with adversary reconnaissance. Targeting PowerShell Operational logs may indicate the adversary is monitoring defensive tooling.
- Step 4: Check whether the output was exported or redirected. Look for command-line flags 'epl' (export-log), 'Out-File', '>' redirection, or Export-Csv. An export — especially to a temp directory or user-writable path — indicates staging for exfiltration.
- Step 5: Correlate with other discovery activity in the same session window. Run a pivot on the same DeviceName and AccountName within ±30 minutes to look for co-occurring T1016 (network config), T1033 (user discovery), T1049 (network connections), T1087 (account enumeration) or T1069 (permission group discovery).
- Step 6: Check if CollectGuestLogs.exe was invoked on a cloud VM outside of expected Azure diagnostics schedules or from a user session rather than SYSTEM/AzureGuestAgent. This tool produces a zip of all VM logs and is a high-confidence exfil vector when triggered manually.
Containment
- If bulk export of Security logs is confirmed and the exporting process was not a known agent, immediately isolate the endpoint via MDE Live Response or Defender Isolation to prevent further staging or exfiltration.
- Disable or reset the account that performed the log enumeration if it is interactive/user-owned, pending investigation. If it is a service account, rotate credentials and audit which services use it.
- Block outbound traffic from the affected host to any destination observed receiving exported log files, using a network ACL or host-based firewall rule pushed via Group Policy or MDE.
- Revoke any active sessions for the compromised account across all endpoints using 'Disable-ADAccount' or equivalent Entra ID revoke-sessions API.
- If CollectGuestLogs.exe was abused on an Azure VM, review and restrict the VM's managed identity permissions and audit Azure Diagnostic Extension settings in the subscription.
Evidence Collection
- Export Windows Security event log (Event ID 4688 process creation or Sysmon Event ID 1) for the affected host covering the full attack window to a forensic share.
- Collect prefetch files from C:\Windows\Prefetch — look for WEVTUTIL.EXE-*.pf and POWERSHELL.EXE-*.pf with recent last-execution timestamps that corroborate the alert timeline.
- If wevtutil 'epl' (export-log) or PowerShell Out-File was used, search the filesystem for the output file. Common adversary drop locations: %TEMP%, C:\Users\Public, C:\Windows\Temp, C:\ProgramData.
- Pull the full PowerShell ScriptBlock logs (Event ID 4104 in Microsoft-Windows-PowerShell/Operational) to reconstruct the full script used to enumerate or export event logs.
- Collect memory of the process that invoked log enumeration if still running, or of its parent, to recover any in-memory tooling (e.g., Cobalt Strike stager, reflective DLL) that initiated the activity.
- For cloud environments: pull Azure Activity Log and Diagnostic Settings audit trail to determine if CollectGuestLogs.exe was invoked via the Azure Serial Console or VM extension REST API.
- Run a timeline of all files created in the session window on the affected host using DeviceFileEvents to identify any log exports that may have been staged for exfiltration.
Escalation Criteria
- ! Escalate immediately if log enumeration is followed within the same session by evidence of lateral movement (T1021) — this indicates the adversary is mapping authentication records to plan their next hop.
- ! Escalate if bulk export of Security logs to a network share or outbound HTTP/SFTP destination is confirmed — this constitutes active data exfiltration and requires IR engagement.
- ! Escalate if the same account is observed enumerating logs across multiple endpoints in the environment — this is consistent with domain-wide reconnaissance by an actor with elevated credentials.
- ! Escalate if log enumeration activity is observed in tandem with log clearing (T1070.001, Event ID 1102) — this is a strong indicator the adversary is both surveilling and covering their tracks.
- ! Escalate if log enumeration is detected on a domain controller or SIEM server — access to centralized logs gives the adversary full visibility into incident response operations.
- ! Escalate if log enumeration precedes or accompanies credential access techniques (T1003 LSASS, T1558 Kerberoasting) — the adversary may be targeting authentication logs to identify privileged accounts for targeting.
Investigation Guide
Forensic Artifacts
- >
Prefetch files: WEVTUTIL.EXE-*.pf (C:\Windows\Prefetch) with timestamps indicating when the tool was run - >
PowerShell ScriptBlock logs: Event ID 4104 in Microsoft-Windows-PowerShell/Operational containing full script content for Get-EventLog or Get-WinEvent activity - >
Process creation events: Security Event ID 4688 or Sysmon Event ID 1 with full command line capturing wevtutil flags and target log names - >
File system artifacts: exported .evtx files or CSV/text log exports in temp directories (%TEMP%, C:\Windows\Temp, C:\ProgramData, C:\Users\Public) - >
Amcache.hve and ShimCache (SYSTEM registry hive) entries for wevtutil.exe and powershell.exe indicating execution history - >
Windows Event Log record: Security Event ID 4656 (object handle requested) and 4663 (object accessed) against Windows log files if object-level auditing is enabled - >
Azure Activity Log entries for CollectGuestLogs.exe invocations, including caller identity, source IP, and result status - >
Memory artifacts: loaded modules and command history in the process that invoked log enumeration, recoverable via volatility or live response
Tuning Guidance
Start by building a baseline of expected log enumeration sources in your environment: document all log forwarding agents (Splunk UF, Elastic Agent, NXLog), backup tools, and monitoring scripts that legitimately invoke wevtutil or Get-WinEvent. Suppress alerts from those specific AccountNames and ParentProcess paths using a named exclusion list rather than broad wildcards. Focus initial alert tuning on the IsBulkExport=true and SuspiciousParent=true flags — these dramatically reduce false positives while preserving detection of adversarial behavior. For wevtutil specifically, the flags 'qe' (query-events) and 'gl' (get-log) are common in legitimate use, but 'epl' (export-log) to a user-writable path is rare in normal operations and should be treated as high-fidelity. Tune CollectGuestLogs.exe alerts to only alert when invoked by a non-SYSTEM, non-AzureGuestAgent principal on cloud VMs. For PowerShell, combine with ScriptBlock logging (Event ID 4104) to see full script context before alerting — many monitoring scripts use Get-WinEvent with constrained queries that are easily distinguishable from adversarial bulk collection.
Hunting Queries
Hunts for high-frequency log enumeration sessions where 5 or more log queries occur within a 5-minute window, indicative of automated tooling or scripts performing bulk log reconnaissance rather than manual administrative activity.
// Hunt: High-frequency log enumeration - multiple queries within short window suggesting automated scanning
let Threshold = 5;
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName =~ "wevtutil.exe" or
(FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("Get-EventLog", "Get-WinEvent"))
| summarize
QueryCount = count(),
UniqueLogTargets = dcount(ProcessCommandLine),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Commands = make_set(ProcessCommandLine, 10)
by DeviceName, AccountName, bin(TimeGenerated, 5m)
| where QueryCount >= Threshold
| extend SessionDuration = datetime_diff('minute', LastSeen, FirstSeen)
| order by QueryCount desc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| search (Image="*\\wevtutil.exe" OR ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe") AND (CommandLine="*Get-EventLog*" OR CommandLine="*Get-WinEvent*")))
| bin _time span=5m
| stats count as query_count, dc(CommandLine) as unique_commands, values(CommandLine) as commands by _time, host, User
| where query_count >= 5
| sort - query_count Hunts for the T1654 + T1070.001 combination: log enumeration followed by log clearing within a 30-minute window on the same host by the same account. This pattern indicates the adversary surveyed logs for useful intelligence and then destroyed evidence — a high-confidence indicator of sophisticated intrusion.
// Hunt: Log enumeration followed by log clearing within the same session (enumerate then destroy)
let LookbackWindow = 7d;
let CorrelationWindow = 30m;
let LogEnum = DeviceProcessEvents
| where TimeGenerated > ago(LookbackWindow)
| where (FileName =~ "wevtutil.exe" and ProcessCommandLine has_any ("qe ", "gl ", "query-events", "get-log"))
or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("Get-EventLog", "Get-WinEvent"))
| project EnumTime = TimeGenerated, DeviceName, AccountName, EnumCommand = ProcessCommandLine;
let LogClear = DeviceProcessEvents
| where TimeGenerated > ago(LookbackWindow)
| where (FileName =~ "wevtutil.exe" and ProcessCommandLine has_any ("cl ", "clear-log"))
or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has "Clear-EventLog")
| project ClearTime = TimeGenerated, DeviceName, AccountName, ClearCommand = ProcessCommandLine;
LogEnum
| join kind=inner LogClear on DeviceName, AccountName
| where ClearTime between (EnumTime .. (EnumTime + CorrelationWindow))
| project EnumTime, ClearTime, DeviceName, AccountName, EnumCommand, ClearCommand
| order by EnumTime desc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| search (Image="*\\wevtutil.exe" AND (CommandLine="*qe *" OR CommandLine="*gl *" OR CommandLine="*query-events*")) OR ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe") AND (CommandLine="*Get-EventLog*" OR CommandLine="*Get-WinEvent*")) OR (Image="*\\wevtutil.exe" AND (CommandLine="*cl *" OR CommandLine="*clear-log*")) OR ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe") AND CommandLine="*Clear-EventLog*")
| eval action=if(match(CommandLine, "(?i)(cl |clear-log|Clear-EventLog)"), "clear", "enumerate")
| sort _time
| streamstats window=10 values(action) as recent_actions by host, User
| where mvfind(recent_actions, "enumerate") >= 0 AND mvfind(recent_actions, "clear") >= 0
| table _time, host, User, action, CommandLine, recent_actions Hunts for wevtutil.exe using the /remote: flag to query event logs on remote hosts, which indicates the adversary is performing lateral log reconnaissance rather than local-only enumeration. Multiple remote targets queried from one host is a strong indicator of domain-wide credential-based reconnaissance.
// Hunt: Log enumeration targeting multiple remote hosts (lateral reconnaissance via WinRM, RPC, or UNC path)
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName =~ "wevtutil.exe"
and ProcessCommandLine has_any ("/r:", "/remote:", "\\\\", "\\\\\\\\")
| extend RemoteTarget = extract(@"(?i)(?:/r:|/remote:)([^\s]+)", 1, ProcessCommandLine)
| where isnotempty(RemoteTarget)
| summarize
TargetCount = dcount(RemoteTarget),
Targets = make_set(RemoteTarget, 20),
Commands = make_set(ProcessCommandLine, 10),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by DeviceName, AccountName
| where TargetCount >= 2
| order by TargetCount desc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
| search Image="*\\wevtutil.exe" AND (CommandLine="*/r:*" OR CommandLine="*/remote:*" OR CommandLine="*\\\\*")
| rex field=CommandLine "(?i)(?:/r:|/remote:)(?P<remote_target>[^\s]+)"
| where isnotnull(remote_target) AND remote_target!=""
| stats dc(remote_target) as target_count, values(remote_target) as targets, values(CommandLine) as commands by host, User
| where target_count >= 2
| sort - target_count Atomic Red Team Tests
Simulates adversary use of wevtutil.exe to query Security event logs for authentication records (mimicking Volt Typhoon TTP) and export them to a staging file for exfiltration.
Command
wevtutil.exe qe Security /q:"*[System[EventID=4624]]" /f:text /c:50 > %TEMP%\sec_logs.txt
wevtutil.exe epl Security %TEMP%\security_export.evtx Cleanup
del %TEMP%\sec_logs.txt 2>nul
del %TEMP%\security_export.evtx 2>nul Expected Telemetry
Sysmon Event ID 1 (process create) for wevtutil.exe with CommandLine containing 'qe Security' and 'epl Security'. Security Event ID 4688 if process auditing is enabled. DeviceFileEvents showing creation of .txt and .evtx files in TEMP directory.
Expected Detection
Alert should fire on wevtutil.exe with 'qe' and 'epl' flags, RiskScore >= 7 (export + security log). IsBulkExport=true, LogTarget=Security.
Uses PowerShell Get-WinEvent to enumerate Security and System event logs and export results to CSV, simulating post-exploitation reconnaissance to identify authenticated sessions and services.
Command
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-WinEvent -LogName Security -MaxEvents 100 | Where-Object {$_.Id -in @(4624,4625,4648)} | Select-Object TimeCreated,Id,Message | Export-Csv -Path $env:TEMP\auth_events.csv -NoTypeInformation; Get-WinEvent -LogName System -MaxEvents 50 | Select-Object TimeCreated,Id,LevelDisplayName,Message | Export-Csv -Path $env:TEMP\sys_events.csv -NoTypeInformation" Cleanup
Remove-Item $env:TEMP\auth_events.csv -ErrorAction SilentlyContinue
Remove-Item $env:TEMP\sys_events.csv -ErrorAction SilentlyContinue Expected Telemetry
Sysmon Event ID 1 for powershell.exe with CommandLine containing 'Get-WinEvent' and 'Export-Csv'. PowerShell ScriptBlock Event ID 4104 showing full script content. DeviceFileEvents for CSV file creation in TEMP.
Expected Detection
Alert on PowerShell Get-WinEvent with Export-Csv, RiskScore 7-9. IsBulkExport=true, LogTarget=Security. May also trigger data staging detection if CSV is large.
Uses native Linux utilities to enumerate authentication and system logs, simulating Aquatic Panda TTP of reading auth logs prior to selective deletion for defense evasion.
Command
journalctl -u ssh --since '7 days ago' --no-pager -o json > /tmp/ssh_audit.json
cat /var/log/auth.log | grep -E 'Accepted|Failed|sudo' > /tmp/auth_enum.txt
ausearch -ts yesterday -te now -k logins 2>/dev/null >> /tmp/auth_enum.txt
lastb -n 100 >> /tmp/auth_enum.txt Cleanup
rm -f /tmp/ssh_audit.json /tmp/auth_enum.txt Expected Telemetry
Linux auditd process execution events for journalctl, cat, ausearch, lastb. Syslog entries showing file reads against /var/log/auth.log. File creation events for /tmp/auth_enum.txt and /tmp/ssh_audit.json via auditd OPEN syscall records.
Expected Detection
Linux-side detection should trigger on rapid sequential access to /var/log/auth.log combined with output redirection. Auditd rules watching reads of /var/log/auth.log and /var/log/secure by non-root interactive sessions should generate alerts.
Uses wevtutil.exe /remote flag to query event logs on a remote host, simulating lateral log reconnaissance where an attacker with credentials queries multiple hosts' Security logs from a single compromised workstation.
Command
wevtutil.exe gl Security /r:%COMPUTERNAME% /u:DOMAIN\testuser /p:TestPassword1!
wevtutil.exe qe Security /r:%COMPUTERNAME% /q:"*[System[EventID=4672]]" /c:20 /f:text Cleanup
No files created. Authentication artifacts will appear in Security log on target. Expected Telemetry
Sysmon Event ID 1 with wevtutil.exe CommandLine containing '/r:' flag and target hostname. Network connection from wevtutil.exe to target port 135/445 (RPC/SMB for remote EventLog access). Security Event ID 4648 (explicit credentials logon) on source if /u: flag is used.
Expected Detection
Remote log enumeration hunting query fires when /remote: flag detected. RiskScore 6+ depending on log target. Network telemetry should show RPC connection from the querying host.