Checksums and how to defeat them

A tutorial by StingRay written for www.flashtro.com

Ok, so here it finally is, my first tutorial for Flashtro.
Lately while doing some HD fixes I found a nice protection which
involved checksum checks and that’s what I’m gonna write about in this
tutorial.
Without further ado let’s have a look at the target:

"The Clue!" (c)1994 Neo

The things you’ll need to follow this tutorial are:

  1. The game of course (CAPS/SPS 2134)
  2. ReSource
  3. An assembler of your choice
  4. An Amiga or emulator

Ok, let’s start the game to see what happens. We are greeted by a nice
“Enter word xx from the manual” window. Now that’s gonna be an easy
crack, right? Yes indeed but only if you do it right 🙂 (or your name is
Codetapper, then you already know everything about any 68k related
things anyway and can stop reading here as this tutorial is not for
such a super experienced cracker like you!)

Ok, let’s load the file in ReSource to have a closer look:
Load file “TheClue!” in ReSource, press “Disassemble” in the
“Project” menu and scroll down a bit. At offset $58 (check Resource’s
menu bar), we’ll see a routine that loads the texts we saw in the
lovely copy protection window into some registers and well, what
to say, that’s of course the protection routine.

Let’s check from where it’s called and what happens after this call. Move
back to the beginning of the file (i.e. offset 0) and press the
“Search” button you can see in the lower part of the screen.
Now press the “Forwards” button and ReSource returns location
$3e, we see a “bsr lbC000058” at this very position. Now press
“Forwards” again to find any other occurrences. There are none.

Most probably the game calls the protection routine and as long
as the correct word is not entered, it won’t return from the
protection routine. So, let’s check what the next routine after
the call to the protection routine does. Et voila, as expected
the next routine (lbC000628) starts the game. It loads the intro
and then the game. So, to disable the protection, we only have
to remove the call to the protection routine. Well, not quite.
For some reason I always find such utterly simple protections
suspicious so let’s look around a bit more to see if there’s
something fishy going on.

Let’s go back to the beginning of the file. Why the heck
does the game store the contents of $3fc.w and initializes
that very address with a pointer to the routine at offset
$A5C? That deserves further investigation!

Ok, let’s quickly do a search for $3fc, we’ll find 3 occurrences,
1. save ptr, 2. load it with a new address, 3. restore old ptr.
So it’s not really used within this file, so let’s load the
file that is loaded after the intro (“TheClouDisk1:Tc.Base”).
Once loaded and disassembled, we enter the “Search” requester
again and search for $3fc. And what a surprise, ReSource
finds the first occurrence at offset $875c and a bit below that
at offset $8784 we see a compare with some weird looking number.
Why is the game doing that? Let’s find out how the routine works.

        move.w  #$3FC,a3        ; should not need any comment :)
        moveq   #0,d4           ; initialize checksum value
        move.l  (a3),d0         ; d0: ptr to offset $a5c in TheClue!
        sub.l   #$A04,d0        ; $A5C-$A04=$58 = start of protection routine
        move.l  d0,a2
        moveq   #0,d5           ; loop counter
lbC00876E
        moveq   #$53,d0
        add.l   d0,d0           ; d0=$53*2=166 = number of longs to check
        cmp.l   d0,d5           ; i.e. check until offset $2A0 which
        bhs.b   lbC008784       ; is the end of the protection routine
        move.l  d5,d0
        asl.l   #2,d0           ; multiply loop counter by 4 to get correct offset
        move.l  (a2,d0.l),d1    ; get current long
        eor.l   d1,d4           ; xor with current checksum value
        addq.l  #1,d5           ; increase loop counter
        bra.b   lbC00876E

lbC008784
        cmp.l   #$42483A01,d4   ; check the checksum :)

Does that need any more explaining? I hope not. 🙂 What we have here is
a classic checksum routine. It either was obfuscated a bit on purpose
or it is the product of a C compiler. Here’s a simplified version
done by yours truely which might be a bit easier to understand:

        move.l  $3fc.w,a2
        sub.w   #$a04,a2
        moveq   #0,d4
        move.w  #166-1,d5
.loop   move.l  (a2)+,d1
        eor.l   d1,d4
        dbf     d5,.loop

It checks 166 longwords from offset $58 in the “TheClue!” file.
And what a wonder, at offset $2A0 the protection routine ends.
If you want to check the routine you can do the following:
Go to offset $875c in ReSource and select “Partial save -> set start”
in the “SV” menu, then scroll down to offset $878a and select “Partial
save -> set end”. Now select “Save .asm -> partial” in the same menu
and ReSource will save the routine then. If you thought I typed
the routine to get it into this document you now know better. 🙂

Anyway, now load this routine into your favourite assembler, change
it so that it would accept a ptr to an area to check and give
it a fitting name like “CalcChecksum” or whatever you prefer.
Then you just “incbin” the “TheClue!” file and call the routine
with a pointer that points to the start of the protection routine.
Adapting my version from above, it would look like:

START   lea     data+32+$58,a0  ; not pc relative to give Codetapper
        bsr     CalcChecksum    ; something he can complain about
        rts

data    incbin  RAM:TheClue!

; a0: ptr to area to check
; --
; d4: 32bit checksum value
CalcChecksum
        moveq   #0,d4
        move.w  #166-1,d5
.loop   move.l  (a2)+,d1
        eor.l   d1,d4
        dbf     d5,.loop
        rts

I think this is easy enough to understand, the only thing you might
wonder about is the “+32”, this is just to skip the hunk header.
There are many ways to get the size of the hunk header, usually I
just do a “d data” in Asm1/Pro and just check where the code
starts, in this case it starts at the 8. longword so the size of
the hunk header is 8*4=32 bytes.

If you execute this routine, d4 will contain the value $42483A01 and
somehow that value does look familiar, doesn’t it? 🙂 As soon as
we mess with the protection routine the checksum will be altered
which would mean the game might do some undesirable things. 🙂
I actually didn’t check what happens if the checksums are not valid,
if you feel like it you can try it yourself.

Now, how to deal with this problem? An obvious way would be to
check for all occurrences of $42483a01 and $3fc and adapt all the checks
accordingly. This would probably be the approach someone super
experienced like Codetapper would use. But we are better than that! 🙂
As a rule of thumb, do your “dirty work” with as less modifications
as possible. I just had a quick look and could spot 7 checksum routines,
that would mean we would have to change at least 7 checks but what if
there are checksum checks in other files as well? So, this approach,
even though it would work, is not elegant at all because it has too many
disadvantages.

  • we need to find EVERY checksum check in each file
  • we would have to alter EVERY file that contains a checksum check

As you can see, this is not only time consuming but also pretty unsafe.
What if we miss some checksum? The game could have “hidden checksums”,
i.e. it could use obfuscated code to check/calculate the checksum without
any direct use of the $3fc pointer and/or the original checksum value!
You would have to fully analyze the code in each file to be 100% sure
you found all checksums as there are endless ways to obfuscate such code.
Like f.e. take this one, invented in 2 minutes by yours truely:

        move.l  #$ffffc040,d0	; move.l #-$3fc<<4,d0
        lea     $00002054,a0	; lea $0815<<2,a0
        lea     (a0,d0.l),a0
        ; do a lot of fake code that uses a0 without altering the value
        ; ...
        ;
        sub.l   #$ffffdc98,a0	; sub.l	#(-$3fc<<4)+($0815<<2)-$3fc,a0
; call a slightly different checksum routine which does
; "add.w #$58,a0" at the beginning
        bsr     CalcCheckSum2	; d4: checksum
        lsr.l   #1,d4
        ; do a lot of fake code here without altering checksum value
        ; ...
        move.l  #CORRECT_CHECKSUM>>1,d0
        sub.l   d4,d0
        beq.b   .checksum_correct

As you can see, no direct $3fc access or using the original checksum
value, so the standard approach of searching for the checksum value
would return nothing! As said, possibilities are endless! 🙂
Or would you have guessed that a0=$3fc without looking at the comments?
If so, your name is probably Codetapper and I told you already that this
tutorial is not for super experienced crackers like you!

Ok, so how can we crack the game then? Easy, we remove the protection
call and put it back before the game is started! 🙂 Now, if that sounds
confusing, just think a bit about it. The game expects to have an unaltered
protection routine and exactly that is what we will feed the game with!
You probably guessed it already, we need to code a loader for the game
which does the following:

  • load file “TheClue!” and get a ptr to the first hunk (LoadSeg)
  • remove the call to the protection routine
  • restore the original code before the game is started so the checksum tests won’t fail

Now, that doesn’t sound too complicated, does it? Except for the fact
that we don’t know in which area of the game we can safely put our patch
as there could be more checksum checks. So even with this approach
we would have to check the whole game for checksums? That’s pretty
useless then, isn’t it? NO! 🙂 Luckily the code is NOT 100% pc relative,
that means there are areas that will always change depending on the
memory location the game has been loaded to as AmigaDOS relocates
these absolute addresses. Thus, they CAN’T be checked by a simple
checksum routine! Make sure you understood the last paragraph, it’s
essential knowledge! Now you might think “but what if it will just
be loaded without LoadSeg within the game?”. As we are NOT touching
the original gamecode in any way, even that check would always return
the correct checksum, our approach simply can’t fail as we don’t touch
the original executable!

Ok, let’s code our cute little loader then.
The only thing we need to do is to find a location where we can place our
patch. Let’s have a look. Too bad, the code that follows directly
after the protection call is fully pc relative and as it is the code
that starts the game, we are doomed? Of course not! 🙂 As the game
uses the “Execute” function in dos.library to load files, we will
simply patch that very function! 🙂 We just have to compare
the filename, if it matches with the one the game loads, we “patch
back” the area we have altered within “TheClue!” and simply remove
our dos “Execute” patch. Patching a library can be done using
a “forbid/store ptr to old routine/set ptr to our new routine/calc new
checksum (oh the irony :D)/ permit” combination or by using exec’s
“SetFunction” routine. As we are lazy, we could use SetFunction but
the disadvantage is that it won’t work with all libraries on
Kickstart 1.3 and guess what, dos.library is one of them. And as
we don’t want to have a patch that works on OS2.0+ machines only,
we need to find a solution for this problem. So let’s examine
what happens when we just use a normal approach, i.e we will do
the following:

  • get a ptr to the original “Execute” routine
  • forbid task switching, i.e. turn multi-tasking off
  • replace it with our patched version
  • call exec’s “SumLib” function to calculate the new library checksum
  • enable task switching, i.e. turn multi-tasking on

The code to do that could look like:

	move.l	$4.w,a6
	lea	DOSname(pc),a1
	jsr	-408(a6)			; OldOpenLibrary() (hello Mr.Spiv :D)
	move.l	d0,a1	
	lea	-222+2(a1),a0			; ptr to execute routine
	lea	Patch(pc),a1			; ptr to our patched routine
	move.l	(a0),OldExecute-Patch(a1)	; store ptr to old routine
	move.l	a1,(a0)				; install it
	jsr	-132(a6)			; Forbid()
	jsr	-426(a6)			; SumLibrary()
	jmp	-138(a6)			; Permit()

If you wonder about the -222+2, the +2 is just to skip the “jmp”
instruction, i.e. the $4ef9 opcode which is 2 bytes long.
That was what I tried first. Apparently it didn’t work very well,
the Amiga crashes with a “Library checksum failure” alert. It puzzled
me for a while but after some trial and error and checking the
“exec/libraries.i” include file I found out that the “LIB_CHANGED” bit
had to be set in the “LIB_FLAGS” before calling SumLibrary, as usual that
wasn’t mentioned anywhere.
Once I added that, patching the library worked fine, as long as the patch
wasn’t started on OS versions below 2.0. And at this point I have to
thank Mr.Spiv for giving the crucial hint. It turned out the 1.3 version
of dos.libray doesn’t use a standard jumptable to call the functions.
Normally, when you call a library function, the code inside the library
would look like:

        jmp     routine  ; if you didn't understand why I did the +2 above
        jmp     routine2 ; you may get the idea now
        jmp     routine3
        ...

So if we take the “Execute” function as example, in library versions greater
than v34 (i.e. OS2.0+) the system would do the following after your
_LVOExecute(a6) call:

DOS_Execute
	jmp DOS_REALEXECUTE

so our approach described above works perfectly. Now, for pre-OS 2.0 versions
of the dos.library things look totally different. This is what the 1.3
version does when you call Execute:

DOS13_Execute
	moveq	#-27,d0
	bra.w	SomeGenericRoutine

As you can see, our approach will totally fail here because the function
is called in a totally different way, no jmp opcode used at all.
The only way to deal with that is to add some special code which
checks if it’s an old library and use different code then. What I did to get
it working was the following: I just coded a very small program which
did nothing more than opening dos.library and giving me the ptr to this
generic routine. Then I just added a mousewait and ran this program
on an 1.3 machine equipped with an Action Replay. Yes, this is actually
one of the very few occasions where using the “magic button” is justified
in my opinion. So once my little program entered the “wait for left mouse”
loop, I pressed the magic button to have a look at the code. What I saw
was the following:

        movem.l d2-d7/a2-a6,-(a7)
        sub.l   a0,a0
        move.l  a7,d5
        sub.l   #$5dc,d5
        ...

Now, this last instruction looked promising because it occupied 6 bytes.
A perfect place for our “jsr patch” instruction as that has exactly the
same size. I think you can figure out the rest yourself, in the patch
I just executed the original code (the “sub.l #$5dc,d5″ instruction) and
called the real patch then. In case you have troubles understanding it,
just check the accompanying source code. You’ll find the complete source
for the “TheClue!” loader, examine it and try to understand the “how and why”.
You’ll notice the mess in the “PatchLib” routine, I originally made it as
a generic library patching routine that could be used similar to “SetFunction”
but due to the stupidity of the 1.3 dos.lib it turned into quite a messy
routine. You’ll also notice that I didn’t add any support to remove the
patch for 1.3 machines, if you feel like hacking the source a bit, you can
add it yourself. 🙂 But you’ll find both methods in the source, SetFunction
and the old-styled method of patching a library as I thought it could be
interesting to see them both. Anyway, it’s all for you to explore! 🙂

But now, back to our actual task, what does the patch actually have to do?
We need to:

  • compare given filename (which is given in register d1)
  • if we found the correct one, we will “repair” the code, i.e. we put back the “bsr.b protection” opcode
  • lastly we simply remove our “Execute” patch as it’s not needed anymore.

Just check this piece of code, it’s the core of the patch:

; d1: filename
Patch   movem.l d1/a0,-(a7)
        move.l  VARS+OldExecute(pc),a0
	jsr     (a0)                    ; execute original "execute" :)
        movem.l (a7)+,d1/a0

; check filename
        movem.l d0-a6,-(a7)
        lea     Introname(pc),a1
.loop   cmp.b   #" ",(a0)
        beq.b   .end
        tst.b   (a0)
        beq.b   .end
        cmpm.b  (a0)+,(a1)+
        bne.b   .wrong
        bra.b   .loop

.end    tst.b   (a1)
        bne.b   .wrong

; file found, let's do the magic :)
        move.l  VARS+Hunkstart(pc),a0
        move.w  #$6118,$3e(a0)          ; restore original code

; remove our patch
        move.l  VARS+DOSbase(pc),a1
        move.l  VARS+OldExecute(pc),d0
        lea     -222.w,a0               ; Execute offset
        move.l  $4.w,a6
        jsr     -420(a6)                ; SetFunction

.wrong  movem.l (a7)+,d0-a6
        rts

So what exactly does it do? First we execute the original “Execute” routine,
in case you wonder why we don’t simply call -222(a6), i.e. _LVOExecute,
then just think a bit about it and you’ll notice we would enter an endless
loop if we would do so! 🙂
Once that routine returns we just check the given filename. If it was
the introfile (“TheClouDisk1:TCIntro”), we just get a pointer to the
first hunk in the “TheClue!” file and simply put back the “bsr.b Protection”
opcode at offset $3e. Once we have done that we don’t need our patch any
longer and thus simply remove it. And that’s actually all there is to do! 🙂
Again, if you have problems understanding it, check out the included
source code, it uses exactly the approaches I’ve described in this tutorial.

So, I guess that’s all I can think of for the moment, I hope you found
the tutorial interesting and could learn something new. It was interesting
to write for me as even I did learn something new (the 1.3 dos.library
patching stuff). I tried to have something different than the usual
“mfm/rnc copylock/novella protection” because I think there are already
enough tutorials covering these topics. If you want to test yourself,
you can try to use the things you (hopefully) learned in this tutorial
to do a 100% crack of Whales Voyage. Even a very talented cracker like
N.O.M.A.D. makes mistakes sometimes, i.e. he missed ALL the checksums
thus rendering the FLT crack totally useless! I can’t remember that I’ve
ever seen a 100% version of that game so you might try to do one yourself!
I actually did it already for my own entertainment, you’ll have to “reverse”
the FLT crack first, i.e. you have to undo the changes N.O.M.A.D. did
to the original file! If you read this tutorial carefully, you should know
how you could check if you successfully reverted the messed up FLT exe
to a clean original executable. 🙂
Another game using checksums is “The Settlers”, you could try your luck
with that one too.

Now, as the very last thing, I’ll reveal how you could have cracked
this game without doing all this dos.library patching and stuff.
Actually, there is a bug/backdoor in the protection routine, if you
place “STR!” (or any other random 4 character word) at offset $52a in
the “TheClue!” file, you’ll have a fully cracked game!
I won’t explain why and how that works, it’s for you to find out! 🙂
Also, I am pretty sure that just “noping” the call to the protection
routine would also yield in a 100% cracked game as I couldn’t find anywhere
that this area is checked. Yet, both of the things I mentioned wouldn’t
work for Whales Voyage f.e. so I still think and hope this tutorial was
useful for you.

Lastly, I want to send out a special thank to Mr.Spiv for giving the
crucial hint why the patch didn’t work on 1.3, I would have never looked
at the library jumptable! 🙂 Also greetings to all on flashtro, I hope
to see some more tutorials soon. 🙂 I’ll try to do another one as well,
I just don’t know in which year that will be. 😉

Have fun, StingRay in August 2007

0

Publication author

offline 3 hours

mus@shi9

0
Comments: 1160Publics: 2778Registration: 06-03-2017

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
cewlout
14 years ago

@The Welder:

Ah well now I understand. First time it will bypass the check because it has been altered then it jumps to a code which replaces the instruction with the original one jumps back to the game.

And you mean the reloc32 table which needs an entry to correctly set up the JSR and of course the second code-hunk with the replace-function. Just like a virus actually 😉

0
The Welder
14 years ago

@cewlout It doesn’t matter if the checksum code is executed multiple times or just once. It’ll always pass the checksum because the code hasn’t been altered!!! Let’s take The Settlers as an example… That has multiple checksum routines, so if you remove the manual protection, when you quit (as an example), the game simply crashes. Okay so here’s what you do:- You can bypass the manual check by just (if I remember rightly) either nopping out an instruction or two, or inserting a jmp. Okay, so this bypasses the protection… but nopping out or putting in that jmp will cause… Read more »

cewlout
14 years ago

@The Welder:

Just out of curiosity. But what happens when the checksum code is executed more often? If you replace the code in first place next time the checksum-code will be again executed then? Isn’t this dangerous?

Also I knew alot of ppl who simply added a memory watchpoint on the modified addresses to see if they get hit to remove checks, is this a bad idea in general?

0
The Welder
14 years ago

In all of my years of cracking, I’ve never seen such utter nonsense as I’ve read here. All this patching of library calls and such just to by-pass a checksum routine – ridiculous. Anyone with a little cracking knowledge wouldn’t have used anything like the described technique, they’d have done as I did with The Settlers. A technique that’s a million times easier and much less messy too, but does require a little knowledge of the executable file format and relocation tables. The ideal solution to defeat this type of protection is to simply nop out (or rather replace) the… Read more »

Codetapper
16 years ago

You must be pretty jealous of my cracking skills to write such a load of crap all through your tutorial Stingray. You can’t have cracked much stuff written in C if you think that earlier code was product of a C compiler either. As for your comment about what if you miss a checksum – you could just do what you did on EAB and release a poor quality patch that crashes on the majority of machines, has post after post of bug reports and then throw all your toys out of the cot when someone doesn’t bow to your… Read more »

DLFRSILVER
16 years ago

It was a 2 minutes crack for me.
I was so disappointed…..

0
DLFRSILVER
16 years ago

i have already done it on the french version, which was not
cracked until 2 years ago.

Just need to nop out the dongle check compare instruction, and everything goes perfect !

Was thinking about Robocop 3 or Dyna Blaster 😀

0
StingRay
16 years ago

Any special wish for a "how to crack a dongle protected game" tutorial? I remember BAT 2 had a dongle protection if I’m not mistaken, I might do one for this game. 🙂

0
DLFRSILVER
16 years ago

thanks for this very good cracktut, it’s a change yes ^^

Why not trying to crack a dongle protected game ?

0
StingRay
16 years ago

Hehehe, easy to explain, he thinks he’s world’s best cracker/hd fixer/coder/whatever and everyone else is a bloody newbie for him. He likes to boast how "good and experienced" he is, while in fact he heavily relies on tools done by others for his work. Just check some of his comments here on Flashtro f.e., totally arrogant and written as if he would know everything about everything. I had some arguments with him because I dared to have my own opinion which apparently pissed him off for a reason I don’t have to understand. Anyway, I wouldn’t mind his boasting if… Read more »

mr.spiv
16 years ago

Oki.. what’s the thing with Codetapper? Didn’t get that 😀

0
StingRay
16 years ago

Feel free to ask any questions here in case you had problems to understand some parts of this tutorial. I’ll try to answer then. 🙂

0
Rob
Rob
16 years ago

Yes, nice work. Very interesting.

0
StingRay
16 years ago

Thanks guys. 🙂 For some reason I have the certain feeling the next tutorial is not too far away. 🙂

0
aLpHa oNe
16 years ago

roxx0r!!

0
mr.spiv
16 years ago

Ah.. great one!

0
WayneK
16 years ago

Great tutorial, nice to see one on a ‘new’ topic… more please! 🙂

0
StingRay
16 years ago

Thanks. 🙂

0
Go0se
16 years ago

Enjoyable + well written tutorial!

Cheers StingRay.

0
Authorization
*
*

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Registration
*
*
*

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Password generation

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

0
Would love your thoughts, please comment.x
()
x