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 


[Win32 C++] How to set a hardware breakpoint?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
toffler
Cheater
Reputation: 0

Joined: 27 Sep 2012
Posts: 35

PostPosted: Fri Jan 19, 2018 5:23 am    Post subject: [Win32 C++] How to set a hardware breakpoint? Reply with quote

I wrote a small debugger that attaches to a process and receives debugger events, the code in general goes like this:

Code:
DebugActiveProcess(pidDbg);

...

while(1)
{
   WaitForDebugEvent(&dbgEv, INFINITE);

   switch(dbgEv.dwDebugEventCode)
   {
      case EXCEPTION_DEBUG_EVENT:
      
         ...

         switch(dbgEv.u.Exception.ExceptionRecord.ExceptionCode)
         {
            case STATUS_ACCESS_VIOLATION:
               ...
               break;
               
            case STATUS_SINGLE_STEP:
            case STATUS_BREAKPOINT:
               
               if(dbgEv.u.Exception.dwFirstChance == 1) {

                  exAddr = dbgEv.u.Exception.ExceptionRecord.ExceptionAddress;

                  if(exAddr == ...) {
                     setBP(...);
                  }
                  else if(exAddr == ...) {
                     clearBP(...);
                  }
                  ...
               }
               break;
   ...

   ContinueDebugEvent(dbgEv.dwProcessId, dbgEv.dwThreadId, dwContinueStatus);
}



I was able to set/clear software breakpoints inside setBP() and clearBP() functions and they work perfectly.

Now I want to add hardware breakpoints. The code I added to setBP() for a test goes like this:

Code:
HANDLE hThread;
WOW64_CONTEXT lcContext;
...
hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, false, thID);
lcContext.ContextFlags = CONTEXT_ALL;
Wow64GetThreadContext(hThread, &lcContext);
lcContext.Dr0 = adr;
lcContext.Dr7 |= 1; // enable DR0 locally
lcContext.Dr7 &= 0xFFF0FFFF; // set bits 16-17 to execution & bits 18-19 to zero.
lcContext.Dr6 = 0; // clear DR6 before returning from the handler
Wow64SetThreadContext(hThread, &lcContext);
CloseHandle(hThread);


The value of adr here is the same I use to set the CC byte for a software breakpoint.

As far as I can see - nothing happens, the debugger loop doesn't receive any single step exceptions (or events) and the process keeps running.

What am I doing wrong here ?

Thank you!
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 347

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

PostPosted: Fri Jan 19, 2018 11:02 am    Post subject: Reply with quote

try Get/SetThreadContext instead of wow64

and a normal Context

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
toffler
Cheater
Reputation: 0

Joined: 27 Sep 2012
Posts: 35

PostPosted: Fri Jan 19, 2018 9:22 pm    Post subject: Reply with quote

I forgot to mention, the debugger is a x64 program, the debugee is x32, hence Wow64.

I use the same functions to clear software breakpoints (for lcContext.Eip--;) and they work, so I don't think the problem is there.

Can it be so that I have enough rights/permissions to set software breakpoints in a program but not hardware breakpoints?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 347

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

PostPosted: Sat Jan 20, 2018 5:10 am    Post subject: Reply with quote

even in a 32-bit process it's easier to use get/setthreadcontext (not wow64)
wow64 is just the secondary layer it jump switches to after exiting from kernelmode or system dll's which are in 64 bit and is the usual context(when a theead gets paused it'll wait in 64 bit mode)

anyhow, you are right, you need to obtain seDebugPrivilege

also, i noticed you're not suspending the tread. that may be needed

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
toffler
Cheater
Reputation: 0

Joined: 27 Sep 2012
Posts: 35

PostPosted: Mon Jan 22, 2018 11:02 am    Post subject: Reply with quote

Ok, I replaced wow64 calls with a get/setthreadcontext, added SuspendThread, successfully obtained seDebugPriviledge for the debugger thread before opening the process using this example https://support.microsoft.com/en-au/help/131065/how-to-obtain-a-handle-to-any-process-with-sedebugprivilege and checked if setthreadcontext returns any errors (it doesn't).

Didn't change a thing. My debugger loop doesn't receive any exceptions from the debugee thread after I set debug registers.

What else I could possibly miss here?

What about the address I put in DR0, is it the same I use for replacing CC byte in SWBP? Is any paging involved here?

Also, I enable HWBR locally and it's said that the CPU will clear debug registers when switching between tasks. How do I make sure it doesn't clean registers before the BP is hit?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 347

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

PostPosted: Mon Jan 22, 2018 1:14 pm    Post subject: Reply with quote

is your debugger process running as admin?


and just call getthreadcontext to verify your breakpoont is still set

oh yes, the context field must be on a 128 byte boundary.

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
toffler
Cheater
Reputation: 0

Joined: 27 Sep 2012
Posts: 35

PostPosted: Wed Jan 24, 2018 8:53 am    Post subject: Reply with quote

I think I found what the problem is: I set a HWBP while suspending a thread_A but the HWBP will be hit by another thread_B that is created later somewhere down the line.

The value of registers DR0-DR3 is preserved across all threads, so if I set it for A it will be there for B.

But the value of DR7 is reset to zero, when I check values at CREATE_THREAD_DEBUG_EVENT my DR0 is fine but DR7 is 0.

How do I preserve DR7 across threads or how do I set HWBP in one thread for another to hit it?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 347

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

PostPosted: Wed Jan 24, 2018 9:20 am    Post subject: Reply with quote

in windows every thread has their own debug registers (on context switch the dr* registers get loaded from the saved threadstate)

you just need to set the breakpoint in every single thread (so watch thread creation)

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
toffler
Cheater
Reputation: 0

Joined: 27 Sep 2012
Posts: 35

PostPosted: Wed Jan 24, 2018 11:24 am    Post subject: Reply with quote

What about an old thread that was created before I need (and know where) to set the HWBP?

If that one happens to be the one to hit the BP how do I set DR7 to it?
Back to top
View user's profile Send private message
OldCheatEngineUser
Whateven rank
Reputation: 8

Joined: 01 Feb 2016
Posts: 865

PostPosted: Wed Jan 24, 2018 11:40 am    Post subject: Reply with quote

just a question off topic, since you are talking about DR:

whats the relation between dr7 and dr0, dr1, dr2, and dr3?
i know a lil bit about them, but i dont understand the relation.

_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
patched cheat engine tutorials
Memory Hacker
Back to top
View user's profile Send private message Visit poster's website
atom0s
Moderator
Reputation: 139

Joined: 25 Jan 2006
Posts: 7351
Location: 127.0.0.1

PostPosted: Wed Jan 24, 2018 3:37 pm    Post subject: Reply with quote

Gives some insight to the debug registers:
https://en.wikipedia.org/wiki/X86_debug_register

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
Dark Byte
Site Admin
Reputation: 347

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

PostPosted: Wed Jan 24, 2018 5:13 pm    Post subject: Reply with quote

toffler:
when you first attach the windows debugger api you will get flooded with create thread notification events, those are the old threads

alternatively, just get a threadlist and open every one of them and apply the debugregs

OldCheatEngineUser: dr7 controls what dr0,1,2 and 3 represent, and contains some extra features like breaking when a debug register is accessed

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Back to top
View user's profile Send private message MSN Messenger
OldCheatEngineUser
Whateven rank
Reputation: 8

Joined: 01 Feb 2016
Posts: 865

PostPosted: Wed Jan 24, 2018 5:20 pm    Post subject: Reply with quote

thanks db, i understood now.
_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
patched cheat engine tutorials
Memory Hacker
Back to top
View user's profile Send private message Visit poster's website
toffler
Cheater
Reputation: 0

Joined: 27 Sep 2012
Posts: 35

PostPosted: Thu Jan 25, 2018 1:08 am    Post subject: Reply with quote

Dark Byte wrote:
toffler:
when you first attach the windows debugger api you will get flooded with create thread notification events, those are the old threads

alternatively, just get a threadlist and open every one of them and apply the debugregs

Thanks, I'll try that


OldCheatEngineUser wrote:
just a question off topic, since you are talking about DR:

whats the relation between dr7 and dr0, dr1, dr2, and dr3?
i know a lil bit about them, but i dont understand the relation.

dr0-dr3 hold up to 4 breakpoint addresses, dr7 enables/disables each of these and specifies if an address is a program command being executed or a data in memory that is being accessed.
Back to top
View user's profile Send private message
OldCheatEngineUser
Whateven rank
Reputation: 8

Joined: 01 Feb 2016
Posts: 865

PostPosted: Thu Jan 25, 2018 9:10 am    Post subject: Reply with quote

so i can say:

dr0 = eax
dr1 = ebx
dr2 = ecx
dr3 = edx
hardware breakpoints

while dr7 control them for whatever uses, looks simple but i know there a lot under the hood.

thanks.

_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
patched cheat engine tutorials
Memory Hacker
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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