Since being released on June 27, the Cylance Threat Guidance team have been analyzing the Petya-like ransomware that was highly effective in targeting organizations around the world. Initially distributed via the hacked Ukrainian accounting software MEDoc, the malware quickly spread within the country, and due to highly sophisticated worm capabilities, spread globally at a rapid rate. In addition to worm propagation, Petya-like can encrypt files, infect the Master Boot Record (MBR) and destroy the filesystem of an infected computer, causing irreversible data-loss.
Read our previous post on Petya-like here. And for those wondering, yes, you’re protected with CylancePROTECT®.
What is Petya?
Petya is a sophisticated ransomware, designed to encrypt the filesystem at a low-level via a custom bootloader. It usually comprises a user-mode dropper/installer, and is often bundled with an additional user-mode ransomware called Mischa, which is used when it’s not possible to install the Petya bootloader. The original author, Janus, released Petya as a RaaS (Ransomware-as-a-Service) in July 2016, meaning anyone could create/distribute their own Petya samples whilst the author takes a cut of the profits.
Is This Petya?
Yes and no! The bootloader in Petya-like is certainly a variant of Petya (albeit slightly modified compared to previous versions). However, the user-mode components vary greatly from anything seen previously. This would appear to be a new strain of malware, developed primarily to utilize the Petya bootloader to securely wipe an infected computer.
In addition, the original author of Petya has publicly stated that he was not responsible for the development of Petya-like, and is actively working with the research community to provide details and analysis, even going so far as to release the private AES decryption key for all prior Petya variants.
Petya-like is modular in nature, relying upon several components to operate:
perfc.dat is the main ransomware DLL, signed with an invalid certificate purporting to belong to Microsoft (and therefore fails to validate). The file is typically executed using rundll32.exe to call the first exported ordinal function:
Figure 1. Petya-like Command-Line
During operation, Petya-like utilizes the following bundled components to assist with credential stealing and network propagation:
This DLL is embedded as resource 1 within perfc.dat and used on x86 systems to harvest credentials from lsass.exe.
This DLL is embedded as resource 2 within perfc.dat and used on x64 systems to harvest credentials from lsass.exe.
This file is embedded as resource 3 within perfc.dat, and is a signed and verified version of Sysinternals’ PsExec utility (version 1.98, released in 2010), used as part of worm propagation.
DoublePulsar Payload (x86)
This DLL contains perfc.dat bundled as a resource named STUB, and gets injected into lsass.exe via kernel shellcode on x86 systems.
DoublePulsar Payload (x64)
This DLL contains perfc.dat bundled as a resource named STUB, and gets injected into lsass.exe via kernel shellcode on x64 systems.
Depending on the system architecture, either a 32 or 64-bit version of Mimikatz will be dropped, and executed using the following command:
Figure 2. Command to Launch Mimikatz
Mimikatz will then proceed to extract username and password combinations from memory belonging to lsass.exe, supplying results via the named pipe specified on the command-line.
In addition, the malware enumerates the user's credential set using the CredEnumerate API. All harvested credentials are used in conjunction with SMB/WMI/PsExec when authenticating with remote systems.
Petya-like is capable of leveraging EternalBlue or EternalRomance to exploit the MS17-010 vulnerability and install the DoublePulsar backdoor.
Prior to exploitation, several techniques are used for IP address discovery. On any machine that is not a domain controller, subnets defined on the DHCP server will be enumerated via the DhcpGetSubnetInfo/DhcpEnumSubnetClients APIs:
Figure 3. DHCP Inform Request
ARP scanning is performed using the GetIpNetTable API:
Figure 4. ARP Requests
LANMAN domain enumeration via the NetServerEnum API:
Figure 5. LANMAN Domain Enumeration
In addition, the GetAdaptersInfo and GetExtendedTcpTable APIs are used to retrieve IP address ranges on the local subnet. During this phase, for each discovered IP address, a connection attempt is made to SMB ports 139 and 445 (TCP) to determine if the host is active and running SMB.
After a 3-minute delay, the ARP scan, LANMAN domain enumeration and GetExtendedTcpTable lookups are repeated.
Providing the following processes are not active on the system, the malware will attempt worm propagation:
- ccSvcHst.exe (Symantec Enterprise)
- NS.exe (Norton Security)
First, it will determine if the remote system already contains a DoublePulsar backdoor by checking for a value of 0x11 at offset 0x1A inside the SMB Transaction2 response:
Figure 6. Check for Existing Backdoor
If the backdoor is not installed, it will check if the remote machine is vulnerable to MS17-010 by sending an SMB transaction request and checking for a STATUS_INSUFF_SERVER_RESOURCES (0xC0000205) error code in the response:
Figure 7. Vulnerability and Operating System Version Checks
After determining what Operating System (OS) version is running on the remote system, either the EternalBlue (Windows 7/2008/2008 R2) or EternalRomance (XP/Server 2003/2003 R2/Vista) exploits will be deployed, resulting in the DoublePulsar Backdoor being installed.
Figure 8. EternalBlue on the Wire
Figure 9. Creation of EternalRomance SMB Packet
The EternalBlue kernel shellcode is very similar to that used by WannaCry, and contains both x86 and x64 versions. First, the shellcode will determine the CPU architecture via an instruction that is interpreted differently depending on whether the CPU is running in x86 or x64 mode. Then it will set a hook on the kernel-mode entry point by replacing the pointer to KiFastCallEntry (stored in MSR IA32_SYSENTER_EIP) with a pointer to a hook function:
Figure 10. KiFastCallEntry Kernel-Mode Hook Function
The hook function will then resolve all necessary APIs and look for the SrvTransaction2DispatchTable structure inside the .data section of Srv.sys (the SMB driver). Once discovered, it will replace the first function pointer to SrvTransactionNotImplemented with a pointer to the DoublePulsar backdoor:
Figure 11. Overwriting the SrvTransactionNotImplemented Function Pointer in Srv.sys! SrvTransaction2DispatchTable
Figure 12. SrvTransaction2DispatchTable Prior to Hooking
Figure 13. SrvTransactionNotImplemented Function Hooked to Use DoublePulsar Backdoor
Except for command and response codes, the DoublePulsar backdoor code is also identical to that used in WannaCry:
Figure 14. DoublePulsar Backdoor Commands
Figure 15. Differences Between Petya-like and WannaCry DoublePulsar Backdoors
After installing DoublePulsar (or finding an active instance), the backdoor is then leveraged to remotely execute the ransomware. An SMB transaction message is used to push a second shellcode, together with the payload DLL, to the remote machine. The x86 version of the shellcode is stored as a resource RT_RCDATA/4 (encrypted with XOR/0x86 and ZLIB compressed), while the x64 version is hardcoded in the .data section and encrypted with XOR/0x64:
Figure 16. Decrypting x86 Shellcode Resource
Figure 17. Hard-coded x64 Shellcode
The first part of the next shellcode payload is executed by the DoublePulsar backdoor in kernel-mode, and is responsible for locating a specified process using a hardcoded hash of "lsass.exe". If found, it injects it with user-mode code via a kernel APC (Asynchronous Procedure Call):
Figure 18. APC Call to Inject into lsass.exe
The user-mode part acts as a reflective DLL loader that will inject the payload binary into memory and call the specified exported function:
Figure 19. Reflective PE Loader
The second shellcode is also identical to the one used in WannaCry, except for one byte:
Figure 20. Differences Between Petya-like and WannaCry Shellcode
The payload binary is composed of a small MZ stub executable and the original malware DLL (perfc.dat) embedded as a resource named STUB/101. The stub loader simply drops the DLL to disk and executes it via rundll32.exe:
Figure 21. STUB Loader Data
The malware leverages SMB, WMI and PsExec to spread laterally across the network, using usernames and passwords harvested from Mimikatz or the CredEnumerate API to attempt authentication.
First, it uses the WNetEnumResource API to enumerate connections. For each resource discovered, the malware will try to copy itself to the admin$ share on the remote system:
Figure 22. SMB File Copy to Remote Admin$ Share
Once copied, it will attempt to use PsExec to remotely execute, with the following command-line supplied to the CreateProcessAsUserW API:
Figure 23. PsExec Command-Line
Figure 24. Propagation Via PsExec
Should this fail, then it will attempt to use the WMI command-line instead:
Figure 25. WMIC Command-Line
Figure 26. Propagation Via WMIC
The encryption process begins after the malware creates the threads responsible for worm propagation and lateral movement.
The encryption routine is fairly simple. For each logical drive of type FIXED, the malware creates a thread that will perform the following steps:
1. Generate a random AES-128 key:
Figure 27. Generate Random AES-128 Key
2. Traverse the filesystem on the drive recursively to find all files with the following extensions (skips files residing under the <DRIVE>:\Windows directory):
3. Encrypt the first megabyte (1,048,576 bytes) of each file with the generated AES-128 key. Files are encrypted directly, first by mapping the file into memory via the MapViewOfFile API, and then using the CryptEncrypt API to perform encryption. However, there is a subtle bug present in the code. Due to the "Final" parameter (a boolean value signifying the last block of data to encrypt) passed to CryptEncrypt being FALSE for all files that are larger than 1MB, the encryption process is flawed, potentially leaving some files encrypted improperly and complicating the decryption process.
Figure 28. Map File and Encrypt (Maximum 1MB)
4. Encrypt the AES-128 key with the author’s 2048-bit RSA public key (hardcoded in the .data section as a Base64 encoded string):
Figure 29. Base64 Encoded RSA Public Key
5. Write the encryption key to <DRIVE>:\README.TXT, along with instructions on how to pay the ransom:
Figure 30. Writing the Ransom Message to README.TXT
6. Delete the AES-128 key using CryptDestroyKey/CryptReleaseContext APIs.
Finally, the malware wipes the Setup, System, Security and Application event logs and deletes the NTFS USN change journal:
Figure 31. Cmd.exe One-liner to Wipe Event Logs and Delete NTFS Journal
If the malware is running with elevated privileges, and SeDebugPrivilege is enabled, disk infection begins with corruption of sector 2 of the NTFS Volume Boot Record (offset 0x200 for logical drive “\\\\.\\C:”). This sector houses part of the NTFS Boot Loader. Despite the Boot Loader occupying 15 contiguous sectors, only a single sector is overwritten.
Next, the partition type for PhysicalDrive0 is checked. Any type other than MBR-based (i.e., GPT), results in a forced dismount and corruption of the first 10 sectors. Additionally, if avp.exe (a Kaspersky process) is found active on the system, the first 10 sectors will also be corrupted.
A substitute MBR along with an MFT-encrypting microkernel is then written to sectors 0 - 31. Following this in sector 32 is the Base58 encoded “personal installation key”, generated using the CryptGenRandom API, together with the 8-byte Salsa20 nonce, 32-byte Salsa20 key and hardcoded Bitcoin Wallet ID. Disk sector 33 is filled with the byte value 0x07 and a copy of the Master Boot Record, XOR’d with 0x07, is written to disk sector 34:
HDD Sector Layout
Figure 32. Contents of the Kernel Configuration on Disk
With the updated MBR in place, a Scheduled Task is created to force a reboot. A random delay of at least ten minutes is specified. If the Scheduled Task is unsuccessful and SeShutdownPrivilege is enabled, a BSOD is triggered via NtRaiseHardError. Alternatively, the InitiateSystemShutdownExW or ExitWindowsEx APIs are called as a last-ditch effort.
Upon reboot, the MBR loads the kernel (sectors 1 – 32) at memory location 0x8000:
Figure 33. Master Boot Record Disassembly
After loading, it jumps directly to the kernel entry-point, before proceeding to jump to the main kernel function. The kernel then initializes the screen, and queries information about attached drives:
Figure 34. Main Kernel Function
Next, the kernel checks if the encryption process has already run by checking the status of a flag (first byte within the kernel configuration):
Figure 35. Check if Encryption Has Run
If the MFT has not been encrypted (i.e. the flag is 0) then a fake CHKDSK screen is presented, and sectors belonging to the MFT are encrypted using the Salsa20 stream cipher:
Figure 36. MFT Header Check and Sector Encryption
Figure 37. Fake CHKDSK Encryption Screen
Once encryption is completed the system reboots, and after restarting, the kernel will again check the configuration flag (which is set to 1 once the encryption process has run). This time, the kernel will now display the ransom screen:
Figure 38. Display Ransom Screen
The ransom message reads as follows:
Ooops, your important files are encrypted.
If you see this text, then your files are no longer accessible, because they have been encrypted. Perhaps you are busy looking for a way to recover your files, but don't waste your time. Nobody can recover your files without our decryption service.
We guarantee that you can recover all your files safely and easily. All you need to do is submit the payment and purchase the decryption key.
Please follow the instructions:
1. Send $300 worth of Bitcoin to following address: 1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX
2. Send your Bitcoin wallet ID and personal installation key to e-mail wowsmith123456(at)posteo(dot)net. Your personal installation key:
If you already purchased your key, please enter it below.
Figure 39. Ransom Screen Text
The user is then prompted to enter a key, which is verified and used to decrypt the drive:
Figure 40. Key Verification Check
However, herein lies the main issue concerning the lack of decryption ability. The “personal installation key” displayed to the user is the Base58 encoded string consisting of 60-bytes of random data stored in sector 32, and in no way relates to the Salsa20 key used for encryption. This means that even if the “personal installation key” was supplied to the author, they would have no way to derive the Salsa20 decryption key to send back to the user. It is also worth noting that after the initial “CHKDSK” encryption process has run, the Salsa20 key is deleted from disk:
Figure 41. Updated Encryption Flag (1 = encrypted) and Blank Salsa20 Key After Encryption (red).
Nonce and Wallet ID Remain.
Therefore, once the encryption process has started, the Salsa20 key is irretrievably lost, and data recovery becomes impossible.
Ironically, code to restore the drive after the encryption process is present in the kernel, albeit containing further flaws that would prevent a user from recovering their data. In a slight departure from previous Petya variants, this implementation uses 129 rounds of spongent hashing to transform a user supplied decryption key into the Salsa20 cipher key:
Figure 42. Transforming User Key Using Spongent Hashing and Decrypting Test Sector
However, there seem to be several issues with this approach:
1. It would be computationally infeasible for the author to find an initial 32-byte ASCII value that when hashed 129 times with spongent yields the correct 32-byte Salsa20 key.
2. The user supplied key is half the entropy of the Salsa20 key, and therefore it would be impossible to reliably generate the Salsa20 key given the transformation process.
3. Should a user somehow manage to ascertain the correct key, the remainder of the decryption code is in place, and seems to be functional:
Figure 43. Kernel Sector Decryption Routine
Finally, the original MBR is read, decrypted and restored, and the user prompted to reboot:
Figure 44. Restore MBR and Reboot
However, without manual intervention in a debugger, it is very unlikely that this code path will ever be executed.
The email address used to send “personal installation keys” to the author was blocked by the provider very early during the campaign, resulting in no means for victims to provide their keys or receive decryption keys. Not that this mattered, as there was (and is) no way for the author to convert these into decryption keys. Despite this fact, people continued to transfer BitCoins, until on July 4, around 3.9 BitCoins ($10.2k) were transferred from the author’s wallet:
Figure 45. BitCoins Transferred
The next day, several “strange” transactions were observed:
Figure 46. We Are Not So Sure!
At around the same time, the “authors” supposedly wrote a message on DeepPaste, requesting 100 BitCoins (~$250k) in exchange for the private key, capable of decrypting all files encrypted in user-mode:
Figure 47. DeepPaste Message From the Authors
After apparently providing proof of decryption abilities to various news outlets, it seemed likely that this message was posted by the original authors. However, for most people whose hard drives have been encrypted at the MFT level, paying the 100 BTC will be of little use, and this service is little more than a scam.
In addition, a fake payment site appeared on Tor in recent days, hosted at 23odsus7tobvmw5r(dot)onion, purporting to offer decryption keys to affected users who have paid the ransom:
Figure 48. Fake Payment Site
Again, this service is also a scam, designed to dupe users into paying the ransom when there is no possibility of receiving a valid decryption key.
- Do not pay the ransom.
- Be wary of online decryption services.
- Where possible, restore from backup.
- Prior to reboot, the MBR infection can be recovered via the “fixmbr” command in the Recovery Console.
- After the fake CHKDSK has run, recovery is impossible.
Petya-like seems hastily constructed, making good use of repurposed code from existing malware, often with simple edits performed via a hex editor. That said, the author clearly possesses a firm grasp of the code to perform these modifications.
On the surface, Petya-like would appear to act like any other ransomware, however, under the hood, it becomes quite apparent that file recovery was not intended.
As a ransomware, Petya-like was very poorly implemented, containing fatal flaws that would prevent the recovery of files. As a wiper, Petya-like is nearly perfect, surreptitiously encrypting sensitive files before destroying the filesystem, severely hampering forensic recovery efforts.
Indicators of Compromise (IoCs)
02ef73bd2458627ed7b397ec26ee2de2e92c71a0e7588f78734761d8edbdcd9f (x86 Mimikatz)
eae9771e2eeb7ea3c6059485da39e77b8c0c369232f01334954fbac1c186c998 (x64 Mimikatz)
1a0f64df3133d5ac7a65c7603448fe11bc0ede8d0fb9af47746430f2118ebcd3 (x86 DoublePulsar payload)
45ef8d53a5a2011e615f60b058768c44c74e5190fefd790ca95cf035d9e1d5e0 (x64 DoublePulsar payload)
BitCoin Wallet ID:
Targeted File Extensions:
.3ds .7z .accdb .ai .asp .aspx .avhd .back .bak .c .cfg .conf .cpp .cs .ctl .dbf .disk .djvu .doc .docx .dwg .eml .fdb .gz .h .hdd .kdbx .mail .mdb .msg .nrg .ora .ost .ova .ovf .pdf .php .pmf .ppt .pptx .pst .pvi .py .pyc .rar .rtf .sln .sql .tar .vbox .vbs .vcb .vdi .vfd .vmc .vmdk .vmsd .vmx .vsdx .vsv .work .xls .xlsx .xvd .zip
Email for BTC Payments (inactive):