Spam. The unbeatable modern plague.
From email providers like FastMail failing to recognize a sender as a spammer even after dozens of reports…
… to numerous Nigerian princes still in dubious financial trouble, it’s as ubiquitous today as it was decades ago.
An increasingly popular vector of attack these days is using outdated web applications as a “patient zero” and infecting the rest of the shared hosting server with some straightforward but overobfuscated PHP scripts that do one thing, and do it well - send spam. Even if the site is hosted on a dedicated or virtual private server, it’s still just as vulnerable if it’s using outdated plugins or CMSes like WordPress or Joomla.
A developer from the Netherlands who is, by some miracle, not yet our author, recently encountered such a script and took it apart at the seams to see what makes it tick. The story is a very interesting one, and his process of reverse engineering it is highly intriguing, so I encourage you to check the full post out, but I’ll briefly recap it here.
The script, when first encountered, looked like a jumbled mess of (much more of) this:
$GLOBALS['jihux92'] = $j10[86].$j10[62].$j10[86].$j10[64].$j10[73].$j10[27].$j10[19]; $GLOBALS['qsxte55'] = $j10[27].$j10[0].$j10[0].$j10[15].$j10[0].$j10[64].$j10[0].$j10[27].$j10[39].$j10[15].$j10[0].$j10[19].$j10[86].$j10[62].$j10[79]; $GLOBALS['eexet82'] = $j10[30].$j10[73].$j10[15].$j10[62].$j10[64].$j10[33].$j10[27].$j10[6].$j10[15].$j10[33].$j10[27]; $GLOBALS['cydwn23'] = $j10[93].$j10[92].$j10[93].$j10[33].$j10[12].$j10[87].$j10[87]; $GLOBALS['dmvah16'] = $j10[33].$j10[27].$j10[56].$j10[86].$j10[62].$j10[27];
After cleaning it up by introducing new lines and replacing references to $j10
with the values defined in $j10
at the top of the script, Jelle realized many of the obfuscated values are PHP function names:
$GLOBALS['dmvah16'] = "define";
$GLOBALS['uvmxr50'] = "isjdn82";
$GLOBALS['oluxf50'] = "zumzi73";
$GLOBALS['gyeof37'] = "md5";
$GLOBALS['frpwz79'] = "count";
$GLOBALS['yguel83'] = "time";
$GLOBALS['vrubd73'] = "constant";
$GLOBALS['cnftt27'] = "mxdtw46";
$GLOBALS['lfazz33'] = "zdowx44";
$GLOBALS['haimq43'] = "vgrtr3";
$GLOBALS['xfeye26'] = "implode";
$GLOBALS['whzhh71'] = "array_keys";
$GLOBALS['bqdjr8'] = "robma76";
$GLOBALS['uulbr4'] = "moijk28";
$GLOBALS['nqqaa78'] = "eklqy22";
$GLOBALS['mdxuq1'] = "rwznq6";
Applying them to the rest of the code and removing these placeholder variables altogether through a few more passes, the resulting script when prettified and made readable looks nothing short of impressive. It’s a bit too long to paste, so check out Jelle’s upload if you’re curious here or the syntax highlighted version here.
What’s particularly interesting is the amount of effort the spammer went through. This is no mere throwaway script - it not only silences errors, but also checks for available connection types, uses sockets, and even checks the DNS records of an email address to make sure it’s valid. This is no mere spambomb.
Obviously, finding out where this script gets its targets and when it gets triggered is another matter, but its logic alone warrants a separate autopsy post. Until we write it, do let us know if you’ve seen something like this in your own codebases and if so, if you’ve made a similar attempt at reverse engineering it. We’d like to see your examples, compare the levels of sophistication, and maybe even try to find common “signatures” in the code styles.