XLL is an Excel Add-in extension file that provides ways to use third-party tools and functions that are not available in Microsoft Excel. It is typically a Dynamic Link Library (DLL) file that can be loaded by Microsoft Excel provided the file uses the .xll extension.
We have seen a surge of malware campaigns and attacks that were using XLL malware. Most of the malicious XLL files that we encountered utilized the open-source framework named Excel-DNA. Excel-DNA is a framework which allows you to create native XLL files using C# or Visual Basic.NET. It also allows you to create user-defined functions, custom ribbons and many more. Palo Alto’s Unit 42 did a great job on the analysis of the first few malicious XLL files that utilized the Excel-DNA framework.
Most Excel-DNA XLL malware that we have observed are simple downloaders or droppers, where the payloads are embedded within the XLL files themselves. The start of its malicious code is usually found in an overridden AutoOpen function from Excel-DNA’s IExcelAddIn interface. Whenever an XLL file is opened by Excel, it invokes the xlAutoOpen function exported by XLL interface, which Excel-DNA passes to IExcelAddIn. AutoOpen().
Typically, the final payload will either be downloaded or dropped onto the file system, before being executed. This typical malicious behavior is usually detected by endpoint security products. However, malware authors are always actively looking for ways to evade such detection.
Recently, we detected improvements implemented in XLL malware to execute its payload without dropping the file to disk. Techniques like this are not totally new, however, this trick may have higher a chance of evading detection by endpoint security products.
This post details this Excel-DNA XLL malware improvements in evading detection.
Analysis
Sample Sha256: 2d9035fccfa410259c75bb54edc9c95c2d736e6bdf87832fc2062dcd89286b39
Our analysis begins with browsing through the resource section of the XLL file. Excel add-ins are usually compressed with LZMA algorithm and embedded in resource section. Looking at the resource named __MAIN__ from DNA directory, this contains the information of the modules to be loaded by Excel-DNA. We can see that a module named ENTER will be loaded. Let’s extract this library and check the code.
Figure 1. DNA Main XML Information
The “Enter” Module
Instead of using a customized Excel add-in library to automatically execute the malicious code via the xlAutoOpen function, this variant uses the Excel ribbon feature, which is supported in the Excel-DNA framework as an interface object. The inherited ExcelRibbon object is assumed to customize the application’s ribbon interface. However, this module does not call the GetCustomUI function which loads the XML used to configure the appearance of the ribbon interface. Instead it takes advantage of this feature to execute a malicious function.
The malicious function will be called in the library’s class constructor. Class constructor is a special member of a class that will be first executed whenever a new instance of that class is created.
Figure 2. Class Constructor
Looking at the handler() function, first it will download some data from an obfuscated URL, which was hard-coded into the module. Its obfuscation is simple, each character was subtracted by a hard-coded key, in this case 2 integer value.
Figure 3. Obfuscated URL
As shown in Figure 3, we expect the file to be downloaded as an RTF document. Instead, it appears to be plaintext configuration data split into an array using “@” as the delimiter. Each element will be accessed through its index in the array. Figure 4 shows the actual split data and Table 1 shows the description by each index
Figure 4. Downloaded Data
Index | Description |
0 | Decryption keys |
1 | URL to the encrypted MSIL download |
2 | Encrypted MSIL DLL injector |
3 | DLL class |
4 | Class method name |
5 | Target application path in reverse string |
Table 1. Data description by index
Next, the encrypted data found in index 2 will be decrypted. The decryption is just a simple XOR using the decryption keys from index 0, and decoded with Base64.
Figure 5. Decryption Function for Encrypted MSIL Application
The decrypted data turns out to be an MSIL assembly named “patent.dll”. This component is just a simple injector, which will be reflectively loaded using the .NET Assembly.Load method. It simply means that this DLL will be loaded directly from memory so methods can be directly invoked without saving the file to disk.
Another file will be downloaded from the URL specified in index 2, which is also encrypted and will be decrypted using the same function shown in Figure 5. Again, this one turns out to be another executable MSIL application, this time named “ZxuiU.exe”. This executable file will be loaded and injected into a target process by calling a method from the MSIL assembly named “patent.dll”. The values in index 3 and index 4 corresponds to the DLL class and method name respectively. And index 5 is the reverse string source path where it will be injected.
Figure 6. Invoke Code Injector
Injected MSIL EXE Component (ZxuiU.exe)
Please take note that at this stage, the malware is already running and injected into a legitimate application, in this case “C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regbrowsers.exe”. This malicious module is also a downloader, where strings are obfuscated so it will not easily be analyzed. Although it was just a simple base64 encoded, the authors implemented some tricks like reverse string, character concatenation, string replace, etc., so this base64 encoded string will not be easily spotted at a first glance.
This malware will download another component MSIL assembly named “BreadPlayer.Common.dll” from the URL below. This DLL will also be reflectively loaded in memory so its methods can be invoked.
hxxps[:]//cdn[.]discordapp[.]com/attachments/960145684319838258/960211802254364722/BreadPlayer[.]Common[.]dll
Upon looking at this module, it appears to be a tool known as “RunPE” which is used for process hollowing. This tool is used by malware to hide and execute its code into a target legitimate process. At first glance, it is not obvious that it is a RunPE tool since all the common APIs used for this trick were hidden. This module implements Dynamic API resolving to make static analysis harder. Figure 8 shows resolving the common APIs used in process hollowing.
Figure 7. APIs for Process Hollowing
After the RunPE module has been downloaded and reflectively loaded, it will then proceed to downloading the final payload, which is executed as a newly created instance of a legitimate system process where the loader is currently running. This invokes the method from the RunPE module with the parameter of the downloaded final payload.
Figure 8. Download RunPE and Final Payload
The final payload downloaded is a Formbook malware, a popular information stealer/trojan available as a Malware-as-a-Service on the dark web market since 2016.
Conclusion
Malware authors are always finding ways to improve their malware capabilities and evade detection. The malware analyzed in this post used multi-stage loading in their XLL malware to further evade detection. These evasion methods are that common which means the chances are still high that this malware could execute on the victim’s machine.
Techniques used with this improved XLL malware have pros and cons. One of its advantages is that components and final payload will not be dropped in the disk, which could evade detection by security products. However, one of its disadvantages is that it needs to download multiple components and the final payload from different URLs; its execution could possibly fail once a single URL is down.
It is no surprise to us to find more upcoming improvements related to this Excel-DNA XLL malware due to its high functioning capabilities. Our team in Cyren will keep monitoring this and other evolving threats to help protect our customers from malware.
Indicators of Compromise
SHA256/URL | Cyren Detection |
2d9035fccfa410259c75bb54edc9c95c2d736e6bdf87832fc2062dcd89286b39 | W64/Exclddn.LWSS-3552 |
0c425d6c6bce93fad4f32c275db574e8b3161a1ae55a9a957d50020b516d3e2c | W64/Exclddn.OMFP-6694 |
5f1beab27690a8ea9b9be78c5d34dd852dd3af4f5128feace84d1b2e10d73b59 | W64/Exclddn.TFNR-0460 |
d838c7ad537e71dab1b968088db4b08195429a5ba6c22fdacad992caf27082a0 | W32/Agent.DND.gen!Eldorado |
3ef33bf0d2e2ce10b3d32bf82e78195acc2c4fd15cc5cd9a8c1226ea98ac6884 | W32/Trojan.ZQXR-7580 |
6c229a6e31cf525bc3d46c0f1d2cf52e6a1a2ced7b4cec7b8ba0fb1672dc38e8 | W32/Injector.QCUW-2488 |
2796fac226083d8b53551fc5cd97f1ab08a2a9b9c6989a594186b05f624e1e32 | W32/Trojan.SOAJ-7035 |
232a16efaec47e6d4fc8f5318ed9d9d58198daef519f30a5d9147d38f293638c | W32/Formbook.A.gen!Eldorado |
hxxps[:]//transfer[.]sh/get/52J99O/ku7AxHxl-s[.]rtf | |
hxxps[:]//transfer[.]sh/get/KcWg0b/JPqlepxl-s[.]rtf | |
hxxps[:]//transfer[.]sh/get/TWyTFS/aj2xJUxl-s[.]rtf | |
hxxps[:]//transfer[.]sh/get/0Bny60/ku7AxHxl-r[.]txt | |
hxxps[:]//transfer[.]sh/get/TllEFR/JPqlepxl-r[.]txt | |
hxxps[:]//transfer[.]sh/get/MqAftf/aj2xJUxl-r[.]txt | |
hxxps[:]//cdn[.]discordapp[.]com/attachments/960145684319838258/960211802254364722/BreadPlayer[.]Common[.]dll | |
hxxp[:]//179[.]43[.]175[.]179/nhtg/binleg2[.]exe |