SnapIt v2.0 for the PowerPC (SH3) Goatass

Published by Tsehp 2002



Recommended readings:


Windows CE Platform SDK (HPC Pro) -

SH3 programming manual -

Any tutorial on PocketPC -




IDA 4.15

WindowsCE SDK

PocketPC (I used the Jornada)


The target:


SnapIt is a utility that takes snapshots of your PowerPC screen.

In demo mode it only takes screenshots of half the screen.

You can register it with a serial number.




I got my Jornada for graduation and started playing with it, installed

some applications and tried reversing them. There isn't all that many

tutorials out there about cracking WindowsCE application so I decided to

contribute. I'm in the process of creating a dedicated web site for WinCE

cracking too so I'll be writing a lot more tutorials (if time permits).


Ok to get started I installed the program and ran it. First thing I noticed

was a "Register" button on the window, I clicked it and entered some info.

Error message pops up saying "Invalid information....". Next I opened my

MS ActiveSync and copied the snapit.exe from the device to my desktop and opened

it with IDA. Once it's all done I loaded an additional binary file (from the File

menu in IDA) and loaded the Coredll.dll that came with the WinCE SDK. Now

I have labels for all the imported functions which helps a crap load.


Looking at the Names window in IDA (the button with the glasses and wond) I found

the string "aInvalidRegistr" clicked on it and I land in some funky code.


.text:00012BFC mov.w @(h'40,pc), r6 ; [00012C40] = h'210

.text:00012BFE mov #h'10, r5

.text:00012C00 mov.l @(h'54,pc), r0 ; [00012C58] = sub_116DC

.text:00012C02 add r15, r6

.text:00012C04 mov.l @(h'58,pc), r4 ; [00012C60] = aXiSnapTicks

.text:00012C06 jsr @r0 ; sub_116DC ; check serial number

.text:00012C08 add r15, r5

.text:00012C0A tst r0, r0

.text:00012C0C bf loc_12C1E ; good jump (branch if false)

.text:00012C0E mov.l @(h'4C,pc), r0 ; [00012C5C] = _MessageBoxW

.text:00012C10 mov.l @(h'38,pc), r5 ; [00012C4C] = aInvalidRegistr

.text:00012C12 mov #h'30, r7 ; '0'

.text:00012C14 mov.l @(h'70,pc), r6 ; [00012C88] = aXiSnapit

.text:00012C16 jsr @r0 ; _MessageBoxW

.text:00012C18 mov r8, r4

.text:00012C1A bra loc_12C30

.text:00012C1C mov #1, r0


I added a couple comments in there where the serial number check happens and if

it fails a message box appears and gives you an Invalid Registration message.

The BF instruction means Branch if False. After the TST r0,r0 the T bit is set

to either 1 or 0 depending on whether the TST (test) instruction is true or false.

In this case the:


.text:00012C06 jsr @r0 ; sub_116DC ; check serial number


instruction must return a "1" in r0 so the tst r0,r0 fails and the bf instruction

jumps. Btw, JSR is Jump to Sub-Routine.


Ok so now lets take a look at sub_116DC since it's where the JSR R0 jumps to and

does all the serial checking. scrolling down a bit we get to:


.text:000116F8 mov.l @(h'58,pc), r5 ; [00011754] = aSoftwareMicr_1

.text:000116FA jsr @r0 ; sub_11C38 ; check reg key


Here the program checks a registry key, SOFTWARE\Microsoft\Windows\Other for a value.

Using a registry editor that came with the SDK we can see that there is some value

in that key. After it reads the value it test to see whether there was a value in

there or not. If there isn't any that means it's the first time the application

is ran and it need to create this value. A couple lines down you will see a call to

GetTickCount and then some more registry crap, that stores the value returned by

GetTickCount into that registry key.


After it either read or created the value in the registry we get to this code:


.text:0001171C mov r8, r5

.text:0001171E bsr sub_11B0C ; do final checking and compare

.text:00011720 add r2, r4

.text:00011722 tst r0, r0

.text:00011724 bf loc_11774 ; must jump


The above BSR sub_11B0C is the Branch to Sub-Routine (better known in asm as a Call)

that we want to investigate. Jump to it in IDA and lets have a look.


.text:00011B22 bsr sub_11820


is the first line of some action, all it does is copy the first part of the serial

to another buffer. If you haven't figured it out by now just from looking at the

string refrences in the file the format of the serial is *******-******* that's 7

character on each side of the "-". After copying the first part of the serial the

program checks it's length and make sures it's 7 digits long.


Get length of the first part of the serial and compare it to 7:


.text:00011B28 mov.l @(h'108,pc), r0 ; [00011C34] = _wcslen

.text:00011B2A jsr @r0 ; _wcslen

.text:00011B2C add r15, r4

.text:00011B2E mov #7, r1

.text:00011B30 cmp/hi r0, r1 ; if R1 > R0 jump

.text:00011B32 bt loc_11B40 ; no jump


Get length of the second part of the serial and compare it to 7:


.text:00011B34 mov.l @(h'FC,pc), r0 ; [00011C34] = _wcslen

.text:00011B36 mov #h'74, r4 ; 't'

.text:00011B38 jsr @r0 ; _wcslen

.text:00011B3A add r15, r4

.text:00011B3C cmp/eq #7, r0

.text:00011B3E bt loc_11B44 ;jump


Following the jump to loc_11B44 we see it converts what we typed in to uppercase.

Since it's converting our serial to uppercase we can assume that it should contain

characters and not numbers.


Next we get to this code:


.text:00011B5C bsr sub_11A54 ; check chars and format

.text:00011B5E add r15, r5

.text:00011B60 tst r0, r0

.text:00011B62 bt loc_11B74 ; no jump


following that BSR to sub_11A54 we will see how the program checks the length of

the two parts, making sure it's 7 digits long, and then it checks to see that it's

between "a" and "z". Not very complicated or interesting but it's there so I

mentioned it.

Following these checks the BT loc_11B74 does not jump and we get to what we've been

looking for:


.text:00011B64 mov.w @(h'BC,pc), r4 ; [00011C24] = h'D8

.text:00011B66 mov.l @(h'C0,pc), r0 ; [00011C28] = _lstrcmpiW

.text:00011B68 mov r9, r5

.text:00011B6A jsr @r0 ; _lstrcmpiW

.text:00011B6C add r15, r4

.text:00011B6E tst r0, r0

.text:00011B70 bt/s loc_11B76

.text:00011B72 mov #1, r0

.text:00011B74 loc_11B74:

.text:00011B74 mov #0, r0


The final compare of our serial and the generated one takes place right here and if

everything is good r0 will be equal to 0 and the BT/S will jump.

Something to keep in mind is that with this processor all of the jumps are delayed,

meaning the instruction following the jump will be executed first and then the jump

will be made. So in our case here we see how r0 gets the value 1 and then it jumps

otherwise it will get the value 1 and then be overwritten with the value 0 which is

a bad flag.


So what I did to patch this to make it work is this:


.text:00011B70 bt/s loc_11B76

.text:00011B72 mov #1, r0

.text:00011B74 loc_11B74:

.text:00011B74 mov #1, r0


This way if you enter a good serial number or a bad one you will be registered.

So open snapit.exe in a hex editor goto offset 1B74 and change the bytes from:


00 E0 to 01 E0


save it and put it back on your device overwirting the original one, actually make

a back up of the original one just in case. Run the program and click "Register",

enter any name and any serial in the format we found out, ex. 1111111-2222222 or

aaaaaaa-bbbbbbb, whatever you pick and click OK. You are now registered and you

can take full screen snapshots of that huge PowerPC screen.




Greets: zip, CrackZ, +tsehp, and my pals in the scene.