Periklis Ntanasis:
Master's Touch

fade out

PHP: Protect the c0d3

Introduction

Protecting the PHP code I wrote has passed my mind in the past but never actually bothered me because the code I have wrote was either open source or hosted in a self-administrated enviroment.

Anyway, as it seems many people are interested in protecting their code from distribution without their permission.

The only true case where I may find it meaningful is when it is about a commercial module that may be redistributed many times and imported in many different projects. In that case the developer may be afraid for pirate redistribution of his work.

However, the best thing a developer can do is to use an appropriate license scheme and get the advice of a good lawyer!

Research

Motivated by this question I have been wondering how someone can secure his PHP code.

After a little research in the interwebz I’ve found that there are two possible solutions:

Source Code Obfuscators

Source code is obfucated to make it hard to understand and make any changes. Example of obfuscation can be removing line breaks, spaces, comments, renaming variables, function names, etc. where applicable, as well as very simple source code encoding. Restoring obfuscated source code is trivial. These solutions are truly insecure, can result in sever performance degradation, and don’t offer 100% code compatibility. None the less such solutions do have a place in the market and are suitable for some people (mostly because they are cheap, about $20, or available for free). You’ll find a bunch quering search engines for "free php obfuscator".

http://www.zubrag.com/articles/php-source-code-encoders-and-protectors.php
— zubrag.com
Encoders

Obfuscate (some can also optimize) PHP source code, compile it to bytecodes, and eliminate the source code. Such solutions are stable and extremely hard to reverse-engineer. Depending on the solution price these will provide you with options to manage licenses, generate files to expire on a given date or after a time period (trial period).

Roughly saying solutions of this type consist of two main parts:

  • Encoder - program which obfuscates, encodes/encrypts source files

  • Loader (decoder) - these programs are designed to decode encrypted sources and feed PHP engine with decoded sources to execute. End user will need to have decoder (loader) installed on their server in order to be able to run your encoded application. Loaders are available for free download.

http://www.zubrag.com/articles/php-source-code-encoders-and-protectors.php
— zubrag.com

So, in other words an obfuscator changes many things regarding the formatting of the program, making it unreadble at first glance. However, the program can still become readable if someone put some effort into it.

The encoders actually encrypt the program by using an encryption algorithm. In order to execute the PHP code a decryptor (loader) has to be installed to the target maschine and the appropriate public key be in place.

Above I’ll demonstrate you both concepts and later I’ll present you some real world solutions!

Let’s have a look

For the above demos I’ll use this pretty cool PHP code:

CoolCode
<?php

/**
* Better use arrays by reference
* http://php.net/manual/en/language.references.php
*
*/

$input = "this is my sample which is sorted and simple";

echo "Input: ".$input."<br/>";

foreach(explode(" ",$input) as $in)
{
        if(isset($firstarray[strlen($in)][$in]))
                $firstarray[strlen($in)][$in]++;
        else
                $firstarray[strlen($in)][$in] = 1;
}

ksort($firstarray);
foreach($firstarray as &$secarray)
{
        ksort($secarray);
}
print_r($firstarray);

?>

Obfuscators

In order to demonstrate how a simple obfuscator works I’ll cook a small java application that uses the power of regex to obfuscate our code!

Here you can find the gist with the whole code.

I’ll just go directly to the interesting part:

code = code.replaceAll("\n|\t", "");        // not tabs and breaks
code = code.replaceAll("/\\*.*\\*/", " ");  // remove the comments

Pattern MY_PATTERN = Pattern.compile("\\$(\\w|\\d)+");  // match variable names
Matcher m = MY_PATTERN.matcher(code);

ArrayList<String> variables = new ArrayList();

// place every variable name in an array
int index = 0;
while (m.find(index)) {
        if (!variables.contains(m.group())) {
                variables.add(m.group());
        }
        index = m.end();
}

// rename the variables with their md5hash (with a leading a infront to
// ensure that their name will start with letter)
Iterator<String> itr = variables.iterator();
while (itr.hasNext()) {
        String variablename = itr.next();
        code = code.replaceAll("\\" + variablename,
        "\\$a" + Coolphpobfuscator.md5(variablename));
}

That what I am doing here are three very simple transformations:

  • Eliminate any line breaks and tabs

  • Remove all the comments (ok, I haven’t actually removed the single line comments but you get the point!)

  • Rename the variables

So after all these transformations our very coolcode will look like that:

ObfuscatedCoolCode
<?php $a6c6f2ffa347ef13815db0c336428e5a1 = "this is my sample which is
sorted and simple";echo "Input: ".$a6c6f2ffa347ef13815db0c336428e5a1."<br/
>";foreach(explode(" ",$a6c6f2ffa347ef13815db0c336428e5a1) as $a679baf73b
aafa7c9f0ada0622c739c32){if(isset($ad490419709e2e8f3f8176b1dd07bb281[strl
en($a679baf73baafa7c9f0ada0622c739c32)][$a679baf73baafa7c9f0ada0622c739c32
]))$ad490419709e2e8f3f8176b1dd07bb281[strlen($a679baf73baafa7c9f0ada0622c
739c32)][$a679baf73baafa7c9f0ada0622c739c32]++;else$ad490419709e2e8f3f8176
b1dd07bb281[strlen($a679baf73baafa7c9f0ada0622c739c32)][$a679baf73baafa7c
9f0ada0622c739c32] = 1;}ksort($ad490419709e2e8f3f8176b1dd07bb281);foreach($
ad490419709e2e8f3f8176b1dd07bb281 as &$a9b6dfdb0fc4e83a29530c5166ed7907f){k
sort($a9b6dfdb0fc4e83a29530c5166ed7907f);}print_r($ad490419709e2e8f3f8176
b1dd07bb281);?>

Actaully, I have introduced some line breaks so you can see the whole code without scrolling but think of it as being a single line.

As you can see this code is obviously not so cool anymore!

So I hope now you get the point! The obfuscation may go on to a higher level, for example you can alter string letters with their numerical code:

<?php
echo "hello";
echo "&#104;&#101;&#108;&#108;&#111;";
echo "\x68\x65\x6c\x6c\x6f";
?>

All the previous lines are echoing hello.

Important Attention! As difficult as it may seems for the obfuscated code to be read it’s just a matter of time until it does from an experienced developer after some "deciphering"!

Encoders

I have write again some java code in order to give you the basic idea behind PHP encoding. The code can be found here.

So let’s see the encoding process:

Encryption
Figure 1. Encoding Process

If you are a little familiar with cryptography then you’ll have already figure out what’s happening. We create an encrpytion key and then we use it and an encryption algorithm to encrypt the source code.

In the particular case I have used the DES algorithm to do that. The cipher text that was generated was the above:

w4P0PI0T9jf6059bbRIAlPqz77hlj5CRmZ4Gz/c3ZSETU3bLO/+WbDYTx9YW3RXkUWjnglCXBIIr
QwnqUpsDfPkhCx2Fg9lNBJyN5cGkKCCMud5+BBB8sTwNFpPUsH2OVPUfhmKjdFea7q2SX0PcThJC
1KW1XCtClIoRAvVgxfK58rT0VsqWtrwiLy1ghlGeSGgS3TUoVguT9IiNLm9Njq3tIe0Dk5l9nOpp
9pW4s8GfGUZQ3WzRENxBAAGb9Y+uFI5lympQfwUG9iz2IZPJFygX4EBfIzIfMIDlyz9uECgYhmuC
bZPw8EyjArf7+m15sKCSALMy/24OTy6dQD5a/t5gFZUa1T2UtChRe/ofna+2ax1vLXx3ToEG9GyC
Kddhck6KwEZMHvgGyBa3dYlyogh6dRcPuvTQTcewa/ESG0MVTW56asbzGBlJn0PYc3WOM6JM+GDO
qusHmJS+Env0+V6scgDZ9p8odDL66776CTJBn3z4rL6laxdtlm76HGiw0QjULVCFcAmrc7i9Gxrs
l2vhMhKYH3AvBGmKOlFlf8kwvWqokfGmRtPMTiZ9dSa+MaivRUxJUD10MvrrvvoJMkxmLFUa7NJf
foobOb33hDbSyPl8i8GMSw==

As you can see it is not possible for someone to decipher this without any help.

Now let’s see the decryption process:

Decryption
Figure 2. Decryption Process

As you could guess decryption is the opposite process that will produce the original source code.

The PHP wrapper in the figure 2 is just a PHP script that will execute the deciphered code. This could be something like that:

<?php
        eval(shell_exec("java -jar Coder.jar -de encoded.txt key"));
?>

However, if you take a look in my code and think the whole process you will spot some problems there.

Firstly, the way I am encrypting the source code I am using a symmetric key algorithm. So, I can decrypt the code with the same key that I am encrypting it. In that way, someone who knows or can asume the encryption algorithm that has been used could easily find the original code.

Secondly, the PHP wrapper is pretty trivial and someone could easily execute the above code to get the original source code:

java -jar Coder.jar -de encoded.txt key

The most common solution in the encryption systems that I have checked is to create a PHP extension that will act as both the decryption mechanism and the php wrapper. This php extension should be installed in the server maschine.

The benefit of doing so is that PHP extensions may be compiled and so the user won’t know which encryption algorithm has been used and wouldn’t be able to intervene and print the code instead of executing it.

Warning In my code I have used code found on the internet. I have commemnded wherever I have used it. Also, both my obfuscator and encoder are very trivial and have been created only for demonstration purposes.

Real World Solutions

I haven’t searched a lot out there but I have spotted some solutions both free software/open source and commercial. I will list them in case you are interested.

Obfuscators

F.O.S.S.

Commercial

From these I have only tested the CodeEclipse. It seems OK to me.

Encoders

Some PHP encoders are also "compiling" the source code in order to gain better execution times. You can find a list with these PHP accelarators in wikipedia.

F.O.S.S.

Commercial

From my little expiriense I can surely advise you not to use the Turck MMCache for PHP. I have tried installing it without luck (I was getting compilation errors) until I figured out that it is discontinued and forked into eAccelarator.

However, eAccelarator removed the encoder and now that feature is not supported.

Other than that I have tested the PHPshadow and you can read about that here.

Overview

Obfuscators can’t protect the code from the experienced developers. They can only slow them down.

Encoders seems to be more effective but they need to install additional software in the webserver. This isn’t always acceptable. Furthermore they are very expensive. However, the speed gain by the compilation that offer the most encryption applications is a plus.

In my opinion, as I have said already in my introduction protecting the PHP source code shouldn’t bother the developer. However, if someone wants to protect her/his code then I guess this would be for the money and not for the pride so I would go for a commercial well tested encryption/acceleration system.

Update

Here are the jar’s of the code mentioned above. These programs exist only as a proof of concept and aren’t created for production use. So use them wisely and at your own risk.

Update 2

Dan was kind enough to take my naive php obfuscator a step further and implement more advanced functionality. His implementation can be found in this gist and a precombiled jar can be downloaded from here.

You can use this obfuscator like that:

java -jar coolphpobfuscator2.jar path_to_input_directory path_to_output_directory

Where path_to_input_directory is the path to the directory which contains the php files to be obfuscated and path_to_output_directory is the directory where the obfuscated files will be placed. Note that path_to_output_directory should already exist before running the program.

Comments

fade out