debugging longman dictionary

Laurent Pinchart laurent.pinchart at skynet.be
Tue Mar 19 15:25:51 CST 2002


I looked at the trace log you attached to your email, and recognised 
(unfortunately) familiar copy protection output :-(

Is anyone working on implementing what would be needed to successfuly run 
copy-protected softwares ?

I ran into the same problems when I tried to play The Longuest Journey with 
Wine. I disassembled a large part of the code and rewrote it in C to try to 
understand what was going on. If anyone is interested I can send my work by 
e-mail (I won't send it to the list as the files are quite big).

Basically, the copy protection scheme I studied used the following technique. 
One of the sections in the PE file is encrypted. The decryption key is 
generated from the content of the other sections. The process of decrypting 
the encrypted section tried to detect if a debugger is running, and fails to 
run properly if so. This results in the inability to decrypt the PE file if 
the unencrypted section is modified or if a debugger is running.

There must be some code to detect if the application CD is genuine but I've 
never been able to go past the decryption part.

To detect if a debugger is running, the following actions are performed (in 
no particular order):

- the code tries to open some files using CreateFileA : "\\.\SICE", 
"\\.\SIWVID" and "\\.\NTICE". This fails as the SoftICE VxDs are not loaded, 
so no problems there

- 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 ?)

- the code writes binary code to the interrupt vector table (at address 0 - 
division by 0 handler), and then cause to the division by 0 interrupt handler 
to be called by dividing a value by 0.

- the TIB (Thread Information Block, which address is located at fs:0) is 
read. The following C code illustrates the technique (which I don't 
understand :-)

bool detect_debugger_from_TIB
{
	char *pTIB;
	asm ( "mov %%fs:0x18, %", "=g"(pTIB) );
	if ( pTIB[0x20] == 0 )
		return FALSE;
	else
		return TRUE;
}

- another debugger detection technique uses int 0x68, functino 0x4300. If the 
content of eax when returning from int 0x68 is not 0x4300, a debugger is 
present. This is not performed on some NEC Japanese systems, which probably 
use int 0x68 for another purpose.

- the last attempt to detect a debugger uses int 0x01 (enter SMM/ICE mode), 
which checks if an external hardware emulator is connected to the processor. 
I haven't been able to understand what the code is supposed to do.

There might be some other anti-debugging techniques, I gave up after 2 weeks 
of disassembly :-)

Hope these observations will help someone.

Laurent Pinchart



More information about the wine-devel mailing list