Д--ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД--ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД--ДД
                       ROSE's  AntiDebugger  F A Q
 Д--ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД--ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД--ДД
             (C)opyright 1988-98 by ROSE Softwareentwicklung,
        Dipl.-Ing. (FH) Ralph Roth, Finkenweg 24, D 78658 Zimmern
         For FAX, Email, PGP etc. refer to the file ROSEBBS.TXT
 Д--ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД--ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД--ДД
         Parts copyright by other sources. Released as BANNERWARE.



ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ

                            -- ETHICS --

    This text/directory contains information on how to stop a debugger from
    single stepping through your program. You may, or may not, want to
    do this.  If you do, consider the ramifications of data destruction
    and your responsibilties in that regard. Locking up a debugger has
    the potential to crash a disk cache or worse, causing lost clusters
    and eventually cross-linking files...

    If data is lost, any data, do you want people saying your program did
    it?  Would your *lawyer* want people saying that?

    If you use the ideas here, strive for a clean exit. Reserve the lockup
    routines for determined crackers, if at all. By no means delete any
    files- it would be unprofessional and your reputation may suffer for it.


ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ


Hi.  Here's release 1 of the Anti-Anti Debugging Tricks article.

 > In order to avoid tracing of a code, one usually disables the
 > interrupt via the 8259 Interrupt Controller, addressed by
 > read/write actions to port 21h.

This is completely ineffective against Soft-ICE, which will still  break
in even when the KB interrupt is disabled.  I've never seen a case where
SI won't break into the code without your program actually reaching  out
and unplugging the keyboard.

 > Just as a side notice, the keyboard may be also disabled by
 > commanding the Programmable Peripheral Interface (PPI), port 61h.

That code doesn't seem to do anything at all, even to debug.

 > This is quite an easy form of an anti-debugging trick.
 > All you have to do is simply replace the vectors of interrupts
 > debuggers use, or any other interrupt you will not be using or
 > expecting to occur.

Any  debugger  that's  worth  anything these days  works  in  a  virtual
machine.   That  means  that it keeps a  separate  interrupt  table  for
itself.  If you try to get to it, you'll get a general protection  fault
and  you'll crash when running under QEMM, Windows, OS/2, or  any  other
protected mode system.

 > This method involves manipulations of the interrupt vectors,
 > mainly for proper activation of the algorithm. Such action, as
 > exampled, may be used to decrypt a code (see also 2.1), using
 > data stored ON the vectors.

Again, debuggers keep separate interrupt tables for themselves.

 > This is a really nasty trick, and it should be used ONLY if you
 > are ABSOLUTELY sure that your programs needs no more debugging.

It  IS a really nasty trick against a real-mode debugger like  Debug  or
something else available 5-10 years ago, but completely useless  against
Soft-ICE, TD386, or any other protected mode debugger.

 > This method simply retains the value of the clock counter, updated
 > by interrupt 08h, and waits in an infinite loop until the value
 > changes. This method is usefull only against RUN actions, not
 > TRACE/PROCEED ones.

That'll  defeat DEBUG and not much else.  Any other debugger has  a  key
that'll  break  into the code.  At that point, one could go  into  trace
mode or just replace the JZ 0109 with a series of NOP instructions.

 > This is a very nice technique, that works especially and only on
 > those who use Turbo Debugger or its kind. What you should do is
 > init a jump to a middle of an instruction, whereas the real address
 > actually contains another opcode.

I'm  not  really  sure what you're trying to  accomplish  here,  but  it
doesn't  do  much.  A simple "U CS:IP" or its equivalent  in  any  other
debugger  will  show the current instruction.  Anyway,  the  code  isn't
correct.

        IN     AL,21                            IN    AL,21h
        MOV    AL,FF                            MOV   AL,0ffh
        JMP    0108                             JMP   108
        MOV    Byte Ptr [21E6],00    --->       MOV   BYTE PTR [21e6h],0cdh
        INT    20                    --->       db    20h

You had an extra 00 in there.

 > This is a nice trick, effective against almost any real mode
 > debugger. What you should do is simply set the trace flag off
 > somewhere in your program, and check for it later.

Isn't  it  sort  of silly to be trying to  defeat  real-mode  debuggers?
That's sort of like putting locks on your back door to make sure  nobody
gets into your house while leaving the front door wide open.

 > This is a technique that causes a debugger to stop the execution
 > of a certain program. What you need to do is to put some INT 3
 > instructions over the code, at random places, and any debugger
 > trying to run will stop there.

Assembling  a NOP over the int 3 will get rid of the break.  Also,  many
debuggers (like Soft-ICE) can be set to not break on an INT 3.

 > This trick is based on the fact that debuggers don't usually use a
 > stack space of their own, but rather the user program's stack space.

I'm not sure where you're getting this, but today's debuggers keep their
own  stack safely hidden away in a protected segment where your  program
can't  corrupt  it.   This  is also  only  effective  against  real-mode
debuggers  if  you  intend to run your entire  routine  with  interrupts
cleared, since most ISR's depend on your stack being there as well.

 > This is a nice way to fool Turbo Debugger's V8086 module (TD386).
 > It is based on the fact that TD386 does not use INT 00h to detect
 > division by zero.

Did  you actually try this?  It doesn't seem to have much effect at  all
on TD386.  Soft-ICE traces through it quite happily too.

 > Another way of messing TD386 is fooling it into an exception.
 > Unfortunately, this exception will also be generated under any
 > other program, running at V8086 mode.

Yes,  and  in  a debugger it's _really_ easy to change  the  code  while
you're tracing through it to jump right over the offending  instruction.
All that you've done is eliminated compatibility with a lot of systems.

 > The first category is simply a code, that has been encrypted,
 > and has been added a decryption routine. The trick here is that
 > when a debugger sets up a breakpoint, it simply places the opcode
 > CCh (INT 03h) in the desired address, and once that interrupt is
 > executed, the debugger regains control of things.

ANY  decent  debugger these days will let you use  hardware  breakpoints
which  have nothing to do with INT 3 or any other instruction  replacing
existing  code.   They'll let you set breakpoints  wherever  you'd  like
without messing up encryption routines or self-modifying code.

 > This is an example of a self-tracing self-modifying code,
 > sometimes called 'The running line'. It was presented by Serge
 > Pachkovsky.

This is really the only effective measure in this document.  It defeated
every debugger I tried except for Soft-ICE.  Even under Soft-ICE it  was
hard to trace, since Soft-ICE has a quirk to it - it disables the  trace
flag  after each instruction.  It also includes fkey macros  though,  so
once  you realize what's going on, it's pretty easy to force it to  turn
the  trap flag back on before it executes the next instruction.  With  a
couple  of additional macros, I had it set up to trace through the  code
like nothing unusual was happening, except of course that the code I was
looking at kept changing, but that's another matter.

I had to change the routine you included since it doesn't handle  multi-
byte instructions very well.





ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
                            Anti Debugging Tricks

                                     By:

                                  Inbar Raz

                 Assistance by Eden Shochat and Yossi Gottlieb

                               Release number 5

ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ


  Today's anti debugging tricks devide into two categories:

  1. Preventive actions;
  2. Self-modifying code.

  Most debugging tricks, as for today, are used within viruses, in order to
avoid dis-assembly of the virus, as it will be exampled later in this file.
Another large portion of anti debugging tricks is found with software
protection programs, that use them in order to make the cracking of the
protection harder.

1. Preventive actions:
----------------------

  Preventive actions are, basically, actions that the program takes in order
to make the user unable to dis-assemble the code or trace it while running.

1.1. Interrupt disable:

       Interrupt disable is probably the most common form of anti-debugging
     tricks. It can be done in several ways:

   1.1.1. Hardware masking of interrupt:

            In order to avoid tracing of a code, one usually disables the
          interrupt via the 8259 Interrupt Controller, addressed by read/write
          actions to port 21h. The 8259 Interrupt Controller controls the IRQ
          lines. This means that any IRQ between 0 and 7 may be disabled by
          this action. Bit 0 is IRQ0, bit 1 is IRQ1 etc. Since IRQ1 is the
          keyboard interrupt, you may disable the keyboard without the
          debugger being able to bypass it.

          Example:

          CS:0100 E421           IN     AL,21
          CS:0102 0C02           OR     AL,02
          CS:0104 E621           OUT    21,AL

            Just as a side notice, the keyboard may be also disabled by
          commanding the Programmable Peripheral Interface (PPI), port 61h.

          Example:

          CS:0100 E461           IN     AL,61
          CS:0102 0C80           OR     AL,80
          CS:0104 E661           OUT    61,AL

   1.1.2. Software masking of interrupt:

            This is quite an easy form of an anti-debugging trick. All you
          have to do is simply replace the vectors of interrupts debuggers
          use, or any other interrupt you will not be using or expecting to
          occur. Do not forget to restore the original vectors when you are
          finished. It is adviseable to use manual change of vector, as shown
          below, rather than to change it using interrupt 21h service 25h,
          because any debugger that has gained control of interrupt 21h may
          replace your vector with the debugger's. The example shows an
          interception of interrupt 03h - the breakpoint interrupt.

          Example:

          CS:0100 EB04           JMP    0106
          CS:0102 0000           ADD    [BX+SI],AL
          CS:0104 0000           ADD    [BX+SI],AL
          CS:0106 31C0           XOR    AX,AX
          CS:0108 8EC0           MOV    ES,AX
          CS:010A 268B1E0C00     MOV    BX,ES:[000C]
          CS:010F 891E0201       MOV    [0102],BX
          CS:0113 268B1E0E00     MOV    BX,ES:[000E]
          CS:0118 891E0401       MOV    [0104],BX
          CS:011C 26C7064C000000 MOV    Word Ptr ES:[000C],0000
          CS:0123 26C7064E000000 MOV    Word Ptr ES:[000E],0000

   1.1.3. Vector manipulation

             This method involves manipulations of the interrupt vectors,
          mainly for proper activation of the algorithm. Such action, as
          exampled, may be used to decrypt a code (see also 2.1), using data
          stored ON the vectors. Ofcourse, during normal operation of the
          program, vectors 01h and 03h are not used, so unless you are trying
          to debug such a program, it works fine.

          Example:

          CS:0100 31C0           XOR    AX,AX
          CS:0102 8ED0           MOV    SS,AX
          CS:0104 BC0E00         MOV    SP,000E
          CS:0107 2E8B0E3412     MOV    CX,CS:[1234]
          CS:010C 50             PUSH   AX
          CS:010D 31C8           XOR    AX,CX
          CS:010F 21C5           AND    BP,AX
          CS:0111 58             POP    AX
          CS:0112 E2F8           LOOP   010C

   1.1.4. Interrupt replacement

            This is a really nasty trick, and it should be used ONLY if you
          are ABSOLUTELY sure that your programs needs no more debugging. What
          you should do is copy the vectors of some interrupts you will be
          using, say 16h and 21h, onto the vectors of interrupt 01h and 03h,
          that do not occur during normal operation of the program. If the
          user wants to debug the program, he would have to search for every
          occurance of INT 01, and replace it with the appropriate INT
          instruction. This trick is very effective if used together with the
          fact that the INT 3 intruction has a ONE BYTE opcode - 0CCh, which
          can not be changed to any other interrupt.

          Example:

          CS:0100 FA             CLI
          CS:0101 31C0           XOR    AX,AX
          CS:0103 8EC0           MOV    ES,AX
          CS:0105 26A18400       MOV    AX,ES:[0084]
          CS:0109 26A30400       MOV    ES:[0004],AX
          CS:010D 26A18600       MOV    AX,ES:[0086]
          CS:0111 26A30600       MOV    ES:[0006],AX
          CS:0115 B44C           MOV    AH,4C
          CS:0117 CD01           INT    01

1.2. Time watch:

       This may be a less common method, but it is usefull against debuggers
     that disable all interrupts except for the time that the program is
     executed, such as Borland's Turbo Debugger. This method simply retains
     the value of the clock counter, updated by interrupt 08h, and waits in an
     infinite loop until the value changes. Another example is when you mask
     the timer interrupt by ORing the value INed from port 21h with 01h and
     then OUTing it back, thus disabling the IRQ0 - Timer interrupt. Note that
     this method is usefull only against RUN actions, not TRACE/PROCEED ones.

     Example:

     CS:0100 2BC0           SUB    AX,AX
     CS:0102 FB             STI
     CS:0103 8ED8           MOV    DS,AX
     CS:0105 8A266C04       MOV    AH,[046C]
     CS:0109 A06C04         MOV    AL,[046C]
     CS:010C 3AC4           CMP    AL,AH
     CS:010E 74F9           JZ     0109

1.3. Fool the debugger:

       This is a very nice technique, that works especially and only on those
     who use Turbo Debugger or its kind. What you should do is init a jump to
     a middle of an instruction, whereas the real address actually contains
     another opcode. If you work with a normal step debugger such as Debug or
     SymDeb, it won't work since the debugger jumps to the exact address of
     the jump, and not to the beginning of an instruction at the closest
     address, like Turbo Debugger.

     Example:

     CS:0100 E421           IN     AL,21
     CS:0102 B0FF           MOV    AL,FF
     CS:0104 EB02           JMP    0108
     CS:0106 C606E62100     MOV    Byte Ptr [21E6],00
     CS:010B CD20           INT    20

     Watch this:

     CS:0108 E621           OUT    21,AL

     Notice:

       This trick does NOT effect the run of the program in ANY debugger. Its
     only use is to try to deceive the user into thinking another opcode is
     used, while another is actually run.

1.4. Check CPU Flags:

       This is a nice trick, effective against almost any real mode debugger.
     What you should do is simply set the trace flag off somewhere in your
     program, and check for it later. If it was turned on, a debugger runs in
     the background...

     Example:

     CS:0100 9C             PUSHF
     CS:0101 58             POP    AX
     CS:0102 25FFFE         AND    AX,FEFF
     CS:0105 50             PUSH   AX
     CS:0106 9D             POPF

     In the middle of the program:

     CS:1523 9C             PUSHF
     CS:1524 58             POP    AX
     CS:1525 250001         AND    AX,0100
     CS:1528 7402           JZ     152C
     CS:152A CD20           INT    20

1.5. Cause debugger to stop execution:

       This is a technique that causes a debugger to stop the execution of a
     certain program. What you need to do is to put some INT 3 instructions
     over the code, at random places, and any debugger trying to run will stop
     there. It is best if used within a loop, as it is run several times.

     Example:

     CS:0100 B96402         MOV    CX,0264
     CS:0103 BE1001         MOV    SI,0110
     CS:0106 AC             LODSB
     CS:0107 CC             INT    3
     CS:0108 98             CBW
     CS:0109 01C3           ADD    BX,AX
     CS:010B E2F9           LOOP   0106

1.6. Halt computer using stack:

       This trick is based on the fact that debuggers don't usually use a
     stack space of their own, but rather the user program's stack space. By
     setting the stack to a location in the middle of a code that does NOT use
     the stack itself, any debugger that will try to trace the code will
     overwrite some of the code by its own stack (mainly interrupt return
     addresses). Again, CLI and STI are in order, and are not shown for the
     purpose of the example only. They must be included, or you risk hanging
     your computer wether a debugger is installed or not.

     Example:

     CS:0100 8CD0           MOV    AX,SS
     CS:0102 89E3           MOV    BX,SP
     CS:0104 0E             PUSH   CS
     CS:0105 17             POP    SS
     CS:0106 BC0B01         MOV    SP,010B
     CS:0109 90             NOP
     CS:010A 90             NOP
     CS:010B EB02           JMP    010F
     CS:010D 90             NOP
     CS:010E 90             NOP
     CS:010F 89DC           MOV    SP,BX
     CS:0111 8ED0           MOV    SS,AX

1.7. Halt TD386 V8086 mode:

       This is a nice way to fool Turbo Debugger's V8086 module (TD386). It is
     based on the fact that TD386 does not use INT 00h to detect division by
     zero (or register overrun after division, which is treated by the
     processor in the same way as in the case of division by zero). When TD386
     detects a division fault, it aborts, reporting about the faulty division.
     In real mode (even under a regular debugger), a faulty DIV instruction
     will cause INT 00h to be called. Therefore, pointing INT 00h to the next
     instruction, will recover from the faulty DIV.

     Note: It is very important to restore INT 00h's vector. Otherwise, the
     next call to INT 00h will cause the machine to hang.

     Example:

     CS:0100 31C0          XOR     AX,AX
     CS:0102 8ED8          MOV     DS,AX
     CS:0104 C70600001201  MOV     WORD PTR [0000],0112
     CS:010A 8C0E0200      MOV     [0002],CS
     CS:010E B400          MOV     AH,00
     CS:0110 F6F4          DIV     AH
     CS:0112 B8004C        MOV     AX,4C00
     CS:0115 CD21          INT     21

1.8. Halt any V8086 process:

       Another way of messing TD386 is fooling it into an exception.
     Unfortunately, this exception will also be generated under any other
     program, running at V8086 mode. The exception is exception #13, and its
     issued interrupt is INT 0Dh - 13d. The idea is very similar to the
     divide by zero trick: Causing an exception, when the exception interrupt
     points to somewhere in the program's code. It will always work when the
     machine is running in real mode, but never under the V8086 mode.

     Note: It is very important to restore the original interrupt vectors.
     Otherwise, the next exception will hang the machine.

     Example:

     CS:0100 31C0          XOR     AX,AX
     CS:0102 8ED8          MOV     DS,AX
     CS:0104 C70634001301  MOV     WORD PTR [0034],0113
     CS:010A 8C0E3600      MOV     [0036],CS
     CS:010E 833EFFFF00    CMP     WORD PTR [FFFF],+00
     CS:0113 B8004C        MOV     AX,4C00
     CS:0116 CD21          INT     21

2. Self-modifying code:
-----------------------

2.1. Encryptive/decryptive algorithm:

     The first category is simply a code, that has been encrypted, and has
     been added a decryption routine.  The trick here is that when a
     debugger sets up a breakpoint, it simply places the opcode CCh (INT
     03h) in the desired address, and once that interrupt is executed, the
     debugger regains control of things.  If you try to set a breakpoint
     AFTER the decryption algorithm, what is usually needed, you will end
     up putting an opcode CCh in a place where decryptive actions are
     taken, therefore losing your original CCh in favour of whatever the
     decryption algorithm produces.  The following example was extracted
     from the Haifa virus.  If you try to set a breakpoint at address
     CS:0110, you will never reach that address, since there is no way to
     know what will result from the change.  Note that if you want to make
     the tracing even harder, you should start the decryption of the code
     from its END, so it takes the whole operation until the opcode
     following the decryption routine is decrypted.

     Example:

     CS:0100 BB7109         MOV    BX,0971
     CS:0103 BE1001         MOV    DI,0110
     CS:0106 91             XCHG   AX,CX
     CS:0107 91             XCHG   AX,CX
     CS:0108 2E803597       XOR    Byte Ptr CS:[DI],97
     CS:010C 47             INC    DI
     CS:010D 4B             DEC    BX
     CS:010E 75F6           JNZ    0106
     CS:0110 07             POP    ES
     CS:0111 07             POP    ES

2.2. Self-modifying code:

   2.2.1. Simple self-modification:

     This method implements the same principle as the encryption method:
     Change the opcode before using it.  In the following example, we
     change the insruction following the call, and therefore, if you try to
     trace the entire call ('P'/Debug or F8/Turbo Debugger), you will not
     succeed, since the debugger will put its CCh on offset 103h, but when
     the routine runs, it overwrites location 103h.

          Example:

          CS:0100 E80400         CALL   0107
          CS:0103 CD20           INT    20
          CS:0105 CD21           INT    21
          CS:0107 C7060301B44C   MOV    Word Ptr [0103],4CB4
          CS:010D C3             RET

          Watch this:

          CS:0103 B44C           MOV    AH,4C

   2.2.2. The Running Line (self-decrypting):

     This is an example of a self-tracing self-modifying code, sometimes
     called 'The running line'.  It was presented by Serge Pachkovsky.  It
     is a bit tricky in implementation, but, unlike all other techiniques
     mentioned in this document, it is relatively resistive to various
     protections of the vector table.  In short, it results in instructions
     being decoded one at time, thus never exposing long code fragments to
     analisys.  I will illustrate it with the following (over-simplified)
     code example:

          XOR     AX, AX
          MOV     ES, AX
          MOV     WORD PTR ES:[4*1+0],OFFSET TRACER
          MOV     WORD PTR ES:[4*1+2],CS
          MOV     BP, SP
          PUSHF
          XOR     BYTE PTR [BP-1], 1
          POPF
          MOV     AX, 4C00H               ; This will not be traced!
          DB      3 DUP ( 98H )
          DB      C5H, 21H

   TRACER:

          PUSH    BP
          MOV     BP, SP
          MOV     BP, WORD PTR [BP+2]
          XOR     BYTE PTR CS:[BP-1], 8
          XOR     BYTE PTR CS:[BP+0], 8
          POP     BP
          IRET

===============================================================================

Comments:

     In order to save lines of code, I did not insert the CLI/STI pair
     before any vector change.  However, it is adviseable to do this pair
     before ANY manual vector change, because if any interrupt occurs in
     the middle of your operations, the machine could hang.

An apology:

     In previous releases of this article, a false example, as noted by
     Serge Pachkovksy, was posted.  That was 2.2.2 - Manipulating the PIQ.
     Apperantly the posted source would not work under any circumstances.
     In return, Serge has presented the 'Running Line' technique.



ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
                 ANTI DEBUGGER TRICKS by Dark Angel

ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ

     This file is divided into two parts.  The first part is devoted to
     developing 'debug resistant' code, and the second part deals with
     defeating disassemblers.  I will not cover encryption, because methods
     of encryption are commonly known and there is really not much further
     I can go with that.  For a complete review of self encryption methods,
     take a look at Dark Angel's Funky Virus Writing Guide (number three,
     the one that hasn't been released yet.)

Part_I: The debugger is NOT your friend

     The basic idea behind writing debug ressistant code is finding a way
     to make your code behave differently when it runs under a debugger.
     With a real mode debugger, this is simplicity itself.  All that is
     necessary is a little knowledge of how a debugger works.  A debugger,
     such as debug or TD traces through a program by setting handlers to
     int 1 and int 3.  These are called after every instruction is
     executed.  A virus that wishes to avoid being debugged can simply
     replace the handlers for these interrupts, and the results will be
     just about whatever you want.  Here is some code to do this:

eat_debug:
        push    cs
        pop     ds
        mov     dx, offset eat_int
        mov     ax,2501h
        int     21h
        mov     al,03h
        int     21h
        ...                     ; rest of code
eat_int: iret

     As you can see, this requires minimal space in your code, and is
     certainly worth the effort.  You can experiment by placing something
     else at 'eat_int'.  Another commonly used tactic is to disable the
     keyboard interrupt while certain parts of the code are being executed.
     This will surely keep lamers baffled, though a pro would recognize
     what was going on immediately.  I am sure McAfee's programmer's scoff
     at code such as this.  Also note that while this will defeat the
     average real mode debugger, any protected mode debugger will step
     through this as if it weren't there.  Playing with interrupts will not
     help you when your program will be running in a virtual cpu anyway.
     One method I found which will work nicely against td386 is to throw in
     a hlt instruction.  This will give TD an exception 13 error, and
     terminate the program.  Anyone who is aware of this will just step
     over a hlt instruction, so therefore methods must be used to conceal
     its presence, or to make it a necessary part of the code.  This will
     be covered in part II.  Another trick you can play is to call int3
     within your program.  If someone tries to run your program under a
     debugger, it will stop each time int3 is called.  It is possible to
     trace through it, but it will be annoying if there are many int3's
     thrown in.

Part_2: Kill your disassembler

     No matter how well you mess up debuggers, your program is entirely at
     the mercy of a programmer armed with a good disassembler.  Unless, of
     course, you use techniques that will confuse disassemblers.  My
     favorite method for baffling them is to create code that overlaps.
     Overlapping code may seem a little bit too complicated for most of us
     at first, but with the knowledge of a few instruction hex
     translations, you too can make effective overlapping code without
     sacrificing too much code size.  Overlapping code can get as complex
     as you would like, but this file will only deal with the simplest
     examples.


eat_sr: mov     ax,02EBh
        jmp     $-2             ; huh?
        ...             ; rest of code

     This may confuse you at first, but it is fairly simple.  The first
     instruction moves a dummy value into ax.  The second instruction jmps
     into the value that was just moved into ax.  '02EB' translates into
     'jmp $+2' (remember that words are stored in reverse).  This jump goes
     past the first jmp, and continues on with the code.  This will
     probably not be sufficient to defeat a good disassembler like Sourcer,
     but it does demonstrate the technique.  The problem with this is that
     Sourcer may or may not just pick up the code after commenting out the
     'jmp $-2'.  It is difficult to predict how Sourcer will respond, and
     it usually depends on the bytes that appear directly after the jmp.
     To severely baffle Sourcer, it is necessary to do some stranger
     things.  Take a look at this example.

erp:    mov     ax,0FE05h
        jmp     $-2h
        add     ah,03Bh
        ...                     ; rest of code

     This code is quite a bit more useful than the previous listing.  Let
     us simulate what would happen if we were to trace through this code,
     showing a hex dump at each step to clarify things.

 B8 05 FE EB FC 80 C4 3B   mov     ax,0FE05h       ; ax=FE05h
 ^^ ^^ ^^
 B8 05 FE EB FC 80 C4 3B   jmp     $-2             ; jmp into '05 FE'
          ^^ ^^
 B8 05 FE EB FC 80 C4 3B   add     ax,0EBFEh       ; 05 is 'add ax'
    ^^ ^^ ^^
 B8 05 FE EB FC 80 C4 3B   cld                     ; a dummy instruction
             ^^
 B8 05 FE EB FC 80 C4 3B   add     ah,3Bh          ; ax=2503h
                ^^ ^^ ^^

     The add ah,03Bh is there simply to put the value 2503h into ax.  By
     adding five bytes (as opposed to simply using 'mov ax,2503h') this
     code will confuse disassemblers pretty well.  Even if the instructions
     are disassembled properly, the value of ax will not be known, so every
     int call after this point will not be commented properly, as long as
     you never move a value into ax.  You can conceal the value from the
     disassembler by using 'add ax' or 'sub ax' whenever possible.  If you
     examine this closely, you can see that any value can be put into ax.
     Two of the values can be changed to whatever you want, namely the FE
     in the first line, and the 3B in the last line.  It is helpful to
     debug through this chunk of code to determine what values should be
     placed here in order to make ax what you would like it to be.  Back to
     the subject of killing debuggers, it is very sneaky to hide something
     like a hlt instruction inside another instruction, such as a jmp.  For
     example, take a look at this:

glurb:  mov     cx,09EBh
        mov     ax,0FE05h ;-\
        jmp     $-2       ;  >--this should look familiar to you
        add     ah,03Bh   ;-/
        jmp     $-10
        ...             ; rest of code

     The three lines in the middle are a repeat of the previous example.
     The important part of this code is the first line and the 'jmp $-10'.
     What happens is, the jmp goes back into the 'mov cx' instruction.  The
     '09EB' translates into 'jmp $+9'.  This lands in the '$-10' part of
     the first jmp.  The $-10 just happens to be stored as 0F4h, the hlt
     instruction.  By making the hlt part of another instruction, it is not
     visible when it is being traced through by td386.  It is also not
     possible to remove it without altering the code.

     The purpose of this article is not to supply code to be thrown into
     your own programs.  The purpose is to get you to think about new ways
     to avoid having your code looked at and modified by others.  The most
     important thing is to be original.  It is pointless for you to simply
     duplicate this code, because anyone else who has read this file will
     already know what you are trying to do.


ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ


Part I  : Fun with int3
Part II : Fun with int8
Part III: The Prefetch


Part_I : Fun with int3

     Int three is the debugger breakpoint.  Every time a debugger breaks
while tracing through a chunk of code, it will call int3.  Int3 is
called after every instruction is executed in trace mode, and after
a breakpoint is reached.  Note that protected mode debuggers do not
execute int3 in trace mode, but they will break when int3 is called from
your code.  You can use this to your advantage.  Simply install a new
handler for int3 and it will execute instead of the debugger if a thief
tries to trace through your program.

start:  mov     ax, 2503h
        mov     dx, offset int_start
        int     21h                     ; put in the new handler at ds:dx

        ...             ; rest of real code here
        int     20h

text db 'Smoke Mah Ass!$'
int_start:
        mov     ah, 9
        mov     dx, offset text
        int     21h
        int     20h

     As soon as the first int21 call in this program is made, the code
at int_start will execute if it is being traced in a debugger.
Otherwise, the int call will be ignored and your normal code will
execute.  The program can do whatever you want if a debugger is found.
For example, you can format the hard drive or display a message.  The
possabilities are endless.  By the way, it might be wise to restore the
old interrupt handler before you exit the program, because it is bad
programming practice to leave interrupts pointed into non-allocated
memory.


compatability:(works against all debuggers marked with an X)
-------------------------------------------------------------------------
Debug           Turbo Debug             Turbo Debug 386         Soft-Ice
  X                   X
-------------------------------------------------------------------------


Part_II: Fun with int8

     The next segment will show you how to make a program nearly
impossable to trace.  The concept is simple.  All you need to do is
place the main body ofyour program into an int8 handler.  Int8 is the
timer interrupt, and it is called 18.2 times a second.  Debuggers do not
execute int8, so whatever you put there will only go when it is run from
dos.  The only drawback to this is a short delay before the main program
is executed.  It will probably go unnoticed, in most cases.  Here is
some code:

thyroid:mov     ax, 3508h
        int     21h                        ; get int8 handler
        mov     word ptr [int_store], bx   ; store it
        mov     word ptr [int_store+2], es
        mov     dx, offset prog_start
        mov     ah, 25h
        int     21h                        ; install new int8 handler

yip:    cmp     flaag, 1
        jne     yip             ; wait for int8 to be called
                        ; int8 must set the flaag to 1
        push    bx
        pop     dx      ; restore
        push    es      ; old
        pop     ds      ; int8
        int     21h     ; handler
        int     20h

flaag db 0
int_store dd ?
prog_start:
_main_program proc far
        ; save all the necessary registers here
        ; ... your code
        mov     flaag, 1
        ; restore the registers

        jmp dword ptr [offset int_store]  ; chain to real int8 handler
_main_program endp

     This code is quite useful in that if some guy tries to trace
through it, he will be stuck forever in the 'yip' loop.  The main code
will never be executed.  If he tries to get out of the loop by
'executing to' the next instruction, he will end up running the entire
program.  No debugger I know of can trace through this, because int8 is
not called from within the debugger.

-------------------------------------------------------------------------
Debug           Turbo Debug             Turbo Debug 386         Soft-Ice
  X                   X                         X                   X
-------------------------------------------------------------------------


Part_III: The Prefetch

     My favorite way to confuse debuggers is to mess with the prefetch
queue.  All intel processors have a small queue where the next
instructions to be executed are stored.  In this way, the CPU does not
have to waste clock cycles by fetching the next instruction, except in
the cases of branching instructions such as jmps and calls.  The next
chunk of code makes use of this:

eapple: mov     ah, 9
        mov     word ptr [offset ear_lobe-2], offset sukk_debug
        mov     dx, offset text
ear_lobe:
        int     21h
        int     20h

text    db 'snee!$'
sukk_debug db 0Ah, 0Dh, 09h, 'blow a goat!', 07h, 0Ah, 0Dh, '$'

     All this program does is print out a text string.  If it is run
from dos, it will print out 'snee!'.  If it is traced through by any
debugger, however, it will print 'blow a goat!', and beep the PC speaker
(07h is ctrl-g).  Let me explain how this works.
     When any chunk of code is executed by dos, the first few bytes are
sent into the prefetch queue.  The actual number of bytes depends on the
model of intel chip, and what year it was made in.  My computer is a
386DX-20 (early model), which has a 16 byte prefetch.  Be sure to check
your code on several machines to insure compatability.
     When the second instruction is reached, it places the offset of
sukk_debug into the next instruction.  That is, the next instruction
becomes 'mov dx, offset sukk_debug', rather than 'mov dx, offset text'.
The system memory will be changed, but the prefetch will not, therefore
only a debugger will respond to the new code.  Dos will execute it as if
the instruction had never changed, because the instruction will already
have been loaded into the prefetch.  This theory can be used, with a
little modification, in order to branch to various subroutines, rather
than just printing out different text.  One interesting application of
this is to use the prefetch area to store registers.  This way, a person
debugging your code can not simply nop it out, because it will be
referred to later on.  In fact, you can even put the stack on the
prefetch.  Try to debug through the following fragment, and watch what
happens:

nee:    mov     ax, 4Ch
        mov     dx, offset text
        mov     sp, offset fin_rot
        push    ax
        mov     ah, 9
fin_rot:int     21h
        pop     ax
        int     21h
text:   db      'Duck is proud of her feet.  They can catch things.$'

     If you run it through debug, the entire program will be corrupted
as soon as you move the stack pointer.  This is because the debug code
uses the stack and expects it to be in a safe location.  If you run it
through soft ice, the code will be corrupted as soon as you push ax.
The stack area will be overwritten when int21 is executed, because the
interrupt uses the stack.  However, in this example, the instruction
pointer will already be beyond this area, so the program will execute
normally.
     Remember not to place the stack past any calls, because then the
prefetch would have to be reloaded after the main program was returned
to, and the instructions that were there before will be gone.

-------------------------------------------------------------------------
Debug           Turbo Debug             Turbo Debug 386         Soft-Ice
  X                   X                         X                   X
-------------------------------------------------------------------------


                                                    
        Remember:  Unprotected code is public domain!
                                                    



ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
           Info taken from "The Poltergeist"/TB-Decrypt
ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ

INFO ON ENCRYPTION IN TBAV EXECUTABLES:
--------------------------------------
The first obstacle I encountered when debugging was INT 1 being re-mapped,
which is the debuggers single step interrupt.  It remaps it to point to
somewhere in the code, the trap flag is set, and INT 1 is executed once.
After that, it decrypts the decryption loop and pushes it onto the stack.
It then jumps to a code segment slightly offset from the stack segment.
This is where the real debugging problems occur.  The stack is RIGHT UNDER
the decryption loop, and if you try to single step anywhere past the RETF
0024 until after the RETF 001E is executed, the debuggers stack will inter-
fere with the decryption loop and mess everything up.  The decryption loop
then proceeds to decrypt the program in memory.  The decryption loop moves
the stack pointer above and below the decryption loop as it cycles through.
The near return loops back around to CS:0000 in the decryption routine.
The RETF 001E jumps to the actual program.

1488:0018 B88CD3         MOV       AX,D38C
1488:001B 153375         ADC       AX,7533
1488:001E 72F9           JB        0019
1488:0020 D4FF           AAM       FF
1488:0022 8AC4           MOV       AL,AH
1488:0024 83C33E         ADD       BX,+3E
1488:0027 8ED8           MOV       DS,AX
1488:0029 B91500         MOV       CX,0015
1488:002C F7D3           NOT       BX
1488:002E 2E871E7E00     XCHG      BX,Word Ptr CS:[007E]
1488:0033 FF77FE         PUSH      Word Ptr [BX-02]      - preserves original
1488:0036 FF37           PUSH      Word Ptr [BX]         - INT 1 vector
1488:0038 8BEC           MOV       BP,SP
1488:003A C747FE4A00     MOV       Word Ptr [BX-02],004A - INT 1 points to
1488:003F 8C0F           MOV       Word Ptr [BX],CS      - CS:004A (hidden
1488:0041 72EC           JB        002F                    code)
1488:0043 2EFF367A00     PUSH      Word Ptr CS:[007A]    - trap flag
1488:0048 9D             POPF
1488:0049 1D5E5B         SBB       AX,5B5E               - actually POP SI
1488:004C 8BD3           MOV       DX,BX                   and POP BX..
1488:004E F7D2           NOT       DX
1488:0050 2E87168400     XCHG      DX,Word Ptr CS:[0084]
1488:0055 58             POP       AX
1488:0056 8F060600       POP       Word Ptr [0006]       - INT 1 restored
1488:005A 83E6FD         AND       SI,-03
1488:005D 8F060400       POP       Word Ptr [0004]
1488:0061 03F2           ADD       SI,DX
1488:0063 2EAD           LODSW      CS:                  - Decrypts decryption
1488:0065 F7D0           NOT       AX                    - loop and pushes it
1488:0067 50             PUSH      AX                    - onto the stack
1488:0068 E0F9           LOOPNE    0063
1488:006A 83D302         ADC       BX,+02
1488:006D 81D6E426       ADC       SI,26E4
1488:0071 81C66EFF       ADD       SI,FF6E
1488:0075 8EDB           MOV       DS,BX
1488:0077 CA2400         RETF      0024                  - to decryption loop

This is where it is after the RETF 0024:

1B81:0000 8704           XCHG      AX,Word Ptr [SI]      -|
1B81:0002 33C4           XOR       AX,SP                  |
1B81:0004 8B4E00         MOV       CX,Word Ptr [BP+00]    |
1B81:0007 33CD           XOR       CX,BP                  |
1B81:0009 33C1           XOR       AX,CX                  |   Decryption
1B81:000B D1C8           ROR       AX,1                   |     loop
1B81:000D 8904           MOV       Word Ptr [SI],AX       |
1B81:000F 4E             DEC       SI                     |
1B81:0010 83EC24         SUB       SP,+24                 |
1B81:0013 FB             STI                              |
1B81:0014 4E             DEC       SI                     |
1B81:0015 E105           LOOPE     001C                  -|-when its done
1B81:0017 FA             CLI                              |
1B81:0018 C22200         RET       0022                  -|-jumps to cs:0000
1B81:001B 90             NOP
1B81:001C 58             POP       AX
1B81:001D CA1E00         RETF      001E                  - to actual program


ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
               Taken from "Q" the misanthrope/40 Hex
ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
Editor's Response:

I am going to keep this response pretty simple.  Do you think that people
who manufacture and distribute guns feel responsible for people who are
murdered by their guns?  I take full responsibility for my actions.  If I
sold flowers and someone bought one from me, and then crammed it down
someone's throat and that person died, am I responsible?  My intention wasn't
to hurt anyone, but someone got hurt.  Viruses are essentially my flowers.
I don't intend for ANYONE to get hurt because of 40hex.  I intend to share
my hobby with others.  No more, no less.

------------

I really appreciate your articles.  I find the articles on non-debugable code
very interesting.  I developed some of my own.  I used the lock command.


17F1:0100 B90601        MOV     CX,0106    ; setup for the jmp cx command
17F1:0103 0C00          OR      AL,00      ; bugus commands whose values are
                                           ; used for adding to cx. this is
                                           ; added if no debugger.
17F1:0105 1B00          SBB     AX,[BX+SI] ; this bogus command is what is
                                           ; added to cx if a debugger is used
17F1:0107 F0            LOCK               ; what makes it all happen
17F1:0108 89E5          MOV     BP,SP      ; get the stack
17F1:010A 8B7EFA        MOV     DI,[BP-06] ; look at offset of return ip value
                                           ; (di=010a if debugging else
                                           ; di=0108)
17F1:010D 034DFB        ADD     CX,[DI-05] ; add the appropriate bogus command
                                           ; to cx that is shown above
17F1:0110 FFE1          JMP     CX         ; go where no man has gone before
17F1:0112 E2EF          LOOP    0103       ; this is the address of where the
                                           ; first jmp cx goes to if there
17F1:0114 90            NOP                ; is no debugger. other
17F1:0115 90            NOP                ; modifications to cx can be done
17F1:0116 90            NOP                ; here but i just decremented cx
17F1:0117 90            NOP                ; and jumped back to the start to do
17F1:0118 90            NOP                ; it again
17F1:0119 90            NOP
17F1:011A 90            NOP
17F1:011B 90            NOP
17F1:011C 90            NOP
17F1:011D 75E4          JNZ     0103       ; this is where jmp cx goes to on
                                           ; the second go around without a
17F1:011F 90            NOP                ; debugger.  i thought i would send
17F1:0120 90            NOP                ; it back for a third time.
17F1:0121 EBDD          JMP     0100       ; this is where jmp cx goes to if
                                           ; there is a debugger running
17F1:0123 90            NOP                ; captain kirk, scottie here, were
17F1:0124 90            NOP                ; stuck in a continuous feedback
17F1:0125 90            NOP                ; loop.
17F1:0126 90            NOP                ; i don't think i can maintain this
17F1:0126 90            NOP                ; much longer.
17F1:0127 90            NOP
17F1:0128 90            NOP
17F1:0129 B8070E        MOV     AX,0E07    ; this is where the jmp cx goes on
                                           ; the third time around
17F1:012C CD10          INT     10         ; lets do a beep for the folks back
                                           ; home
17F1:012E B8004C        MOV     AX,4C00    ; that's all folks.
17F1:0131 CD21          INT     21

the same sort of thing could be done to get the relative offset with the hlt
command. again debuggers will get it wrong

17F1:0100 EB04          JMP     0106       ; deja vu
17F1:0102 31C0          XOR     AX,AX      ; dummy program
17F1:0104 CD21          INT     21         ; bye
17F1:0106 F0            HLT                ; halt that processor
17F1:0107 89E5          MOV     BP,SP      ; lookie at our stack data
17F1:0109 8B6EFA        MOV     BP,[BP-06] ; and suck off the returned ip
17F1:010C 83ED07        SUB     BP,+07     ; for people who can't figure out
                                           ; how to adjust this value
                                           ; out of their displacement

Sincerely,

"Q" the misanthrope.


ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
           Anti-Debugging Tricks posted by Dale Curtis
ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ


Date: Mon, 19 Feb 1996 14:39:48 -0600
To: rar@fh-albsig.de
Subject: Anti-Debugging

Hello again,

    This is Dale Curtis. Here are some Anti-Debugging Tricks and
Code-Concealment Tricks I found you might use them for DECOM or HackStop
if you want. I'me not sure about all of them, you'll have to check. Before
the code, I will tell what debuggers it works on. Here they are:

      1. DEBUG              : Kills it.
         Turbo DEBUG        : Kills it.
         Real Mode Debugger : Kills it.
         Turbu DEBUG 386    : Nothing happens.
         Soft-Ice           : Nothing happens.
         Virtual Mode       : Nothing happens.

         eat_debug:
            push    cs
            pop     ds
            mov     dx,offset eat_int
            mov     ax,2501h
            int     21h
            mov     al,03h
            int     21h
            ; Rest of your code
         eat_int:
            iret ; or whatever. EXPERIMENT!!!

      2. DEBUG              : Kills it.
         Turbo DEBUG        : Kills it.
         Real Mode Debugger : Kills it.
         Turbo DEBUG 386    : Nothing Happens.
         Soft Ice           : Nothing Happens.
         Virtual Mode       : Nothing Happens.

         start:
            mov     ax,2503h
            mov     dx,offset int_start
            int     21h                       ; put new handler at ds:dx
            ; Rest of your code
            int     20h
         int_start:
            int     20h

      3. DEBUG              : Kills it.
         Turbo DEBUG        : Kills it.
         Real Mode Debugger : Kills it.
         Turbo DEBUG 386    : Kills it.
         Soft-Ice           : Kills it.
         Virtual Mode       : Kills it.

         thyroid:
            mov     ax,3508h
            int     21h                        ; get int8 handler
            mov     word ptr [int_store],bx    ; store it
            mov     word ptr [int_store+2],es
            mov     dx,offset prog_start
            mov     ah,25h
            int     21h                        ; install new handler
         yip:
            cmp     flaag,1                    ; wait for int8 to be called
            jne     yip                        ; int8 must set flaag to 1
            push    bx
            pop     dx                         ; restore
            push    es                         ; old
            pop     ds                         ; int8
            int     21h                        ; handler
            int     20h

         flaag      db 0
         int_store  dd ?

         prog_start:
         _main_program proc far
            ; save all necessary registers here
            ; ... your code
            mov     flaag,1
            ; restore the registers
            jmp     dword ptr [offset int_store] ; chain to real int8 handler
         _main_program endp

      4. DEBUG              : Kills it.
         Turbo DEBUG        : Kills it.
         Real Mode Debugger : Kills it.
         Turbo DEBUG 386    : Kills it.
         Soft-Ice           : Kills it.
         Virtual Mode       : Kills it.

         nee:
            mov     ax,4Ch              ; ???
            mov     sp,offset fin_rot
            push    ax
         fin_rot:
            int     21h
            pop     ax
            int     21h

         *** NOTE: CODE uses the PreFetch check on different machines for
compatability ****

ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ


% Article by Sepultura %
ДДДДДДДДДДДДДДДДДДДДДДДД
taken from IR #7


              Anti-Debugger Techniques: The Obvious
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        There are many simple and trivial ways to thwart debuggers. This
document will deal mainly with more advanced methods. The simple methods
outlined in this section can be seen in the code example of  "Using Your
Anti-Debug Routines as the Decryption Key", later on in this document.

        Perhaps the most obvious way to kill a debugger, is to overwrite
the Interrupt Vector  of  Interrupts 1 (Debug Single Step), and 3 (Debug
Break Point). This can be defeated by simply skipping the instructions.
Another thing you could do, is place an INT 3 in a long loop, which will
cause the debugger to stop at the INT 3 each iteration,  which will stop
the AV from simply proceeding through the loop.  This  is  very  easilly
defeated by NOP'ing out the INT 3.

        Another thing to do, is turn of the keyboard. There are manyways
to do this, but the simplest is:        IN      AL,20h ;Turn of Keyboard IRQ
                                        OR      AL,02
                                        OUT     AL,20

                                        <virus code>

                                        IN      AL,20   ;Enable Keyboard IRQ
                                        AND     AL,NOT 2
                                        OUT     AL,20

           Anti-Debugger Techniques: Interrupt Replacement
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        This technique involves replacing the vector of a  INTERRUPT 1/3
with the interrupt off another interrupt, and calling that instead. This
works especially well with INT 3, as it is only 1 byte long, and can not
simply be replaced with the proper Interrupt. Here is an example of  INT
replacement from the virus [H8urNMEs].  It changes INT 3 to point to the
tunneled INT 21, and calls INT 3 for all DOS requests:
------------------------------------------------------------------------

        mov     ax,3503
        int     21

        mov     int_3_seg,es
        mov     int_3_off,bx

        lds     dx, site_traced_off
        mov     ax,2503
        int     21

        mov     ds,cs

        mov     ax,3524
        int     3

        mov     int_24_seg,es
        mov     int_24_off,bx
------------------------------------------------------------------------

        It simply makes INT 3 point to DOS,  and uses this fact to fetch
the INT 24 vector.

       Anti-Debugger Techniques: INT 1 Tracing Destroys the Stack
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       When tracing through code,  with INT 1,  the 6 bytes below SP are
overwritten with the pushed returnig IP, CS, and Flags. There are 2 ways
to take advantage of this fact.  The first is to PUSH a value on to  the
stack, POP it, and then adjust SP and POP it again to see if it changes.
If it has, the code has been traced. Here is an example:
------------------------------------------------------------------------

                PUSH    AX
                POP     AX
                DEC     SP
                DEC     SP
                POP     BX              ;BX should point to the pushed AX.
                CMP     AX,BX
                JNE     CODE_IS_TRACED
------------------------------------------------------------------------

        The second  way is to store  a critigal value  like a Decryption
key in SP. This value should also point to the code, and you should  NOT
use any stack operations. This way,  if a debugger is running,  the code
that SP  points to will  be overwritten.  Here is a  complete program to
illustrate it. To make it run properly,  you must have to encrypt it.  I
will not how you how.. If you can not work it out you should not even be
reading this.  It also has the  added advantage of avoiding the TBAV '#'
(decryptor) flag. Any way here it is:
------------------------------------------------------------------------
;STACK.ASM

        radix   16

elength equ     (end - estart)/2

        org     100

        mov     bp,sp
        cli
        mov     sp,estart
        sti

        mov     bx,sp
        mov     cx,elength

eloop:  xor     cs:[bx],sp      ;SP is decryption key.
        inc     bx
        inc     bx              ;If a Debugger is running,
        cli                     ;All the code after ESTART will be
        add     sp,6            ;overwritten.
        sti
        loop    eloop

estart:
        cli
        mov     sp,bp
        sti

        mov     ah,9
        mov     dx,offset msg - 12
        add     dx,12
        int     21
        mov     ah,4c
        int     21

msg     db      'Yeah!!$'

end:

------------------------------------------------------------------------

 Anti-Debugger Techniques: Use Your Anti-Debug Routines as The Decrypt Key
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        This is a lot easier to do then it sounds. Basically, all you have
to do is retreive a byte from the Anti - Debugger routines each time,  and
use it to modify your decryption routine in some manor. Of course the code
you are decrypting must have been encrypted in a corresponding manner! Any
way, here is a code fragment example:
------------------------------------------------------------------------

;This code LODSBs a byte from the Anti-Debug routine, on each iteration,
;and ADDs it to the XOR key. Because of this the AV can not simply NOP
;out the INT 3, and other traps in the Anti-Debug routine which is called
;on each iteration! DEC_START is assumed to be the offset of the start of
;the encrypted code, while DEC_LENGTH is the number of bytes to decrypt.

                mov     dl,0aa  ;initial key.

decrypt:        mov     di,offset dec_start
                mov     cx,dec_length
                mov     si,offset decrypt       ;offset of code to use
                                                ;to modify decryption key.
dec_loop:       lodsb                           ;AL=byte from anti-debug
                                                ;routines

                add     dl,al                   ;MODIFY KEY. If code has been
                                                ;modified, the key will be
                                                ;wrong.

                xor     [di],dl                 ;decrypt
                inc     di

                call    anti_debug              ;kill debuggers.
                                                ;this call cant be NOP'd out,
                                                ;as it is part of the Decrypt
                                                ;key.

                cmp     si,offset end_ad        ;if SI has reached end of
                jne     no_fix                  ;anti-debug code, reset it.
                mov     si,offset decrypt

no_fix:         loop    dec_loop

                jmp     dec_start               ;JMP past Anti_Debug to
                                                ;the newly decrypted code..

Anti_Debug:     in      al,20   ;get IRQ status.
                or      al,2    ;Disable IRQ 1 (keyboard)
                out     20,al

                int     3       ;stop the debugger on each loop (you cant
                int     3       ;NOP these out!), note that when the debugger
                                ;stops here, the keyboard will be disabled,
                                ;so the can't do any thing!


                push    ax
                push    ds
                xor     ax,ax
                mov     ds,ax
                xchg    ax,[4]  ;Kill INT 1
                int     3       ;Fuck with their heads
                xchg    ax,[4]  ;restore INT 1
                pop     ds

                mov     ax,offset ad_jmp        ;destination of JMP
                push    ax
                pop     ax
                dec     ax
                dec     ax      ;if this code was traced, AX will no longer
                pop     ax      ;be equal to the JMP destination
                jmp     ax
                pop     ax
                ret

        (BELOW CODE IS ENCRYPTED)
dec_start:      in      al,20
                and     al,NOT 2
                out     20,al   ;Re-Enable Key board..

                <REST OF VIRUS CODE>

------------------------------------------------------------------------

                Anti-Debugger Techniques: The Running Line
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        The last method, I am going to illustrate, is called the Running
Line. It is VERY resistant to debuggers. It involves hooking INT 1,  and
Decrypting each instruction _JUST BEFORE_ it's run, and Re-Encrypting it
_STRAIGH AFTER_ it has been executed.  This way, only _1_ instruction at
a time is decrypted in memory. Here is a fully working example.
------------------------------------------------------------------------

;RUNLINE.ASM

        radix   16

        org     100

        xor     ax,ax                   ;ax=0
        mov     es,ax                   ;es=ax=0
        mov     di,es:W[4]
        mov     si,es:W[6]              ;save int 1 vector
        mov     es:W[4],offset tracer
        mov     es:W[6],cs              ;int1 = cs:tracer
        mov     bp,sp
        pushf
        or      B[bp-1],1               ;set TRACE flag
        popf                            ;set it

        xor     dx,dx                   ;this serves no purpose, and
                                        ;is just here because the first
                                        ;instruction after setting the
                                        ;flag is not traced.

;**********************************************************************
;** The below data, is the Encrypted instructions. The INT 1 handler **
;** only decrypts instruction on WORD (EVEN) boundaries. It XORs the **
;** instruction (WORD) with its offset in CS (ie. it's IP when it's  **
;** run). Thats why each word is XOR'd with $ (it's position).       **
;**********************************************************************

        dw      01f0e   XOR     $       ;PUSH CS / POP DS
        dw      009b4   XOR     $       ;MOV AH,9h
        dw      0ba90   XOR     $       ;NOP / MOV DX,
        dw      offset msg              ;offset msg
        dw      021cd   XOR     $       ;INT 21h
        dw      0e589   XOR     $       ;MOV BP,SP
        dw      06680   XOR     $       ;AND B[BP+,
        dw      0feff                   ;FF],FE (turn off TRACE flag).

last_enc        equ             $
        dw      0bb9d   XOR     $       ;POPF / MOV BX,
        dw      last_enc                ;LAST_ENC

        xor     cs:W[bx],bx             ;re-encrypt last instruction..

        mov     es:W[4],di
        mov     es:W[6],si              ;restore int 1 vector

        mov     ah,4c
        int     21

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;THINGS TO NOTE FROM THE ABOVE: Firstly, in the instructions
;       NOP
;       MOV     DX,OFFSET MSG
;the MOV DX opcode is on an odd boundary, and hence, the decryptor will
;not decrypt it. Secondly the 'DW OFFSET MSG' in MOV     DX,OFFSET MSG
;is not encrypted, because it it is data from another instruction, and
;therefore it will never be executed, and passed to the INT 1 handler.
;The same goes for the +FF(-1),FE in the AND B[BP-1],FE.


;**********************************************************************
;** The following procedure, is the work horse of this code. The CPU **
;** will call this INT 1 handler before each opcode as long as the   **
;** TRACE flag is set. Unlike most INT 1 handlers that you'll see in **
;** virii, this contains no defensive traps. This is because we are  **
;** tracing our own code, and not unknown (possibly hostile) code.   **
;** It retrieves the calling IP from the stack, and if it is odd,    **
;** exits. If even, it will re-encrypt the previous instruction, and **
;** decrypt the current one. It saves the calling IP, so that it can **
;** re-encrypt it when it is called for the next instruction.        **
;**********************************************************************

tracer:
        push    bp                      ;save BP
        mov     bp,sp                   ;BP=SP for reference point of stack.
        push    si                      ;save SI
        mov     bp,W[bp+2]              ;BP = calling IP (position of
                                        ;encrypted instruction).
        test    bp,1                    ;check if on an odd boundry..
        jnz     is_odd                  ;it is so leave.
        mov     si,cs:last              ;else get the position of the last
                                        ;decrypted instruction to reincrypt.
        mov     cs:last,bp              ;save current position for next time.
        xor     cs:W[si],si             ;re-encrypt last (XOR it with its IP)
        xor     cs:W[bp],bp             ;decrypt current (XOR it with its IP)
is_odd:
        pop     si                      ;restore SI
        pop     bp                      ;restore BP
        iret                            ;adeos!

last    dw      0                       ;last IP for re-encrpytion..
msg     db      'Yeah!!$'               ;EVERYBODY SAY YEAH!!!!
------------------------------------------------------------------------


Article taken from the MAG "Infected Voice"
Some virus releated stuff deleted. :-(
ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ


                          80386 DEBUG REGISTERS
                        -------------------------
                        Contents:       - Intro and overview
                                        - INT 13 intercepting (.ASM)
                                        - Literature

        The 80386 is famous not only for its Protected Mode which allows us
 to create more stable virii but in Real Mode we can play some tricks using
 the 80386's special abilities. Intel remind the system programmer they built
 powerful debugging tools inside the chip.
 Since the 80286 you can move the Interrupt Table from its throne 0000:0000
 into deep RAMpages by changing IDTR register. Cool !
        I just explored the 80386+ Debug Registers. A bulk of literature I
 have read contains a lot of info, but it appears with uncomprehensible
 material and has mistakes, so working code cannot be written. But I did it!

        Some difficulties I've met during my experiments:

        The first.
        Some types of EMM386, QEMM etc. may cause an Exception Error -
 Protection Violation. DR available for PL=0 only, Virtual Machine has PL=3,
 so Error occurrs. Use the VCPI or DPMI service to change the Debug Registers
 in this case.

        The second. RESUME FLAG.
        16-th bit of EFLAGS register contains the Resume Flag. It sets when
 Exception_1 (namely the breakpoint by code execution) appears.
 Exception executing before the code where breakpoint was set.
 When Exception done, we're back to the same address. What will happen?
 Exception_1. To avoid eternal cycle, Exception must be ignored until the
 next instruction, so ResumeFlag cause Exception ignorance for one instruc-
 tion. Then RF automatically clears. Real Mode doesn't use IRETD command so
 RF is unusable for this mode.
 I suggest to clear hardware breakpoint, set ordinal trace, then set hardware
 breapoint back.

        The fourth. INT_01 vector cannot be protected.

        Imagine you want to protect INT_01 vector, using hardware breakpoint.
 You can set the breakpoint on Read/Write_Data or Write_Data at address
 0000:0004. What will happen when something will change this vector ?
 Exception will be called right after vector changing. By which address ?

        The last. Breakpoint Defense Flag (BD)
        It appears before the command, trying to change one of debug
        registers. It's a mess. Nothing happened. Lets test it :

        Insert this code into INT_1 handler (see below) :

                cmp eax,00002000h       ; Breakpoint Defense Bit
                jz  NothingImpossible
                int 19h                 ; you will see if it works
                NothingImpossible:

        Run program.

        And now try to change DR7, for example.

                                xor eax,eax
                                mov dr7,eax
                                retn

        Run it after.
        As result all breakpoints will be switched off because BD doesn't work.
  Maybe it works in PM. Who knows ...

  Here's materials of my investigations.

  What to do if processor is not 386 ? The simplest way to avoid disaster -
  Int 06 handling - Invalid Opcode. If it appears, direct your virus code to
  8086 routines.
                        I wish you success!

  DEBUGGING.

        CPU provides three types od Debugging:

1. Single Step Interrupt  (INT 1).
----------------------------------------------------
   Activation condition: "Trace Flag" in EFLAGS is ON.
   Setting TF:   1)   pushf / pop  ax / or ax,0100H / push ax / POPF
                 2)   IRET with bit 8 set in ss:[sp+4]

     INT 01 appears right after the next executed command.
     INT 01            - places FLAGS register to stack (with TF=1)
                       - clears TF
                       - jumps far to address, stored in 0000:0004 (IP,CS)
                       - IRET
                       - next command executing
                       - INT 01 appears again and so on until TF not cleared.

   Application in viriis:- locating the true INT 21h or INT 13h addresses
                           (tracing till DOS or BIOS area)
                         - dynamic crypting/decrypting
                         - tracing the beginning of loaded program to
                           place virus' "JMP VIRUS" since 2nd or N-th command
                           (see Emmie virus, which invades since 2nd program
                            instruction)

2. The Breakpoint Interrupt (INT 3).
-------------------------------------
   It's ordinal program interrupt.
   The single difference is an one-byte opcode (0CCh).
   One byte size allows to replace any instruction to 0CCh for setting the
   breakpoint
   Technology is following:
              - save one byte of required instruction
              - place 0CCh here - INT 3 will appear at reaching it
        Algorithm description:
              - handler itself
              - place back the saved byte
              - CS:IP in stack points to byte after 0CCh
                change IP in stack to address or replaced command (IP-1)
              - IRET (to loose this Breakpoint) or...
             If you want to use breakpoint at this place again,
              - handle the INT 1 and make one tracing step;
                Your INT 1 handler must place back 0CCh and clear themself


   Application in viriis: - splicing
                          - placing INT 3 many times in your virus body to
                            annoy debugger

3.  Debug Registers
-----------------------
         In processors 80386 and higher appeared new, more slim debuuging
    tools. These are additional 32-bit registers DR0..DR7 , which allows
    to handle such Exceptions, as:

        at reaching CS:IP(EIP) certain values
or      data read/write
or      data read

        Debug registers allows to set to 4 different breakpoints.
These are HARDWARE breakpoints in difference from usual INT 1 and INT 3.

        Debug Registers available as in Protected Mode for PL=0, as in Real
mode.

DR0-3 contains linear address of breakpont:   (CS*10H+IP)
      (Linear address can differs from physical if Memory Page'ing enabled.)
DR4-5 reserved. ( For example, TASM cause a compilation error if you try to
      use command "MOV DR4,EAX
DR6   status register

                                      15 14 13                   3  2  1  0
                                      і  і  і                    і  і  і  і
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 BT BS BD 0 0 0 0 0 0 0 0 0 B3 B2 B1 B0
                                      і  і  і                    ѕ  і  і  і
              BreakPoint Task Switch Нѕ  і  і                    НННѕ  і  і
              BreakPoint Single Step ННННѕ  і                    ННННННѕ  і
              BreakPoint Defence НННННННННННѕ                    НННННННННѕ

     All described debugging resources are operates with INT 01
     ( Exception 01 ), because that, INT 1 handler must know, by what reason
     it was called. We can find this reason in DR6 register.
     DR6 doesn't clears by Processor, so you must clean it after every
     call, or we will not know what was the reason of Exception.

     There are only 7 bits used in DR6.
     When Exception occures, processor sets the reason of it in DR6:

                BT  -   switching to task, which TSS contains Trap Flag
                BS  -   old good single step tracing - has highest
                        priority: when BS set, other reasons may presents too
                BD  -   Breakpoint defense - next instruction will read or
                        write from/to one of DR's
                B0,B1,B2,B3 -
                        Exception by one of 4 breakpoints

DR7  Control Register
     Contains info about breakpoints:

    30  28   26  24   22  20   18  16      12       8           4           0
    і   і    і   і    і   і    і   і       і        і           і           і
 LEN3 RW3 LEN2 RW2 LEN1 RW1 LEN0 RW0 0 0 0 0 0 0 GE LE G3 L3 G2 L2 G1 L1 G0 L0

   Gi - Global Breakpoint: allowed for all tasks
   Li - Local Breakpoint : for this task only
   LE,GE (Local Exact, Global Exact)
                 Used when breakpoints to data has been set.
                 Doesn't influent on Code Breakpoints.
                 Influent on all Data Breakpoints in whole.

                 Convaiering allows processor to take more than one command
                 to execute.
                 That's a reason why Data Breakpoint Exception calls later
                 than data operating command has been executed.

                 GE or LE setting (for Global or Local Breacpoint in accord)
                 slows internal processor's operations and calls Exception
                 right in time.
   LENi Ё RWi  - 2-bit fields for data breakpoints.
          LENi - size of data (1,2 or 4 bytes)
          RWi  - 00 = by Code              10 = undefined
                 01 = by Data Write        11 = by Data Read/Write

;========================== Cut here (start) =============================

;       This program enables the Code Breakpoint at INT 13 entrance.
;       (INT 13 vector is taken from Vector Table) It uses DR0 register.
;       Exception handler BEEPs when reached.
;
;       For 386 and higher only.

.MODEL TINY
.386p
.CODE
 ORG 100h
 START:
;--------------------
      Copyright:
        mov ah,09
        mov dx,offset CMsg
        int 21h
        jmp short OverCop
        CMsg db '80386 DEBUG REGISTERS AUDIO-DEMO GLUE.',0dh,0ah
             db 'Copyright (C) 1995, by LovinGOD, STEALTH group',0dh,0ah
             db 'Beeps when Int 13 entry point reached','$'
      OverCop:
;--------------------
        mov ax,3513h            ; Get INT 13 address
        int 21h
                                ; Converting ES:BX to a physical address
                                ; ES*10h+BX, store it to EAX
        xor eax,eax
        mov ax,es
        mov cl,4
        shl eax,cl

        and ebx,0000FFFFh
        add eax,ebx

        mov dr0,eax             ; DR0 contains address of breakpoint

        xor eax,eax             ; DR6 - status register
        mov dr6,eax             ; Clear it

                                ; DR7 - control register

        xor eax,eax             ; Disabling all Debug Breakpoints, and
                                ; clearing LEN0 and RW0 (our Breakpoint is
                                ; a Code Breakpoint)
        or  al,2                ; G0 - it's global breakpoint
        mov dr7,eax

        pushf                   ; Clear TraceFlag
        pop ax
        and ah,0FEh
        push ax
        popf

        mov dx,offset Tracer    ; Set our Exception handler
        mov ax,2501h
        int 21h

        mov dx,offset theend    ; TSR
        int 27h

ЬЬЬ  TRACER :ЬЬЬЬЬ              ; Exception handler

        push bp eax

        mov bp,sp
        mov eax,dr6             ; status register
        ;* here you can include test of BD flag
        test eax,00004000h      ; single step tracing ?
        jz  HardBreak           ;

                ; single step tracing occured, it was used by us to
                ; restore our hardware breakpoint (see further)
                ; DR0 is a Hardware breakpoint again

        xor eax,eax
        mov dr6,eax
        or  eax, 00000002h      ; Setting Exception by DR0
        and eax,0FFF0FFFFh      ; Code Exception
        mov dr7,eax

        and word ptr [bp+0Ah],0FEFFh    ; Clearing trace flag in stack
        jmp short exitrace

HardBreak:                      ; DR0 Exception handler

        mov eax,dr6             ; Clear status register
        xor eax,eax
        mov dr6,eax

        mov eax,dr7
        and eax,0FFFFFFFDh
        mov dr7,eax             ; Disable DR0 Hardware Breakpont, or else
                                ; recycling when return (ResumeFlag doesn't
                                ; resumes... making it by the handle)

                                ; The purpose of our hardware breakpoint
        mov ax,0E07h            ; Say "What's a nice fuckin hell! "
        int 10h                 ; (censored to "BEEP")

;       ....                    ; Insert everything what you need.

  SetTF:                        ; Setting usual tracing for further
                                ; DR0 resuming
        or word ptr [bp+0Ah],0100h      ; Walkin thru the condemned place,
                                        ; carry your flag high !
  ExiTrace:
        pop eax bp
        iret

 TheEnd:
 End Start


ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ
         Your code could be inserted here - so send it to me

ЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯЯ

How to contact the assembler of this AntiDebugger FAQ?

Hmmm, hard....  try to locate my address in the file ROSEBBS.TXT :))