Reverse Engineering Hacker’s Code

Yesterday a client came to us with a compromised website. It was a very familiar story. They used WordPress and hadn’t updated their plugins, theme or WordPress core for probably years. A lot of the plugins were abandoned or removed from the WordPress plugin repository and some weren’t even being used.

So it was no surprise really.

We signed in and noticed very quickly that the usual admin ability to add new plugins or perform updates had vanished. This has become the first sign that all is not well with a WordPress site. More on that later.

Taking a quick look at Wordfence’s latest scan log revealed that wp-config.php (the main WordPress configuration file, more on this later too) was flagged as compromised.

Quick look at this file and we found the following injected code (we have changed it slightly so it can’t harm your computer) …

Most developers will remove the code (which we did) and notice that the site admin functions return to normal (if you don’t have any other modified files). The site can then be cleaned, upgraded, patched, etc and most will think that that hopefully will be the end of the problem. But it isn’t. And we will show you why.

So we decided to take the time to see what this code actually does; and we were secretly quite pleased to find it was a bit of a challenge!

The first thing the script does is create an anonymous function using the php command create_function(). Eagle eyed readers will see they have hidden this command (because it’s probably searched for by security plugins) putting “create_” at the beginning and ‘function’ towards the end of the script.

But what is the function it creates? Well that’s all hidden in the encrypted text which takes up the bulk of this code.

To decrypt the text (rather than run it) we found the line which read “$ebalew[2]=gzuncompress(mitagov(235^552,1316^3087));” and changed it to echo the result rather than put it in the array $ebalew[2]. This renders the code safe to run as it breaks the create_function command.

And this is what we discovered …

We quickly realised that our job wasn’t done yet; the script was still riddled with hidden, encrypted variables likeĀ mitagov(24+185,9).

Amazingly, these encrypted variables are extracted by referring to a function in the original code which uses the original encrypted text to hide these values. So we created a function that would allow us to decrypt these variables one by one …

And piece by piece we put the hacker’s code together. Changing the variable names from gibberish to make them easier to read and understand.

So here’s what it does šŸ™‚

The first thing they do is save the error reporting level in PHP and turn off error reporting …

if (function_exists('error_reporting')) {
$error_level = error_reporting();

… at the end they return error reporting to where it was in the first place …

if (function_exists('error_reporting')) {

The next thing causes the symptoms that you find in WordPress …


This tells WordPress not to allow files to be edited which in turn prevents plugins from being installed or any updates from being applied. We assume this is to try to prevent WordPress users from being able to edit the files and remove the hacker’s code but for the life of us we’re not sure why they put this in as it immediately alerts WordPress users that there’s something not quite right!

Next there are a few functions. The first is the most worrying. It appears to be some kind of decrypting algorithm. We think to either decrypt double md5 hashed passwords or to extract an encryption salt or something else, we’re not 100% sure. So we’re not going to show it but it’s fired when a cookie is found on the user’s computer so we think it’s either to identify the hacker and show them something or it’s to identify a logged in user and capture their login cookie.

The code then runs though the page’s passed query variables, makes changes to them and saves them back to the query variable.

The following array of server directories …

$array_of_local_directories_to_test = Array( '/dev/shm', '/run/shm', '/run/lock', $directory_path.'/wp-content/cache', @ini_get('upload_tmp_dir'), @$_SERVER['TMP'], @$_SERVER['TEMP'], @$_ENV['TMP'], @$_ENV['TMPDIR'], @$_ENV['TEMP'], '/tmp/.font-unix', '/tmp/.ICE-unix', $directory_path.'/tmp', $directory_path.'/wp-content/uploads', '/tmp', @session_save_path() );

… is then tested to see if the script has permission to write to them!

It then tests to see if the user is in fact a search engine and then it contacts the following servers …


… and sends them everythingĀ it’s found including a copy of the WordPress wp-config.php file.

We have only looked at this code for a few hours and may not have got everything right … but … the upshot is that if you find anything similar to this in your WordPress installation then removing it and cleaning the site is not enough. You will need to do the following afterwards …

  1. Change all your user passwords
  2. Change your database password (and username and database name if you can)
  3. Change all theĀ Authentication Unique Keys and Salts that are set in the wp-config.php file

We hope this hasn’t scared you too much but if there’s one thing we’d like you to take from this post, it’s to take the security of your website even more seriously!