How EternalPetya Encrypts Files In User Mode
On Thursday of last week (June 29th 2017), just after writing about EternalPetya, we discovered that the user-mode file encryption-decryption mechanism would be functional, provided a victim could obtain the correct key from the malware’s author. Here’s a description of how that mechanism works.
EternalPetya malware uses the standard Win32 crypto API to encrypt data.
For every fixed drive in the system which is assigned to a drive letter (C:, D: etc) the following is performed:
- Initialize a context by calling CryptAcquireContext. Provider is “Microsoft Enhanced RSA and AES Cryptographic Provider”
- CryptGenKey is called to generate a public/private key pair. The algorithm is AES-128. Afterwards it calls CryptSetKeyParam to set padding to PKCS5 and mode to CBC.
- All files on the drive are enumerated. Files in C:\Windows and subfolders are skipped. The file extension is checked against a fixed list of 65 extensions.
Petya public key, exclusions list, and file extensions list.
- If there is a match, the file will be encrypted:
- The file is opened via the Windows file mapping API.
- If the file is larger than 1 MB, only the first MB will be encrypted.
- Call to CryptEncrypt is made to encrypt the selected data.
- The encrypted file is NOT renamed.
- Note: there is a “bug” in this function: if the file is larger than 1 MB, the Initialization Vector will not be reset for the next file (i.e. the encryption “continues” there), making decryption more prone to failure.
In order to decrypt the files successfully, the files should be enumerated in the exact same order as during encryption, and with the same “bug” in place.
- After all selected files have been encrypted, preparations are made to create the README.TXT contents. Here’s what happens:
- The malware contains a hardcoded public encryption key in base64 format: “MIIBCgKCAQEAxP/VqKc0yLe9JhVqFMQGwUITO6…..” (see above screenshot). This key is first decoded using CryptDecodeObjectEx. The result is then passed to CryptImportKey to create the corresponding public key to be used in the next step.
- CryptExportKey is called to export the private (file decryption) key. The output is encrypted using the public key generated in the previous step.
- Finally, CryptBinaryToString is called to transform this encrypted key into a string representation.
- Just before rebooting, the README.TXT – containing this encrypted string – is generated and written to the disk’s root folder.
File decryption should be possible, provided that:
- We have been provided with a private key to decrypt the file decryption key. (As of writing, the malware authors haven’t published it.)
- Files are enumerated in the exact same order as during encryption, i.e. no files were added, moved, or deleted between encryption and decryption phases.
- The disk’s MFT (master file table) hasn’t been destroyed by the other malware components.
- File encryption was only performed once. As we previously noted, propagation techniques in the malware may end up encrypting files a second time, with a different key. This would make the files absolutely unrecoverable.
Note that the malware does not include this decryption functionality. A separate decryptor tool would need to be provided to victims.