
Free Information Xchange '97 presents:

Virtua Fighter - CD Crack by Static Vengeance

Requirements:
Hex Editor and Full Install


	Ok, once again I set out to remove the CD check from a SEGA Entertainment game using W32Dasm
from URSoft.  Having already cracked two games by Sega (Daytona USA and Virtua Fighter 2) I thought
this game would be striaght forward and fairly easy to do.  However, just when you count on something
being easy, it's not!.. So if you following along I'll show what I found and what I did to remove the
CD check from this game.  Also bear in mind that the program version I'm using is the updated DirectX
v3b version of Virtua Fighter and not the version from the CD, although I have included a simular patch
for that version also.  Let's get going:
	Start up W32Dasm and 'Open file to disassemble' using vfpc.exe from where ever you installed it
to.  Once W32Dasm has finished it's process and is ready, go up to the title bar select 'Refs' and choose
'String data references'.  From here grab the slider bar and scroll down looking at the strings.
Eventually you find "Cannot find Virtua Fighter(TM) ".  So double click on this and it puts you in the
middle of the CD check routine.  So let's take a look at the code:

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00505544(C), :00505558(C)
|
:00505565 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"Virtua Fighter PC"
                                  |
:00505567 68D0CFB000              push 00B0CFD0

* Reference To: USER32.FindWindowA, Ord:00C8h
                                  |
:0050556C FF1598F5BE00            Call dword ptr [00BEF598]
:00505572 8945DC                  mov dword ptr [ebp-24], eax
:00505575 837DDC00                cmp dword ptr [ebp-24], 00000000
:00505579 0F8411000000            je 00505590
:0050557F 8B45DC                  mov eax, dword ptr [ebp-24]
:00505582 50                      push eax

* Reference To: USER32.BringWindowToTop, Ord:000Ah
                                  |
:00505583 FF15A0F5BE00            Call dword ptr [00BEF5A0]
:00505589 33C0                    xor eax, eax
:0050558B E9D2000000              jmp 00505662

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00505579(C)
|
:00505590 E87FCEEFFF              call 00402414         <-- Check for file on CD
:00505595 85C0                    test eax, eax         <-- Did it pass?
:00505597 0F844A000000            je 005055E7           <-- Take this jump for a pass

* Reference To: KERNEL32.GetOEMCP, Ord:00F6h            <-- Otherwise tell EVIL user to insert CD
                                  |
:0050559D FF15BCF4BE00            Call dword ptr [00BEF4BC]
:005055A3 8945B0                  mov dword ptr [ebp-50], eax
:005055A6 817DB0A4030000          cmp dword ptr [ebp-50], 000003A4
:005055AD 0F8519000000            jne 005055CC
:005055B3 6A30                    push 00000030

* Possible StringData Ref from Data Obj ->"Virtua Fighter PC"
                                  |
:005055B5 68D0CFB000              push 00B0CFD0

* Possible StringData Ref from Data Obj ->"Virtua Fighter(TM) PC "
                                  |
:005055BA 6820D0B000              push 00B0D020
:005055BF 6A00                    push 00000000

* Reference To: USER32.MessageBoxA, Ord:0197h
                                  |
:005055C1 FF1538F5BE00            Call dword ptr [00BEF538]
:005055C7 E914000000              jmp 005055E0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005055AD(C)
|
:005055CC 6A30                    push 00000030

* Possible StringData Ref from Data Obj ->"Virtua Fighter PC"
                                  |
:005055CE 68D0CFB000              push 00B0CFD0

* Possible StringData Ref from Data Obj ->"Cannot find Virtua Fighter(TM) "  <-- Seems like something we're
                                        ->"PC CD."                           <-- looking for, right?
                                  |
:005055D3 68CCD0B000              push 00B0D0CC
:005055D8 6A00                    push 00000000

* Reference To: USER32.MessageBoxA, Ord:0197h
                                  |
:005055DA FF1538F5BE00            Call dword ptr [00BEF538]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005055C7(U)
|
:005055E0 33C0                    xor eax, eax
:005055E2 E97B000000              jmp 00505662

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00505597(C)
|
:005055E7 8B4510                  mov eax, dword ptr [ebp+10]
:005055EA 50                      push eax
:005055EB 8B4514                  mov eax, dword ptr [ebp+14]
:005055EE 50                      push eax
:005055EF 8B450C                  mov eax, dword ptr [ebp+0C]
:005055F2 50                      push eax
:005055F3 8B4508                  mov eax, dword ptr [ebp+08]
:005055F6 50                      push eax
:005055F7 E815CCEFFF              call 00402211
:005055FC 83C410                  add esp, 00000010
:005055FF 85C0                    test eax, eax
:00505601 0F8507000000            jne 0050560E
:00505607 33C0                    xor eax, eax
:00505609 E954000000              jmp 00505662

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00505601(C)
|
:0050560E C745E000000000          mov [ebp-20], 00000000
:00505615 8D45E0                  lea eax, dword ptr [ebp-20]
:00505618 50                      push eax
:00505619 68301C4000              push 00401C30

* Reference To: USER32.EnumWindows, Ord:00C3h
                                  |
:0050561E FF15A4F5BE00            Call dword ptr [00BEF5A4]
:00505624 837DE001                cmp dword ptr [ebp-20], 00000001
:00505628 0F8E07000000            jle 00505635
:0050562E 33C0                    xor eax, eax
:00505630 E92D000000              jmp 00505662

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00505628(C)
|
:00505635 A164395400              mov eax, dword ptr [00543964]
:0050563A 50                      push eax
:0050563B 8B4514                  mov eax, dword ptr [ebp+14]
:0050563E 50                      push eax
:0050563F 8B4510                  mov eax, dword ptr [ebp+10]
:00505642 50                      push eax
:00505643 8B450C                  mov eax, dword ptr [ebp+0C]
:00505646 50                      push eax
:00505647 8B4508                  mov eax, dword ptr [ebp+08]
:0050564A 50                      push eax
:0050564B E872CFEFFF              call 004025C2
:00505650 83C414                  add esp, 00000014
:00505653 8945EC                  mov dword ptr [ebp-14], eax
:00505656 E888C7EFFF              call 00401DE3
:0050565B 33C0                    xor eax, eax
:0050565D E900000000              jmp 00505662

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0050553B(U), :00505560(U), :0050558B(U), :005055E2(U), :00505609(U)
|:00505630(U), :0050565D(U)
|
:00505662 5F                      pop edi
:00505663 5E                      pop esi
:00505664 5B                      pop ebx
:00505665 C9                      leave
:00505666 C21000                  ret 0010

	The first conditional branch before it prints "cannot find.." comes from 5055AD by way of
listed reference at 5055CC.. so time to check out 5055AD and surounding code a little closer.  We see
the conditional branch/jump (jne) at 5055AD and a call to the KERNEL32.GetOEMCP... so back up some
more... and you see at 505590 is a call, a test and a condition jump... this looks interesting...
following the code you check out 402414 and will find it jumps to 4ACDF9.  Alright, time to follow
that section of code and try to see what it does:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402414(U)
|
:004ACDF9 55                      push ebp
:004ACDFA 8BEC                    mov ebp, esp
:004ACDFC 81EC54010000            sub esp, 00000154
:004ACE02 53                      push ebx
:004ACE03 56                      push esi
:004ACE04 57                      push edi

* Possible StringData Ref from Data Obj ->"rb"
                                  |
:004ACE05 68C011B400              push 00B411C0

* Possible StringData Ref from Data Obj ->"texture2.bin"              <-- Check CD for this file
                                  |
:004ACE0A 68C411B400              push 00B411C4
:004ACE0F E89250F5FF              call 00401EA6
:004ACE14 83C404                  add esp, 00000004
:004ACE17 50                      push eax
:004ACE18 E823F90700              call 0052C740
:004ACE1D 83C408                  add esp, 00000008
:004ACE20 8945FC                  mov dword ptr [ebp-04], eax
:004ACE23 837DFC00                cmp dword ptr [ebp-04], 00000000
:004ACE27 0F850A000000            jne 004ACE37
:004ACE2D B801000000              mov eax, 00000001
:004ACE32 E9B8000000              jmp 004ACEEF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACE27(C)
|
:004ACE37 8B45FC                  mov eax, dword ptr [ebp-04]
:004ACE3A 50                      push eax
:004ACE3B 6800010000              push 00000100
:004ACE40 6A01                    push 00000001
:004ACE42 8D85ACFEFFFF            lea eax, dword ptr [ebp+FFFFFEAC]
:004ACE48 50                      push eax
:004ACE49 E812F90700              call 0052C760
:004ACE4E 83C410                  add esp, 00000010
:004ACE51 8B45FC                  mov eax, dword ptr [ebp-04]
:004ACE54 50                      push eax
:004ACE55 E826F80700              call 0052C680
:004ACE5A 83C404                  add esp, 00000004

* Possible StringData Ref from Data Obj ->"\vfpc\vfrright.txt"      <-- Path of file on CD to check for
                                  |
:004ACE5D A1BC11B400              mov eax, dword ptr [00B411BC]
:004ACE62 50                      push eax
:004ACE63 0FBE8548FFFFFF          movsx eax, byte ptr [ebp+FFFFFF48]
:004ACE6A 83C040                  add eax, 00000040
:004ACE6D 50                      push eax

* Possible StringData Ref from Data Obj ->"%c:%s"
                                  |
:004ACE6E 68D411B400              push 00B411D4
:004ACE73 8D45AC                  lea eax, dword ptr [ebp-54]
:004ACE76 50                      push eax
:004ACE77 E824FD0700              call 0052CBA0
:004ACE7C 83C410                  add esp, 00000010
:004ACE7F 6A00                    push 00000000
:004ACE81 8D45AC                  lea eax, dword ptr [ebp-54]
:004ACE84 50                      push eax
:004ACE85 E856ED0800              call 0053BBE0
:004ACE8A 83C408                  add esp, 00000008
:004ACE8D 85C0                    test eax, eax                      <-- Here's a test
:004ACE8F 0F850C000000            jne 004ACEA1                       <-- Not equal, look again
:004ACE95 33C0                    xor eax, eax                       <-- Good, make eax = zero
:004ACE97 E953000000              jmp 004ACEEF                       <-- jmp to end of routine
:004ACE9C E94E000000              jmp 004ACEEF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACE8F(C)
|

* Possible StringData Ref from Data Obj ->"\vfpc\vfrright.txt"       <-- File on CD again...
                                  |
:004ACEA1 A1BC11B400              mov eax, dword ptr [00B411BC]
:004ACEA6 50                      push eax
:004ACEA7 0FBE8547FFFFFF          movsx eax, byte ptr [ebp+FFFFFF47]
:004ACEAE 83C040                  add eax, 00000040
:004ACEB1 50                      push eax

* Possible StringData Ref from Data Obj ->"%c:%s"
                                  |
:004ACEB2 68DC11B400              push 00B411DC
:004ACEB7 8D45AC                  lea eax, dword ptr [ebp-54]
:004ACEBA 50                      push eax
:004ACEBB E8E0FC0700              call 0052CBA0
:004ACEC0 83C410                  add esp, 00000010
:004ACEC3 6A00                    push 00000000
:004ACEC5 8D45AC                  lea eax, dword ptr [ebp-54]
:004ACEC8 50                      push eax
:004ACEC9 E812ED0800              call 0053BBE0
:004ACECE 83C408                  add esp, 00000008
:004ACED1 85C0                    test eax, eax			<-- Test again
:004ACED3 0F850C000000            jne 004ACEE5                  <-- not equal, then fail
:004ACED9 33C0                    xor eax, eax			<-- good, set eax to zero
:004ACEDB E90F000000              jmp 004ACEEF                  <-- jmp to end
:004ACEE0 E90A000000              jmp 004ACEEF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACED3(C)
|
:004ACEE5 B801000000              mov eax, 00000001             <-- Force fail value (anything but zero)
:004ACEEA E900000000              jmp 004ACEEF

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004ACE32(U), :004ACE97(U), :004ACE9C(U), :004ACEDB(U), :004ACEE0(U)
|:004ACEEA(U)
|
:004ACEEF 5F                      pop edi
:004ACEF0 5E                      pop esi
:004ACEF1 5B                      pop ebx
:004ACEF2 C9                      leave
:004ACEF3 C3                      ret

	I guess that seems fairly straight forward... now that I had looked into it a bit.  This little
section of code is THE determining factor in the CD check:

:00505590 E87FCEEFFF              call 00402414  <-- Check for \vfpc\vfrright.txt on CD
:00505595 85C0                    test eax, eax  <-- Test the results of the CD check
:00505597 0F844A000000            je 005055E7    <-- eax=zero is good check

	Ok, now we have the code responsible for the CD check, and we see the test and the single
conditional jump for a pass or fail of that check.  The edit comes in the form of replacing the call
with instructions to xor eax,eax (eXcluse OR eax to itself, which zeros out eax and would be the same
as a good CD check) which makes the je (jump on equal (zero)) always true.  Then fill in the remainder
of bytes with NOP's (No OPeration)  The actual edits for the crack depends on the version you have:

CD file version EDIT vfpc.exe (offset 1,058,725)
================================================
Search for: E8 9C F0 EF FF
Change to : 33 C0 90 90 90

dx3b update version EDIT vfpc.exe (offset 1,067,408)
====================================================
Search for: E8 7F CE EF FF
Change to : 33 C0 90 90 90

	Now you can play Virtua Fighter without putting the CD in the CD-ROM drive first, becuase
you have just FiX'ed this game.

Static Vengeance
