bilbo
December 23rd, 2004, 06:06
Hi Orp,
one macroscopic difference is that, if you are in USER MODE (RING 3) an "INT 1" instruction generates an access violation exception, not a single step exception.
In all cases (RING 0 or RING 3), your handler can always peek at the opcode which generated the exception.
On the other hand, it is useless for the exception handler to look at the EFLAGS, as FrankRizzo suggested, because the Trace Flag is automatically reset by the hardware as soon as the exception is generated.
Have a look at the following VisualC snippet:
Code:
#include <windows.h>
#include <stdio.h>
//#define INT_1
void
main(void)
{
LPEXCEPTION_POINTERS pep = 0;
__try {
#ifdef INT_1
__asm int 1;
#else
__asm {
pushfd
or dword ptr [esp], 0x100
popfd
nop
nop // <-- exception here
}
#endif
}
// copy the pointers to "pep" be accessed by the handler later
__except (pep=GetExceptionInformation(), EXCEPTION_EXECUTE_HANDLER) {
printf("%x EIP=%x TRACEFLAG=%x opcode=%x\n",
pep->ExceptionRecord->ExceptionCode,
pep->ExceptionRecord->ExceptionAddress,
pep->ContextRecord->EFlags & 0x100,
*(LPBYTE)pep->ExceptionRecord->ExceptionAddress);
exit(0);
}
}
If you compile the code with INT_1 defined, you will see the output
Quote:
c0000005 EIP=401034 TRACEFLAG=0 opcode=cd
|
C0000005 is the code for STATUS_ACCESS_VIOLATION, CD is the opcode for "int N"
If you compile the code with INT_1 not defined, you will see the output
Quote:
80000004 EIP=40103e TRACEFLAG=0 opcode=90
|
80000004 is the code for STATUS_SINGLE_STEP, 90 is the opcode for "nop"
Regards, bilbo