XLM + AMSI: New runtime defense against Excel 4.0 macro malware

We have recently expanded the integration of Antimalware Scan Interface (AMSI) with Office 365 to include the runtime scanning of Excel 4.0 (XLM) macros, to help antivirus solutions tackle the increase in attacks that use malicious XLM macros. This integration, an example of the many security features released for Microsoft 365 Apps on a regular basis, reflects our commitment to continuously increase protection for Microsoft 365 customers against the latest threats.

Microsoft Defender Antivirus is using this integration to detect and block XLM-based malware, and we encourage other antivirus products to use this open interface to gain better visibility and improve protections against these threats.

XLM macros is a legacy macro language that was made available to Microsoft Excel in 1992, prior to the introduction of Visual Basic for Applications (VBA) in 1993. While more rudimentary than VBA, XLM is powerful enough to provide interoperability with the operating system, and many organizations and users continue to use its functionality for legitimate purposes. Cybercriminals know this, and they have been abusing XLM macros, increasingly more frequently, to call Win32 APIs and run shell commands.

The AMSI instrumentation for VBA has been providing deep visibility into the runtime behavior of VBA macros. Its release in 2018 effectively removed the armor that macro-obfuscation equipped malware with, exposing malicious code to improved levels of scrutiny. Naturally, threat actors like those behind Trickbot, Zloader, and Ursnif have looked elsewhere for features to abuse and operate under the radar of security solutions, and they found a suitable alternative in XLM.

Like VBA and many other scripting languages abused by malware, XLM code can be obfuscated relatively easily to conceal the real intent of the macro. For example, attackers can hide URLs or file names of executable files from static inspection through simple strings manipulations. Attackers also take advantage of the way macro code persists within the Excel document—while VBA macros are stored in a dedicated OLE stream (and hence can be easily located and extracted), XLM macros do not exist as a separate, well-defined entity. Rather, each XLM macro statement is a formula within a cell. Extracting a whole XLM macro can become a cumbersome task, requiring a cell-by-cell inspection of the whole document.

Screenshot of Microsoft Excel file with malicious XLM macros

Figure 1. Sample malicious XLM macro

In addition, while formulas are typically executed downwards starting from the top, with XLM the macro content can be quite spread out, thanks to control flow statements like RUN, CALL, or GOTO, which allow the switching of execution flow from one column to another. This feature, together with obfuscation, has been abused by attackers to craft documents that could evade static analysis.

AMSI instrumentation for Excel 4.0 (XLM) macros

AMSI is an open interface that allows any application to request the scanning of any data at any time. In a nutshell, this technology provides applications the capability to interface with the installed antivirus solution in order to inspect and scan potentially dangerous data (e.g., a file downloaded from a remote location, or data generated dynamically by an application). Microsoft already utilizes this technology in various applications to detect malicious macros, script-based malware, and other threats:

  • Office VBA macros
  • JScript
  • VBScript
  • PowerShell
  • WMI
  • Dynamically loaded .NET assemblies
  • MSHTA/Jscript9

The data provided by AMSI is leveraged extensively by Microsoft Defender for Endpoint. It provides important data for machine learning models that process billions of signals every day to identify and block malicious behaviors. The XLM instrumentation is similar to the implementation in VBA and other scripting engines that integrate with AMSI:

Diagram representation of AMSI instrumentation for XLM

Figure 2. AMSI instrumentation for XLM

The XLM language allows a user to write programs that call native runtime functions, as well as external Win32 APIs. In both cases, the interfaces that dispatch the calls to these functions are intercepted and directed to an internal logger. The logger component stores the intercepted functions in text format within a circular buffer. When certain dangerous functions are called, for example the runtime function EXEC or the Win32 API ShellExecute, XLM halts the macro execution and invokes AMSI to request a synchronous scan of the circular buffer containing the functions logged up to that point. Such dangerous functions are called “trigger functions”. If the antivirus identifies the macro as malware, the execution of the macro is aborted and Excel is safely terminated, blocking the attack and preventing the malicious macro from doing any damage. Otherwise, the user experience continues seamlessly.

It’s important to observe that the interception of XLM function calls happens at runtime. This means that the logger component always registers the true behavior of all functions and associated parameters, which may contain URLs, file names, and other important IOCs, regardless of the obfuscation used by the malware.

The following is an example of an XLM macro found in a malicious document:

Screenshot of XLM macro

Figure 3. Sample XLM macro

This malicious macro consists of a series of commands (e.g., RUN, REGISTER, IF, etc.) with related parameters specified by references to other cells. For example, the token $CA$1889 passed to the first function RUN indicates that the string provided as parameter for this function is in the cell at column CA and row 1889.

This is only one of the many ways that XLM-based malware can obfuscate code. Detecting this macro is challenging because it doesn’t expose any suspicious strings or behavior. This is where the power of AMSI comes into play: the instrumentation allows XLM to inspect functions when they are invoked, so that all their parameters have already been de-obfuscated. As a result, the above macro produces a log that looks like the following:

Sample log produced when XLM macro is run

Figure 4. Sample log

The XLM engine determines that the dangerous function ShellExecuteA is being invoked, and subsequently places the macro execution on hold and passes the macro behavioral log to AMSI for scanning. The antivirus now has visibility into a behavioral log that completely exposes all of the data including, API names, URLs, and file names. The log makes it easy to conclude that this macro is trying to download and execute a DLL payload via the tool Rundll32.

Case study: ZLoader campaign

ZLoader is a malware family that has been actively perpetrating financial theft for several years. Like many of its peers, ZLoader operates via aggressive campaigns that rely on social engineering and the abuse of Office documents spread via email.

We have been monitoring the activity of this threat and observed that in the last year the attackers shifted to XLM as their infection vector of choice. The Excel documents have a typical lure message to trick the user into clicking “Enable Content” to allow the macro code to run.

Screenshot of malicious Excel file used in Zloader campaign

Figure 5. Malicious Excel file used in Zloader campaign

A closer look at the document reveals an Excel sheet with an obscure-looking name. That sheet embeds XLM macro formulas, which are stored several rows down to make the sheet look empty. Furthermore, the macro formulas are spread out and obfuscated, hindering static analysis and raising more challenges for identifying intent.

Screenshot of XLM macro used in Zloader campaign

Figure 6. Malicious XLM macro used in ZLoader campaign

Executing and debugging the macro with Excel is not very straightforward either. The macro has long loops that are used to decode and run further obfuscated macro formulas, and the Excel’s debugger doesn’t have the ability to control the execution in a granular way in order to skip loops and break on specific formulas.

However, when this macro runs with the AMSI instrumentation enabled, it produces up to three different logs that are passed to AMSI. The first two look like the following:

Screenshot of log produced when XLM macro used in Zloader campaign is run

Figure 7. Log produced when ZLoader’s XLM macro is run

The image only shows the final part of the log where the interesting activity shows up. We can see that the macro is issuing a new EXEC statement to run a .vbs file via explorer.exe. This EXEC statement causes the execution of the VBScript named EW2H.vbs, which has been decoded and saved to disk by the macro prior to the EXEC line. The VBScript then tries to download and run a binary payload. The macro attempts to do this twice, hence this log (with minor variations) is passed to AMSI twice.

If the above steps fail, the macro resorts to downloading the payload directly, producing the following log for AMSI:

Screenshot of log produced when XLM macro used in Zloader campaign is run

Figure 8. Log produced when ZLoader’s XLM macro is run

The macro defines two URLs, then downloads their content with the API URLDownloadToFileA, and finally invokes the API ShellExecuteA to launch the downloaded payload (the file jxi09.txt) via rundll32.exe. We can infer from this line that the payload is a DLL.

All three logs offer plenty of opportunities to detect malicious behavior and also allow the easy extraction of relevant IOCs like URLs, file names, etc. The initial XLM code in the Excel document is completely obfuscated and contains no usable information, making it tricky to issue static detections that are both effective and durable. With the dynamic nature of AMSI, the runtime behavior can be observed in cleartext, even with obfuscation. Detections based on the logs passed to AMSI also have the advantage of being more robust and generic in nature.


Runtime inspection of XLM macros is now available in Microsoft Excel and can be used by antivirus solutions like Microsoft Defender Antivirus that are registered as an AMSI provider on the device. This feature is included as an addition to the existing AMSI integration with Office. It’s enabled by default on the February Current Channel and Monthly Enterprise Channel for Microsoft 365 subscription users.

In its default configuration, XLM macros are scanned at runtime via AMSI, except in the following scenarios:

Administrators can now use the existing Microsoft 365 applications policy control to configure when both XLM and VBA macros are scanned at runtime via AMSI. Get the latest group policy template files.

Group Policy setting name Macro Runtime Scan Scope
Path User Configuration > Administrative templates > Microsoft Office 2016 > Security Settings
This policy setting specifies the behavior for both the VBA and Excel 4.0 (XLM) runtime scan features. Multiple Office apps support VBA macros, but XLM macros are only supported by Excel. Macros can only be scanned if the antivirus software registers as an Antimalware Scan Interface (AMSI) provider on the device.

If you enable this policy setting, you can choose from the following options to determine the macro runtime scanning behavior:

Disable for all files (not recommended): If you choose this option, no runtime scanning of enabled macros will be performed.

Enable for low trust files: If you choose this option, runtime scanning will be enabled for all files for which macros are enabled, except for the following files:

  • Files opened while macro security settings are set to “Enable all macros”
  • Files opened from a trusted location
  • Files that are Trusted Documents
  • Files that contain VBA that is digitally signed by a trusted publisher

Enable for all files: If you choose this option, then low trust files are not excluded from runtime scanning. The VBA and XLM runtimes report to an antivirus system certain high-risk code behaviors the macro is about to execute. This allows the antivirus system to indicate whether or not the macro behavior is malicious. If the behavior is determined to be malicious, the Office application closes the session and the antivirus system can quarantine the file. If the behavior is non-malicious, the macro execution proceeds.

Note: When macro runtime scanning is enabled, the runtime performance of affected VBA projects and XLM sheets may be reduced.

If you disable this policy setting, no runtime scanning of enabled macros will be performed.

If you don’t configure this policy setting, “Enable for low trust files” will be the default setting.

Note: This policy setting only applies to subscription versions of Office, such as Microsoft 365 Apps for enterprise.

AMSI improves security for all

AMSI provides deep and dynamic visibility into the runtime behaviors of macros and other scripts to expose threats that hide malicious intent behind obfuscation, junk control flow statements, and many other tricks. Microsoft Defender Antivirus, the built-in antivirus solution on Windows 10, has been leveraging AMSI to uncover a wide range of threats, from common malware to sophisticated attacks. The recent AMSI instrumentation in XLM directly tackles the rise of malware campaigns that abuse this feature. Because AMSI is an open interface, other antivirus solutions can leverage the same visibility to improve protections against threats. Security vendors can learn how to leverage AMSI in their antivirus products here.

At Microsoft, we take full advantage of signals from AMSI. The data generated by AMSI is not only useful for immediate client antimalware detections, but also provides rich signals for Microsoft Defender for Endpoint. In our blog post about AMSI for VBA, we described how these signals are ingested by multiple layers of cloud-based machine learning classifiers and are combined with all other signals. The result is an enhanced protection layer that learns to recognize and block new and unknown threats in real-time.

Figure 9. Example of detection from Microsoft Defender Antivirus based on data inspected by AMSI

Figure 10: Notification from Microsoft Excel after AMSI reported malware detection

Figure 11: Example of Microsoft Defender for Endpoint alert for detection of XLM malware

The visibility provided by AMSI leads to significant improvements in generic and resilient signatures that can stop waves of obfuscated and mutated variants of threats. AMSI-driven protection adds to an extensive multi-layer protection stack in Microsoft Defender for Endpoint, which also includes attack surface reduction, network protection, behavior monitoring and other technologies that protect against macro malware and other similar script-based threats.

The AMSI-enriched visibility provided by Microsoft Defender for Endpoint is further amplified across Microsoft 365 Defender, such that XLM macro threats are detected and blocked on various entry vectors. The orchestration of signal-sharing and coordinated defense in Microsoft 365 ensures that, for example, Microsoft Defender for Office 365 blocks macro malware distributed via email, which is the most common delivery methods for these threats.

Learn how you can stop attacks through automated, cross-domain security and built-in AI with Microsoft Defender 365.

Giulia Biagini, Office 365 Threat Research Team

Auston Wallace, Microsoft 365 Security Team

Andrea Lelli, Microsoft 365 Defender Research Team