Amiga cracking
"Alcatraz" (c) 1992 Infogrames
Things you will need:
1. The original of "Alcatraz" (c) 1992 Infogrames. The CAPS (SPS) version (number 2073) is the one I’ve used here.
2. An Amiga or a copy of UAE.
3. Action Replay 3 cart, or rom for use with UAE.
This time our target is a novella/code protection – the sequel to popular action game "Hostages", this time called "Alcatraz". Making a copy of the 2 disks reveals that there is no disk protection whatsoever, despite the presence of this string in the bootblock:-
So of course the first step is to let the game load as normal, and get a look at exactly what kind of protection check we are dealing with…and eventually, we see a code-entry screen like this:-
It’s a joystick-controlled code-entry scheme, the codes are 3 digits long and can only contain the numbers 1-4. This clearly means that we can’t simply look at the key-irq or key-input routines to find the section of code dealing with the protection, nor can we search for a string that we entered in memory…
The easiest way to find the right area of code to look at, seems to be to find the text asking us to enter our code. The message reads:-
"ENTER WEAPONS FOR LINE xx COLUMN yy"
…where xx and yy are whichever numbers it is requesting this time around.
So we hop into the AR via the magic button, and do a string search looking for the "for line" part of the code request text:-
As you can see, the string was found at $17BE4. Then we look for code that references the part of the string where the line number is (because we know this is not fixed, so the game has to write it there once it has decided which line/column to ask us for). A quick count shows that we are looking for references to $17BED, so we use the ‘FA’ command and find only 1 match… it’s time to start disassembling the code around $17976. We can see that the code found just writes the ascii version of the code into the code request text (as we would expect!), but where is it fetching this value from? If we disassemble a few lines back, we see the following:-
017906 CLR.W $000169A0 01790C BSR.W $00016314 017910 TST.W $000169A0 017916 BEQ.B $0001790C 017918 BSR.W $00016314 ;generate 'random' number 01791C AND.W #$00FF,D7 017920 CMP.W #$000A,D7 ;value must be 0-10 range... 017924 BGE.B $00017918 ;...or we go back and do it again 017926 ADD.W #$00000001,D7 017928 MOVE.W D7,$00017D0E ;save this (COLUMN) 01792E BSR.W $00016314 ;generate 'random' number 017932 AND.W #$00FF,D7 017936 CMP.W #$0014,D7 ;value must be 0-20 range... 01793A BGE.B $0001792E ;...or we go back and do it again 01793C ADD.W #$00000001,D7 01793E MOVE.W D7,$00017D10 ;save this (LINE) 017944 MOVE.W $00017D0E,D0 ;fetch COLUMN value 01794A ADD.W #$0040,D0 ;convert value to ascii "A" to "J" 01794E LEA.L $00017BCD,A1 017954 MOVE.B D0,(A1)+ ;and write it into the code request text... 017956 LEA.L $00017BF7,A1 01795C MOVE.B D0,(A1)+ ;... at the 2 places it needs to be 01795E MOVE.W $00017D10,D0 ;fetch LINE value 017964 BSR.W $00017662 017968 ADDA.W #$00000003,A0 01796A LEA.L $00017BC3,A1 017970 MOVE.B (A0),(A1)+ 017972 MOVE.B $01(A0),(A1)+ ;and write it into the code request text... 017976 LEA.L $00017BED,A1 01797C MOVE.B (A0),(A1)+ 01797e MOVE.B $01(A0),(A1)+ ;... at the 2 places it needs to be
Well, that part was simple! In fact no need to do any breakpoints or messing around, the code is as human-readable as you’ll find in any game. Our next step is to find code that references either $17D0E or $17D10, now that we know this is where the game stores the correct COLUMN/LINE values respectively.
Using the ‘FA 17D0E’ command, we find 3 references. Two of them we already knew about, they are in the code above… let’s investigate the 3rd one, which is at $17D44.
Now that looks promising! This is obviously the comparison between the code you entered and the code the game requires. The first few lines you see in the screenshot above, simply take the code you entered (1 byte at a time) and convert it into a word value by shifting/or’ing. Then this value is compared against a value from a table indexed by the COLUMN/LINE values. If we look at the table at $1C862 we see 200 code words, eg: 0323 0312 0444 etc. This makes sense since we know the COLUMN value is limited to 1-10 range, and the LINE value limited to 1-20, giving us 10*20 possible code words.
So now all that remains is to decide how to patch it, and the patching itself. We have 3 options:-
-
[1] Patch after the CMP yourcode,goodcode so that the FAIL flag (d7=$FFFFFFFF) is never set.
[list=2]
[2] Patch the entire code table to $0111, this means anyone using your crack only has to press fire 3 times at the code screen and they will succeed.
[list=3]
[3] Patch the code routines to lookup the correct code, and tell the user what to enter (by inserting the correct code into the code request text).
Now, #1 is obviously the easiest approach, and #3 is the hardest (not hard at all in fact, but it’s all relative!). However, both require modifying code within the protection-check part of the game, and as such are likely candidates for any evil checksum routines lurking elsewhere…therefore, we’re going to go with option #2, since I think it very unlikely the game will checksum the entire code table.
NOTE: I’ve chosen to edit the "Please enter code" text to tell the user to enter 111 as the code – if you were really worried about checksums you wouldn’t do this, and simply make sure you tell the user which code to enter in your crack-intro text.
Above you can see I’ve just read in the first half of the disk, and searched for the text we know should be in mem… thankfully it seems as if nothing on the disk is compressed, so we find the text at $2D5E4 – this means it is at offset $255E4 on the disk, since we started loading at $8000 in memory.
The second thing we need to look for on disk is the code table. We know this starts with 0323 0312 0444, so a quick search finds this at $32262 in memory which means it’s at offset $2A262 on disk. A couple of quick calculations (offset/$1600) tell us that the text we want to modify is on track $1B, and the codetable is on track $1E.
Now we need to modify what’s in memory – I just used the ‘M’ command to view/edit the text "enter weapons for " to say "enter code 111 " at $2D5D0 onwards. Once that is done, it’s time to write a few lines of code to overwrite the code table with $0111:-
000400 LEA.L $00032262,A0 000406 LEA.L $000323f2,A1 00040c MOVE.L #$01110111,D0 000412 MOVE.L D0,(A0)+ 000414 CMPA.L A0,A1 000416 BNE.B $00000412 000418 BRA.B $00000418
Not the most complex routine you will ever see (or the neatest!), but after assembling this at $400 and executing (‘G 400’ in AR), we can press the magic button again and see that the code table now contains what we want.
All that remains is to save our modifications to a copy of disk 1, and test our crack! ‘WT 1B 5 2D200’ writes out the tracks we need ($1B to $1F inclusive), once that’s finished it’s time for a reboot and playtest.
Everything seems ok, another novella protection laid to rest!
-WK
Short and Sweet!
I like it;)