Free Information Xchange '98 presents: Ultim@te Race Pro - CD crack by Static Vengeance Requirements: Hex editor and full game install W32Dasm if you wish to follow along Ultim@te Race Pro (URP) is a great racing sim that really shows off what one of the new VooDoo2 cards can do. It also supports PowerVR cards in native SGL mode and other 3D cards with Direct3D. Anyways, there is one little problem with the game that needs to be FiX'ed and that is the CD check. When you try to run the game without the CD up pops a standard Win95 dialog box and it tells you to "Insert the Ultim@te Race Pro CD-ROM !!!" Great, no problem we'll just disassemble the game exe with W32Dasm and track down the string. Well, when I tried to disassemble the file W32Dasm came up and started, but the code segment had an offset of 00000000 and a size of 00000000. So no code listed was generated. I ended up with this: Disassembly of File: Ultim@te Race Pro.exe Code Offset = 00000000, Code Size = 00000000 <-- Something is wrong here! Data Offset = 00106A00, Data Size = 00041600 Number of Objects = 0006 (dec), Imagebase = 00400000h Object01: .text RVA: 00001000 Offset: 00000400 Size: 00102400 Flags: C0000020 <-- here is a clue Object02: .rdata RVA: 00104000 Offset: 00102800 Size: 00004200 Flags: 40000040 Object03: .data RVA: 00109000 Offset: 00106A00 Size: 00041600 Flags: C0000040 Object04: .idata RVA: 004EF000 Offset: 00148000 Size: 00001400 Flags: C0000040 Object05: RVA: 004F1000 Offset: 00149400 Size: 00001400 Flags: C0000040 Object06: .rsrc RVA: 004F3000 Offset: 0014A800 Size: 00001800 Flags: 40000040 Hmmmmmmmm... there must be some type of problem in the internal file link. So I started comparing disassembly listings for other programs I had cracked like Powerboat Racing: Disassembly of File: PBoat.exe Code Offset = 00000400, Code Size = 00097800 <-- Everything seems ok here Data Offset = 00097C00, Data Size = 0000DC00 Number of Objects = 0006 (dec), Imagebase = 00400000h Object01: BEGTEXT RVA: 00001000 Offset: 00000400 Size: 00097800 Flags: 60000020 <-- Different values here Object02: DGROUP RVA: 00099000 Offset: 00097C00 Size: 0000DC00 Flags: C0000040 Object03: .bss RVA: 000A7000 Offset: 00000000 Size: 00048800 Flags: C0000080 Object04: .idata RVA: 000F0000 Offset: 000A5800 Size: 00001000 Flags: C0000040 Object05: .reloc RVA: 000F1000 Offset: 000A6800 Size: 00010000 Flags: 42000040 Object06: .rsrc RVA: 00101000 Offset: 000B6800 Size: 00001200 Flags: 40000040 The more comparisons I did the more I noticed that the "Flags" for the code section were usually 60000020 and in URP it was C0000020 and most programs the code had an offset or 400h. So I got HEdit up and running and looked at the first section of the URP file. Then I compared it's structure against other games that I had cracked. Seeing the general pattern, the only real difference seemed to be the Flag value of C0000020. So I renamed the URP exe file and copied another copy to the directory I was working in. Then I editted the renamed copy to change the Flags value to 60000020. At offset 412 I changed the 20 to a 40 and at 415 I changed the C0 to 60. Then I tried to disassmble it again with W32Dasm and it worked! I was rewarded with a disassmbled listing of Ultim@te Race Pro that I could start poking around in. So now it's back to the normal routine of going up to the menu bar and selecting "Refs" and then select "String data references" from the drop down menu. Now, in the pop up reference box scroll down until you see the string "Insert the Ultim@te Race Pro CD-ROM" double click on it and W32Dasm will put you in the middle of the CD checking routine that looks like this: * Referenced by a CALL at Address: |:00493BEF <-- Where it was called from | :00493DE0 81EC00020000 sub esp, 00000200 * Possible StringData Ref from Data Obj ->"CD_NEEDED" | :00493DE6 B964575300 mov ecx, 00535764 :00493DEB E8D0F10000 call 004A2FC0 :00493DF0 85C0 test eax, eax :00493DF2 0F84D0000000 je 00493EC8 :00493DF8 8D8C2400010000 lea ecx, dword ptr [esp+00000100] :00493DFF E88CFDFFFF call 00493B90 :00493E04 8D842400010000 lea eax, dword ptr [esp+00000100] * Possible StringData Ref from Data Obj ->"French" <-- Various languages supported | :00493E0B 6864125200 push 00521264 :00493E10 50 push eax :00493E11 E82A390600 call 004F7740 :00493E16 83C408 add esp, 00000008 :00493E19 85C0 test eax, eax :00493E1B 750A jne 00493E27 * Possible StringData Ref from Data Obj ->"Ins" | :00493E1D 6890585300 push 00535890 :00493E22 E994000000 jmp 00493EBB * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493E1B(C) | :00493E27 8D942400010000 lea edx, dword ptr [esp+00000100] * Possible StringData Ref from Data Obj ->"Spanish" | :00493E2E 6844125200 push 00521244 :00493E33 52 push edx :00493E34 E807390600 call 004F7740 :00493E39 83C408 add esp, 00000008 :00493E3C 85C0 test eax, eax :00493E3E 750C jne 00493E4C :00493E40 8D442400 lea eax, dword ptr [esp] :00493E44 6864585300 push 00535864 :00493E49 50 push eax :00493E4A EB74 jmp 00493EC0 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493E3E(C) | :00493E4C 8D8C2400010000 lea ecx, dword ptr [esp+00000100] * Possible StringData Ref from Data Obj ->"German" | :00493E53 6854125200 push 00521254 :00493E58 51 push ecx :00493E59 E8E2380600 call 004F7740 :00493E5E 83C408 add esp, 00000008 :00493E61 85C0 test eax, eax :00493E63 750C jne 00493E71 :00493E65 8D542400 lea edx, dword ptr [esp] * Possible StringData Ref from Data Obj ->"Legen Sie die Ultim@te Race Pro-CD!!!" <-- Say it in German | :00493E69 683C585300 push 0053583C :00493E6E 52 push edx :00493E6F EB4F jmp 00493EC0 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493E63(C) | :00493E71 8D842400010000 lea eax, dword ptr [esp+00000100] * Possible StringData Ref from Data Obj ->"Italian" | :00493E78 6834585300 push 00535834 :00493E7D 50 push eax :00493E7E E8BD380600 call 004F7740 :00493E83 83C408 add esp, 00000008 :00493E86 85C0 test eax, eax :00493E88 7507 jne 00493E91 * Possible StringData Ref from Data Obj ->"Inserire il CD Ultim@te Race Pro " <-- Say it in Italian ->"!!!" | :00493E8A 680C585300 push 0053580C :00493E8F EB2A jmp 00493EBB * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493E88(C) | :00493E91 8D942400010000 lea edx, dword ptr [esp+00000100] * Possible StringData Ref from Data Obj ->"Portuguese" | :00493E98 6838125200 push 00521238 :00493E9D 52 push edx :00493E9E E89D380600 call 004F7740 :00493EA3 83C408 add esp, 00000008 :00493EA6 85C0 test eax, eax :00493EA8 750C jne 00493EB6 :00493EAA 8D442400 lea eax, dword ptr [esp] * Possible StringData Ref from Data Obj ->"Coloque o CD de Ultim@te Race " <-- Say it in Portuguese?!? ->"Pro !!!" | :00493EAE 68E4575300 push 005357E4 :00493EB3 50 push eax :00493EB4 EB0A jmp 00493EC0 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493EA8(C) | * Possible StringData Ref from Data Obj ->"Insert the Ultim@te Race Pro CD-ROM " <-- The string that got us ->"!!!" <-- here in the first place | :00493EB6 68BC575300 push 005357BC * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00493E22(U), :00493E8F(U) | :00493EBB 8D4C2404 lea ecx, dword ptr [esp+04] :00493EBF 51 push ecx * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00493E4A(U), :00493E6F(U), :00493EB4(U) | :00493EC0 E88BF30500 call 004F3250 :00493EC5 83C408 add esp, 00000008 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493DF2(C) | :00493EC8 A1500D8E00 mov eax, dword ptr [008E0D50] :00493ECD 6835200000 push 00002035 :00493ED2 8D542404 lea edx, dword ptr [esp+04] * Possible StringData Ref from Data Obj ->"Ultim@te Race Pro Message" | :00493ED6 68147A5200 push 00527A14 :00493EDB 52 push edx :00493EDC 50 push eax * Reference To: USER32.MessageBoxA, Ord:0195h | :00493EDD FF15E8F58E00 Call dword ptr [008EF5E8] :00493EE3 83F802 cmp eax, 00000002 <-- 02 means you hit cancel :00493EE6 7507 jne 00493EEF :00493EE8 33C9 xor ecx, ecx :00493EEA E8F14E0300 call 004C8DE0 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493EE6(C) | :00493EEF E81CDE0300 call 004D1D10 :00493EF4 81C400020000 add esp, 00000200 :00493EFA C3 ret Alright now lets back trace the program a little and check out the routine that called the above code to see what it does: * Referenced by a CALL at Addresses: |:00493C65 , :00493CB8 <-- Called twice! | :00493BC0 56 push esi :00493BC1 8BF1 mov esi, ecx * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493BF4(U) | * Possible StringData Ref from Data Obj ->"CDROM:>Ultim@te Race Pro>Ultim@te " ->"Race Pro.exe" | :00493BC3 B960565300 mov ecx, 00535660 :00493BC8 E883790300 call 004CB550 :00493BCD 85C0 test eax, eax :00493BCF 7525 jne 00493BF6 * Possible StringData Ref from Data Obj ->"CDROM2:>Ultim@te Race Pro>Ultim@te " ->"Race Pro.exe" | :00493BD1 B990565300 mov ecx, 00535690 :00493BD6 E875790300 call 004CB550 :00493BDB 85C0 test eax, eax :00493BDD 7517 jne 00493BF6 * Possible StringData Ref from Data Obj ->"CDROM3:>Ultim@te Race Pro>Ultim@te " ->"Race Pro.exe" | :00493BDF B9C0565300 mov ecx, 005356C0 :00493BE4 E867790300 call 004CB550 :00493BE9 85C0 test eax, eax :00493BEB 7509 jne 00493BF6 :00493BED 8BCE mov ecx, esi :00493BEF E8EC010000 call 00493DE0 :00493BF4 EBCD jmp 00493BC3 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00493BCF(C), :00493BDD(C), :00493BEB(C) | :00493BF6 5E pop esi :00493BF7 C3 ret Okay, so this routine seems to use some type of call interpeter, where the CDROM-CDROM3 are for the different types of install options, ie: small, medium and full. So I decided to go back on step more and check out the two routines that called this new code above. -- Program Code -- :00493C55 B964575300 mov ecx, 00535764 :00493C5A E861F30000 call 004A2FC0 :00493C5F 85C0 test eax, eax :00493C61 7407 je 00493C6A <-- This conditional jump will be useful :00493C63 8BCD mov ecx, ebp :00493C65 E856FFFFFF call 00493BC0 <-- Call the CD check routine * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00493C61(C) | :00493C6A 8BFD mov edi, ebp :00493C6C 83C9FF or ecx, FFFFFFFF :00493C6F 33C0 xor eax, eax -- Continuing Program Code -- No secondary flags or results checked after the call to the CD check routine. But wait!, look at the conditional jump (je or Jump Equal) at 493C61. If taken, it'll jump over the CD check and continue the game, which is what we want. So our edit here will be changing the conditional jump to a non conditional jump. Then this CD check is bypassed! Now lets check the second call out: -- Program Code -- :00493CA0 8B442414 mov eax, dword ptr [esp+14] :00493CA4 85C0 test eax, eax :00493CA6 7415 je 00493CBD * Possible StringData Ref from Data Obj ->"CD_NEEDED" | :00493CA8 B964575300 mov ecx, 00535764 :00493CAD E80EF30000 call 004A2FC0 :00493CB2 85C0 test eax, eax :00493CB4 7407 je 00493CBD <-- Again, a useful conditional jump :00493CB6 8BCD mov ecx, ebp :00493CB8 E803FFFFFF call 00493BC0 <-- Second call to the CD check routine * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00493CA6(C), :00493CB4(C) | * Possible StringData Ref from Data Obj ->"CDROM:>Ultim@te Race Pro>" | :00493CBD BFF0565300 mov edi, 005356F0 :00493CC2 83C9FF or ecx, FFFFFFFF :00493CC5 33C0 xor eax, eax -- Continuing Program Code -- Basicly that same as the first call to the CD check and we'll make the same type of edit here as well. I made the edit and ran URP to see the effect, it came right up and I raced around for a bit. So the only thing left to do is apply the actual edit. Make the same edit at BOTH locations: Edit Ultim@te Race Pro at BOTH offsets of 602,209 AND 602,292 ============================== Search for: 85 C0 74 07 8B CD Change to : -- -- EB -- -- -- Edit Ultim@te Race Pro v1.03 beta at BOTH offsets of 607,023 AND 607,105 ============================== Search for: 85 C0 74 07 8B CD Change to : -- -- EB -- -- -- For the Creative Labs Voodoo2 bundled version of Ultim@te Race Pro: Edit Ultim@te Race Pro at BOTH offsets of 602,751 AND 602,834 ============================== Search for: 85 C0 74 07 8B CD Change to : -- -- EB -- -- -- Ultim@te Race Pro is now FiX'ed and can be run completly from your hard drive without the need for the original CD to be in your CD-ROM drive. For future versions, try searching for "85 C0 74 07 8B CD" and change the "74" to "EB", you should find two occurrances close together. That should help you out with other versions that may come out. Static Vengeance