On Mon 21 Apr 2025 at 13:53:49 +0200, Didier Derny wrote: > later the dongle was officially removed the software existed in 2 version > the hard disk version (not protected) and the floppy version protected Interesting, I have not found such a version yet. (I found most versions in a file named Images.zip which was linked from Ruud on one of the vintage computer sites, but I didn't take note of the exact source unfortunately). > it's probably easier with modern logic analyser able to capture large event > the one I was using was limited to 256 captures... > but it was connected by IEEE488 to CBM3000 with a software > to trace the execution What I did was run them in Vice, and set a breakpoint on reading $E811. I knew from the page which was linked upthread that that would be cassette #1's read line, i.e. data in for the shift register. That interrupted WordCraft at the right place. I examined the code around it ant it turns out that it obfuscates the checking code, but now it was running so I could read it. After the check it gets obfuscated again. There was some self-modifying code that puts the value which is received from the dongle in some other place, and around there a EOR instruction also refers back to the dongle code. I didn't analyze that further but it is likely a tamper detection. There could be well another detection against tampering with the tamper detection. Different WordCraft versions have mostly the same code but at different addresses. A small difference is if they load 7 or 15 bits from the dongle. I also found 2 different "master" programs to make copies of WordCraft disks. One of them required a dongle (with any number except zero) and could change the serial number in the copy. But so far I have no hints that that was used for anything else than displaying it on start-up. The other program was marked "Commodore B.V." so it was from a Dutch dealer or even Commodore NL BV. There are also variations in the dialog for selecting a printer driver. There may have been separate versions for Letter QUality printers. And there is something with networking. You can select an address for the current computer, and choose between two modes (which both meant nothing to me). Here are the notes I collected about the dongle code: Dongle on cassette port E840 VIA port B bit 3 tape data out 4 tape #2 motor E84D VIA IFR $10 CB1 input from cassette #2 E810 PIA1 port A bit 4 & 5: cassette #1 & #2 sense E811 CRA CA1: cassette #1 read line E813 CRB CB2 tape #1 motor load: Cassette port Sense clockIn: Cassette port Write clockEnable: Cassette port Motor dataIn: Cassette port Read Graham lashed up a 74LS165 8 bit shift register on a piece of Veroboard wired to a connector on the tape cassette port - the PET had two such ports. The logic was simple: the software would waggle a clock line to the shift register and shift the 8 bit data in on another line. The shift register lines were tied randomly to ground or 5V providing 255 possible values (excluding zero!) This was really simple stuff but we felt it was enough - especially if the whole thing could be potted in epoxy resin so no-one could see what was going on. By the time we left Graham's place the PET was on his kitchen table with the wires and Veroboard dangling out of the back - so we called it a "dongle". void setup() { pinMode (led,OUTPUT); pinMode (load,OUTPUT); pinMode (clockEnable,OUTPUT); pinMode (clockIn,OUTPUT); pinMode (dataIn,INPUT); // ********************************************************** void readDongle() { String s = ""; // Used to hold dongle number for output as a string of bits: e.g. 10101010 byte dongle = 0; // Dongle number read from 74LS165 digitalWrite(load, LOW); // Pulse load pin delayMicroseconds(5); digitalWrite(load, HIGH); delayMicroseconds(5); digitalWrite(clockIn, HIGH); digitalWrite(clockEnable, LOW); // Has no effect because pin 15 on the 74LS165 (CLK INH) is tied low dongle = shiftIn(dataIn, clockIn, LSBFIRST); digitalWrite(clockEnable, HIGH); // Has no effect because pin 15 on the 74LS165 (CLK INH) is tied low dongleOut (dongle); // Reflect the dongle number on the 12-way connector if (dongle < 2) s = "0" + s; // Add leading zeros if (dongle < 4) s = "0" + s; if (dongle < 8) s = "0" + s; if (dongle < 16) s = "0" + s; if (dongle < 32) s = "0" + s; if (dongle < 64) s = "0" + s; if (dongle < 128) s = "0" + s; s = s + String(dongle, BIN); display2 ("DONGLE NO:", s); // Display dongle number delay (1000); oled_clearDisplay(); // Clear the display after each dongle read oled_display(); // Send memory buffer to OLED delay (250); } .C:20d4 78 SEI .C:20d5 20 AA 21 JSR $21AA decode dongle code .C:20d8 4C 9D 21 JMP $219D -> 20f5 -- decoded from here .C:20da 21 pulse tape data out ->0 -> 1 .C:20db A9 D7 LDA #$D7 %1101 0111 port A tape data out: 0 .C:20dd 8D 40 E8 STA $E840 .C:20e0 A9 DF LDA #$DF %1101 1111 port A tape data out: 1 .C:20e2 8D 40 E8 STA $E840 VIA PORT B .C:20e5 60 RTS (C:$2169) d 20e6 .C:20e6 A9 38 LDA #$38 %0011 1000 .C:20e8 8D 11 E8 STA $E811 CRA CA1 active low, irq off, DDR active .C:20eb 8E 10 E8 STX $E810 DDRA X=$3F set cassette senses to output? .C:20ee A9 3C LDA #$3C %0011 1100 make PORTA active .C:20f0 8D 11 E8 STA $E811 CRA CA1 active low .C:20f3 D0 EB BNE $20E0 always .C:20f5 78 SEI do the whole dongle reading thing .C:20f6 A2 01 LDX #$01 .C:20f8 86 03 STX $03 .C:20fa 86 7E STX $7E what bit value an active transition is (initially 1) .C:20fc 86 04 STX $04 .C:20fe 86 80 STX $80 .C:2100 CA DEX .C:2101 86 7D STX $7D .C:2103 86 7F STX $7F .C:2105 AD 11 E8 LDA $E811 PIA 1 CRA .C:2108 AD 4C E8 LDA $E84C VIA PCR .C:210b 29 EF AND #$EF .C:210d 8D 4C E8 STA $E84C VIA PCR .C:2110 A9 30 LDA #$30 .C:2112 2D 10 E8 AND $E810 PIA 1 PORT A .C:2115 C9 30 CMP #$30 .C:2117 D0 68 BNE $2181 .C:2119 A2 3F LDX #$3F .C:211b 20 E6 20 JSR $20E6 senses output, tape data 1 .C:211e A9 30 LDA #$30 .C:2120 8D 10 E8 STA $E810 PIA 1 PORT A .C:2123 20 E0 20 JSR $20E0 .C:2126 A9 00 LDA #$00 .C:2128 8D 10 E8 STA $E810 PIA 1 PORT A .C:212b A9 30 LDA #$30 .C:212d 8D 10 E8 STA $E810 PIA 1 PORT A .C:2130 06 04 ASL $04 bits^2 from cass #2 <7F 04> .C:2132 26 7F ROL $7F .C:2134 06 03 ASL $03 bits^2 from cass #1 <7D 03> .C:2136 26 7D ROL $7D .C:2138 B0 42 /--BCS $217C if an 1 comes out we have all bits .C:213a 20 DB 20 | JSR $20DB pulse tape data out signal .C:213d AD 11 E8 | LDA $E811 PIA 1 CRA .C:2140 10 0E |/-BPL $2150 positive when CA1 had no active transition (cass 1 read line) .C:2142 49 02 | EOR #$02 active transition switch .C:2144 8D 11 E8 | STA $E811 PIA 1 CRA .C:2147 AD 10 E8 | LDA $E810 PIA 1 PORT A/DDR A .C:214a A5 7E | LDA $7E .C:214c 49 01 | EOR #$01 toggle which value is represented by active transn. .C:214e 85 7E | STA $7E bits from cass #1 .C:2150 AD 4D E8 ->LDA $E84D VIA IFR .C:2153 29 10 | AND #$10 CB1 interrupt bit, input from cassette #2 .C:2155 F0 0C /-BEQ $2163 when input from cassette #2 inactive .C:2157 4D 4C E8 | EOR $E84C VIA PCR .C:215a 8D 4C E8 | STA $E84C VIA PCR .C:215d A5 80 | LDA $80 .C:215f 49 01 | EOR #$01 .C:2161 85 80 | STA $80 bits from cass #2 .C:2163 A5 04 ->LDA $04 .C:2165 05 80 | ORA $80 .C:2167 85 04 | STA $04 .C:2169 A5 03 LDA $03 .C:216b 05 7E ORA $7E bits from cass #1 .C:216d 85 03 STA $03 bits^2 from cass #1 .C:216f 4C 30 21 JMP $2130 .C:2172 84 03 | STY $03 4 -> 3 copy data from dongle #2 to #1 .C:2174 A9 00 | LDA #$00 .C:2176 85 04 STA $04 and wipe its source .C:2178 A5 7F LDA $7F 7F -> 7D .C:217a 85 7D | STA $7D | have got all bits from the shift register .C:217c A2 0F \->LDX #$0F .C:217e 20 E6 20 JSR $20E6 senses output, tape data 1 .C:2181 A4 7D LDY $7D do something with input from cass #1 <7D 03> .C:2183 8C 67 0F STY $0F67 MODIFYING CODE! : EOR #$D2 .C:2186 98 TYA .C:2187 49 D2 EOR #$D2 $7D expected to be #$D2? (hi) .C:2189 D0 06 /-BNE $2191 .C:218b A5 03 | LDA $03 .C:218d 49 10 | EOR #$10 .C:218f F0 09 | BEQ $219A $03 expected to be #$10? (lo) .C:2191 A4 04 ->LDY $04 .C:2193 D0 DD BNE $2172 a dongle present in cass #2? check failed .C:2195 A9 02 LDA #$02 JAM opcode .C:2197 8D 47 10 STA $1047 MODIFYING CODE! get there when you press STOP .C:219a 4C AA 21 JMP $21AA -- re-encrypt the dongle code .C:219d 20 F5 20 JSR $20F5 -- do the reading thing again -- decode up to here .C:21a0 D0 57 BNE $21F9 .C:21a2 A4 1C LDY $1C .C:21a4 8C D6 22 STY $22D6 .C:21a7 4C F9 21 JMP $21F9 .C:21aa 48 PHA decode dongle code .C:21ab A2 C5 LDX #$C5 .C:21ad 8A TXA A=C5 .C:21ae 18 CLC .C:21af 69 FE ADC #$FE A=X-2=C3 .C:21b1 5D DA 20 EOR $20DA,X Decode some code?, high 219f .C:21b4 9D DA 20 STA $20DA,X The code that does the checking... .C:21b7 CA DEX .C:21b8 D0 F3 BNE $21AD .C:21ba 58 CLI .C:21bb 68 PLA .C:21bc 60 RTS ... .C:2284 A9 00 LDA #$00 .C:2286 8D F0 FF STA $FFF0 8096 version .C:2289 A2 FF LDX #$FF .C:228b 78 SEI .C:228c 9A TXS .C:228d 20 16 FD JSR $FD16 .C:2290 A9 93 LDA #$93 .C:2292 8D 6F 02 STA $026F .C:2295 A9 83 LDA #$83 .C:2297 8D 70 02 STA $0270 .C:229a A9 02 LDA #$02 .C:229c 85 9E STA $9E .C:229e 4C 1E FD JMP $FD1E .C:22a1 C9 F0 CMP #$F0 .C:22a3 F0 30 BEQ $22D5 .C:22a5 A2 1F LDX #$1F .C:22a7 A9 00 LDA #$00 .C:22a9 9D 1F 03 STA $031F,X .C:22ac CA DEX .C:22ad 10 FA BPL $22A9 .C:22af A2 21 LDX #$21 .C:22b1 9D 01 04 STA $0401,X .C:22b4 CA DEX .C:22b5 10 FA BPL $22B1 .C:22b7 8E 21 03 STX $0321 .C:22ba A5 80 LDA $80 .C:22bc C9 FC CMP #$FC .C:22be D0 04 BNE $22C4 .C:22c0 A9 30 LDA #$30 .C:22c2 85 80 STA $80 .C:22c4 B1 30 LDA ($30),Y .C:22c6 C9 60 CMP #$60 .C:22c8 F0 0B BEQ $22D5 .C:22ca C9 2C CMP #$2C .C:22cc D0 13 BNE $22E1 .C:22ce C8 INY .C:22cf 06 80 ASL $80 .C:22d1 06 80 ASL $80 .C:22d3 D0 E5 BNE $22BA .C:22d5 A9 00 LDA #$00 <- constant modified by dongle code above .C:22d7 85 1C STA $1C .C:22d9 A9 01 LDA #$01 .C:22db 8D D6 22 STA $22D6 .C:22de 6C 32 00 JMP ($0032) -Olaf. -- ___ Olaf 'Rhialto' Seibert <rhialto/at/falu.nl> \X/ There is no AI. There is just someone else's work. --I. Rose
Archive generated by hypermail 2.4.0.