Uninitiated people often ask questions like “How do I decode an obfuscated PHP-script?”, “Is PHP-script obfuscation safe enough?” and even like “Would you help me to deobfuscate it please, wouldn’t you?”. The main purpose of this article is to show, that obfuscators provide absolutely no protection in 90% cases (which are able to provide protection only from people, who got acquainted with programming language for the first time in their lives). It can be removed in 10 to 20 minutes, as a result you get PHP script in its original form. The rest 10% cases demonstrate slightly stronger protection, which can be removed in similar ways though. If you wish to learn how to remove obfuscation from scripts on your own, then this article is what you need!
As I mentioned above, the problem of deobfuscating PHP-scripts is an issue of the day. Such question is a hot topic discussed on several popular hack-forums. There are also a lot of online services allowing to remove most simple obfuscation variants.
So, let’s discuss step-by-step how PHP scipts should be deobfuscated in most cases. Let’s consider an example from one popular forum topic, which contains requests from people who are not willing to deal with this issue by themselves or think that it is very complicated.
To perform deobfuscation we will need hands, a cool head and Notepad++ (other editor can be used, better the one which is able to highlight similar substrings in document – this will speed up the process of removing obfuscation).
As an example we take completely random script, covered by unfamiliar to me, but very popular lately obfuscator: original.php.
We save it to our web server directory as “original.php“, then save it again under other name, like script.php. I will explain the purpose of this later. Now we open the script and begin to examine it.
As we see, the script itself is small in size, although at the end of the file, after the script, there is a piece of encoded text. We also see eval() PHP instruction call, which executes provided PHP code. In the first place change eval to print, to see the code it executes. To make sure the script is not able to harm our computer in any way, we examine resulting code – it is harmless urldecode() call, several string concatenations and a couple of variable assignments. Besides that, before calling eval(), there is a function executed, which name is stored in variable $OOO0000O0. Let us check if this function is able to do bad things. Firstly we print its name and comment the line containing eval.
Please notice that I edit script.php, keeping original.php untouched. We run script.php in browser and see output: base64_decode. Ok, this means that there is nothing bad happening before eval() call and it can be easily replaced with print().
We run script.php in browser again and see the following output:
Yet this unintelligible code is enough to guess that it opens some file for execution and performs something with it (most possibly, reads). Besides that, there shows up another eval() call. We print the value of $OOO000O00 variable and see, that it is nothing else than name of function – fopen(). But what file is opened by this code? We are going to use Notepad++ highlight:
We see that it is the name of current file, i.e. script.php. We have already changed this script significantly, but we can make the code to read original file, which we kept intact carefully all this time!
Further, we output the value of $O0O00OO00 and make sure that it is the name of function fread and the file is really being read. At first 0x49f bytes are read from this file and then discarded, followed by 0x17c bytes, which are somehow processed by this script. To determine, what exactly it does to them, we output as usual the values of $OOO0000O0 (this is base64_decode) and $OOO00000O (this is strtr) variables. Thus, at first contents acquired from file are processed by strtr(), and then base64_decode(). In short, this means that decoding is performed. Next, decoded content is passed to eval(). Now it can be safely replaced with print().
We run script.php in browser again and see the following piece of code:
We add this to script.php and begin to examine it:
Using Notepad++ highlight (selecting one by one variables with corrupted names) we recognize the familiar sequence base64_decode(strtr(fread())), but the number of bytes to read in fread function is now set implicitly, however this is not a problem, because slightly earlier this number was stored in a variable, which is transferred to fread:
Here is an explicit call to str_replace, which replaces all occurrences of “__FILE__” substring to the name of our file in read and decoded string. So, we change the replacement string to “original.php“, as we did before:
And again we run the script in browser… Oh yeah! At last we got script source code! It has several variables with corrupted names, but this is not a problem, because we are able to see the source code!
That’s it, the script is decoded without any problems and complications! Using this method, analyzing code pieces step-by-step, any obfuscation can be removed in no more than half an hour! Doing this several times to different types of scripts and obfuscators will let you to recognize them by their form and decode them literally in 5 minutes!
It should be mentioned that you should not change anything in scripts covered by the obfuscator discussed here (including comments), because script reads itself, and reading offsets are hardcoded. Therefore, if you change the first comment, for example, by removing a single symbol, you turn the script to a non-executable text file.
I should also mention that while deobfuscating this script I performed lots of unnecessary actions (to show in as much details as possible the step-by-step process of obfuscation removing), and all this can be done in more quick and optimal way if you have a little knowledge about particular obfuscator inner structure.
For certain obfuscators it is possible to make an automatic deobfuscator script to minimize the work.
Some time ago I created a script, which allowed to remove this certain obfuscation, and I’m glad to share it with you. This script is also able to remove the protection (because the obfuscator discussed in this article is able to bind the script to certain domain). Download deobfuscator!