Jump to content
Tuts 4 You

Hardware data/read/execute breakpoints...


Recommended Posts

Hi guys,


I have a short question again.So at the moment I am looking for any code [MultiASM style] or any dll export xy which I could use to set different HWBPs at any address / locations and I found this...





...so if I understand it right then you can set HWBPs + remove set HWBPs with...


SetHardwareBreakpoint(HANDLE hThread,HWBRK_TYPE Type,HWBRK_SIZE Size,void* s) 

RemoveHardwareBreakpoint(HANDLE hBrk)  


....what sounds good so far on the first view but now I have the problem that I can't compile this source code to a dll file which I then could use.So can anybody of you coders create a dll with this source for me or all if the source code of this HWBP exsample is ok etc.


So I hope that this works with the same process which is loaded in Olly...


Main goal is to set HWBPs and to catch them if they get access at the locations where the HWBPs was set without to use Olly itself for this etc you know what I mean right.


So a nice handy dll would be cool so that I then just need to use the 2 exports. :)


Thank you

Link to comment
Share on other sites


What are you trying to do? You could use TitanEngine, but I dont think that works in odbgscript or soemthing.


Link to comment
Share on other sites

I think Lcf need a code to set a Hwbp in Asm

and patch this code to the target with Multiasm


ex: Self debugging

Edited by ragdog
Link to comment
Share on other sites



I had a look at the code u posted, and it seems OK and is straightforward to compile (for me w/mingw).


I understand that u have a target that, for whatever reason, Olly cannot set hardware breakpoints, and u need another way right?


If I hear u right, then the way u posted is possible but has some disadvantages:


1. For this to work u will have to manually inject calls to LoadLibrary/GetProcAddress in the target


2. U will have to hand ASM code calls to both SetHardwareBreakpoint and RemoveBreakpoint, find free space for them, set regs back to previous state upon completion, etc.


3. Using this way it does not look like u can choose an address to break at like u can in Olly. So u will have to find ur target address, find space for all the injected code, inject it, then break, remove it, etc. maybe a code cave will be necssary.


So if this is what u want and we are on the same page - let me know and I can send it to u

Link to comment
Share on other sites

Hi again and thanks for your answers so far. :)


So ragdog said it already right. :) So I need to set HWBPs via some code "Self-debugging" + controlling them too via my code without to use Olly for this.


Also the HWBP thing is only needed for the same process which I debug = load file in Olly and now write the HWBP code in a mem section and with this code I wanna set HWBPs at location xy and the code should also catch them if they will triggered.So I don't wanna use Olly itself for this via OllyScript so this would take very much time if I have to handle tons HWBPs where OllyScript would need hours and a simple ASM code would do this in a few seconds.


@ simple


So if you could just create a compiled ready dll for me or us (just attach it here) then it would be great so I am no real coder and have also no C++ language etc so I can just all write manually.



HWBP set code xy
............ // set HWBP access or write to VA 10079E4
jmp 0100739D // call routine xy HWBP check code xy
0100739D >PUSH 70
0100739F PUSH 1001898
010073A4 CALL 01007568 ; notepad.01007568
010073A9 >XOR EBX,EBX
010073AB PUSH EBX ; /pModule = ""
010073AC MOV EDI,DWORD PTR DS:[10010CC] ; |kernel32.GetModuleHandleA
010073B2 CALL EDI ; \GetModuleHandleA
010073B4 NOP
010073B5 >NOP
010073B6 NOP
010073B7 NOP
010073B8 NOP
010073B9 NOP
010073BA NOP
010073BB NOP
010073BC NOP
010073BD NOP
010073BE NOP
010073BF >NOP ;
010073C0 NOP
010073C1 NOP
010073C2 NOP
010073C3 NOP
010073C4 MOV DWORD PTR DS:[10079E4],0A ; <-- command who write 0A to [10079E4]
010073CE NOP ; <-- latest process stop here now
010073CF NOP ;

So now the HWBP on write at VA 10079E4 will tiggered and at this address or 010073CE has it to stop or catch and come back to my HWBP handling code so that I now can read at the location VA [10079E4] the value of 0A inside and then I just wanna resume the process again.Almost very simple so far right?Its just the same as you would use Ollys HWBPs manually.


The questions now is how to do this so I don't whether the source code I did found and postet can do this too you know.So its not the same as would I just set HWBPs on execution so then I could just use and set int3 exceptions at this VA and handle them via custom set SEH handlers etc.


Now I thought that this source code I found and I did post via links can do this (just the set HWBP at xy and catch HWBP if triggered) and if yes then I could us this source as ready dll for exsample just using the 2 exports of it.


Same as like any API calls as...


push 0

call GetModuleHandle A

= loaded base of main target process xy


Instead to check the whole PEB manually etc.


My code xy set HWBP write at VA xy

run process

Catch HWBP at my VA where I did set HWBP = jump to my HWBP controlling code

Read data which was written to VA xy

Remove HWBP at this location and set other HWBP at VA xy

Resume process



So the way is simple so far.


PS: So if you could compile a dll for or anybody else who can compile a dll with this source then it would be very nice. :) Thank you again.Hurry hurry. ;)



Link to comment
Share on other sites

Thanks flashuser


But where are the 2 exports?





So the dll has no exports.Do you know at which VA they start?Did you compile it?If yes do it again but this time with both exports please.



Link to comment
Share on other sites

Ok thanks again but next time use smaller exports names if possible. :)


Ok now I wrote a little test code and see it does seems to work so far.HEHEHEHE :) Coolio!

Copy hwbrk32.dll to system32 folder if you want to exe the same peace.

<00410000> ;<-- mem section of this code below @DLL:
"\x00\x00\x00\x00" @start:
call @load_dll
call @alloc
mov esi, eax ; edi = section where I set HWBP write
mov dword [@TEST_LOCA], esi
call GetCurrentThread
mov esi, eax
mov dword [@THREAD], eax
push [@TEST_LOCA] ; VA of set HWBP write
push 3 ; HWBRK_SIZE_4
push dword [@THREAD]
call [@SET_API]
push 0
push 0
push 0
mov dword [ecx], -1 ; <--- dword write
pop eax <--- I do stop here.
pop eax
pop eax
nop @alloc:
PUSH 1000
PUSH 20000
CALL VirtualAlloc
push @DLL
call LoadLibraryA
mov dword [@DLL_BASE], eax
mov edi, eax
push @SET_HWBP
push edi
call GetProcAddress
mov dword [@SET_API], eax
push edi
call GetProcAddress
mov dword [@REM_API], eax

So it seems to work on my first little test but I also see that I dont need to use the remove API so it does just work one time after setting the VA.


So if you know more or have again some hints etc then just tell me. :)



Link to comment
Share on other sites

Ok thanks again flashuser for the new file so I check this out.


So now I have test some own written codes to also test this Set API...


SetHardwareBreakpoint(HANDLE hThread,HWBRK_TYPE Type,HWBRK_SIZE Size,void* s)


...so now I found maybe out that this not really work.So if I set the API with HWBP_TYPE_WRITE = push value 1 (see my exsample code in post above) then it works on write and on access too and the other HWBP_TYPE_READWRITE = push 3 instead does not work!?!

if (h->Type == HWBRK_TYPE_CODE)
st = 0;
st = 3;
if (h->Type == HWBRK_TYPE_WRITE)
st = 1;
int le = 0;
if (h->Size == HWBRK_SIZE_1) <-- 1 byte right?
le = 0;
if (h->Size == HWBRK_SIZE_2) <-- 2 bytes word right?
le = 1;
if (h->Size == HWBRK_SIZE_4) <-- 4 bytes DWORD right?
le = 3;
if (h->Size == HWBRK_SIZE_8) <-- ?? Whats this 8 bytes?!?
le = 2;

So I am not sure wether I do made the right parameters or not and I only get this one write parameter working so far.

; Its correct so? push [@TEST_LOCA] ; VA of set HWBP write
push 3 ; HWBRK_SIZE_4
push dword [@THREAD]
call [@SET_API

Maybe anybody of you could check this too also with the other types.


Ok so the next problem I have is: If I wanna use this API to set HWBPs then I need to hook KiUserExceptionDispatcher API and let it jump to my code and there I do check the exception for singlestep (80000004) which does the API set as HWBP.So the questions is how do I handle it correctly if exceptions are triggered from the Set HWBP API and other protection code exceptions.So at the moment I don't use a own exception handler code so if the exceptions was from the set HWBP then I just jump to ZwContinue back....

7C91E47C KiUserExceptionDispatcher MOV ECX,DWORD PTR SS:[ESP+4] <-- jump to my code
7C91E485 CALL 7C93A50E
7C91E48C JE SHORT 7C91E49A
7C91E48E POP EBX <---- Here I let jump back
7C91E490 PUSH 0
7C91E493 CALL 7C91D05E ; ntdll.ZwContinue
7C91E498 JMP SHORT 7C91E4A5
..... mycode:
if exceptions is from set HWBP then jump to ZWC
If not then execute normaly the KiUserExceptionDispatcher

...so the questions is whether this is right and ok so far?So I have test this way with notepad.exe and there is does work without problems but I am not sure whether this method is right or not so etc you know what I mean so maybe you know any better working way for this?Maybe using other exception API + set handlers etc?What is better?So if you have some better ideas then tell me.




Link to comment
Share on other sites

KiUserExceptionDispatcher calls RtlDispatchException to walk all registered SEH handlers. If a handler handles the exception and continues execution, the call to RtlDispatchException never returns. If RtlDispatchException returns, there are two possible paths: either NtContinue is called, which lets the process continue, or another exception is raised which is unrecoverable and leads to process termination.


So what you want to do is handle the exception and jump back so NtContinute can be called.


However I recommend registering a SEH handler to do this instead. Because the way you hook KiUserExceptionDispatcher, you completly bypass all SEH handlers that might be installed, which is dangerous.

Link to comment
Share on other sites



ah ok.So if you mean I should set SEHs then I have also a question about this.So how can I be sure that my set SEH will access FIRST on any exception?Lets say I set a SEH and the later the protection does set also own SEHs which then get listet first in the SEH records.Lets say the protection SEH used also checks for single steps if they was found then it will not return this handle with eax 1 (call next SEH).So you know what I mean right?


So I could only hook KIUED API then jump to my code and install my SEH = first who will called etc.Sounds also not very good or?Other problem I have is a overwrite problem of other handlers in stack so how can I prevent this problem?So where in the stack should I set the new record + to be sure that this stack address will not overwritten by anything etc.Do you have some more tipps?



Link to comment
Share on other sites

You are right. If a SEH handler gets installed after yours which handles the same exception (Single Step) then you have no chance getting it.


Yes you could hook KIUED and install your SEH, so it gets called first, then jump back to KIUED. I would jump back to the very beginning of KIUED, after executing the opcodes you overwrote with your jmp. That way the original behavior of KIUD remains the same.


You are right with the stack. No idea. Have to think about this. I havent done all this myself but am theorizing by best knowledge :P

Link to comment
Share on other sites



yes thats the bad problem. :) I do install a own SEH but it gets kicked out by the protector if its sets own SEHs later so this really sux.Also the stack overwrite thing is a problem where I don't know how to handle this issue at the moment.Ok I will test again to find any better solution but in the meantime you could try to think a little to find any better way maybe and then tell me. :) Thanks again and till later.


EDIT: Ok I could handle it now with my own SEHs. :)

<7C91E47C> ; KIUED Hook
jmp @seh <01CA0000>
cmp dword [ecx], 80000004 ; check for sinple step
jne short @prothandler ; jmp to remove first handler
mov dword [@SET_BIT], 01 ; set to 1 if my handler should handle it ;; here my handle code stuff I like jmp short @prothandler
mov esi, esp
mov esp, esi
cmp dword [@SET_BIT], 01
mov dword [@SET_BIT], 00
jne short @callNexthandler
mov eax,0
mov eax,1
add esp, 8
jmp 7C91E483 ; Back to KI

So with this code I do set my SEH and jump it on and check for exception xy and if the exceptions is any other then Iet return it with eax 1 to call next SEH.Good or. :)


Ok so the problem what I now still have is the HWBP dll so this seems not to work correctly. :( Only the HWBRK_TYPE_WRITE = push 1 does sometimes work or not etc and also on access it works too with push 1 not only for write.So this sux again.Can you check whether the dll does work for you correctly?Maybe I do still something wrong etc.



Link to comment
Share on other sites

I dont know this HWBP lib and dont have a test for it, would have to code one.


But as you are such a "MASM-Freak", why dont you just set HWBPs yourself? You dont need a lib for that.


- GetThreadContext(hThread, Context) //Context is a struct with DWORDs. You need first 4 (DR0 - DR3) = Debug Registers and DR6 and DR7 = control registers

- Set address of HWBP to DR0

- Set 1 to DR7 = enable BP, more flags (size etc can be found here http://www.lowlevel.eu/wiki/Debug_Register

- When breakpoint is hit, you can use DR6 to see why an which of the 4 possible BPs it was


Pseudo Code:

mov ecx, [esp+some_addr]; CONTEXT
push hThread and CONTEXT
call GetThreadContext
mov ecx, [esp+some_addr] ; This is a CONTEXT structure on the stack you pushed to GetThreadContext and got filled by it
mov dword ptr [ecx + 04h], BP_addr; Dr0 (mov 0 as address to clear)
mov dword ptr [ecx + 08h], BP_addr; Dr1
mov dword ptr [ecx + 0ch], BP_addr; Dr2
mov dword ptr [ecx + 10h], BP_addr; Dr3
mov dword ptr [ecx + 18h], 1; Dr7 (1 = enable, 0=disable)
push hThread and CONTEXT struct
call SetThreadContext; use updated CONTEXT struct

Thats all there is to do. Together with your SEH handler, where you can read DR6, this should be all you need


Hope this helps


PS: also TitanEngine has working HWBPs and MASM headers. However you would need to run the target in the TE debugloop. Thats probably not what you want

Edited by cypher
Link to comment
Share on other sites

Hi again,


coolio. :) Yes so this I thought already that this could also be possible just to get and set the context manually but I thought that this would be maybe just to easy.Ok I have test it on that way and it works too on a first test.Hehehe. :)


Ok listen.What about the HWBP types (read / write / code) so which flags I have to set in DR6 or DR7?So your link does not show any info so I see a empty page (login needed so I think).


How to see which HWBP was access in the DR6 & DR7?


DRs after HWBP was read at 010073AB

DR0 010073AB
DR1 00000000
DR2 00000000
DR3 00000000
DR7 00000401

Where can I see which DR0 - DR3 was triggered if I would set more than one HWBP?So on the link which I did postet at the top there I can also see a description about it but I can't calc which position does belong to what in DR6 and DR7 etc you know what I mean.Just need a half byte description like..

DR6 F|F|F|F|0|F|F|1 = DWORD 4 bytes = 8 half bytes / bits
DR7 0|0|0|0|0|4|0|1= DWORD 4 bytes = 8 half bytes / bits Which position is what to read and set
(HWBP access / write / code / sizes etc)

[DR6+01] = xy

[DR6+02] = xy

[DR6+03] = xy

[DR6+04] = xy

[DR6+05] = xy

[DR6+06] = xy

[DR6+07] = xy

[DR6+08] = xy



PS: Not really a "MASM-Freak" so I just like it to have more control and options. :)


Thanks again cypher

Link to comment
Share on other sites

@LCF-AT: here is the correct link: http://www.lowlevel.eu/wiki/Debug_Register

It works with bits:

//modes in bitsenum HWBP_MODE{    MODE_DISABLED=0, //00    MODE_LOCAL=1, //01    MODE_GLOBAL=2 //10};//types in bytesenum HWBP_TYPE{    TYPE_EXECUTE=0, //00    TYPE_WRITE=1, //01    TYPE_READWRITE=3 //11};//sizes in bitsenum HWBP_SIZE{    SIZE_1=0, //00    SIZE_2=1, //01    SIZE_8=2, //10    SIZE_4=3 //11};struct DR7{    BYTE HWBP_MODE[4];    BYTE HWBP_TYPE[4];    BYTE HWBP_SIZE[4];};ULONG_PTR dr7uint(DR7* dr7){    ULONG_PTR ret=0;    //bits 0+1 are MODE1    if(BITGET(dr7->HWBP_MODE[0],0))        BITSET(ret,0);    if(BITGET(dr7->HWBP_MODE[0],1))        BITSET(ret,1);    //bits 2+3 are MODE 2    if(BITGET(dr7->HWBP_MODE[1],0))        BITSET(ret,2);    if(BITGET(dr7->HWBP_MODE[1],1))        BITSET(ret,3);    if(BITGET(dr7->HWBP_MODE[2],0))        BITSET(ret,4);    if(BITGET(dr7->HWBP_MODE[2],1))        BITSET(ret,5);    if(BITGET(dr7->HWBP_MODE[3],0))        BITSET(ret,6);    if(BITGET(dr7->HWBP_MODE[3],1))        BITSET(ret,7);    //bits 16+17 are TYPE 1    if(BITGET(dr7->HWBP_TYPE[0],0))        BITSET(ret,16);    if(BITGET(dr7->HWBP_TYPE[0],1))        BITSET(ret,17);    //bits 18+19 are SIZE 1    if(BITGET(dr7->HWBP_SIZE[0],0))        BITSET(ret,18);    if(BITGET(dr7->HWBP_SIZE[0],1))        BITSET(ret,19);    if(BITGET(dr7->HWBP_TYPE[1],0))        BITSET(ret,20);    if(BITGET(dr7->HWBP_TYPE[1],1))        BITSET(ret,21);    if(BITGET(dr7->HWBP_SIZE[1],0))        BITSET(ret,22);    if(BITGET(dr7->HWBP_SIZE[1],1))        BITSET(ret,23);    if(BITGET(dr7->HWBP_TYPE[2],0))        BITSET(ret,24);    if(BITGET(dr7->HWBP_TYPE[2],1))        BITSET(ret,25);    if(BITGET(dr7->HWBP_SIZE[2],0))        BITSET(ret,26);    if(BITGET(dr7->HWBP_SIZE[2],1))        BITSET(ret,27);    if(BITGET(dr7->HWBP_TYPE[3],0))        BITSET(ret,28);    if(BITGET(dr7->HWBP_TYPE[3],1))        BITSET(ret,29);    if(BITGET(dr7->HWBP_SIZE[3],0))        BITSET(ret,30);    if(BITGET(dr7->HWBP_SIZE[3],1))        BITSET(ret,31);    return ret;}
Notice that the first bit is called 'bit 0' here.


Mr. eXoDia

Link to comment
Share on other sites

Hi eXoDia,


thanks for the link + list but now I have still problems to read them correctly.


Exsample: I did set HWBP access byte on DR0

DR0 010010CC
DR1 00000000
DR2 00000000
DR3 00000000
DR7 00030501

So what is what now?If I check your list then I get confused a little so I think I can only see the Mode = DR7+8 = 1 = MODE_LOCAL or?Where to check the rest?I think I need it in a other easy exsample...

DR0 010010CC
DR1 00000000
DR2 00000000
DR3 00000000
DR7 00030501
DR7 00030501 -----------------------
DR6: F F F F 0 F F 0
DR7 0 0 0 3 0 5 0 1
----------------------- DR6+0 = xy
DR6+1 = xy

...you know what I mean right?



Link to comment
Share on other sites


Here is the example:


DR0, ACCESS, BYTEis:- MODE_LOCAL = 01- TYPE_READWRITE = 11- SIZE_1 = 00S=SIZET=TYPEM=MODEnumber = debug register numberS3 T3 S2 T2 S1 T1 S0 T0 RESERVED M3 M2 M1 M0--------------------------------------------00 00 00 00 00 00 00 11 00000000 00 00 00 01converted to hex (use keygenner assistant):00000000000000110000000000000001gives:0x30001 (=DR7)DR0 = address
Greetings Edited by Mr. eXoDia
Link to comment
Share on other sites

Hi again,


wait wait wait. :)

S3 T3 S2 T2 S1 T1 S0 T0 RESERVED M3 M2 M1 M0
00 00 00 00 00 00 00 11 00000000 00 00 00 01 = DR6 and DR7 from left to right yes?
Here I do stop with a HWBP on execution
EIP 010073B2 notepad.010073B2
DR0 010073B2
DR1 00000000
DR2 00000000
DR3 00000000
DR7 00000401 DR6 and DR7 = S3 T3 S2 T2 S1 T1 S0 T0 RESERVED M3 M2 M1 M0
F F F F 0 F F 0 0000 0 4 0 1 so right now? M2 = 4 = hhmm
M0 = oahhhh!

So I don't get it. :( So can you not use my DRx datas above to show it in a exsample?Just wanna know which single bit is for what etc you know what I mean.So at the moment I just know that the last bit of DR7 = 1 HWBP is enabled and 0 disabled.Sorry for asking again.



Link to comment
Share on other sites

To get which HWBP was triggered, just take DR6 value when a EXCEPTION_SINGLE_STEP has been generated, and examine the lowest 4 bits of DR6 (DR6 AND 0xF will give you the bits of interest):
XXX1 -> HWBP reached because of DR0
XX10 -> HWBP reached because of DR1
X100 -> HWBP reached because of DR2
1000 -> HWBP reached because of DR3I hope this makes sense... :)





Link to comment
Share on other sites

DR6 is completly different to DR7 ! DR7 controls what size, type, mode DR0-3 have. = setting BP. DR6 contains information which of DR0-3 has been hit and why.


mr.exodia already explained it very detailed. And while I'm writing this, nacho_dj also did :)


Your DR6 result of FFFF0FF0  converted to bin 11111111111111110000111111110001 (thx calc.exe) means:


31-16 15   14   13  12  11-4   3   2    1   0


1        BT   BS  BD  0     1      B3 B2 B1 B0

  • B0-B3 shows which register got hit  -> 0001 = DR0
  • BD is set if exception got raised because of accessing debug register -> 0
  • BS is set if exception was raised for single step -> 0
  • BT is set, if the T-Bit was set in TSS during Task-Switch -> 0

and for DR7: It combines all 4 debug register controls. cant explain it better than mr.exodia already did.



Edit:  Correct bitmask to set in DR7 if you want only DR0 address to be readwrite for 1byte = 0x30001, for 2byte = 0x70001, 4byte = 0xF0001

For only DR1 r/w, 1byte = 0x300004,  etc...

Edited by cypher
Link to comment
Share on other sites

Hi & thanks you guys again,


ok so I get this..




So the 1 at the end means DR0 was triggered yes.

DR6: FFFF|4|3|2|1| 1 = DR0 = HWBP first slot
2 = DR1 = HWBP second slot
3 = DR2 = HWBP third slot
4 = DR3 = HWBP forth slot
if 1 into = HWBP slot xy triggered?

Ok so far about this little piece if I did understand it right.The question now is where to enable the HWBP 1,2,3,4?I only see it in DR7 last pin to 1 = enabled DR0 right?Where to enable / disable the rest etc?


So what I need is just a simple exsample without these bin calc stuff etc you know what I mean.I only wanna set HWBPs at all slots HWBP code / readwrite / write + sizes xy etc and then I wanna read the return context at KI API if any HWBP was triggered to see which one it was + enable / disable etc so that all.So maybe I don't need to know anything about this so just to know the HWBP stuff + handle / set them would be already fine so far.



Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...