Wiper Malware – A Detection Deep Dive
*This blog post has been updated to include Command and Control IP addresses used by the malware.
A new piece of wiper malware has received quite a bit of media attention. Despite all the recent press, Cisco’s Talos team has historic examples of this type of malware going back to the 1990s. Data is the new target, this should not surprise anyone. Recent examples of malware effectively “destroying” data – putting it out of victims’ reach – also include Cryptowall, and Cryptolocker, common ransomware variants delivered by exploit kits and other means.
Wiping systems is also an effective way to cover up malicious activity and make incident response more difficult, such as in the case of the DarkSeoul malware in 2013.
Any company that introduced proper back-up plans in response to recent ransomware like Cryptolocker or Cryptowall should already be protected to a degree against these threats. Mitigation strategies like defense in depth will also help minimize the chance of this malware reaching end systems.
The Deep Dive
Initially we started investigating a sample reported to be associated with the incident to improve detection efficacy. Based off our analysis of e2ecec43da974db02f624ecadc94baf1d21fd1a5c4990c15863bb9929f781a0a we were able to link 0753f8a7ae38fdb830484d0d737f975884499b9335e70b7d22b7d4ab149c01b5 as a nearly identical sample. By the time we reached the network-related functions during our analysis, the relevant IP addresses belonging to the C2 servers were no longer responding back as expected. In order to capture the necessary traffic we had to modify both of the aforementioned disk wiper components. One modification replaced one of the hard-coded C2 server IP addresses with a local address belonging to a decoy VM while changing references to the other hard-coded addresses to point to this local address instead. The other modification simply changed the parameter being passed to an instance of the Sleep() function so debugging efforts wouldn’t be put on hold for 45 minutes (the original sample used a 10 minutes sleep).
When we initially examined a rule that was being distributed in the public we were looking for areas where we could improve coverage to better protect our customers. The new Wiper variant is poorly written code and luckily includes very little obfuscation.The author(s) made the mistake of allocating a buffer for the send() function that surpasses the data they wished to include in the payload: a null-terminated opening parentheses byte, the infected host’s local IP address, and the first 15 bytes of the host name. This incorrect buffer allocation results in the desired data, in addition to some miscellaneous data already present on the stack (including the 0xFFFFFFFF bytes we alerted on in the first revision of our rule).
Simply running the disk wiper component on different versions of Windows proves the miscellaneous data from the stack that we onced alerted on only applies to beacons being sent from Win XP hosts:
Beacon payload from infected WinXP x86 VM:
Beacon payload from infected Win7 x64 VM:
We have tested part of this hypothesis by running the malware on the same VMs when they had maximum length host names. The resulting beacons continued to limit the hostname bytes in the payload to 15 bytes. To confirm the entire hypothesis, we had to debug and step carefully through the instructions responsible for the data in these beacon payloads. You start by running the disk wiper component alone with the -w flag (which will naturally occur at some point when the disk wiper component is executed and copies itself to host three times). When you hit the following instruction…
…we have to force execution of the alternate jump condition using the debugger to get to the next interesting chunk of assembly:
We eventually arrive to our function call in the code block following the ZF toggle. It’s responsible for setting up the necessary socket and sending the beacon payload once a connection has been established:
Later on, we reach a call within the current function (sub_402D10) that is purely responsible for sending the constructed payload:
When we arrive at the following instruction…
The code is just about to move 10 double words (ECX is currently 0x0A) from ESI (currently assigned to 0x415D60, which was on the stack prior to calling sub_402C80) to the stack itself (starting at EDI, currently assigned stack pointer 0x12F4CE).
Finally, we reach the call to the Windows function send():
Now, at this point you’re probably thinking, “Cool. You explained how the payload is ultimately sent out, but how does this explain the random bytes in the payload?”. Glad you asked…
Shortly after the instruction where you had to manually toggle the ZF but prior to sub_402D10, there’s a call to a function that fetches the name of the infected host:
The first block of instructions belonging to this function is shown below:
When you get to the following instruction in that block…
…ECX = 0x08, ESI = 0x14F8D4, & EDI = 0x415D64. This means that eight double words will be extracted starting at the pointer in ESI and moved to the pointer in EDI. Guess what’s on the stack right now?:
The data from these eight stack frames will get moved to the .data section, starting at 0x415D64. You’ll get the four “prefix bytes” added on once the local IP address is acquired from that same code block via:
And, as we’ve already detailed earlier, 0x2800 will be added as final prefix bytes to the resulting payload. But, we now have another hard-coded element we can alert on in the beacon payload:
The third instruction shown above will store 0x04 as a doubleword to 0x415D84, which just happens to be at the very end of the payload currently stored in the .data section.
With this information, we were able to revise accordingly and design the following rule:
Click for a text version. It is important to note that sid 32674 will continue to be improved in the future as the malware evolves. This blog applies to the variants we are aware of as of revision 2 of the signature.
This rule will alert on the samples we’ve analyzed thus far that send these beacons back to their respective C2 servers. What’s more, the rule alerts on all of the hard-coded portions of the payload, providing more complete coverage regardless of the major Windows version running on these infected hosts.
We always want to deliver up-to-date detection for the latest threats in the quickest most efficient manner possible. However, the quality of the detection should never be dismissed. The suggested rule we initially landed upon did cover these wiper components when run under select Windows environments, but our team wanted to fully understand the reasoning and justification behind every option of that rule. This helps us ensure we cover the threat to the best extent possible and do so in the most efficient way possible. Once we did we were able to analyze further and release coverage that was more robust for our customers to help prevent further compromises of this magnitude that may just utilize the Wiper malware family.
Advanced Malware Protection (AMP) is well suited to detect and block this type of attack.
ESA is not applicable for this attack because this threat is not using email.