Free Information Xchange '98 presents: Last Bronx - CD crack by Static Vengeance Requirements: hex editor and full install Alright, I wrote up another tutorial on CD check cracking. This time the game is Last Bronx, a new fighter game (with weapons) from Sega Entertainment. The game plays well, however it needs a few modifications. First it needs a patch to support the current crop of 3D accelerators. Next, Sega could change some of the Japanese stuff, like the writting on signs and the voice wavs of the fighters to English, that would be nice then I could understand what they're saying at the end of each fight. And the most needed "FiX" is the removal of the CD check. While I cannot reprogram the game or change the wav files to english, I can show you how to FiX the CD check in this program. As with my other tutorials on CD checks I will be using W32Dasm to disassemble and crack this new fighter game. If you want to follow along then load up W32Dasm and disassemble lb.exe from the directory you installed it to. One of the first things you might want to do, is to run the game without the CD. This will tell you how the game asks for the original CD. Or the easier method is going up to the menu bar and select "Refs" and then select "String data references" from the drop down menu (you knew I was going to say that, right?). From there I just look for the string "Insert.." or "Please insert.." or something along those lines. Grabbing the slider bar from the string refs box and scrolling down will, in many cases, lead you to the string used in the CD check. For the Last Bronx you'll find the string "Please insert the LAST BRONX CD." From there double clicking it will put you in the middle of code that does the CD check. That code looks like this: * Referenced by a CALL at Address: |:004ADFA8 <-- Where the call came from | :004AF470 81EC88020000 sub esp, 00000288 :004AF476 8D842488000000 lea eax, dword ptr [esp+00000088] :004AF47D 53 push ebx :004AF47E 55 push ebp :004AF47F 56 push esi :004AF480 57 push edi :004AF481 50 push eax :004AF482 6800010000 push 00000100 * Reference To: KERNEL32.GetLogicalDriveStringsA, Ord:00F8h <-- String that's often used in CD checks | :004AF487 FF157CB04D00 Call dword ptr [004DB07C] :004AF48D 85C0 test eax, eax :004AF48F 7510 jne 004AF4A1 <-- Must take this jump to perform check :004AF491 B801000000 mov eax, 00000001 <-- Or else load eax for a failed check :004AF496 5F pop edi :004AF497 5E pop esi :004AF498 5D pop ebp :004AF499 5B pop ebx :004AF49A 81C488020000 add esp, 00000288 :004AF4A0 C3 ret <-- Return to caller with eax containing result * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF48F(C) | * Reference To: KERNEL32.OpenFile, Ord:01AFh <-- Trying to open specific file on CD | :004AF4A1 8B1DA0B04D00 mov ebx, dword ptr [004DB0A0] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF57F(C) | :004AF4A7 8A842498000000 mov al, byte ptr [esp+00000098] :004AF4AE 8DAC2498000000 lea ebp, dword ptr [esp+00000098] :004AF4B5 84C0 test al, al :004AF4B7 0F84AB000000 je 004AF568 <-- Jump to "Insert ... CD" section * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF562(C) | :004AF4BD 55 push ebp * Reference To: KERNEL32.GetDriveTypeA, Ord:00DFh <-- Common string in CD check routines | :004AF4BE FF1580B04D00 Call dword ptr [004DB080] :004AF4C4 83F805 cmp eax, 00000005 <-- 05 is the CD-ROM value :004AF4C7 0F8581000000 jne 004AF54E <-- If NO CD-ROM then take this jump :004AF4CD 8BFD mov edi, ebp :004AF4CF 83C9FF or ecx, FFFFFFFF :004AF4D2 33C0 xor eax, eax -- CLIP uninformative code (compares, shr's & and's ect) -- :004AF542 C644241C88 mov [esp+1C], 88 :004AF547 FFD3 call ebx :004AF549 83F8FF cmp eax, FFFFFFFF :004AF54C 7547 jne 004AF595 <-- Taking this jump means check passed * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF4C7(C) | :004AF54E 807D0000 cmp byte ptr [ebp+00], 00 :004AF552 7408 je 004AF55C * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF55A(C) | :004AF554 8A4501 mov al, byte ptr [ebp+01] :004AF557 45 inc ebp :004AF558 84C0 test al, al :004AF55A 75F8 jne 004AF554 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF552(C) | :004AF55C 8A4501 mov al, byte ptr [ebp+01] :004AF55F 45 inc ebp :004AF560 84C0 test al, al :004AF562 0F8555FFFFFF jne 004AF4BD <-- Jump up and start check over * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF4B7(C) | :004AF568 6A35 push 00000035 * Possible StringData Ref from Data Obj ->"Last Bronx" | :004AF56A 680874B400 push 00B47408 * Possible StringData Ref from Data Obj ->"Please insert the LAST BRONX CD." <-- The all important string | :004AF56F 68F474B400 push 00B474F4 :004AF574 6A00 push 00000000 * Reference To: USER32.MessageBoxA, Ord:019Bh | :004AF576 FF1534B24D00 Call dword ptr [004DB234] :004AF57C 83F802 cmp eax, 00000002 <-- 00000002 in eax means you hit cancel :004AF57F 0F8522FFFFFF jne 004AF4A7 :004AF585 B801000000 mov eax, 00000001 <-- Check failed, load eax with 00000001 :004AF58A 5F pop edi :004AF58B 5E pop esi :004AF58C 5D pop ebp :004AF58D 5B pop ebx :004AF58E 81C488020000 add esp, 00000288 :004AF594 C3 ret * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004AF54C(C) | :004AF595 8BFD mov edi, ebp <-- If you got this far, then the CD is in :004AF597 83C9FF or ecx, FFFFFFFF <-- your CD-ROM drive when this code was run :004AF59A 33C0 xor eax, eax :004AF59C F2 repnz :004AF59D AE scasb :004AF59E F7D1 not ecx :004AF5A0 2BF9 sub edi, ecx :004AF5A2 8BD1 mov edx, ecx :004AF5A4 8BF7 mov esi, edi :004AF5A6 BF309A6401 mov edi, 01649A30 :004AF5AB C1E902 shr ecx, 02 :004AF5AE F3 repz :004AF5AF A5 movsd :004AF5B0 8BCA mov ecx, edx :004AF5B2 83E103 and ecx, 00000003 :004AF5B5 F3 repz :004AF5B6 A4 movsb :004AF5B7 BF309A6401 mov edi, 01649A30 :004AF5BC 83C9FF or ecx, FFFFFFFF :004AF5BF F2 repnz :004AF5C0 AE scasb :004AF5C1 A1EC74B400 mov eax, dword ptr [00B474EC] :004AF5C6 8A0DF074B400 mov cl, byte ptr [00B474F0] :004AF5CC 4F dec edi :004AF5CD 8907 mov dword ptr [edi], eax :004AF5CF 33C0 xor eax, eax <-- All important instruction that sets :004AF5D1 884F04 mov byte ptr [edi+04], cl <-- eax to zero for a passed CD check :004AF5D4 5F pop edi :004AF5D5 5E pop esi :004AF5D6 5D pop ebp :004AF5D7 5B pop ebx :004AF5D8 81C488020000 add esp, 00000288 :004AF5DE C3 ret That was most of the code that's responsible for checking for the original CD being present on your system. So now lets check out the call to the CD check and the surounding code to see what it does and how we can disable the check: -- Program Code -- :004ADF6B B801000000 mov eax, 00000001 :004ADF70 A3E49C6401 mov dword ptr [01649CE4], eax :004ADF75 A3E89C6401 mov dword ptr [01649CE8], eax :004ADF7A A3E09C6401 mov dword ptr [01649CE0], eax :004ADF7F EB16 jmp 004ADF97 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004ADF66(C) | :004ADF81 892DE49C6401 mov dword ptr [01649CE4], ebp :004ADF87 892DE89C6401 mov dword ptr [01649CE8], ebp :004ADF8D C705E09C640101000000 mov dword ptr [01649CE0], 00000001 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:004ADF69(C), :004ADF7F(U) | :004ADF97 8B4C2460 mov ecx, dword ptr [esp+60] :004ADF9B E880FDFFFF call 004ADD20 :004ADFA0 392D2C74B400 cmp dword ptr [00B4742C], ebp <-- See if we already "know" the CD is there :004ADFA6 740D je 004ADFB5 <-- Take this jump if it's been found once :004ADFA8 E8C3140000 call 004AF470 <-- Else, do the CD check for the first time :004ADFAD 85C0 test eax, eax <-- eax is 00 for passed check :004ADFAF 0F85B5080000 jne 004AE86A <-- On fail eax is 01 and this jump is taken * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004ADFA6(C) | * Reference To: USER32.GetSystemMetrics, Ord:012Ch <-- Jumping or falling through will contiune | <-- With the game, which is what we want! :004ADFB5 8B3508B24D00 mov esi, dword ptr [004DB208] :004ADFBB 55 push ebp :004ADFBC FFD6 call esi :004ADFBE 6A01 push 00000001 :004ADFC0 A348B06401 mov dword ptr [0164B048], eax :004ADFC5 FFD6 call esi :004ADFC7 6A68 push 00000068 :004ADFC9 53 push ebx :004ADFCA A34CB06401 mov dword ptr [0164B04C], eax :004ADFCF 895C2444 mov dword ptr [esp+44], ebx -- The rest of the program code -- After checking this section of code it's quite simple to crack this one. You see the program checks to see if the CD check has already been done (and passed of course). If so, the program jumps over the call to the CD check and starts the game. Otherwise the program falls through to the call to the CD check and makes sure you have the original CD on-line. From here the crack should be straight forward and easy to see. Just change the conditional jump (je 004ADFB5) at 4ADFA6 to a jump (jmp 004ADFB5) so the game will always run. This way the CD check is never run and the game will always start right up. Another or different edit would be to NOP out the call to the CD check routine (at 4ADFA8) and then NOP out the conditional jump (at 4ADFAF) to allow the code to fall through to the continue section of the game. The actual edit to the file would be: EDIT lb.exe at offset 709,542 ================================ Search for: 74 0D E8 C3 14 00 00 Change to : EB -- -- -- -- -- -- That's all that needs to be done to FiX the Last Bronx Static Vengeance