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