Mirror

Anti-Debugging Tips (Views: 100)

Problem/Question/Abstract:
I found this article on the net. The author is Roy Hasson (roy@soft-analysts.com)
Anti-debugging tricks are key components in any software protection solution.  Protecting the application’s code from prying eyes can increase the security of the product a great deal.  There are many tools available to on the Internet for analyzing code at runtime and in a deadlisting.  It is difficult to protect against every single tool out there, but 99% of the time a finite set of tools will be used.  Such tools are SoftIce, a real mode debugger, IDA and W32dasm which are tools to disassemble an application.  In the following paper several anti-debugging techniques will be demonstrated.  Any code example will be giving in a x86 assembly language due to it’s easy of use in such operations

Answer:

The tricks –



Name: MeltIce



Description: Detect the presence of SoftIce and many other memory resident tools by attempting to load SoftIce related devices such its display driver, or its access driver.

Devices such as SICE, NTICE, SIWVID, FROGICE.



Example:



szSICE = “\\.\SICE” ;

hSICE = CreateFileA(szSICE, GENERIC_READ, NULL, NULL, OPEN_EXISTING\

FILE_ATTRIBUTE_READONLY, NULL);

if (hSICE !=NULL) printf (Error: softice detected);

else continue…..



Notes: This trick is old and well known, it still works well but is easily circumvented.





Name: BoundsChecker



Decription: SoftIce uses something called BoundsChecker for trapping certain exceptions, this interface can be exploited to detect the presence of SoftIce.



Example:



mov ebp,”BCHK”

mov ax,4

int 3

cmp ax,4

jne softice_detected



Notes: An older trick but still works, it is very simple to implement thus should be used just to add additional checks.





Name:  VXD ID



Description:  SoftIce could be detected by reading its VXD ID from memory.



Example:



mov ax,01684h

mov bx,0202h ; VXD ID for SoftIce, check out Ralf Brown's interrupt list

xor di,di

mov es,di

int 2fh

mov ax,es

add di,ax

cmp di,0

jne softice_detected



Notes:  Unlike the first two examples where a cracker could mask the device names, this VXD ID can not be changes therefore allowing for an easy detection.





Name: Interrupt 68



Description: SoftIce hooks interrupt 68 for its own use, one can use that to detect its presence.



Example:  Checks if INT68 handler was installed by SoftIce.



mov ah,43h

int 68h

cmp ax,0f386h

jnz softice_detected



Example2:  Checks the interrupt descriptor table if a handle is installed for INT68.



xor ax,ax

mov es,ax

mov bx, word ptr es:[68h*4]

mov es, word ptr es:[68h*4+2]

mov eax, 0f43fc80h

cmp eax, dword ptr es:[ebx]

jnz softice_detected



Notes: A good trick, not so simple to overcome.





Name:  INT3 detection



Description:  When a user sets a breakpoint on a certain part of the application or on an API, the debugger replaces the byte where the breakpoint is to be inserted with an INT3 (0xCC) instruction.  When the application is restarted the INT3 is executed and the debugger is triggered.



Solution: In order to protect critical sections of code the application could search the portion of code during runtime for the 0xCC op code and if detected it will be replaced with the original byte thus not triggering the debugger.  A more complex solution would be to install a new INT3 handler which will be triggered whenever a breakpoint if executed thus taking control away from the debugger and leading the attacker on to a different path.



Example:  Hooking an interrupt





;---------------------------------------------------------------------------

; SIDT stores the Interrupt Descriptor Table (IDT) Register into the specified ; operand

;------------------------------------------------------------------------------

push eax

sidt [esp-2]                  ; get pointer to the interrupt descriptor table

pop eax                 ; and get the pointer to the 32 bit base address of                           ; the table

mov ebx, 3

mov edx, 8

imul ebx, edx

add eax, ebx                  ; 3*8 bytes and eax points to the int 3 info now



;-----------------------------------

;save old INT 3 handler

;----------------------------------

mov dx, [eax+06h]           ; get the low word offset from the interrupt gate table

shl edx, 010h           ; shift into high word position in register

mov dx, [eax]     ; get the high word part of the offset from the interrupt                     ; gate table

push edx

pop OldInterruptHandler             ; save old INT 3 handler



;-----------------------------------

;insert new INT 3 handler

;-----------------------------------

mov edx, offset InterruptHandler



cli                           ; ignore maskable external interrupts

mov [eax],dx                        ; modify the high word part of the offset

shr edx,010h                        ; shift into low word position in register

mov [eax+6],dx                ; modify the low word part of the offset

sti                           ; resume responding to interrupts



ret









;---------------------------------------------------------------------------

; Restore old interrupt handler back

;---------------------------------------------------------------------------



push eax

sidt [esp-2]                  ; get pointer to the interrupt descriptor table

pop eax                 ; and get the pointer to the 32 bit base address of                           ; the table

add eax, 18h                 ; 3*8 bytes and eax points to the int 3 info now



;-----------------------------------

;insert old INT 3 handler

;-----------------------------------

mov edx, OldInterruptHandler



cli                           ; ignore maskable external interrupts

mov [eax],dx                        ; modify the high word part of the offset

shr edx,010h                        ; shift into low word position

mov [eax+6],dx                ; modify the low word part of the offset

sti                           ; resume responding to interrupts



ret





Notes:  This is a good technique and if understood could be very powerful.  Make sure to restore the old interrupt back when you are done with it.



Name: Import scanning

Description: When setting breakpoints on Windows APIs the debugger replaces the first byte in the imported function with the op code 0xCC.  A routine could be implemented to go through the import table scanning each individual imported function or selected ones for a 0xCC byte.

Notes:  Might slow an application down but could be beneficial if certain APIs are being used inside the protection scheme that if breakpointed could result in compromise.

Conclusion –

There are many different ways to detect debugging tools and the retaliation is limitless.   The best way for retaliation is to either redirect an attacker down the wrong path or just exit the application without error messages warming them of your attempts to detect their tools.



<< Back to main page