'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Tue, Jun 26th, 2012 @ 21:14 ( . )

I've been working on the protection on Demon Stalkers and it fits into the description of PirateSlayer V2 that is described on this site but either there is a mistake there, or this one is slightly different.

What I'm referring to is the byte string the protection check is looking for on T2 S0. It's listed here as "Checks for the pattern $D7 $D7 $EB $CC $AD on track 2" that is correct except for when it gets to the bytes $CC and $AD it is looking for a repeating set of those 2 bytes 512 long. Only after those 512 have been verified is the last set of bytes, $55 $AE $9B $55 $AD $55 $CB $AE $6B $AB $AD $AF checked.

On another note, the drive code is pretty sneaky on how it executes. It actually executes twice in buffer $0300. First time through it only gets a few instructions into the routine when it is interrupted and restarted at the beginning, right in the middle of executing


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Pete Rittwage (registered user: 558 posts )
Date: Tue, Jun 26th, 2012 @ 21:20 ( . )

Thanks for looking at it. I suspect there are some slightly different revisions of PS that I don't differentiate, as you found...


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Tue, Jun 26th, 2012 @ 21:44 ( . )

Yea that thing is a mass of encryption routines several levels deep. I managed to get it all decrypted and listed out but it was not easy.

Drive code was interesting. It read a block in to the drive buffer at $0300 from the computer side. Later it did a block execute but the beginning of the code only went a few instructions in before returning, not executing the bulk of the rest of the code until I realized what it was doing. The very first instruction checked a memory location in ram for a value and if it was set, it jumped to the main portion of the drive code. Trouble was it was set *after* it was checked so the code as it was would never execute the main routine. What it did was right after that it set up a job with T2 S0, the one with the protection on it, then it used a job code of $E0. This not only set up the track and sector to use, but halted execution of the current routine and restarted it at the beginning. Now when the ram value was checked it was set correctly and it jumped to the main code to do the protection


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:LordCrass (guest: search)
Date: Wed, Jun 27th, 2012 @ 21:18 ( . )

The loader is actually an early version of ProDOS, although it has a no-sync key track that is very similar to what is found on PirateSlayer. Skate or Die also uses this loader. The GCR pattern for track 2 (at non-standard density %01) is:

$d7* $eb ($cc $dd)*$200 $55 $ae $9b $55 $ad $55 $cb $ae $6b $ab $ad $af

Many loaders/protections will use the $E0 job code as a quick and easy way to seek to a track and then jump to a buffer of code.



REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Wed, Jun 27th, 2012 @ 21:42 ( . )

ProDOS is Apple isn't it?

What I'm dealing with now isn't any kind of fast loader if that's what you mean. Its all copy protection. It's encrypted I lost count of how many layers deep and by several different encryption methods. On top of that it has several checksums for the code at several places, all to do the check of T2 S0 and if any of it fails the programs checks out to never never land.

Unfortunately I forgot to put in my notes where and how the drive code that does the check gets to the buffer so I'll have to go through all that decryption mess yet again :(


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Pete Rittwage (registered user: 558 posts )
Date: Wed, Jun 27th, 2012 @ 21:53 ( . )

In modern times I just wait until the protection is executing in Vice (on track 2) and exit to monitor to look at drive code.

Decrypting all that to get there is for the 'old days'. :)


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Wed, Jun 27th, 2012 @ 22:15 ( . )

Laughing, I know but the fun for me is disassembling the protection down to the bitter end. I just find it fascinating all the tricks that are used both for hiding, and executing the protection checks.

I tried using VICE with a freezer cart, to catch the decrypted code at each step (not only does it decrypt the code, it re-encrypts the previous code) but the reaction time is just too slow on VICE for the freezer and I can't freeze it before what I'm looking for is obliterated. At any rate that means a trip back to the real C64 to try and find where the drive code is located. I have no bloody idea why I didn't document that, but I'm gonna pay for it now ;)


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:hyper active (registered user: 296 posts )
Date: Thu, Jun 28th, 2012 @ 05:32 ( . )

Hi.Just curious How long is the actual track 2 in question?
due to the lack of sync, you get 8192 bytes when using nibtools, but I'd like to find out what the true size is.
Cheers.


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Pete Rittwage (registered user: 558 posts )
Date: Thu, Jun 28th, 2012 @ 08:31 ( . )

It will have an expected track size based on the density detected.

/* To calculate the bytes per rotation:

4,000,000 * 60
b/minute = ------------------------------------------------ = x bytes/minute
speed_zone_divisor * 8bits

4,000,000 is the base clock frequency divided by 4.
8 is the number of bits per byte.
60 gets us to a minute of data, which we can then divide by RPM to get our numbers.

speed zone divisors are 13, 14, 15, 16 for densities 3, 2, 1, 0 respectively
*/

#define DENSITY3 2307692.308 // bytes per minute
#define DENSITY2 2142857.143
#define DENSITY1 2000000.000
#define DENSITY0 1875000.000

Further divide this by the RPM (300) to get the number of bytes on a track that "should" be there.

Now, if the disks were not written with a 1541, this will be inaccurate. It's already known that a trace duplicator will be a slightly different bitcell size that a 1541, but it's close.

Also, we cannot always tell where a custom tracks starts and ends when written on a 1541, though. Well, at least I can't- maybe there are other methods to do so I haven't explored.


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Thu, Jun 28th, 2012 @ 08:40 ( . )

The data is read in the protection routine from this track at density 1 (%01) Not sure if this is standard for track 2, don't have my books handy.


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Thu, Jun 28th, 2012 @ 11:16 ( . )

Another thing I noticed, and I'll have to confirm this, is the protection code is read in one sector at a time, it starts at T1 S7, but the odd thing is it appears to go up to T1 S23, that track should only go to S21. Is it even possible to jam 2 extra sectors onto that track? The sector loading code is in the file EA.prg and is not encrypted if you want to take a look


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:LordCrass (guest: search)
Date: Thu, Jun 28th, 2012 @ 15:48 ( . )

I disassembled and commented the entire pre-loader, protection check code (host & drive side), and in-game loader (host & drive side) for this a while back. I don't recall it using extra sectors, but I can check it later.


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Thu, Jun 28th, 2012 @ 16:05 ( . )

I verified that it at least tried to load up to sector 23. I don't know if it actually loaded data from extra sectors or if it just bypassed them when they weren't found. I put a break at the end of the sector load routine and the sector counter was at 23


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:LordCrass (guest: search)
Date: Thu, Jun 28th, 2012 @ 20:38 ( . )

It tries to load up to 23, but the drive starts throwing back "illegal track or sector" after sector 20, so the buffer contents that are read for each of those is a repeat of sector 20.

You can't use the U1 drive command to read extra tracks or sectors. You'd need to use the job queue directly, or write a custom routine.


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Thu, Jun 28th, 2012 @ 21:49 ( . )

Yep. I tried loading the extra sectors from a drive monitor using job codes and there was nothing there, it just returned $02 back (header block not found)

Wonder if it was a bug, or possibly leftover code from some other loader?

Anyway thanks for verifying that, and the heads up about the U1 command, I didn't know it would return errors if you tried to go past standard tracks/sectors


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Sun, Jul 01st, 2012 @ 11:31 ( . )

Finally found the drive code and how it's loaded. After all the decryption of the main code, the drive code is there and in its decrypted state but you still can't see it.
How it works is there are 2 blocks of $100 bytes that just look like random garbage. The code takes a byte from the first block, then it does some elaborate calculations on that byte involving all three registers, A, X, Y. When it's finished it comes up with an offset into the second block which is one byte of the drive code. It transmits that byte to the drive into the buffer at $300 and then starts again with the next byte.

I think for completeness I may alter the drive code to read in track 2 in it's entirety into the extra drive ram I have to try and capture exactly whats there. I'll save that for another day though

At any rate I think I now have the code and data for the protection in it's entirety and completely decrypted state, unless I run into any other little terrors like the drive code


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Displacer (registered user: 14 posts )
Date: Sun, Jul 01st, 2012 @ 12:51 ( . )

OK, I think I captured the track, and it makes one thing I had assumed does not appear to be correct. I had thought the beginning of the string of bytes for protection started with 2 $D7 bytes. This doesn't seem to be the case. While it is looking for the $D7 bytes, there are actually 5 of them. After looking at the code it is not just looking for 2 of them, it's looping through the $D7 bytes until they end and then looking for the other bytes. I'm pretty sure this is the reference "header" it uses to signal that the actual protection bytes follow immediately after.


REPLY: [With No Quote] --- [With Quoted Text]

'PirateSlayer'
Author:Fungus (registered user: 20 posts )
Date: Sat, Aug 18th, 2012 @ 06:59 ( . )

Which game are you looking at?

If it's pirate slayer/busters the tool I coded here can determine version and decrypt the main loader for you.

[link]

saves a lot of time.

If it's not, I'd be a bit interested to look at it myself.


REPLY: [With No Quote] --- [With Quoted Text]

'encryption routines '
Author:Alex (guest: search)
Date: Wed, Oct 24th, 2012 @ 19:58 ( . )

Hi,

I see that you guys found some old-school crypto employed in the code. I am a cryptographer and I would like to take a look at the routines, produce readable pictures.
Let me know if any of the encryption/decryption routines are not mere XORs. Also the random number generator with the two tables sounds interesting (mentioned below in the thread), where could I get the code for that?

Thanks,
A.


REPLY: [With No Quote] --- [With Quoted Text]


--- 0 Users Online --- 0 Recent Unique Posters

Q302=1660602517 - Threads: / 1660602517