Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - rogue

Pages: [1]
Ripping Amiga music / Re: Up Rough musicdisks
« on: March 20, 2015, 18:11:04 »
Great! I am really happy to hear that.

I must say I do miss the good old days and hacking with UAE is like a time machine. And it also help make my tiny contribution to the awesome AMP. Now, I go back optimizing my 68000 mandelbrot code, see you again in next music disk!
Ripping Amiga music / Re: Up Rough musicdisks
« on: March 19, 2015, 16:57:11 »
I saved all the modules of up-ep003 with 's' key and the compared to files decrypted with the tool. Each of the 5 modules was identical. Maybe the old AMP files were obtained from some other source, or maybe ripped with something like ProWizard from memory?
Ripping Amiga music / Re: Up Rough musicdisks
« on: March 18, 2015, 18:52:24 »
You're welcome, and I'm happy to hear the tool gets some serious action right away. :)

But I'm confused about the 's' function now. I ran my tool on one of the encrypted modules and got one file, then saved the same module with 's' command. I did bit-by-bit comparison and the files were identical. Or did I just manage to pick a module which is not affected by clearing the first 4 bytes (and shouldn't that be 2 bytes if we are talking about the repeat info)?
Ripping Amiga music / Re: Up Rough musicdisks
« on: March 17, 2015, 00:34:06 »
The 'save' feature saves from memory or converts from disk ? I'd say from memory since it saves the "current" music.

Hmm. I wonder - if you can't tell the difference, does it really, really matter? I will show you that in this case they are the same, but as you probably won't believe me without seeing the disk rip decoder yourself, we will go the hard way. :) So, let us begin.

I was able to locate the decryption (or perhaps just descrambling or decoding) code with UAE by using breakpoints to intercept dos.library Read() calls and examining what happens next in the code. This turned out to be both easy and fruitful, as the program immediately decodes the file after loading. With disassembler I saw a call to subroutine that does some odd bit fiddling with the loaded data. It looked promising so I ran it to completion and the end result was decoded file in the same memory location. Yay! Below is the decoder for your viewing pleasure. It is called with the address of loaded data in registers a0 and a1, and the length of the loaded data in d0.

Code: [Select]
4005acb8: 48e7 7ff0 41f0 0800 43f1 MVMLE.L #$7ff0,-(A7)
4005acbc: 41f0 0800 43f1 0800 45f9 LEA.L (A0, D0.L*1, $00) == $400cc6e1,A0
4005acc0: 43f1 0800 45f9 4005 f350 LEA.L (A1, D0.L*1, $00) == $400cc6e1,A1
4005acc4: 45f9 4005 f350 47f9 4005 LEA.L $4005f350,A2
4005acca: 47f9 4005 f394 7227 740d LEA.L $4005f394,A3
4005acd0: 7227 740d 760d 2e00 1821 MOVE.L #$00000027,D1
4005acd2: 740d 760d 2e00 1821 1a32 MOVE.L #$0000000d,D2
4005acd4: 760d 2e00 1821 1a32 1800 MOVE.L #$0000000d,D3
4005acd6: 2e00 1821 1a32 1800 1433 MOVE.L D0,D7
4005acd8: 1821 1a32 1800 1433 2800 MOVE.B -(A1),D4
4005acda: 1a32 1800 1433 2800 bb04 MOVE.B (A2, D1.L*1, $00) == $400cc6e1,D5
4005acde: 1433 2800 bb04 1633 3800 MOVE.B (A3, D2.L*1, $00) == $5008cef1,D2
4005ace2: bb04 1633 3800 1104 b902 EOR.B D5,D4
4005ace4: 1633 3800 1104 b902 b903 MOVE.B (A3, D3.L*1, $00) == $40069001,D3
4005ace8: 1104 b902 b903 0202 003f MOVE.B D4,-(A0)
4005acea: b902 b903 0202 003f e40b EOR.B D4,D2
4005acec: b903 0202 003f e40b 1202 EOR.B D4,D3
4005acee: 0202 003f e40b 1202 b701 AND.B #$3f,D2
4005acf2: e40b 1202 b701 5387 66dc LSR.B #$00000002,D3
4005acf4: 1202 b701 5387 66dc 43f9 MOVE.B D2,D1
4005acf6: b701 5387 66dc 43f9 4005 EOR.B D3,D1
4005acf8: 5387 66dc 43f9 4005 f348 SUB.L #$00000001,D7
4005acfa: 66dc 43f9 4005 f348 7200 BNE.B #$ffffffffffffffdc == 4005acd8 (TRUE)
4005acfc: 43f9 4005 f348 7200 740d LEA.L $4005f348,A1
4005ad02: 7200 740d 760d 7800 7a00 MOVE.L #$00000000,D1
4005ad04: 740d 760d 7800 7a00 7c00 MOVE.L #$0000000d,D2
4005ad06: 760d 7800 7a00 7c00 5380 MOVE.L #$0000000d,D3
4005ad08: 7800 7a00 7c00 5380 1c10 MOVE.L #$00000000,D4
4005ad0a: 7a00 7c00 5380 1c10 1e06 MOVE.L #$00000000,D5
4005ad0c: 7c00 5380 1c10 1e06 ccf1 MOVE.L #$00000000,D6
4005ad0e: 5380 1c10 1e06 ccf1 4800 SUB.L #$00000001,D0
4005ad10: 1c10 1e06 ccf1 4800 da06 MOVE.B (A0),D6
4005ad12: 1e06 ccf1 4800 da06 1c32 MOVE.B D6,D7
4005ad14: ccf1 4800 da06 1c32 1800 MULU.W (A1, D4.L*1, $00) == $400d67f4,D6
4005ad18: da06 1c32 1800 5404 bd07 ADD.B D6,D5
4005ad1a: 1c32 1800 5404 bd07 10c7 MOVE.B (A2, D1.L*1, $00) == $400cc6e1,D6
4005ad1e: 5404 bd07 10c7 0204 0006 ADD.B #$00000002,D4
4005ad20: bd07 10c7 0204 0006 1433 EOR.B D6,D7
4005ad22: 10c7 0204 0006 1433 2800 MOVE.B D7,(A0)+
4005ad24: 0204 0006 1433 2800 7c00 AND.B #$06,D4
4005ad28: 1433 2800 7c00 1633 3800 MOVE.B (A3, D2.L*1, $00) == $5008cef1,D2
4005ad2c: 7c00 1633 3800 bf02 bf03 MOVE.L #$00000000,D6
4005ad2e: 1633 3800 bf02 bf03 0202 MOVE.B (A3, D3.L*1, $00) == $40069001,D3
4005ad32: bf02 bf03 0202 003f e40b EOR.B D7,D2
4005ad34: bf03 0202 003f e40b 1202 EOR.B D7,D3
4005ad36: 0202 003f e40b 1202 b701 AND.B #$3f,D2
4005ad3a: e40b 1202 b701 5380 66cc LSR.B #$00000002,D3
4005ad3c: 1202 b701 5380 66cc 7001 MOVE.B D2,D1
4005ad3e: b701 5380 66cc 7001 ba10 EOR.B D3,D1
4005ad40: 5380 66cc 7001 ba10 6702 SUB.L #$00000001,D0
4005ad42: 66cc 7001 ba10 6702 7000 BNE.B #$ffffffffffffffcc == 4005ad10 (TRUE)
4005ad44: 7001 ba10 6702 7000 4cdf MOVE.L #$00000001,D0
4005ad46: ba10 6702 7000 4cdf 0ffe CMP.B (A0),D5
4005ad48: 6702 7000 4cdf 0ffe 4e75 BEQ.B #$00000002 == 4005ad4c (FALSE)
4005ad4a: 7000 4cdf 0ffe 4e75 4e71 MOVE.L #$00000000,D0
4005ad4c: 4cdf 0ffe 4e75 4e71 4eb9 MVMEL.L #$0ffe,(A7)+
4005ad50: 4e75 4e71 4eb9 4005 f3e8 RTS.L

As you can see the code refers to a decoding key at address $4005f350 (attached as file 4005f350). In the same spirit as the venerable Confusion music disk, the key is just program code, not really a separate key at all. But this time the algorithm is much more complex than just basic XOR. I am not sure about the length of the key. Since it is indexed with a byte offset both from beginning and offset 0x44, the total offset should never be more than 0x143. I just dumped 512 bytes of memory and that seems to be enough. Since the key is part of EP code, it is the same for all disks.

Also, there is a small table used for multiplications at $4005f348 (attached as file 4005f348). Based on this saved information, it is possible to write a decoder even without understanding the decoder function at all. Just extract the code and run it on input data using the key and table. I wrote a simple C language emulator for the disassembly above and a CLI frontend to load files, call the decoder and save decoder file. (Attached as unuprough.c, key.h and Makefile). Again, just build it and run it on the encoded module files like this:
Code: [Select]
./unuprough module01.up module02.up ...
The output file name is generated by concatenating strings "mod." and whatever is in the beginning of the decoded file. This works for Protracker mods, but some modules are in different format (AHX at least, perhaps others) and these files will get random file names. Perhaps it is better to decode them one at time and rename the random name manually.

Now that we can decode the disk rips, we can also verify that the files obtained by the "s" command are identical. :)

P.S. in my earlier message I made a mistake - the encoded file is not shorter than the original, instead it is always 1 byte longer.
P.P.S. I think I just learned something about myself... I'll throw myself at any crazy impulse challenge you post here... and really enjoy that. :)
Ripping Amiga music / Re: Up Rough musicdisks
« on: March 08, 2015, 18:15:26 »
Ah, more encrypted mods! This is excellent news, it has been a while...

What kind of problems exactly you had? I took a look at this and created a new UAE A4000 instance. First I did a fresh install of Workbench 3.1 on a harddisk image file. I then copied C= installer from Aminet into C: and ran the provided install script. (Man, the post-2000 musicdisk world is different from what it used to be - where is the track loader, for instance? What, no lack of memory allocation? No decompression to fixed memory address? Heck you can even exit these ones!)

The installer seems to be a bit broken, you need to manually fix some file protection settings once the install is complete:
Code: [Select]
protect EP:start +s
protect EP:prefs +s
protect EP:EP +e

After that you can run "start". I got a warning message
Code: [Select]
Couldn't find the file "ENV:sys/ahi/prefs"! but this does not seem to matter. In the prefs you need to select a screenmode and EP dir (for this particular one it should be EP:EPs/blowme!morehitsforkids. Save the prefs and click Start, and the musicdisk runs just fine for me. And it can save the modules if you press "s".

I guess the authors realized the futility of encryption - after all there are people like us in the world.  :) We could of course crack it just for sport, but I am sure manually saving the modules is more efficient. Or maybe even asking the authors for originals. :)

I suggest you make sure you are using a harddisk image file (UAE can use the host OS disk but AmigaOS will likely get confused by the different file protection/permission bits, remember AmigaDOS is pretty unique with this). Then just use the provided install script with the manual fixes and save the modules manually. If you need my .uaerc I can send it to you but it will need to be adapted for you.

As for the actual encryption: I don't really know, but it seems to include some kind of compression as the encrypted mods are smaller than originals. Or perhaps it is just a different way of storing the pattern data.
Ripping Amiga music / Re: Confusion Musicdisk
« on: August 05, 2014, 20:01:58 »
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:
Code: [Select]
>w 1 14843c 10 w
1: 0014843C - 0014844B (16) W
Wait for that pattern/note to be played and the write trips the watch:
Code: [Select]
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:
Code: [Select]
>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
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:
Code: [Select]
>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:
Code: [Select]
./unconfuse mod.x mod.lost ...
I'll FTP the decoded mods separately anyway so you don't need to touch my icky code.
Ripping Amiga music / Re: Confusion Musicdisk
« on: August 04, 2014, 02:09:50 »
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.
Code: [Select]
>f 123b30
Breakpoint added
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:
Code: [Select]
; 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
Pages: [1]