snoopy Posted December 25, 2013 Posted December 25, 2013 Hey guys, I am reading up on ARteam securom information. What I am wondering is the following. Deroko in his post is posting a method to set hardware breakpoints to work his way around with the code splicing. What I am mis understanding is the following code from the goodies dir there is vmtrace.asm. In here he sets Dr0 with the following info: mov [ecx.context_dr0], eax //eax reg hold the address to breakpointmov [ecx.context_dr7], 10101h //should be a breakpoint on write What I am missing here is how did he calculate 10101h. According to the intel manual, there is 31 bits: 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 BITS 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 LE LE RW RW 3 3 2 2 1 1 0 0 DEBUG REGS Based on the above I am doing the following: I set bit 1 to enable global breakpoint for debug register 0 Than I set 0 to the other bits till 10, according to the intel manual bit 10 should be 1. Bits 11 - 15 are set to 0 Bit 16 and 17 describes what type of breakpoint to setAccording to the intel manual:00 break on execution01 break on write //Bit 16 = 0 - Bit 17 = 1?10 break on read/ write11 break on read/ write Than bit 18 and 19 describe the size:According to intel manual:00 1 byte //Bit 18 = 0 - Bit 19 = 0 to tell 1 byte?01 2 bytes10 undefined/ 8 bytes11 4 bytes based on the above my results = 20402h What am I missing here? as my breakpoint isn't triggered either, it only works when setting 10101h and I have no idea why. Could someone explain to me how to work with these. Thanks in advance.
evlncrn8 Posted December 25, 2013 Posted December 25, 2013 sure it isnt 10101h as a b, its bitflags so binary makes more sense here,
snoopy Posted December 26, 2013 Author Posted December 26, 2013 evlncrn8 the result from deroko = 10000000100000001 -> converted to hexadecimal as 10101h My result = 100000010000000010 -> converted to hexadecimal as 20402h. I have no idea why I am not getting the result he is getting.It looks like he is setting lesser bits or I am missing an important thing here.
mrexodia Posted December 26, 2013 Posted December 26, 2013 (edited) Some time ago I wrote a usable hardware breakpoint structure + conversion to uint and vice-versa, so I decided to extend the thing a little.Using this code (c++):#include <stdio.h>#include <windows.h>enum HWBP_MODE{ MODE_DISABLED=0, //00 MODE_LOCAL=1, //01 MODE_GLOBAL=2 //10};enum HWBP_TYPE{ TYPE_EXECUTE=0, //00 TYPE_WRITE=1, //01 TYPE_READWRITE=3 //11};enum 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];};#define BITSET(a,x) (a|=1<<x)#define BITCLEAR(a,x) (a&=~(1<<x))#define BITTOGGLE(a,x) (a^=1<<x)#define BITGET(a,x) (a&(1<<x))ULONG_PTR dr7uint(DR7* dr7){ ULONG_PTR ret=0; if(BITGET(dr7->HWBP_MODE[0],0)) BITSET(ret,0); if(BITGET(dr7->HWBP_MODE[0],1)) BITSET(ret,1); 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); if(BITGET(dr7->HWBP_TYPE[0],0)) BITSET(ret,16); if(BITGET(dr7->HWBP_TYPE[0],1)) BITSET(ret,17); 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;}void uintdr7(ULONG_PTR dr7, DR7* ret){ memset(ret, 0, sizeof(DR7)); if(BITGET(dr7,0)) BITSET(ret->HWBP_MODE[0],0); if(BITGET(dr7,1)) BITSET(ret->HWBP_MODE[0],1); if(BITGET(dr7,2)) BITSET(ret->HWBP_MODE[1],0); if(BITGET(dr7,3)) BITSET(ret->HWBP_MODE[1],1); if(BITGET(dr7,4)) BITSET(ret->HWBP_MODE[2],0); if(BITGET(dr7,5)) BITSET(ret->HWBP_MODE[2],1); if(BITGET(dr7,6)) BITSET(ret->HWBP_MODE[3],0); if(BITGET(dr7,7)) BITSET(ret->HWBP_MODE[3],1); if(BITGET(dr7,16)) BITSET(ret->HWBP_TYPE[0],0); if(BITGET(dr7,17)) BITSET(ret->HWBP_TYPE[0],1); if(BITGET(dr7,18)) BITSET(ret->HWBP_SIZE[0],0); if(BITGET(dr7,19)) BITSET(ret->HWBP_SIZE[0],1); if(BITGET(dr7,20)) BITSET(ret->HWBP_TYPE[1],0); if(BITGET(dr7,21)) BITSET(ret->HWBP_TYPE[1],1); if(BITGET(dr7,22)) BITSET(ret->HWBP_SIZE[1],0); if(BITGET(dr7,23)) BITSET(ret->HWBP_SIZE[1],1); if(BITGET(dr7,24)) BITSET(ret->HWBP_TYPE[2],0); if(BITGET(dr7,25)) BITSET(ret->HWBP_TYPE[2],1); if(BITGET(dr7,26)) BITSET(ret->HWBP_SIZE[2],0); if(BITGET(dr7,27)) BITSET(ret->HWBP_SIZE[2],1); if(BITGET(dr7,28)) BITSET(ret->HWBP_TYPE[3],0); if(BITGET(dr7,29)) BITSET(ret->HWBP_TYPE[3],1); if(BITGET(dr7,30)) BITSET(ret->HWBP_SIZE[3],0); if(BITGET(dr7,31)) BITSET(ret->HWBP_SIZE[3],1);}int main(){ printf("size: %d\n", sizeof(DR7)); DR7 dr7; memset(&dr7, 0, sizeof(DR7)); dr7.HWBP_MODE[0]=MODE_GLOBAL; //enable hardware breakpoint dr7.HWBP_SIZE[0]=SIZE_4; //dword dr7.HWBP_TYPE[0]=TYPE_READWRITE; //readwrite ULONG_PTR dr7_=dr7uint(&dr7); printf("dr7: %X\n", dr7_); DR7 test; uintdr7(dr7_, &test); if(!memcmp(&test, &dr7, sizeof(DR7))) puts("good!"); ULONG_PTR deroko=0x10101; uintdr7(deroko, &test); char* modes[]= {"MODE_DISABLED","MODE_LOCAL","MODE_GLOBAL"}; char* types[]= {"TYPE_EXECUTE","TYPE_WRITE","TYPE_IO","TYPE_READWRITE"}; char* sizes[]= {"SIZE_1","SIZE_2","SIZE_8","SIZE_4"}; for(int i=0; i<4; i++) printf("HWBP%d:%s,%s,%s\n", i+1, modes[test.HWBP_MODE[i]], types[test.HWBP_SIZE[i]], sizes[test.HWBP_TYPE[i]]); memset(&dr7, 0, sizeof(DR7)); dr7.HWBP_MODE[0]=MODE_GLOBAL; //enable hardware breakpoint dr7.HWBP_SIZE[0]=SIZE_8; //dword dr7.HWBP_TYPE[0]=TYPE_READWRITE; //readwrite printf("dr7: %.16llX\n", dr7uint(&dr7)); //11110000000000000010 return 0;}Prints me:HWBP1:MODE_LOCAL,TYPE_EXECUTE,SIZE_2HWBP2:MODE_DISABLED,TYPE_EXECUTE,SIZE_1HWBP3:MODE_DISABLED,TYPE_EXECUTE,SIZE_1HWBP4:MODE_DISABLED,TYPE_EXECUTE,SIZE_1So you're setting a local hardware breakpoint (that's OK), on execute with size 2 (which is ignore iirc)Also notice, that the code you provided:mov [ecx.context_dr0], eax //eax reg hold the address to breakpointmov [ecx.context_dr7], 10101h //should be a breakpoint on writewill NOT work work x64, you should first set dr7 and then dr0 (otherwise dr0 gets reset):mov [ecx.context_dr7], 10101h //should be a breakpoint on writemov [ecx.context_dr0], eax //eax reg hold the address to breakpointSeems like deroko made a small mistake in his paper..EDIT: 0x10001 is the result of, so you should use that:dr7.HWBP_MODE[0]=MODE_LOCAL; //enable hardware breakpointdr7.HWBP_SIZE[0]=SIZE_1; //byte+word+dword(+qword)dr7.HWBP_TYPE[0]=TYPE_WRITE; //write Edited December 26, 2013 by Mr. eXoDia
deepzero Posted December 26, 2013 Posted December 26, 2013 will NOT work work x64, you should first set dr7 and then dr0 (otherwise dr0 gets reset): what do you mean? you're only modifying a struct in memory, as long as you call SetContext() only once, you'll be fine. Also, writing to a dr register does not have any sideeffects on other dr registers, to my knowledge (x86 and x64). merry christmas, btw!
snoopy Posted December 26, 2013 Author Posted December 26, 2013 Mr_Exodia, Thanks for the information.I am trying to do it in ASM, will see what I can make out of this C++ information.Atm the results still don't make sense to me, and all the results are giving me are stack overflows (as the breakpoint is never triggered). So: 10001 = the right result, but I still don't understand how to calculate them manually by setting the bits.
deepzero Posted December 26, 2013 Posted December 26, 2013 10001(hex) would set a data breakpoint on the address in DR0, local, on write for one byte. The breakpoint would not work if * there is no valid address in DR0* the address is only read, not written to as to the why: VAs: DR0,DR1,DR2,DR3Invalid: DR4,Dr5Status: DR6Flags: DR7Bits Meaning0-7 Flags for each of the 4 debug registers (2 for each). The first flag is set to specify a local breakpoint (so the CPU resets the flag when switching tasks), and the second flag is set to specify a global breakpoint. 16-23 2 bits for each register, defining when the breakpoint will be triggered: 00b - Triggers when code is executed 01b - Triggers when data is written 10b - Reserved 11b - Triggers when data is read or written24-31 2 bits for each register, defining the size of the breakpoint: 00b - 1 byte 01b - 2 bytes 10b - 8 bytes 11b - 4 bytes10001hex == 1-0000-0000-0000-0001bin The rightmost flag (position 0) enabes a local breakpoint for DR0.The leftmost flag (position 17) specifies "data written".The 24th bit (not written) is zero and specifies "1 byte size".
mrexodia Posted December 26, 2013 Posted December 26, 2013 (edited) what do you mean? you're only modifying a struct in memory, as long as you call SetContext() only once, you'll be fine. Also, writing to a dr register does not have any sideeffects on other dr registers, to my knowledge (x86 and x64). merry christmas, btw! Merry Christmas to you too! Here is a video to show what I mean, not setting dr7 sort of 'locks' the dr0 register... But you're indeed right about the structure part, in this case it doesn't matter.. x64_dr7.rar Edited December 26, 2013 by Mr. eXoDia
snoopy Posted December 27, 2013 Author Posted December 27, 2013 Thanks for the explanations guys!It's time to finish this little debug engine. Thanks again!
cypher Posted May 6, 2014 Posted May 6, 2014 Stumbled over this old thread, meanwhile there is a tool to easy calculate Debug Register values -> https://bitbucket.org/cypherpunk/drx_calc
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now