----------------EduCalc---------------- A 4am crack 2015-02-11 --------------------------------------- Name: EduCalc Genre: educational Year: 1985 Credits: Created by Intentional Educations Written by Francis Gerard Power with Bob Stickgold, Susan Christie Thomas, Kathleen DeBoer, and George Sullivan Programmed by Yen-Ching Chu, Shih-San Chen, Chi-Ren Chang, Katharine Lloyd, Eric Andersen, and Chau-Wen Tseng Publisher: Grolier Publishing Media: double-sided 5.25-inch floppy OS: Diversi-DOS Other versions: none (preserved here for the first time) Identical cracks: Classifying Animals With Backbones (4am crack no. 204) Both sides are bootable. I'll start with side A. ~ Chapter 0 In Which Various Automated Tools Fail In Interesting Ways COPYA no errors, but the copy hangs on boot Locksmith Fast Disk Backup ditto EDD 4 bit copy (no sync, no count) ditto Copy ][+ nibble editor nothing suspicious Disk Fixer T00,S00 -> standard DOS 3.3 boot0 T00-02 -> looks like DOS 3.3 T01,S09 -> startup program is blank?! T11 -> DOS 3.3 disk catalog Why didn't any of my copies work? probably a nibble check during boot Next steps: 1. Capture bootloader with AUTOTRACE 2. Find nibble check and disable it 3. There is no step 3 ~ Chapter 1 In Which We Have A Few False Starts, Then Our Adventure Begins In Earnest [S6,D1=original disk] [S5,D1=my work disk] ]PR#5 ... CAPTURING BOOT0 ...reboots slot 6... ...reboots slot 5... SAVING BOOT0 CAPTURING BOOT1 ...reboots slot 6... ...reboots slot 5... SAVING BOOT1 SAVING RWTS ]CATALOG,S6,D1 ]CATALOG,S6,D1 C1983 DSR^C#254 308 FREE *A 002 HELLO *B 004 ASCII.CHR *B 005 IENPB.GROL/CALC *B 041 TUT.OVR *B 045 EDUMAIN *B 045 LEARN *B 005 QUIT.OVR *B 013 TEMPLEARN *B 012 OPENING.OVR ]RUN HELLO ?SYNTAX ERROR IN 43446 ]LIST 43446 M INPUT ROT= HOME PR# q q HOME INVERSE DRAW a 60406 FLASH OUT OF MEMORY LEFT$ ATN CHR$ HGR2 FORMULA TOO COMPL EX TYPE MISMATCH ATN OUT OF MEMORY XDRAW LIST NEW SPC( SPEED= TO - RUN TAB( STEP OR > INT SIN RESUME RESUME NEW TRACE ABS HGR CLEAR FLASH &z PRINT RECALL POKE LET ON USR NOT TAB( LOMEM: / IF IF CONT VTAB IF LOMEM: RUN TO TAN ATN ASC BREAK Hmm. Either this is an intentional dead end, or something in the original DOS is required to read it. Let's back up. ]BLOAD BOOT1,A$2600,S5,D1 ]CALL -151 *FE89G FE93G *B600<2600.2FFFM *B700L . . nothing unusual, until... . B738- 20 03 BB JSR $BB03 *BB03L BB03- 4E 06 BB LSR $BB06 Uh oh. Self-modifying code. The 6502 processor has no instruction cache, so one instruction can literally change the next instruction in memory, and the CPU will execute the new instruction. Which is what's happening here. ~ Chapter 2 In Which We Learn The True Meaning Of Patience To capture this self-modifying code, I need to reproduce the modifications without running the modified code. I'll start with a pristine copy (at $2B00), copy it into place (at $BB00), then reproduce the modifications and inspect the results. Lather, rinse, repeat. 2000- A0 00 LDY #$00 2002- B9 00 2B LDA $2B00,Y 2005- 99 00 BB STA $BB00,Y 2008- C8 INY 2009- D0 F7 BNE $2002 200B- 4E 06 BB LSR $BB06 200E- 60 RTS *2000G *BB03L BB03- 4E 06 BB LSR $BB06 BB06- 38 SEC BB07- 6E 0A BB ROR $BB0A More self-modifying code. *200E:38 6E 0A BB 60 *2000G *BB0AL BB0A- A0 27 LDY #$27 BB0C- 6E 0F BB ROR $BB0F More. *2012:A0 27 6E 0F BB 60 *2000G *BB0FL BB0F- 6E 1B BB ROR $BB1B BB12- 6E 15 BB ROR $BB15 More. *2017:6E 1B BB 6E 15 BB 60 *2000G *BB15L BB15- 6E 1E BB ROR $BB1E BB18- 6E 25 BB ROR $BB25 BB1B- B9 00 BB LDA $BB00,Y More. *201D:6E 1E BB 6E 25 BB B9 00 BB 60 *2000G *BB1EL BB1E- 59 00 B8 EOR $B800,Y BB21- 99 00 BB STA $BB00,Y BB24- C8 INY BB25- D0 F4 BNE $BB1B More, now using the page at $B800 as an encryption key. *2026:59 00 B8 99 00 BB C8 D0 F4 60 *2000G *BB27L BB27- A0 55 LDY #$55 BB29- B9 00 BC LDA $BC00,Y BB2C- 59 00 B8 EOR $B800,Y BB2F- 99 00 BC STA $BC00,Y BB32- 88 DEY BB33- 10 F4 BPL $BB29 More. *202F:A0 55 B9 00 BC 59 00 B8 99 00 BC 88 10 F4 60 *2000G *BB35L Finally some real code. ; cover our tracks in memory (overwrite ; the call to $BB03) BB35- A9 93 LDA #$93 BB37- 8D 39 B7 STA $B739 BB3A- A9 B7 LDA #$B7 BB3C- 8D 3A B7 STA $B73A ; push an address to the stack BB3F- A9 B5 LDA #$B5 BB41- 48 PHA BB42- A9 18 LDA #$18 BB44- 48 PHA ; save some other values on the stack BB45- AD EC B7 LDA $B7EC BB48- 48 PHA BB49- AD ED B7 LDA $B7ED BB4C- 48 PHA ; set up an RWTS read BB4D- A9 00 LDA #$00 BB4F- 8D EC B7 STA $B7EC BB52- A9 06 LDA #$06 BB54- 8D ED B7 STA $B7ED BB57- A9 01 LDA #$01 BB59- 8D F4 B7 STA $B7F4 ; $BB00 is going to get overwritten by ; the RWTS (it's used as scratch space) ; so this relocates the rest of the ; copy protection routine to as-yet- ; unused memory BB5C- A0 00 LDY #$00 BB5E- B9 6A BB LDA $BB6A,Y BB61- 99 00 B4 STA $B400,Y BB64- C8 INY BB65- D0 F7 BNE $BB5E BB67- 4C 00 B4 JMP $B400 *B400 and hangs until you press something else. That part is skipped for now, but I'm guessing it's called later. Location | Description | Value -------------+------------------+------ $B474 | length of data | $03 $B475/$B476 | starting address | $A502 $B477..$B479 | data The 3 bytes at $B477 end up at $A503, which is the tail end of the RUN entry point. It's just a JMP to the code that was just patched earlier: A503- 4C 36 9E JMP $9E36 Thus, trying to break to the prompt during boot will hang until you press something else. (Even if you did manage to get to the prompt, the RUN flag would ensure you couldn't do anything useful. Defense in depth!) Location | Description | Value -------------+------------------+------ $B47A | length of data | $30 $B47B/$B47C | starting address | $B749 $B47D..$B4AC | data The $30 bytes at $B47D end up at $B74A, which is normally the part of the disk initialization routine that writes DOS to a freshly initialized disk. The new code looks like this: B74A- 60 RTS B74B- A0 20 LDY #$20 B74D- B9 59 B7 LDA $B759,Y B750- 99 00 03 STA $0300,Y B753- 88 DEY B754- 10 F7 BPL $B74D B756- 4C 00 03 JMP $0300 B759- A9 BF LDA #$BF B75B- 85 01 STA $01 B75D- A0 00 LDY #$00 B75F- 84 00 STY $00 B761- 91 00 STA ($00),Y B763- C8 INY B764- D0 FB BNE $B761 B766- C6 01 DEC $01 B768- A5 01 LDA $01 B76A- C9 08 CMP #$08 B76C- B0 F3 BCS $B761 B76E- AD 81 C0 LDA $C081 B771- 20 93 FE JSR $FE93 B774- 20 89 FE JSR $FE89 B777- 4C 00 E0 JMP $E000 Looks like this is going to be The Badlands routine that wipes main memory and exits. Location | Description | Value -------------+------------------+------ $B4AD | length of data | $01 $B4AE/$B4AF | starting address | $B7C1 $B4B0 | data | $60 This puts an RTS instruction at $B7C2, which would normally set up the RWTS parameters for writing DOS after INIT. Location | Description | Value -------------+------------------+------ $B4B1 | length of data | $03 $B4B2/$B4B3 | starting address | $9E72 $B4B4..$B4B6 | data This modifies DOS's image of the page 3 jump vectors so that will jump to $B74B, a.k.a. The Badlands. Location | Description | Value -------------+------------------+------ $B4B7 | length of data | $02 $B4B8/$B4B9 | starting address | $A396 $B4BA..$B4BB | data | 18 60 This patch neutralizes the SAVE handler at $A397 so it does nothing but claims to have succeeded. Location | Description | Value -------------+------------------+------ $B4BC | length of data | $03 $B4BD/$B4BE | starting address | $A38A $B4BF..$B4C1 | data This patch adds a "JMP $A582" to the end of the BLOAD command handler that starts at $A35D. Location | Description | Value -------------+------------------+------ $B4C2 | length of data | $32 $B4C3/$B4C4 | starting address | $A57E $B4C5..$B4F6 | data The $32 bytes at $B4C5 end up at $A57F, where they look like this: A57F- 4C 84 9D JMP $9D84 A582- 20 71 A4 JSR $A471 A585- A5 68 LDA $68 A587- 48 PHA A588- A5 67 LDA $67 A58A- 48 PHA A58B- 38 SEC A58C- AE 61 AA LDX $AA61 A58F- AC 60 AA LDY $AA60 A592- D0 01 BNE $A595 A594- CA DEX A595- 88 DEY A596- 8A TXA A597- E8 INX A598- 6D 73 AA ADC $AA73 A59B- 85 68 STA $68 A59D- AD 72 AA LDA $AA72 A5A0- 85 67 STA $67 A5A2- C6 68 DEC $68 A5A4- 20 BC A3 JSR $A3BC A5A7- CA DEX A5A8- D0 F8 BNE $A5A2 A5AA- 68 PLA A5AB- 85 67 STA $67 A5AD- 68 PLA A5AE- 85 68 STA $68 A5B0- 60 RTS The previous patch set up a jump to $A582 at the end of the BLOAD handler. It looks like this is reusing the on-the-fly decryption routine at $A3BC (already used for Applesoft programs) for binary programs as well. Encrypt all the things! Location | Description | Value -------------+------------------+------ $B4F7 | length of data | $02 $B4F8/$B4F9 | starting address | $A351 $B4FA..$B4FB | data | 9A A3 This sets up a jump to $A39A in the middle of the BSAVE command handler. Location | Description | Value -------------+------------------+------ $B4FC | length of data | $02 $B4FD/$B4FE | starting address | $A35A $B4FF..$B500 | data | A6 A3 This sets up a jump to $A3A6 at the end of the BSAVE command handler. Location | Description | Value -------------+------------------+------ $B501 | length of data | $15 $B502/$B503 | starting address | $A396 $B504..$B518 | data The $15 bytes at $B504 end up at $A397, overwriting the SAVE command handler. They look like this: A397- EA NOP A398- 18 CLC A399- 60 RTS A39A- 8D 61 AA STA $AA61 A39D- 8C 60 AA STY $AA60 A3A0- 20 E0 A3 JSR $A3E0 A3A3- 4C 85 A5 JMP $A585 A3A6- 20 FF A3 JSR $A3FF A3A9- 4C 85 A5 JMP $A585 It looks like this *encrypts* binary files on-the-fly. One branch of the BSAVE handler jumps to $A39A; the other jumps to $A3A6. The latter routes the data in memory through the routine at $A3FF, which serves as both an encryption and decryption routine (it's just XOR after all). That's it. The next byte is $00, so the BEQ at $B583 branches and the patch loop exits gracefully via RTS. The result is a really messed up DOS that is maximally unfriendly to prying eyes and maximally incompatible with any other version of DOS. It decrypts both BASIC and binary files on the fly, traps , traps , sets the RUN flag, and disables the SAVE command. It does not, however, hinder copying the disk itself. The only patch I need to bypass the copy protection is at $BB03, to unconditionally push $B5/$18 to the stack and jump to $B793. BB03- A9 B5 LDA #$B5 BB05- 48 PHA BB06- A9 18 LDA #$18 BB08- 48 PHA BB09- 4C 93 B7 JMP $B793 T00,S05,$03 change "4E 06 BB 71 6E 0A BB 40 27" to "A9 B5 48 A9 18 48 4C 93 B7" Side B has identical protection. Quod erat liberandum. --------------------------------------- A 4am crack No. 220 ------------------EOF------------------