[prog] 'protecting' perl code

Almut Behrens almut-behrens at gmx.net
Thu May 6 22:09:53 EST 2004


On Thu, May 06, 2004 at 05:54:06PM +0200, Riccarda Cassini wrote:
> at the moment.  Actually, he is rather pleased with the application's
> final appearance, so I'd like to pass on the praise to those of you who
> deserve it at least as much as I do...

Thanks (if I was among the ones you had in mind :)

> I guess the problem at hand is a little unusual:  I've been asked
> whether it would be possible to 'protect' existing perl scripts from
> prying eyes - such that you can give them away to people who are not
> supposed to see what the code does...  Comparable to having some
> compiled binary executable, that you can't easily reverse engineer.

Not that unusual - this topic seems to come up from time to time...
The last request I got from a client was about a year ago. That was
when I eventually decided to give it a try.


Some people would argue that writing code in perl would automatically
solve any obfuscation demands without much further ado ... Okay, just
kidding.

Using the perl compiler is not a real option for this purpose, because
(a) it's still too 'experimental' for real production use, and (b) it's
hardly possible to take effective measures against automatic
decompilation of the byte code.

The approach I finally chose was based upon some ideas and example code
distributed together with the module Filter::Util::Call by Paul
Marquess (btw, there's another, similar one: Filter::Simple by Damian
Conway, which is built on top of Filter::Util::Call, but provides a
simplified interface...).
The key concept is "source filters". Perl provides low-level mechanisms
to intervene with how the parser handles the stream of source code that
makes up the script. Type 'perldoc perlfilter' to get a concise but
good description of what this is all about.

To get a general idea of what source filtering allows you to do, you
might want to take a look at the module Acme::Bleach or Acme::Morse by
Damian Conway. Acme::Bleach allows you to represent/recode any perl
source as whitespace characters only, while retaining executability.
Although this is obviously meant as a joke, similar more sophisticated
mechanisms can be employed to obfuscate your code sufficiently to have
it withstand moderately determined attempts to decipher it.

It's important to understand, though, that this is always "security
through obscurity". Even employing strong cryptography will not really
help, as there will always be some point when the parser needs to see
tiny portions of the cleartext perl code, to be able to execute it. 
Also, you have to distribute the decrypting code itself (as part of
the perl binary, typically). Otherwise, it wouldn't be possible to
execute the script... (this holds independently of whether you decide
to have the user enter some password to run the program).
See further below on the minimum precautions needed to make life
difficult for some potential cracker.

>From the point of view of cryptography, the whole obfuscation approach
is _always_ lame, but for many practical purposes, the time required to
crack some program would typically be beyond what it's worth -- if done
well enough.
(Make sure, however, that your client knows about these facts...
preferably in written form.)

> 
> I gooled a bit, but all I found were a few commercial solutions (source
> code obfuscators like Perlguardian, Perl-obfus, etc.), and rather
> heated discussions about why you should never ever do such a thing at
> all, as it would be a breach of the open source philosophy, ethically.

Googling for something like 'perl "source filters"' will probably turn
up the most useful stuff on the subject...

Don't miss:
http://beatnik.perlmonk.org/yapc2002/SourcefiltersinPerl-slides.pdf
  (a presentation at YAPC 2002)

and the module Filter::CBC by the same author (Hendrik Van Belleghem).

> 
> Well, I'm afraid this is a little over my head anyway - at least I'd
> probably have to learn a couple of things along the way...
> Still, does anyone have any ideas how one could go about it?  I'd hate
> to give up before having had a go at it.

Here's a rough sketch of what needs to be done (more details upon
request):

* write the source filter as an extension module in C.  Although you
can, in principle, write source filters in perl (see Filter::Simple,
for example), this would be too easy to reverse engineer.

* link the module _statically_ with the perl interpreter (building it
as a shared object (as usual) would make it rather easy to debug/crack).

* strip all symbol information from the resulting perl binary, to make
debugging even more difficult.

* choose some decent cryptographic algorithm to encrypt the source --
at least make sure it's not the weakest element in the chain.

* take some other special precautions, like checking for the presence
of the perl compiler (the module B) - for details see the template
decrypt.pm that comes with Filter::Util::Call.

* add a good amount of 'dummy' code with the only purpose to confuse,
i.e. code that does seemingly useful operations, while the real
required functionality happens as hidden side effects in the background.

The general idea is that anyone running the perl interpreter in a
debugger (like gdb) would have a hard time figuring out what's _really_
going on...

> 
> Is this doable at all within a reasonable project time span, or should
> I rather tell my client to use some commercial solution right away?

Depends. As a general rule, I'd say: if someone is willing to pay you
(or your company) for it, why not just do it... :)
(yes, sure, do some serious consulting first -- however, they may have
their specific reasons for wanting a non-standard solution...  well,
you get the idea).


For various reasons I don't want to go into here, I can't make the
source of the solution I wrote publically available. But you (Riccarda)
can have the code, makefiles, etc. as an example solution, if you
promise to modify it sufficiently and not sell it to someone in the
immediate vicinity of the company I originally wrote it for.


Well, you know what to do first...

Almut

 


More information about the Programming mailing list