Confusion Musicdisk

Started by Asle, March 30, 2014, 13:51:53

Previous topic - Next topic

Asle

I need help this time.
The production Music Disk by Confusion.

The NDOS disk contains several Crunchmania Address exe subfiles. If you overlook the DOS Copy issue, affecting the 4th subfile, all others decrunch correctly. However, once decrunched, the file containing musics have some sort of encryption on the pattern data.

I've attached one of these files.

I've checked the memory little, but it doesn't help. The patterns _seem_ to be decrypted somewhere but with another form of encryption. Well, as far as I could tell ...

Last, I'm quite sure it encrypted and not packed as the pattern data size (protracker wise) is as expected according to the patternlist. It's not shorter nor longer.

Anyway, if someone has an idea on how to proceed from here, I'd welcome hints :)

rogue

#1
Hi Asle, are you still working on this one? I wanted to take a look at this earlier but real life kicked in in multiple unavoidable ways. Better late than never I hope.

I also examined memory and replay code with UAE debugger and I can confirm what you already know. The tunes are perfect Protracker modules, except that the pattern data (and only the pattern data) looks like garbage. Ok, there is also a curious "K.M." tag in place of the normal "M.K." tag. I dumped the entire memory and looked for anything that resembles pattern data, but there is no such thing in memory.

What I found interesting however is that the replay code looks also perfectly normal for Protracker: it picks the sample number, period and effect from their usual locations in memory. I experimented with breakpoints and memory dumps, and behold: a single line of the pattern data is decrypted in place for playback, and encrypted immediately after use again. At $00123b30 there seems to be code which reads the pattern data (pattern data base address is @a0, current offset from base is @d1). So I put a breakpoint there and investigated pattern data in memory.

>f 123b30
Breakpoint added
>g
Breakpoint at 00123B30
D0: 00000004 D1: 00000a30 D2: 00000004 D3: 00000008
D4: 00000010 D5: 00000020 D6: 00000040 D7: 00000080
A0: 0014843c A1: 00121a20 A2: 001483b8 A3: 0014800c
A4: 00148b66 A5: 00dff0a0 A6: 001249b6 A7: 000fff86
USP=0011fffc ISP=000fff86 MSP=00000000 VBR=00000000
T=00 S=1 M=0 X=0 N=0 Z=1 V=0 C=0 IMASK=3
FP0: 0 FP1: 0 FP2: 0 FP3: 0
FP4: 0 FP5: 0 FP6: 0 FP7: 0
N=0 Z=0 I=0 NAN=0
00123b30: 4a96 6604 6100 02e4 2cb0 TST.L (A6)
next PC: 00123b32

I then dump pattern data at base + offset, or $14843c + $a30 = $148e6c. 16 bytes per pattern line (4 channels * 4 bytes per channel). Dump three times after stepping the module forward three divisions (4 break + go rounds each, as there are 4 channels). See how nicely the pattern data comes and goes:

; round N
>m 148e6c
00148e6c 0000 0000 0000 0000 0000 0000 0000 0000  ................ <-- currently playing this line
00148e7c ff7a 3c1d 09b4 222d 0814 a0ad 0800 cebd  .z<..."-........
00148e8c 0966 700d d2bc 0098 9680 5380 4a80 6e08  .fp.......S.J.n.

; round N+4 (1 round for each channel)
>m 148e6c
00148e6c 7400 2c6d 0170 41ed 09b4 43ed 09b8 4eae  t.,m.pA...C...N.
00148e7c 00d6 1c30 0000 0000 01ac 3000 01ac 5c10  ...0......0...\. <-- currently playing this line
00148e8c 0966 700d d2bc 0098 9680 5380 4a80 6e08  .fp.......S.J.n.

; round N+8
>m 148e6c
00148e6c 7400 2c6d 0170 41ed 09b4 43ed 09b8 4eae  t.,m.pA...C...N.
00148e7c ff7a 3c1d 09b4 222d 0814 a0ad 0800 cebd  .z<..."-........
00148e8c 00d6 1c05 0000 0000 0000 0000 0000 0000  ................ <-- currently playing this line


I have yet to find and isolate the decryption code however. Perhaps it is easier to inject some extra code to copy decrypted pattern data into some stash and just overwrite the pattern data from the tunes you already ripped. l'll try to locate the decryption code with memory write watch first and see if it makes any sense.

Edit: clarified a little

rogue

#2
Well the encryption turned out to be trivial after all. Although - it was not broken for 20 years so I suppose it was more than adequate for its intended purpose.  :)

Using a memory write watch on pattern data with UAE debugger, the decoder function was found. Put a watch on pattern 0 note 0:

>w 1 14843c 10 w
1: 0014843C - 0014844B (16) W

Wait for that pattern/note to be played and the write trips the watch:

>g
Memwatch 1: break at 0014843C.L W 01FC1A0F
D0: 225160e4 D1: 00000000 D2: 00000004 D3: 00000008
D4: 00000010 D5: 00000020 D6: 00000040 D7: 00000080
A0: 00148440 A1: 001217e4 A2: 0012390c A3: 0011fff4
A4: 0011fff4 A5: 0012c884 A6: 00000000 A7: 000fffba
USP=0011fffc ISP=000fffba MSP=00000000 VBR=00000000
T=00 S=1 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=3
FP0: 0 FP1: 0 FP2: 0 FP3: 0
FP4: 0 FP5: 0 FP6: 0 FP7: 0
N=0 Z=0 I=0 NAN=0
00120a12: 2019 b198 2019 b198 2019 MOVE.L (A1)+,D0
next PC: 00120a14

Disassemble, starting a little before that:

>d 1209dc
1001209dc: 1039 0012 09be 4880 41f9 MOVE.B $001209be,D0
1001209e2: 4880 41f9 0014 83b8 1030 EXT.W D0
1001209e4: 41f9 0014 83b8 1030 0000 LEA.L $001483b8,A0
1001209ea: 1030 0000 4880 41f9 0014 MOVE.B (A0, D0.W*1, $00) == $0014e524,D0
1001209ee: 4880 41f9 0014 843c c0fc EXT.W D0
1001209f0: 41f9 0014 843c c0fc 0400 LEA.L $0014843c,A0
1001209f6: c0fc 0400 d0c0 d0f9 0012 MULU.W #$0400,D0
1001209fa: d0c0 d0f9 0012 09c2 43f9 ADDA.W D0,A0
1001209fc: d0f9 0012 09c2 43f9 0012 ADDA.W $001209c2,A0
100120a02: 43f9 0012 17e0 d2f9 0012 LEA.L $001217e0,A1
>d
100120a08: d2f9 0012 09c2 2019 b198 ADDA.W $001209c2,A1
100120a0e: 2019 b198 2019 b198 2019 MOVE.L (A1)+,D0
100120a10: b198 2019 b198 2019 b198 EOR.L D0,(A0)+
100120a12: 2019 b198 2019 b198 2019 MOVE.L (A1)+,D0
100120a14: b198 2019 b198 2019 b198 EOR.L D0,(A0)+
100120a16: 2019 b198 2019 b198 4e75 MOVE.L (A1)+,D0
100120a18: b198 2019 b198 4e75 0001 EOR.L D0,(A0)+
100120a1a: 2019 b198 4e75 0001 2a7c MOVE.L (A1)+,D0
100120a1c: b198 4e75 0001 2a7c 0017 EOR.L D0,(A0)+
100120a1e: 4e75 0001 2a7c 0017 5d90 RTS.L

As you can see this is just a XOR, and some analysis reveals that the encryption key is the same length as pattern data (1024 bytes). The key is at $1217e0, which by the way is code - I really like this product! :) So, to decode, save the key to file named "key" with debugger:

>S key 1217e0 400

And XOR it with each pattern. I wrote a simple C program to do this (attached with the key). Just build with any Linux/BSD/whatever Unix-like machine and run on the ripped modules like this:

./unconfuse mod.x mod.lost ...

I'll FTP the decoded mods separately anyway so you don't need to touch my icky code.

Asle

mman.h: no such file or directory :)

But man, woaw, very nice !

Asle

Thanks for sending the musics ! You're outstanding !

I've run it on the disk rip files and it's working like a charm. You're great my friend :)
I've attached the result, including the intro music that was not encrypted.
In the end, remains the one music inside the archive that is corrupted by DOScopy thing. New disk image wanted :D

Thanks again for your extremely great effort on this thing. Wouldn't have ever found a 1024 key ;)