View Full Version : Getting around anti-debugger code

October 19th, 2007, 20:51
Malicious software will often contain anti-debugger code to make it more difficult to analyze the target. One of the many common anti-debugger tricks is breakpoint-searching. This involves scanning areas of memory for breakpoints set by the analyst via their debugger. We can easily defeat this with our own anti-anti-debugger trick.

When setting a software-breakpoint (as opposed to a hardware-breakpoint) in a program, the debugger overwrites the first byte of the instruction at the breakpoint with a 0xCC byte. This byte corresponds to the x86 instruction int 3. When this instruction is hit during execution, a software interrupt generates an exception and is caught by the debugger, at which point the debugger will automatically replace the 0xCC byte with the original byte from the original instruction and notify the analyst that their breakpoint was hit.

Why don't we ever see these int 3 instructions in memory after we set breakpoints? Because the debugger hides them from us to simplify analysis. But rest assured, they're there.

So why does any of this matter? Because breakpoint-searching is done by searching for 0xCC bytes. Thus, if we can create a breakpoint without using 0xCC bytes, then we can defeat this anti-debugger trick. Instead of using your debugger's Set-Breakpoint command, try overwriting the instruction that you want to break on with something else that will cause an exception, such as the ud2 instruction (0xF0 0x0B) ("http://www.x86.org/secrets/opcodes/ud2.htm"), icebp instruction (0xF1) ("http://www.x86.org/secrets/opcodes/icebp.htm"), or a good ol' divide-by-zero such as xor eax, eax (0x33 0xC0) followed by div eax (0xF7 0xF0). Any of these will cause your debugger to break and return control to you (assuming your debugger isn't set to ignore such exceptions). Of course, the only downside is that once your debugger breaks at these custom-breakpoints, you'll have to restore the original instructions yourself (and set EIP to point to them) as opposed to having the debugger automatically do it.