
Free Information Xchange '98 presents:

Incoming - CD crack by Static Vengeance

Requirements:
Hex Editor and Full Install
W32Dasm if you want to follow along

   NOTE:  I'm using the bundled version of Incoming that came with my CL Voodoo2 card.  The retail
version MAY be slightly different and I don't know if edits listed will work with any other version
of Incoming.  However, the SAME process will work for "all" other versions of Incoming.

	Incoming a great little game the really shows off my Voodoo2 card.  Great graphics and effects
makes for a great game.  However there is a little bug I have run into with Incoming, a bug that must
be FiX'ed before I can fully enjoy the game.  The bug I'm talking about is the CD check (actually it
has multiply CD checks) you run into before you can play a game.  So I loaded up W32Dasm from RUSoft
and disassembled Incoming to remove the CD checks.  When you run the game without the CD present you
get a little Win95 pop up dialog that says "CD not present." and you're dumped back to Win95.  So I
went up to the menu bar and selected "Refs" then selected "String data references" from the drop down
menu.  Once the string refs box came up I grabbed the slider bar and scrolled down to "CD not present"
and double clicked on it.  This put me in middle of this section of code:

:0042675E E84FABFDFF              call 004012B2
:00426763 85C0                    test eax, eax
:00426765 0F8457030000            je 00426AC2
:0042676B 8B0DE01F6700            mov ecx, dword ptr [00671FE0]
:00426771 E893AEFDFF              call 00401609                 <-- Some type of check for the CD?
:00426776 85C0                    test eax, eax                 <-- Test the result returned in eax
:00426778 750D                    jne 00426787                  <-- Take this to jump over the "bad" code

* Possible StringData Ref from Data Obj ->"CD not present."     <-- One thing we don't want to see pop up
                                  |
:0042677A 68544B4800              push 00484B54
:0042677F E896ACFDFF              call 0040141A
:00426784 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00426778(C)
|
:00426787 8B4D10                  mov ecx, dword ptr [ebp+10]   <-- Continue with the game
:0042678A E8A1040000              call 00426C30
:0042678F 85C0                    test eax, eax
:00426791 0F842B030000            je 00426AC2
:00426797 897D98                  mov dword ptr [ebp-68], edi
:0042679A 8B15E01F6700            mov edx, dword ptr [00671FE0]
:004267A0 8BCE                    mov ecx, esi
:004267A2 E8CAAAFDFF              call 00401271

	Having a call, a test and a conditional jump right before it prints the "CD not present." string
means we need to check out the call to 401609.  At 401609 you see it just jumps to 427960.  So let's check
out that section of code and see what it does:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401609(U)
|
:00427960 83EC2C                  sub esp, 0000002C
:00427963 56                      push esi

* Reference To: WINMM.mciSendCommandA, Ord:0032h                <-- This is all I need to see
                                  |
:00427964 8B35A0B9B300            mov esi, dword ptr [00B3B9A0]
:0042796A 57                      push edi
:0042796B 8D442420                lea eax, dword ptr [esp+20]
:0042796F 50                      push eax
:00427970 6802300000              push 00003002
:00427975 890DA04E6700            mov dword ptr [00674EA0], ecx
:0042797B 890D984A6700            mov dword ptr [00674A98], ecx
  --  More code to this routine  --

	You can see Incoming checks for the CD via calls through the Windows Multi-Media (WINMM) DLL.  As
long as there is no special value returned we can overwrite the call 401609 (E8 93 AE FD FF) with
mov eax, 00000001 (B8 01 00 00 00).  This will force the conditional jump to always be taken and prevent
Incoming from checking for the CD through the code at 427960.  So I ran Incoming and it started loading...
loading further but up pops the "CD not present" warning.  So there is another call to the CD check or
a second routine that checks for the CD.  Back to the disassembled listing and backing to looking for more
clues.  Listing through the imported DLL list you see the KERNEL32 calls.  Scrolling down the list you'll
see the GetDriveTypeA call being used.  The most common place I have seen that call used is in CD checks.
Using the "Find Text" function of W32Dasm I searched for GetDriveTypeA and was rewarded with this:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004016D6(U)
|
:0043E220 A19C805400              mov eax, dword ptr [0054809C]       <-- Load some kind of flag value
:0043E225 85C0                    test eax, eax                       <-- Test it
:0043E227 56                      push esi                            <-- If we push it we HAVE to pull it!
:0043E228 0F85AE000000            jne 0043E2DC                        <-- Jump if not zero to a return
:0043E22E 803DB8C548005A          cmp byte ptr [0048C5B8], 5A
:0043E235 C7059C80540001000000    mov dword ptr [0054809C], 00000001  <-- Setting the flag to 00000001
:0043E23F 744F                    je 0043E290                         <-- We'll make use of this jump

* Reference To: KERNEL32.GetDriveTypeA, Ord:00DFh                     <-- Text string that got us here
                                  |
:0043E241 8B3514B8B300            mov esi, dword ptr [00B3B814]

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

* Possible StringData Ref from Data Obj ->"D:\"                      <-- Start with D drive as CD rom
                                  |
:0043E247 68B8C54800              push 0048C5B8
:0043E24C FFD6                    call esi
:0043E24E 83F805                  cmp eax, 00000005                  <-- 05 is the value for CD Rom drives
:0043E251 7520                    jne 0043E273
:0043E253 A0B8C54800              mov al, byte ptr [0048C5B8]

* Possible StringData Ref from Data Obj ->"r"                        <-- Set up for a read
                                  |
:0043E258 6824194900              push 00491924

* Possible StringData Ref from Data Obj ->"D:\rage.ico"              <-- The file on the CD to check for
                                  |
:0043E25D 68C0C54800              push 0048C5C0
:0043E262 A2C0C54800              mov byte ptr [0048C5C0], al
:0043E267 E8D4BD0200              call 0046A040
:0043E26C 83C408                  add esp, 00000008
:0043E26F 85C0                    test eax, eax
:0043E271 7512                    jne 0043E285                       <-- Take this jump for a GOOD CD check

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043E251(C)
|
:0043E273 A0B8C54800              mov al, byte ptr [0048C5B8]
:0043E278 FEC0                    inc al
:0043E27A 3C5A                    cmp al, 5A                        <-- Check up to 5Ah times
:0043E27C A2B8C54800              mov byte ptr [0048C5B8], al
:0043E281 740D                    je 0043E290                       <-- Failed too many times
:0043E283 EBC2                    jmp 0043E247                      <-- Go back up and try again

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043E271(C)
|
:0043E285 50                      push eax                         <-- Getting here is good CD check
:0043E286 E8C5BB0200              call 00469E50
:0043E28B 83C404                  add esp, 00000004
:0043E28E 5E                      pop esi                          <-- We NEED to get here from our jump!!
:0043E28F C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:  <-- Getting here means CD check failed
|:0043E23F(C), :0043E281(C)
|
:0043E290 8B0DF85B4A00            mov ecx, dword ptr [004A5BF8]
:0043E296 51                      push ecx

* Possible StringData Ref from Data Obj ->"%s"
                                  |
:0043E297 6898224800              push 00482298
:0043E29C 6898164A00              push 004A1698

* Reference To: USER32.wsprintfA, Ord:0264h
                                  |
:0043E2A1 FF158CB8B300            Call dword ptr [00B3B88C]
:0043E2A7 83C40C                  add esp, 0000000C
:0043E2AA E8D837FCFF              call 00401A87
:0043E2AF 6A00                    push 00000000

* Possible StringData Ref from Data Obj ->"Incoming Error Report."   <-- Header for No CD present
                                  |
:0043E2B1 68545E4800              push 00485E54
:0043E2B6 6898164A00              push 004A1698
:0043E2BB 6A00                    push 00000000

* Reference To: USER32.MessageBoxA, Ord:0195h
                                  |
:0043E2BD FF15F8B8B300            Call dword ptr [00B3B8F8]
:0043E2C3 8B15E01F6700            mov edx, dword ptr [00671FE0]
:0043E2C9 6A00                    push 00000000
:0043E2CB 68439C0000              push 00009C43
:0043E2D0 6811010000              push 00000111
:0043E2D5 52                      push edx

* Reference To: USER32.SendMessageA, Ord:01DAh
                                  |
:0043E2D6 FF1548B9B300            Call dword ptr [00B3B948]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043E228(C)
|
:0043E2DC 5E                      pop esi
:0043E2DD C3                      ret                               <-- Finally return

	The best way I can see to bypass this routine would be to kill the call to the above section of
code.  I traced back and found jump to jump to jump with no easy way to kill the call to this CD check.
Instead I thought I would use the conditional jump at 43E23F to get us down to where we need to be.
Because the code does a push esi we need to get to the line that does the pop esi.  The conditional jump
I chose actually jumps two (2) bytes beyond the place we want to get to.  Changing this to a standard
jump with the right offset would be a simple crack for this one.  The whole reason I chose the second
conditional jump and not the jne long (0F 85 AE 00 00 00) at 43E228 was the code checks a flag then turns
around and sets the flag.  Why not let the code set the flag for us and then bypass the rest of the code!
You never know when some other part of the game will also check that flag value for 00000001.  Anyways,
to contine there is another exact copy of the above CD check at 43EAC0 and the same type of edit will
bypass it as well.  I installed the different language versions of Incoming and all seem to be using the
same exe file so I only need to give one set of edits for all the different language installs.  The only
thing left to do is to make the actual edits to the file:

Edit incoming.exe
=============================================
Search for: E8 93 AE FD FF  at offset 154,481
Change to : B8 01 00 00 00

   At offset 251,453 -AND- offset 253,661

Search for: 3C 5A 74 4F 8B
Change to : -- -- EB 4D --

For the OEM update 2/Cyrix patch
Edit incoming.exe
=============================================
Search for: E8 D6 0C 00 00  at offset 116,565
Change to : B8 01 00 00 00

Search for: 3C 5A 74 4F 8B  at offset 194,889
Change to : -- -- EB 4C --

Search for: 3C 5A 74 4C     at offset 196,489
Change to : -- -- EB 5B

	It was a little bit more work than the average CD check, but Incoming is now FiX'ed

Static Vengeance
