Eddie Morra

Hiya MT viewers

For those of you who are unaware, AMSI stands for Antimalware Service Interface, and it is a Windows 10 only feature. It allows security software to receive callback notifications for certain activities (e.g. PowerShell, VBScript execution) and performs scans of the content it is filtering for to determine if the script should be allowed or not. Furthermore, AMSI can be operated by non-security software to get the opinion of the provider engines linked up to it... for example, a web browser may use the public AMSI APIs to scan a newly downloaded file with the security solution installed on the current environment if it has AMSI integration.

As some of you already know, Microsoft recently announced that Office 365 now has AMSI integration for the VBA Macro model. In reality, the support has been there for at-least numerous of months now (and I would imagine that Microsoft had been using it in Windows Defender since before the unofficial announcement, and possibly other third-party security solutions as well), but I have created this thread for discussing the new integration since it has now been officially mentioned.

The AMSI integration with Microsoft Office is planted under the Visual Basic Environment (v7) - this means the VBE7.dll module is going to be involved. We can confirm this with some reverse-engineering but I'll save you the trouble and leave some brief screenshots below which demonstrates that VBE7.dll does have use the AMSI APIs (which are exported by AMSI.dll).

Dynamic Imports.png

There's a cleaned version available below since I've renamed things to make it more readable.

Dynamic Imports (Cleaned).png

Below is a break-down of what the above routine is doing (we're only focusing on the key parts here of interest).

1. AMSI.dll is being loaded into the address space of the process which is using the Visual Basic Environment engine.
2. Since AMSI.dll is now accessible to the current process, dynamic imports are being setup for the following AMSI API routines: AmsiInitialize, AmsiUninitialize, AmsiScanString.
3. The AmsiInitialize routine from the AMSI API is being called to initialize the AMSI API and the provided context is being stored globally so it can be accessed by other routines in the future.

"OFFICE_VBA" is the application name throughout all usage of the AMSI usage by VBE7.dll.

The AmsiScanString routine from the AMSI API is being used later down the road for scanning scripts for malware (by VBE7.dll). When this API is used to scan scripts, the AMSI providers which are registered on the environment (e.g. Windows Defender or any other third-party solution with AMSI integration on the machine) will become involved for the scan operation and will process the scan of the string being passed to the AmsiScanString routine by VBE7.dll to be scanned.

We can see the AmsiScanString routine being called later down the road.


In the above image where disassembly of an unknown routine is shown, we can see the address of the AmsiScanString routine being used in a CALL instruction; the arguments for the routine are passed through usage of 64-bit registers since the version of VBE7.dll I am using for this is 64-bit. Afterwards, the AMSI scan result which is given back to the caller is checked out.

Now we know that Microsoft Office 2016/Office 365 really does have AMSI integration for Office VBA Macro's...

1. Cylance made a blog post a few months ago which took a look at AMSI and exposed a previously undocumented registry key which can be enabled to opt-in for AMSI support with VBE7.dll.
2. The latest update to the Administrative Templates for Office 365 with Group Policy Editor has a new area for configuring AMSI support with Office VBA Macro's.

To enable the AMSI support with Microsoft Office 2016/Office 365: HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Common\Security -> MacroRuntimeScanScope (DWORD) -> set to appropriate value depending on the wanted mode.

Below are the details for the MacroRuntimeScanScope key. Cylance mentioned the key and the value of 2 but the meanings of the value of 2 were undocumented to the public and the other modes were not mentioned anywhere else until now as far as I could find.

<policy name="L_MacroRuntimeScanScope" class="User" displayName="$(string.L_MacroRuntimeScanScope)" explainText="$(string.L_MacroRuntimeScanScopeExplain)" presentation="$(presentation.L_MacroRuntimeScanScope)" key="software\policies\microsoft\office\16.0\common\security">
      <parentCategory ref="L_SecuritySettings" />
      <supportedOn ref="windows:SUPPORTED_Windows_10_0" />
        <enum id="L_MacroRuntimeScanScopeEnum" valueName="macroruntimescanscope">
          <item displayName="$(string.L_DisableForAllDocuments)">
              <decimal value="0" />
          <item displayName="$(string.L_EnableForLowTrustDocumentsOnly)">
              <decimal value="1" />
          <item displayName="$(string.L_EnableForAllDocuments)">
              <decimal value="2" />
Based on the above which was taken from the Administrative Templates (I opened the office16.admx in a text editor and found the correct rules for it):

1. Set the MacroRuntimeScanScope key to 0 for disabling AMSI integration with all macro-enabled documents.
2. Set the MacroRuntimeScanScope key to 1 for enabling AMSI integration with only low-trusted documents.
3. Set the MacroRuntimeScanScope key to 2 for enabling AMSI integration with all documents regardless of whether they are trusted or not.

Here is more information about the low-trusted documents mode:
If the feature is enabled for low trust documents, the feature will be enabled for all documents for which macros are enabled except:

- Documents opened while macro security settings are set to "Enable All Macros"

- Documents opened from a Trusted Location

- Documents that are Trusted Documents

- Documents that contain VBA that is digitally signed by a Trusted Publisher
The above quote was taken from the group policy information.

I've done testing with the AMSI integration for Office 365 Business version and thus can confirm it does indeed work however there is something you should be aware of and that is that... it isn't as good as PowerShell is with AMSI. The reason for this is because Microsoft decided to limit it to working only when selected instructions are used in the macro scripts (for an unknown/non-public reason?). Cylance also mentioned this.

Due to the above limitation... Office VBA Macro support for AMSI integration is no where near as good as it could be... I wanted it to work like the PowerShell implementation where I can freely scan anything being executed by the macro script, but that isn't the case sadly. It'll only trigger for specific things being done by the macro.

These limitations are also present for VBScript and JavaScript execution through wscript.exe and cscript.exe. It'll only trigger for select things like when you try to spawn another program, and not for everything being executed by the script interpreter.
Last edited by a moderator: