Anti-Analysis Techniques Used in Excel 4.0 Macros
24 March 2021
By Jacob Pimental
I recently reversed another Excel document with 4.0 Macros that was similar to my previous post on the subject but had some added anti-analysis features that I wanted to share. I recommend reading the previous post to learn more as this article will not be going step-by-step through the analysis process. If you would like to follow along you can find the sample here.
New Obfuscation Style
Instead of storing the encrypted data as a blob of characters in cells, the sample stores them as integers in Sheet1
of the document. It will then loop through these and subtract them from a stored key in R50C3:R59:C3
. If the integer value at the current index of Sheet1
is greater than 1000, then the end of the string has been reached. This is very similar to the old sample, but the use of integer values seemed interesting to me.
Decryption function
Integer arrays in Sheet1
Anti-Analysis Tricks
Like the previous analysis, the document performs a lot of the same VM/Analysis checks such as: checking for the presence of a cursor, if macros are set to run by default, etc. This specific sample, however, had a few more tricks.
Xlcall32
The sample will use the =CALL
macro to make a call to the Excel4
function from the Xlcall32
library. This is a callback function that is used to continue running the macros at a defined cell. This is a good way to prevent an analyst from just debugging the macros since this would spawn in a new process and won’t show in the debugger.
This will continue running the macros at R106C1
and evade debugging
In this sample, the call to Excel4
is dynamically generated via the deobfuscation code from earlier. When running the deobfuscation code, I will put a =HALT()
instruction at the end to prevent further execution. Once the anti-analysis technique is bypassed, I will continue running the macros at the location passed as a parameter to Excel4
. This gives the same results as calling the Excel4
function except now I can see what the code is doing.
Visualization of how I bypass the anti-analysis technique
Alternate Data Streams (ADS)
Alternate Data Streams (ADS) are a feature of the NT File System (NTFS) that allows a user to store additional content in a file apart from its original content. ADS is used legitimately for file integrity and storing metadata; however, attackers can use it to hide malicious code. In older versions of SQL Server, for example, the DBCC CHECKDB process would create alternate data streams to store information.
When a file is downloaded from the internet, it will contain an ADS called Zone.Identifier
which has data about where the file originated. In this case, the sample I downloaded was from Zoho Docs, therefore, it contained that URL in the stream. This particular sample checks to see if the ADS is present by actually trying to delete the ADS itself. If this sample were run in a sandbox, there would be no ADS, thus triggering this anti-analysis technique and halting the execution of the macros.
The alternate data stream of the sample
Checking for Zone.Identifier
alternate data stream by trying to delete it
C2s
As with the previous analysis, once all the checks are complete, the sample will reach out to C2s to try to grab the second stage payload and execute it. In this case, it appears to be a DLL that will be executed through rundll32.exe
calling DllRegisterServer
. Both of the C2s were down when I found the sample, so I could not get the second stage to continue the analysis.
Downloading the second stage from C2
C2 |
---|
https://fernandogaleano[.]com/server.php |
https://catedraloor[.]com/server.php |
Conclusion
Hopefully, this provided insight into a few anti-analysis techniques seen in the wild and can be a good reference to other analysts in the future. The call to Xlcall32
was new to me, and I had not seen the alternate data stream check used before. If you have any questions or comments on this analysis feel free to reach out to me on my Twitter or LinkedIn.
Thanks for reading and happy reversing!