[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Tamper-Proof Software? No!
In your essay, you overlook the use of pseudo-code interpreters
and cryptographic code mangling. It is not possible to make software
unconditionally tamper proof, but it is possible to make it hard,
perhaps as hard as finding a hamiltonian of a graph. I speak as a
person with a 3 year cracking/tampering background. Let me pass on an
experience I once had:
I was trying to crack this game with a dongle. The code had dongle
checks spread throughout it. I thought I could merely search for the
signature of the dongle check and fix all of them, but the check was
different each time, disguised by indirect addressing, illegal
instructions, interrupt tricks, and stack tricks. The only solution
was a tedious process of tracing the execution of the program and
backtracing the failure routine. That wasn't the only problem though.
On top of the dongle checks, checks for the dongle check routine and
various checksum routines were spread throughout the code. In fact,
there were so many of these checks that trying to separate the "useful
part" of the program, and the dongle checks was hard because they were
virtually everywhere. yes, it cost the game speed, but the game
wasn't one that was particulary synced wih the display. Anyway, it
took about a week of hacking on and off to find them all. There were
about 30. What if there had been 1000? What if the code wasn't pure
assembly, but a p-code interpreter which executed not a straight
byte-code, but an actual recursive encryption algorithm in the
interpreter? In other words, 0x80 might stand for "add a to b" in one
instance, but in the next instance, "suicide mode" Perhaps the library
i/o for the p-code itself also changes/gets mangled through the
process. Furthermore, let us assume that this mangling is in some
sense, cryptographically strong. A few things become very hard:
1) writing a decompiler for the general case
2) separating the "application" from the "protection" Why? Because in some
sense, you'd have to rewrite the interpreter, or the application to remove
all the "suicide" instructions. The p-code could be set up so in fact, most
instructions are suicide unless decrypted properly. Thus, if you were
to remove one suicide instruction, all of a sudden, a perfectly
legimate section of code would become riddled with them. Removing
protection would no longer be as simple as "NOPing out" the
instruction. The code would be, by the nature of the interpreter,
interdependent in a way far deeper than "checking for the presence of
the dongle check routine"
(note: this scenario is not isomorphic to the usual protection trick
of having an interrupt decrypt the next instruction to be executed
and encrypting the previously executed instruction. In that
scenario, the re-encrypter can be disabled, so that after a
complete execution, the code is plaintext for the debugger to save to
disk. Here, the problem is that the code is never "decrypted"
in the first place. What changes, is the meaning of the instruction
set itself.)
I suppose, one could attempt to isolate the suicide routine and just
make it do nothing. That still doesn't solve the problem that a
section of code has been mangled and probably not doing what it is
supposed to.
While a determined hacker could still break through this, I'd say
that it would make the effort not worth it in most cases. Currently,
most software protection is so simple that an hour of so in a debugger
can isolate a manual check, and remove it. Most of the time, code is
only skimmed. My cryptographic p-code proposal forces the hacker to
virtually disassemble and understand the function of the entire
interpreter, write a decompiler, remove any protection algorithms from
the code, and then somehow, fix the interpreter so that the code still
works.
Imagine the task of having to create a plaintext which will generate
a certain MD5 hash. Here, you'd have to remove the protection, but
make sure the cryptographic execution flow of the interpreter matched
the original. i.e. coming up with *different* code (sans protection)
that causes the interpreter to decode the stream in the same manner.
(if you want to know how code is p-compiled, I can explain later
after I flesh it out more. I suspect I am probably reinventing the
wheel for the Nth time, but I haven't read anything on it, so I may
as well make a fool of myself.)
Instead of picturing my p-code proposal, picture a much simpler
idea. A seething morass of code, most of it garbage, protection
decoys, all of it interdependent with other checks (chained in various
ways), and somewhere in the middle of it all, is the application. I
don't care what romantic vision of teenage hackers you have, it is
possible to make removing the protection require the effort of
rewriting a large chunk of the application. One of the other things I
used to do was "NTSC fixing", taking PAL frequency games and fixing
them for US computers. In some cases, it was simple (chop off the
bottom of the screen, adjust rasters and timing) But sometimes, it
required rewriting a portion of the graphics engine. This was no joy
and sometimes I just gave up. If crackers had to alter just 10% of an
application to get it to work unprotected, I think that would be a
sufficient deterrent to most of them. Depending on how much speed
you wanted to trade off, you could probably make the code arbitrarily
"deep" (or, as Tim likes to talk about, imagine a hacker that has to
crack a program encoded as DNA!)
digression:
Now grant me something more powerful. Imagine in the future that
most software is in the form of distributed objects and that many of
those objects reside and execute on remote systems. If these remote
systems require cryptographic authentication before they allow a
remote execution (e.g. Telescript), copy protection can be
conditionally secure as RSA. Cracking would require writing a
replacement object or buying one, presuming of course, major objects
weren't trade secrets and you only had the API to work with. (once
again, the function arguments could be permuted crytographically, so
that even if you had the API, you still couldn't write a replacement)
The result, is that you'd have to pay for software because software
would consist of a client + object services, and the objects would
require cryptographic cash/authentication to use, and replacements
would be hard to write. However, unlike dongles, the system would be
totally automatic and convenient, so there would be none of the problems
associated with traditional protection (pain of look-up-in-the-manual or
dongle). The same system could be extended to hypertext publishing where
documents are distributed all over the net in different databases.
One could pirate a "snapshot" of a document, but what makes the
documents valuable is the dynamic quality of hypertext, being able to
lay it out however you choose, and follow links. This means you need
constant access to the databases, and therefore you pay for the
service.
My point in writing all this, is to disagree with Tim's implication
in the cryptoanarchist manifesto, that cryptographic technology will
eliminate intellectual property. Cryptography doesn't eliminate barbed
wire, it is the ultimate fence. While it could provide untracable
networks for "information laundering", it can also provide
authenticated networks for unpiratable software, or teach us how to
compile code in a manner that is "expensive" or as Tim might say
"logically deep". (too deep to unravel its full meaning.)
(I agree if Tim meant that it would make *legal* protection of iprop
impossible, but I consider legal protection irrelevent anyway. If I need
something protected, I'll do it myself, not depend on government)
Well, I've said my peace. Now Tim can tear my argument to pieces. ;-)
-Ray
Any and all mistakes the result of lack of sleep...ZzzzT.
"Information wants to be free..."
"Not if Mathematics has anything to say about it."