Late last week saw the appearance of a new ransomware called GandCrab. Surprisingly, it is distributed via two exploit kits: RIG EK and GrandSoft EK.
Why is this surprising? Other than Magnitude EK, which is known to consistently push the Magniber ransomware, other exploit kits have this year mostly dropped other payloads, such as Ramnit or SmokeLoader, typically followed by RATs and coin miners.
Despite a bit of a slowdown in ransomware growth towards the last quarter of 2017, it remains a tried and tested business that guarantees threat actors a substantial source of revenue.
Distribution
GandCrab was first spotted on Jan 26 and later identified in exploit kit campaigns.
RIG exploit kit
The well-documented Seamless gate appears to have diversified itself as of late with distinct threads pushing a specific payload. While Seamless is notorious for having switched to International Domain Names (IDNs) containing characters from the Russian alphabet, we have also discovered a standard domain name in a different malvertising chain. (Side note: that same chain is also used to redirect to the Magnitude exploit kit.)
We observed the same filtering done upstream, which will filter out known IPs, while the gav[0-9].phpstep is a more surefire way to get the redirection to RIG EK.
At the moment, only the gav4.php flow is used to spread this ransomware.
GrandSoft exploit kit
This exploit kit is an oldie, far less common, and thought to have disappeared. Yet it was discovered that it too was used to redistribute GandCrab.
GrandSoft EK’s landing page is not obfuscated and appears to be using similar functions found in other exploit kits.
Ransom note
Interestingly, GandCrab is not demanding payment in the popular Bitcoin currency, but rather a lesser-known cryptocurrency called Dash. this is another sign that threat actors are going for currencies that offer more anonymity and may have lower transaction fees than BTC.
Technical analysis
After unpacking, the binary is pretty straight forward as far as analysis is concerned. There were no attempts to obfuscate data or code beyond just the first layer of the packer. Everything from the exclusion file types to web request variables, URLs, list of AVs—even the whole ransom message—is in plain text within the data section. On initial look-through, you can deduce what some of the functionality might be just by simply looking at the strings of the binary.
The code flow stays relatively inline, so as far as reverse engineering is concerned, it allows you to quite accurately analyze it even just statically in a disassembler. The code is divided up into three main segments: initialization, network, and encryption.
Initialization
After unpacking, GranCrab starts out with a few functions whose tasks are to set up some information to be used later in the code. It queries information about the user such as:
- username
- keyboard type
- computer name
- presence of antivirus
- processor type
- IP
- OS version
- disk space
- system language
- active drives
- locale
- current Windows version
- processor architecture
It specifically checks if the keyboard layout is Russian, writes out an integer representation for that result, and builds a string with all this info. Below is the code that is starting to write out the variable names to label the information gathered:
It then cycles through all letters of the alphabet querying if a drive exists and what type it is. If it is a CDRom, unknown, or non existent, it skips it. If a fixed drive is found, it copies its name to a buffer and copies a string describing what type of drive it is. For example, the C: drive is FIXED.
It then gets disk free space and information on sectors that it converts into another series of numbers via printf function tokens: C:FIXED_64317550592. It continues this for every drive and builds a list.
It puts all of the information gathered on the system together and you can assume, before you even get to this point in the code, that this will be sent up to a C2 server at some point, as it is in the format of a GET request. Here is an example of how the system info gets structured below:
ip=99.8.160.100&pc_user=virusLab&pc_name=VI
It also searches running processes, checking against a finite set of antivirus programs that will also be converted to the info string for the C2 server.
It then proceeds to create a mutex with some system info along with a generated ID. For example:
Global\pc_group=WORKGROUP&ransom_id=c9ed65de824663f
In order to initialize itself for the future encryption, it cycles through a hardcoded list of processes to kill. This is a common technique among ransomware that attempts to kill processes that might have a lock on certain files, which it would like to encrypt.
KEY PROCESS LIST:
msftesql.exe sqlagent.exe sqlbrowser.exe
sqlservr.exe sqlwriter.exe oracle.exe
ocssd.exe dbsnmp.exe synctime.exe
mydesktopqos.exe agntsvc.exe isqlplussvc.exe
xfssvccon.exe mydesktopservice.exe ocautoupds.exe
agntsvc.exe agntsvc.exe agntsvc.exe
encsvc.exe firefoxconfig.exe tbirdconfig.exe
ocomm.exe mysqld.exe mysqld-nt.exe
mysqld-opt.exe dbeng50.exe sqbcoreservice.exe
excel.exe infopath.exe msaccess.exe
mspub.exe onenote.exe outlook.exe
powerpnt.exe steam.exe thebat.exe
thebat64.exe thunderbird.exe visio.exe
winword.exe wordpad.exe
Next, it calls the built-in crypto functions to generate keys. GandCrab generates the public and private keys on the client side and uses the standard Microsoft crypto libraries available using API calls from Advapi32.dll. It calls CryptGenKey with the RSA algorithm.
Network connection
Now it enters the main loop for the Internet functionality portion of the ransomware. This area of code either succeeds and continues to the encryption section of code, or it loops again and again attempting to succeed. If it never succeeds, it will never encrypt any file.
This section starts off by making a GET request to ipv4bot.whatismyipaddress.com that saves the IP address returned and adds to the GET request string, which has been built with the system information.
It continues and takes a binary chunk, which is the RSA public key that was stored earlier in the initialization. That key is converted to base64 via the CryptBinaryToStringA API with the following parameters:
CRYPT_STRING_NOCRLF and CRYPT_STRING_BASE64
It will be tacked on the the existent GET string, which it has been building this whole time. Below is an example of the RSA key generated in binary and its conversion, followed by the finalized GET string with the base64 of the keys in it:
This is an example of an RSA public key generated with the crypto APIs:
A7 EC BD E2 49 43 E1 11 DA 12 10 E0 25 59 AA 83 77 35 FC 3E 49 C8 3B 6C 3D 91 CF FF 96 6E D8 45 FE 8A 58 20 E6 CB 91 AB 99 6A E2 04 EC 58 66 95 05 8C 2F 7E C6 19 6D 24 B5 5F C4 9A 01 3D 3B FB 31 4E AC 25 07 8C 0E 6C 57 4C C0 23 24 3A EB 57 97 17 79 F8 62 73 6B AD B2 09 60 BB B7 9A CF F9 5B 68 B8 C1 44 07 F5 5E 3E 06 FE C2 35 CF 99 82 29 28 37 1B E6 51 29 6C 0B 87 89 F9 90 26 F7 CC DA 75 C4 46 A1 E3 30 09 C0 6A CB 5E CB 87 8E 40 EF 4C 7E 02 AE E8 06 6A D7 24 FC 0E 40 EA 69 CD 6D 8D 24 92 6E 53 2F D2 69 D2 A2 F3 97 54 63 EB D9 C7 BD 9E 41 19 91 F1 6B D6 CA AD 9E 0E D3 0B A0 53 50 84 87 6D 49 4C 49 D2 3B 8E 80 F7 7F 35 F1 D7 A7 81 0F 90 04 40 AC 4B 7C ED 37 71 8A B1 FA 84 33 33 FB 62 EE 04 A3 C7 9A 47 2C 64 64 95 3D 34 A5 CC 12 6E E4 81 40 E6 7F 03 02 C4 57 D6
Which gets converted to:
BgIAAACkAABSU0ExAAgAAAEAAQCn7L3iSUPhEdoSEOAlWaqDdzX8PknIO2w9kc//lm7YRf6KWCDmy5GrmWriBOxYZpUFjC9+xhltJLVfxJoBPTv7MU6sJQeMDmxXTMAjJDrrV5cXefhic2utsglgu7eaz/lbaLjBRAf1Xj4G/sI1z5mCKSg3G+ZRKWwLh4n5kCb3zNp1xEah4zAJwGrLXsuHjkDvTH4CrugGatck/A5A6mnNbY0kkm5TL9Jp0qLzl1Rj69nHvZ5BGZHxa9bKrZ4O0wugU1CEh21JTEnSO46A93818dengQ+QBECsS3ztN3GKsfqEMzP7Yu4Eo8eaRyxkZJU9NKXMEm7kgUDmfwMCxFfW
And builds the GET string to send to the C2 with all the system information from earlier, and also the encryption keys:
action=call&ip=99.8.160.100&pc_user=virusLab&pc_name=VIRUSLAB-PC&pc_group=WORKGROUP&pc_lang=en-US&pc_keyb=0&os_major=Windows 7 Enterprise&os_bit=x64&ransom_id=c9ed65de824663fc&hdd=C:FIXED_64317550592/50065174528&pub_key=BgIAAACkAABSU0ExAAgAAAEAAQCn7L3iSUPhEdoSEOAlWaqDdzX8PknIO2w9kc//lm7YRf6KWCDmy5GrmWriBOxYZpUFjC9+xhltJLVfxJoBPTv7MU6sJQeMDmxXTMAjJDrrV5cXefhic2utsglgu7eaz/lbaLjBRAf1Xj4G/sI1z5mCKSg3G+ZRKWwLh4n5kCb3zNp1xEah4zAJwGrLXsuHjkDvTH4CrugGatck/A5A6mnNbY0kkm5TL9Jp0qLzl1Rj69nHvZ5BGZHxa9bKrZ4O0wugU1CEh21JTEnSO46A93818dengQ+QBECsS3ztN3GKsfqEMzP7Yu4Eo8eaRyxkZJU9NKXMEm7kgUDmfwMCxFfW &priv_key=BwIAAACkAABSU0EyAAgAAAEAAQCn7L3iSUPhEdoSEOAlWaqDdzX8PknIO2w9kc//lm7YRf6KWCDmy5GrmWriBOxYZpUFjC9+xhltJLVfxJoBPTv7MU6sJQeMDmxXTMAjJDrrV5cXefhic2utsglgu7eaz/lbaLjBRAf1Xj4G/sI1z5mCKSg3G+ZRKWwLh4n5kCb3zNp1xEah4zAJwGrLXsuHjkDvTH4CrugGatck/A5A6mnNbY0kkm5TL9Jp0qLzl1Rj69nHvZ5BGZHxa9bKrZ4O0wugU1CEh21JTEnSO46A93818dengQ+QBECsS3ztN3GKsfqEMzP7Yu4Eo8eaRyxkZJU9NKXMEm7kgUDmfwMCxFfWGRZmQmHH5W5K1RYgSg8VJEFLebRW8+o7X0K30wzzrw5NHpJpVJYX8OKot8KvopS4wsZzuxu5YJih1ZYVgF6QT5FW4WEG3BzMtq5vGVqTmrlckudC0xfGlGb7J41vUkZsp6S07NTIIT7HtYJSA/pxS51Zg+13TfU0nxC92RkKuva/8Dzmgssm6uE7aYJQFEkUmkPImYreHGIPsffEEGtZM9zwz4tXbrXLch0BoRNHeR+GFLJclnLc5JMg/J4BLaS6js+RGxRbZGMPJDVX6lTEEl+aIYO38Wh49+Zcpzs4EOUfb1EsoLEDAZbppIWq8Yr1P6KtWkqIXRzjUk9HXiJm3qHm0u0vchV4iRAKz2MJ/xZdYjHp+C3qMTTsNbQbtcscpy13/rEv8oO6clfciSCPcthy5IkLFLKZQP5be+IcsAjxeSoOqqtEpNpj8nOKfZ5PvEs+/kn718vG0R5CMU4I0fyF0BD68AFat6dl5gHK1sKs0ndAvCKdDMg/HqO/JKUZRSza2VKkgxpXC57BRGNP0r/jYySGnqhE2owHQaXoEmP9tme1A8PHsAoNtUEd0SO4/pn4hDg70o/Nmph/UWqtOq9nSlrxQMD8Q08w4K2H1CC3eCAnHZOM8PTCDYH3nh6f/ftkVtyrpudTpicTjoUSEkwtEPRsWk7ff3F/Na8D2FcXSI5xQ6R+R2uy8GvVoxpBy8Xdh78VqViOBlu5+Jxp09PMQmI2EFususg4VJeH047Wayi2r+VemzAX1rTuMh2mRKfKa+eae+YBKjBUkIh9WPCmFjO+3lll7GqV7P4JFm1g2sjrm/dPWnoGzfg1E7brER6aD2q+w1+4o8wCzNTNvPH2bwPMyV6R+vbWOVZUTprzZ4sRr7KxT0ucZmNA76WX39NegSU56tOngYpAQprOMrJP0NYmrizT8FsCOcqlUGk0jf6moarJSWQxh2MxXtlpFAvJjPTqqKruIVMhIkTJ9aZHKnn02a5PIdLcs4a09D85js9klKZn90Gj6C4AxlT2nI/ba9mEx+7srvxxbh1XNgI987IWLsLYpWxHlRptJqIvI0ZAA3EuvwZuZ8f6sqLM2/rSxdOnFW5hd8am9zgopimktfkjFtsHpev/Svf0VlxQ3Fj22A06aXqfi7hmWPZ8ZCtZ874PUHgbrG3foNESQiTghT2NLV9rNNad7ij/kVA= &version=1.0
[Crypto key base 64 functions]
[Section of code that is adding the encoded keys to the get string under priv_key parameter]
At this point, it is clear that the malware will be sending this info to the C2 server. This is interesting because it may be possible to pull the keys from memory and use them for the decryption of files. We will continue to investigate this and update the article if any discoveries are found.
GandCrab’s server is hosted on a .bit domain, and therefore it has to query a name server that supports this TLD. It does this by querying for the addresses of the following domains using the command:
nslookup [insert domain] a.dnspod.com.
This command queries the a.dnspod.com name server, which support the .bit TLD for one of the domains below.
bleepingcomputer.bit nomoreransom.bit esetnod32.bit emsisoft.bit gandcrab.bit
The NSlookup child process is opened through a pipe that was created. This is done so that a child process can directly affect the memory in the parent process, rather than transferring outputs manually back and forth. It is an interesting and useful technique. You can look at the following section of code for more details:
The ransomware now attempts to send data to the server, and if an error occurs or the server was not reachable, it continues this whole process in an infinite loop until it finds one that works, re-querying for client IP and running nslookup again and again with different IP outputs. Unless it connects with the server, it will run until it is closed manually.
As mentioned before, it will not continue to the encryption routine until it finds a server, which means it will enter in an infinite loop of IP requests:
Once it finds one of these, it continues to open a thread that will start the main encryption functionality. However, before it begins, it opens another thread that creates a window and labels itself as Firefox.The window is loaded with code that will copy itself to the temp directory and set itself up in the registry. This is actually one of the few parts of the malware that is not taken directly from plain text. The file name copy of itself is a random series of letters generated by calling the cryptGenRandom function, and using its output on an array of letters.
The strange part about this function is not what it does, because it is creating persistence that we had been waiting for, but rather why a window was created in the first place. As far as we could understand, there is no benefit of launching a window to perform these tasks. Maybe it was experiment on the part of the author, but the intent remains unclear.
Encryption routine
As we have established from the initialization section of the malware, the encryption algorithm used is RSA. Before we get the encryption section, the code makes sure that it is not encrypting specific types of files that it considers protected. The files are the following, hard coded into the malware:
desktop.ini autorun.inf ntuser.dat iconcache.db bootsect.bak boot.ini ntuser.dat thumbs.db GDCB-DECRYPT.txt .sql
If it finds that the file name is on that list, it will skip it and continue to the next. It also skips looking into a folder if it is one of these key folders:
local app data windows programfiles program data ransomware localsettings
When it passes these checks and gets to a specific file, it runs one final check on the extension against a list of acceptable file extensions to be encrypted:
If all checks pass, it proceeds to use the previously generated keys along with some salt and random number generated to encrypt the file and rename it with a .GDCB extension. The main encryption loop is a recursive function that will eventually make it to every file on the drive.
Protection
Malwarebytes users are protected at the delivery chain (exploit protection), but we also proactively stopped this ransomware before having seen it, thanks to our anti-ransomware engine:
Conclusion
It is interesting to see a new ransomware being distributed via exploit kits in what so far seems to be a few ongoing campaigns. The other interesting aspect is that two distinct exploit kits are delivering it, although it is unclear if the same actor is behind both campaigns and experimenting with different distribution channels.
Working as a cyber security solutions architect, Alisa focuses on application and network security. Before joining us she held a cyber security researcher positions within a variety of cyber security start-ups. She also experience in different industry domains like finance, healthcare and consumer products.