shad0wfyr3 Newbie cheater
Reputation: 0
Joined: 07 Jan 2008 Posts: 11 Location: /dev/null
|
Posted: Mon Feb 22, 2010 8:51 pm Post subject: Hardware Breakpoint EXCEPTION_SINGLE_STEP Issues |
|
|
Hey everyone. I'm writing a debugger and learning how to do single stepping, based on hardware breakpoints. I've been utilizing the code from Dark_byte's Debugger.pas (hxxp://ce.colddot.nl/browser/Cheat%20Engine/Debugger.pas).
It steps through and works great. The only problem is that when it prints out the EIP, it is one instruction too far. It should be printing out:
but instead, it prints out:
which is the address of the first byte of the instruction following the one at 0x004c4256.
Here's cheat engine's runtime disassembly of the relevant area of the binary (apparently, i can't post urls. sorry):
hxxp://img407.imageshack.us/img407/5293/ceforumrelavantcode001.png
And here is my debugger's output at the command line:
hxxp://img51.imageshack.us/img51/9264/ceforumrelavantcode002.png
For context, I'm debugging "halo.exe" and every time I fire a bullet with the pistol, the hardware breakpoint is hit.
Below is the relevant code. If anyone can tell what is causing it to print the address of the instruction after the target instruction, rather than the address of the target instruction, please clue me in. Thanks so much.
| Code: | void Debugger::DebugLoop()
// main debug loop
{
if (!DebugActiveProcess(this->pid))
{
#ifdef DEBUG_UNIQUE
printf("%s cannot be debugged. Error: %d\n","halo.exe",GetLastError());
}
else
{
printf("%s is now being debugged.\n","halo.exe");
#endif
}
DEBUG_EVENT de;
DWORD dwContinueStatus = DBG_CONTINUE;
DWORD tid = GetProcessThreadID(this->pid);
#ifdef DEBUG_UNIQUE
printf("ProcessThreadId: %d\n",tid);
#endif
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,tid);
#ifdef DEBUG_UNIQUE
printf("hThread: 0x%x\n",hThread);
#endif
CONTEXT cx = {0};
DWORD bp1 = 0x400EA5DC; // holds the ammo count (changes very often)
cx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
cx.Dr0 = bp1;
cx.Dr7 = reg0w | reg0len4 | reg0set;
BOOL stc = SetThreadContext(hThread,&cx);
#ifdef DEBUG_UNIQUE
printf("dr0: 0x%.8x\ndr7: 0x%.8x\n",cx.Dr0,cx.Dr7);
#endif
CloseHandle(hThread);
hThread = NULL;
bool justBroke = false;
bool procRunning = true;
while(procRunning == true)
{
WaitForDebugEvent(&de, INFINITE);
switch (de.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch(de.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
break;
case EXCEPTION_BREAKPOINT:
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
break;
case EXCEPTION_SINGLE_STEP:
#ifdef DEBUG_UNIQUE
if(!justBroke)
printf("EXCEPTION_SINGLE_STEP\n");
#endif
hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,de.dwThreadId);
SuspendThread(hThread);
cx.ContextFlags = CONTEXT_FULL|CONTEXT_FLOATING_POINT|CONTEXT_EXTENDED_REGISTERS;
GetThreadContext(hThread,&cx);
if (justBroke)
{
cx.Dr0 = bp1;
justBroke = false;
}
else
{
printf("eax:%.8x ebx:%.8x ecx:%.8x edx:%.8x eip:%.8x ebp:%.8x\n",cx.Eax,cx.Ebx,cx.Ecx,cx.Edx,cx.Eip,cx.Ebp);
printf("dr0:%.8x dr1:%.8x dr2:%.8x dr3:%.8x dr6:%.8x dr7:%.8x\n",cx.Dr0,cx.Dr1,cx.Dr2,cx.Dr3,cx.Dr6,cx.Dr7);
// eip should equal 004C4256, but it equals 004C425A
cx.Dr0 = 0x0;
justBroke = true;
}
cx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
SetThreadContext(hThread,&cx);
if (justBroke)
{
cx.ContextFlags = CONTEXT_FULL;
cx.EFlags = 0x0100;
SetThreadContext(hThread, &cx);
}
ResumeThread(hThread);
break;
case DBG_CONTROL_C:
break;
default:
break;
}
break;
case CREATE_THREAD_DEBUG_EVENT:
dwContinueStatus = this->OnCreateThreadDebugEvent(&de);
break;
case CREATE_PROCESS_DEBUG_EVENT:
dwContinueStatus = this->OnCreateProcessDebugEvent(&de);
break;
case EXIT_THREAD_DEBUG_EVENT:
dwContinueStatus = this->OnExitThreadDebugEvent(&de);
break;
case EXIT_PROCESS_DEBUG_EVENT:
dwContinueStatus = this->OnExitProcessDebugEvent(&de);
procRunning = false;
break;
case LOAD_DLL_DEBUG_EVENT:
dwContinueStatus = this->OnLoadDllDebugEvent(&de);
break;
case UNLOAD_DLL_DEBUG_EVENT:
dwContinueStatus = this->OnUnloadDllDebugEvent(&de);
break;
case OUTPUT_DEBUG_STRING_EVENT:
dwContinueStatus = this->OnOutputDebugStringEvent(&de);
break;
case RIP_EVENT:
dwContinueStatus = this->OnRipEvent(&de);
break;
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
}
} |
|
|