Dailydave mailing list archives

Re: Tool announce: user mode single stepping


From: "Matt Conover" <mconover () gmail com>
Date: Wed, 29 Nov 2006 17:15:09 -0800

I guess you never heard of tcodetrace...
http://72.14.203.104/search?q=cache:gDeAFf4bIJ4J:www.cybertech.net/~sh0ksh0k/projects/tcodetrace

There was been a documented included with the code since March 2006 named
"Self Single-Stepping.txt" which as title implies, utilizes this exact
technique. The source code has also been posted there for a long time..
these are the contents of "Self Single-Stepping.txt":

For static code, every instruction between
TRAP_STATIC_CODE_START/TRAP_STATIC_CODE_END is trapped
For dynamic code, you specify the code address and code size all within
TRAP_DYNAMIC_CODE

You specify all callback that will be called for each instruction about to
be executed.
The callback can analyze the instruction and chose one of these options:
1. Execute the instruction (return TRAP_EXECUTE)
2. Stop trapping (return TRAP_STOP) and continue after the trapping code (
e.g., first instruction after TRAP_STATIC_CODE_END/TRAP_DYNAMIC_CODE)
3. Kick in a debugger (return TRAP_DEBUG) by leaving the single-step
exception unhandled
4. Skip the instruction (return TRAP_SKIP).
5. Disable trapping and execute until a breakpoint is reached (TRAP_GO)
6. Step over the current instruction (TRAP_STEP_OVER). If the next
instruction is a call, for example, it will execute the function and then
break after the call completes.
7. Step out of the current function (TRAP_STEP_OUT).

Non single-step exceptions are left unhandled so that the program will
function as it normally would have

The benefit of doing it this is way as opposed to using the native Win32
debugging technique is that:
1. You can load whatever code you want to execute within the current process
2. You don't leave signs the code is being debugged like debugging does

Currently it will skip int1/int3/into/popf automatically, but anything more
advanced should be done by the user-defined handler.

+++ TRAP_SAMPLE.C

TRAP_CONTEXT TrapA, TrapB, TrapC, *CurrentTrap;
BOOL DumpInstruction(TRAP_CONTEXT *TrapContext, CONTEXT *CPU);
DWORD TestFunc();

void TestTrap()
{
   char buf[] = "\xcc\x90\xcc\x90";

   CurrentTrap = &TrapA;
   TRAP_STATIC_CODE_START(TrapA, DumpInstruction)
   _asm int 3
   _asm mov eax, 0x12345678
   _asm mov ebx, 0xAABBCCDD
   TRAP_STATIC_CODE_END(TrapA)
   printf("\n=== Finished (stepped through %d instructions)\n\n",
TrapA.Count);
   assert(TRAP_COUNT(TrapA) == 3);

   CurrentTrap = &TrapB;
   TRAP_STATIC_CODE_START(TrapB, DumpInstruction)
   _asm call TestFunc
   TRAP_STATIC_CODE_END(TrapB)
   assert(TRAP_COUNT(TrapA) == 3);
   printf("\n=== Finished (stepped through %d instructions)\n\n",
TrapB.Count);

   CurrentTrap = &TrapC;
   TRAP_DYNAMIC_CODE(TrapC, buf, 4, DumpInstruction)
   printf("\n=== Finished (stepped through %d instructions)\n\n",
TrapC.Count);
   assert(TRAP_COUNT(TrapC) == 4);
}

__declspec(naked) DWORD TestFunc()
{
   _asm
   {
       mov eax, 0xABABCDCD
       ret
   }
}

BOOL DumpInstruction(TRAP_CONTEXT *TrapContext, CONTEXT *CPU)
{
   DWORD Address = CPU->Eip;
   BYTE *p = (BYTE *)Address;

   {
       // Demonstrate that it isn't detected as a debugger
       BOOL (*f)();
       f = (BOOL (*)())GetProcAddress(GetModuleHandle("kernel32"),
"IsDebuggerPresent");
       assert(f && !f());
   }

   printf("Executing 0x%08lx", Address);
   if (!TRAP_IN_RANGE(Address, *CurrentTrap)) printf(" (outside trap
range)");
   putchar('\n');
   return TRAP_CONTINUE;
}

+++ OUTPUT

Executing 0x00418165
Executing 0x00418166
Executing 0x0041816b

=== Finished (stepped through 3 instructions)

Executing 0x0041820f
Executing 0x004013ac (outside trap range)
Executing 0x004183e0 (outside trap range)
Executing 0x004183e5 (outside trap range)

=== Finished (stepped through 4 instructions)

Executing 0x0012feb4
Executing 0x0012feb5
Executing 0x0012feb6
Executing 0x0012feb7

=== Finished (stepped through 4 instructions)

#include "disasm.h"

#define ENABLE_TRAPPING_ON_CONTEXT(c) (c)->EFlags |= EFLAGS_TF
#define DISABLE_TRAPPING_ON_CONTEXT(c) (c)->EFlags &= ~EFLAGS_TF

#define ENABLE_BREAKPOINTS_ON_CONTEXT(c) \
{ \
   (c)->EFlags &= ~EFLAGS_RF; \
   if ((c)->Dr0) (c)->Dr7 |= (1<<0); \
   if ((c)->Dr1) (c)->Dr7 |= (1<<1); \
   if ((c)->Dr2) (c)->Dr7 |= (1<<2); \
   if ((c)->Dr3) (c)->Dr7 |= (1<<3); \
}
#define DISABLE_BREAKPOINTS_ON_CONTEXT(c) \
{ \
   (c)->EFlags |= EFLAGS_RF; \
   (c)->Dr7 &= ~0x0F; \
}

#define SET_EFLAGS(flags) \
{ \
   _asm mov eax, flags \
   _asm push eax \
   _asm popfd \
}

#define ENABLE_TRAPPING() \
{ \
   _asm pushfd \
   _asm pop eax \
   _asm or eax, EFLAGS_TF \
   _asm push eax \
   _asm popfd \
}

#define DISABLE_TRAPPING() \
{ \
   _asm pushfd \
   _asm pop eax \
   _asm mov ebx, EFLAGS_TF \
   _asm not ebx \
   _asm and eax, ebx \
   _asm push eax \
   _asm popfd \
}

#define ENABLE_BREAKPOINTS() \
{ \
   _asm pushfd \
   _asm pop eax \
   _asm mov ebx, EFLAGS_RF \
   _asm not ebx \
   _asm and eax, ebx \
   _asm push eax \
   _asm popfd \
}

#define DISABLE_BREAKPOINTS() \
{ \
   _asm pushfd \
   _asm pop eax \
   _asm or eax, EFLAGS_RF \
   _asm push eax \
   _asm popfd \
}

// The trap handler must return one of these three values:
#define TRAP_CONTINUE 1  // Contiues execution with trapping enabled
#define TRAP_STOP 2      // Stop execution of trapping code, continue
immediately after all trapping code
#define TRAP_DEBUG 3     // Leaves the single step exception unhandled
#define TRAP_SKIP 4      // Skips an instruction instruction
#define TRAP_STEP_OVER 5 // Runs until the instruction following the current
one is reached (used for branches or privileged instructions)
#define TRAP_STEP_OUT 6  // Runs until a return instruction is reached
#define TRAP_GO 7 // Continues execution with trapping disabled

typedef BOOL (*USER_TRAP_HANDLER)(struct _TRAP_CONTEXT *TrapContext, CONTEXT
*CPU);

#define TRAP_STATIC_CODE_START(TrapId, UserTrapHandler, disasm) \
   assert(DISASM_ARCH_TYPE(disasm) == ARCH_X86); \
   memset(&TrapId, 0, sizeof(TrapId)); \
   TrapId.Disassembler = disasm; \
   TrapId.Handler = UserTrapHandler; \
   TrapId.CommandFile = stdin; \
   CurrentTrap = &TrapId; \
   __try \
   { \
       PEXCEPTION_ROUTINE InternalHandler = NULL; \
       _asm { mov eax, fs:[0] } \
       _asm { mov eax, [eax+4] } \
       _asm { mov InternalHandler, eax } \
       assert(!IsBadCodePtr((FARPROC)InternalHandler)); \
       TrapId.InternalHandler = InternalHandler; \
       goto TrapId##_CodeEnd; \
TrapId##_GetStartAddress: \
       TrapId.StartPointer = (DWORD)GetEIP() + 13; \
       ENABLE_TRAPPING() \
       _asm { nop }

#define TRAP_STATIC_CODE_END(TrapId) \
       _asm { nop } \
TrapId##_CodeEnd: \
       TrapId.EndPointer = (DWORD)GetEIP() - 6; \
       goto TrapId##_GetStartAddress; \
       HANDLE_TRAP(TrapHandler)

#define TRAP_DYNAMIC_CODE(TrapId, Code, CodeSize, UserTrapHandler, disasm) \
   assert(DISASM_ARCH_TYPE(disasm) == ARCH_X86); \
   memset(&TrapId, 0, sizeof(TrapId)); \
   TrapId.Disassembler = disasm; \
   TrapId.CommandFile = stdin; \
   TrapId.Handler = UserTrapHandler; \
   CurrentTrap = &TrapId; \
   __try \
   { \
       PEXCEPTION_ROUTINE InternalHandler = NULL; \
       _asm { mov eax, fs:[0] } \
       _asm { mov eax, [eax+4] } \
       _asm { mov InternalHandler, eax } \
       assert(!IsBadCodePtr((FARPROC)InternalHandler)); \
       TrapId.InternalHandler = InternalHandler; \
       TrapId.StartPointer = (DWORD)Code; \
       TrapId.EndPointer = (DWORD)(Code + CodeSize); \
       _asm lea ebx, Code \
       _asm mov ebx, [ebx] \
       _asm pushfd \
       _asm pop eax \
       _asm or eax, EFLAGS_TRAP \
       _asm push eax \
       _asm popfd \
       _asm jmp ebx \
   HANDLE_TRAP(TrapHandler)

#define HANDLE_TRAP(a) } __except(a(GetExceptionInformation())) { }

#define IS_TRAP(a) ((a)->ExceptionRecord->ExceptionCode ==
EXCEPTION_SINGLE_STEP)
#define IS_BREAKPOINT(a) ((a)->ExceptionRecord->ExceptionCode ==
EXCEPTION_BREAKPOINT)

#define DUMP_TRAP_EXCEPTION(e) \
{ \
   DWORD e_i = 0; \
   printf("Exception code: "); \
   switch ((e)->ExceptionCode) \
   { \
       case EXCEPTION_ACCESS_VIOLATION: printf("access violation\n");
break; \
       case EXCEPTION_BREAKPOINT: printf("breakpoint reached\n"); break; \
       case EXCEPTION_DATATYPE_MISALIGNMENT: printf("datatype
misalignment\n"); break; \
       case EXCEPTION_SINGLE_STEP: printf("single step trap\n"); break; \
       case DBG_CONTROL_C: printf("Control-C (application break)\n");
break; \
       default: printf("unknown exception code = 0x%08lx\n",
(e)->ExceptionCode); break; \
   } \
   if ((e)->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
printf("Non-continuable\n"); \
   printf("Exception address: 0x%08lx\n", (e)->ExceptionAddress); \
   if ((e)->NumberParameters != -1 && !(e)->NumberParameters) \
   { \
       printf("Exception information:\n"); \
       for (e_i = 0; e_i < (e)->NumberParameters; e_i++)
printf("\t0x%08lx\n", (e)->ExceptionInformation[e_i]); \
   } \
   putchar('\n'); \
}

#define DUMP_TRAP_CONTEXT(c) \
{ \
   printf("Registers:\n"); \
   printf("EIP: 0x%08lx  ESP: 0x%08lx  EBP: 0x%08lx  EFLAGS: 0x%08lx\n",
(c)->Eip, (c)->Esp, (c)->Ebp, (c)->EFlags); \
   printf("EAX: 0x%08lx  EBX: 0x%08lx  ECX: 0x%08lx  EDX: 0x%08lx\n", \
       (c)->Eax, (c)->Ebx, (c)->Ecx, (c)->Edx); \
   printf("ESI: 0x%08lx  EDI: 0x%08lx\n", (c)->Esi, (c)->Edi); \
   putchar('\n'); \
}

#define DUMP_TRAP_INFO(a) \
{ \
   DUMP_TRAP_EXCEPTION((a)->ExceptionRecord); \
   DUMP_TRAP_CONTEXT((a)->ContextRecord); \
}

// NOTE: this will of course return false if the to-be-trapped code does a
call or jump
// to code outside of the trap range
#define TRAP_IN_RANGE(eip, TrapId) (eip >= (TrapId).StartPointer && eip <
(TrapId).EndPointer)

TRAP_CONTEXT *CurrentTrap;

int TrapHandler (EXCEPTION_POINTERS *Context);

#define RETURN_TRAP_ERROR(c) \
{ \
   fflush(stdout); fflush(stderr); \
   TrapDisableAllBreakpoints(CurrentTrap); \
   DISABLE_TRAPPING_ON_CONTEXT(c); \
   ENABLE_BREAKPOINTS_ON_CONTEXT(c); \
   if (CurrentTrap->PendingBreakpoints)
TrapReenableBreakpoints(CurrentTrap); \
   (c)->Dr6 = 0; \
   CurrentTrap->BreakpointOccurred = FALSE; \
   CurrentTrap->MemoryBreakpointAddress = NULL; \
   return EXCEPTION_CONTINUE_SEARCH; \
}

#define RETURN_TRAP_STOP(c) \
{ \
   DISABLE_BREAKPOINTS_ON_CONTEXT(c); \
   DISABLE_TRAPPING_ON_CONTEXT(c); \
   TrapRemoveAllBreakpoints(CurrentTrap); \
   (c)->Dr6 = 0; \
   CurrentTrap->BreakpointOccurred = FALSE; \
   CurrentTrap->MemoryBreakpointAddress = NULL; \
   CurrentTrap->LastTrapType = TRAP_STOP; \
   return EXCEPTION_EXECUTE_HANDLER; \
}

#define RETURN_TRAP_GO(c) \
{ \
   fflush(stdout); \
   memcpy(&CurrentTrap->PreviousContext, (c), sizeof(CONTEXT)); \
   DISABLE_TRAPPING_ON_CONTEXT(c); \
   ENABLE_BREAKPOINTS_ON_CONTEXT(c); \
   if (TRAP_IN_RANGE((c)->Eip, *CurrentTrap)) CurrentTrap->TrapExecuted++;
\
   CurrentTrap->TotalExecuted++; \
   if (CurrentTrap->PendingBreakpoints)
TrapReenableBreakpoints(CurrentTrap); \
   (c)->Dr6 = 0; \
   CurrentTrap->BreakpointOccurred = FALSE; \
   CurrentTrap->MemoryBreakpointAddress = NULL; \
   CurrentTrap->LastTrapType = TRAP_GO; \
   return EXCEPTION_CONTINUE_EXECUTION; \
}

#define RETURN_TRAP_CONTINUE(c) \
{ \
   fflush(stdout); \
   memcpy(&CurrentTrap->PreviousContext, (c), sizeof(CONTEXT)); \
   ENABLE_TRAPPING_ON_CONTEXT(c); \
   ENABLE_BREAKPOINTS_ON_CONTEXT(c); \
   (c)->Dr6 = 0; \
   CurrentTrap->BreakpointOccurred = FALSE; \
   CurrentTrap->MemoryBreakpointAddress = NULL; \
   CurrentTrap->LastTrapType = TRAP_CONTINUE; \
   return EXCEPTION_CONTINUE_EXECUTION; \
}

#define TRAP_HANDLE_BREAKPOINT() \
{ \
   Breakpoint->CurrentTriggerCount++; \
   Breakpoint->TotalTriggerCount++; \
   if (!TrapDisableBreakpoint(CurrentTrap, Breakpoint)) { assert(0); goto
abort; } \
   if (Breakpoint->CurrentTriggerCount >= Breakpoint->Threshold) \
   { \
       if (Breakpoint->Flags) \
       { \
           printf("*** Hit "); \
           if (Breakpoint->Flags & BREAKPOINT_READ) printf("read/write ");
\
           else printf("write "); \
           printf("memory breakpoint 0x%08lx at 0x%02lX\n",
Breakpoint->SavedAddress, CPU->Eip); \
       } \
       else \
       { \
           printf("*** Hit code breakpoint at 0x%02lX\n",
Breakpoint->SavedAddress); \
           assert(Breakpoint->SavedAddress == (BYTE *)CPU->Eip); \
       } \
       Breakpoint->CurrentTriggerCount = 0; \
       if (Breakpoint->RemoveOnTrigger) \
       { \
           if (!TrapRemoveBreakpoint(CurrentTrap, Breakpoint)) { assert(0);
goto abort; } \
       } \
       else \
       { \
           Breakpoint->Reenable = TRUE; \
           CurrentTrap->PendingBreakpoints = TRUE; \
       } \
   } \
   else \
   { \
       Breakpoint->Reenable = TRUE; \
       CurrentTrap->PendingBreakpoints = TRUE; \
   } \
}

TRAP_CONTEXT TrapThreads[TRAP_MAX_THREADS];
TRAP_CONTEXT *CurrentTrap, *OriginalTrap;
extern BOOL Interactive;

int TrapHandler(EXCEPTION_POINTERS *Context)
{
   DWORD i, EIP = Context->ContextRecord->Eip;
   BYTE *pEIP = (BYTE *)EIP;
   INSTRUCTION *pInstruction = &CurrentTrap->Disassembler->Instruction;
   BREAKPOINT *Breakpoint;
   CONTEXT *CPU, tmpContext;

   DISABLE_BREAKPOINTS()

   if (TrapThreads[0].Initialized != TRAP_INITIALIZED)
   {
       OriginalTrap = CurrentTrap;
       // This is the first time TrapHandler has been called, initialize
TrapThreads
       memcpy(&TrapThreads[0], CurrentTrap, sizeof(TRAP_CONTEXT));
       CurrentTrap = &TrapThreads[0];
       CurrentTrap->Initialized = TRAP_INITIALIZED;
       CurrentTrap->ID = GetCurrentThreadId();
       CurrentTrap->LastTrapType = CurrentTrap->TrapType = TRAP_CONTINUE;
   }
   else
   {
       CurrentTrap = NULL;
       for (i = 0; TrapThreads[i].Initialized == TRAP_INITIALIZED; i++)
       {
           if (TrapThreads[i].ID == GetCurrentThreadId())
           {
               CurrentTrap = &TrapThreads[i];
               break;
           }
       }
       if (!CurrentTrap)
       {
           if (i == TRAP_MAX_THREADS)
           {
               printf("ERROR: too many threads (%d max)\n",
TRAP_MAX_THREADS);
               fflush(stdout); assert(0);
               goto abort;
           }

           memcpy(&TrapThreads[i], CurrentTrap, sizeof(TRAP_CONTEXT));
           CurrentTrap = &TrapThreads[i];
           CurrentTrap->Initialized = TRAP_INITIALIZED;
           CurrentTrap->ID = GetCurrentThreadId();
           CurrentTrap->LastTrapType = CurrentTrap->TrapType =
TRAP_CONTINUE;
           printf("*** NEW THREAD %d (%d total threads)\n",
CurrentTrap->ID, i+1);
       }
   }

   assert(GetCurrentThreadId() == CurrentTrap->ID);
   assert(CurrentTrap->LastTrapType == TRAP_CONTINUE ||
CurrentTrap->LastTrapType == TRAP_GO);
   CPU = CurrentTrap->CPU = Context->ContextRecord;
   if (CurrentTrap->PendingBreakpoints &&
!TrapReenableBreakpoints(CurrentTrap)) { assert(0); goto abort; }

   // Disable memory breakpoints while in the exception handler
   memset(&tmpContext, 0, sizeof(CONTEXT));
   tmpContext.ContextFlags = CONTEXT_DEBUG_REGISTERS;
   if (GetThreadContext(GetCurrentThread(), &tmpContext))
   {
       DISABLE_BREAKPOINTS_ON_CONTEXT(&tmpContext);
       if (!SetThreadContext(GetCurrentThread(), &tmpContext)) assert(0);
   }
   else
   {
       assert(0); // ignore
   }

   if (IS_BREAKPOINT(Context) && !TrapFindBreakpoint(CurrentTrap, pEIP))
   {
       // This breakpoint occurred naturally in the program
       printf("  *** Hit native code breakpoint at 0x%02lX\n", pEIP);
       CurrentTrap->BreakpointOccurred = TRUE;
       CurrentTrap->PredictedStackChange =
CurrentTrap->PredictedFlagChanges = 0;
       CurrentTrap->IgnoreFlagMask = -1;
       CurrentTrap->PredictedBranch = NULL;
       if (!CurrentTrap->EmulateResumeFlag) RETURN_TRAP_ERROR(CPU)
       pEIP++; CPU->Eip++;
       if (CurrentTrap->LastTrapType == TRAP_CONTINUE)
RETURN_TRAP_CONTINUE(CPU)
       else RETURN_TRAP_GO(CPU)
   }
   else if (IS_TRAP(Context) || IS_BREAKPOINT(Context))
   {
       assert(pEIP == (BYTE *)CPU->Eip);
       Breakpoint = TrapFindBreakpoint(CurrentTrap, pEIP-1);
       if (Breakpoint)
       {
           if (*(pEIP-1) == X86_NOP)
           {
               // This is a temporary breakpoint used to skip instructions
               if (!TrapRemoveBreakpoint(CurrentTrap, Breakpoint)) {
assert(0); goto abort; }
           }
           Breakpoint = NULL;
           assert(!CurrentTrap->BreakpointOccurred);
       }

       if (CPU->Dr6 & 0x0F) // a memory breakpoint occurred
       {
           CurrentTrap->MemoryBreakpointAddress = NULL;
           switch (CPU->Dr6 & 0x0F)
           {
               case (1<<0): CurrentTrap->MemoryBreakpointAddress = (BYTE
*)CPU->Dr0; break;
               case (1<<1): CurrentTrap->MemoryBreakpointAddress = (BYTE
*)CPU->Dr1; break;
               case (1<<2): CurrentTrap->MemoryBreakpointAddress = (BYTE
*)CPU->Dr2; break;
               case (1<<3): CurrentTrap->MemoryBreakpointAddress = (BYTE
*)CPU->Dr3; break;
               default: assert(0); goto abort; // multiple breakpoints
occurred at once?
           }

           assert(CurrentTrap->MemoryBreakpointAddress);
           Breakpoint = TrapFindBreakpoint(CurrentTrap,
CurrentTrap->MemoryBreakpointAddress);
           Breakpoint = NULL;
           if (!Breakpoint)
           {
               printf("*** Hit native memory breakpoint at instruction
before 0x%02lX\n", pEIP);
               assert(0); // this shouldn't happen very often --
anti-debugging trick?
               CurrentTrap->BreakpointOccurred = TRUE;
               CurrentTrap->PredictedStackChange =
CurrentTrap->PredictedFlagChanges = 0;
               CurrentTrap->IgnoreFlagMask = -1;
               CurrentTrap->PredictedBranch = NULL;
               // EFLAGS.RF flag has no effect on memory breakpoints, so
pass it to the program
               if (CurrentTrap->LastTrapType != TRAP_CONTINUE)
RETURN_TRAP_GO(CPU)
               // The current mode is TRAP_CONTINUE, so just continue as if
nothing happened
           }
           else
           {
               TRAP_HANDLE_BREAKPOINT();
               Breakpoint = NULL;
           }
       }

       Breakpoint = TrapFindBreakpoint(CurrentTrap, pEIP);
       if (Breakpoint && !Breakpoint->Disabled)
       {
           // A breakpoint at the current instruction
           assert(Breakpoint->SavedAddress == (BYTE *)CPU->Eip);
           TRAP_HANDLE_BREAKPOINT();
           Breakpoint = NULL;
       }

       if (EIP != (DWORD)CurrentTrap->EndPointer)
       {
           TrapGetFPU(CurrentTrap);
           switch (CurrentTrap->Handler(CurrentTrap, CPU))
           {
               case TRAP_DEBUG:
                   RETURN_TRAP_ERROR(CPU)
                   assert(0);

               case TRAP_STOP:
                   goto stop;

               case TRAP_CONTINUE:
                   CurrentTrap->TotalExecuted++;
                   if (TRAP_IN_RANGE(EIP, *CurrentTrap))
CurrentTrap->TrapExecuted++;
                   RETURN_TRAP_CONTINUE(CPU)
                   assert(0);

               case TRAP_SKIP:
                   assert(pEIP == (BYTE *)EIP);
                   if (pInstruction->Address != pEIP)
                   {
                       pInstruction =
GetInstruction(CurrentTrap->Disassembler, EIP, (BYTE *)EIP, 0);
                       if (!pInstruction) { assert(0); goto abort; }
                   }
                   CurrentTrap->TotalSkipped++;
                   if (TRAP_IN_RANGE(EIP, *CurrentTrap))
CurrentTrap->TrapSkipped++;
                   CPU->Eip += pInstruction->Length - 1;
                   pEIP += pInstruction->Length - 1;
                   if (!TrapAddBreakpoint(CurrentTrap, pEIP, X86_NOP, 1,
TRUE)) { assert(0); goto abort; }
                   RETURN_TRAP_CONTINUE(CPU)
                   assert(0);

               case TRAP_STEP_OVER:
                   pEIP += pInstruction->Length;
                   if (!TrapAddBreakpoint(CurrentTrap, pEIP, X86_BREAK, 1,
TRUE)) { assert(0); goto abort; }
                   RETURN_TRAP_GO(CPU)
                   assert(0);

               case TRAP_STEP_OUT:
                   if (IsBadCodePtr((FARPROC)CurrentTrap->ReturnAddress))
                   {
                       printf("ERROR: invalid return address 0x%02lX\n",
CurrentTrap->ReturnAddress);
                       assert(0); goto abort;
                   }
                   printf("*** Setting break point on return address
0x%02lX\n", CurrentTrap->ReturnAddress);
                   if (!TrapAddBreakpoint(CurrentTrap,
CurrentTrap->ReturnAddress, X86_BREAK, 1, TRUE)) { assert(0); goto abort; }
                   RETURN_TRAP_GO(CPU)
                   assert(0);

               case TRAP_GO:
                   // Run through trap code, but with trapping disable
                   printf("context emuate %d\n",
CurrentTrap->EmulateResumeFlag);
                   RETURN_TRAP_GO(CPU)
                   assert(0);

               default:
                   assert(0);
                   goto abort;
           }
       }
       else
       {
           printf("\nReached last instruction at 0x%02lX\n", EIP);
stop:
           assert(!OriginalTrap->TotalExecuted &&
!OriginalTrap->TotalSkipped);
           for (i = 0; TrapThreads[i].Initialized == TRAP_INITIALIZED; i++)
           {
               OriginalTrap->TotalExecuted += TrapThreads[i].TotalExecuted;
               OriginalTrap->TotalSkipped += TrapThreads[i].TotalSkipped;
               OriginalTrap->TrapExecuted += TrapThreads[i].TrapExecuted;
               OriginalTrap->TrapSkipped += TrapThreads[i].TrapSkipped;
           }
           RETURN_TRAP_STOP(CPU)
       }

       assert(0); // shouldn't be reached
   }

abort:
   DUMP_TRAP_INFO(Context);
   RETURN_TRAP_ERROR(CPU)
}
_______________________________________________
Dailydave mailing list
Dailydave () lists immunitysec com
http://lists.immunitysec.com/mailman/listinfo/dailydave

Current thread: