Hunting PrivateLoader: The malware behind InstallsKey PPI service | Bitsight

Now, both Triage sandbox and also our YARA rule are not matching the file being dropped by PrivateLoader as itself, neither is it detecting its memory dump. This prompted us to look deeper into the sample, aiming to write a new detection rule.

Reversing PrivateLoader

Examining the sample details on VirusTotal, it’s evident that the .text section, where code usually resides, is empty. In contrast, the .vmp section contains the majority of the data, totaling 5.6 megabytes. The entropy score of 8, the highest possible, coupled with the detection signature from DetectItEasy identifying “Protector: VMProtect (new 18 jmp 11) [DS]”, strongly suggests that this sample has been packed using VMProtect, a commercially available packer.

Binaries packed with VMProtect are hard to unpack for several reasons. Firstly, VMProtect utilizes a virtual machine (VM) to execute code, making it difficult for traditional unpacking methods to decipher the original instructions. Additionally, VMProtect employs various obfuscation techniques, such as instruction reordering and encryption, to further obscure the code’s functionality. Furthermore, VMProtect employs anti-debugging and anti-reverse engineering mechanisms, which actively detect and thwart attempts to analyze or manipulate the packed binary during runtime. These combined features make unpacking binaries packed with VMProtect a challenging task, requiring advanced techniques and significant effort to bypass its defenses and recover the original code.

Fortunately, it’s possible to unpack it using unpac.me public service, although a memory dump from a sandbox run might have also worked for our purposes. Looking at the unpacked sample, the .text section now has 6.6 of entropy, which may suggest some level of encryption, but not necessarily an indication that the file is still packed. Furthermore, looking at the program strings, there are very few, which may indicate that they are encrypted (as expected). There are however some known wide strings used by PrivateLoader (fig. 5), some of them actually present in our old YARA rule which detects older versions of PrivateLoader. This is evidence enough to conclude that PrivateLoader was successfully unpacked. However, one usually important component is absent from the unpacked sample: the import address table, which wasn’t reconstructed. Nonetheless, as will be demonstrated shortly, the program’s strings contain the majority of the Windows API functions utilized.

Ghidra, going up in the function call tree from any known wide string (fig. 5), eventually the main function is reached, which takes a minute to decompile since it’s a huge function (as seen in past versions). Scrolling through the code, looking for the known PXOR pattern for string decryption, there’s no sight of it. There’s instead a different pattern: again, stack variables being built at runtime (fig. 6), but this time the key for the XOR encryption is different (fig. 7), yet still straightforward to understand.

Stack variable built at runtime
String decryption function (decompiled)

Fig. 6 Stack variable built at runtime (disassembled).

Fig. 7 – String decryption function (decompiled).

The algorithm basically translates to:

For each character in string:
    character = character XOR (character position + key)

This algorithm is spread throughout the code, either as inline code or in a function, of which there are many. Now, about the loop part, most disassembled basic blocks look like figures 8 and 9.

String decryption loop
loop-ex-2

Fig. 8 – String decryption loop (Example 1).

Fig. 9 – String decryption loop (Example 2).

Leveraging all known and specific PrivateLoader wide strings (network related) and this constant pattern of string decryption instructions, we share a YARA rule to detect and hunt the new versions of this family. We’ve also combined this rule with our old rule to have one rule to catch most PrivateLoader versions. Here’s the rule:

Source: https://www.bitsight.com/blog/hunting-privateloader-malware-behind-installskey-ppi-service