# oR10n Labs **[or10nlabs.tech/reverse-engineering-the-mustang-panda-plugx-rat-extracting-the-config/](https://or10nlabs.tech/reverse-engineering-the-mustang-panda-plugx-rat-extracting-the-config/)** By oR10n 2020-07-05 [HomeReverse EngineeringReverse Engineering the Mustang Panda PlugX RAT – Extracting](https://or10nlabs.tech/) the Config ## Reverse Engineering the Mustang Panda PlugX RAT – Extracting the Config Hello everyone! This is a continuation on the series of blog posts focused on reverse engineering a new-ish variant of PlugX malware gaining traction around the Asia Pacific region. [On my previous post, we reverse engineered the loader to determine how it decrypts, load,](https://or10nlabs.tech/reverse-engineering-the-mustang-panda-plugx-loader/) and execute the actual RAT component of PlugX. For this post, we will continue from where we left off and focus on one thing – extracting the malware configuration. ## Introduction Extracting malware configuration is one of the sub-tasks we can focus on when reverse engineering malware. By accomplishing this, we can obtain information used by the malware during execution such as hardcoded C2 addresses, bot IDs, mutexes, file paths, and registry keys among others. More often than not, a malware configuration is stored within the malware binary itself as an encoded or encrypted blob to prevent easy detection and analysis. We have to do some reverse engineering in order to figure out where it is located, how it is encoded or encrypted, and how to reverse the algorithm to see the plain text configuration. After successfully extracting the configuration, we can create an automation scrip to facilitate extraction to a huge number of samples. This is extremely useful for a number of use cases such as tracking C2 addresses for a specific malware family, blacklisting C2 addresses on network security devices, hunting for indicators-of-compromise within an environment, assisting incident responders during an investigation, and so on. Let’s continue with the analysis. ## Extracting the configuration ----- [On my previous post, we were able to figure out that the payload is decrypted by the loader](https://or10nlabs.tech/reverse-engineering-the-mustang-panda-plugx-loader/) using XOR with multi-byte key. We also created an automation script to decrypt the payload and save it to disk. We’ll use this script to save a copy of the decrypted payload to disk and start from there. [Looking at the payload in DiE, we can see that it is a DLL file with a DLL name of HT.dll, 1](https://github.com/horsicq/Detect-It-Easy) Export function named Loader, and a bunch of Import functions from kernel32.dll and **user32.dll.** ----- Interestingly enough, the Import functions for this sample are not that many and doesn’t include typical functions you see for a RAT. Furthermore, the presence of GetProcAddress and LoadLibraryA potentially indicates that this sample dynamically resolves Win32 API functions at run time just like the loader. [Running FLOSS at the sample will give us a bunch of interesting strings to pivot from at IDA](https://github.com/fireeye/flare-floss) for a deeper analysis, but one interesting thing that immediately struck me was this blob with repeating pattern of “123456789“. By this time, some of you may already have an idea of what this is potentially and why the repeating pattern of 123456789 is so interesting for us. But to be sure, let’s take a closer look at the disassembly in IDA. Clicking this on the Strings window of IDA will show us that this blob starts at offset 0 of the data section. ----- Checking the x-refs of unk_10025000, will bring us to a function at sub_1000BE90. ----- As you can see, unk_10025000 is pushed onto the stack along with 724h and another memory offset dword_1002FC00 as parameters for a function located at sub_10002E20. Looking closer at sub_10002E20, we can immediately figure out that this is a wrapper function that dynamically resolves the address of memcpy from msvcrt (sub_100018B0) via GetProcAddress and LoadLibrary (sub_100018B0) and then calls it with the parameters passed to the function. ----- ----- In simpler terms, this function copies the first 1828 bytes of the data section (unk_10025000) to another memory location (dword_1002FC00). After that, dword_1002FC00 is pushed onto the stack along with 8 and another memory offset aXxxxxxxx as parameters for a function located at sub_10001950. This function is quite similar with the previous one but dynamically resolves the address of memcmp from **msvcrt and then calls it with the parameters passed to the function.** ----- Again in simpler terms, this function compares the first 8 bytes of dword_1002FC00 to “XXXXXXXX“. The result of the comparison determines the execution path of the malware. **Note: The malware uses a lot of wrapper functions like this to dynamically resolve the** address of various Win32 API functions from different DLLs via GetProcAddress and **LoadLibrary and then execute it. This is one of the anti-detection measures implemented by** this specific PlugX variant and is common through out the whole binary. Let’s focus on the execution path where it doesn’t match “XXXXXXXX“. As you can see, it pushes the string “123456789” onto the stack and calls a function at sub_10002DC0. ----- This is another wrapper function but this time, for lstrlenA to find the length of the string passed as a parameter. The resulting string length is stored in EAX and is pushed onto the stack along with the string “123456789“, 724h, and dword_1002FC00 which contains the blob we noted earlier before a call to sub_1000B840 is made. Looks familiar right? Yes, this is the same format of parameters we noted on the loader before the call to the decryption function – the key length, the key, the length of the encrypted data and the address of the encrypted data ----- Looking closer at sub_1000B840 and due to the fact that there are repeating patterns of **123456789 on the encrypted blob, we can immediately recognize that the algorithm used to** encrypt it is XOR with multi-byte key as well. So by extracting the first 1828 bytes of the data section and performing a multi-byte XOR on it with the key 123456789, we can decrypt the blob and see if it really contains the malware configuration. Let’s try it with a quick Cyberchef recipe: ----- As you can see, there are a few interesting information in here such as: - An Adobe themed unicode string “AAM UpdatesEqn” - A random looking unicode string “cHtWZJzVclxydatCXSUA” - IP addresses that are likely the C2 addresses Each IP address entry looks like it starts with 01 00, then followed by two bytes which are likely port numbers in hex, and then finally the IP address itself. If we convert the port numbers in hex to decimal (little endian) and the IP addresses in hex to ascii we will get the following addresses: ``` 103.200.97[.]189:965 103.200.97[.]189:110 185.239.226[.]17:965 185.239.226[.]17:110 ``` Let’s try to confirm our findings by running the sample on a VM and monitoring for any interesting events using some dynamic analysis tools. **File, registry, and process events captured by Procmon:** ----- From the Procmon output, we can see that the malware: - Created a new folder named AAM UpdatesEqn on the Program Data directory and copied the PlugX components to it - Attempted to access HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\Current **Version\Run for registry write operation but failed** - Succeeded in accessing HKCU\SOFTWARE\Microsoft\Windows\Current Version\Run for registry write operation - Created a new value named AAM UpdatesEqn. This is a persistence mechanism which will execute “C:\ProgramData\AAM UpdatesEqn\AAM Updates.exe” 701 across system reboots - Created a new process for C:\ProgramData\AAM UpdatesEqn\AAM Updates.exe passing the value 701 as parameter **HTTP request captured by fakenet:** From the Fakenet output, we can see that the malware communicated to one of the IP address and port combinations we noted earlier. **Searching for cHtWZJzVclxydatCXSUA handle in Procexp:** ----- Lastly, we can see that cHtWZJzVclxydatCXSUA is a mutex object used by the malware. These observations confirm that we were successful in extracting the configuration of the malware. ## Automating the config extraction To make our lives easier, I created this quick-and-dirty python script to automatically extract the configuration information for this variant: I’ve tested this script on a bunch of samples and it seems to work fine. However, there can be instances where it won’t work if the config is structured differently. That’s it guys! I really hope you learned something new today and as always, thank you for reading my blog. [Tags:Malware,](https://or10nlabs.tech/tag/malware/) [Mustang Panda,](https://or10nlabs.tech/tag/mustang-panda/) [PlugX,](https://or10nlabs.tech/tag/plugx/) [RAT,](https://or10nlabs.tech/tag/rat/) [Reverse Engineering](https://or10nlabs.tech/tag/reverse-engineering/) -----