# PaaS, or how hackers evade antivirus software **[ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/paas-or-how-hackers-evade-antivirus-software/](https://www.ptsecurity.com/ww-en/analytics/pt-esc-threat-intelligence/paas-or-how-hackers-evade-antivirus-software/)** Positive Technologies Published on 12 April 2021 Malware is one of the main tools of any hacking group. Depending on the level of qualification and the specifics of operation, hackers can use both publicly available tools (such as the Cobalt Strike framework) and their own developments. Creating a unique set of tools for each attack requires huge resources; therefore, hackers tend to reuse malware in different operations and also share it with other groups. The mass use of the same tool inevitably leads to its getting on the radar of antivirus companies, which, as a result, reduces its efficiency. To prevent it from happening, hackers use code packing, encryption, and mutation techniques. Such techniques can often be handled by [separate tools called crypters or sometimes simply packers. In this article, we will use the example of the RTM banking trojan to discuss which](https://www.ptsecurity.com/ru-ru/research/hacker-groups/rtm/) packers attackers can use, how they complicate detection of the malware, and what other malware they can pack. ## Packer-as-a-service A hacker group responsible for RTM distribution regularly sent mass phishing emails with malicious attachments until the end of 2020. Apparently, the attacks were automated. ----- Figure 1. RTM phishing email, December 2020 Each attachment contained files that significantly differed from each other, but the final payload remained almost the same. Figure 2. Example of RTM archive Such feature is a natural consequence of using crypters. Initially, the group behind RTM used its own unique crypter. In 2020, however, the group changed it twice. When analyzing samples packed in a new way, we detected numerous other malware protected by similar method. Taking into account the fact that packing process is automated, such overlapping with other malware allows us to assume that attackers use the packer-as-a-service model. In this model, packing of malicious files is delegated to a special service managed by a third party. ----- Figure 3. Website of a crypt service Access to such services can often be found on sale on hacker forums. Figure 4. Advertisement of file packing as a service Later in this article, we will discuss specific examples of crypters used by the RTM group. ## Rex3Packer The first use of this packer by the RTM group that we detected dates back to November 2019. The group started actively using the packer in April–May 2020. Rare uses of the packer for distributing old versions of the RTM trojan were also observed in late January 2021. ----- Figure 5. Phishing email by RTM, January 2021 We couldn't associate this packer with any of the publicly described ones, so we named it according to three specifics of its working: recursion, bit reverse, and reflective loading of PE files (reflection), hence the name Rex3Packer. ### Unpacking algorithm The overall algorithm for extracting the payload is as follows: 1. A predetermined amount of memory is allocated with read, write, and execute rights using VirtualAlloc. 2. The content of the current process image in the memory is copied to the allocated buffer (in particular, section .text). 3. Control passes to the function inside the buffer. 4. The difference is calculated between the location of data in the buffer and in the PE file image (difference between the addresses in the buffer and virtual addresses in the image). This difference is written to the ebx register. All references to virtual addresses in code are indexed by the content of this register. As a result, wherever necessary, a correction is added to the PE image addresses that allows obtaining the corresponding address in the buffer. Figure 6. Calls to functions and variables taking into account the correction in the ebx register 5. Another buffer is allocated for packed data. 6. By calling VirtualProtect, RWX rights are assigned to the entire memory region with the PE file image. 7. The packed data is copied to the buffer. 8. The packed data is decoded. 9. The memory region with the PE image is filled with null bytes. 10. The decoded data represents an executable file—the PE payload. This payload is reflectively loaded to where the initial PE image was, and control passes to its entry point. ----- spec c a go t o decod g pac ed data s o spec a te est to us t s case, t ou d be co ect to co pa e pac g t compression, as the algorithm is such that the size of packed data is always bigger than that of the initial data. The packed data is preceded by a 16-byte header that contains four 4-byte fields: Size of the header Size of initial data (PE payload) Position in initial data (*) at which they are divided (more details below) Encoding mode (1, 2, or 4) The decoding looks as follows: 1. Inside each byte, bit order is reversed (for example, 10011000 becomes 00011001). 2. Depending on encoding mode (1, 2, 4), data is divided into blocks with N size of 9, 5, or 3 bytes, respectively. The result of the block decoding is N-1 byte (8, 4, or 2). 3. In the first N-1 bytes of the block, some bits are missing: their values always equal zero. To restore the original bytes, the missing bits are extracted from the last byte of the block by using 00000001, 00010001, or 01010101 masks. The mask is shifted for each subsequent byte. As a result, the last byte of the block is composed of the bits extracted from previous bytes and united by the logical operation OR. For example, in mode 4, the last byte is composed of even bits of the block's first byte and odd bits of the block's second byte. As a result of "returning" these bits to the first and second bytes, an original sequence of two bytes is composed. Figure 7. Scheme of obtaining initial bytes in mode 4 4. When bits are restored in all blocks, the obtained data represents the initial PE file divided by two parts at position (*). These parts, in turn, were swapped. The second rearrangement (taking into account the (*) value) allows obtaining the original file. ### Obfuscation To complicate code analysis, various obfuscation techniques are used in the packer: In between the execution of significant code, various WinAPI functions are called. Their results are saved but not used, and the functions are selected so that not to affect the program operation. Figure 8. Calling WinAPI functions A typical feature of this packer is the presence of cycles (not performing useful operations) implemented via a recursive function. Figure 9. Recursive function (sample without junk code) ----- o u t e ob uscat o, se e a do e s o a do y ge e ated u ct o s a e added to e ecutab e e ey ay ca eac ot e, but o e of them obtains control ever. Figure 10. Example of generated function ### Usage In addition to RTM samples, we detected the use of Rex3Packer for packing various malware, mainly originating from the CIS countries. Below is the list with examples of such malware: **Malware family** **SHA256** [Phobos Ransomware](https://malpedia.caad.fkie.fraunhofer.de/details/win.phobos) 6e9c9b72d1bdb993184c7aa05d961e706a57b3becf151ca4f883a80a07fdd955 [Zeppelin Ransomware](https://malpedia.caad.fkie.fraunhofer.de/details/win.zeppelin_ransomware) 8d44fdbedd0ec9ae59fad78bdb12d15d6903470eb1046b45c227193b233adda6 [Raccoon Stealer](https://malpedia.caad.fkie.fraunhofer.de/details/win.raccoon) 3be91458baa365febafb6b33283b9e1d7e53291de9fec9d3050cd32d98b7a039 [KPOT Stealer](https://malpedia.caad.fkie.fraunhofer.de/details/win.kpot_stealer) 9b6af2502547bbf9a64ccfb8889ee25566322da38e9e0ccb86b0e6131a67df1e [Predator The Thief](https://malpedia.caad.fkie.fraunhofer.de/details/win.predator) d1060835793f01d1e137ad92e4e38ef2596f20b26da3d12abcc8372158764a8f [QakBot](https://malpedia.caad.fkie.fraunhofer.de/details/win.qakbot) 18cc92453936d1267e790c489c419802403bb9544275b4a18f3472d2fe6f5dea [We also detected the use of this packer for packing malware samples of the Nemty,](https://malpedia.caad.fkie.fraunhofer.de/details/win.nemty) [Pony, and](https://malpedia.caad.fkie.fraunhofer.de/details/win.pony) [Amadey families. This is, of course, not an](https://malpedia.caad.fkie.fraunhofer.de/details/win.amadey) exhaustive list of all cases of using Rex3Packer. ## HellowinPacker In May 2020, RTM started using a new packer and went on using it until the beginning of 2021. We called it HellowinPacker because of the file name "hellowin.wav" we spotted in strings of some samples. The packer's key feature is two levels of code mutation. The first one significantly changes the unpacking code structure, making samples look different from each other. ----- Figure 11. Comparison of code in two samples of different structure The example above shows the comparison of samples 5b5f30f7cbd6343efd409f727e656a7039bff007be73a04827cce2277d873aa0 (on the left) and 1f9a8b3c060c2940a81442c9d9c9e36c31ad37aaa7cd61e1d7aec2d86fe1c585 (on the right). The second level only changes some details, and the code structure remains in general the same. The changes mainly affect assembler instructions and constants that do not impact the program operation. As a result, the code looks almost identical when decompiled. Figure 12. Comparison of code in two samples of the same structure ----- Just e e 3 ac e, e o ac e s act e y used by attac e s to pac a ous a a e ote t at a a e o t e sa e a y as t e same structure when packed. This lasts for at least some time, after which the structure can change. All these features coincide with the description of a packing service the access to which is sold on hacker forums: [Uniqueness] A customer is given a unique crypter that does not depend on other customers. If your files were spotted, your uploads are to blame. We're not looking for 10,000+ customers, we provide correct Premium support and have a very limited number of clients. We make only unique stubs for a customer. Apparently, each unique crypter has its own structure of generated code. The crypter itself can also mutate code but at a lower level, without changing the program structure. In any case, the significant executable code remains the same. ### Unpacking algorithm One of the first actions in all packed files is an attempt to open the registry key HKEY_CLASSES_ROOT\Interface\{b196b287-bab4-101ab69c-00aa00341d07} (character case may differ in each particular case) and request a default value. Correct program operation in some modifications of generated code depends on whether these operations are successful. Interface GUIDs may also differ. Here are some of the possible options: {3050f1dd-98b5-11cf-bb82-00aa00bdce0b} {aa5b6a80-b834-11d0-932f-00a0c90dcaa9} {683130a6-2e50-11d2-98a5-00c04f8ee1c4} {c7c3f5a1-88a3-11d0-abcb-00a0c90fffc0} {b8da6310-e19b-11d0-933c-00a0c90dcaa9} The subsequent code obtains the address at which a block of encrypted data is located. This block starts with a 4-byte number, which stores the size of initial data (those that will be obtained after decoding). By calling VirtualAlloc, a memory block of required size with RWX rights is allocated for decrypted data. Encrypted data is copied to the allocated memory by blocks of X bytes each. In the original file, "spaces" of Y byte length are located between these blocks. Figure 13. Scheme of data copying in HellowinPacker Data is then decrypted by 4-byte blocks: Each next block is interpreted as an integer (DWORD). Index of the first byte in the block is added to the integer. An xor operation is executed between the obtained value and the sum of the index and a fixed key (Z number) ----- a p e o a go t p e e tat o yt o ``` def decrypt(data, Z): index = 0 while index < len(data): dword = struct.unpack("