Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Hardware Breakpoint EXCEPTION_SINGLE_STEP Issues

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
shad0wfyr3
Newbie cheater
Reputation: 0

Joined: 07 Jan 2008
Posts: 11
Location: /dev/null

PostPosted: Mon Feb 22, 2010 8:51 pm    Post subject: Hardware Breakpoint EXCEPTION_SINGLE_STEP Issues Reply with quote

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:
Code:
eip:004c4256

but instead, it prints out:
Code:
eip:004c425a

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);
    }
}
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25828
Location: The netherlands

PostPosted: Mon Feb 22, 2010 9:14 pm    Post subject: Reply with quote

that's just how it is
Memory access breakpoints show the state of the register AFTER they have been executed.
So disassemble the instruction to find out the size of the previous instruction to find the proper eip

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
shad0wfyr3
Newbie cheater
Reputation: 0

Joined: 07 Jan 2008
Posts: 11
Location: /dev/null

PostPosted: Mon Feb 22, 2010 10:03 pm    Post subject: Reply with quote

thanks Dark Byte. that clears it up for me.

btw, your source code has been central to my understanding of how memory scanners/disassemblers/windows auditing in general works. thanks for making it open source.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites