===============================================================================================================
       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
     Cracker : Zaks (tntpcclub@hotmail.com)
       Tools : W32Dasm, Hiew, Softice
  Difficulty : Moderate
Tutorial No. : 7
	Font : Courier New (8)
===============================================================================================================

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		<- Compare returned eax with 5 (for Cd-roms)
:0055D05D 0F8598000000            jne 0055D0FB			<- if eax was not 5 then jump to 0055d0fb
:0055D063 8D956CFFFFFF            lea edx, dword ptr [ebp+FFFFFF6C]
:0055D069 6A40                    push 00000040
:0055D06B 8D45EC                  lea eax, dword ptr [ebp-14]
:0055D06E 52                      push edx
:0055D06F 8D4DF8                  lea ecx, dword ptr [ebp-08]
:0055D072 50                      push eax
:0055D073 51                      push ecx
:0055D074 6A00                    push 00000000
:0055D076 8D55AC                  lea edx, dword ptr [ebp-54]
:0055D079 6A40                    push 00000040
:0055D07B 8D45FC                  lea eax, dword ptr [ebp-04]
:0055D07E 52                      push edx
:0055D07F 50                      push eax
:0055D080 FFD7                    call edi			<- GetVolumeInformationA is called here
:0055D082 85C0                    test eax, eax			<- test for errors in GetVolumeInf...
:0055D084 7411                    je 0055D097			<- if any were detected then jmp to 0055d097
:0055D086 8B55F4                  mov edx, dword ptr [ebp-0C]	
:0055D089 8D4DAC                  lea ecx, dword ptr [ebp-54]	
:0055D08C E88F5AEDFF              call 00432B20		
:0055D091 85C0                    test eax, eax
:0055D093 7479                    je 0055D10E			<- GoodBoy
:0055D095 EB64                    jmp 0055D0FB

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0055D084(C)
|
:0055D097 6A03                    push 00000003			
:0055D099 68ED000000              push 000000ED

* Possible StringData Ref from Data Obj ->"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.

===============================================================================================================

10.04.2000
Written by Zaks