defeating anti-debug trick inside tpkd.vxd
Joking apart. Guys from Interlok made device driver in order to defeat the winice. The tpkd.vxd is a part of Installshield protection. In this document I will describe only the vxd part of this protection, the rest is on you.
I - sniff around I started the debug session with loading the program. I hit the CTRL+D, typed the BMSG XXX ... then a restart. Wow. Trap for winice. Next I tried filemon and exespy. Worked! I found vl.vxd and tpkd.vxd. Both are dynamically loaded. Tpkd.vxd is loaded via CreateFileA. So I put the breakpoint on the control of the VXD. First of course I did bpx CreateFileA. II - the main problem So we put bpx on control of the tpkd.vxd. Do it carefully! Otherwise you have to reboot. C000693A push eax ;place the bpx before the cli instruction C000693B pusha C000693C cld C000693D pushf C000693E cli C000693F cmp ds:dword_C0002400, 0 To do this propelry put bpx on CreateFileA or DeviceIoControl. After winice informs you that tpkd module is loaded do the vxd command and find the control dispatcher. After winice pops up step little inside the vxd. When I flew trough this piece of code I found something interesting: C0000AAA push ebp C0000AAB mov ebp, esp C0000AAD sub esp, 20h C0000AB0 push ebx C0000AB1 push esi C0000AB2 push edi C0000AB3 mov [ebp+var_C], 88h C0000AB7 push ebx C0000AB8 push dx C0000ABA push ax C0000ABC lea ebx, loc_C0000AD5 C0000AC2 xor byte ptr [ebx], 0BEh ;byte decryptor C0000AC5 jmp short $+2 C0000AC7 mov dx, 38h C0000ACB mov ax, 80h C0000ACF pushfw C0000AD1 cli C0000AD2 shl dx, 1 C0000AD5 C0000AD5 loc_C0000AD5: ; DATA XREF: sub_C0000AAA+12o C0000AD5 push eax ; out 70,80 - disable the NMI signal C0000AD5 ; C0000AD6 xor byte ptr [ebx], 0BEh C0000AD9 lea ebx, loc_C0000AE8 C0000ADF xor byte ptr [ebx], 8Ch ;same as above C0000AE2 jmp short $+2 C0000AE4 jmp short $+2 C0000AE6 inc dx C0000AE8 loc_C0000AE8: ; DATA XREF: sub_C0000AAA+2Fo C0000AE8 pusha ;in ax,71 ; ax=0 C0000AE9 mov ah, al C0000AEB mov al, 0 C0000AED dec dx C0000AEF xor byte ptr [ebx], 8Ch C0000AF2 lea ebx, loc_C0000AFF C0000AF8 xor byte ptr [ebx], 8Fh C0000AFB jmp short $+2 C0000AFD jmp short $+2 C0000AFF C0000AFF loc_C0000AFF: ; DATA XREF: sub_C0000AAA+48o C0000AFF popa ; out 70,00 C0000B00 popfw C0000B02 mov byte ptr [ebp+var_8], ah After this again interesting piece: C0000B3D mov dword ptr [eax], 4245C8Bh ; what's this? C0000B43 mov eax, [ebp+var_20] C0000B46 add eax, 4 C0000B49 mov [ebp+var_20], eax C0000B4C mov eax, [ebp+var_20] C0000B4F mov dword ptr [eax], 66D23366h C0000B55 mov eax, [ebp+var_20] C0000B58 add eax, 4 C0000B5B mov [ebp+var_20], eax C0000B5E mov eax, [ebp+var_20] C0000B61 mov dword ptr [eax], 0E2C16642h C0000B67 mov eax, [ebp+var_20] C0000B6A add eax, 4 C0000B6D mov [ebp+var_20], eax C0000B70 mov [ebp+var_A], 0C3h C0000B74 mov eax, [ebp+var_20] C0000B77 mov dword ptr [eax], 0EC426605h C0000B7D mov eax, [ebp+var_20] C0000B80 add eax, 4 C0000B83 mov [ebp+var_20], eax C0000B86 jmp short $+2 C0000B88 push offset byte_C0001D44 C0000B8D lea eax, [ebp+var_1C] C0000B90 call eax ; call the above placed code C0000B90 ; C0000B92 pop ecx C0000B9A call sub_C000481F C0000B9F mov [ebp+var_4], eax C0000BA2 push offset loc_C0000950 C0000BA7 push 1 C0000BA9 mov ecx, offset byte_C0000130 C0000BAE call sub_C00047A3 C0000BB3 call [ebp+var_4] ; call what? C0000BB6 pop edi C0000BB7 pop esi C0000BB8 pop ebx C0000BB9 leave C0000BBA retn I stepped inside the C0000BB3 call [ebp+var_4]. The tpkd was fiddling the winice code, read my Interrupt descriptor and placed some strange values inside debug registers. This was too much! At third or fourth time you reach the control comes the restart. Then I put the whole problem on the message board. Spath gave me some hints. Thanks Spath! The restart was done trough keyboard controller /*out 64,fe*/. Nice piece of code: C000451E push ebp ; come never back C000451F mov ebp, esp C0004521 push ecx C0004522 push ebx C0004523 push esi C0004524 push edi C0004525 mov [ebp+var_4], ecx C0004528 C0004528 loc_C0004528: ; CODE XREF: sub_C000451E+1Aj C0004528 mov dx, 32h ;dx=32 - hide the value! C000452C shl dx, 1 ;dx*2=64 -the keyb. controller C000452F in al, dx ; AT Keyboard controller 8042. C0004530 jmp short $+2 C0004532 jmp short $+2 C0004534 test al, 2 C0004536 jz short loc_C000453A C0004538 jmp short loc_C0004528 C000453A ; --------------------------------------------------------------------- C000453A C000453A loc_C000453A: ; CODE XREF: sub_C000451E+18j C000453A mov al, 0FEh C000453C out dx, al ; AT Keyboard controller 8042. C000453C ; Resend the last transmission alias reset C000453D C000453D loc_C000453D: ; CODE XREF: sub_C000451E+1Fj C000453D jmp short loc_C000453D I was missing some info so I downloaded the intel's keyboard controller manual. It doesn't matter which one. It should be 8042 compatible. I found the 8XC51SL/LOW VOLTAGE 8XC51SL's datasheet. It says: Power Down mode can only be exited via a reset. This reset may occur either from the RST pin, or an internally generated reset. See the 51SL Hardware Description (Order No. 272268) for a detailed de- scription of this reset. Internal reset. I patched the vxd immediately - location at C000451E to ret. It worked with PAGE fault. Pretty complicated, huh? - Did you find this text? Pretty joke. No, it wasn't the stack problem. When I single stepped the first time routine the proggy worked! So it's the NMI problem. Try to jump over the in and outs in the C0000AAA subroutine. It fails when you reach this: C0000BA9 mov ecx, offset byte_C0000130 C0000BAE call sub_C00047A3 C0000BB3 call [ebp+var_4] ; page fault inside C0000BB6 pop edi C0000BB7 pop esi C0000BB8 pop ebx C0000BB9 leave C0000BBA retn At this point I tried a newbie trick - to change the C0000BB3 location to nops. Man! It works! The tpkd is defeated.
Programmers, don't make jokes. You just give hints to cracker where not to search. The patch is pretty easy, huh? Special thanks to Spath who gave me some useful hints. PS: I think there are still some traps left, so be careful.