Cracking

AGA-Fixing | Artwork | Cracking | Demos | Emulation | FAQ | Feedback | Games | HD-Installing
History | Home | Icons | Join Us | Links | Memberlist | MFM-Installing | News | Patches | Rob Northen | Utilities

This information is purely for users that need help with removing protection from games to write HD installs for JST/WHDLoad!

This is quite an old document and unfortunately the author is unknown. Some of the practices are very dodgy. ie. You shouldn't assume memory will be at $c00000, you should remove all self modifying code and at least disable the caches (the example is further down) but it is more of a look back in time at the art of cracking than a current how-to article.

If you are the original author of this document or you know who is, please contact me so I can credit you!

Codetapper/Action

How to Crack Amiga games

So, some of you guys would like to know how to go about cracking Amiga games? Well, here's how you do it!

The first place to start is always the bootsector! The bootsector is so small that most games don't bother having any protection at all there.

Generally (on professional productions) the bootsector will be a 1k long raw-tracks loader. Not dos standard of course.

Simply rip the bootsector off and disassemble it. If you're lucky (for some nice easy work) it will only kill the DMA, interrupts, colours and set up the stack real low. Then it usually copies itself just up above the stack (it doesn't need to be position-dependant any more if it's been previously relocated) and will load some tracks.

Disassemble the bootcode: 30 seconds work!

If you're good enough, you won't have to even look at the routine for more than a minute to figure out where the tracks are loaded too, and how much. Now assemble the bootcode, and stick in a mouse-wait at the top. Ok! Run... Now hit the button on your cartridge (why do things the hard way?) and set a breakpoint at the place where the loader will terminate and jump into the loaded tracks.

Now save out the loaded tracks to disk and get ready for stage two!

Stage two starts to become more fun! You've got two more options from here. Either there will be another sub-loader, or this will be the main loading routine.

If it's the former, you're in for some fun over the next day or two! What will of course occur is they will try to kill your cartridge, lose you in the code, generally put all those great obsticles in the way. The same kind of general guidelines will apply from now on, so here they come:

  1. Always go from one step to another from an assembled file. ie. Have a binary file, incbin it, and emulate all of the conditions that have been setup to that point.

  2. At all times make sure that the game will work correctly from your assembled file! Lots of games are paticularly good at making hidden/latent protection bugs which will multiply.

  3. Always make sure that the game will run with your cartridge in, as it will save a lot of work in the long run.

  4. Watch out for the cool trick of leaving the stack pointing into the middle of some crucial data (it's obvious when you know what to look for 'cuz no interrupts will be used conspicuously). What happens is when you press your button, the data will get corrupted = Messy if the data was packed and in the middle of de-packing!

  5. The standard trick is the Trace-Vector-Decoder! Remember this name!

    What will happen here is that the trace routine to be executed will be pushed onto the stack, and the trace-vector will be pointed to it. You will see a load of shit just in front of the PC, and the last command will be a move to the SR to kick off the trace.

    [Erm, for new guys! What happens is that the trace vector code is executed after each instruction, and after the current instruction, the trace vector decodes what the next instruction will be! Thus all you see in front of the PC is garbage!]

    So you want to know the best way to get around this?

    Easy! The golden rule is: Know the length!

    Write a routine which counts from 0 to whatever, and chuck this at the end of the trace (in place of the rte put a jump to your code - watch out for the trace taking checksums of the trace itself and the area below the stack!) Locate the screen address if it's being displayed, and you can get your 'counter' to show you the number of repetitions of the trace simply by printing the current number of reps to the screen!

    Small ones are a piece of piss, longer ones like the ones on Gods or Magic Pockets are harder, but really fun eh! [Well over 270 reps if I remember!]

    Of course any good TVDecoder will kill your cartridge on it's way through. Anyway, find out what it does. Finding out the effects is always really important. I'm too lazy to write more.

    TVDecoders will be used to encrypt the disk-loaders, encrypt packers, hide some sneak checksum routine etc, etc...

  6. Packers are always a gimme. After a while, you'll know your packers like back of your cock, er... hand! Most of them are junk/repeats anyway, and always easy to find where the files go to.

  7. Further disk loaders are always fun. The guy has got all this memory to try to confuse you, but if he can understand it, so can you...

  8. I'm getting bored of all of this! You've gotta learn all the tricks yourself! It's the only way. A helpful tip is look out for interrupts! Watch what will happen to the stack when you press your cartridge!

  9. MOST IMPORTANTLY! NEVER GO TO THE NEXT STAGE OF THE PROTECTION IF YOU CAN'T RUN IT FROM YOUR ASSEMBLER AND GET IT RUNNING WITH THE ORIGINAL DISK IN THE DRIVE!

Hehe, I nearly forgot! Here's a neat trick for all you learning crackers, what do you think this code does? You can assume caches have been disabled:

           move.w  #$4e71,PokeMe       ;This is a 'nop' for guys who

           ...

PokeMe     bra.s   Red                 ;don't memorise the opcode!

           bra.s   Green



Red        move.w  #$f,$dff180

           bra.s   Red



Green      move.w  #$f0,$dff180        ;Hint - you get a green screen!

           bra.s   Green

Look, this is the type of 68000 trick that the other guy will try to put over your head. This type of thing is boring to a pro, but don't become frustrated, you have the rest of your life to work it out! You'll figure out all the tricks sooner or later!

What will happen is that the other guy will try to lose you in the code, but you must follow the PC until you get to the main program (there's ALWAYS a main program of some sort or another!)

Save the main program out to disk (sometimes 1 file, sometimes lots) and then get into your assembler and get out your CRACKSHELL and put in the code which will emulate the conditions of the machine which will allow you to run the game from the assembler.

Right, the aim here is to gradually alter the loaders until none of the originals are used!

So this is the setup... You've got your main program as a binary file, say starting at $400, stack below $400 and you've got all the contents of all hardware and registers set up before you start.

If the file is big, pack it, as it will save time in the long-run! Get another Amiga with loads of memory just for packing!

This is what your 'CRACK-SHELL' will look like:

  • Kill DMA, Interupts etc, Supervisor mode (I use the division by 0 method).
  • Depack main program to $400.
  • Set stack, all registers... CIA are important to set up too! (This is a common mistake for beginners - also use the SR! - a lot of Amiga guys leave it alone!)
  • Wait mouse!

OK, now assemble, run, put the original into the drive and press the mouse. (The game will run normally as if nothing has happened!)

This is the basic shell from which a lot of crackers work! Now, you've gotta pick up the files if it's a multi-load (they all are nowadays... But in the old days... *Sigh*)

OK, the idea is to figure out the loaders, rip them off and get the files. When you first see the disk-code (its LONG!) you think WHAT? I'm not doing that every time!

Relax, you've gotta serve your apprenticeship and become familiar with the routines. After a while you'll be able to pick out the head-steppers, drive-selecters, decoder, etc and it's easy to work out what's going on. (Just like packers, they become a help rather than a hinderence - there are only a limited number of ways to do the loading!)

OK, now you have to collect the extra files! Look at the code to find the routines which load the files:

           moveq   #1,d0               ;File number - load routine will use it

           lea     $60000,a0           ;Destination address of the file

           jsr     _loader

There are two ways to collect the files:

  1. Train the game, and play right through to the end, collecting the files with your cartridge as they load in.

    Or

  2. Rip-off the loaders and decrunchers and use the other guy's own routines to get his files! You must get his 'file info' if you want to do this!

    Write a program which accepts the inputs, and uses his routines. eg:

    • Get start block, end block.
    • Kill system and load the files using the original routines (don't forget to insert the original disk first).
    • Depack them with his routines if necessary.
    • Restore system and save the files to your own disk.

Right, you've got the files, now this is where all your meg's come in handy. Get the files packing on your other Amiga for a few hours, and try to pick the disk-protection.

Of course watch out for the obligatory checksum/etc routine(s) to make sure that code within the game - specifically the loaders - aren't tampered with...

OK, the files are packed! (Shit! That was a long-wait if it was a two-disk game!)

You must code a routine which merges all of the small packed files into a 'BIGCRUNCH' as I call it... This BIGCRUNCHER will put all of the packed files into 1 single large file and save this file out PLUS a list of all of the offsets of the individual files in the big file.

Ok, ok... You're ready to go. Include the BIGCRUNCH into your assembler CRACKSHELL... incbin... Include some code to copy the bigcrunch to say $c00000 if it's not used. The aim here is to run the file and get the file-loader routines replaced with your de-packer routine!

ie. Instead of loading from disk, all the files will be depacked down from the high-ram into their proper places! (Yeah! move.w $dff006,$dff180)

Now you've gotta alter the main game program so that your routines will be executed instead of the original loaders. The routine that you will write will take the same inputs as the main game supplies, and has the same effect as the original routines.

Assemble this program to disk, relocate it to say, $d00000, with your relocator utility.

Now, you've gotta change your CRACKSHELL so that it does this:

  1. Kill the system.
  2. Copies the main-game file to it's original position.
  3. Copies the BIGCRUNCH (ie. all of the extra files - packed) to say $C00000
  4. Copies your loader-emulator to say $d00000
  5. Set up the initial conditions, as before
  6. POKE THE MAIN GAME FILE SO THAT IT EXECUTES YOUR ROUTINE AT $D00000!

Number 6 is the most important new one. Say the original used to do this:

           moveq   #1,d0                ;File number

           lea     $60000,a0            ;Destination address

           jsr     $1004                ;Load routine

Then at $1004 you must do this:

           jmp   $d00000

Thus, your routine will be executed instead of the original file-loader and the result will be that the files are still put into there required positions by your depacker routine, and the RTS at the end will continue the game on as if nothing had ever happened! (A lot of games need eg. registers to be returned with values).

Now, the tough part about replacing the loader routine with your one at $d00000 is that the original loader will usually leave some kind of message that it's been executed, and usually there is some disk protection in the loader code! This is where I'm becoming bored of typing all this info in, so I'll give you some general guidelines here!

  1. Watch out for interrupt routines! They might be checking things!
  2. Find out the total effect of the loader routine and emulate it.
  3. The protection might even involve setting a CIA register a certain way! I've seen this one before!
  4. An equally good way of beating the routines is to find out the routine which detects if the loader has been run.

The number of tricks which can be used here is huge, you must learn to overcome these yourself!

OK, now you will have a completely 1-meg game!

You can assemble the CRACKSHELL and run it, and the only time that the disk will spin is when the disk protection is working!

THE NEXT STEP IS TO BUST THE DISK PROTECTION ROUTINES!

When you think about it, then only real way to protect a game is to check for something which is hard to copy. Like a dongle, or a disk.

Thus, you have to have a routine sitting in memory to be able to do this checking, and this is the vulnerable part! All you have to do is remove the routine at this point and you've got the game cracked (as we have the files already). Easy?

No!

This is where most of the action is! Most of the effort will go into protecting this routine from removal, and not the routine itself!

This is where you will win or lose! This routine may be encrypted with a trace vector decoder, or there may be checks to make sure that this routine is run, it will pass some values back to the main game routines probably, there will be other routines to check that this routine is not removed. The list of methods is huge!

I'd like to make some points here:

  1. For the sake of simplicity, I didn't really mention that that the file loader (which we earlier bypassed) will be very heavily protected like the copy protection routines. Very often there is no separate copy protection routine, just a hugely fortified file-loader.

  2. In the majority of cases, the protection code will not be seen by the programmer himself.

    eg. Early Rob Northern. The programmer will get 2 files. 1 will put the protection on the disk, and the other will be incbin'ed into the game, and be jsr'ed, the result returned in the trace vector (or somewhere else!)

    Thus your job will be easier in this case, as the protection is 'modular' if you can understand that expression.

As I'm not going to give you specific details of the types of things that can trick you here, I will simply give you the aim of all this!

The aim is to get to the stage where the original disk is no longer accessed! Thus all of the extra files will be depacked from the extra-mem and the game will work as normal!

Right, so you can run the game without the original disk! Yeah! You're nearly there!

THE SECOND LAST STEP IS TO INSERT YOUR OWN DISK LOADERS!

As a cracker you'll probably have a collection of diskloaders! Some like to use raw tracks, others like to use file-loaders.

I'm a file loader freak! The file loader will be a standard routine which only needs the name of the file to be defined, the destination address and the address where you can do DMA too.

The file loader must be very nice to the game! Not using anything or changing anything. So these are the rules:

  1. Decode the sectors into the same area that you do DMA to.
  2. Don't touch anything other than the necessary registers. eg. The game shouldn't be able to see your loader! Use the beam position for waiting, use the 68000 to decode (though you can try using the blitter if the original used it) etc.
  3. Make sure all registers etc are returned as the original did.
  4. If you're a really cool guy, you will want to use the trick of loading the files into there destination positions and depacking them back over themselves. Make sure you put depack stripes in to show how cool you are!

Many games use file names, and a pointer to the file name itself will be given. In which case, just use the original name. Otherwise, a number will be given. Let me explain.

This will be the code in the original game:

           moveq   #1,d0

           lea     $60000,a0           ;Maybe also pass the DMA address here

           jsr     _loader

And in the original, there will be an array of "file info". (This is looking at memory):

eg.        $0016,$009f                 ;File 0 goes from block 22 to $9f

           $0100,$0106                 ;File 1 goes from block $100 to $106

           $0107,$0110                 ;File 2 goes from block $107 to $110

           ...

Thus, the original loader would do this:

           add.w   d0,d0

           add.w   d0,d0

           lea     data,a1

           add.w   d0,a1               ;Now get the data

(Another common file info format is start block, length of file).

We don't need to bother about this, as we have files on the disk! The solution is to use the value in D0 as the filename on the disk.

eg. If d0 = 1, then the name of the file is "$0001" on the disk. This is easy to do! At the beginning of your file-loader, make a small routine that constructs the name, then take it's hash as normal, and load it.

How many times have you seen cracks with file names like $0001, $0002? Look out for it in future, and you'll know why!

The next step will be to get rid of your big-crunch, and get the files loading in from disk. ie. Put your disk-loader at $d00000 instead of the depacker.

Then comes the tricky part, you must find a place to copy your own loading code into the main game somewhere. The ideal way is to of course use the area where the original routine was sitting. (Watch out for routines that take checksums/check bytes in this area = good protection against this). But this is not always possible.

If you can't put your routine over the original, make sure you find some area which is DEFINITELY FREE (not so easy sometimes eh!), otherwise you'll have to release a one-meg game and you've been beaten.

There are two factors here:

  1. Positive: Your disk-loader is really small anyway, only a few small bytes (well under 2k anyway).

  2. Negative: Many programmers purposely try to eat up all of the memory so that you can't fit your routines in there (Hybris is a bloody good example of this).

OK, that's it! You have a main-file in the form of your CRACKSHELL which sets up the status of the machine and then jumps into the main file, which has been altered with your own loader, and all other protection removed!

Put the extra-files onto the final disk! Now put your intro onto the front of the crack shell, make sure the game is coded to hell to stop lame crack-stealers from ripping you off, and yeah, nearly forgot - put your name into the high-score table!

OK, now you've got a hot crack on your hands after those few days work, so spread the crap out of it, and start on the next one!

Author unknown!


AGA-Fixing | Artwork | Cracking | Demos | Emulation | FAQ | Feedback | Games | HD-Installing
History | Home | Icons | Join Us | Links | Memberlist | MFM-Installing | News | Patches | Rob Northen | Utilities
 

Site updated: 28/8/2005 ©1997-2005 Codetapper/Action! All rights reserved.