13

Inclusion of an INT 2D instruction appears to be a fairly common anti-debugging tactic used by Windows malware authors. From what I understand, it causes a process to act differently when a debugger is attached from when it is not attached.

I have read that this is due in part to an asynchronous (not part of normal program flow) increment to the instruction pointer. This increment can be made to lead to instruction scission.

Could someone explain this anti-debugging tactic, specifically why this increment to the instruction pointer occurs, and what happens when a debugger is and is not attached.

16

From my "Ultimate" Anti-Debugging reference (see pferrie.host22.com):

The interrupt 0x2D is a special case. When it is executed, Windows uses the current EIP register value as the exception address, and then it increments by one the EIP register value. However, Windows also examines the value in the EAX register to determine how to adjust the exception address. If the EAX register has the value of 1, 3, or 4 on all versions of Windows, or the value 5 on Windows Vista and later, then Windows will increase by one the exception address. Finally, it issues an EXCEPTION_BREAKPOINT (0x80000003) exception if a debugger is present. The interrupt 0x2D behaviour can cause trouble for debuggers. The problem is that some debuggers might use the EIP register value as the address from which to resume, while other debuggers might use the exception address as the address from which to resume. This can result in a single-byte instruction being skipped, or the execution of a completely different instruction because the first byte is missing. These behaviours can be used to infer the presence of the debugger. The check can be made using this code (identical for 32-bit and 64-bit) to examine either the 32-bit or 64-bit Windows environment:

xor  eax, eax ;set Z flag
int  2dh
inc  eax ;debugger might skip
je   being_debugged

[end]

So you can see that there's nothing asynchronous happening here. The change occurs immediately when the exception occurs. As far as why it occurs, the skipped byte is intended to be used to pass one byte of additional information at the time of the exception.

  • Indeed it was pretty obvious that there wasn't any "asyncronousness" check going on when I started reading about it. I would imagine the UD2 instruction might do something similar? – cb88 Apr 3 '13 at 15:40
  • 1
    UD2 does not have the same effect. That one behaves like any other invalid instruction. It exists solely for the purpose of seeing what a definitely invalid instruction looks like (as opposed to a random opcode combination that's invalid today but becomes valid in a new CPU tomorrow). – peter ferrie Apr 5 '13 at 20:40
6

An Anti-Reverse Engineering Guide

And the primary explanatory comment from the code presented there.

// The Int2DCheck function will check to see if a debugger
// is attached to the current process. It does this by setting up
// SEH and using the Int 2D instruction which will only cause an
// exception if there is no debugger. Also when used in OllyDBG
// it will skip a byte in the disassembly and will create
// some havoc.

Note here is a bit on SEH.

3

For some good examples of usage of INT2d in Malware, check out Dr. Fu's blog:

http://fumalwareanalysis.blogspot.com/p/malware-analysis-tutorials-reverse.html

There are 3 different examples and explanations, one is with Max++ which gives a good idea of what to expect in your own Malware samples.

3

The interrupt 0x2D is a special case. When it is executed, Windows uses the current EIP register value as the exception address, and then it increments by one the EIP register value. However, Windows also examines the value in the EAX register to determine how to adjust the exception address. If the EAX register has the value of 1, 3, or 4 on all versions of Windows, or the value 5 on Windows Vista and later, then Windows will increase by one the exception address. Finally, it issues an EXCEPTION_BREAKPOINT (0x80000003) exception if a debugger is present. The interrupt 0x2D behaviour can cause trouble for debuggers. The problem is that some debuggers might use the EIP register value as the address from which to resume, while other debuggers might use the exception address as the address from which to resume. This can result in a single-byte instruction being skipped, or the execution of a completely different instruction because the first byte is missing. These behaviours can be used to infer the presence of the debugger. The check can be made using this code (identical for 32-bit and 64-bit) to examine either the 32-bit or 64-bit Windows environment:

At first, I didn't understand the meaning of the "exception address" and I think I'm not the only one. Fortunately, the Dr. Fu's blog have a better explanation about it.

From Dr Fu's blog:

Here the "exception address" is the "EIP value of the context" (which to be copied back to user process), and the "EIP register value" is the real EIP value of the user process when the exception occurs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.