Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Defeating a 40-year-old copy protection dongle (dmitrybrant.com)
859 points by zdw 7 months ago | hide | past | favorite | 290 comments


These dongles used to be ubiquitous and they broke all the time.

As a young intern, I arrived early one morning to find the PCB layout software (PADS PowerPCB) on our "design PC" wasn’t working. (I use quotes because it was just the beefiest machine we had, naturally our boss’s PC, which he kindly shared)

Obviously the dongle. I tried unplugging and replugging it, with and without the printer daisy-chained. Nothing.

So I begrudgingly asked my colleague who’d just arrived. He looked at the dongle, looked at me, looked at the dongle again, and started laughing.

Turns out our Boss had stayed late the previous night processing customer complaints. One customer had sent back a "broken" dongle for the product we were selling. Boss tested it on his PC, found it worked fine, and mailed it back on his way home.

Except he didn’t send our dongle back. He had sent my PowerPCB dongle. More fun was had when the rest of the team and finally our boss arrived. Luckily he took it with good humor.


I remember when I worked in an electronics lab one of our EEs built several "dongle buses", a parallel port "bus" that you could plug up to about half a dozen dongles in, and it was frequently fully populated on the machines we used for CAD and PCB layout. An early version of PADS (PADS2000?) was one of the applications we used.


We had proper licenses for all PADS seats at my previous work, but all the users always installed the cracked versions because it was unusable with the dongle.


>they broke all the time

While I was reading the OP I kept thinking about how an accounting firm's entire ability to do business rested on the continued functioning of a parallel-port dongle. I just have to imagine that they had a box full of these.


Many a crack back in the day was even more simple still, we'd just find and alter the right JE or JNE into a JMP and we're off to the races. As the author found, the tough part is just finding and interpreting where and how the protection was implemented. If throwing the exe in a hex editor gave you access to String Data References (not always the case, but more common than not) then you'd just fail the check you were trying to skip, find that string, hop over into assembly to see what triggered loading that, and then just alter the logic to jump over it when the time comes.


Many years ago I was a technician supporting a few custom programs on thousands of PCs. The developer of one of these programs had added a date check to his code so the program would refuse to run after a set date and each new release would increase this date by a few months so it would stop working after a few weeks if he ever stopped creating new releases. His contract ended and a few weeks later his software, now relied upon by hundreds of sites, stopped working. The contract for the software development was thoroughly checked and legal action against the developer was started but I asked to see if I could resolve the problem in the meantime.

It only took ten minutes with a dissassembler to find the JGT (Jump if greater than) and convert it to a JLT so the software would stop running if the date was before a certain date rather than after. I created a patching tool that simply flipped one bit that was sent out to all the sites and everything was good again. I don't think I'll ever beat the elegance of a single bit flip hack.


If you think it's bad now, the early days of the web were absolutely filled with scumbag grifters who made small fortunes hiring contractors and then refusing to pay.

Many of them disappeared in the y2k dot com bust, but then seem to have reappeared in SF after 2008.

In the late 1990's, my second ever Flash app development client stiffed me on a $10k invoice.

He finally figured out 6 months later that he didn't have the source material to make changes and paid the full invoice in order to get it.

So I took precautions with the next client. It was a small agency that was serving a much larger business.

We were on 30 days net payment terms and I submitted the invoice when the project was done.

They didn't pay and within a couple weeks of gentle reminders, they stopped responding.

I smiled.

Exactly 30 days from the due date, I got a panicked call shrieking about their largest client website being down and did I have anything to do with it?!

I asked them what the hell they were talking about, they don't own a website. They never paid for any websites. I happen to own a website and I would be happy to give them access to it if they want to submit a payment.

They started to threaten legal nonsense, and how they had a "no time bombs clause in the contract."

I laughed because my contract had no such clause. If they signed such a contract with the client, that's not my problem.

I told them I wouldn't release the source files until the check cleared my bank, which could be weeks. A cashier's check arrived that morning and their source files were delivered.

By the end of it, the folks at the agency thanked me because that client wasn't planning to pay them and they hired me for other work (which, they had to prepay for).

Of course I don't know about the OP, but I'd bet the company was trying to stiff that contractor on their last check.


> because that client wasn't planning to pay them

Wait, you mean they used your little ruse as a means to be paid themselves??


Yes they did, and it worked!


Mostly non-malicious example... My employer asked me to write a UI to solve a problem for a handful of people until a proper (giant ever-delayed) migration was finished. Over a couple of weeks I made it work despite not having dealt with MVVM/XAML/Whatever before and I was pretty pleased with the outcome. But it was a hacked together thing! I'm not a real dev and given that I got a promise it wouldn't get distributed.

So, you know, in the program.cs startup I checked the username vs a hardcoded list of people in the relevant teams, and if it wasn't crashed out with an error and a support email address.

About 18 months after I had moved on, I got an email with a screenshot of that error message. it would appear the Milan (something like that) office had got their hands on a copy but it just wouldn't work for them...

Trivial to undo of course, but I did enjoy the throwback!


That's a dangerous fix. What if someone tries to run your new version in the past?


the spacetime paradox is the bigger concern imo. nothing to worry about.


There's a lot of things going on that lead to this.

One, the developers spend more time running this code than we do, and they have to get the program working before we can even use it. So any parts of the program that are hostile to the developers risks killing the entire project. Obfuscating the copy protection can hit a point where it makes bug fixing difficult.

Two, lack of training. If you, me, and Steve each have a bag of tricks we all use to crack games, whichever one of us figures it out gets bragging rights but the game remains cracked. Meanwhile Developer Dan has to be aware of all the tricks in all of our bags together if he wants to keep the three of us out. Only there's not three of us, there's 300. Or today, probably more like 30,000.

Three, lack of motivation, which is itself several different situations. There's a certain amount of passive aggression you can put into a feature you don't even really want to work on. You can lean into any of the other explanations to defend why your code didn't protect from cracking all that much, but it's a checkbox that's trying to prove a negative, and nobody is going to give you any credit for getting it to work right in the same way they give you credit for fixing that corner glitch that the QA people keep bitching about. Or getting that particle animation to work that makes the AOE spells look badass.


Another method (much more common for software that asks for two pieces of information, like a name and a key) is to take a memdump of the process at the "your key is invalid" dialog, find the invalid key you just typed, and hope that a valid key is somewhere nearby in memory. Unlike the assembly trick, this requires 0 programming expertise beyond the ability to type `strings` on the command line.

This works because some programs use a hashing algorithm to calculate the key based on the name, do a strcmp, and pop a messagebox if the keys don't match, without zeroizing the valid key buffer first. If the key buffers are on the stack (or if the two mallocs just happen to use the same region in memory), it is often easy to find a valid key if you know where the invalid one is.

I guess software that derives keys this way is far less common than it once was, but I know of somebody who cracked something using this method just a few years ago, so it still pops up from time to time.


When I was a child, in the 90s, I did this all of the time.

Input a unique string I could watch for, fire up SoftICE, watch for the string, and then step through until the == comparison happened, then either grab the calculated key and input it, or patch the comparison from == to != or just return true, depending on the implementation.


SoftICE was such a gift and pain in the ass.

I did a massive crack that involved a program and it’s inf/dll hardware driver package.

Some of the most rewarding work I’ve done and also just so tedious!

Having to stop the OS like that and accidentally getting to the kernel but then not wanting to lose my position so having to hit step over and step out until just the right place… whew.


Yep. I used SoftICE to do a few of these dongle-workarounds. Amazing and terrible software. :D


Haha yeah. It was mostly just fun for me as a nerdy child who spent way too much time on Astalavista forum.

Cracking and RE were just gateways into a career in (defensive) security for me.