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.

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.

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:

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:

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.

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:

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:

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.

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

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:

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 queryinghttp://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.

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

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.

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:

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:

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.

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:

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