Tomb Raider 5
Title : TOMB RAIDER 5 (GAME)
Version : 1.0
Description : 3D ADVENTURE (TOMB RAIDER CLONE)
Protection : CD CHECK
Producer : http://www.eidosinteractive.com
Tools : Softice, W32Dasm, Hiew
Difficulty : Very Easy
1) Install Tomb Raider 5 Chronicles. Copy all data from the cd to your installation directory (mine is d:\games\tomb5). Restart your windows with Softice switched on. Ctrl+d (Softice pops up) and you put a breakpoint on getdrivetypea (bpx getdrivetypea). F5 (back in windows) and you run pctomb5.exe. Softice breaks, you press F12 and you are in the middle of the check routine:
:004A3C33 83F805 cmp eax, 00000005 // was cd rom found?
Make backup of pctomb5.exe (example pctomb5.bak) and disassemble it in W32dasm to take a look at the check routine:
// Part of pctomb5.exe
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402B21(U)
|
:004A3BC0 83EC18 sub esp, 00000018 // Here the check routine begins
:004A3BC3 A1DC655100 mov eax, dword ptr [005165DC]
:004A3BC8 8B0DE0655100 mov ecx, dword ptr [005165E0]
:004A3BCE 8B15E4655100 mov edx, dword ptr [005165E4]
:004A3BD4 53 push ebx
:004A3BD5 8944240C mov dword ptr [esp+0C], eax
:004A3BD9 66A1E8655100 mov ax, word ptr [005165E8]
:004A3BDF 56 push esi
:004A3BE0 57 push edi
:004A3BE1 894C2418 mov dword ptr [esp+18], ecx
:004A3BE5 8954241C mov dword ptr [esp+1C], edx
:004A3BE9 6689442420 mov word ptr [esp+20], ax
* Reference To: KERNEL32.GetLogicalDrives, Ord:0120h
|
:004A3BEE FF156C27EF00 Call dword ptr [00EF276C]
:004A3BF4 8D4C240C lea ecx, dword ptr [esp+0C]
* Possible StringData Ref from Data Obj ->"A:\"
|
:004A3BF8 68D8655100 push 005165D8
:004A3BFD 51 push ecx
:004A3BFE 8BD8 mov ebx, eax
:004A3C00 C605584A870041 mov byte ptr [00874A58], 41 // this address contains the drive letter
* Reference To: KERNEL32.lstrcpyA, Ord:0302h
|
:004A3C07 FF158C27EF00 Call dword ptr [00EF278C]
:004A3C0D 85DB test ebx, ebx
:004A3C0F 7461 je 004A3C72
* Reference To: KERNEL32.GetDriveTypeA, Ord:0104h
|
:004A3C11 8B3D8427EF00 mov edi, dword ptr [00EF2784]
* Reference To: KERNEL32.CreateFileA, Ord:0034h
|
:004A3C17 8B358827EF00 mov esi, dword ptr [00EF2788]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004A3C70(C)
|
:004A3C1D F6C301 test bl, 01
:004A3C20 743E je 004A3C60
:004A3C22 8A15584A8700 mov dl, byte ptr [00874A58]
:004A3C28 8D44240C lea eax, dword ptr [esp+0C]
:004A3C2C 50 push eax
:004A3C2D 88542410 mov byte ptr [esp+10], dl
:004A3C31 FFD7 call edi // getdrivetypea is called
:004A3C33 83F805 cmp eax, 00000005 // was cd rom found?
:004A3C36 7528 jne 004A3C60 // if not jump to test another drive
:004A3C38 8A0D584A8700 mov cl, byte ptr [00874A58]
:004A3C3E 6A00 push 00000000
:004A3C40 6880000000 push 00000080
:004A3C45 6A03 push 00000003
:004A3C47 6A00 push 00000000
:004A3C49 6A00 push 00000000
:004A3C4B 8D542428 lea edx, dword ptr [esp+28]
:004A3C4F 6800000080 push 80000000
:004A3C54 52 push edx
:004A3C55 884C2430 mov byte ptr [esp+30], cl
:004A3C59 FFD6 call esi // createfilea is called here
:004A3C5B 83F8FF cmp eax, FFFFFFFF // compare eax with -1
:004A3C5E 751B jne 004A3C7B // if not jump to goodguy
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004A3C20(C), :004A3C36(C)
|
:004A3C60 8A0D584A8700 mov cl, byte ptr [00874A58]
:004A3C66 FEC1 inc cl
:004A3C68 D1EB shr ebx, 1
:004A3C6A 880D584A8700 mov byte ptr [00874A58], cl
:004A3C70 75AB jne 004A3C1D
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004A3C0F(C)
|
:004A3C72 5F pop edi // Badguy
:004A3C73 5E pop esi
:004A3C74 32C0 xor al, al
:004A3C76 5B pop ebx
:004A3C77 83C418 add esp, 00000018
:004A3C7A C3 ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004A3C5E(C)
|
:004A3C7B 50 push eax // Goodguy
* Reference To: KERNEL32.CloseHandle, Ord:001Bh
|
:004A3C7C FF15C027EF00 Call dword ptr [00EF27C0]
:004A3C82 5F pop edi
:004A3C83 5E pop esi
:004A3C84 B001 mov al, 01 // al becomes 1 (seems very important)
:004A3C86 5B pop ebx
:004A3C87 83C418 add esp, 00000018
:004A3C8A C3 ret
2) As you see this is an usual check routine with just one new element createfilea and without getvolumeinformationa. Now put the cd in, start the game and trace with Softice to see the registers's values at the end of the routine (before ret is executed). When cd in you have al 1, bl 0, cl p. Now do this again with cd out of the drive. When cd is out you have al 0, bl 0, cl g.
3) I tried to disable the protection itself by making cl, dl and byte ptr [00874A58] "." and al 01 (mov cl, 2e then mov dl,cl, mov byte ptr [00874A58], cl then mov al, 1). They have the value of your cd drive and al have to be 1 for a check after ret... It did not work. The game just "performed an illegal operation and had to be closed". So there is something that I had to do at first and not wasting my time. I suggest you try this every time with this kind of protections. Go at the beginning of the check routine :
:004A3BC0 83EC18 sub esp, 00000018
and note the offset. For me it was a3bc0. Open pctomb5.exe with hiew. F4 - decode, F5 - goto a3bc0 (your offset), F3 - edit, F2 - write in ASM and write mov al,1 ENTER ret ENTER, ESC F9 to save. Exit hiew and run the game without the cd.
CHANGE :
:004A3BC0 83EC18 sub esp, 00000018
TO
:004A3BC0 B001 mov al, 01
:004A3BC2 C3 ret