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

 This supposed to be a reply to the author of 'Anti-Anti Debugging Tricks',
 Michael Forrest. If this ever reaches you, please contact me...

 NOTE: 'Anti-Anti Debugging Tricks' was kind of a reply to Inbar Raz' '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.

 If it really is true that you've never seen a program lock out the keyboard,
 it's about time you saw one. Please try the example in my article and watch
 your keyboard completely freeze in Soft-ICE (or nearly _any_ other program),
 no matter if BREAK is ON or not.

> > 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.

 That's just because your machine probably isn't a PC/XT :). On ATs and up
 those PPI ports are occupied by the Keyboard Controller (KBC). It's possible
 to disable its keyboard interface, but it's no trouble to Soft-ICE in any
 case, though, just like the Interrupt Mask Register trick.

> > 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.

 Yes, that's right. But although the Interrupt Descriptor Table (IDT) which
 _you_ were talking about, the VM86 environment has a virtual interrupt table
 and messing with _it_ will be enough in most cases. Since any program running
 in a VM86 task still needs DOS services, their behaviour can be changed...

> > 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.

 You didn't get it, did you? If you don't succeed in tracing the code properly
 at the first trial, totally messed up VM86 interrupt vectors will cause the
 VM86 program crash, along with DOS, and this guarantees you that the only way
 out is a reset even if the 386 debugger still works! Haven't seen yet such an
 intelligent debugger which would actually create a VM86 task as a copy of the
 first 1MB in Real Mode by using memory paging, not _in_ the 1MB area...

> > 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.

 Nobody's perfect and remember that a 386 debugger cannot be easily fooled.

> > 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.

 Actually, that doesn't defeat even DEBUG. The trick won't work even on Turbo
 Debugger it was designed for (unless it's the v3.1 of TD that doesn't have
 that "bug"). Anyway, a simple CLI will effectively disable keyboard on all
 Real Mode debuggers and even 386 debuggers must emulate the CLI by setting
 IOPL<3 to prevent this.

> > 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.
>
>       [fixed example removed...]

 Isn't the description clear enough? Turbo Debugger _does_ show CS:IP values
 but the issue here is that when a jump is initiated to an address which is
 already on screen, decoded, but it's in the middle of an opcode, TD will not
 re-decode the instruction CS:IP points to, on screen, until debugger screen is
 refreshed. There may not be many debuggers doing this but TD is one. And Mr.
 Raz _did_ mention that the trick really doesn't affect execution in any way,
 its only purpose is to confuse the user!

> > 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.

 Why is it that you're mocking these tricks all the time? Since you're so
 anxious to criticize his Real Mode debugger traps, there must be some tricks
 you know that are worth something against 386 debuggers. Wouldn't you share
 them with the rest of us?

> > 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.

 Well, as such this trick isn't really much worth but linking another routine
 to it might be... although that was another trick.

> > 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.

 In case you already didn't know it, single-stepping through code in Real Mode
 will _always_ overwrite the six bytes prior to SS:SP. This is because a
 single-step trap is also an interrupt and therefore also needs to save FLAGS
 and CS:IP. It is unavoidable in Real Mode, but Protected Mode has ways of
 saving that info onto the new task's stack in case of a task switch.

> > 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.

 As mentioned, it is _only_ meant for fooling TD386! Soft-ICE doesn't grab
 INT 00 handler for itself and thus nothing unusual happens. However, there is
 no way to get TD386 execute the VM86 INT 00 routine, other than through some
 tedious code and memory manipulation (can't use INT 00 or dividing by zero)...

> > 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.

 Here I must agree with you. This trick is the only one that is no good as
 regards compatibility, but he _did_ mention that... indirectly. ;)

> > 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.

 However, only four hardware breakpoints are available simultaneously, and
 using more breakpoints requires taking advantage of old INT 3 -style
 breakpoints. So watch out not to get your fingertips burnt...

> > 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.
> ...

 Hmm. What did the macros consist of? 
  There is another bug in Soft-ICE, too. Let's first assume we know a memory
 location that will be read or written to in the encrypted code and we want to
 get back to the debugger at that point. In case of self-tracing code, hardware
 data (memory access) breakpoints are useless since Soft-ICE decides to process
 the VM86 single-step trap before the breakpoint. This is probably because both
 data breakpoints and the single-step trap are checked for simultaneously, so
 bits indicating both conditions will be set in DR6. If INT 01 routine modifies
 the code it traces, a breakpoint could be set to be triggered by that
 modification but a simple IRET as INT 01 routine disables all data breakpoints
 in the code that is being self-traced.
  So much for Soft-ICE...

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

 I'd really like to see your implementation of it. Just curious how you solved
 the problem.

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

---
 mhk@sci.fi
