Dark Reign 2
Title : Dark Reign 2 (GAME)
Version : 1.0 (should work with any)
Protection : Cd Check
Producer : Do not know a web site. Try : http://www.activision.com
Tools : W32Dasm, Hiew, Softice
Difficulty : Moderate
1) Install the Dark Reign 2. Make typical install (only one available for me). It is around 550MB. Run the game without the cd. All seems ok .. we see intro then comes a menu where we can only choose multiplayer without the original cd. Disassemble the Dr2.bak (backuped copy of Dr2.exe) into W32Dasm. Look for Getdrivetypea. We have 4 places but only one compares eax to 5 (for cd rom search).
* Referenced by a CALL at Address:
|:00494D4F
|
:0055D000 55 push ebp
:0055D001 8BEC mov ebp, esp
:0055D003 81EC94000000 sub esp, 00000094
:0055D009 53 push ebx
:0055D00A 56 push esi
:0055D00B 57 push edi
:0055D00C 894DF4 mov dword ptr [ebp-0C], ecx
* Reference To: KERNEL32.GetLogicalDrives, Ord:0120h
|
:0055D00F FF155C917400 Call dword ptr [0074915C]
:0055D015 85C0 test eax, eax
:0055D017 8945F0 mov dword ptr [ebp-10], eax
:0055D01A 0F84E5000000 je 0055D105
:0055D020 8B0D50D57A00 mov ecx, dword ptr [007AD550]
* Reference To: KERNEL32.GetDriveTypeA, Ord:0104h
|
:0055D026 8B35D4927400 mov esi, dword ptr [007492D4] < - in esi is stored pointer to GetDriveTypeA
* Reference To: KERNEL32.GetVolumeInformationA, Ord:0177h
|
:0055D02C 8B3D60917400 mov edi, dword ptr [00749160] < - in edi is stored pointer to GetVolume....
:0055D032 894DFC mov dword ptr [ebp-04], ecx
:0055D035 33DB xor ebx, ebx < - ebx gets a value of 0
:0055D037 EB03 jmp 0055D03C < - jump to 0055D03C
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D0FF(C)
|
:0055D039 8B45F0 mov eax, dword ptr [ebp-10]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D037(U)
|
:0055D03C BA01000000 mov edx, 00000001 < - edx is now 1
:0055D041 8BCB mov ecx, ebx < - ecx gets value of ebx. Becomes 0
:0055D043 D3E2 shl edx, cl < - dont know
:0055D045 85D0 test eax, edx < - eax is compared with edx (1)
:0055D047 0F84AE000000 je 0055D0FB < - jump if zero flag is set (eax=edx)
:0055D04D 8AC3 mov al, bl < - Interesting. How much is bl? I found 0
:0055D04F 8D4DFC lea ecx, dword ptr [ebp-04]
:0055D052 0441 add al, 41 < - al becomes 0+41 first time. Becomes "A"
:0055D054 51 push ecx
:0055D055 8845FC mov byte ptr [ebp-04], al < - here the letter is stored in *(ebp-04)
:0055D058 FFD6 call esi < - GetDriveTypeA is called here
:0055D05A 83F805 cmp eax, 00000005 "E:\src\code\main\setup.cpp"
|
:0055D09E 68A4D37A00 push 007AD3A4
* Possible StringData Ref from Data Obj ->"Thu Jun 8 18:03:13 2000"
|
:0055D0A3 6884C07A00 push 007AC084
:0055D0A8 B990268000 mov ecx, 00802690
:0055D0AD E8AE27EDFF call 0042F860
:0055D0B2 8D4DFC lea ecx, dword ptr [ebp-04]
:0055D0B5 51 push ecx
* Possible StringData Ref from Data Obj ->"Unable to get volume information " < - this really speaks of itself
- >"for drive [%s]"
|
:0055D0B6 6820D57A00 push 007AD520
:0055D0BB 6890268000 push 00802690
:0055D0C0 E8BB25EDFF call 0042F680
:0055D0C5 83C40C add esp, 0000000C
:0055D0C8 B990268000 mov ecx, 00802690
:0055D0CD 6A03 push 00000003
:0055D0CF 68EE000000 push 000000EE
* Possible StringData Ref from Data Obj ->"E:\src\code\main\setup.cpp"
|
:0055D0D4 68A4D37A00 push 007AD3A4
* Possible StringData Ref from Data Obj ->"Thu Jun 8 18:03:13 2000"
|
:0055D0D9 6884C07A00 push 007AC084
:0055D0DE E87D27EDFF call 0042F860
:0055D0E3 E878FFECFF call 0042D060
:0055D0E8 50 push eax
* Possible StringData Ref from Data Obj ->" - [%s]"
|
:0055D0E9 6818D57A00 push 007AD518
:0055D0EE 6890268000 push 00802690
:0055D0F3 E88825EDFF call 0042F680
:0055D0F8 83C40C add esp, 0000000C
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0055D047(C), :0055D05D(C), :0055D095(U)
|
:0055D0FB 43 inc ebx < - ebx is increased by 1.Becomes 2 at first then 3 ....
:0055D0FC 83FB1A cmp ebx, 0000001A < - was all drives checked ?
:0055D0FF 0F8234FFFFFF jb 0055D039 < - if not go back to check the others (b, c, d, e ....)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D01A(C)
|
:0055D105 5F pop edi < - if all drives were checked and no cd detected then
:0055D106 5E pop esi < - we are here and it is very bad for us
:0055D107 33C0 xor eax, eax
:0055D109 5B pop ebx
:0055D10A 8BE5 mov esp, ebp
:0055D10C 5D pop ebp
:0055D10D C3 ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D093(C)
|
:0055D10E 6A03 push 00000003 < - here we are at GoodBoy
:0055D110 68D0000000 push 000000D0
* Possible StringData Ref from Data Obj ->"E:\src\code\main\setup.cpp"
|
:0055D115 68A4D37A00 push 007AD3A4
* Possible StringData Ref from Data Obj ->"Thu Jun 8 18:03:13 2000"
|
:0055D11A 6884C07A00 push 007AC084
:0055D11F B990268000 mov ecx, 00802690
:0055D124 E83727EDFF call 0042F860
:0055D129 8B45F8 mov eax, dword ptr [ebp-08]
:0055D12C 8D956CFFFFFF lea edx, dword ptr [ebp+FFFFFF6C]
:0055D132 52 push edx
:0055D133 8D4DAC lea ecx, dword ptr [ebp-54]
:0055D136 50 push eax
:0055D137 8D55FC lea edx, dword ptr [ebp-04]
:0055D13A 51 push ecx
:0055D13B 52 push edx
* Possible StringData Ref from Data Obj ->"Found Original CD : [%s] [%s] "
->"[%d] [%s]"
|
:0055D13C 68F0D47A00 push 007AD4F0
:0055D141 6890268000 push 00802690
:0055D146 E83525EDFF call 0042F680
:0055D14B 83C418 add esp, 00000018
:0055D14E 33FF xor edi, edi < - edi is 0
:0055D150 33DB xor ebx, ebx < - ebx is 0
* Possible StringData Ref from Data Obj ->"library\activision\tools.cat"
|
:0055D152 68D0D47A00 push 007AD4D0
* Reference To: KERNEL32.LoadLibraryA, Ord:01C2h
|
:0055D157 FF1544927400 Call dword ptr [00749244]
:0055D15D 8BF0 mov esi, eax
:0055D15F 85F6 test esi, esi
:0055D161 742C je 0055D18F < - No jump here
* Possible StringData Ref from Data Obj ->"tracklen_CheckTrackLengths"
|
:0055D163 68B4D47A00 push 007AD4B4
:0055D168 56 push esi
* Reference To: KERNEL32.GetProcAddress, Ord:013Eh
|
:0055D169 FF1590907400 Call dword ptr [00749090]
:0055D16F 85C0 test eax, eax
:0055D171 7411 je 0055D184 < - Hmm when Cd is in we do not jump here also
* Possible StringData Ref from Data Obj ->"library\activision\tools.dat"
|
:0055D173 6894D47A00 push 007AD494
:0055D178 BF01000000 mov edi, 00000001 < - edi is now 1
:0055D17D FFD0 call eax < - Here is getdrivetypea is called again (I saw it in
:0055D17F 83C404 add esp, 00000004 < - Softice)
:0055D182 8BD8 mov ebx, eax < - what is eax now ? I saw 1 in Softice
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D171(C)
|
:0055D184 56 push esi
* Reference To: KERNEL32.FreeLibrary, Ord:00B4h
|
:0055D185 FF152C927400 Call dword ptr [0074922C]
:0055D18B 85FF test edi, edi
:0055D18D 7520 jne 0055D1AF < - GoodBoy. We have to take this one
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D161(C)
|
:0055D18F 6A05 push 00000005
* Possible StringData Ref from Data Obj ->"Thu Jun 8 18:03:13 2000"
|
:0055D191 6884C07A00 push 007AC084
:0055D196 BAE5000000 mov edx, 000000E5
* Possible StringData Ref from Data Obj ->"E:\src\code\main\setup.cpp"
|
:0055D19B B9A4D37A00 mov ecx, 007AD3A4
:0055D1A0 E8BB13EDFF call 0042E560
* Possible StringData Ref from Data Obj ->"A required file was not found: "
->"tools.cat"
|
:0055D1A5 6868D47A00 push 007AD468
:0055D1AA E8E113EDFF call 0042E590
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D18D(C)
|
:0055D1AF 5F pop edi < - at last we are at the end of the check routine
:0055D1B0 8BC3 mov eax, ebx
:0055D1B2 5E pop esi
:0055D1B3 5B pop ebx
:0055D1B4 8BE5 mov esp, ebp
:0055D1B6 5D pop ebp
:0055D1B7 C3 ret < - here in Softice we take all values that interest us
< - we take value of eax (? eax = 1), al (? al = 1) and also < - note that edi and esi are 0 (maybe not esential but eax
< - and al are)
:0055D1B8 90 nop
:0055D1B9 90 nop
:0055D1BA 90 nop
:0055D1BB 90 nop
:0055D1BC 90 nop
:0055D1BD 90 nop
:0055D1BE 90 nop
:0055D1BF 90 nop
2) Well we know the best way to crack this is to return to 00494D4F (CALL) and to nope it then to force the conditional jump always to be taken or nope it too. Do not waste your time because this does not work here. What does this mean? This means that there are important values that must be returned from this call. Well here comes Softice. Cover Softice with Frogice (Dark Reign 2 detects debugers) and bpx getdrivetypea. Place your Dark Reign 2 Cd into the Cd rom and run dr2.exe and Softice breaks. We see we are not at the right place so F5 and Softice breaks again and we see we are at the check routine above so we trace with F10. We have to do a very long trace through the whole routine and in the last line
:0055D1B7 C3 ret
we take all values that interest us. We ? eax which gives us 1, ? al gives us 1 too,? ebx (undefined) ? edi and ? esi (they are 0). This seems enough. So we are ready to do patching. Take the offset number for the first line of the check routine.
:0055D000 55 push ebp
Here we will do our patching, for me the offset was 15d000. Open dr2.exe with Hiew. F4- Decode, F5- Go to 15d000, F3- Edit, F2- Asm and write down (ENTER means press Enter key) :
mov eax,1 ENTER mov al,1 ENTER mov [ebp-04],al ENTER ret ENTER. F9 to update Esc to exit. Run the game and we can play singleplayer without cd. So what have we done. We forced the called procedure to return eax 1, al 1 and [ebp-04] 1, and not to make any checks at all. Well another game that can not be just noped.