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

Reply via email to