http://www.perlmonks.org?node_id=256527

zentara has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I learned a great "fishing lesson today" from a post on the perl.beginners list. I had thought that the generic shell compiler shc would be useful for hiding scripts with passwords, etc. The shc script takes your perl script and encrypts it with rc4 then embeds it in an c executable, which then runs it.

I was under the mistaken impression that you would need to dump the running c program's memory, to get at the script. I was shown how to use MO=Deparse to dump the perl script.The method follows:

by Paul Johnson: Patch O.pm --- /usr/local/pkg/perl-5.8.0/lib/5.8.0/i686-linux/O.pm Tue Sep 10 21: +35:11 2002 +++ ./O.pm Thu May 8 00:34:26 2003 @@ -6,6 +6,11 @@ use Carp; sub import { + unless (-e "qaz") + { + system "touch qaz"; + return; + } my ($class, @options) = @_; my ($quiet, $veryquiet) = (0, 0); if ($options[0] eq '-q' || $options[0] eq '-qq') { Stick it in your current directory. Set an env var: export PERL5OPT=-I.\ -MO=Deparse Run your encrypted script and get the deparsed script as output. rm qaz to run it again.
I find this very cool. But my question is this. Short of removing the Deparse module, is there a way to write a script which will prevent it from being dumped by DeParse?

Replies are listed 'Best First'.
Re: Can you prevent MO=Deparse
by broquaint (Abbot) on May 08, 2003 at 14:19 UTC
    Short of removing the Deparse module, is there a way to write a script which will prevent it from being dumped by DeParse?
    In theory, no, since -MO=Deparse will mean that B::Deparse is processed before any other modules, and therefore at the top of the BEGIN chain, and since it sets the minus_c switch, no other code can be run (except for anything in a BEGIN/CHECK block of course). But inevitably the argument will come down to the fact that you can't hide perl's source (see. Here is a commercial obfuscator for an interesting discussion on the matter of source obfuscation).

    This won't work in your case, but I thought I'd put it up for amusement value anyways

    ## place before use O 'Deparse'/-MO=Deparse BEGIN { unshift @INC => sub { ## 'empty' should be a valid module open(F, "empty") and return *F if $_[1] =~ /O.pm|B.pm/; }; }
    If this code is placed before -MO=Deparse or a use O 'Deparse' then the deparsing will be skipped.
    HTH

    _________
    broquaint

Re: Can you prevent MO=Deparse
by chip (Curate) on May 08, 2003 at 14:48 UTC
    Two pieces of advice:

    • Learn strong crypto. Learn why I said this.
    • "IF YOU WANT TO HIDE YOUR SOURCE WHERE NOBODY WILL FIND IT, WHY DON'T YOU STICK IT UP YOUR ASS?" --Dominus

        -- Chip Salzenberg, Free-Floating Agent of Chaos

      Yeah, but the "border guards" might still find it. :-)
Re: Can you prevent MO=Deparse
by pfaut (Priest) on May 08, 2003 at 13:46 UTC

    Perl is an interpreted language. In order to run your script, perl needs to be able to read it. Therefore, at some point when you are trying to run it, the script must be in a decrypted and readable form. If your program needs to be that secure, write it in some other language than perl.

    90% of every Perl application is already written.
    dragonchild

      If your program needs to be that secure, write it in some other language than perl.

      Sorry, but that's just wrong. "Security" is not gained by hiding your source code. That's a temperary measure, at best. Perl just happens to make this problem more obvious.

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      Note: All code is untested, unless otherwise stated

Re: Can you prevent MO=Deparse
by RMGir (Prior) on May 08, 2003 at 14:51 UTC
    Every once in a while, someone on p5p finds a construct that gets Deparse'd wrong.

    It's always possible that there's some language construct out there that would make Deparse croak. I'd be surprised, but if you search the perl5-porters archives or here on pm, maybe someone's already found one.

    In any case, though, this won't get you real security, as everyone else is pointing out...
    --
    Mike

      Of course, any Deparse bug that causes crashes will eventually be fixed, so hiding your code behind a Deparse bug is surely rather Pythonish. ("How Not To Be Deparsed," anyone?)

          -- Chip Salzenberg, Free-Floating Agent of Chaos

Re: Can you prevent MO=Deparse
by Abigail-II (Bishop) on May 08, 2003 at 22:25 UTC
    I don't know whether you can turn tainting on in embedded programs, but if you can, you can at least prevent the trick above by turning tainting on.

    Another way to prevent the construct above is to make your own custom perl, in which have removed any support for the backend modules. Then you statically link your C program against the modified perl.

    Abigail

      Thanks Abigail-II, I tested using Taint mode on some scripts this afternoon, and it does indeed prevent it from being deparsed by the above method. Great.
        Are you calling the system's perl? In that case all I need to do is rename it, and put a perl binary somewhere that adds -MO=Deparse to the commandline before calling the renamed perl to make the above trick work again.

        Makeshifts last the longest.

Re: Can you prevent MO=Deparse
by crenz (Priest) on May 08, 2003 at 21:10 UTC

    If you want to hide away passwords, you need to solve your problem on the OS level, not in Perl.

    For example, on a shared webserver you better hide away your database passwords and/or database files (if you use something like DBM). I do this by limiting access to the files that contain sensitive information: Only my userid is allowed to access these files (the proverbial chmod g-rwx,o-rwx myscript.cgi). The programs working with that information either run from my account (e.g. via cron) or as wrapped CGIs (ie., they run under my userid instead of the webserver's).

    This leaves me with no need for obfuscating the source code, and is definitely more secure than any obfuscation method someone could come up with.

Re: Can you prevent MO=Deparse
by hardburn (Abbot) on May 08, 2003 at 13:47 UTC

    No. Next question.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated