Hacker News new | ask | show | jobs
by csl 2013 days ago
Very clever and great article! But it sounds pretty easy to write a cracker for it: Just rewrite the machine code to jump over the check. Or did I miss anything?

Edit: Guess it depends on the details and amount of "obfuscation" that he mentions.

5 comments

>Very clever and great article! But it sounds pretty easy to write a cracker for it: Just rewrite the machine code to jump over the check. Or did I miss anything?

Nope, you did not miss anything. Many of these old DOS game floppy protections could be bypassed by a single byte change to the exe (or com, depending on the game) file. The time consuming part was working out exactly which byte to change.

Source: I cracked most of my DOS games back in the day, using nothing more than DOS's supplied 'debug' tool, so I did not have to go find, and insert, the floppy in order to play the game. On many of them, changing a single JC to JNC or a single JE to JZ (or the reverse) was all it took to bypass the copy protection. A few others took a few more bytes worth of patching, one had to convert a conditional into an unconditional branch or otherwise nop out a small code segment. The one that required the most effort was MicroProse's Apache helicopter simulator. They used the "weak sector trick" but the contents of the "weak sector" was also a small bit of the overall game code. So for that one I created a loader that hooked the disk interrupt and when it detected the weak sector read, it returned the sector data and the proper "disk read error" state for the rest of the game to work with.

> Just rewrite the machine code to jump over the check

Sure. It's even easier today: not only we have specialized software for cracking things, but we can even dump the memory contents and inspect them, patch up while the program is paused, and then rewind and try again from the same location. If we mess up, we can quite easily restart, just run the program again from our fast NVME drives(it will probably come straight from the OS cache). Heck, in some cases we can "fuzz" the program and let the computer try to figure out the winning combination! We can do this in parallel with our multiple cores.

Now think about the context back in the day. For the most part, people were trying to crack the copy protection using the same machine that ran the software. In the case of the BBC Micro, you could have anywhere from 16 to 128KB, depending on the model. In that era, it was often the case that you couldn't even run a debugger, because it wouldn't fit alongside the program you were debugging. And even if you could, their capabilities were nowhere close to what we have today and - depending on the hardware - some breakpoints you couldn't even reach (inside code that disabled interruptions - which was often the case for software that accesses disks).

It could be incredibly hard to find exactly what "jump" you had to change. If you messed up, this could mean a machine lockup. Now you have to reboot and load your stuff again from slow floppy media.

It was difficult.

I did basically everything you mention, back in the day, although on a C64.

In many ways, things were much easier back then: Direct access to most of the hardware, flat memory layout, smaller and vastly simpler ISAs, smaller programs (meaning shorter disassemblies to wade through), no protected mode so you could overwrite anything in RAM and so on. And you wouldn't even have to do it live in-memory, just disassemble the program piecewise from disk. People did extraordinary things back then, and you vastly underestimate their capabilities. Sure, you had to write a lot of tooling yourself, but it was simpler times.

I am not trying to detract from the copy protection mechanism, which truly is ingenious. I was just genuinely curious whether I was misunderstanding anything from the article.

Or... what I also encountered and found to be the hardest to reverse engineer, having a block decode in the interrupt vector table using all registers including stack pointers as decode keys.

That meant that making a mistake would result in a tedious re-iteration.

Copying one of my old comments from slashdot... it sounds similar to Sierra's "cpc.com". While I was reading the article I wondered if the equivalent of this process for the 6502 (BRK/COP interrupt table?) would work.

Back in the 1980s Sierra On-Line used to copy protect their adventure games with a copy protection system which involved strangely formatted sectors on the original disk which were impossible to duplicate exactly using standard PC hardware.

The loader "sierra.com" used to call a copy-protection program "cpc.com" which loaded data from the disk to decrypt the main program and run it. cpc.com had some of the most obscure, twisty, awful code ever written to prevent debugging and it constantly used different methods to thwart stepping through the program using INT 3 (these were the days before Soft-Ice).

But the solution (or "crack") was just dead simple. Just fire up debug, step to the beginning of cpc.com, and copy the vector from INT 3 into the INT 13 vector - then cpc.com stops right at the point where the data from the disk is being loaded, so it can be copied.

Despite all the incredibly complex code, cpc.com had to read the data off the disk so there was no way the Sierra programmers could thwart this method.

My thoughts exactly. I spent a good amount of time learning about and cracking various schemes. It was never about distribution but about bragging rights and the different ways code was obfuscated. Most were disappointingly simple, others had more layers, very rarely found ones that needed special effort beyond say a person-day or two to solve.
Skate Or Die in the C64 was tricky as it had self modifying code for obfuscation. Took me a while to “debug” that.

The copy protection of Ocean games was much easier to crack. They had a “IsOkToRun” type of function which returned 1 in the A register.

So, same as every single bit of copy protection?