Ransomware is now a common term not only in the security industry, but also in our day-to-day life. A new ransomware seems to pop up almost every given day. What we don’t normally see is how codes are implemented within these malware.
Ransomware employs different techniques and attack vectors in order to infiltrate your computer system. They also use different armoring techniques to evade detection and avoid analysis. One trick they use to harden themselves against analysis is through implementing metamorphic, encryption, and polymorphic algorithms.
We discussed metamorphic algorithm recently in our blog post here. (http://blog.fortinet.com/2016/01/26/metamorphic-code-in-ransomware) Simply put, metamorphic algorithms enable malware to generate different copies of its binaries, while they continue to look like normal code.
Another technique used by malware is encryption. Malware code can be encrypted using a key to render it unreadable even with the use of disassembler. But in order for malware to generate different copies of itself, it uses a polymorphic algorithm.
Polymorphic algorithms use different keys to encrypt and generate different copies of itself. Which means that knowing one key is not enough to detect different copies of the malware.
Most malware uses a simple decryption algorithm to decrypt the malware code in its virtual memory. This gives researchers a chance to read and analyze the malware code. It also provides a chance for antivirus engines to read and determine whether or not the code is malicious. The encryption keys don’t matter that much once the malware code has been decrypted into the memory. Malware using different keys will still generate the same decrypted malware code in memory.
Polymorphic malware generates a new key in order to encrypt the malware code in memory for the purpose of writing a new copy of the malware into a different file. It thus generates different binaries every time the malware drops a copy of itself.
But all the same, the malware always has the same original decrypted copy in memory. So in this regard, a researcher can still dump a decrypted version of the malware from memory to do static analysis.
But what if the malware has the capability of generating a different copy of itself in memory? In that case, dumping the decrypted version of the malware will be impossible. And reading the malware code in memory is also rendered impossible.
Virlock is a ransomware that has metamorphic algorithm, as discussed in the blog post cited above. It also has what I have coined as an on-demand polymorphic algorithm.
Similar to a regular polymorphic malware using a key, it decrypts the malware code into the memory. The only difference is that Virlock only decrypts the code that it needs at a given moment. and then encrypts it back. To further complicate things, it then uses a different key when it encrypts it back to memory. The new instance of the encrypted malware is now different from the initial binary. And the longer Virlock uses this code, and its continuing series of decryption and encryption patterns, the malware in memory will look completely different from the original encrypted copy before it was loaded in memory. Dropping a different copy of itself is just simply copying the content of the memory into a file.
Figure 1 shows a block of encrypted malware code. The first 16 bytes are shown on the right. The block of code is an exact copy of the encrypted malware code from the initial executable file.
Figure 2 shows the decrypted version of the same block of code shown in Figure 1. After decrypting the necessary bytes, the malware executes the decrypted code, then encrypts it back with a different key.
Figure 3 shows the newly encrypted block of code, which is now totally different from the original bytes. Every single time the malware needs to execute a certain block of code, it will be encrypted back to a different set of bytes.
The encrypted bytes shown in Figure 3 are not the final bytes. They will change again once Virlock decides to use them, or when that particular piece of code is needed to perform another task. It will be continuously decrypted and re-encypted using different keys.
This means that researchers cannot dump the whole malware all at once to be able to use a disasssembler. Dumping a completely decrypted copy of the malware is not possible because only a block of code is decrypted at any given time.The only way to analyze the malware fully is to follow every code in the debugger. This can be time-consuming and tedious, and it has discouraged some researchers from further investigation.
While the changes in every byte do not look that much different, if you have a chance to look at a complete view of the malware in memory, it helps to add some highlights and different colors for every change. If there is enough of them, you might have an early Christmas light show.
Everyday, malware and ransomware authors have played a mix-and-match game with different techniques and strategies on their code. It is a challenge, but we will always be there to analyze them.