Peter Hyde commented:

> Like I say (and which Max repeats in his far more thorough outline),
> no scheme can promise utter security...

Indeed, but treating this as an intellectual challenge it should be
possible to throw some serious spanners in the works of anyone who wants
to crack the application.

The two main routes that all hacks take are to either alter the binary
executable so that the security checking code is neutered, or to reverse
engineer the algorithm for the security code generation and from there
create new codes as needed.

The first attack of a modified executable is fun to play with. The best
case I ever had to crack for the copy protection for an Mac game that had
some startup code that check summed itself to find the encryption key to
unlock chunks of the executable. But even this level of paranoia was
easily defeatable with an nice debugging monitor and a few minutes spent
relocating the code and executing it to find the key in question.

So the best idea that I have seen involve several different checking code
procedures that fire at different times. You need to separate these in the
code so that they are not all easily locatable one after the other, and
you need to have one or two that are  used very often so that the hacker
will think that they have found the troublesome routines. The other checks
need to fire only at long intervals so that they can detect changes in the
code when the hacker has passed the hacked product onto others. Then you
can disable, cripple, or otherwise have the application stop working in
some subtle and annoying way. Intermittent crashes and data corruption are
better than telling the user that you know what they are up to. Especially
if you can trick then into asking for support so that you can find out who
they are.

The second attack of unpicking the security code is best tackled by having
all the code that does that stuff exhibiting some annoying behaviour. But
this I mean it should:

  1. Make heavy use of recursion.
  2. Include a complex state machine.
  3. Be implemented in an interpreted language.
  4. Include message passing, exceptions and interrupts during processing.
  5. And for extra spice use cooperative threads or coroutines.

One good solution I can image in a virtual machine implementing a small
forth derived language. Only a serious loony would send the time to
reverse engineer a complex pile of recursive forth that manipulated a
state engine.

I know this, because I once gave up on a nasty virtual machine that
implemented some kind of p-code. You quickly established that there was a
central dispatch loop in the assembler that used a jump table to call more
virtual code that jumped back into the central dispatch code. The only
attack would have been to write a decompiler for the p-code, and this was
more effort than it was worth for the game in question.

So there are some ideas, and they would be fun to implement as well, and
as long as you combine the two sorts of protection you'll be safe for
99.9% of the people out there.

Cheers, Max.


---------------------------------------------------------------------------
    New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
                  Website: http://www.delphi.org.nz
To UnSub, send email to: [EMAIL PROTECTED] 
with body of "unsubscribe delphi"

Reply via email to