On Monday 18 March 2002 22:58, Eric Pouech wrote:
- it also tries to read/write to the debug registers. this produces an
unhandled exception. should be trivial to write an exception handler to support that (right ?)
how does it do the writing exactly ? (I'd suspect more the program wants to catch itself a watchpoint)
Here's the C code I wrote from the disassembler output. It might not be correct, and might not even compile, but the idea is there.
BOOL ReadWriteDR2 (DWORD command, DWORD * value) { struct { WORD limit; DWORD * base; } idtr;
void *int0Handler; DWORD int0handlerHigh; DWORD int0handlerLow;
DWORD valDR2; BOOL writeDR2;
if ( value == 0 ) return FALSE;
if ( command == 0x1010 ) { writeDR2 = FALSE; } else if ( command == 0x1011 ) { writeDR2 = TRUE; valDR2 = *value; } else return FALSE;
idtr = reg.IDTR; int0Handler = idtr.base[4] & 0xffff0000; int0Handler |= idtr.base[0];
int0handlerLow = ((DWORD*)int0Handler)[0]; int0handlerHigh = ((DWORD*)int0Handler)[1];
/* Install the division by 0 handler: pop %eax pop %eax push %cs push %ebx iret */ ((DWORD*)int0Handler)[0] = 0x530e5858; ((DWORD*)int0Handler)[1] = 0x000000cf;
asm ( " movl %%ebx, (%0) " : "=m"(return_label1) ); asm ( " xorl %%eax, %%eax; div %%eax, %%eax " );
return_label1: if ( writeDR2 ) { reg.DR2 = valDR2; } else { valDR2 = reg.dr2; }
idtr = reg.IDTR; int0Handler = idtr.base[4] & 0xffff0000; int0Handler |= idtr.base[0];
/* Install the division by 0 handler: pop %eax pop %eax push %cs push %ebx iret */ ((DWORD*)int0Handler)[0] = 0x53515858; ((DWORD*)int0Handler)[1] = 0x000000cf;
asm ( " xorl %%ecx, %%ecx; movw %%ecx, %%cs " ); asm ( " movl %%ebx, (%0) " : "=m"(return_label2) ); asm ( " xorl %%eax, %%eax; div %%eax, %%eax " );
return_label2: ((DWORD*)int0Handler)[0] = int0handlerLow; ((DWORD*)int0Handler)[1] = int0handlerHigh;
if ( ! writeDR2 ) *value = valDR2;
return TRUE; }
The only call to the ReadWriteDR2 function I found in the disassembler output is a read call, and the DR2 value is compared with 0xffb31146. Hope this helps.
bool detect_debugger_from_TIB { char *pTIB; asm ( "mov %%fs:0x18, %", "=g"(pTIB) ); if ( pTIB[0x20] == 0 ) return FALSE; else return TRUE; }
fs:0x18 points in memory to the TEB structure and offset 0x20 (from thread.h) says: 20 Process id (win95: debug context) so I assume you run it on Win9x, and got it tested this way (I wouldn't be surprised that under nt it did test dword 0x64 and/or 0x68)
You're right, that function is for Win9x. I haven't disassembled the NT function but I can do if needed.
Where can I find some doc about how the fs and gs registers are used ?
Laurent Pinchart