Unsafedisc
Introduction
I'm actually doing an internship, so it's difficult to work on my personal project.
But today i found some times to finish the first release of my unsafedisc, actually it will work
only with version 1.11.0 because i haven't got enough game with safedisc protection.
But when i will touch my pay, i will have the possibility to buy some old school games :]
Tiny Encryption Algorithm
In my last post about safedisc, i said dplayerx.dll was here for decrypting some sections of the icd file, like .data and .text. I reversed all the stuff from this dll, there is a lot obfuscation inside by using stc, jb, jmp instruction, the only solution i found was to trace the code and reconstruct with my own hand. If you want to check the decrypt routine look at the begining of segment text2 inside dplayerx.dll.
The interesting thing to know is the key that is present in this form :
ABCD - ABCD - ABCD - ABCD
It uses a 128-bit key with the same 32-bit pattern.
So we are able to bruteforce it, but how to know it's the good key ?
At the begining i was thinking about decrypting the 64-bit blocks where oep is, and check if the value equal to push ebp, mov ebp, esp (0x55 0x89 0xe5), but it's not enough, it was a really bad idea.
After switching on my brain, i looked at .data section :
We can easily see the same pattern : 0xA7E6ED0A 0x01E06592, TEA use electronic codebook mode (ECB), if we got in our example two 64-bit block of "0" they will have the same cipher.
With the end of section data, we are able to bruteforce easily the key :].
Monte Carlo algorithm
The last part for breaking safedisc, is reconstruct all the iat. By reading information from woodmann, and my reversed stuff from dplayerx.dll especially this routine :
00D42420 51 PUSH ECX
00D42421 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] ; tea key
00D42425 53 PUSH EBX
00D42426 8B5C24 0C MOV EBX,DWORD PTR SS:[ESP+C] ; Allocated memory
00D4242A 55 PUSH EBP
00D4242B 56 PUSH ESI
00D4242C 8B7424 18 MOV ESI,DWORD PTR SS:[ESP+18] ; Nb max api 0x99 or 0x5c
00D42430 33ED XOR EBP,EBP
00D42432 33C9 XOR ECX,ECX
00D42434 57 PUSH EDI
00D42435 8B38 MOV EDI,DWORD PTR DS:[EAX]
00D42437 3BF5 CMP ESI,EBP
00D42439 896C24 10 MOV DWORD PTR SS:[ESP+10],EBP
00D4243D 76 11 JBE SHORT dplayerx.00D42450
00D4243F 33C0 XOR EAX,EAX
00D42441 41 INC ECX
00D42442 890483 MOV DWORD PTR DS:[EBX+EAX*4],EAX
00D42445 8BC1 MOV EAX,ECX
00D42447 25 FFFF0000 AND EAX,0FFFF
00D4244C 3BC6 CMP EAX,ESI
00D4244E ^ 72 F1 JB SHORT dplayerx.00D42441
00D42450 3BF5 CMP ESI,EBP
00D42452 76 5E JBE SHORT dplayerx.00D424B2
00D42454 69FF 6D5AE835 IMUL EDI,EDI,35E85A6D
00D4245A 33D2 XOR EDX,EDX
00D4245C 81C7 E9621936 ADD EDI,361962E9
00D42462 85F6 TEST ESI,ESI
00D42464 8BC6 MOV EAX,ESI
00D42466 74 05 JE SHORT dplayerx.00D4246D
00D42468 42 INC EDX
00D42469 D1E8 SHR EAX,1
00D4246B ^ 75 FB JNZ SHORT dplayerx.00D42468
00D4246D 81E2 FFFF0000 AND EDX,0FFFF
00D42473 8BC7 MOV EAX,EDI
00D42475 8BCA MOV ECX,EDX
00D42477 D3E8 SHR EAX,CL
00D42479 B9 20000000 MOV ECX,20
00D4247E 2BCA SUB ECX,EDX
00D42480 0FAFC6 IMUL EAX,ESI
00D42483 D3E8 SHR EAX,CL
00D42485 8BCD MOV ECX,EBP
00D42487 81E1 FFFF0000 AND ECX,0FFFF
00D4248D 3BC1 CMP EAX,ECX
00D4248F 74 14 JE SHORT dplayerx.00D424A5
00D42491 8B148B MOV EDX,DWORD PTR DS:[EBX+ECX*4]
00D42494 895424 20 MOV DWORD PTR SS:[ESP+20],EDX
00D42498 8B1483 MOV EDX,DWORD PTR DS:[EBX+EAX*4]
00D4249B 89148B MOV DWORD PTR DS:[EBX+ECX*4],EDX
00D4249E 8B4C24 20 MOV ECX,DWORD PTR SS:[ESP+20]
00D424A2 890C83 MOV DWORD PTR DS:[EBX+EAX*4],ECX
00D424A5 45 INC EBP
00D424A6 8BD5 MOV EDX,EBP
00D424A8 81E2 FFFF0000 AND EDX,0FFFF
00D424AE 3BD6 CMP EDX,ESI
00D424B0 ^ 72 A2 JB SHORT dplayerx.00D42454
00D424B2 5F POP EDI
00D424B3 5E POP ESI
00D424B4 5D POP EBP
00D424B5 5B POP EBX
00D424B6 59 POP ECX
00D424B7 C3 RET
This routine will just build a table of ascending dwords, with a size of nb api, and sort the table into the correct order, using two consts, and morphing the decrypt key with them.
As you can see all the ordinal value of each IMAGE_THUNK_DATA differ, we have to reverse their algorithm for reconstruct well all IMAGE_THUNK_DATA.
Conclusion
That's all for understanding all the suff i coded in masm : my_unsafedisc.rar.