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