Support → Documentation → Perl-Obfus suite → gen-ident-exceptions.pl

1. Make sure you know about online commandline builder for Perl-Obfus
2. Prepare makefile
3. Update use of symbol names in the modules
4. Update the export tables for your modules and 'use vars' statements
5. Test your original code with all modifications necessary for protection applied
6. Collect names of symbols that should not be modified.
7. Test protection with "lite" protection applied

# Steps in detail

## Make sure you know about online commandline builder for Perl-Obfus

Make sure you are aware of Stunnix interactive online commandline builder. It not only helps to build command lines, but can be used as a Table Of Content for the Perl-Obfus manual.

## Prepare makefile

Prepare a Makefile for a Make utility or compose a script that will perform protection for your entire project; make sure that it allows to edit commandline options applied to all invokations of Perl-Obfus in a single place. It will be very useful since you will have to run Perl-Obfus on your entire project several times, with different settings.

## Update use of symbol names in the modules

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
        sub SN { '';$_[0]; } #return 1st argument
        sub SNS { '';@_; }	#return all arguments

If the name of the symbol is a string constant, wrap it into the call of SN subroutine:

    #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;");

If your code uses some string that comes from external source as a name of the symbol, list all possible names of symbols as exceptions. E.g. the example below you will have to list 'f1' and 'f2' as exceptions in the 'exceptions.txt' file, otherwise your code won't work once protected since there won't be subroutines with names 'f1' and 'f2' (there would be subs with names something like z343a1b034 and z5e915db6).

    sub f1 {}
    sub f2 {}

    my $subnm = CGI::param('what');
    &$f1();

## 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();

## Test your original code with all modifications necessary for protection applied

Make sure your original code, after making all modifications described in the steps above, works as the code before your modifications.

## Collect names of symbols that should not be modified.

There can be several reasons a symbol should not be replaced with a meaningless string - most frequently case is when the symbol is in external module that is shipped in non-protected form (for perl, such modules are e.g. CGI). Another case is when some symbols are used from the parts of your application, that are not obfuscated - e.g. from html templates with embedded perl code.

There are several options available on how to do this:

1. Only for the first case (symbols from external Perl modules): use 'gen-ident-exceptions.pl' utility shipped with Perl-Obfus, like this: (command will save list of external symbols used by files 'file1.pl', 'file2.pl', 'file3.pm' to file named 'symlist.txt') - for unix (assuming you don't have any third-party modules in the directories relative to current - i.e. if all third-party modules reside in /usr/):

       	gen-ident-exceptions.pl -d / symlist.txt file1.pl file2.pl file3.pm ..

   for windows (assuming you don't have any third-party modules in the directories relative to current - i.e. if all third-party modules reside in 'c:\'):

       	perl gen-ident-exceptions.pl -d c: symlist.txt file1.pl file2.pl file3.pm ..

2. For symbols that are defined in public interface of ActiveX or OLE component, it's possible to extract names of these symbols using Project Manager. Start Project Manager, go to the Tools menu and select 'Extract symbols from ActiveX components' (this menuitem is available only on Windows platforms). For each component your project uses, select the component, click 'Extract' button, and you will be prompted to save a list of exceptions extracted from the component to the file of your choice. Please note that Evaluation and Demo editions don't offer this functionality (empty file will be produced).
3. Produce list of exceptions manually. Sometimes this is necessary even for symbols from external Perl modules too. Just add them to the file (e.g. named 'symlist.txt') one per line.

## Test protection with "lite" protection applied

Apply "lite" protection to your application, and test as much of your app as possible (i.e. try to perform all operations, or at least most common; try to visit links of all types on the site or all menuitems in GUI app). The 99% of the problems encountered when trying to run protected app is that some symbol from external module was not listed as exception, and got replaced with different name. Once run, you will get errors like "Undefined subroutine CGI::z34ea8c" in places where original code calls "CGI::param()" and "param" is not listed as exception. In order to easily identify that "CGI::z34ea8c" should stand for "CGI::param()", one should to use "lite" protection, that will make symbols only slightly less understandable, but different from original, e.g. you will get errors like "Undefined subroutine CGI::Z439Z_param", that will signal you that "param" is not listed as exception. The following commandline will stand for "lite" protection:

    perl perl-obfus -i prefix -n none -s none -e 0

that will stand for "Number of encoding iterations applied: 0 - don't encode", "Obfuscation of symbol names: none", "Obfuscation of integer constants: none", "Obfuscation of strings: none" options in interactive online commandline builder.

You can use find-undeclared-subs.pl - utility shipped with Perl-Obfus, for finding calls of undeclared subroutines instead of some fraction of manual testing of modules. If your code uses 'use strict' pragma, it will help a lot too, since undeclared variables will be detected at compile-time.

Once your app works correctly once such "lite" protection is applied, you should apply "final" protection, using options you wish. It such "finally-protected app" works differently, revert commandline options back to "lite" protection, and turn on each type of protection incrementally, e.g. turn on "Obfuscation of integer constants", then "Obfuscation of string constants", then "Number of encoding iterations applied: 10", testing your app one each step. Make sure you are familiar with the "BUGS" section in Perl-Obfus manual, that lists common bugs revealed in the Perl interpreter itself when it runs protected code, and update your orignal code accordingly.