Debugger Detection

May 1, 2024 · View on GitHub

ID B0001
Objective(s) Anti-Behavioral Analysis
Related ATT&CK Techniques None
Anti-Analysis Type Detection
Version 2.3
Created 1 August 2019
Last Modified 27 April 2024

Debugger Detection

Malware detects whether it's being executed inside a debugger by checking for artifacts such as DLLs, processes, and registry keys [1]. If malware detects a debugger, it may change its execution path or change its code to initiate a crash [2].

While many methods are listed in the table below, among the most commonly used are:

  • Using APIs such as IsDebuggerPresent, CheckRemoteDebuggerPresent, and OutputDebugString
  • Reading the BeingDebugged bit (is it a 1 or 0) in the Process Environment Block (PEB)
  • Checking whether a software breakpoint instruction is used (INT3; 0xCC opcode)

Details on detecting debuggers can be found in the references.

Methods

NameIDDescription
API Hook DetectionB0001.001Module bounds based [7].
Anti-debugging InstructionsB0001.034Malware code contains mnemonics related to anti-debugging (e.g., rdtsc, icebp).
CheckRemoteDebuggerPresentB0001.002The kernel32!CheckRemoteDebuggerPresent function calls NtQueryInformationProcess with ProcessInformationClass parameter set to 7 (ProcessDebugPort constant).This method is related to Unprotect technique U0121.
Check ProcessesB0001.038The malware may check running processes for specific strings such as "malw" to detect a analysis environment.
CloseHandleB0001.003(NtClose); If an invalid handle is passed to the CloseHandle function and a debugger is present, then an EXCEPTION_INVALID_HANDLE (0xC0000008) exception will be raised. [7] This method is related to Unprotect technique U0114.
Debugger ArtifactsB0001.004Malware may detect a debugger by its artifact (window title, device driver, exports, etc.).
Hardware BreakpointsB0001.005(SEH/GetThreadContext); Debug registers will indicate the presence of a debugger. See [7] for details. This method is related to Unprotect technique U0127.
InterruptionB0001.006If an interruption is mishandled by the debugger, it can cause a single-byte instruction to be inadvertently skipped, which can be detected by malware. Examples include Interrupt 0x2d and Interrupt 1 [7]. This method is related to Unprotect technique U0129.
IsDebuggerPresentB0001.008The kernel32!IsDebuggerPresent API function call checks the PEB BeingDebugged flag to see if the calling process is being debugged. It returns 1 if the process is being debugged, 0 otherwise. This is one of the most common ways of debugger detection.This method is related to Unprotect technique U0122.
Memory BreakpointsB0001.009(PAGE_GUARD); Guard pages trigger an exception the first time they are accessed and can be used to detect a debugger. See [7] for details. This method is related to Unprotect technique U0102.
Memory Write WatchingB0001.010[7]
Monitoring ThreadB0001.011Malware may spawn a monitoring thread to detect tampering, breakpoints, etc.
NtQueryInformationProcessB0001.012Calling NtQueryInformationProcess with its ProcessInformationClass parameter set to 0x07 (ProcessDebugPort constant) will cause the system to set ProcessInformation to -1 if the process is being debugged. Calling with ProcessInformationClass set to 0x0E (ProcessDebugFlags) or 0x11 (ProcessDebugObject) are used similarly. Testing "ProcessDebugPort" is equivalent to using the kernel32!CheckRemoteDebuggerPresent API call (see next method). This method is related to Unprotect technique U0120.
NtQueryObjectB0001.013The ObjectTypeInformation and ObjectAllTypesInformation flags are checked for debugger detection. This method is related to Unprotect technique U0118.
NtSetInformationThreadB0001.014Calling this API with a fake class length or thread handle can indicate whether it is hooked. After calling NtSetInformationThread properly, the HideThreadFromDebugger flag is checked with the NtQueryInformationThread API. [7]This method is related to Unprotect technique U0119.
NtYieldExecution/SwitchToThreadB0001.015[7]
OutputDebugStringB0001.016(GetLastError); The OutputDebugString function will demonstrate different behavior depending whether or not a debugger is present. See [7] for details. This method is related to Unprotect technique U0117.
Page Exception Breakpoint DetectionB0001.017[7]
Parent ProcessB0001.018(Explorer.exe); Executing an application by a debugger will result in the parent process being the debugger process rather than the shell process (Explorer.exe) or the command line. Malware checks its parent process; if it's not explorer.exe, it's assumed to be a debugger. [7]
Process Environment BlockB0001.019The Process Environment Block (PEB) is a Windows data structure associated with each process that contains several fields, such as "BeingDebugged," "NtGlobalFlag," and "IsDebugged". Testing the value of this PEB field of a particular process can indicate whether the process is being debugged. Testing "BeingDebugged" is equivalent to using the kernel32!IsDebuggerPresent API call (see separate method). This method is related to Unprotect technique U0113.
Process Environment Block BeingDebuggedB0001.035The BeingDebugged field is tested to determine whether the process is being debugged.
Process Environment Block IsDebuggedB0001.037The IsDebugged field is tested to determine whether the process is being debugged.
Process Environment Block NtGlobalFlagB0001.036The NtGlobalFlag field is tested to determine whether the process is being debugged. This method is related to Unprotect technique U0111.
Process JobsB0001.020[7]
ProcessHeapB0001.021Process heaps are affected by debuggers. Malware can detect a debugger by checking heap header fields such as Flags (debugger present if value greater than 2) or ForceFlags (debugger present if value greater than 0).This method is related to Unprotect technique U0112.
RtlAdjustPrivilegeB0001.022Malware may call RtlAdjustPrivilege to detect if a debugger is attached (or to prevent a debugger from attaching).
SeDebugPrivilegeB0001.023(Csrss.exe); Using the OpenProcess function on the csrss.exe process can detect a debugger. [7]
SetHandleInformationB0001.024(Protected Handle)
Software BreakpointsB0001.025(INT3/0xCC) This method is related to Unprotect technique U0105.
Stack CanaryB0001.026Similar to the anti-exploitation method of the same name, malware may try to detect mucking with values on the stack.
TIB AwareB0001.027Malware may access information in the Thread Information Block (TIB) for debug detection or process obfuscation detection. The TIB can be accessed as an offset of the segment register (e.g., fs:[20h]).
TLS CallbacksB0001.029[7]
Timing/Delay CheckB0001.028Malware may compare time between two points to detect unusual execution, such as the (relative) massive delays introduced by debugging. This method is related to Unprotect techniques U110 and U1308.
Timing/Delay Check GetTickCountB0001.032Malware uses GetTickCount function in a timing/delay check. This method is related to Unprotect technique U0125.
Timing/Delay Check QueryPerformanceCounterB0001.033Malware uses QueryPerformanceCounter in a timing/delay check. This method is related to Unprotect techniques U110 and U1309.
UnhandledExceptionFilterB0001.030The UnhandledExceptionFilter function is called if no registered exception handlers exist, but it will not be reached if a debugger is present. See [7] for details. Row 11 This method is related to Unprotect technique U0108.
WudfIsAnyDebuggerPresentB0001.031Includes use of WudfIsAnyDebuggerPresent, WudfIsKernelDebuggerPresent, WudfIsUserDebuggerPresent.

Use in Malware

NameDateMethodDescription
Redhip2011--Redhip uses general approaches to detecting user level debuggers (e.g., Process Environment Block 'Being Debugged' field), as well as specific checks for kernel level debuggers like SOFTICE. [4]
Redhip2011B0001.032Redhip checks for a time delay using GetTickCount. [15]
Redhip2011B0001.035Redhip checks for PEB BeingDebugged flag. [15]
Gamut2014B0001.006The malware detects debuggers using an INT 03h trap. [8]
Gamut2014B0001.008The malware detects debuggers using IsDebuggerPresent. [8]
Rombertik2015B0001.016The malware calls the Windows API OutputDebugString function 335,000 times. [9]
Rombertik2015B0001.032The malware checks for a time delay via GetTickCount. [15]
Rombertik2015B0001.038An anti-analysis function within the packer is called to check the username and filename of the executing process for strings like “malwar”, “sampl”, “viru”, and “sandb”. [9]
Poison Ivy2005B0001.005Poison Ivy Variant checks for breakpoints and exits immediately if found. [13]
Poison Ivy2005B0001.008Poison Ivy uses the IsDebuggerPresent API function call to check if the process is running in a debugger. [13]
Matanbuchus2021B0001.032The malware calls GetTickCount64 to retrieve timestamp. Malware executes Sleep and Beep in a repeated loop for 10 times. [11] [12]
Ursnif2016B0001.028The malware manipulates TLS Callbacks while injecting to a child process. [12]
Dark Comet2008B0001.032The malware checks for a time delay via GetTickCount. [15]
Hupigon2013B0001.025The malware checks for software breakpoints. [15]
Hupigon2013B0001.032The malware checks for a time delay via GetTickCount. [15]
Hupigon2013B0001.034The malware executes anti-debugging instructions. [15]
UP0072016B0001.032The malware checks for a time delay via GetTickCount. [15]

Detection

Tool: capaMappingAPIs
check for trap flag exceptionDebugger Detection (B0001)--
check for software breakpointsDebugger Detection::Software Breakpoints (B0001.025)--
check process job objectDebugger Detection (B0001)kernel32.QueryInformationJobObject, kernel32.OpenProcess
check for PEB BeingDebugged flagDebugger Detection::Process Environment Block BeingDebugged (B0001.035)--
check for time delay via GetTickCountDebugger Detection::Timing/Delay Check GetTickCount (B0001.032)--
check for protected handle exceptionDebugger Detection::SetHandleInformation (B0001.024)SetHandleInformation, CloseHandle
check for OutputDebugString errorDebugger Detection::OutputDebugString (B0001.016)kernel32.SetLastError, kernel32.GetLastError, kernel32.OutputDebugString
check for unexpected memory writesDebugger Detection::Memory Write Watching (B0001.010)kernel32.GetWriteWatch
check for kernel debugger via shared user data structureDebugger Detection (B0001)--
check for time delay via QueryPerformanceCounterDebugger Detection::Timing/Delay Check QueryPerformanceCounter (B0001.033)--
check for hardware breakpointsDebugger Detection::Hardware Breakpoints (B0001.005)kernel32.GetThreadContext
check ProcessDebugPortDebugger Detection::NtQueryInformationProcess (B0001.012)NtQueryInformationProcess
check for debugger via APIDebugger Detection::CheckRemoteDebuggerPresent (B0001.002)kernel32.CheckRemoteDebuggerPresent, WUDFPlatform.WudfIsAnyDebuggerPresent, WUDFPlatform.WudfIsKernelDebuggerPresent, WUDFPlatform.WudfIsUserDebuggerPresent
check for debugger via APIDebugger Detection::WudfIsAnyDebuggerPresent (B0001.031)kernel32.CheckRemoteDebuggerPresent, WUDFPlatform.WudfIsAnyDebuggerPresent, WUDFPlatform.WudfIsKernelDebuggerPresent, WUDFPlatform.WudfIsUserDebuggerPresent
check for PEB NtGlobalFlag flagDebugger Detection::Process Environment Block NtGlobalFlag (B0001.036)--
execute anti-debugging instructionsDebugger Detection::Anti-debugging Instructions (B0001.034)--
PEB accessDebugger Detection::Process Environment Block (B0001.019)--
Tool: CAPEMappingAPIs
antidebug_checkremotedebuggerpresentDebugger Detection (B0001)CheckRemoteDebuggerPresent, NtQueryInformationProcess
antiav_nthookengine_libsDebugger Detection (B0001)LdrGetDllHandle, LdrLoadDll
antiav_nthookengine_libsDebugger Detection::API Hook Detection (B0001.001)LdrGetDllHandle, LdrLoadDll
antidebug_setunhandledexceptionfilterDebugger Detection (B0001)SetUnhandledExceptionFilter
antidebug_setunhandledexceptionfilterDebugger Detection::UnhandledExceptionFilter (B0001.030)SetUnhandledExceptionFilter
antidebug_addvectoredexceptionhandlerDebugger Detection (B0001)AddVectoredExceptionHandler
antidebug_outputdebugstringDebugger Detection (B0001)GetLastError, SetLastError, OutputDebugStringW, OutputDebugStringA
antidebug_outputdebugstringDebugger Detection::OutputDebugString (B0001.016)GetLastError, SetLastError, OutputDebugStringW, OutputDebugStringA
antidebug_gettickcountDebugger Detection (B0001)GetTickCount
antidebug_gettickcountDebugger Detection::Timing/Delay Check GetTickCount (B0001.032)GetTickCount
antidebug_guardpagesDebugger Detection (B0001)VirtualProtectEx, NtAllocateVirtualMemory, NtProtectVirtualMemory
antidebug_guardpagesDebugger Detection::Memory Breakpoints (B0001.009)VirtualProtectEx, NtAllocateVirtualMemory, NtProtectVirtualMemory
antidebug_ntsetinformationthreadDebugger Detection (B0001)NtSetInformationThread
antidebug_ntsetinformationthreadDebugger Detection::NtSetInformationThread (B0001.014)NtSetInformationThread
antidebug_debugactiveprocessDebugger Detection (B0001)DebugActiveProcess

B0001.019 Snippet

Anti-Behavioral Analysis::Debugger Detection::Process Environment Block SHA256: e33a713b96b45e2b2e0da350c0fdaaf865139607066aadff3b67b0ced82ca8bc Location: 0x1800270A2
mov     rax, qword ptr GS:[0x60]        ; GS:[0x60] contains a pointer to the Windows Process Environment Block on 64-bit versions of Windows.  This command is copying that pointer into the rax register.

References

[1] S. Yosef,"RASPBERRY ROBIN: ANTI-EVASION HOW-TO & EXPLOIT ANALYSIS," https://research.checkpoint.com/, 18 Apr 2023. [Online]. Available: https://research.checkpoint.com/2023/raspberry-robin-anti-evasion-how-to-exploit-analysis/.

[2] M. Sikorski and A. Honig, Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software, No Starch Press, 2012.

[3] Peter Ferrie, "The 'Ultimate' Anti-Debugging Reference," 4 May 2011. https://anti-reversing.com/Downloads/Anti-Reversing/The_Ultimate_Anti-Reversing_Reference.pdf.

[4] https://web.archive.org/web/20200815134441/https://www.fireeye.com/blog/threat-research/2011/01/the-dead-giveaways-of-vm-aware-malware.html

[5] Ayoub Faouzi (LordNoteworthy), Al-Khaser v0.79. https://github.com/LordNoteworthy/al-khaser

[6] Nicolas Falliere, Symantec, "Windows Anti-Debug Reference," 11 September 2007. https://www.symantec.com/connect/articles/windows-anti-debug-reference.

[7] Anti Debugging Tricks, Al-Khaser. https://github.com/LordNoteworthy/al-khaser/wiki/Anti-Debugging-Tricks

[8] https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/gamut-spambot-analysis/

[9] https://blogs.cisco.com/security/talos/rombertik

[10] https://www.mandiant.com/sites/default/files/2021-09/rpt-poison-ivy.pdf

[11] https://www.0ffset.net/reverse-engineering/matanbuchus-loader-analysis/

[12] https://www.cyberark.com/resources/threat-research-blog/inside-matanbuchus-a-quirky-loader

[13] https://www.fortinet.com/blog/threat-research/deep-analysis-of-new-poison-ivy-variant

[14] https://www.fireeye.com/blog/threat-research/2017/11/ursnif-variant-malicious-tls-callback-technique.html

[15] capa v4.0, analyzed at MITRE on 10/12/2022