Analysis of a piece of ransomware in development: the story of ‘CryptoApp’

Ransomware sure has had an uptick the past years; more and more variants appear while some have been leading the pack for the past years. This article is on a new ‘strain’, it dates to March this year from what I can tell. I haven’t seen any write-up or info about it yet (nor had any major incidents at $dayjob or heard of it from any other analysts). From what I can tell its still under development, this article will tell the story of this ransomware.

Discovery

I was going through some Tor hidden service addresses (onion addresses) I obtained by scraping. Normally there are a lot of markets and random ‘hacker-for-hire’ sites but this one stood out. Its address (as of writing this article) is:

guhvuoz7am24b5mv.onion

Note:
The service did go down at the start of August. It could be that the ‘project’ was stopped or that the other simply moved to a new C2 to start his operation; with the old one being a test setup.

When visiting the hidden service I was greeted with the following:

This message looked like the kind seen with Ransomware like CryptoWall etc. It got my attention because it talks about files being cripted with RSA-2048 which is really similar to the CryptoWall message. After payment of the ransom files would be restored. Scrolling down we get section 2:
image
This section says there are no ways to decrypt the file without the original key (makes sense if you use RSA on 2048). It also notes using any other tools than theirs would only make it worse. After this message we find section 3:
image

This section talks about the ransom that needs to be paid, 1 Bitcoin. Examples are given where Bitcoins can be bought and the address the Bitcoin needs to be transfered to: 1AbwLtv7JTtbLmj8LrGq7TzCdkD4ZNET5C. There is also a link to a download of the decrypter which (with bold emphasis) only works after the ransom payment is made.

Below section 3 there is a small section about how Antivirus products might detect the decrypter and cause decryption issues:
image
All of this gives a good indication there’s some (new) kind of ransomware ongoing which at least I haven’t seen before. Its time to find a sample to combine with this.

One thing that is interesting is that there was no need for a ‘payment id’ as you normally see with CryptoWall, CTB or TorrentLocker infections. The machine gets a unique ID and this is used to track the payments of ransom. On this C2 (if we can call it that) everyone pays towards the same Bitcoin address, its just a static page.

Analysis of the malware itself

Finding a sample was actually quite easy, it was uploaded to Malwr.com in May this year: [csrsss.exe].
The reason I was able to find it was due to the fact that the Bitcoin address was in the binary itself (as a text string):
image
If you look at the rest of the text it actually matches the matches on the C2 but we’ll look at that later. Lets grab the sample and just look at some of the info in the PE file.

One thing that immediately jumps out is that this thing is written in C++ with lots of inheritance (base classes), a lot of vftable lookups make a bit painful to look at in OllyDBG.
Another thing jumping out is the bulid timestamp; it seems to be the same date as the Malwr.com submission (of course this can be faked):
image
What is more interesting are the resources in the PE, it seems it hasn’t been packed in any way and the resources are available plain:
image
There’s 2 that sort of jump out, ‘BIN’ and ‘HTML’, BIN actually contains two PE’s:
image
The HTML resource (which matched the Bitcoin address we searched for) is in fact a ransom message that is dropped on the victim’s PC:
image
There are also a ton of dialogs in the PE, some of which look like a ransomware pop-up normally seen with this type of malware:
image
image
image
The last one looks like a classic ransomware pop-up you would/could see after being hit by it.
When going through the payloads I also noticed every bin had its linker information (with PDB path) in tact which gave me the following PDB paths:

  • C:UserswindowsDesktopCryptoAppbuildbinReleaseCryptoApp.pdb
  • C:UserswindowsDesktopCryptoAppbuildbinReleaseKeepAlive.pdb
  • C:UserswindowsDesktopCryptoAppbuildbinReleaseSelfDestroy.pdb

These PDB paths are the reason I’ve called it the ‘CryptoApp’ ransomware of course.

Startup & Persistence

The main ‘CryptoApp.pdb’ comes from the intiail sample grabbed from Malwr, the other two come from the two embedded PE’s. Their function is pretty much what they have been named.
‘KeepAlive’ creates startup keys for windows (although it doesn’t even bother copying the payload anywhere, just from the directory it was ran from):
image
What is interesting to note is the ‘CryptoAppDelay’ key is constantly updated, it keeps going up every refresh. Lets look up the part of the code that is responsible for this, we find it here:
image
This part can be split up in three sections (marked with red blocks), the first section checks for the presence of the ‘CryptoAppForcedEnded’ key to be present (indicated with the green lines). If this key is not present it moves onto the next section in which it spawns a thread, waits for it to finish. After the thread is finished the code continues into section 3 where it changes the value of the ‘CryptoAppDelay’ key.
While this part is not super interesting the newly created thread is, its a sort of watchdog. The idea behind this thread is that it waits for the ‘delay’ to reach a certain number after which it will execute the rest of the code. The thread code looks like this:
image
First it obtains a handle for the SOFTWAREMicrosoftWindowsCurrentVersionRun key to be able to query values under it (the ‘CryptoAppDelay’ value that is). After that it sets up some variables and jumps into a loop (indicated with the green box). The loop is where ‘the magic happens’; it checks the value of ‘CryptoAppDelay’ and compares it to a number while the assembly isn’t super clear to read it basically does the following:

Take the value of the ‘CryptoAppDelay’ key, divide by 1000 and compare if its surpased 86400

The reason for this is as follows, if it doesn’t hit this number the ‘CryptoAppDelay’ value is set to the value returned from ‘CurrenTickCount()’ which is a Windows function that returns the amount of milliseconds that have passed since the machine booted. Dividing that by 1000 gets you the seconds, 86400 is in fact 24 hours; the ransomware waits untill the machine has been on for 24 hours before doing anything.

Whenever the ransomware runs it spawns the embedded PEs which are used for things like persistence. An example is ‘keepalive’ which you will find running when you get infected:
image
Here the ‘keepalive.exe’ is dumped in the Temp directory (marked by the green box) and the actual ransomware process ‘csrss.exe’ still sleeping waiting for the uptime to hit 24 hours (marked by the red box). Trying to kill the ransomware process doesn’t do much, its beeing kept alive by the keepalive payload, lets see how that works. Looking at the arguments given to the keepalive PE we can get a good idea already of how it works:
image
It is given an image path (of the ransomware itself) and the PID of the currently running ransomware process. Looking at the disassembly from the ‘keepalive.exe’ PE we find the arguments are indeed used to ‘protect’ the main ransomware process. The way its ‘preventing’ the main ransomware from being stopped is that it just starts it over and over again. It works like this:

  • Get a handle for the process to watch
  • Call the Windows function WaitForMulipleObjects and halt on the process handle
  • When it returns (and its related to quitting) restart the ransomware process and shutdown self (keepalive just exits after restarting the ransomware’s main program)
  • Ransomware process starts a new keepalive which starts the same thing again (watchdog thread)

The ransomware process itself can be restarted, its just counting the system uptime (with the registry keys described before).

File encryption

The ransomware will encrypt files with the following file extensions, 162 file extensions in total:

.3fr .3gp .7z .accdb .ai
.arc .arw .avi .bad .bay .bmp
.cam .cdr .cer .cineon .cr2 .crt
.crw .csv .ctl .dat .db .dbf
.dcr .der .des .dicom .dng .doc
.docm .docx .dsc .dwg .dxf .dxg
.eps .erf .fla .flv .fmb .fmt
.fmx .gif .hdr .html .iif .img
.indd .jpe .jpeg .jpg .kdc .log
.lst .m4v .mdb .mdf .mef .mov
.mpeg .mrw .nd .nef .nrw .odb
.odm .odp .ods .odt .openexr .ora
.orf .p12 .p7b .p7c .pbm .pck
.pdd .pdf .pef .pem .pfx .pgm
.pic .pkb .pks .plb .pls .png
.pot .ppm .pps .ppt .pptm .pptx
.prn .psb .psd .pst .ptx .qba.tlg
.qbm .qbr .qbw .qbw.tlg .qbx
.qby .qfx .r3d .raf .rar .raw
.rdf .rdo .rep .rex .rtf .rw2
.rwl .sql .srf .srw .sti .sxi
.tiff .txt .vdi .wb2 .wpd .wps
.xbm .xlk .xls .xlsb .xlsm .xlsx
.xml .yaml .zip .php .css .asp
.cpp .c .js .pl .perl .swf
.aspx .potx .potm .ppam .ppsx .ppsm
.sldx .sldm .thmx .xlam .xltm .dotm
.dotx

Most of the filetypes here aren’t that surprising, image format, text document formats, presentation formats. The ones that I do find interesting are file extensions for files related to accounting, specifically to the QuickBooks accounting software (.qba .tlg .qbm .qbr .qbw .qbw .tlg .qbx .qby .qfx) to target companies.
To find files it attempts to access all available logical drives, it uses a call to [GetLogicalDrives()] to map with the following list of drive letters (basically every possible driver letter, the whole alphabet):

A: B: C: D: E: F:
G: H: I: J: K: L:
M: N: O: P: Q: R:
S: T: U: V: W: X:
Y: Z:

To keep track of the files it encrypted the ransomware stores this information in a sqlite database on disc.

The ransomware makes use of the Microsoft CryptoAPI, specifically it uses the RSA crypto provider:
image
After setting up the Crypto provider and generating a private/public key pair it starts going through the files, the method it follows for encryption is the ’Hybrid cryptosystem’. In this system you don’t encrypt the files using the private key but you create symmetric keys (I call them ‘file’ keys below) for data encryption. These keys are encrypted using the private key after use. This means decryption of the file needs the private key to get the ‘file’ key decrypted which in turn can decrypt the file data.
It searches for them based on the available logic drives shown above matching files based on the described file extensions. When a file is ‘valid’ for encryption it will start encryption which works as follows:

  • It will grab the full filename and append .encrypted to it as the new file extension
  • A ‘file’ key (MSDN will refer to it as s session key) is generated by calling [CryptGenKey()] using the previously initialized Cryptographic provider and using PROV_RSA_FULL
  • A file handle is openend to the newly created filename (the .encrypted one)
  • 4 bytes are written into the open file (an int) with the ‘magic value’ of 0x2200AF which is a kind of marker/tag for the encrypted files
  • After the 4 bytes an export of the ‘file’ key (key used to encrypt/decrypt the file data, encrypted of course, can be decrypted by using the private key from the pub/priv key part in use) is written using [CryptExportKey()] with the SIMPLEBLOB blob type for export
  • After writing the ‘file’ key to the file the original (unencrypted) file is being read, encrypted and appended to the .encrypted file
  • After the file is encrypted on disc it is inserted into the SQLite database on disc (used to list the user his/her encrypted files as well as for the decrypter to find the files again)
  • After successfuly inserting the encrypted file into the SQLite database it is removed from disc by calling the [DeleteFile()] function.

The private / public key pair it send to the C2 server as well, see the ‘C2 communciation’ section below for details on this.
As a sidenote; throughout the encryption process the ransomware keeps states in registry indicating its current state of encrypting, how many files, etc.

The Decrypter

On the website there’s a link to the Decrypter which is quite interesting. Besides it being a ‘decrypter’ for any infection from the original malware it is actually both. The decrypter is in fact a slightly modified version of the main malware itself.
It does however show something interesting, the sample I managed to grab from Malwr.com is an outdated version of the ransomware. Besides some clean-up and slightly changed functions it also has some added functions. One of these functions is the one to display this image:
image
It is dropped in the temp directory as ‘wlp.jpg’ and set as a system background; we can see this behaviour in the disassembly:
image
Besides the lock message there is also a new dialog in the decrypter (together with the one from the ransomware itself) for the decryption process:
image
The dropped ransome messages in the form of a HTML page we saw in the previous sample has also been updated. It now includes the links to the Tor hidden service also seen on the red image:
image
This all gives the indication the samples I grabbed from Malwr.com is rather old.

The decrypter itself checks against the Blockchain.info website to see if the user did pay. We can see clear usage of it in the decrypter’s dissasembly:
image
It parses transaction counts and matches up the Bitcoin address from blockchain.info as well, the transaction parsing as an example:
image
The way payments are confirmed works as follows:

  • The user pays the set amount of Bitcoins to the specified Bitcoin address 1AbwLtv7JTtbLmj8LrGq7TzCdkD4ZNET5C
  • The user pastes his own Bitcoin address in the payment form of the Ransomware
  • The decrypter checks if this Bitcoin address made a payment to the specified Bitcoin address after the infection date (this is stored in the registry as well) to confirm the payment being related to the infection.
  • If the user paid it will talk to the C2 to obtain key information

The Bitcoin address listed on the site for payment ’1AbwLtv7JTtbLmj8LrGq7TzCdkD4ZNET5C’ has only had one payment ever on the 15th of May for 1 Bitcoin; the exact ransom demand. The payment was send only 2 days after the first development version of the ransomware was uploaded to Malwr.com which makes it look like a test for the Decrypter part of the ransomware.

File decryption

When the decrypter has confirmed that the user has paid the required ransom amount the private key is obtained from the C2 server (how this is done is explained in the C2 communciation section below). With this private key it will go through the steps of decrypting the user’s files:

  • Find the local SQLite database which lists all the encrypted files
  • It will grab the file and change its file extension from .encrypted to .encrypted.decrypted
  • It will confirm the first 4 bytes of the file having the magic marker / tag of 0x2200AF, if it doesn’t it will ignore the file
  • It will grab the next section from the file which contains the ‘file’ or ‘session’ key
  • Using this key and the private key it will start decrypting the file
  • This process continues for every file until they have all been decrypted.

C2 Communication

While the hidden service shows the ‘scary’ message about the needed ransom payment there is no C2 communication traffic to this host. The real communication goes towards a host outside of Tor. Interestingly this host went down the same time the hidden service went down which could indicate them being hosted on the same system; although I have no proof for this of course.
The communication for the ransomware itself is HTTP only towards a centralized C2 server while the decrypter has communication towards both the centralized C2 server over HTTP as well as SSL traffic towards blockchain.info.

Ransomware C2 communciation

The ransomware itself communicates towards a static domain: cryptorepairsystems.com (at the time pointing to a host in Bosnia and Herzegovina at 80.242.123.197) on plain HTTP. There are two communication paths:

  • cryptorepairsystems.com/ksubmit.php – Used to send the key used for file encryption to
  • cryptorepairsystems.com/kretrieve.php – Used by the decrypter to retrieve the crypto key from to decrypt the encrypted files

The communication to /ksubmit.php is simple HTTP POST communication. A specific header is hardcoded for this communication: “Content-Type: application/x-www-form-urlencoded” which enforces the server to inspect it as urlencoded form data. The form data has the following format:

bitcoin_address=%s&empid=%s&comp=%s&ipv4=%s&blkk=%s&publ=%s&priv=%s

The specific parameters are:

  • bitcoin_address – Payment address for the ransom
  • empid – Unique ID for the system
  • comp – Computer name obtained by calling [GetComputerName()]
  • ipv4 – IPV4 address for the infected client
  • blkk – Empty hardcoded value (unsure of the real purpose)
  • publ – Public key of the RSA key set used for the file encryption
  • priv – Private key of the RSA key set used for the file encryption

Decrypter C2 communciation

As said in the previous section, the communication to /kretrieve.php is specific to the Decrypter. Its communication protocol is also just plain HTTP POST communication. A specific header is hardcoded for this communication as well, its the same as for the ransomware check-in: “Content-Type: application/x-www-form-urlencoded”. The form data has the following format:

empid=%s&comp=%s&ipv4=%s

The specific parameters are:

  • empid – Unique ID for the system
  • comp – Computer name obtained by calling [GetComputerName()]
  • ipv4 – IPV4 address for the infected client

Conclusions: Unfinished, not spread around

From what I can see this piece of Ransomware is in development and not finished. Some things seem to work just fine others seem to be a bit broken / unstable. I don’t have any leads on who is behind it or if there are more C2s.

Comparing it to other ransomware threats like CryptoWall its quite amateuristic and simple, but then again its quite hard to compare. Without knowing anything about the backend (it could be spinning up C2 onion addresses per affiliate if it has an affiliate system (it doesnt look like it but who knows) and actors I can’t tell much about it from a ‘size’ perspective.
Besides what I said above the thing is also very flawwed, I will not go into details on my blog but file recovery would have been possible in a lot of different ways. Sadly the C2 went down, I’ll be keeping my eyes open to see if and when a new one pops up 🙂

Note: If you go through the sample yourself it might look as if I’ve skimmed / skipped over some details. I only included details that mattered to the story to get a good image of how this thing works.

Samples & IOCs

I have only found 2 samples, one is the old development built I discovered on Malwr.com and the Decrypter from the Tor hidden service C2. The decrypter wasn’t public yet before I posted it on Malwr.com. Here are the samples downloadable from Malwr.com and VirusTotal:

I have seen the following domains associated with it (besides the SSL traffic to blockhain.info for the decrypter):

  • guhvuoz7am24b5mv.onion (and its Tor web proxy variants of course)
  • cryptorepairsystems.com (originally pointed to 80.242.123.197)