
Free Information Xchange '98 presents:

Addiction Pinball - CD crack by Static Vengeance

Requirements:
Hex editor and full game install
W32Dasm if you wish to follow along

	I have another tutorial to pass along to you.  Like all my past tutorials I will be showing
you how to hunt down and defeat a CD check.  Also I'll be using my favorite programs for cracking,
those being W32Dasm from URSoft and HEdit from Yuri Software.  With that said, let's get to FiX'ing
what needs to be FiX'ed:
	This time the game I'll be working with is Addiction Pinball (AP) from MicroProse (Team17).
This is a Win95 based game so it should be somewhat easy to crack.  First thing to do, is to install
the game and run it without the CD to see how it asks for it.  AP comes up with a simple pop-up dialog
box asking for the original CD.  No problem, we'll start up W32Dasm and look for that data reference.
Once you have disassembled pinball.exe you'll see there is no direct reference to the "Insert CD..."
string.  Well, next in line for things to try is to look for the KERNEL32 call "GetDriveTypeA"  Using
the text string search function of W32Dasm I came across this little bit of code:

* Referenced by a CALL at Addresses:
|:00401A8E   , :004033BC   , :00403BD5                        ; Called from three different locations
|
:0043E8F0 83EC44                  sub esp, 00000044
:0043E8F3 53                      push ebx
:0043E8F4 56                      push esi
:0043E8F5 57                      push edi
:0043E8F6 55                      push ebp
:0043E8F7 BB02000000              mov ebx, 00000002           ; We'll use this instruction later

* Reference To: KERNEL32.GetLogicalDrives, Ord:00F9h          ; Commonly used in CD check routines
                                  |
:0043E8FC FF156C934700            Call dword ptr [0047936C]
:0043E902 8BF8                    mov edi, eax
:0043E904 8B74245C                mov esi, dword ptr [esp+5C]
:0043E908 C64424113A              mov [esp+11], 3A
:0043E90D C64424125C              mov [esp+12], 5C
:0043E912 C644241300              mov [esp+13], 00

* Reference To: KERNEL32.GetVolumeInformationA, Ord:014Eh     ; Check for the volume name of the CD
                                  |
:0043E917 8B2D64934700            mov ebp, dword ptr [00479364]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043E96F(C)
|
:0043E91D B801000000              mov eax, 00000001
:0043E922 8ACB                    mov cl, bl
:0043E924 D3E0                    shl eax, cl
:0043E926 85C7                    test edi, eax
:0043E928 7441                    je 0043E96B
:0043E92A 8D4361                  lea eax, dword ptr [ebx+61]
:0043E92D 88442410                mov byte ptr [esp+10], al
:0043E931 8D442410                lea eax, dword ptr [esp+10]
:0043E935 50                      push eax

* Reference To: KERNEL32.GetDriveTypeA, Ord:00DEh               ; What lead us here
                                  |
:0043E936 FF1568934700            Call dword ptr [00479368]
:0043E93C 83F805                  cmp eax, 00000005             ; 05 is the code value for a CD ROM drive
:0043E93F 752A                    jne 0043E96B                  ; If NOT a CD the exit to the fail code
:0043E941 8D442414                lea eax, dword ptr [esp+14]
:0043E945 6A00                    push 00000000
:0043E947 8D4C2414                lea ecx, dword ptr [esp+14]
:0043E94B 6A00                    push 00000000
:0043E94D 6A00                    push 00000000
:0043E94F 6A00                    push 00000000
:0043E951 6A00                    push 00000000
:0043E953 6A40                    push 00000040
:0043E955 50                      push eax
:0043E956 51                      push ecx
:0043E957 FFD5                    call ebp
:0043E959 8D4C2414                lea ecx, dword ptr [esp+14]
:0043E95D 56                      push esi
:0043E95E 51                      push ecx
:0043E95F E8FCDD0100              call 0045C760
:0043E964 83C408                  add esp, 00000008
:0043E967 85C0                    test eax, eax
:0043E969 7412                    je 0043E97D             ; Take this jump to contiune with the CD check

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0043E928(C), :0043E93F(C)
|
:0043E96B 43                      inc ebx                 ; Counter for the CD check loop
:0043E96C 83FB20                  cmp ebx, 00000020       ; Try upto 32 times
:0043E96F 7CAC                    jl 0043E91D
:0043E971 33C0                    xor eax, eax            ; A zero in EAX means the CD check failed
:0043E973 5D                      pop ebp
:0043E974 5F                      pop edi
:0043E975 5E                      pop esi
:0043E976 5B                      pop ebx
:0043E977 83C444                  add esp, 00000044
:0043E97A C20800                  ret 0008                ; Return to the caller

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043E969(C)
|
:0043E97D 8B542458                mov edx, dword ptr [esp+58]
:0043E981 85D2                    test edx, edx
:0043E983 7423                    je 0043E9A8
:0043E985 8D7C2410                lea edi, dword ptr [esp+10]
:0043E989 B9FFFFFFFF              mov ecx, FFFFFFFF
:0043E98E 2BC0                    sub eax, eax
:0043E990 F2                      repnz
:0043E991 AE                      scasb
:0043E992 F7D1                    not ecx
:0043E994 2BF9                    sub edi, ecx
:0043E996 8BC1                    mov eax, ecx
:0043E998 C1E902                  shr ecx, 02
:0043E99B 8BF7                    mov esi, edi
:0043E99D 8BFA                    mov edi, edx
:0043E99F F3                      repz
:0043E9A0 A5                      movsd
:0043E9A1 8BC8                    mov ecx, eax
:0043E9A3 83E103                  and ecx, 00000003
:0043E9A6 F3                      repz
:0043E9A7 A4                      movsb

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043E983(C)
|                                                          ; Ultimately where we want to get!
:0043E9A8 B801000000              mov eax, 00000001        ; Set up for passed CD check
:0043E9AD 5D                      pop ebp
:0043E9AE 5F                      pop edi
:0043E9AF 5E                      pop esi
:0043E9B0 5B                      pop ebx
:0043E9B1 83C444                  add esp, 00000044
:0043E9B4 C20800                  ret 0008                 ; Return to the caller

	Alright, with that section of the CD check code explained you can see we need to get down to
43E9A8 for the code to return the right value in EAX for a passed CD check.  The other option would
be to back trace the calling function and eliminate the calls to the CD check routine and force the
code that checks for 01 to be in EAX to pass.  To me, this is the perferred method of cracking, why
run the CD check if it'll fail anyways.  Well I went back and found all three calls and tried to
overwrite them with mov eax, 00000001 (EI: make sure EAX is loaded with 01 like a good CD check).
However this would only work with the first check and failed with the other two because the program
pushes a 00000000 on the stack before the last two calls.  I couldn't seem to get around that so I
decided to look at the above code one more time to find a good place to put (or force) a jump down to
43E9A8.  This way the routine jumps right to the "found the CD" portion of code and doesn't actually
check for the CD.  Looking back you'll see at 43E8F7 the instruction "mov ebx, 00000002."  This is
the perfect spot for our little redirection of the CD checking code.  Not only that but the instruction
is also the same length as a jmp long (IE jmp with 32 bit displacement) instruction.  So calculating the
right displacement is all that's needed to FiX this code.  Replacing the mov ebx, 00000002 with a jmp
43E9A8 will solve all our problems.
	There is however and secondary type of check that goes through the WINMM (Windows Mulit-media)
system calls.  I was able to track this down after some thought.  First I checked to see how the calls
to the first CD checks where made and I found this:

* Possible StringData Ref from Data Obj ->"ADDICTION"            ; Volume of the CD
                                  |
:004033AF 68BCEE4600              push 0046EEBC
:004033B4 8B0D20504700            mov ecx, dword ptr [00475020]
:004033BA 6A00                    push 00000000
:004033BC E82FB50300              call 0043E8F0                  ; The above CD check
:004033C1 85C0                    test eax, eax                  ; Check eax  00=fail, 01=pass
:004033C3 750A                    jne 004033CF                   ; "Jump Not Equal" means we must take this jump
:004033C5 B90B000000              mov ecx, 0000000B
:004033CA E8E1FA0200              call 00432EB0                  ; Set up to quit to Win95

	With that in mind and looking for MCISendCommandA calls I searched for the string "mcisendcommanda"
and found a few hits.  However this one seemed more interesting then the others:

* Referenced by a CALL at Addresses:
|:00401EED   , :0043FE05                                         ; Called twice
|
:00442360 83EC30                  sub esp, 00000030
:00442363 53                      push ebx
:00442364 56                      push esi
:00442365 57                      push edi
:00442366 8BF1                    mov esi, ecx
:00442368 55                      push ebp
:00442369 E8A24F0100              call 00457310
:0044236E 8D462C                  lea eax, dword ptr [esi+2C]
:00442371 33C9                    xor ecx, ecx
:00442373 89460C                  mov dword ptr [esi+0C], eax
:00442376 894E30                  mov dword ptr [esi+30], ecx
:00442379 894E34                  mov dword ptr [esi+34], ecx
:0044237C 89763C                  mov dword ptr [esi+3C], esi
:0044237F BB00200000              mov ebx, 00002000
:00442384 8D4628                  lea eax, dword ptr [esi+28]
:00442387 C7463800FF0000          mov [esi+38], 0000FF00
:0044238E C6463B01                mov [esi+3B], 01
:00442392 C74624FFFFFFFF          mov [esi+24], FFFFFFFF

* Possible StringData Ref from Data Obj ->"cdaudio"               ; Checking for an audio CD
                                  |
:00442399 C7442428DC534700        mov [esp+28], 004753DC
:004423A1 3808                    cmp byte ptr [eax], cl
:004423A3 7409                    je 004423AE
:004423A5 BB00220000              mov ebx, 00002200
:004423AA 8944242C                mov dword ptr [esp+2C], eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004423A3(C)
|
:004423AE 8D6C2420                lea ebp, dword ptr [esp+20]

* Reference To: WINMM.mciSendCommandA, Ord:0032h                   ; The string we were looking for
                                  |
:004423B2 8B3DE0944700            mov edi, dword ptr [004794E0]
:004423B8 55                      push ebp
:004423B9 53                      push ebx
:004423BA 6803080000              push 00000803
:004423BF 6A00                    push 00000000
:004423C1 FFD7                    call edi
:004423C3 85C0                    test eax, eax
:004423C5 7415                    je 004423DC
:004423C7 81E3FFFDFFFF            and ebx, FFFFFDFF
:004423CD 55                      push ebp
:004423CE 53                      push ebx
:004423CF 6803080000              push 00000803
:004423D4 6A00                    push 00000000
:004423D6 FFD7                    call edi
:004423D8 85C0                    test eax, eax
:004423DA 7564                    jne 00442440

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004423C5(C)
|
:004423DC 8B442424                mov eax, dword ptr [esp+24]
:004423E0 8D4C2434                lea ecx, dword ptr [esp+34]
:004423E4 51                      push ecx
:004423E5 894624                  mov dword ptr [esi+24], eax
:004423E8 6800040000              push 00000400
:004423ED 8BCE                    mov ecx, esi
:004423EF C74424400A000000        mov [esp+40], 0000000A
:004423F7 680D080000              push 0000080D
:004423FC E85F010000              call 00442560
:00442401 33C0                    xor eax, eax
:00442403 8D4C2410                lea ecx, dword ptr [esp+10]
:00442407 89442410                mov dword ptr [esp+10], eax
:0044240B 51                      push ecx
:0044240C 6802010000              push 00000102
:00442411 8BCE                    mov ecx, esi
:00442413 8944241C                mov dword ptr [esp+1C], eax
:00442417 6814080000              push 00000814
:0044241C C744242403000000        mov [esp+24], 00000003
:00442424 89442428                mov dword ptr [esp+28], eax
:00442428 E833010000              call 00442560
:0044242D 8B4C2414                mov ecx, dword ptr [esp+14]
:00442431 83F91E                  cmp ecx, 0000001E                 ; Compare for ???
:00442434 730A                    jnb 00442440                      ; Conditional jump
:00442436 B9B8090000              mov ecx, 000009B8
:0044243B E8700AFFFF              call 00432EB0                     ; The "exit to windows" jump

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004423DA(C), :00442434(C)
|
:00442440 5D                      pop ebp
:00442441 5F                      pop edi
:00442442 5E                      pop esi
:00442443 5B                      pop ebx
:00442444 83C430                  add esp, 00000030
:00442447 C3                      ret

	Well that seems odd, to have a jump to the exit code within this routine.  So I changed the jnb
to jmp at 442434 and ran the game.  Everything worked and I could play the game without the CD online.
I missed this the first time due to having a program called FlexiCD (from MS Powertoys) being active.
Once I exitted FlexiCD, Addiction Pinball would quick back to Win95 all the time.  So I went back into
the code and looked for a secondary CD check (like the above code).  Once I forced the conditional jump
at 442434 to always jump over the exit call Addiction Pinball was running just fine without the CD even
if FlexiCD wasn't running.  So now I know I have a complete 100% working crack... this time!

  To crack this game make the following edit:

Edit pinball.exe
============================================
Search for: BB 02 00 00 00 at offset 253,175
Change to : E9 AC 00 00 00

Search for: 83 F9 1E 73 0A at offset 268,340
Change to : -- -- -- EB --

	Two simple edits is "all" it takes to FiX Addiction Pinball and get rid of the CD check.

Static Vengeance
