Perl Obfuscator - Introduction and key concepts

Table of contents

Key facts about Perl-Obfus

  • It never overwrites input files.
  • It has both GUI and command line interfaces. GUI uses command line interface under the hood, but GUI adds some handy tools, so GUI interface is more powerfull and feature-rich and is more recommended to use.

    It's really greatly recommended to use GUI interface to set up the project. Later you can export scripts (or .bat files for Windows) that allow you to build/rebuild/clean your project from command line - they are called buildscripts.

    And if you insist on never using GUI interface (it's very bad idea!) you can still generate command line using GUI on your computer (go to Tools ⇒ Command line builder) or online command line builder available on our site.

  • Trial version can perform only one kind of transformation for symbol names - by prepending string ReplacementFor_ to them. This does not limit your ability to evaluate Perl-Obfus in any way! The trial version does allow you to fully evaluate Perl-Obfus and prepare your project for obfuscation using only trial edition.

    Just imagine that instead of ReplacmentFor_someFunction you'll get z78a4b2e. Those symbols that got prefix with trial version will become something unreadable when protected by non-trial. It's easier to prepare project for obfuscation using this kind of replacement (when some prefix is prepended), so it's called a debug mode. Using debug mode is recommended when using non-trial version of the product too! - as it allows to understand what's going on much easier (you'll get errors looking like "unknown symbol ReplacementFor_someFunction" instead of "unknown symbol z72a63be9f" - the former is much more readable when debugging!).

    Once you created a project, prepared it for protection using trial, you can purchase non-trial, just open that project in non-trial edition, click Build ⇒ Rebuild all and you'll get your project fully protected. So you won't loose any time spent evaluating trial edition.

  • Default settings and values of parameters are safe and reasonable.
  • Obfuscation of the project is not as quick as zipping the folder with source code - you have to confiure your project (by listing names that should not be modified, called exceptions) and even modify your code a little in case you use eval() in your code . So be ready to spend from hours to days before you get protected version of your code that works correctly after obfuscation.

Key concept: exceptions - names of symbols that should not be modified

The purpose of Perl-Obfus is to replace symbols with meaningless names. Apparently, not all symbols can be changed without introducing errors. For example, names of subs that you use from modules shipped with Perl, like getcwd from POSIX.pm, can not be changed. Names of such symbols should be added to the list of exceptions - so obfuscator does not change them adding symbols to exceptions .

Symbols defined in 3rd-party modules

If your code calls some functions from 3rd-party modules that you are not allowed to modify or are shipped with Perl , you have to list all symbols that you use from those modules as exceptions adding symbols to exceptions .

Perl-Obfus ships with a lot of tools that help generating exceptions for 3rd-party modules extacting list of symbols .

Exporting symbols to 3rd parties

If your code is in fact a module that you sell or distribute, then you have to list as exceptions all symbols defining its API adding symbols to exceptions . Use tools shipped with Perl-Obfus to generate exceptions for API of your module extacting list of symbols

Dealing with names of symbols in strings

Find all places in your code that uses symbol names to make a reference. Add the following lines to the begining of those files (or make sure that the definitions of these functions are visible to your code from some base module):

    #the definition for SN and SNS
    BEGIN{eval('sub SNS{@_;}sub SN{$_[0];}');}
	#SN takes just 1 symbol as argument. 
	#SNS takes a LIST of symbol names as arguments.

Most typical is update necessary to use vars statement, where you will have to wrap the list of symbol names into call of SNS:
#before
    use vars qw($foo @bar %blah);
#after
    use vars SNS(qw($foo @bar %blah));

Sometimes you may have to put that use vars block inside BEGIN{} block if use vars block is at the topmost level in your file.

Sometimes, your code refers to names of functions or variables inside the strings, e.g. in strings passed to eval() function. What to do in such case:

If the name of the symbol inside the string is computed at runtime
(e.g. entered by the user ), then the only option you have is to list all possible names of symbols that can be used this way in your code in the list of exceptions adding symbols to exceptions .

Sample:

sub f1 {}
sub f2 {}

my $subnm = CGI::param('what'); #assuming it can be 'f1' or 'f2', 
	    #you have to put both f1 and f2 to list of exceptions
&$f1();

If the name of the symbol is a constant string
you have these options:
  • put that symbol to the list of exceptions to prevent it from being modified adding symbols to exceptions .
  • List that symbol as "quoted symbol name". In this case Perl-Obfus will replace every string whose value is equal to the symbol name, with a string equal to mangled symbol name. Strings that include some other characters around symbol name won't be changed. Register "quoted symbol name" in Symbols ⇒ Edit strings that contains symbol names if using GUI, or put them, one symbol per line, to a text file and pass its name after --quoted-symbol-names command line option if using command line interface.
  • wrap that name in the call to SN function
    #before
        my $method = "process";
        $obj->$method();
    #after
        my $method = SN("process");
        $obj->$method();
    
    #before
        my $varname = "myvar";
        eval("\$$varname = 23; \$blah = 15;");
    #after
        my $varname = SN("myvar");
        eval("\$$varname = 23; \$" . SN('blah') . "=15;");
    

    For this to work, add the following lines to the begining of your files (or make sure that these definitions are visible to each of your files):
    BEGIN{eval('sub SNS{@_;}sub SN{$_[0];}');}
    

GUI has special tool to help with this - it lists all symbols found inside strings, in Symbols ⇒ View strings encountered in code. Most probably you should copy list of such symbols to Symbols ⇒ Edit strings that contains symbol names, or to the list of exceptions (Symbols ⇒ Edit user-specified exceptions), or alter your code by wrapping string constants with those symbols in call to SN().

Update the export tables for your modules and 'use vars' statements

Modify all modules that have @EXPORT variable defined and that use Exporter.pm, to use SN and SNS subroutines (read previous step for more information). E.g. code before:

BEGIN {
        use Exporter   ();
        use vars       qw($VERSION @ISA @EXPORT %h1 @list1 $var2);
        $VERSION     = 1.00;
        @ISA         = qw(Exporter);
    
        @EXPORT      = qw(%h1 @list1 $var2);
};								    

The code should look like the following after your modifications:
sub SN { '';$_[0]; } #return 1st argument
sub SNS { '';@_; }	#return all arguments

BEGIN {
        use Exporter   ();
        use vars       (SNS(qw($VERSION @ISA @EXPORT %h1 @list1 $var2)));
        $VERSION     = 1.00;
        @ISA         = qw(Exporter);
    
        @EXPORT      = SNS(qw(%h1 @list1 $var2));
};								    

Note that list of names of variables in 'use vars' was wrapped in call of SNS; the initializer of @EXPORT was also wrapped in call of SNS();

Steps for obfuscating the project with Perl-Obfus

Step 1: add SN to your code

Alter all places where your code refers to names of symbols inside string constants, by wrapping names of symbols into a call of SN or SNS function, as explained above.

Then test that after these changes your unobfuscated code works same as your original code.

Step 2: collect set of exceptions for your code

A lot of tools for this are shipped with Perl-Obfus extacting list of symbols

Step 3: process your code using lite protection and test it

With lite protection, names of symbols that are to be made unreadable, will just get ReplacementFor_ prefix. This will result in error messages looking like "Undefined function ReplacementFor_SomeFunctionName" when you'll run your code - it will clearly indicate that symbol SomeFunctionName should be added to the list of exceptions (see more on what exceptions are here).

Proceed to next step only if your protected code works fine.

Step 4: process your code using non-lite protection and test it

After switching protection mode to non-lite, your code should work exactly as when protected by lite protection. Note that trial version of Perl-Obfus can perform only one kind of transformation for symbol names - by prepending prefix ReplacementFor_ to them. This does not limit your ability to evaluate Perl-Obfus in any way as mangling integers and strings in non-lite mode is the same for both trial and non-trial, so once you tested your code protected with trial in non-lite mode, you will need only minimal testing of code once upgrading trial into non-trial of Perl-Obfus.