Anti Debug With Exception
Anti Debug With Exception
Introduction
Several techniques for detecting exception swallowing debuggers have been documented. The concept is simple: by design, debuggers handle certain kinds of exceptions. If such an exception is wrapped in a try block, the exception handle is only executed if a debugger is not attached. Hence it can be inferred that a debugger is attached whenever the exception block is not executed.
Interrupt 0x2C
Interrupt 0x2C raises a debug assertion exception. This exception is consumed by WinDbg, but none of the other debuggers tested handled it. The instruction can be generated using the __int2c intrinsic. This interrupt only works on Vista or later. Because of this, the windows version is dynamically checked, and if it is less than six false is returned.
BOOL IsDebuggerPresent_Int2c() { OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); if (osvi.dwMajorVersion < 6) return FALSE; __try { __int2c(); } __except(1) { return FALSE; } return TRUE; }
Interrupt 0x2D
When interrupt 0x2D is executed Windows raises a breakpoint exception.
BOOL IsDebuggerPresent_Int2d() { __try { __asm int 0x2d } __except(1) { return FALSE; } return TRUE; }
ICEBP (0xF1)
ICEBP is an undocumented instruction that serves as a single byte interrupt 1, generating a single step exception.
BOOL IsDebuggerPresent_IceBp() { __try { __asm __emit 0xF1 } __except(1) { return FALSE; } return TRUE; }
RaiseException
Several different types of exceptions generated with the RaiseException function are swallowed by debuggers. OutputDebugString, a function commonly used to detect an attached debugger, relies on RaiseException. The effective exception codes are as follows: STATUS_BREAKPOINT STATUS_SINGLE_STEP DBG_PRINTEXCEPTION_C DBG_RIPEXCEPTION DBG_CONTROL_C DBG_CONTROL_BREAK DBG_COMMAND_EXCEPTION (0x80000003) (0x80000004) (0x40010006) (0x40010007) (0x40010005) (0x40010008) (0x40010009)
BOOL TestExceptionCode(DWORD dwCode) { __try { RaiseException(dwCode, 0, 0, 0); } __except(1) { return FALSE; } return TRUE; } BOOL IsDebuggerPresent_RipException() { return TestExceptionCode(DBG_RIPEXCEPTION); }
Compatibility Chart
VS2008 SP1 Interrupt 3 (1 Byte) Interrupt 3 (2 Byte) Interrupt 0x2C (Vista and later) Interrupt 0x2D ICEBP (0xF1) Trap Flag RaiseException STATUS_BREAKPOINT RaiseException STATUS_SINGLE_STEP RaiseException DBG_PRINTEXCEPTION_C RaiseException DBG_RIPEXCEPTION RaiseException DBG_CONTROL_C RaiseException DBG_CONTROL_BREAK RaiseException DBG_COMMAND_EXCEPTION RaiseException ASSERTION_FAILURE RaiseException STATUS_GUARD_PAGE_VIOLATION RaiseException SEGMENT_NOTIFICATION RaiseException EXCEPTION_WX86_SINGLE_STEP RaiseException EXCEPTION_WX86_BREAKPOINT X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X VS2010 SP1 X WinDbg 6.12.1.633 X OllyDbg 2.01A4 X X Ida 5.0
X X X
Resources
Anti-unpacker tricks - part two http://www.virusbtn.com/virusbulletin/archive/2009/01/vb200901-anti-unpacker-tricks Anti-unpacker tricks - part three http://www.virusbtn.com/virusbulletin/archive/2009/02/vb200902-anti-unpacker-tricks Windows Anti-Debug Reference http://www.symantec.com/connect/articles/windows-anti-debug-reference
Undocumented OpCodes: ICEBP http://www.rcollins.org/secrets/opcodes/ICEBP.html EFLAGS Individual Bit Flags http://www.c-jump.com/CIS77/ASM/Instructions/I77_0070_eflags_bits.htm __int2c http://msdn.microsoft.com/en-us/library/5d6627x5.aspx Reversing: Secrets of Reverse Engineering http://www.amazon.com/Reversing-Secrets-Engineering-Eldad-Eilam/dp/0764574817 The _emit Pseudoinstruction http://msdn.microsoft.com/en-us/library/1b80826t(v=vs.80).aspx NTSTATUS values http://msdn.microsoft.com/en-us/library/cc704588(v=prot.10).aspx