Crack on a new platform using the dead list approach. Experience the M68000 assembler. Make your own Java key generator for a Pilot application.
|
|
Necessary :
Palm OS Emulator : you'll need this to use your PC to emulate the Pilot. You don't really need it if you already have a REAL Pilot. Anyway, this emulator is amazing.
PRC2BIN : this will extract all the resources linked in a Pilot .PRC executable file.
PilDis : the best Pilot disassembler around.
M68K Disassembler 1.1 : I experienced some problems with this one (it made me lose one hour of my life :(), but sometimes it disassembles a bit better than PilDis.
Pila
: the Pilot assembler.
Hacker's
View 5.66 : this is the hex-editor I prefer, but any other will
do.
Optional :
ROM File : You'll find debug ROM's for the Palm OS Emulator at 3COM's, but with them I experienced some unexpected crashes (yes, usually I expect crashes under WinSuxx95 :). That's why I encourage you to take a released ROM. If you don't have a real Pilot, you'll find some on the Net. This URL might be down by the time you read these lines, but anyway, you know how to search, don't you.
ASDK : this is an almost complete toolbox that contains many very useful programs like PilDis, PRC2BIN and Pila.
The Copilot Home Page : there you'll find some infos about the original PalmPilot emulator.
Pilot Assembler Reference : excellent compilation of infos to program (and crack) Pilot apps.
CrossFire 5.10 : this program doesn't interest us much in itself, but it contains an excellent description of most M68000 instructions.
Pilot Programming FAQ : if you know how to program, you've done a good part of the way to the crack.
MC68328 DragonBall : official informations about Motorola's processor.
Atomic Fire Balls : you'll need these hot cinammon candies to fight against the DragonBall processor. If you cannot find them in Europe, you can place an order at CandyDirect. One ball should last long enough for you to read this essay. If you prefer the more classical Martini/Vodka, I advise you NOT to eat an Atomic Fire Ball while sipping your favorite cocktail...
A Good Bootleg : just put on a good concert of Lush, Garbage or Nirvana while cracking Pilot programs. You'll see, it helps to feel the code. If you fancy trading bootlegs with me, my list is here.
|
|
|
00005d18 363c05dc
MOVE.W #1500!$5dc,D3 ;mov word ptr D3, 05DCh
00005d1c 6052
BRA L885
;jmp L885
00005d1e 363c0640
MOVE.W #1600!$640,D3
00005d22 604c
BRA L885
00005d24 363c06a4
MOVE.W #1700!$6a4,D3
00005d28 6046
BRA L885
00005d2a 363c0708
MOVE.W #1800!$708,D3
00005d2e 6040
BRA L885
00005d30 363c076c
MOVE.W #1900!$76c,D3
00005d34 603a
BRA L885
00005d36 363c07d0
MOVE.W #2000!$7d0,D3
00005d3a 6034
BRA L885
00005d3c 363c0834
MOVE.W #2100!$834,D3
00005d40 602e
BRA L885
00005d42 363c0898
MOVE.W #2200!$898,D3
00005d46 6028
BRA L885
00005d48 363c08fc
MOVE.W #2300!$8fc,D3
00005d4c 6022
BRA L885
00005d4e 363c0960
MOVE.W #2400!$960,D3
00005d52 601c
BRA L885
00005d54 363c09c4
MOVE.W #2500!$9c4,D3
00005d58 6016
BRA L885
00005d5a 363c0a28
MOVE.W #2600!$a28,D3
00005d5e 6010
BRA L885
00005d60 363c0a8c
MOVE.W #2700!$a8c,D3
00005d64 600a
BRA L885
00005d66 363c0af0
MOVE.W #2800!$af0,D3
00005d6a 6004
BRA L885
00005d6c 363c0b54
MOVE.W #2900!$b54,D3
00005d70 4a43
L885 TST.W D3
;cmp word ptr D3, 0
00005d72 6708
BEQ L886
;jz L886
00005d74 3f03
MOVE.W D3,-(A7)
00005d76 4e4f
TRAP #15
00005d78 a195
DC.W sysTrapFrmHelp ;display a Help Form
00005d7a 544f
ADDQ.W #2,A7
00005d7c 4cdf0438
L886 MOVEM.L (A7)+,D3-D5/A2
00005d80 4e75
RTS
;ret
If you have never dealt with the M68000 assembler before, this piece
of code needs some comments. You may have noticed that the second operand
of each instruction is the target and not the source (contrary to the X86
assembler).
MOVE.W #1500!$5dc,D3 means that the value 1500d (= 05DCh) will be put
into the register D3 using the space of a WORD. The M68000 processor contains
8 data registers (D0-D7), 7 address registers (A0-A6) and a stack pointer
(A7). Registers have 32 bits.
Instructions that use registers are followed by a .B (byte : 8 bits),
.W (word : 16 bits) or .L (long : 32 bits). This tells the processor how
much bits of the register the instruction will act on (almost like our
BYTE PTR, WORD PTR and DWORD PTR).
BRA means "branch". This is a simple unconditional jump to the specified
location. The TST instruction may be useful to us : it tests if the register
(here D3) equals zero and sets the flags accordingly. The flags are then
checked by BEQ (Branch if EQual). This conditional jump will branch if
the result of the TST instruction was zero.
Finally, there is the call to sysTrapFrmHelp preceded by the TRAP instruction
(interrupt call) to display the Help Form and the RTS (ReTurn from Subroutine)
to return to the caller.
If you're interested in getting more informations about the M68000
processor and assembler, please refer to the Tools section of this essay.
Seemingly, in our protection we do not expect a Help Form but an Alert
Form. Let's have a look at the second occurrence of the ResID :
00007d8a 2c48
L1174 MOVEA.L A0,A6
00007d8c 2f0c
MOVE.L A4,-(A7)
00007d8e 4e4f
TRAP #15
00007d90 a139
DC.W sysTrapFldGetTextPtr ;get a pointer on the first text
field (User Name)
00007d92 2808
MOVE.L A0,D4
00007d94 2444
MOVEA.L D4,A2
00007d96 2f0e
MOVE.L A6,-(A7)
00007d98 4e4f
TRAP #15
00007d9a a139
DC.W sysTrapFldGetTextPtr ;get a pointer on the second text
field (Reg. Num.)
00007d9c 2a08
MOVE.L A0,D5
00007d9e 4a84
TST.L D4
;first text field pointer = null ?
00007da0 4fef000c
LEA 12(A7),A7
00007da4 6748
BEQ L1177
;if yes, branch to Bad_Guy
00007da6 4a85
TST.L D5
;second text field pointer = null ?
00007da8 6610
BNE L1176
;if no, calculate the right Reg. Num.
00007daa 6042
BRA L1177
;if yes, branch to Bad_Guy
00007dac 1012
L1175 MOVE.B (A2),D0
;calculate the right Reg. Num. from the User Name
00007dae 4880
EXT.W D0
00007db0 d046
ADD.W D6,D0
00007db2 064004a3
ADDI.W #1187!$4a3,D0
00007db6 3c00
MOVE.W D0,D6
00007db8 528a
ADDQ.L #1,A2
00007dba 4a12
L1176 TST.B (A2)
00007dbc 66ee
BNE L1175
;loop while not end of User Name string
00007dbe 2f05
MOVE.L D5,-(A7)
00007dc0 4e4f
TRAP #15
00007dc2 a0ce
DC.W sysTrapStrAToI ;convert
the entered Reg. Num. to Integer
00007dc4 7200
MOVEQ #0,D1
00007dc6 3206
MOVE.W D6,D1
00007dc8 b280
CMP.L D0,D1
;are the calculated and the entered Reg. Nums equal ?
00007dca 584f
ADDQ.W #4,A7
00007dcc 6620
BNE L1177
;no, then branch to Bad_Guy
00007dce 2f04
MOVE.L D4,-(A7)
;Good_Guy, the entered Reg. Num. is right
00007dd0 486dfc66
PEA -922(A5)
00007dd4 4e4f
TRAP #15
00007dd6 a0c5
DC.W sysTrapStrCopy ;save
the User Name
00007dd8 2f05
MOVE.L D5,-(A7)
00007dda 486dfc86
PEA -890(A5)
00007dde 4e4f
TRAP #15
00007de0 a0c5
DC.W sysTrapStrCopy ;save
the Reg. Num.
00007de2 1b7c0001fc96
MOVE.B #1,-874(A5)
;put on the "Registered" flag
00007de8 4fef0010
LEA 16(A7),A7
00007dec 6016
BRA L1178
;branch over Bad_Guy and continue normal execution
00007dee 422dfc66
L1177 CLR.B -922(A5)
;Bad_Guy - clear the User Name variable
00007df2 422dfc86
CLR.B -890(A5)
;clear the Reg. Num. variable
00007df6 422dfc96
CLR.B -874(A5)
;clear the "Registered" flag
00007dfa 3f3c05dc
MOVE.W #1500!$5dc,-(A7) ;wowowow... here is our
Bad_Guy ResID
00007dfe 4e4f
TRAP #15
00007e00 a192
DC.W sysTrapFrmAlert ;display
the Alert Form
00007e02 544f
ADDQ.W #2,A7
00007e04 3f2dfeb2
L1178 MOVE.W -334(A5),-(A7) ;keep on
normal execution
00007e08 4e4f
TRAP #15
00007e0a a19e
DC.W sysTrapFrmReturnToForm
As you can see, the names of the sysTraps are meaningful enough for
us to understand them. With our search for 05DC, we have landed right in
the protection routine. We don't even need to understand EVERY instruction;
a global view is more than enough for now. We'll spend more time on this
protection at the end of this essay : we'll program a key generator for
Currency Calculator.
What we have to patch is quite obvious : just put a No OPeration (NOP)
at 00007DCC which will force the program to go to Good_Guy. Same scheme
as always...
Now we have a big problem : we all know that on our beloved PC's the
opcode of NOP is 90h. What is the opcode of NOP on the M68000 ? We can
try to make a string search for NOP on the dead listing of CURRCAL1.PRC,
but no NOP is found. A good solution (if, like me, you cannot afford buying
a 70$ book containing all the M68000 opcodes) is to use Pila, the Pilot
Assembler. Just put a NOP somewhere in the sample file, assemble and then
disassemble with PilDis to find the opcode. I know that this technique
is not so smart but it works fine though. We discover that NOP is 4E71h
(yes Sir, 2 bytes).
The crack is finished. Use Hacker's View to replace the 6620h at 00007DCC
with 4E71h. Load the cracked app from the emulator and enter anything in
the fields. It works quite well. Zero-character strings are not accepted
and will refuse you the registration. Don't patch the checks for null pointers
at 00007DA4 and 00007DAA as it would crash your Pilot badly (this is "normal"
as the called API cannot handle empty strings).
Note that your registration will not be kept in memory if you EXIT
the emulator just after registering. You have to run another program in
order to keep the memory as changed. I suppose that this is due to the
fact that you cannot EXIT a real Pilot (this would be equal to a cold reset
and the memory wouldn't be kept either). On the real Pilot, you just press
the green button to turn it off, which doesn't throw away the changes that
might have occurred inside the memory.
Now you can also patch CURRCAL2.PRC. You have to put the NOP at the
offset 00004BE0.
Ok, let's move on to another target. I chose TealPaint 2.20 from
TealPoint Software. This is an excellent drawing program (at least on the
Pilot). TealPoint Software distribute many other applications like TealDoc
or TealEcho. They seem to make a big business out of Pilot apps. That's
why we'll crack TealPaint and that's why I encourage you to crack all other
TealPoint apps, like I already did myself...
Once again, you may not find exactly the same version at PilotGear,
but you can handle the offset changes. The important thing is to UNDERSTAND
what happens inside the target.
Here we go : run the target and a nag-screen will appear just after
you have entered a database name. Now you can press the Register button
to see what happens. The registration process uses your HotSync ID as User
Name and you have to enter the corresponding key. So boring...
Let's get the ResID of the Alert Form that contains "Make sure your
HotSync ID matches the one in your Registration message" that is displayed
after you have entered a bad key.
We can now use PRC2BIN and PilDis on TEALPNT.PRC. We find our Bad_Guy
string in TALT07D1.BIN and you'll notice that TALT07D2.BIN contains "Thank
You, Registration key accepted". Browsing ALL resource files is often helpful
and not so time-consuming.
A string search for our ResID (07D1) in the disassembled file TEALPNT.PRC.s
gives us only one occurrence in the code area at 000050CC which is directly
followed by a call to sysTrapFrmAlert :
000050b6 528b
L293 ADDQ.L #1,A3
000050b8 0c130020
CMPI.B #32!$20,(A3)
000050bc 6ef8
BGT L293
000050be 16bc0000
MOVE.B #0,(A3)
000050c2 4eba0026
JSR L296
;call to L296
000050c6 4a00
TST.B D0
;D0=0 ?
000050c8 6700000e
BEQ L294
;if yes, branch to Good_Guy
000050cc 3f3c07d1
MOVE.W #2001!$7d1,-(A7) ;Bad_Guy
000050d0 4e4f
TRAP #15
000050d2 a192
DC.W sysTrapFrmAlert ;display
the Bad_Guy Alert Form
000050d4 548f
ADDQ.L #2,A7
000050d6 600a
BRA L295
;jump over Good_Guy
000050d8 3f3c07d2
L294 MOVE.W #2002!$7d2,-(A7) ;Good_Guy
000050dc 4e4f
TRAP #15
000050de a192
DC.W sysTrapFrmAlert ;display
the "Thank You..." Alert Form
000050e0 548f
ADDQ.L #2,A7
000050e2 4cdf1cf8
L295 MOVEM.L (A7)+,D3-D7/A2-A4 ;pop registers
000050e6 4e5e
UNLK A6
;remove the stack frame
000050e8 4e75
RTS
;return to the caller
This seems to be easy... let's replace the BEQ at 000050C8 by a BRA
and the program will unconditionally branch to Good_Guy. This time, no
need to assemble a BRA like we did with NOP. There are many BRA's in the
program. Watch at offset 000050D6 : BRA is 60h plus the displacement (here
0Ah to reach L295). We have two possibilities : either replace the 67h
at offset 000050C8 with 60h and it will make a far jump to L294 or put
a 600Eh at the same offset to make a short jump. Both work fine.
Now you can reload the patched version of TEALPNT.PRC into your Palm
emulator and try it. Press the Register button, enter something in the
Key field, press OK and we can see that our crack works fine. Now run another
program to force TealPaint to quit. Rerun TealPaint and... bad thing, the
nag-screen is still here. Our crack is not so good. Why ? Because the key
is checked each time the program executes. We only forced it to display
the "Thank You ..." form, but now we must crack the check for the nag-screen.
What happens just before the TST, at 000050C2 ? The program makes a
Jump to SubRoutine (i.e. a call to a procedure). We can assume that this
procedure must return 0 in D0 if we want the BEQ to branch to Good_Guy.
If the nag-screen is still displayed, that's because there is certainly
another call to this subroutine somewhere else in the code. A search for
L296 gives us :
0000438c 4eba0d5c
L243 JSR L296
;call the registration check
00004390 1b400536
MOVE.B D0,1334(A5) ;store D0 in a variable
00004394 4a2d0536
TST.B 1334(A5) ;test the variable
for 0
00004398 670000c0
BEQ L246
;jump over the nag-screen display routine if D0=0
Now we can be sure that the procedure must return 0 in D0. Let's have a look at this famous L296 :
000050ea 4e560000
L296 LINK A6,#0
000050ee 48e71f38
MOVEM.L D3-D7/A2-A4,-(A7)
000050f2 486d090f
PEA 2319(A5)
000050f6 4eba008c
JSR L297
000050fa 588f
ADDQ.L #4,A7
000050fc 3f3c0004
MOVE.W #4,-(A7)
00005100 2f3c00005673
MOVE.L #22131!$5673,-(A7)
00005106 2f3c00001234
MOVE.L #4660!$1234,-(A7)
0000510c 486d090f
PEA 2319(A5)
00005110 4eba009e
JSR L298
00005114 4fef000e
LEA 14(A7),A7
00005118 2800
MOVE.L D0,D4
0000511a c8bc00003f3f
AND.L D4,#16191!$3f3f
00005120 45ed0568
LEA 1384(A5),A2
00005124 2f0a
MOVE.L A2,-(A7)
00005126 4e4f
TRAP #15
00005128 a0c7
DC.W sysTrapStrLen
0000512a 588f
ADDQ.L #4,A7
0000512c 264a
MOVEA.L A2,A3
0000512e d7c0
ADDA.L D0,A3
00005130 528b
ADDQ.L #1,A3
00005132 3f3c0005
MOVE.W #5,-(A7)
00005136 2f3c0000e113
MOVE.L #57619!$e113,-(A7)
0000513c 2f3c0000f985
MOVE.L #63877!$f985,-(A7)
00005142 2f0a
MOVE.L A2,-(A7)
00005144 4eba006a
JSR L298
00005148 4fef000e
LEA 14(A7),A7
0000514c c0bc0000003f
AND.L #63!$3f,D0
00005152 e188
LSL.L #8,D0
00005154 2600
MOVE.L D0,D3
00005156 3f3c0005
MOVE.W #5,-(A7)
0000515a 2f3c0000e113
MOVE.L #57619!$e113,-(A7)
00005160 2f3c0000f985
MOVE.L #63877!$f985,-(A7)
00005166 2f0b
MOVE.L A3,-(A7)
00005168 4eba0046
JSR L298
0000516c 4fef000e
LEA 14(A7),A7
00005170 c0bc0000003f
AND.L #63!$3f,D0
00005176 8083
OR.L D3,D0
00005178 b084
CMP.L D4,D0
;compare D4 and D0
0000517a 56c0
SNE D0
;if (D0=D4) then D0:=0; if (D0/=D4) then D0=FFh
0000517c 4cdf1cf8
MOVEM.L (A7)+,D3-D7/A2-A4
00005180 4e5e
UNLK A6
00005182 4e75
RTS
Again, we don't need to understand every instruction. This procedure
is quite complex (some JSR's, ...). We know it must return 0 in D0, so
we can reverse it. We begin at the end and watch what happens with D0.
The key to our problem seems to be located at 0000517A. We can put 0 in
D0 ourselves with the instruction : MOVE.B #0, D0 . We use a MOVE.B as
only a byte is tested for zero at 00004394 and 000050C6. Assemble this
instruction, disassemble it and you'll find the opcode 103C0000h . As it
takes 4 bytes, we can put it at 00005178 which will overwrite the CMP and
the SNE.
The crack works fine now and there is no nag-screen anymore, even before
we have entered a registration key... this behavior was expected as we
patched the subroutine that is used for all checks to the key.
If you disassemble TealDoc, you'll see that its protection routine
is almost the same as TealPaint's. I hope that someone will fancy writing
a generic patcher for all TealPoint apps, all versions. This may involve
writing a heuristic searcher to find and patch the protection part even
if it has been slightly changed through different versions. This would
be an excellent exercise.
Ok, we've seen enough easy protections. Our new target, PAL 1.31,
doesn't have a "ready-to-crack" registration routine. PAL is a nice applications
launcher that allows you to categorize your apps (even though the new Palm
OS 3.0 would have the same feature built-in). At the bottom of the screen,
the date blinks with an "UNREGISTERED" message. If it doesn't blink, click
on the locker, turn on the Pilot with the green button and then it will
blink.
What do we want to do ? Of course, you could put your handle instead
of the "UNREGISTERED" message and it would be nice, but what we want is
that the date stops blinking. We have no idea of which API could be used
to display this string. As Palm programs are quite small, we can try a
"brute" technique that is to perform a string search for "sysTrap". I told
you it was brute... This way, we'll get ALL API calls that the program
makes. It won't take you more than five minutes to browse all these calls,
and you'll learn much.
I experienced some problems when disassembling PAL.PRC with PilDis.
Some parts of the code area that are important to our cracking purpose
were not correctly disassembled. Therefore you should use the M68K Disassembler
for this target.
The disassembly done, let's browse the sysTrap calls. At the beginning
you'll find many memory related sysTraps that are unuseful to us. A bit
further, at 00000E8A, we land on a sysTrapTimeToAscii followed by a sysTrapWinEraseRectangle
and a sysTrapWinDrawChars :
00000e84 e188
LSL.L #8,D0
00000e86 2f00
MOVE.L D0,-(A7)
00000e88 4e4f
TRAP #15
00000e8a a268
sysTrapTimeToAscii ;convert the
current time to ASCII chars
00000e8c 4fef000c
LEA 12(A7),A7
00000e90 48780000
PEA $0000.W
00000e94 486f0038
PEA 56(A7)
00000e98 4e4f
TRAP #15
00000e9a a219
sysTrapWinEraseRectangle ;erase a rectangle part of the screen
00000e9c 504f
ADDQ.W #8,A7
00000e9e 2f3c004b0000 MOVE.L #4915200!$4b0000,-(A7)
00000ea4 486f0024
PEA 36(A7)
00000ea8 4e4f
TRAP #15
00000eaa a0c7
sysTrapStrLen
;get the length of the time string
00000eac 584f
ADDQ.W #4,A7
00000eae 7200
MOVEQ #0,D1
00000eb0 3200
MOVE.W D0,D1
00000eb2 7010
MOVEQ #16,D0
00000eb4 e1a9
LSL.L D0,D1
00000eb6 0041002c
ORI.W #44!$2c,D1
00000eba 2f01
MOVE.L D1,-(A7)
00000ebc 486f0028
PEA 40(A7)
00000ec0 4e4f
TRAP #15
00000ec2 a220
sysTrapWinDrawChars ;draw the chars
of the time string on the screen
Doesn't it look like a time-display routine ? We can assume that the
same routine must exist for the date and for the "UNREGISTERED" message.
Let's keep on our search. At 00000EFA we have the sysTrapDateToAscii
we were waiting for, and it is also followed by the same display API. Now
we know that the display of the "UNREGISTERED" string should be made through
sysTrapWinDrawChars.
The search for sysTrapWinDrawChars gives quite a lot of occurrences.
This time, you really have to feel the code, unlike with our previous
targets.
If you're an experienced cracker, you'll notice that only one occurrence
of sysTrapWinDrawChars corresponds with the pattern above :
00001df0 4feffff4
L63 LEA -12(A7),A7
00001df4 3f7c00040004
MOVE.W #4,4(A7)
00001dfa 3f7c008a0006
MOVE.W #138!$8a,6(A7)
00001e00 3f7c00490008
MOVE.W #73!$49,8(A7)
00001e06 3f7c000b000a
MOVE.W #11!$b,10(A7)
00001e0c 2f3c01000000
MOVE.L #16777216!$1000000,-(A7)
00001e12 4e4f
TRAP #15
00001e14 a164
sysTrapFntSetFont
00001e16 584f
ADDQ.W #4,A7
00001e18 3f400002
MOVE.W D0,2(A7)
00001e1c 48780000
PEA $0000.W
00001e20 486f0008
PEA 8(A7)
00001e24 4e4f
TRAP #15
00001e26 a219
sysTrapWinEraseRectangle
00001e28 504f
ADDQ.W #8,A7
00001e2a 2f3c00890000
MOVE.L #8978432!$890000,-(A7)
00001e30 2f3c000c0005
MOVE.L #786437!$c0005,-(A7)
00001e36 486dff18
PEA -232(A5)
00001e3a 4e4f
TRAP #15
00001e3c a220
sysTrapWinDrawChars
00001e3e 4fef000c
LEA 12(A7),A7
00001e42 7000
MOVEQ #0,D0
00001e44 302f0002
MOVE.W 2(A7),D0
00001e48 7218
MOVEQ #24,D1
00001e4a e3a8
LSL.L D1,D0
00001e4c 2f00
MOVE.L D0,-(A7)
00001e4e 4e4f
TRAP #15
00001e50 a164
sysTrapFntSetFont
00001e52 4fef0010
LEA 16(A7),A7
00001e56 4e75
RTS
It's quite difficult to find the pointer to "UNREGISTERED" that must
be passed to sysTrapWinDrawChars. I suppose that the PEA -232(A5) (Push
Effective Address) does the trick. Anyway, now we have 2 solutions, either
we prevent the call to L63 which is done at 0000307A, either we return
from the procedure just after it has been called, that means we put a RTS
intruction (ReTurn from Subroutine) at L63.
The opcode of RTS is 4E75h. We put it at 00001DF0 and we're done. The
babe is perfectly cracked.
I must tell you that it took me about 30 minutes to figure out where
was hidden the display of "UNREGISTERED" among the multiple calls to sysTrapWinDrawChars,
but the first routine I patched was the right one; no luck here. I consider
this as a hard crack for the pilot. Usually you can get through the protection
in 5-10 minutes. I hope that now that I've written this essay some Pilot
programmers will try making more funny protection (encrypted code would
be MUCH fun). Maybe that one day Aladdin will make a PalmHASP... we can
still dream.
Anyway, I think that now you've seen most techniques usable on the Pilot
with only a dead listing approach. If you think that you've had enough
for now, you can stop reading and begin you first Pilot crack, but if you're
interested in understanding the M68000 assembler a bit better, there is
still something funny we can do : a key generator. Therefore we'll get
back to Currency Calculator. We'll write our own key gen using Java.
Why Java ? It's portable Sir. It might be run on a PC as well as on a Mac
or even on a Pilot ;) I'm not a Java guru at all, so please don't criticize
my code too much; it runs and that's more than enough for me !
I will explain only succinctly the boring parts of the key gen process,
as you are all able to figure out what I did.
Here is the protection part of CURRCAL1.PRC again :
00007d8a 2c48
L1174 MOVEA.L A0,A6
00007d8c 2f0c
MOVE.L A4,-(A7)
00007d8e 4e4f
TRAP #15
00007d90 a139
DC.W sysTrapFldGetTextPtr ;get a pointer on the first text
field (User Name)
00007d92 2808
MOVE.L A0,D4
00007d94 2444
MOVEA.L D4,A2
00007d96 2f0e
MOVE.L A6,-(A7)
00007d98 4e4f
TRAP #15
00007d9a a139
DC.W sysTrapFldGetTextPtr ;get a pointer on the second text
field (Reg. Num.)
00007d9c 2a08
MOVE.L A0,D5
00007d9e 4a84
TST.L D4
;first text field pointer = null ?
00007da0 4fef000c
LEA 12(A7),A7
00007da4 6748
BEQ L1177
;if yes, branch to Bad_Guy
00007da6 4a85
TST.L D5
;second text field pointer = null ?
00007da8 6610
BNE L1176
;if no, calculate the right Reg. Num.
00007daa 6042
BRA L1177
;if yes, branch to Bad_Guy
00007dac 1012
L1175 MOVE.B (A2),D0
;calculate the right Reg. Num. from the User Name
00007dae 4880
EXT.W D0
00007db0 d046
ADD.W D6,D0
00007db2 064004a3
ADDI.W #1187!$4a3,D0
00007db6 3c00
MOVE.W D0,D6
00007db8 528a
ADDQ.L #1,A2
00007dba 4a12
L1176 TST.B (A2)
;ASCIIZ string : did we reach the 00h
00007dbc 66ee
BNE L1175
;loop while not end of User Name string
00007dbe 2f05
MOVE.L D5,-(A7)
00007dc0 4e4f
TRAP #15
00007dc2 a0ce
DC.W sysTrapStrAToI ;convert
the entered Reg. Num. to Integer
00007dc4 7200
MOVEQ #0,D1
00007dc6 3206
MOVE.W D6,D1
00007dc8 b280
CMP.L D0,D1
;are the calculated and the entered Reg. Nums equal ?
00007dca 584f
ADDQ.W #4,A7
00007dcc 6620
BNE L1177
;no, then branch to Bad_Guy
Everything happens in L1175. From 00007D94 we know that A2 points to the beginning of the User Name string. Each character will be loaded into D0 (at 00007DAC) and D0 will be extended to a word. Then, D6 (which contains a number calculated previously) is added to D0, 04A3h (=1187d) is also added to D0 and D0 is copied to D6. The same algorithm is applied to each character of the User Name. Here is the code explained line by line :
00007dac 1012
L1175 MOVE.B (A2),D0
;copy one character of the User Name to D0 (BYTE PTR)
00007dae 4880
EXT.W D0
;extend D0 to a word
00007db0 d046
ADD.W D6,D0
;add D6 to D0 (WORD PTR)
00007db2 064004a3
ADDI.W #1187!$4a3,D0 ;add 04A3h
to D0 (ADD Immediate value)
00007db6 3c00
MOVE.W D0,D6
;copy D0 to D6
00007db8 528a
ADDQ.L #1,A2
;inc A2
00007dba 4a12
L1176 TST.B (A2)
;did we reach the end of the User Name string ?
00007dbc 66ee
BNE L1175
;if no, then loop back to L1175
A good question that you might ask is : what is the value of D6 at the
beginning of the loop. Reversing the whole thing shows that at 00007C8A
D6 is initialized to 0. Now everything is ok to make our key generator.
Here is the Java code that I've written :
import java.awt.*;
import java.applet.*;
import java.lang.*;
public class CurrCalcKeyGen extends Applet
{
Font font;
Panel ThePanel = new Panel();
TextField UserNameField = new TextField(30);
String Generated = "";
public void init()
{
setBackground(Color.white);
ThePanel.add(new Label("User
Name : ", Label.RIGHT));
ThePanel.add(UserNameField);
add(ThePanel);
add(new Button("Generate
The Registration Number"));
resize(400, 170);
}
public boolean action(Event
evt, Object arg)
{
int GeneratedRegNum=0;
String UserName = UserNameField.getText();
if (UserName.length()==0)
{
Generated="Maybe you should enter something...";
}
else
{
for (int i=0;i<UserName.length();i++)
GeneratedRegNum+=UserName.charAt(i)+1187;
Generated="Your registration number is : "+GeneratedRegNum;
}
repaint();
return true;
}
public void paint (Graphics
g)
{
g.setColor(Color.blue);
font=new Font("TimesRoman", Font.BOLD, 20);
g.setFont(font);
g.drawString(Generated, 50, 100);
g.setColor(Color.black);
font=new Font("TimesRoman", Font.BOLD, 10);
g.setFont(font);
g.drawString("Written by TeK", 300, 140);
}
}
I think that there is nothing more to explain. That's quite easy. You
can click here to view this code in action.
The generator works fine, but you may experience problems if you use weird
characters in the User Name (like accents). The Pilot character set is
definatelly not the Unicode used by Java.
Furthermore, the registration number is a WORD. If your User Name contains
more than 50-55 chars, the Reg. Num. may get bigger than 65535 and what
happens then ? Well, it should come back to zero... but our Java key gen
will not. As you can see, not all of what I call "limit cases" are treated
here, but the key generator will work if it's used normally. The zero-char
string case has been treated.
|
|
|
+HCU papers
homepage links search_forms +ORC students'
essays academy
database
reality
cracking how
to search javascript
wars
tools anonymity
academy cocktails antismut
CGI-scripts mail_fravia+
Is
reverse engineering legal?