Ma First Steps in Reversing on the PPC / WinCE OS
Published by +Tsehp May 2002
CHAPTER ONE - walking up the path to iPAQia

ok, let's start now! making friends with the PPC OS (formerly known as WindowsCE) is not that difficult if you're already familiar with Win32 cracking. One thing is that different Handheld devices use different processors. That means that, even if they all run the Microsoft PPC Os, they use different opcodes. The most common processors atm are StrongARM, Mips and SH3. So, once again, you'll have to deal with differnt commands and opcodes depending of the type of handheld device you're actually using. This example here focuses on StrongARM processors as I'm using a Compaq iPAQ maself.

choosing your weapons ...

Till today i haven't found any disassemblers or debuggers running on the handheld device itself. that means that all the reversing is done on your local pc. therefor in order to reverse a PPC-app you'll need a disassembler capable of disassembling ARM executables (eg. IDA Pro 4.15), a hexeditor (eg. HIEW) and maybe some resource editor (eg. exescope or whatever .. the win9x versions do work for wince as well!). With the microsoft embedded visual tools comes a debugger and an emulator as well, but it only runs on WinNT. it's available for free download from microsoft.com and features a visual basic and a visual cpp compiler, an ide a. s. o. . That's the url to it:


know your enemy ...

before we start with an example you should have a short look at some of the papers about the arm processor etc. i'd suggest the following stuff:

heyrick.co.uk's instruction set quick finder
opcodes    you're gonna need them for patching ... (my latest version can be found at http://www.ka0s.net)
help-files about evc-rt-library functions and the ce-api-set (come with ms's embedded visual tools)
maybe google knows more ...

for the following example you should at least have an idea of the opcodes + commands and know a bit about cracking in general! the example will be a very easy one, so... no fear ;)
CHAPTER TWO- Opening the gates

target for this example is a pack of games called ScaryBear.GamePack I and II (http://www.scarybearsoftware.com). it's a pack of some games which use the same protection. the tools i used were IDA v4.15 and hiew.

let's start with the game LINES v1.1. first of all install it to your handheld device and have a look at it. run the game and click Options/About. You'll see the AboutBox that tells you that Lines v1.1 still is only a Trial Version and asks you for your reg code. enter whatever you want and click (OK) in the upper right corner. nothing happens ... shite ;) an obvious hook would make it easier. so let's have a look at the included README.TXT file:

NOTE: These games have a 14-day trial period, after which, you will need to purchase a Game Pack 2 reg code to permanently activate all 3 games. For more details, please visit: http://www.scarybearsoftware.com

so let's try to set the system-date 15 days ahead and run the game again. try to click the game-screen ... YAY, we got our hook: a MessageBoxW. now copy the game .exe to your local pc and load it into IDA. when ida asks you for the processor type just choose: ARM Processor: ARM. then it asks for some libraries, in this case: AYGSHELL.DLL. normally you can just copy these .dll files from your handheld device (let's only call it PPC from now on) to your local pc as well. important system dll files come with ms's embedded visual tools.

the MessageBox that appears after setting the date ahead displays the following message:

14-Day Trial Period is over. Please visit www.scarybearsoftwarecom to purchase a copy.

back in IDA open the names window (shift+F4) and search for that string. depending on your ida-settings you should find somthing like
'a14DayTrialPeri'. doubleclick it and ida brings you to the rite location.

.data:00016160 a14DayTrialPeri unicode 0, <14-Day Trial Period is over.>
.data:00016160 ; DATA XREF: .text:0001173C

then follow the XREFs till you find the place where the MessageBoxW finally is called. the place's here:

.text:00011704 ; ---------------------------------------------------------------------------
.text:00011704                 STMFD   SP!, {R4-R6,LR}
.text:00011708                 MOV     R4, R3          ; <-- R1 .. R5 a.s.o are registers
.text:0001170C                 BL      sub_13578       ; <-- call some sub that checks wheter you're regged or not
.text:00011710                 CMP     R0, #1          ; <-- does R0 equal 1 ?
.text:00011714                 BNE     loc_11744       ; <-- if it doesn't .. jump to some nice place
.text:00011718                 BL      sub_13964       ; <-- did u use that game for more than 14 days??
.text:0001171C                 CMP     R0, #1          ; <-- is 'R0 = 1' true?
.text:00011720                 BNE     loc_11744       ; <-- no? OK, let's play that game
.text:00011724                 LDR     R2, =aError     ; -----------------------------------------------------
.text:00011724                                         ; <-- you're not registered, show the damn
.text:00011724                                         ;     MessageBox
.text:00011728                 MOV     R3, #0          ;
.text:0001172C                 LDR     R1, =a14DayTrialPeri ; <-- set message
.text:00011730                 MOV     R0, #0          ; <-- set type
.text:00011734                 BL      MessageBoxW     ; <-- api call
.text:00011738                 B       loc_11840       ; <-- jump to the place of no return ;)
.text:00011738 ; ---------------------------------------------------------------------------
.text:0001173C off_1173C       DCD a14DayTrialPeri     ; DATA XREF: .text:0001172Cr
.text:0001173C                                         ; "14-Day Trial Period is over.\nPlease vis"...
.text:00011740 off_11740       DCD aError              ; DATA XREF: .text:00011724r
.text:00011740                                         ; "Error"
.text:00011744 ; ---------------------------------------------------------------------------

the BL on line 1170C calls a sub that finds out wheter you're registered or not. the return value is saved in R0. R0 then is checked for equality with 1. if R0 doesn't equal 1 we are registered and can continue playing the game without getting the stupid nag telling us that our trial time is over. now we could only change the BNE on line 11714 to a BEQ or a B and we could continue playing the game without the nag. but in order to make the game think we're really registered we'll have to examine sub_13578. examining the code in this subroutine shows that every mistake in the serial brings us to the same location ... .text:00013680 MOV R0, #1:

.text:00013578 ;  S U B R O U T I N E 
.text:00013578 sub_13578                               ; CODE XREF: .text:0001170Cp
.text:00013578                                         ; .text:00011B4Cp ...
.text:00013578                 STMFD   SP!, {R4,R5,LR}
.text:0001357C                 SUB     SP, SP, #0xE0
.text:00013580                 LDR     R0, =aRegcode
.text:00013584                 ADD     R1, SP, #0x18
.text:00013588                 BL      sub_13BCC
.text:0001358C                 ADD     R0, SP, #0x18
.text:00013590                 BL      wcslen
.text:00013594                 CMP     R0, #0xA
.text:00013598                 BCC     loc_13680       ; <-- WRONG KEY
.text:0001359C                 ADD     R0, SP, #0x18
.text:000135A0                 BL      sub_1371C
.text:000135A4                 MOVS    R3, R0
.text:000135A8                 BNE     loc_13680       ; <-- WRONG KEY
.text:000135AC                 LDRH    R3, [SP,#0x26]
.text:000135B0                 MOV     R4, #0
.text:000135B4                 LDR     R1, =aD
.text:000135B8                 ADD     R2, SP, #0x14
.text:000135BC                 ADD     R0, SP, #0
.text:000135C0                 STRH    R3, [SP]
.text:000135C4                 STRH    R4, [SP,#2]
.text:000135C8                 BL      swscanf
.text:000135CC                 ADD     R2, SP, #4
.text:000135D0                 LDRH    R3, [SP,#0x1E]
.text:000135D4                 ADD     R0, SP, #0
.text:000135D8                 LDR     R1, =aD_0
.text:000135DC                 STRH    R3, [SP]
.text:000135E0                 STRH    R4, [SP,#2]
.text:000135E4                 BL      swscanf
.text:000135E8                 ADD     R2, SP, #8
.text:000135EC                 LDRH    R3, [SP,#0x1C]
.text:000135F0                 ADD     R0, SP, #0
.text:000135F4                 LDR     R1, =aD_1
.text:000135F8                 STRH    R3, [SP]
.text:000135FC                 STRH    R4, [SP,#2]
.text:00013600                 BL      swscanf
.text:00013604                 ADD     R2, SP, #0xC
.text:00013608                 LDRH    R3, [SP,#0x2A]
.text:0001360C                 ADD     R0, SP, #0
.text:00013610                 LDR     R1, =aD_2
.text:00013614                 STRH    R3, [SP]
.text:00013618                 STRH    R4, [SP,#2]
.text:0001361C                 BL      swscanf
.text:00013620                 ADD     R0, SP, #0x18
.text:00013624                 BL      sub_136A4
.text:00013628                 LDRH    R3, [SP,#0x2C]
.text:0001362C                 ADD     R2, SP, #0x10
.text:00013630                 MOV     R5, R0
.text:00013634                 LDR     R1, =aD_3
.text:00013638                 STRH    R3, [SP,#0x18]
.text:0001363C                 ADD     R0, SP, #0x18
.text:00013640                 LDRH    R3, [SP,#0x2E]
.text:00013644                 STRH    R4, [SP,#0x1C]
.text:00013648                 STRH    R3, [SP,#0x1A]
.text:0001364C                 BL      swscanf
.text:00013650                 LDR     R3, [SP,#0x14]
.text:00013654                 LDR     R2, [SP,#0xC]
.text:00013658                 CMP     R3, R2
.text:0001365C                 BNE     loc_13680       ; <-- WRONG KEY
.text:00013660                 LDR     R3, [SP,#4]
.text:00013664                 LDR     R2, [SP,#8]
.text:00013668                 CMP     R2, R3
.text:0001366C                 BNE     loc_13680
.text:00013670                 LDR     R3, [SP,#0x10]
.text:00013674                 MOV     R0, #0          ; R0 = 0 and you're fully registred
.text:00013678                 CMP     R5, R3
.text:0001367C                 BEQ     loc_13684       ; <-- YAY, your serial is valid! :)
.text:00013680 loc_13680                               ; CODE XREF: sub_13578+20j
.text:00013680                                         ; sub_13578+30j ...
.text:00013680                 MOV     R0, #1          ; R0 = 1 and you're not registered!
.text:00013684 loc_13684                               ; CODE XREF: sub_13578+104j
.text:00013684                 ADD     SP, SP, #0xE0
.text:00013688                 LDMFD   SP!, {R4,R5,PC}
.text:00013688 ; End of function sub_13578

the easiest way to make the app think that you're using a correct serial is just to change that single line

.text:00013680 MOV R0, #1
.text:00013680 MOV R0, #0.

why again?? because when the app returns from that subroutine R0 is checked for equality with 1. and as we found out before, if it equals 1, the app knows that it's NOT registered! ;)

CHAPTER THREE - The Bare Knuckle Fight

now it's time for the heXeditor. for me the thing that makes changing the code a bit more difficult than changing the code of a win32 app is that you can't just easily use HIEW's built in assembly-view but that you have to know the opcodes. that's the point where i'm opening ma opcode list ;).

MOV (reg,value) xxxxA0E3
Mov R1,#0 0010A0E3
Mov R0,#1 0100A0E3

now load 'lines.exe' into your heXeditor and go to Offset 13680.

.text:00013680 - 01 00 A0 E3 E0 D0 8D E2-30 80 BD E8 38 64 01 00 ".0Ǣ8d."

by the way, arm commands consist of 4 bytes (and btw. each command can be conditional! eg. MOVEQ, MOVNE). now let's see how we gotta change that command:

MOV R0, #1 stands for 01 00 A0 E3
MOV R0, #0 is 00 00 A0 E3

so quickly patch the .exe file, save it and upload it to your PPC. run it and .. TATAA, you're fully registered!

as you can see, cracking on a PPC / WinCE OS is not too different from cracking on Win9X. the api function set is quite equal to Win9X's, tho the CE api set is a bit smaller .. some functions are just missing or carry other names.

ah, ok .. that's it for now. if you're looking for more texts about wince / ppc cracking check ka0s.net every now and then and
!have a niiiice day!

greetings and thanks to ma mum, iri5, toni, regen, paul, nutty, tommek, the lz0 tribe, COREPDA and all ma friends!