Debugger Evasion
This detection identifies adversary attempts to detect and evade debuggers during malware execution. Adversaries employ techniques including Windows API calls (IsDebuggerPresent, CheckRemoteDebuggerPresent, NtQueryInformationProcess), manual inspection of the Process Environment Block (PEB) BeingDebugged flag, querying /proc/self/status for TracerPID on Linux, enumerating foreground window titles for known debugger strings, abusing Structured Exception Handling (SEH) to detect suspended execution, and flooding debug channels via OutputDebugStringW loops. Known malware families employing these techniques include Lumma Stealer, AsyncRAT, PlugX, StealBit, and StrelaStealer. Detection focuses on process command-line artifacts exposing debug API references, suspicious process access events with debug-level rights, Linux /proc/self/status reads, and behavioral signals such as non-system processes with very short lifespans that terminate after potential environment checks.
What is T1622 Debugger Evasion?
Debugger Evasion (T1622) maps to the Defense Evasion and Discovery tactics — the adversary is trying to avoid being detected in MITRE ATT&CK.
This page provides production-ready detection logic for Debugger Evasion, covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Defense Evasion Discovery
- Technique
- T1622 Debugger Evasion
- Canonical reference
- https://attack.mitre.org/techniques/T1622/
let DebuggerWindowNames = dynamic(["x32dbg", "x64dbg", "windbg", "ollydbg", "dnspy", "immunity", "cheatengine", "processhacker", "x64_dbg"]);
let DebugApiTerms = dynamic(["IsDebuggerPresent", "CheckRemoteDebuggerPresent", "NtQueryInformationProcess", "BeingDebugged", "DebugActiveProcess", "OutputDebugStringW", "OutputDebugStringA"]);
let LegitParents = dynamic(["devenv.exe", "code.exe", "msbuild.exe", "dotnet.exe", "vstest.console.exe", "testhost.exe", "WerFault.exe", "rider64.exe", "clion64.exe"]);
DeviceProcessEvents
| where TimeGenerated > ago(24h)
| where FileName !in~ (LegitParents)
| where InitiatingProcessFileName !in~ (LegitParents)
| where (
// Direct debugger API references in command line (scripted, injected, or reflective loading)
ProcessCommandLine has_any (DebugApiTerms)
or
// Debugger window name enumeration — Lumma Stealer / AsyncRAT pattern
(ProcessCommandLine has_any (DebuggerWindowNames) and ProcessCommandLine !contains "install" and FileName !in~ (DebuggerWindowNames))
or
// Linux /proc/self/status read for TracerPID field
(ProcessCommandLine has "/proc/self/status" and ProcessCommandLine has_any ("TracerPID", "cat ", "grep ", "awk ", "read "))
or
// .NET managed code debugger detection via PowerShell reflection
(ProcessCommandLine has_any ("Debugger.IsAttached", "Debugger.Launch", "[System.Diagnostics.Debugger]") and FileName in~ ("powershell.exe", "pwsh.exe"))
)
| extend RiskScore = case(
ProcessCommandLine has_any ("NtQueryInformationProcess", "BeingDebugged"), 90,
ProcessCommandLine has_any ("IsDebuggerPresent", "CheckRemoteDebuggerPresent"), 80,
ProcessCommandLine has_any ("Debugger.IsAttached", "Debugger.Launch"), 75,
ProcessCommandLine has_any (DebuggerWindowNames), 70,
ProcessCommandLine has "/proc/self/status", 65,
60
)
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine, FolderPath,
SHA256, ProcessId, InitiatingProcessId, RiskScore
| order by RiskScore desc, TimeGenerated desc Detects processes exhibiting debugger evasion behaviors via command-line analysis. Covers Win32 API debug checks (IsDebuggerPresent, CheckRemoteDebuggerPresent, NtQueryInformationProcess), debugger window name enumeration matching Lumma Stealer and AsyncRAT patterns, Linux /proc/self/status TracerPID reads, and .NET Debugger class usage via PowerShell reflection. A risk score is assigned by evasion method specificity.
Data Sources
Required Tables
False Positives
- Legitimate developer toolchains and IDEs (Visual Studio, VS Code, JetBrains Rider, CLion) that call debugger presence checks internally during build and test pipelines
- .NET and Java applications using Debugger.IsAttached or equivalent to conditionally emit verbose diagnostic logging in development builds deployed to test environments
- Game anti-cheat modules (Easy Anti-Cheat, BattlEye, Vanguard) that legitimately enumerate debugger and memory editor window titles to enforce fair play policies
- Commercial software protection wrappers (Themida, VMProtect, ENIGMA Protector) that check for analysis environments as part of legitimate copy protection enforcement
- Security testing frameworks and red team tools running in authorized engagements where analysts are intentionally testing these API call patterns
Sigma rule & cross-platform mapping
The detection logic for Debugger Evasion (T1622) 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 T1622
References (9)
- https://attack.mitre.org/techniques/T1622/
- https://github.com/processhacker/processhacker
- https://www.apriorit.com/dev-blog/784-anti-debugging-techniques-csharp
- https://github.com/LordNoteworthy/al-khaser
- https://www.cadosecurity.com/blog/p2pinfect-the-rusty-peer-to-peer-self-replicating-worm/
- https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/hellhounds-operation-lahat/
- https://research.checkpoint.com/2021/stopping-serial-killer-catching-the-next-strike-of-cl0p/
- https://objective-see.org/blog/blog_0x59.html
- https://www.fortiguard.com/threat-signal-report/4703/strelastealer-infostealer-continues-targeting-european-countries
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 IsDebuggerPresent Check via PowerShell P/Invoke
Expected signal: Sysmon EventCode=1 with Image=powershell.exe and CommandLine containing 'IsDebuggerPresent' and 'DllImport'. Microsoft Defender for Endpoint DeviceProcessEvents entry with matching FileName and ProcessCommandLine fields.
- Test 2Windows NtQueryInformationProcess ProcessDebugPort Check via PowerShell
Expected signal: Sysmon EventCode=1 with Image=powershell.exe and CommandLine containing 'NtQueryInformationProcess'. Windows Security EventCode=4688 may fire with truncated command line depending on audit policy. DeviceProcessEvents entry in Defender with full ProcessCommandLine.
- Test 3Linux TracerPID Debugger Check via /proc/self/status
Expected signal: Linux auditd syscall record for openat/open with file path '/proc/self/status' (if auditd watches /proc), or Sysmon for Linux EventCode=1 with CommandLine containing '/proc/self/status' and 'TracerPid'. Available in Syslog or linux_secure Splunk sourcetype.
- Test 4Windows Debugger Window Enumeration via PowerShell (Lumma Stealer Pattern)
Expected signal: Sysmon EventCode=1 with Image=powershell.exe and CommandLine containing 'GetForegroundWindow' and debugger strings ('x32dbg', 'x64dbg', etc.). DeviceProcessEvents entry with matching ProcessCommandLine.
Response Playbook
Triage
- Step 1: Collect the full binary path (FolderPath), SHA256 hash, and signing status of the triggering process. Submit SHA256 to your threat intel platform (VirusTotal, internal sandbox). Unsigned binaries or binaries signed by unknown or revoked certificates in non-standard paths are high-confidence indicators of malware.
- Step 2: Examine the parent/initiating process. If the parent is a browser, Office application, PDF reader, or archive utility, treat this as a likely phishing-delivered payload and escalate immediately. If the parent is a developer IDE or build tool, document and deprioritize pending further indicators.
- Step 3: Check whether the process exited within seconds of creation. Query DeviceProcessEvents for ProcessTerminated events with the same ProcessId within 30 seconds — rapid self-termination after a debugger check is a hallmark of evasion-aware malware that detected an analysis environment.
- Step 4: Search DeviceProcessEvents and DeviceNetworkEvents for other activity from the same SHA256 across the fleet over the prior 7 days. Widespread execution suggests a dropper campaign; first-time-seen hashes from isolated endpoints suggest targeted activity.
- Step 5: Review DeviceNetworkEvents within ±10 minutes of the detection event for external connections from the same process. C2 connections (especially on non-standard ports or to newly-registered domains) immediately following a successful debugger check confirm an active implant that passed its evasion gates.
- Step 6: For Linux endpoints, check auditd syscall logs (openat with pathname=/proc/self/status) or Sysmon for Linux EventCode=1 records. Correlate with subsequent file writes to /tmp, /dev/shm, or /var/tmp and any outbound connections from the same process session.
Containment
- If SHA256 is confirmed malicious via threat intel or sandbox behavioral match: isolate the endpoint immediately via Defender for Endpoint Live Response network isolation or MDM quarantine policy, and terminate the process tree using `Stop-Process -Force`.
- Suspend the user account associated with the executing process if there is evidence of credential theft or lateral movement — check DeviceLogonEvents and SecurityEvent 4648/4768 from the endpoint for anomalous authentication in the surrounding time window.
- Create a SHA256 block indicator in Defender for Endpoint custom indicators or your SIEM-driven EDR to prevent re-execution of the same payload on other endpoints fleet-wide.
- If the process made external network connections, block the destination IPs and domains at the perimeter firewall and web proxy. Query all endpoints for connections to the same destinations over the prior 30 days to identify additional compromised hosts.
Evidence Collection
- Collect a full process memory dump using Defender for Endpoint Live Response (`run GetProcessMemoryDump.ps1 <PID>`) or via WinPMEM if the process is still running — packed or encrypted payloads unpack in memory and the dump will expose the true payload code, strings, and embedded C2 configuration.
- Export Windows Prefetch files from C:\Windows\Prefetch\ for the triggering process. Prefetch records every DLL loaded and file accessed, and will show ntdll.dll resolution patterns confirming which native APIs were imported.
- Collect the binary itself using Live Response `getfile <full_path>` and submit to a behavioral sandbox (ANY.RUN, Joe Sandbox, Cuckoo) to observe whether the sample executes differently when a debugger is not attached.
- Export Windows Event Log channels: Security, System, and Microsoft-Windows-Sysmon/Operational covering a 4-hour window before and after the detection timestamp.
- On Linux: collect /proc/<PID>/maps, /proc/<PID>/cmdline, /proc/<PID>/environ, and any files written to /tmp, /var/tmp, /dev/shm, or home directory hidden folders during the same session. Use `auditctl -l` to confirm audit rules are capturing openat syscalls.
- Capture ETW trace data from the Microsoft-Windows-DotNETRuntime provider if the process is a managed .NET application — this will confirm Debugger.IsAttached calls and record JIT compilation events revealing true payload behavior.
Escalation Criteria
- ! Escalate to P1 immediately if the process is confirmed malicious AND made external network connections — active C2 communication means the payload passed its evasion checks and is executing its mission.
- ! Escalate immediately if the initiating/parent process is a document reader, browser, script interpreter, or macro-enabled Office application — this indicates successful exploitation of a user-facing attack vector.
- ! Escalate if the same binary hash or behavioral pattern is detected on more than two endpoints within a 24-hour window — this indicates active campaign propagation.
- ! Escalate if the triggering process or processes in its tree accessed LSASS memory (DeviceProcessEvents where FileName == 'lsass.exe' with OpenProcess access), read registry hive files (SAM, SYSTEM, SECURITY), or accessed credential stores — debugger evasion protecting a credential theft payload is a critical combined indicator.
- ! Escalate if the process created persistence mechanisms (Run/RunOnce registry keys, scheduled tasks, services, or startup folder entries) — evasion techniques are typically employed to protect payloads intended to survive reboot.
Investigation Guide
Forensic Artifacts
- >
Windows Prefetch files (C:\Windows\Prefetch\<PROCESS>-*.pf) — reveal DLL load order and all file accesses, confirming which debug-detection APIs were imported from ntdll.dll and kernel32.dll - >
Process memory dump — packed/encrypted payloads unpack into memory; dynamic analysis of the dump exposes the true payload code, embedded configuration, and C2 addresses regardless of evasion outcome - >
Sysmon EventCode=7 (Image Load) records for the process — reveal ntdll.dll, kernel32.dll, and any custom DLL loads that implement anti-debug routines - >
Windows Mini Crash Dumps (C:\Windows\Minidump\) — SEH-based debugger detection intentionally triggers structured exceptions; if the exception propagates to a crash, a minidump is generated with call stack evidence - >
Auditd syscall logs on Linux: syscall=openat with path /proc/self/status — confirms TracerPID check was attempted; correlated with process tree provides attribution to the suspicious process - >
ETW provider Microsoft-Windows-DotNETRuntime trace — captures Debugger.IsAttached and Debugger.Launch calls in managed .NET code with full call stack context - >
Registry: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options — presence of debugger assignments for suspicious process names may indicate an attacker-configured trap or anti-analysis technique
Tuning Guidance
Primary noise sources are developer toolchains, game anti-cheat modules, and commercial software protection systems. Recommended tuning steps: (1) Build an allowlist of code-signed binaries from known software vendors (Microsoft, JetBrains, Unity, Epic Games, anti-cheat vendors) and exclude them by publisher certificate or SHA256. (2) Scope detections to non-standard process locations — processes executing from C:\Windows\, C:\Program Files\, and C:\Program Files (x86)\ should carry elevated investigation thresholds before alerting. (3) Enrich alerts with asset context from your CMDB — detections on developer workstations tagged as such in inventory are lower priority than identical detections on servers, kiosks, or end-user machines without development tool assignments. (4) For the short-lifespan hunting query, tune the threshold between 5–30 seconds depending on environment noise tolerance; 15 seconds is a reasonable starting point that catches evasion-triggered exits while excluding most legitimate quick-exit utilities. (5) Correlate findings with DeviceNetworkEvents — an anti-debug alert with a simultaneous external connection is far higher priority than an isolated process-creation event with no network activity.
Hunting Queries
Hunts for non-system processes outside standard installation paths that spawn and terminate within 15 seconds — a strong behavioral indicator of malware that detected an analysis environment (debugger, sandbox, or AV) and self-terminated to avoid analysis.
// Hunt: non-system processes with very short lifespans — strong indicator of evasion-triggered self-termination
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where ActionType == "ProcessCreated"
| where FolderPath !startswith "C:\\Windows\\"
| where FolderPath !startswith "C:\\Program Files\\"
| where FolderPath !startswith "C:\\Program Files (x86)\\"
| where FileName !in~ ("conhost.exe", "WerFault.exe", "cmd.exe", "timeout.exe", "ping.exe", "more.exe", "where.exe")
| join kind=inner (
DeviceProcessEvents
| where ActionType == "ProcessTerminated"
| project DeviceId, TermProcId=ProcessId, TerminationTime=TimeGenerated
) on DeviceId, $left.ProcessId == $right.TermProcId
| extend LifespanSeconds = datetime_diff('second', TerminationTime, TimeGenerated)
| where LifespanSeconds between (0 .. 15)
| project TimeGenerated, DeviceName, FileName, FolderPath, ProcessCommandLine,
InitiatingProcessFileName, LifespanSeconds, SHA256
| order by TimeGenerated desc index=windows sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" (EventCode=1 OR EventCode=5)
| eval proc_guid=ProcessGuid
| stats min(_time) as start_time max(_time) as end_time count as event_count by proc_guid Image CommandLine Computer
| where event_count >= 2
| eval lifespan_sec=end_time - start_time
| where lifespan_sec <= 15 AND lifespan_sec >= 0
| where NOT match(Image, "(?i)(conhost\.exe|WerFault\.exe|timeout\.exe|ping\.exe|cmd\.exe|where\.exe)")
| where NOT match(Image, "(?i)(C:\\\\Windows\\\\|C:\\\\Program Files)")
| table start_time Computer Image CommandLine lifespan_sec
| sort - start_time Hunts for processes outside standard installation paths that load ntdll.dll (required for NtQueryInformationProcess native API resolution) AND make external network connections on non-standard ports — indicates a debugger-aware implant that resolved anti-debug APIs and subsequently reached its C2 communication phase.
// Hunt: processes loading ntdll.dll from non-standard paths AND making external network connections
// Indicates a debugger-aware implant that resolved native APIs and successfully reached C2 phase
DeviceImageLoadEvents
| where TimeGenerated > ago(7d)
| where FileName =~ "ntdll.dll"
| where InitiatingProcessFolderPath !startswith "C:\\Windows\\"
| where InitiatingProcessFolderPath !startswith "C:\\Program Files\\"
| where InitiatingProcessFolderPath !startswith "C:\\Program Files (x86)\\"
| where InitiatingProcessFileName !in~ ("devenv.exe", "code.exe", "msbuild.exe", "dotnet.exe")
| project DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath,
InitiatingProcessSHA256, InitiatingProcessId, DllLoadTime=TimeGenerated
| join kind=inner (
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemoteIPType != "Private"
| where RemotePort !in (80, 443)
| project DeviceName, NetworkTime=TimeGenerated, RemoteIP, RemotePort,
InitiatingProcessFileName, InitiatingProcessFolderPath, InitiatingProcessId
) on DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath, InitiatingProcessId
| where abs(datetime_diff('minute', NetworkTime, DllLoadTime)) < 10
| project DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath,
InitiatingProcessSHA256, RemoteIP, RemotePort, DllLoadTime, NetworkTime
| order by DllLoadTime desc index=windows sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=7 ImageLoaded="*\\ntdll.dll"
| where NOT match(Image, "(?i)(C:\\\\Windows\\\\|C:\\\\Program Files|devenv\.exe|code\.exe|msbuild\.exe)")
| eval proc_id=ProcessId, host=Computer
| join type=inner proc_id host [
search index=windows sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
| where NOT match(DestinationIp, "^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.|::1|fe80)")
| where NOT (DestinationPort=80 OR DestinationPort=443)
| eval proc_id=ProcessId, host=Computer
| stats count as conn_count values(DestinationIp) as dst_ips values(DestinationPort) as dst_ports by proc_id host Image
]
| table _time host Image conn_count dst_ips dst_ports
| sort - _time Hunts for non-system processes that open a handle to their own process (SourceProcessId == TargetProcessId via Sysmon EventCode=10). CheckRemoteDebuggerPresent internally opens a handle to the calling process to inspect debug state — self-targeting process access from non-development binaries is anomalous.
// Hunt: processes making process-access calls to themselves — self-debugging check pattern
// CheckRemoteDebuggerPresent opens its own process handle; detect OpenProcess to self from non-system processes
DeviceEvents
| where TimeGenerated > ago(7d)
| where ActionType == "OpenProcessApiCall"
| where InitiatingProcessFolderPath !startswith "C:\\Windows\\"
| where InitiatingProcessFolderPath !startswith "C:\\Program Files\\"
| where InitiatingProcessFileName !in~ ("devenv.exe", "code.exe", "WerFault.exe", "taskmgr.exe", "procexp.exe", "procexp64.exe")
| extend TargetPid = tolong(extractjson("$.TargetProcessId", AdditionalFields))
| where TargetPid == ProcessId
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath,
InitiatingProcessCommandLine, InitiatingProcessSHA256, ProcessId, TargetPid
| order by TimeGenerated desc index=windows sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=10
| where NOT match(SourceImage, "(?i)(C:\\\\Windows\\\\|C:\\\\Program Files|devenv\.exe|code\.exe|WerFault\.exe|taskmgr\.exe)")
| where SourceProcessId=TargetProcessId
| eval host=Computer
| table _time host SourceImage SourceProcessId TargetProcessId GrantedAccess CallTrace
| sort - _time Atomic Red Team Tests
Simulates malware-style debugger presence check by calling the Win32 IsDebuggerPresent API via PowerShell Add-Type P/Invoke reflection. This technique is used by AsyncRAT and PlugX to detect analysis environments before executing the primary payload.
Command
powershell -ExecutionPolicy Bypass -Command "$sig = '[DllImport(\"kernel32.dll\")] public static extern bool IsDebuggerPresent();'; $t = Add-Type -MemberDefinition $sig -Name 'DbgCheck' -Namespace Win32 -PassThru; $r = $t::IsDebuggerPresent(); Write-Host \"IsDebuggerPresent result: $r\"" Cleanup
# No persistent artifacts — PowerShell in-memory Add-Type is unloaded with the session Expected Telemetry
Sysmon EventCode=1 with Image=powershell.exe and CommandLine containing 'IsDebuggerPresent' and 'DllImport'. Microsoft Defender for Endpoint DeviceProcessEvents entry with matching FileName and ProcessCommandLine fields.
Expected Detection
KQL query matches on DebugApiTerms has_any 'IsDebuggerPresent', assigns RiskScore=80. SPL query matches debugger_api_hit=1, evasion_score=80, evasion_type='Win32 Debugger API Check'.
Simulates advanced debugger detection using NtQueryInformationProcess with ProcessInformationClass=7 (ProcessDebugPort), a more reliable detection method than IsDebuggerPresent used by sophisticated malware families including StealBit and StrelaStealer. A non-zero DebugPort return value indicates an attached debugger.
Command
powershell -ExecutionPolicy Bypass -Command "$sig = '[DllImport(\"ntdll.dll\")] public static extern int NtQueryInformationProcess(IntPtr hProcess, int procInfoClass, ref IntPtr procInfo, int procInfoLen, out int retLen);'; $t = Add-Type -MemberDefinition $sig -Name 'NtAPI' -Namespace Win32 -PassThru; $port = [IntPtr]::Zero; $rlen = 0; $status = $t::NtQueryInformationProcess([System.Diagnostics.Process]::GetCurrentProcess().Handle, 7, [ref]$port, [IntPtr]::Size, [ref]$rlen); Write-Host \"NtQueryInformationProcess status=0x$($status.ToString('X')) DebugPort=$port\"" Cleanup
# No persistent artifacts — in-memory operation only Expected Telemetry
Sysmon EventCode=1 with Image=powershell.exe and CommandLine containing 'NtQueryInformationProcess'. Windows Security EventCode=4688 may fire with truncated command line depending on audit policy. DeviceProcessEvents entry in Defender with full ProcessCommandLine.
Expected Detection
KQL query matches on 'NtQueryInformationProcess' in ProcessCommandLine, assigns RiskScore=90 (highest tier). SPL evasion_score=90, evasion_type='Native API Debug Check'.
Simulates Linux malware debugger detection by reading /proc/self/status and parsing the TracerPID field. A non-zero TracerPID indicates the process is being traced by a debugger (gdb, strace, ltrace). This technique is used by P2PInfect and Hellhounds malware on Linux systems.
Command
bash -c 'tracer=$(grep -m1 "^TracerPid:" /proc/self/status | awk "{print \$2}"); if [ "$tracer" -ne "0" ] 2>/dev/null; then echo "DEBUGGER DETECTED: TracerPid=$tracer"; else echo "No debugger: TracerPid=$tracer"; fi' Cleanup
# No cleanup required — read-only access to /proc virtual filesystem Expected Telemetry
Linux auditd syscall record for openat/open with file path '/proc/self/status' (if auditd watches /proc), or Sysmon for Linux EventCode=1 with CommandLine containing '/proc/self/status' and 'TracerPid'. Available in Syslog or linux_secure Splunk sourcetype.
Expected Detection
KQL query matches on ProcessCommandLine has '/proc/self/status' and 'TracerPID', RiskScore=65. SPL query matches proc_status_hit=1, evasion_score=65, evasion_type='Linux /proc TracerPID Check'.
Simulates Lumma Stealer's technique of enumerating the foreground window title to check for known debugger and analysis tool strings ('x32dbg', 'x64dbg', 'windbg', 'ollydbg', 'dnspy'). If a debugger window is in the foreground, the malware terminates to avoid analysis.
Command
powershell -ExecutionPolicy Bypass -Command "$sig = '[DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow(); [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder buf, int max);'; $t = Add-Type -MemberDefinition $sig -Name 'WinCheck' -Namespace Win32 -PassThru; $hwnd = $t::GetForegroundWindow(); $title = New-Object System.Text.StringBuilder 256; $t::GetWindowText($hwnd, $title, 256) | Out-Null; $dbgs = @('x32dbg','x64dbg','windbg','ollydbg','dnspy','immunity'); $hit = $dbgs | Where-Object { $title.ToString() -match $_ }; Write-Host \"Window='$($title)' DebuggerFound=$($null -ne $hit)\"" Cleanup
# No persistent artifacts created Expected Telemetry
Sysmon EventCode=1 with Image=powershell.exe and CommandLine containing 'GetForegroundWindow' and debugger strings ('x32dbg', 'x64dbg', etc.). DeviceProcessEvents entry with matching ProcessCommandLine.
Expected Detection
KQL query matches on DebuggerWindowNames has_any pattern, assigns RiskScore=70. SPL query matches debugger_window_hit=1, evasion_score=70, evasion_type='Debugger Window Enumeration'.