----------------Megabots--------------- A 4am crack 2014-04-15 --------------------------------------- Megabots is a 1986 educational game distributed by Neosoft, Inc. The original disk uses a standard 6-2 nibble encoding; standard address prologue and epilogue; standard data prologue and epilogue. COPYA gives disk read errors on tracks $1D and $1E. Locksmith 7.0 Fast Disk Copy (ignoring errors on those tracks) produces a copy that boots, loads title screen, then hangs. Listening to the disk boot, it sounds like it's loading a standard DOS from tracks 2, 1, and 0. Maybe even Pronto-DOS or some other variant that only uses the first sector on track 2. Any attempt to use Ctrl-C during early boot displays a flashing cursor, then hangs. Copy ][+ can read the disk catalog on track $11. Viewing the track/sector map confirms that tracks $1D and $1E are unused by any files. My intuition tells me that's where the nibble check is. TRACK 1 2 0123456789ABCDEF0123456789ABCDEF012 S0 GAVSOMIHFEDCCB HIJKLLA BB E1 HFAVROLIHFEDCCB HIJJLLA BB C2 HFZVROLIHFDDCCB HIJJLLA BB T3 HFZVROLIHFDDCCB HIIJLLA BB O4 HEZUROLIHFDDCCB HIIJLLA BB R5 HEZUROLIHFDDCCB HIIJLLA BB 6 HEZTRNKIGFDDCCB HIIJLLL BB 7 HDZTQNKIGFDDCBB HIIJKLL BB 8 HDYTQNKIGEDCCBB HIIJKLL B 9 HDYTQNKIGEDCCBB HIIJKLL B A HCYTPNKIGEDCCBB HIIJKLL B B HCXSPNJIGEDCCBB HIIJKLL B C HCXSPMJIGEDCCBB HHIJKLL B D HBWSPMJIGEDCCBB HHIJKLLA B E GBWSPMJHFEDCCBB HHIJKLLAM B F GBWSPMJHFEDCCBB HHIJKLLAM B ^^ nothing here ---++ (Hey, I was right about the DOS only using one sector of track 2. I'll be sure to list that skill on my resume.) Since the (non-working) copy has a disk catalog and files, let's start there. [S6D1=non-working copy] [S5D1=my work disk] ]PR#5 ]CATALOG,S6,D1 C1983 DSR^C#254 131 FREE A 008 HELLO B 049 ANAL.DROIDS B 031 ANAL.FINAL GAME B 022 ANAL.HELMET B 010 ANAL.TOP0 B 010 ANAL.TOP1 B 008 ANAL.TOP2 B 008 ANAL.TOP3 B 014 ANAL.TOP4 B 005 ANAL.BASE0 B 005 ANAL.BASE1 B 005 ANAL.BASE2 B 005 ANAL.BASE3 B 006 ANAL.DROIDHIT3 B 006 ANAL.DROIDHIT0 B 006 ANAL.DROIDHIT1 B 003 ANAL.DROIDHIT2 B 006 ANAL.NO POWER DROID B 006 ANAL.DROIDHIT4 B 005 ANAL.GUIDE B 002 ANAL.HIT00 B 004 ANAL.HIT01 B 003 ANAL.HIT03 B 002 ANAL.HIT11 B 003 ANAL.HIT12 B 006 ANAL.HIT14 B 002 ANAL.HIT20 B 003 ANAL.HIT22 B 003 ANAL.HIT23 B 003 ANAL.HIT30 B 003 ANAL.HIT31 B 003 ANAL.HIT32 B 003 ANAL.HIT33 B 033 PIC.X A 025 DROIDS B 018 DROIDS.OBJ0 A 010 FINAL B 033 PIC.FRONT PANEL A 002 V ]LOAD HELLO ]LIST 10 PRINT CHR$ (4);"MAXFILES 1" : REM " HELLO VER 1.0 1/6/86 COPYRIGHT 1986 NEOSOFT INC. ALL RIGHTS RESERVED 20 LOMEM: 38695: DIM A$,FR%(12) :TF% = 256:D$ = CHR$ (13) + CHR$ (4) 30 FOR J = 0 TO 4: READ FR%(J): NEXT : DATA 0,1236,2472,382 6,5364 40 HOME : HGR : POKE - 16300,0 : POKE - 16302,0: POKE - 1 6297,0: POKE - 16304,0: PRINT D$;"BLOAD PIC.FRONT PANEL,A$ 2000": CALL 4001 120 T1% = 249:GI% = 20736 130 PN% = 16384:PS% = PN% + 3:ME % = PS% + 3:GP% = ME% + 3:VO % = GP% + 3:WI% = VO% + 3:GK % = WI% + 3:RK% = GK% + 3:CK % = RK% + 3:ST% = CK% + 3:PP % = ST% + 3:AN% = PP% + 3 150 PRINT D$;"BLOAD DROIDS.OBJ0 " 160 PRINT D$;"BLOAD ANAL.HELMET ,A";GI%: CALL PS%,6 171 PRINT D$;"BLOAD PIC.X,A$200 0" 175 P = FR%(3) + GI%: CALL ST%, PEEK (P + 1), PEEK (P), PEEK (P + 3), PEEK (P + 2),FR%(4) 180 A$ = "You finally made itdow n here, eh?": GOSUB 300 Etc. etc. Actually, I cut the listing short at line 180 for a reason. When I boot the original disk, it displays the hi-res title screen, plays some music, then loads another hi-res screen and prints "You finally made it down here, eh?" in a little speech bubble. My non-working copy never gets that far, so that tells me that the copy protection is called somewhere in this HELLO program, before line 180. A quick check confirms that PIC.FRONT PANEL is the title screen that I'm seeing (BLOAD'd in line 40), so that points to "CALL 4001" as the first possibility for a copy protection routine. (Side note: this assembly language routine is actually saved as part of the Applesoft BASIC HELLO program. They wrote the BASIC program, then faked the program length in memory and saved it. Anything after the end of the Applesoft commands is saved as-is, loaded as-is, and can be CALL'd from BASIC. Of course it can be destroyed if you make any changes from BASIC, since Applesoft knows nothing about it, but it's great for hiding assembly language code without putting it in a separate file.) 4001 in decimal is $0FA1, so let's start there. ]CALL -151 *FA1L ; manually pushing values to the stack ; is always suspicious 0FA1- A9 0F LDA #$0F 0FA3- 48 PHA 0FA4- A9 64 LDA #$64 0FA6- 48 PHA ; save some state 0FA7- A5 08 LDA $08 0FA9- 8D D6 0F STA $0FD6 0FAC- A5 09 LDA $09 0FAE- 8D D7 0F STA $0FD7 ; simple decryption loop modifies ; $0EC5..$0FBB (which destroys the ; first part of this routine) 0FB1- A9 C5 LDA #$C5 0FB3- 85 08 STA $08 0FB5- A9 0E LDA #$0E 0FB7- 85 09 STA $09 0FB9- A9 96 LDA #$96 0FBB- 48 PHA 0FBC- A0 00 LDY #$00 0FBE- 68 PLA 0FBF- 51 08 EOR ($08),Y 0FC1- 91 08 STA ($08),Y 0FC3- 48 PHA 0FC4- C8 INY 0FC5- 98 TYA 0FC6- C9 F7 CMP #$F7 0FC8- D0 F4 BNE $0FBE 0FCA- 68 PLA ; restore state 0FCB- AD D6 0F LDA $0FD6 0FCE- 85 08 STA $08 0FD0- AD D7 0F LDA $0FD7 0FD3- 85 09 STA $09 ; and "return" to the address that was ; manually pushed onto the stack (+1) 0FD5- 60 RTS So this decrypts the code at $0EC5 and "returns" to $0F65. Since the routine just ends with an RTS, I can just run it manually to decrypt the next stage. *FA7G Now that the next stage is decrypted, let's see what we have. *F65L ; set up RWTS parameter table and use ; regular RWTS routines to seek the ; disk, presumably in preparation for ; the nibble check after that sector 0F65- 20 DF 0E JSR $0EDF ; "Engage!" (the drive motor) 0F68- AD EA C0 LDA $C0EA 0F6B- AD E9 C0 LDA $C0E9 ; check for nibble sequence 0F6E- A9 AB LDA #$AB 0F70- 8D D1 0E STA $0ED1 0F73- A9 AF LDA #$AF 0F75- 8D D0 0E STA $0ED0 0F78- 20 09 0F JSR $0F09 ; seek again 0F7B- A9 01 LDA #$01 0F7D- 8D CB 0E STA $0ECB 0F80- 20 DF 0E JSR $0EDF ; nibble check #2 0F83- AD E9 C0 LDA $C0E9 0F86- A9 04 LDA #$04 0F88- 8D 43 0F STA $0F43 0F8B- A9 AB LDA #$AB 0F8D- 8D D2 0E STA $0ED2 0F90- A9 AB LDA #$AB 0F92- 8D D1 0E STA $0ED1 0F95- A9 AB LDA #$AB 0F97- 8D D0 0E STA $0ED0 0F9A- 20 09 0F JSR $0F09 ; success path: turn off drive motor ; and exit quietly 0F9D- AD E8 C0 LDA $C0E8 0FA0- 60 RTS ; subroutine to call standard RWTS ; routine to position the drive head 0EDF- 20 E3 03 JSR $03E3 0EE2- 8C FD 0E STY $0EFD 0EE5- 8D FE 0E STA $0EFE 0EE8- A2 04 LDX #$04 0EEA- 18 CLC 0EEB- BD C5 0E LDA $0EC5,X 0EEE- 6D FD 0E ADC $0EFD 0EF1- 8D FD 0E STA $0EFD 0EF4- 90 03 BCC $0EF9 0EF6- EE FE 0E INC $0EFE 0EF9- BD CA 0E LDA $0ECA,X 0EFC- 8D 00 00 STA $0000 0EFF- CA DEX 0F00- 10 E8 BPL $0EEA 0F02- 20 E3 03 JSR $03E3 0F05- 20 D9 03 JSR $03D9 0F08- 60 RTS ; subroutine to check for a nibble ; sequence (stored in reverse at ; $0ED0..$0ED5) 0F09- AD EE C0 LDA $C0EE 0F0C- AD EC C0 LDA $C0EC 0F0F- 10 FB BPL $0F0C 0F11- C9 FF CMP #$FF 0F13- D0 F7 BNE $0F0C 0F15- AD EC C0 LDA $C0EC 0F18- 10 FB BPL $0F15 0F1A- C9 FF CMP #$FF 0F1C- D0 EE BNE $0F0C 0F1E- AD EC C0 LDA $C0EC 0F21- 10 FB BPL $0F1E 0F23- C9 FF CMP #$FF 0F25- F0 F7 BEQ $0F1E 0F27- A2 07 LDX #$07 0F29- 10 05 BPL $0F30 0F2B- AD EC C0 LDA $C0EC 0F2E- 10 FB BPL $0F2B 0F30- DD D1 0E CMP $0ED1,X 0F33- D0 D7 BNE $0F0C 0F35- CA DEX 0F36- D0 F3 BNE $0F2B 0F38- A2 02 LDX #$02 0F3A- AD EC C0 LDA $C0EC 0F3D- 10 FB BPL $0F3A 0F3F- DD CF 0E CMP $0ECF,X 0F42- D0 C8 BNE $0F0C 0F44- CA DEX 0F45- D0 F3 BNE $0F3A 0F47- 60 RTS ; The Badlands, from which there is no ; return. Turn off the drive motor, set ; interrupts, wipe all memory, and go ; into an infinite loop. At this point, ; Megabots is just not that into you. 0F48- 68 PLA 0F49- 68 PLA 0F4A- 68 PLA 0F4B- 68 PLA 0F4C- AD E8 C0 LDA $C0E8 0F4F- 78 SEI 0F50- A9 00 LDA #$00 0F52- AA TAX 0F53- 9D 65 0F STA $0F65,X 0F56- E8 INX 0F57- D0 FA BNE $0F53 0F59- 9D 53 0E STA $0E53,X 0F5C- CA DEX 0F5D- D0 FA BNE $0F59 0F5F- CE 5B 0F DEC $0F5B 0F62- 4C 59 0F JMP $0F59 The important takeaway from this: the success path for the nibble check simply returns to the caller. If it fails, the routine at $0F48 ("The Badlands") never returns. Therefore, it should be sufficient to put an RTS instruction at $0FA1 and bypass it all. You say nybble, I say nibble, let's call the whole thing off. Using my trusty Copy ][+ sector editor and "F" to follow the HELLO program, I scan for the hex sequence "A9 0F 48" (the first three opcodes at $0FA1) and find it on T19,S0D. T19,S0D,$A2 change "A9" to "60" Success! The game boots and runs without complaint. Quod erat liberandum. --------------------------------------- A 4am crack No. 18 ------------------EOF------------------