There's been a bit of talk about the Neutrino exploit kit lately, most of it revolving around sites redirecting users to Neutrino. But Neutrino has also been through some interesting technological changes and now the landing page of Neutrino only loads a single Flash file to begin its entire attack flow, a change that makes the Neutrino EK landing page harder to recognize.
In this blog post we will look at Neutrino from a technical perspective and analyze what happens when that single Flash file is loaded. We will show what Neutrino looks for on a client machine to to identify targets and evade security products, what tricks it uses to obfuscate its true intentions, and other interesting tidbits we've noticed during our analysis.
We start off with the landing page, which as we mentioned loads a single Flash file. Unlike many other exploit kits, Neutrino does not pass any arguments to this Flash file using the "FlashVars" parameter.
Figure 1 – The Neutrino Landing Page
On the landing page we can see several variables defined, followed by the loading of the aforementioned Flash file, "aWdpYXd5aXc" which we will now start digging into.
Figure 2 – The main Neutrino Flash
In the image above we can see a decompiled version of the Flash file. We've marked three parts of this Flash file. Two interesting things happen here:
- Ten different chunks of binary data embedded within the file (1) are concatenated into one large byte array of encrypted data, which is then decrypted using the RC4 method "this.g" and the following key stored in variable "_loc51_" (2):
5C F0 10 5D 0D 7F 67 A3 80 93 54 CB 18 6B 6F 55 94 84 24 21 FA F6 D1 FE 2C 89 06 6F 01 1E C3 5D 0E
This data is then loaded as an additional Flash file using the common loadBytes method.
- Instead of being loaded as-is and executing the rest of the attack on its own, the execution continues when the external Flash file loads another chunk of binary data from "r.m" and calls the method "ep" of the inner Flash file while passing "m" as a variable.
This draws our attention to the inner Flash file. At this point in most exploit kits we expect to see the actual exploits, but in Neutrino's case we ran into yet another layer of obfuscation that had to be analyzed. There are several more chunks of binary data within this inner file:
Figure 3 – Binary Data of first inner Flash
It is fairly obvious from the names of these binary data chunks that some of them are Flash and HTML exploits even though the data within is encrypted, but there are a few more blobs of data within this file that are part of the obfuscation:
Figure 4 – Code Snippet of first inner Flash
Figure 5 – class_2.method_7
Looking at this method_7 we see that based on the value it receives, it returns a value from a global array called var_9.
Let's examine var_9 at the time of this code's execution:
Figure 6 – content of the var_9 array
The following piece of code answers these questions in part:
Figure 7 – var_9 being created
method_3 here is responsible for reading data from one of the byte arrays. We see that it first reads an integer which represents the size of the data, and then proceeds to read the number of bytes within this integer into a variable which is finally decrypted using the RC4 key and pushed into var_9.
So these values actually come from the binary data chunks we saw earlier, let's look at them again:
Figure 8 – Binary Data of inner Flash
The actual data used to generate the strings we saw in var_9 is stored in binaryData #7, but in order to decrypt it the code uses a set of 9 RC4 encryption keys stored in binaryData #8 and used iteratively on each of the data items decrypted. Finally, in order to determine which index of var_9 contains the value needed by the code, the number we saw earlier being passed to class_2.method_7 is xor'd with the value stored in binaryData #9.
Looking at the content of binaryData #7 we can clearly see this pattern of an integer representing size, followed by data, followed by another size integer, etc..
Figure 9 – Content of binaryData #7
And looking at the content of binaryData #8 we can clearly see the keys, with the first byte containing the number of keys (0x09) and the rest represent a set of 9 16-byte RC4 keys:
Figure 10 – Content of binaryData #8
Now that we understand how to decrypt the code, let's take a step back from the specifics and understand what it is that Neutrino is actually looking to do with all of this. A global variable, var_12, contains the many pieces of information about the client machine that Neutrino has collected:
Figure 11 – Data collected by Neutrino about the client machine
We can see that Neutrino looks for some interesting things: whether the environment runs PhantomJS, Node.js, Rhino, a debug version of Flash, etc.
Since finding any of the above implies that this is likely a virtualized/test environment rather than a real victim, failing any of these checks will cause Neutrino to stop its execution flow and shut down quietly.
The checks for the less obvious items on this list are as follows:
Figure 12 – Interesting checks performed by Neutrino
If, on the other hand, the client machine passes these checks, Neutrino sends out a pingback to one of its servers (for your convenience, a clear-text version of the code executed using ExternalInterface is shown below in a comment):
Figure 13 – Neutrino sending out a pingback to its servers
Following the pingback, Neutrino will attempt to load 6 different modules exploiting 5 different vulnerabilities, with each exploit module performing its own checks for version/OS/browser in order to decide whether or not to attempt exploitation.
CVE-2015-2419 – Checks that the browser is Internet Explorer.
CVE-2013-2551 – Checks that the browser is Internet Explorer.
CVE-2014-6332 – This CVE has two separate modules, one for Windows XP and one for all newer versions of Windows.
CVE-2015-7645 – Checks for Flash versions 11.4–188.8.131.52
CVE-2014-0569 – Checks for Flash versions 11.6-13.0.0244 and 14.0-184.108.40.206
The last missing piece in this puzzle is binaryData "m" we mentioned at the beginning of this blog post, the one sent from the external ("top") Flash file.
This chunk contains data that changes more frequently in Neutrino, such as which URLs to get the payload from and where to send the pingback request:
Figure 14 – Neutrino URLs JSON
This closes the loop of Neutrino's Flash analysis; we now know where all the pieces of this Neutrino puzzle come from and the whole picture they make up.
It's an interesting shift that Neutrino has made in using Flash as, essentially, a landing page itself. As this analysis shows, they are clearly very well versed in the capabilities of Flash and are using their knowledge in a way that is somewhat different to what we see from their Exploit Kit competitors. As always, it will be interesting to see where they take it next.
This blog post was co-authored by Daniel Chechik and Anat Davidi.
We would like to thank Kafeine for sharing the original saz, which can be found here: https://www.virustotal.com/en/file/05a50b8b9cccdfa6adcb1f1173c021c8944b3aa5312e21e0af015a98735263b2/analysis/1447730847/
Additional decrypted files uploaded to VirusTotal as well:
The inner Flash file:
Trustwave Secure Web Gateway protects customers against the Neutrino Exploit Kit.