# برنامه نویسی سطح پایین > برنامه نویسی اسمبلی خانواده x86 >  win32 Anti-Debugging Tricks

## Best Programmer

The  IsDebuggerPresent function  indicates  whether  the  calling process is

 running  under the  context  of  a  debugger. This function is exported from

 KERNEL32.DLL.

 BOOL IsDebuggerPresent&#40;VOID&#41;

 - Parameters

 This function has no parameters.

 - Return Value

 &amp;thorn; If the current process is running in the context of a debugger, the return

   value is nonzero.

 &amp;thorn; If the current process  is not running  in the  context of a debugger, the

   return value is zero.

 -&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;

 So, an example for demonstrate this is very simple. Here it goes.

;&amp;Auml;&amp;Auml;&amp;Auml;&#91; CUT HERE &#93;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;

       .586p

       .model flat

extrn   GetProcAddress&#58;PROC

extrn   GetModuleHandleA&#58;PROC

extrn   MessageBoxA&#58;PROC

extrn   ExitProcess&#58;PROC

                .data

szTitle         db      "IsDebuggerPresent Demonstration",0

msg1            db      "Application Level Debugger Found",0

msg2            db      "Application Level Debugger NOT Found",0

msg3            db      "Error&#58; Couldn't get IsDebuggerPresent.",10

                db      "We're probably under Win95",0

@IsDebuggerPresent db   "IsDebuggerPresent",0

K32             db      "KERNEL32",0

       .code

antidebug1&#58;

        push    offset K32                      ; Obtain KERNEL32 base address

        call    GetModuleHandleA

        or      eax,eax                         ; Check for fails

        jz      error

        push    offset @IsDebuggerPresent       ; Now search for the existence

        push    eax                             ; of IsDebuggerPresent. If

        call    GetProcAddress                  ; GetProcAddress returns an

        or      eax,eax                         ; error, we assume we're in 

        jz      error                           ; Win95

        call    eax                             ; Call IsDebuggerPresent

        or      eax,eax                         ; If it's not 0, we're being

        jnz     debugger_found                  ; debugged

debugger_not_found&#58;

        push    0                               ; Show "Debugger not found"

        push    offset szTitle

        push    offset msg2

        push    0

        call    MessageBoxA

        jmp     exit

error&#58;

        push    00001010h                       ; Show "Error! We're in Win95"

        push    offset szTitle

        push    offset msg3

        push    0

        call    MessageBoxA

        jmp     exit

debugger_found&#58;

        push    00001010h                       ; Show "Debugger found!"

        push    offset szTitle

        push    offset msg1

        push    0

        call    MessageBoxA

exit&#58;

        push    00000000h                       ; Exit program

        call    ExitProcess

end     antidebug1

;&amp;Auml;&amp;Auml;&amp;Auml;&#91; CUT HERE &#93;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;

 Ain't it nice? Micro$oft  did the job for us &#58;&#41; But, of course, don't expect

 this method to work with SoftICE, the g0d ;&#41;

 &#91; Win32&#58; Another way of know if we're under the context of a debugger &#93;

 If you take a look into the article "Win95 Structures and Secrets", that was

 written by Murkry/iKX, and published in the Xine-3, you'll realize that the-

 re is a very cool structure in the FS register. Take a look  into the  field

 FS&#58;&#91;20h&#93;... It's 'DebugContext'. Just make the following&#58;

        mov     ecx,fs&#58;&#91;20h&#93;

        jecxz   not_being_debugger

        &#91;...&#93;   &lt;--- do whatever, we're being debugged &#58;&#41;

 So, if FS&#58;&#91;20h&#93; is  zero, we're not being  debugged. Just enjoy this  little

 and simple method for detect debuggers! Of course, this  can't be applied to

 SoftICE...

 &#91; Win32&#58; Stopping Application level debuggers with SEH &#93;

 I still don't know why,  but the  application level  debuggers die simply if 

 the program  uses SEH. And also  the  code emulators, if we make faults, die

 too &#58;&#41; The SEH, as i published in my article in DDT#1 is used for many inte-

 resting purposes. Well, as  i don' t want to tell you all SEH stuff again, i

 will cut'n'paste my old description &#58;&#41;

 --&#91;DDT#1.2_6&#93;---------------------------------------------------------------

 Well, this is a very simple tutorial about the Structured Exception Handler.

 When i saw SEH implemented in a  virus, i thought "Well, it does a lot. Must

 be very hard  to implement". So i simple skipped its use. But, as my Destiny

 made General Protection Faults  running under NT, as i read in 0BFF70000h, i

 realized that i had  to do something. And SEH was the only way. Well, we can

 do it very complex to understand, or very easy. Of course, i prefer to do it

 more easy &#58;&#41;

 % Setting up the SEH frame %

 &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;

 Firstly we save it for our own safety with a simple text line.

                push    dword ptr fs&#58;&#91;0&#93;

 And now it's time to make  the thingy  to point to our handler &#40;for example,

 imagine that we  used a  call for call the setup of the SEH, and our handler

 is just after that call instructions&#58; we can use  the offset of ret for make

 it point there&#41;

                push    offset SEH_Handler

                mov     fs&#58;&#91;0&#93;,esp

 Well, as  easy as it gets. What  about restore  the original SEH? More easy.

 Simply do the opposite of the first instruction.

                pop     dword ptr fs&#58;&#91;0&#93;

 It's surprising that that very simple thing for implement if our Windoze vi-

 ruses could do for us. For me &#40;as it was the use of SEH i was searching&#41; the

 most important one is  that i can  help  us to  avoid  all that goddamn blue

 screens when we run our Win95 virus under NT  enviroments. That goddamn blue

 screen appears everytime we try to make comparisons over our hardcoded Win95

 kernel under NT.

 % Example of SEH use %

 &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;  &amp;Auml;&amp;Auml;

 Well, you can compile this with&#58;

 tasm32 /m3 /ml sehtest,,;

 tlink32 /Tpe /aa sehtest,sehtest,,import32.lib

;&amp;Auml;&amp;Auml;&amp;Auml;&#91; CUT HERE &#93;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;

        .386p

        .model  flat                            ; Good good... 32 bit r0x0r

extrn   MessageBoxA&#58;PROC                        ; Defined APIs

extrn   ExitProcess&#58;PROC

        .data

szTitle         db      "Structured Exception Handler example",0

szMessage       db      "Intercepted General Protection Fault!",0

        .code

start&#58;

        call    setupSEH                        ; The call pushes the offset

                                                ; past it in the stack rigth?

                                                ; So we will use that &#58;&#41;

exceptionhandler&#58;

        mov     esp,&#91;esp+8&#93;                     ; Error gives us old ESP                          

                                                ; in &#91;ESP+8&#93;

        push    00000000h                       ; Parameters for MessageBoxA

        push    offset szTitle

        push    offset szMessage

        push    00000000h

        call    MessageBoxA

        push    00000000h                       

        call    ExitProcess                     ; Exit Application

setupSEH&#58;

        push    dword ptr fs&#58;&#91;0&#93;                ; Push original SEH handler

        mov     fs&#58;&#91;0&#93;,esp                      ; And put the new one &#40;located

                                                ; after the first call&#41;

        mov     ebx,0BFF70000h                  ; Try to write in kernel &#40;will

        mov     eax,012345678h                  ; generate an exception&#41;

        xchg    eax,&#91;ebx&#93;

end     start

;&amp;Auml;&amp;Auml;&amp;Auml;&#91; CUT HERE &#93;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;

 &#91;...&#93;

 --&#91;DDT#1.2_6&#93;---------------------------------------------------------------

 Well, i hope you understood that. If not... Erhm, forget it &#58;&#41; Also, as the

 other methods presented before, this cannot be applied to SoftICE

 &#91; Win9X&#58; Detect SoftICE &#40;I&#41; &#93;

 Well, i must greet here Super/29A, because he was the one that told me about

 this method. I  broke this into two parts&#58; in  this  one  we will see how to 

 do it from a Ring-0 virus. I won't  put a  whole  example program because it

 would  fill  unnecessary lines, but you  must know  that this method must be

 executed  in Ring-0, and the VxDCall must  be restored because the call-back

 problem &#40;do you remember?&#41;.

 Well, we are  gonna  use the  Virtual Machine Manager &#40;VMM&#41; service Get_DDB,

 so  the  service  will be 00010146h &#40;VMM_Get_DDB&#41;. Let's see the information

 about this service on the SDK.

 -&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;

         mov    eax, Device_ID

         mov    edi, Device_Name

         int    20h                             ; VMMCall Get_DDB

         dd     00010146h

         mov    &#91;DDB&#93;, ecx

 - Determines  whether or not a VxD is installed for the specified device and

 returns a DDB for that device if it is installed.

 - Uses ECX, flags.

 - Returns a DDB for the specified device if the function succeeds;

 - otherwise, returns zero.

 &amp;thorn; Device_ID&#58; The  device  identifier. This  parameter  can be zero for name-

   based devices.

 &amp;thorn; Device_Name&#58; An eight-character  device name  that  is  padded  with blank

   characters. This  parameter  is  only  required if  Device_ID is zero. The

   device name is case-sensitive.

 -&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;

 Well, you are wondering  why all this shit. Very simple, the Device_ID field

 of SoftICE VxD is constant for all programs, as it's registered in Micro$oft

 so we have a weapon again  the marvelous SoftICE. It's Device_ID is 202h al-

 ways. So we should use code like this&#58;

        mov     eax,00000202h

        VxDCall VMM_Get_DDB

        xchg    eax,ecx

        jecxz   NotSoftICE

        jmp     DetectedSoftICE

 Where NotSoftICE  should be  the  continuation  of virus code, and the label

 DetectedSoftICE  should  handle  the action  to perform, as we know that our

 enemy is alive &#58;&#41; I don't suggest anything destructive because, for example,

 would hurt my computer, as i always have SoftICE active &#58;&#41; 

 &#91; Win9X&#58; Detect SoftICE &#40;II&#41; &#93;

 Well, here goes another method for detect the presence of my beloved SoftICE

 but based in the  same  concept of before&#58; the 202h ;&#41; Again i must greet to

 Super &#58;&#41; Well, in  the  Ralph Brown  Interrupt  list  we can see a very cool

 service in the interrupt 2Fh &#40;multiplex&#41;, the 1684h

 -&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;

 Inp.&#58;

        AX = 1684h

        BX = virtual device &#40;VxD&#41; ID &#40;see #1921&#41;

        ES&#58;DI = 0000h&#58;0000h

 Return&#58;ES&#58;DI -> VxD API  entry  point, or 0&#58;0 if the VxD does not support an

        API

 Note&#58;  some Windows  enhanced-mode virtual  devices  provide  services  that

        applications  can  access.  For example, the  Virtual  Display Device

        &#40;VDD&#41; provides an API used in turn by WINOLDAP.

 -&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;-&amp;uacute;

 So, you  put in  BX a  202h, and  execute this function. And you then say...

 "Hey Billy... How the ****  i  can use interrupts?". My answer is... USE THE

 VxDCALL0!!!

 &#91; Win32&#58; Detect SoftICE &#40;III&#41; &#93;

 The definitive  and wonderful trick that you was waiting... The global solu-

 tion of finding SoftICE in both Win9x and WinNT enviroments! It's very easy,

 100% API based, and without "dirty" tricks that  go againist  compatibility.

 And the answer isn't as hidden as you can think... the key is in an API that

 you've surely  used before&#58; CreateFile. Yes, that  API... ain't it charming?

 Well, we have to try to open the following&#58;

        + SoftICE for Win9x &#58; ".SICE"

        + SoftICE for WinNT &#58; ".NTICE"

 If the  API returns us  something  different than -1 &#40;INVALID_HANDLE_VALUE&#41;,

 SoftICE is active! Here follows a demonstration program&#58;

;&amp;Auml;&amp;Auml;&amp;Auml;&#91; CUT HERE &#93;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;Auml;&amp;  Auml;&amp;Auml;

        .586p

        .model  flat

extrn   CreateFileA&#58;PROC

extrn   CloseHandle&#58;PROC

extrn   MessageBoxA&#58;PROC

extrn   ExitProcess&#58;PROC

        .data

szTitle         db      "SoftICE detection",0

szMessage       db      "SoftICE for Win9x &#58; "

answ1           db      "not found!",10

                db      "SoftICE for WinNT &#58; "

answ2           db      "not found!",10

                db      "&#40;c&#41; 1999 Billy Belcebu/iKX",0

nfnd            db      "found!    ",10

SICE9X          db      ".SICE",0

SICENT          db      ".NTICE",0

        .code

DetectSoftICE&#58;

        push    00000000h                       ; Check for the presence of

        push    00000080h                       ; SoftICE for Win9x envirome-

        push    00000003h                       ; nts...

        push    00000000h

push    00000001h

        push    0C0000000h

        push    offset SICE9X

        call    CreateFileA

        inc     eax

        jz      NoSICE9X

        dec     eax

        push    eax                             ; Close opened file

        call    CloseHandle

        lea     edi,answ1                       ; SoftICE found!

        call    PutFound

NoSICE9X&#58;       

        push    00000000h                       ; And now try to open SoftICE

        push    00000080h                       ; for WinNT...

        push    00000003h

        push    00000000h

push    00000001h

        push    0C0000000h

        push    offset SICENT

        call    CreateFileA

        inc     eax

        jz      NoSICENT

        dec     eax

        push    eax                             ; Close file handle

        call    CloseHandle

        lea     edi,answ2                       ; SoftICE for WinNT found!

        call    PutFound

NoSICENT&#58;

        push    00h                             ; Show a MessageBox with the

        push    offset szTitle                  ; results

        push    offset szMessage

        push    00h

        call    MessageBoxA                     

        push    00h                             ; Terminate program

        call    ExitProcess

PutFound&#58;

        mov     ecx,0Bh                         ; Change "not found" by 

        lea     esi,nfnd                        ; "found"; address of where 

        rep     movsb                           ; to do the change is in EDI

        ret

end     DetectSoftICE

----------

