Introduction
This is a quick post about the WanaCryptor ransomware wreaking havoc on many networks across the world this weekend. With all the news coverage, most of you already know the trouble caused by it.
Once executed on a system, it will use the RSA and AES cryptographic algorithms to encrypt files before demanding payment in exchange for a key necessary to recover those files. If you want to understand the RSA cryptosystem, please read here since all the talk about public and private keys might be confusing to some readers at first.
WanaFork
The source code provided along with this post is intended primarily for security researchers who wish to understand the encryption and decryption process, which may help with recovery of files in the event authors of ransomware decide to release their private key.
There’s no discussion here on any behavior of the ransomware except the encryption/decryption process so if you want information about something else, have a look at this file here which was compiled by various security researchers in the #wannadecryptor channel on Freenode IRC servers.
For the source code to wanafork, see sources in C here. It’s only been compiled with MSVC and tested on Windows, although MINGW should compile it ok, provided it’s a recent version.
Encryption Process
Each system generates an RSA key pair of 2048-bits using the CryptGenKey API which is part of the Microsoft Crypto API (CAPI).
The public key is stored in 00000000.pky using CryptExportKey
The private key is stored in 00000000.eky using CryptExportKey but is also encrypted before storage using CryptEncrypt API with the master public key embedded inside the DLL responsible for encrypting files on disk.
This encryption of private key is what prevents recovery of files without assistance from the ransomware authors.
For each file encrypted, CryptGenRandom API is used to derive a 16-byte value which is used with AES-128 in CBC mode to encrypt the data.
The AES key is encrypted with the users public key and stored along with AES ciphertext.
The only way to recover this AES key and thus the contents of encrypted files is through decryption using the private key and we need the master private key to do this.
Ransom payment process
Although I haven’t researched this at all, it seems reasonable to make some assumptions based on the encryption model that some component of the ransomware sends the encrypted private key stored in 00000000.eky to a server over the TOR network where it’s decrypted by the ransomware authors using their master private key.
The decrypted private key is then sent back to the victim’s system and stored as 00000000.dky which allows @WanaDecryptor@.exe to recover files.
Open to correction of course. It has been pointed out by some that there’s no way for the ransomware authors to identify who makes a payment.
Because of the algorithm used, it isn’t feasible to recover data from encrypted files without assistance from the ransomware authors.
The rest of post may only be of interest to developers / researchers.
Definitions
You’ll see these values throughout the source code shown here.
WanaCryptor Archive Structure
Each encrypted file or what I call archive, has a predefined structure necessary for successful decryption.
- Signature
- Key Length
- Encrypted AES key
- Unknown 32-bit value
- File Length
- Ciphertext
64-bit signature. Currently set to the string “WANACRY!
Indicates length in bytes of the following encrypted AES key.
128-bit AES key encrypted using the users RSA public key stored in 00000000.pky
This key is generated by CryptGenRandom.
I’m unsure what this is for yet. It’s usually set to 3 or 4
64-bit value obtained from GetFileSizeEx which indicates the original size of file.
Encrypted data using AES-128 in CBC mode. Uses zero padding.
The following is a structured hex dump of encrypted file generated by the malware.
RSA Key Generation
As said, the RSA keys generated are unique to each system.
In the tool, both public + private keys are exported in their plaintext form. The private key is also encrypted for illustrating how the malware does it.
AES Key Generation
The AES keys for each file are generated using CryptGenRandom API which is cryptographically secure and therefore invulnerable to attack.
When decrypting an archive, we need to decrypt the encrypted AES key using the RSA private key blob stored in 00000000.dky
In both scenarios, because I’m using Crypto API for AES, additional steps are required to import the key into a CAPI key object.
I’d guess using a custom AES was probably easier to use than Crypto API, but that’s just speculation on my part.
Encryption
WanaCryptor uses Zero Padding, but Crypto API doesn’t support it.
Rather than set the bFinalize flag to TRUE when encrypting final block, the buffer should be aligned by 16 bytes and padded with null bytes. The bFinalize flag should remain FALSE in order to be compatible with WanaCryptor.
Here’s an example of creating a WanaCryptor archive and using Crypto API to perform AES-128-CBC encryption of file data.
Decryption
As with Encryption, the bFinalize flag (if using Crypto API) should always be FALSE. This is because Microsoft Crypto CSPS don’t support zero padding.
Summary
Without the master private key generated by the authors, it’s not possible to recover data from encrypted files unless by miracle someone discovers a flaw with either AES or RSA.
Thanks to 0x4d_ for helping with post and all the folks on freenode for researching this malware over the weekend.
This tool will require a lot more testing before it can be considered reliable and the only reason for releasing it early is so that others can study the source and write their own decryption tools.
It’s worth noting (although rarely noted) that it’s using the default Crypto API settings for RSA encryption, which means it’s using PKCS1v1.5 padding.
If the sample decryption feature sends a ciphertext to the C2, it’s likely that this can be exploited to recover plaintexts without paying the ransom. (See: Bleichenbacher’s 1998 attack.)
LikeLiked by 1 person
The sample decryption does not sent/receive any requests. Actually a very small subset of the files is encrypted using the same mechanism but without actually encrypting the 128-Bit AES key stored within the crypted file. So these files (different suffix: .wncyr instead of .wncry) can be decrypted without any knowledge of the private key.
See:
https://gist.github.com/rain-1/989428fa5504f378b993ee6efbc0b168#gistcomment-2094933
LikeLike
The sample decryption only works because the sample files are encrypted and decrypted with a key that is stored locally. Sadly this means that the sample decryption can happen offline, and is useless in helping decrypt the rest of the files.
LikeLike
https://twitter.com/e55db081d05f58a/status/863109716456747008
Is this not the primary keypair?
LikeLike
That private key is for decrypting the DLL stored in t.wnry.
LikeLike
Hi, i have 132 160 files on my server was crypter. i stoped it when unplug network cable. ma files server was crypted by my other server.. and i isolated my files server and i backuped it and i reinstell a new server file. .and i restored the backup volume without shadow copie because was include the @wanadecriptor@ virus.. now i have a file server clean when 132 160 file crypted by extendion .WNCRY and i search a solution for decrypt this files.. this exploit when resolved by other the hacker, is a hero. i work it all time for slove this algoritme.. good luck all ! Tony.
LikeLike
Does .wncyr files shares the same internal structure with .wncry files? If they have the AES key unendrypted, they shouldn’t, right?
LikeLike
Pingback: Episódio #125 – WannaCry – Segurança Legal