{"componentChunkName":"component---src-templates-post-template-js","path":"/amsi-create-provider-en","result":{"data":{"markdownRemark":{"id":"0033a114-3b4d-50b2-8d08-49b24a3992ff","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/amsi-create-provider\">original page</a>.</p>\n</blockquote>\n<p>Following on from <a href=\"/amsi-learn-en\">an overview of AMSI and how it works</a> and <a href=\"/amsi-create-interface-en\">issuing AMSI scan requests from a custom application</a>, this time I will read through the sample code for a provider that processes scan requests using the AMSI interface.</p>\n<p>Reference: <a href=\"https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/AmsiProvider\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Windows-classic-samples/Samples/AmsiProvider at main · microsoft/Windows-classic-samples</a></p>\n<!-- omit in toc -->\n<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ul>\n<li><a href=\"#registering-the-provider\">Registering the provider</a></li>\n<li><a href=\"#the-dllmain-function\">The DllMain function</a></li>\n<li>\n<p><a href=\"#overriding-sampleamsiprovider\">Overriding SampleAmsiProvider</a></p>\n<ul>\n<li><a href=\"#overriding-the-displayname-method\">Overriding the DisplayName method</a></li>\n<li><a href=\"#overriding-the-closesession-method\">Overriding the CloseSession method</a></li>\n<li><a href=\"#overriding-the-scan-method\">Overriding the Scan method</a></li>\n</ul>\n</li>\n<li><a href=\"#collecting-and-analyzing-etw-trace-logs\">Collecting and analyzing ETW trace logs</a></li>\n<li><a href=\"#summary\">Summary</a></li>\n</ul>\n<h2 id=\"registering-the-provider\" style=\"position:relative;\"><a href=\"#registering-the-provider\" aria-label=\"registering the provider permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Registering the provider</h2>\n<p>You can register <code class=\"language-text\">AmsiProvider.dll</code>, built from the AmsiProvider sample code, on the system with the command <code class=\"language-text\">regsvr32 AmsiProvider.dll</code>.</p>\n<p>This command calls the <code class=\"language-text\">DllRegisterServer</code> function.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/directshow/implementing-dllregisterserver\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Implementing DllRegisterServer - Win32 apps | Microsoft Learn</a></p>\n<p>In the sample code, the <code class=\"language-text\">DllRegisterServer</code> function is implemented as follows, and performs several registry operations required to register the DLL as an AMSI provider.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">HRESULT <span class=\"token function\">SetKeyStringValue</span><span class=\"token punctuation\">(</span>_In_ HKEY key<span class=\"token punctuation\">,</span> _In_opt_ PCWSTR subkey<span class=\"token punctuation\">,</span> _In_opt_ PCWSTR valueName<span class=\"token punctuation\">,</span> _In_ PCWSTR stringValue<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    LONG status <span class=\"token operator\">=</span> <span class=\"token function\">RegSetKeyValue</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">,</span> subkey<span class=\"token punctuation\">,</span> valueName<span class=\"token punctuation\">,</span> REG_SZ<span class=\"token punctuation\">,</span> stringValue<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token function\">wcslen</span><span class=\"token punctuation\">(</span>stringValue<span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">wchar_t</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">HRESULT_FROM_WIN32</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n\nSTDAPI <span class=\"token function\">DllRegisterServer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">wchar_t</span> modulePath<span class=\"token punctuation\">[</span>MAX_PATH<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">GetModuleFileName</span><span class=\"token punctuation\">(</span>g_currentModule<span class=\"token punctuation\">,</span> modulePath<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>modulePath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">>=</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>modulePath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> E_UNEXPECTED<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Create a standard COM registration for our CLSID.</span>\n    <span class=\"token comment\">// The class must be registered as \"Both\" threading model</span>\n    <span class=\"token comment\">// and support multithreaded access.</span>\n    <span class=\"token class-name\">wchar_t</span> clsidString<span class=\"token punctuation\">[</span><span class=\"token number\">40</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">StringFromGUID2</span><span class=\"token punctuation\">(</span><span class=\"token function\">__uuidof</span><span class=\"token punctuation\">(</span>SampleAmsiProvider<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> E_UNEXPECTED<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token class-name\">wchar_t</span> keyPath<span class=\"token punctuation\">[</span><span class=\"token number\">200</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    HRESULT hr <span class=\"token operator\">=</span> <span class=\"token function\">StringCchPrintf</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> L<span class=\"token string\">\"Software\\\\Classes\\\\CLSID\\\\%ls\"</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">SetKeyStringValue</span><span class=\"token punctuation\">(</span>HKEY_LOCAL_MACHINE<span class=\"token punctuation\">,</span> keyPath<span class=\"token punctuation\">,</span> nullptr<span class=\"token punctuation\">,</span> L<span class=\"token string\">\"SampleAmsiProvider\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">StringCchPrintf</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> L<span class=\"token string\">\"Software\\\\Classes\\\\CLSID\\\\%ls\\\\InProcServer32\"</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">SetKeyStringValue</span><span class=\"token punctuation\">(</span>HKEY_LOCAL_MACHINE<span class=\"token punctuation\">,</span> keyPath<span class=\"token punctuation\">,</span> nullptr<span class=\"token punctuation\">,</span> modulePath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">SetKeyStringValue</span><span class=\"token punctuation\">(</span>HKEY_LOCAL_MACHINE<span class=\"token punctuation\">,</span> keyPath<span class=\"token punctuation\">,</span> L<span class=\"token string\">\"ThreadingModel\"</span><span class=\"token punctuation\">,</span> L<span class=\"token string\">\"Both\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Register this CLSID as an anti-malware provider.</span>\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">StringCchPrintf</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> L<span class=\"token string\">\"Software\\\\Microsoft\\\\AMSI\\\\Providers\\\\%ls\"</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">SetKeyStringValue</span><span class=\"token punctuation\">(</span>HKEY_LOCAL_MACHINE<span class=\"token punctuation\">,</span> keyPath<span class=\"token punctuation\">,</span> nullptr<span class=\"token punctuation\">,</span> L<span class=\"token string\">\"SampleAmsiProvider\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> S_OK<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>This function performs the following registry key operations:</p>\n<ol>\n<li>Using the sample provider’s UUID, <code class=\"language-text\">{2E5D8A62-77F9-4F7B-A90C-2744820139B2}</code>, it registers the provider name <code class=\"language-text\">SampleAmsiProvider</code> under <code class=\"language-text\">HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{2E5D8A62-77F9-4F7B-A90C-2744820139B2}</code>.</li>\n<li>It adds <code class=\"language-text\">HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{2E5D8A62-77F9-4F7B-A90C-2744820139B2}\\InProcServer32</code> and registers the file path of the provider DLL.</li>\n<li>It also adds a string value named <code class=\"language-text\">ThreadingModel</code> directly under the same key and sets its value to <code class=\"language-text\">Both</code>.</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/628393f2bc04a1cdba98e36a333a1df9/cd78c/image-20250701163500895.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 15.833333333333332%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAm0lEQVQI12WP0QrDIAxF+/+/t4d2lFWojCptsdZqVq3eqWPsYYHDgYRckqbjE6QQMMaAyCGEgOu6qr9473GeZ3Xwn3lKCTHGPxq1rjmQo+1a3PsHGGNgAwPnHHwcIYSEUqoipITMOOegtYa19kfu0euFJiaA7IJb16MdnpjnuS7tu4FeF8hpgiNCKcoun5Tatg3HcdTwElhcLn8DKsHlsUzdRZUAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/628393f2bc04a1cdba98e36a333a1df9/8ac56/image-20250701163500895.webp 240w,\n/static/628393f2bc04a1cdba98e36a333a1df9/d3be9/image-20250701163500895.webp 480w,\n/static/628393f2bc04a1cdba98e36a333a1df9/e46b2/image-20250701163500895.webp 960w,\n/static/628393f2bc04a1cdba98e36a333a1df9/5b1dd/image-20250701163500895.webp 1236w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/628393f2bc04a1cdba98e36a333a1df9/8ff5a/image-20250701163500895.png 240w,\n/static/628393f2bc04a1cdba98e36a333a1df9/e85cb/image-20250701163500895.png 480w,\n/static/628393f2bc04a1cdba98e36a333a1df9/d9199/image-20250701163500895.png 960w,\n/static/628393f2bc04a1cdba98e36a333a1df9/cd78c/image-20250701163500895.png 1236w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/628393f2bc04a1cdba98e36a333a1df9/d9199/image-20250701163500895.png\"\n            alt=\"image-20250701163500895\"\n            title=\"image-20250701163500895\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<ol start=\"4\">\n<li>Finally, it registers the sample provider’s UUID as a key directly under <code class=\"language-text\">HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\AMSI\\Providers</code>, and stores the provider name <code class=\"language-text\">SampleAmsiProvider</code>.</li>\n</ol>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/63559ea4838985dec3a4317cb6d89c28/f5209/image-20250701163932598.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 16.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAmElEQVQI112MyQ6CQBQE+f9/82xEJQgGZBtmYZ0BygkJauykU+/1oQKlNE2ZkGcpxhg6o9Faefq7M4hWEEcRdd0wDAN93yOlJMtz1nXdt0aIfZ/mmcC6hc113OOQ0znm9qwIk4JrWnLxbJVh9GLnHL+x1u48pOM4siwLwTRb3KR45Q/SrKASkrIWvi1VI1H6K9u27dPj/88bsmTmzYKnwaEAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/63559ea4838985dec3a4317cb6d89c28/8ac56/image-20250701163932598.webp 240w,\n/static/63559ea4838985dec3a4317cb6d89c28/d3be9/image-20250701163932598.webp 480w,\n/static/63559ea4838985dec3a4317cb6d89c28/e46b2/image-20250701163932598.webp 960w,\n/static/63559ea4838985dec3a4317cb6d89c28/44ba8/image-20250701163932598.webp 1061w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/63559ea4838985dec3a4317cb6d89c28/8ff5a/image-20250701163932598.png 240w,\n/static/63559ea4838985dec3a4317cb6d89c28/e85cb/image-20250701163932598.png 480w,\n/static/63559ea4838985dec3a4317cb6d89c28/d9199/image-20250701163932598.png 960w,\n/static/63559ea4838985dec3a4317cb6d89c28/f5209/image-20250701163932598.png 1061w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/63559ea4838985dec3a4317cb6d89c28/d9199/image-20250701163932598.png\"\n            alt=\"image-20250701163932598\"\n            title=\"image-20250701163932598\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>To uninstall the provider registered this way, run the command <code class=\"language-text\">regsvr32 /u AmsiProvider.dll</code>.</p>\n<p>The <code class=\"language-text\">DllUnregisterServer</code> function is responsible for deleting the registry keys created above.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">STDAPI <span class=\"token function\">DllUnregisterServer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">wchar_t</span> clsidString<span class=\"token punctuation\">[</span><span class=\"token number\">40</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">StringFromGUID2</span><span class=\"token punctuation\">(</span><span class=\"token function\">__uuidof</span><span class=\"token punctuation\">(</span>SampleAmsiProvider<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> E_UNEXPECTED<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// Unregister this CLSID as an anti-malware provider.</span>\n    <span class=\"token class-name\">wchar_t</span> keyPath<span class=\"token punctuation\">[</span><span class=\"token number\">200</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    HRESULT hr <span class=\"token operator\">=</span> <span class=\"token function\">StringCchPrintf</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> L<span class=\"token string\">\"Software\\\\Microsoft\\\\AMSI\\\\Providers\\\\%ls\"</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n    LONG status <span class=\"token operator\">=</span> <span class=\"token function\">RegDeleteTree</span><span class=\"token punctuation\">(</span>HKEY_LOCAL_MACHINE<span class=\"token punctuation\">,</span> keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>status <span class=\"token operator\">!=</span> NO_ERROR <span class=\"token operator\">&amp;&amp;</span> status <span class=\"token operator\">!=</span> ERROR_PATH_NOT_FOUND<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token function\">HRESULT_FROM_WIN32</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Unregister this CLSID as a COM server.</span>\n    hr <span class=\"token operator\">=</span> <span class=\"token function\">StringCchPrintf</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">,</span> <span class=\"token function\">ARRAYSIZE</span><span class=\"token punctuation\">(</span>keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> L<span class=\"token string\">\"Software\\\\Classes\\\\CLSID\\\\%ls\"</span><span class=\"token punctuation\">,</span> clsidString<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">FAILED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> hr<span class=\"token punctuation\">;</span>\n    status <span class=\"token operator\">=</span> <span class=\"token function\">RegDeleteTree</span><span class=\"token punctuation\">(</span>HKEY_LOCAL_MACHINE<span class=\"token punctuation\">,</span> keyPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>status <span class=\"token operator\">!=</span> NO_ERROR <span class=\"token operator\">&amp;&amp;</span> status <span class=\"token operator\">!=</span> ERROR_PATH_NOT_FOUND<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token function\">HRESULT_FROM_WIN32</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> S_OK<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2 id=\"the-dllmain-function\" style=\"position:relative;\"><a href=\"#the-dllmain-function\" aria-label=\"the dllmain function permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The DllMain function</h2>\n<p>First, let’s look at the <code class=\"language-text\">DllMain</code> function, which serves as the entry point called when the DLL is loaded or unloaded.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/dlls/dllmain\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DllMain entry point - Win32 apps | Microsoft Learn</a></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">BOOL APIENTRY <span class=\"token function\">DllMain</span><span class=\"token punctuation\">(</span>HMODULE module<span class=\"token punctuation\">,</span> DWORD reason<span class=\"token punctuation\">,</span> LPVOID reserved<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>reason<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">case</span> DLL_PROCESS_ATTACH<span class=\"token operator\">:</span>\n        g_currentModule <span class=\"token operator\">=</span> module<span class=\"token punctuation\">;</span>\n        <span class=\"token function\">DisableThreadLibraryCalls</span><span class=\"token punctuation\">(</span>module<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">TraceLoggingRegister</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Loaded\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        Module<span class=\"token operator\">&lt;</span>InProc<span class=\"token operator\">></span><span class=\"token operator\">::</span><span class=\"token function\">GetModule</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">Create</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">case</span> DLL_PROCESS_DETACH<span class=\"token operator\">:</span>\n        Module<span class=\"token operator\">&lt;</span>InProc<span class=\"token operator\">></span><span class=\"token operator\">::</span><span class=\"token function\">GetModule</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">Terminate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Unloaded\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">TraceLoggingUnregister</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> TRUE<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>When this DLL is loaded, it first calls the <code class=\"language-text\">DisableThreadLibraryCalls</code> function with the handle to the DLL module it received, disabling <code class=\"language-text\">DLL_THREAD_ATTACH</code> and <code class=\"language-text\">DLL_THREAD_DETACH</code> notifications.</p>\n<p>This seems to have the advantage of preventing unnecessary calls whenever threads are created or terminated within the process.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/libloaderapi/nf-libloaderapi-disablethreadlibrarycalls\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DisableThreadLibraryCalls function (libloaderapi.h) - Win32 apps | Microsoft Learn</a></p>\n<p>Next, <code class=\"language-text\">TraceLoggingRegister</code> registers the TraceLogging provider.</p>\n<p>This is for ETW trace logging. At this point, the provider given as the argument, <code class=\"language-text\">g_traceLoggingProvider</code>, is registered with the provider name <code class=\"language-text\">SampleAmsiProvider</code> and the GUID <code class=\"language-text\">00604c86-2d25-46d6-b814-cd149bfdf0b3</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token comment\">// Define a trace logging provider: 00604c86-2d25-46d6-b814-cd149bfdf0b3</span>\n<span class=\"token function\">TRACELOGGING_DEFINE_PROVIDER</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"SampleAmsiProvider\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">(</span><span class=\"token number\">0x00604c86</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0x2d25</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0x46d6</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0xb8</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0x14</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0xcd</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0x14</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0x9b</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0xfd</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0xf0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0xb3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/traceloggingprovider/nf-traceloggingprovider-traceloggingregister\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">TraceLoggingRegister - Win32 apps | Microsoft Learn</a></p>\n<p>After that, <code class=\"language-text\">TraceLoggingWrite(g_traceLoggingProvider, \"Loaded\");</code> outputs an event whose event name is <code class=\"language-text\">Loaded</code>.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/traceloggingprovider/nf-traceloggingprovider-traceloggingwrite\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">TraceLoggingWrite macro (traceloggingprovider.h) - Win32 apps | Microsoft Learn</a></p>\n<p>Finally, <code class=\"language-text\">Module&lt;InProc>::GetModule().Create();</code> is called.</p>\n<p>I do not fully understand its behavior in detail, but it appears to prepare an instance using <code class=\"language-text\">Microsoft::WRL::Module</code>, a class WRL provides for managing modules for COM DLLs.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/cpp/cppcx/wrl/how-to-create-a-classic-com-component-using-wrl?view=msvc-170\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">How to: Create a Classic COM Component Using WRL | Microsoft Learn</a></p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/cpp/cppcx/wrl/module-class?view=msvc-170\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Module Class | Microsoft Learn</a></p>\n<h2 id=\"overriding-sampleamsiprovider\" style=\"position:relative;\"><a href=\"#overriding-sampleamsiprovider\" aria-label=\"overriding sampleamsiprovider permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Overriding SampleAmsiProvider</h2>\n<p>An AMSI provider is, in practice, a COM server implemented as a DLL loaded into the host, and it exposes the <code class=\"language-text\">IAntimalwareProvider</code> interface, which inherits from <code class=\"language-text\">IUnknown</code>.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/amsi/nn-amsi-iantimalwareprovider\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IAntimalwareProvider (amsi.h) - Win32 apps | Microsoft Learn</a></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">class\n    <span class=\"token function\">DECLSPEC_UUID</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"2E5D8A62-77F9-4F7B-A90C-2744820139B2\"</span><span class=\"token punctuation\">)</span>\n    SampleAmsiProvider <span class=\"token operator\">:</span> public RuntimeClass<span class=\"token operator\">&lt;</span>RuntimeClassFlags<span class=\"token operator\">&lt;</span>ClassicCom<span class=\"token operator\">></span><span class=\"token punctuation\">,</span> IAntimalwareProvider<span class=\"token punctuation\">,</span> FtmBase<span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span>\npublic<span class=\"token operator\">:</span>\n    <span class=\"token function\">IFACEMETHOD</span><span class=\"token punctuation\">(</span>Scan<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>_In_ IAmsiStream<span class=\"token operator\">*</span> stream<span class=\"token punctuation\">,</span> _Out_ AMSI_RESULT<span class=\"token operator\">*</span> result<span class=\"token punctuation\">)</span> override<span class=\"token punctuation\">;</span>\n    <span class=\"token function\">IFACEMETHOD_</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">,</span> CloseSession<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>_In_ ULONGLONG session<span class=\"token punctuation\">)</span> override<span class=\"token punctuation\">;</span>\n    <span class=\"token function\">IFACEMETHOD</span><span class=\"token punctuation\">(</span>DisplayName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span>_Outptr_ LPWSTR<span class=\"token operator\">*</span> displayName<span class=\"token punctuation\">)</span> override<span class=\"token punctuation\">;</span>\n\nprivate<span class=\"token operator\">:</span>\n    <span class=\"token comment\">// We assign each Scan request a unique number for logging purposes.</span>\n    LONG m_requestNumber <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>By overriding the <code class=\"language-text\">Scan</code> method of the <code class=\"language-text\">IAntimalwareProvider</code> interface, AMSI provider developers can implement their own content scanning.</p>\n<h3 id=\"overriding-the-displayname-method\" style=\"position:relative;\"><a href=\"#overriding-the-displayname-method\" aria-label=\"overriding the displayname method permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Overriding the DisplayName method</h3>\n<p><code class=\"language-text\">IAntimalwareProvider::DisplayName</code> is a method that simply returns the name of the AMSI provider.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/amsi/nf-amsi-iantimalwareprovider-displayname\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IAntimalwareProvider::DisplayName (amsi.h) - Win32 apps | Microsoft Learn</a></p>\n<p>In <code class=\"language-text\">SampleAmsiProvider</code>, it is overridden as shown below and implemented to return the name <code class=\"language-text\">Sample AMSI Provider</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">HRESULT SampleAmsiProvider<span class=\"token operator\">::</span><span class=\"token function\">DisplayName</span><span class=\"token punctuation\">(</span>_Outptr_ LPWSTR <span class=\"token operator\">*</span>displayName<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token operator\">*</span>displayName <span class=\"token operator\">=</span> const_cast<span class=\"token operator\">&lt;</span>LPWSTR<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>L<span class=\"token string\">\"Sample AMSI Provider\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> S_OK<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"overriding-the-closesession-method\" style=\"position:relative;\"><a href=\"#overriding-the-closesession-method\" aria-label=\"overriding the closesession method permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Overriding the CloseSession method</h3>\n<p><code class=\"language-text\">IAntimalwareProvider::CloseSession</code> is defined as a method that closes an AMSI session, but in this sample it only outputs <code class=\"language-text\">Close session</code> to the ETW trace session.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/amsi/nf-amsi-iantimalwareprovider-closesession\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IAntimalwareProvider::CloseSession (amsi.h) - Win32 apps | Microsoft Learn</a></p>\n<p>Presumably, if some kind of resource handling were performed during AMSI scanning, cleanup would need to happen here.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">void</span> SampleAmsiProvider<span class=\"token operator\">::</span><span class=\"token function\">CloseSession</span><span class=\"token punctuation\">(</span>_In_ ULONGLONG session<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Close session\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>session<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"overriding-the-scan-method\" style=\"position:relative;\"><a href=\"#overriding-the-scan-method\" aria-label=\"overriding the scan method permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Overriding the Scan method</h3>\n<p>In this sample, the <code class=\"language-text\">IAntimalwareProvider::Scan</code> method, which scans the content stream, is overridden as follows.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/amsi/nf-amsi-iantimalwareprovider-scan\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IAntimalwareProvider::Scan (amsi.h) - Win32 apps | Microsoft Learn</a></p>\n<p>Although it is called a Scan method, in practice this sample implements it as a method that simply XORs all bytes of the received data and outputs the result as an ETW trace event, returning <code class=\"language-text\">AMSI_RESULT_NOT_DETECTED</code> for every scan request.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">HRESULT SampleAmsiProvider<span class=\"token operator\">::</span><span class=\"token function\">Scan</span><span class=\"token punctuation\">(</span>_In_ IAmsiStream<span class=\"token operator\">*</span> stream<span class=\"token punctuation\">,</span> _Out_ AMSI_RESULT<span class=\"token operator\">*</span> result<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    LONG requestNumber <span class=\"token operator\">=</span> <span class=\"token function\">InterlockedIncrement</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>m_requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Scan Start\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">auto</span> appName <span class=\"token operator\">=</span> <span class=\"token function\">GetStringAttribute</span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_APP_NAME<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">auto</span> contentName <span class=\"token operator\">=</span> <span class=\"token function\">GetStringAttribute</span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_CONTENT_NAME<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">auto</span> contentSize <span class=\"token operator\">=</span> GetFixedSizeAttribute<span class=\"token operator\">&lt;</span>ULONGLONG<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_CONTENT_SIZE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">auto</span> session <span class=\"token operator\">=</span> GetFixedSizeAttribute<span class=\"token operator\">&lt;</span>ULONGLONG<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_SESSION<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">auto</span> contentAddress <span class=\"token operator\">=</span> GetFixedSizeAttribute<span class=\"token operator\">&lt;</span>PBYTE<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_CONTENT_ADDRESS<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Attributes\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingWideString</span><span class=\"token punctuation\">(</span>appName<span class=\"token punctuation\">.</span><span class=\"token function\">Get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"App Name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingWideString</span><span class=\"token punctuation\">(</span>contentName<span class=\"token punctuation\">.</span><span class=\"token function\">Get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Content Name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingUInt64</span><span class=\"token punctuation\">(</span>contentSize<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Content Size\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingUInt64</span><span class=\"token punctuation\">(</span>session<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Session\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingPointer</span><span class=\"token punctuation\">(</span>contentAddress<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Content Address\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>contentAddress<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// The data to scan is provided in the form of a memory buffer.</span>\n        <span class=\"token keyword\">auto</span> result <span class=\"token operator\">=</span> <span class=\"token function\">CalculateBufferXor</span><span class=\"token punctuation\">(</span>contentAddress<span class=\"token punctuation\">,</span> contentSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Memory xor\"</span><span class=\"token punctuation\">,</span>\n            <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">else</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// Provided as a stream. Read it stream a chunk at a time.</span>\n        BYTE cumulativeXor <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n        BYTE chunk<span class=\"token punctuation\">[</span><span class=\"token number\">1024</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n        ULONG readSize<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>ULONGLONG position <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> position <span class=\"token operator\">&lt;</span> contentSize<span class=\"token punctuation\">;</span> position <span class=\"token operator\">+=</span> readSize<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            HRESULT hr <span class=\"token operator\">=</span> stream<span class=\"token operator\">-></span><span class=\"token function\">Read</span><span class=\"token punctuation\">(</span>position<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>chunk<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> chunk<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>readSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">SUCCEEDED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">{</span>\n                cumulativeXor <span class=\"token operator\">^=</span> <span class=\"token function\">CalculateBufferXor</span><span class=\"token punctuation\">(</span>chunk<span class=\"token punctuation\">,</span> readSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Read chunk\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>position<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>readSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>cumulativeXor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n            <span class=\"token keyword\">else</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Read failed\"</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>position<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Scan End\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// AMSI_RESULT_NOT_DETECTED means \"We did not detect a problem but let other providers scan it, too.\"</span>\n    <span class=\"token operator\">*</span>result <span class=\"token operator\">=</span> AMSI_RESULT_NOT_DETECTED<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> S_OK<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>At the start of this method, it safely increments <code class=\"language-text\">m_requestNumber</code> using <code class=\"language-text\">InterlockedIncrement</code>, then outputs a log named <code class=\"language-text\">Scan Start</code>.</p>\n<p><code class=\"language-text\">m_requestNumber</code> is a variable added by the sample provider itself to identify scan requests for logging purposes.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/winnt/nf-winnt-interlockedincrement\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">InterlockedIncrement function (winnt.h) - Win32 apps | Microsoft Learn</a></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">LONG requestNumber <span class=\"token operator\">=</span> <span class=\"token function\">InterlockedIncrement</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>m_requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Scan Start\"</span><span class=\"token punctuation\">,</span> <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the following code, <code class=\"language-text\">GetStringAttribute</code> and <code class=\"language-text\">GetFixedSizeAttribute</code> are used to retrieve various attribute values such as <code class=\"language-text\">AMSI_ATTRIBUTE_APP_NAME</code> from the received stream and output them to the log.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">auto</span> appName <span class=\"token operator\">=</span> <span class=\"token function\">GetStringAttribute</span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_APP_NAME<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">auto</span> contentName <span class=\"token operator\">=</span> <span class=\"token function\">GetStringAttribute</span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_CONTENT_NAME<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">auto</span> contentSize <span class=\"token operator\">=</span> GetFixedSizeAttribute<span class=\"token operator\">&lt;</span>ULONGLONG<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_CONTENT_SIZE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">auto</span> session <span class=\"token operator\">=</span> GetFixedSizeAttribute<span class=\"token operator\">&lt;</span>ULONGLONG<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_SESSION<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">auto</span> contentAddress <span class=\"token operator\">=</span> GetFixedSizeAttribute<span class=\"token operator\">&lt;</span>PBYTE<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>stream<span class=\"token punctuation\">,</span> AMSI_ATTRIBUTE_CONTENT_ADDRESS<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Attributes\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">TraceLoggingWideString</span><span class=\"token punctuation\">(</span>appName<span class=\"token punctuation\">.</span><span class=\"token function\">Get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"App Name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">TraceLoggingWideString</span><span class=\"token punctuation\">(</span>contentName<span class=\"token punctuation\">.</span><span class=\"token function\">Get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Content Name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">TraceLoggingUInt64</span><span class=\"token punctuation\">(</span>contentSize<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Content Size\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">TraceLoggingUInt64</span><span class=\"token punctuation\">(</span>session<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Session\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function\">TraceLoggingPointer</span><span class=\"token punctuation\">(</span>contentAddress<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Content Address\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p><code class=\"language-text\">GetStringAttribute</code> and <code class=\"language-text\">GetFixedSizeAttribute</code> appear to be helper functions that retrieve AMSI scan request metadata by using the <code class=\"language-text\">GetAttribute</code> method of the <code class=\"language-text\">IAmsiStream</code> interface.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/amsi/nf-amsi-iamsistream-getattribute\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IAmsiStream::GetAttribute (amsi.h) - Win32 apps | Microsoft Learn</a></p>\n<p>The <code class=\"language-text\">GetAttribute</code> method of <code class=\"language-text\">IAmsiStream</code> must return the attribute specified by the <code class=\"language-text\">AMSI_ATTRIBUTE</code> value in its first argument.</p>\n<p>First, <code class=\"language-text\">GetStringAttribute</code> is implemented as follows and retrieves values such as <code class=\"language-text\">AMSI_ATTRIBUTE_APP_NAME</code> and <code class=\"language-text\">AMSI_ATTRIBUTE_CONTENT_NAME</code>.</p>\n<p>When the output buffer size it receives is not large enough, <code class=\"language-text\">GetAttribute</code> returns <code class=\"language-text\">E_NOT_SUFFICIENT_BUFFER</code> and the required byte size is returned in <code class=\"language-text\">allocSize</code>, so the function uses that information to call <code class=\"language-text\">GetAttribute</code> again and retrieve the required attribute.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">HeapMemPtr<span class=\"token operator\">&lt;</span><span class=\"token class-name\">wchar_t</span><span class=\"token operator\">></span> <span class=\"token function\">GetStringAttribute</span><span class=\"token punctuation\">(</span>_In_ IAmsiStream<span class=\"token operator\">*</span> stream<span class=\"token punctuation\">,</span> _In_ AMSI_ATTRIBUTE attribute<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    HeapMemPtr<span class=\"token operator\">&lt;</span><span class=\"token class-name\">wchar_t</span><span class=\"token operator\">></span> result<span class=\"token punctuation\">;</span>\n\n    ULONG allocSize<span class=\"token punctuation\">;</span>\n    ULONG actualSize<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>stream<span class=\"token operator\">-></span><span class=\"token function\">GetAttribute</span><span class=\"token punctuation\">(</span>attribute<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> nullptr<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>allocSize<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> E_NOT_SUFFICIENT_BUFFER <span class=\"token operator\">&amp;&amp;</span>\n        <span class=\"token function\">SUCCEEDED</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span><span class=\"token function\">Alloc</span><span class=\"token punctuation\">(</span>allocSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n        <span class=\"token function\">SUCCEEDED</span><span class=\"token punctuation\">(</span>stream<span class=\"token operator\">-></span><span class=\"token function\">GetAttribute</span><span class=\"token punctuation\">(</span>attribute<span class=\"token punctuation\">,</span> allocSize<span class=\"token punctuation\">,</span> reinterpret_cast<span class=\"token operator\">&lt;</span>PBYTE<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">.</span><span class=\"token function\">Get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>actualSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n        actualSize <span class=\"token operator\">&lt;=</span> allocSize<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> result<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> HeapMemPtr<span class=\"token operator\">&lt;</span><span class=\"token class-name\">wchar_t</span><span class=\"token operator\">></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If you issue a memory scan request using the sample client program created in <a href=\"/amsi-create-interface-en\">the previous article</a>, you can confirm that the hard-coded <code class=\"language-text\">Contoso Script Engine v3.4.9999.0</code> is indeed returned as the <code class=\"language-text\">AppName</code>, and that it obtains the address of the scan string <code class=\"language-text\">Hello, World</code>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 877px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6df6c8d9ba64ed571077dd1593c2112f/4b446/image-20250705223137319.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 40%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABc0lEQVQoz3WSWZaCMBBFWYggKAKSAQhhEFRm7f1v6HUlDv3VH++EAye3blXhTNOEYRxRVxW0rnA8Z0hShq7rkGUZMimR5wVCpuD5ATx3B8/z/o2zbRuWZUFFwGEYkbYrkrzBtkx4PJ7o+x7zNEL1sy3m7QPsdjsb14QKuARyXdfGWdcV8zyjrmtcrzekzQLW/+Csb2SWY1x/UFQtmQoIsk14jjAMcTqdEIQR9sGRrN0/ww/QGN7ud8QlhaAGKFUFqS+IothC4jjGKTxaWBS9gB4BX6Zvw0/LZmYGaFrTwxNpVkLS7Dhn0GVpDaXgBE0QniX8/R6B7yMIfBwOh2+coijQNI2dVUkXu0uLC4ULgTMTYEJCZAQuyFbVlIa+SaRpipQxOtnr+R3HwEzLxnKkbZvcydTYDvP2zopuWKAvN1QtFaa/QSllBcxpImm+jAo4nPOvnXn+RFB7qqH31wW5pqVUHXheolTFF6K1tvfM8swOzL1fvTD5BGT2NTgAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/6df6c8d9ba64ed571077dd1593c2112f/8ac56/image-20250705223137319.webp 240w,\n/static/6df6c8d9ba64ed571077dd1593c2112f/d3be9/image-20250705223137319.webp 480w,\n/static/6df6c8d9ba64ed571077dd1593c2112f/d7666/image-20250705223137319.webp 877w\"\n              sizes=\"(max-width: 877px) 100vw, 877px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/6df6c8d9ba64ed571077dd1593c2112f/8ff5a/image-20250705223137319.png 240w,\n/static/6df6c8d9ba64ed571077dd1593c2112f/e85cb/image-20250705223137319.png 480w,\n/static/6df6c8d9ba64ed571077dd1593c2112f/4b446/image-20250705223137319.png 877w\"\n            sizes=\"(max-width: 877px) 100vw, 877px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/6df6c8d9ba64ed571077dd1593c2112f/4b446/image-20250705223137319.png\"\n            alt=\"image-20250705223137319\"\n            title=\"image-20250705223137319\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Meanwhile, <code class=\"language-text\">GetFixedSizeAttribute</code> is implemented as follows.</p>\n<p>This function retrieves <code class=\"language-text\">AMSI_ATTRIBUTE_CONTENT_SIZE</code>, <code class=\"language-text\">AMSI_ATTRIBUTE_SESSION</code>, and <code class=\"language-text\">AMSI_ATTRIBUTE_CONTENT_ADDRESS</code> according to the type specified when it is called.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">template<span class=\"token operator\">&lt;</span>typename T<span class=\"token operator\">></span>\nT <span class=\"token function\">GetFixedSizeAttribute</span><span class=\"token punctuation\">(</span>_In_ IAmsiStream<span class=\"token operator\">*</span> stream<span class=\"token punctuation\">,</span> _In_ AMSI_ATTRIBUTE attribute<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    T result<span class=\"token punctuation\">;</span>\n\n    ULONG actualSize<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">SUCCEEDED</span><span class=\"token punctuation\">(</span>stream<span class=\"token operator\">-></span><span class=\"token function\">GetAttribute</span><span class=\"token punctuation\">(</span>attribute<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>T<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> reinterpret_cast<span class=\"token operator\">&lt;</span>PBYTE<span class=\"token operator\">></span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>actualSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n        actualSize <span class=\"token operator\">==</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>T<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> result<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">T</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>When the attribute <code class=\"language-text\">AMSI_ATTRIBUTE_CONTENT_ADDRESS</code>, which is the memory address used when the content is fully loaded in memory, can be obtained, the sample uses <code class=\"language-text\">CalculateBufferXor</code> to compute the XOR of all bytes in the memory content and outputs the result to the log.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\">BYTE <span class=\"token function\">CalculateBufferXor</span><span class=\"token punctuation\">(</span>_In_ LPCBYTE buffer<span class=\"token punctuation\">,</span> _In_ ULONGLONG size<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    BYTE value <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>ULONGLONG i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> size<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        value <span class=\"token operator\">^=</span> buffer<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> value<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>contentAddress<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// The data to scan is provided in the form of a memory buffer.</span>\n    <span class=\"token keyword\">auto</span> result <span class=\"token operator\">=</span> <span class=\"token function\">CalculateBufferXor</span><span class=\"token punctuation\">(</span>contentAddress<span class=\"token punctuation\">,</span> contentSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Memory xor\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>If the scan target is a file, it uses the <code class=\"language-text\">Read</code> method to obtain the content in 1024-byte chunks and performs the same calculation with <code class=\"language-text\">CalculateBufferXor</code>.</p>\n<p>Reference: <a href=\"https://learn.microsoft.com/ja-jp/windows/win32/api/amsi/nf-amsi-iamsistream-read\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">IAmsiStream::Read (amsi.h) - Win32 apps | Microsoft Learn</a></p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token keyword\">else</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Provided as a stream. Read it stream a chunk at a time.</span>\n    BYTE cumulativeXor <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n    BYTE chunk<span class=\"token punctuation\">[</span><span class=\"token number\">1024</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    ULONG readSize<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>ULONGLONG position <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> position <span class=\"token operator\">&lt;</span> contentSize<span class=\"token punctuation\">;</span> position <span class=\"token operator\">+=</span> readSize<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">{</span>\n        HRESULT hr <span class=\"token operator\">=</span> stream<span class=\"token operator\">-></span><span class=\"token function\">Read</span><span class=\"token punctuation\">(</span>position<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>chunk<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> chunk<span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span>readSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">SUCCEEDED</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">{</span>\n            cumulativeXor <span class=\"token operator\">^=</span> <span class=\"token function\">CalculateBufferXor</span><span class=\"token punctuation\">(</span>chunk<span class=\"token punctuation\">,</span> readSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Read chunk\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>position<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>readSize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>cumulativeXor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">else</span>\n        <span class=\"token punctuation\">{</span>\n            <span class=\"token function\">TraceLoggingWrite</span><span class=\"token punctuation\">(</span>g_traceLoggingProvider<span class=\"token punctuation\">,</span> <span class=\"token string\">\"Read failed\"</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>requestNumber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>position<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                <span class=\"token function\">TraceLoggingValue</span><span class=\"token punctuation\">(</span>hr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>As you can see, the <code class=\"language-text\">Scan</code> method in this sample provider is implemented in a very simple way.</p>\n<h2 id=\"collecting-and-analyzing-etw-trace-logs\" style=\"position:relative;\"><a href=\"#collecting-and-analyzing-etw-trace-logs\" aria-label=\"collecting and analyzing etw trace logs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Collecting and analyzing ETW trace logs</h2>\n<p>This sample provider outputs ETW trace logs with the GUID <code class=\"language-text\">{00604c86-2d25-46d6-b814-cd149bfdf0b3}</code>.</p>\n<p>You can capture ETW trace logs with various tools such as <code class=\"language-text\">logman</code> and <code class=\"language-text\">traceview.exe</code>.</p>\n<p>If you use <code class=\"language-text\">traceview.exe</code>, which is included in the Windows WDK, it is convenient because you can easily browse ETW trace logs in a GUI or save them as ETL files.</p>\n<p>If you have already installed the WDK, you can open <code class=\"language-text\">traceview.exe</code> from a path such as <code class=\"language-text\">C:\\Program Files (x86)\\Windows Kits\\10\\bin\\&lt;version>\\x64\\traceview.exe</code>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 960px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/658b515933d3ba57971f34eb0234f7e8/af975/image-20250705232855416.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 30.83333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA1ElEQVQY04WRgQ6DIAxE/f+PnAgquqBgdAYVvbXdXLZsyUheoECPa8nKsoJzHfquhzElrG2Ehmla4hnT2vce03TDPM8/iTEia+liCAG3aYLWGnmucLnkyAml1JNCuLZXSVzX9YtlWZBSQmathff08jjCaANFgixakIAutOxxXFW1JHLStm1IW5L1Ce/t+/4QDD58CKqXYCGu2XFdW0n4NzLuFZcsgubh5nR4uuS4JofHcfwXfJVMPRSHJPJeMs/smM+ccxiGASM9HuMin8Bw/3jmltwBvcfHCbtVF5AAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n          <source\n              srcset=\"/static/658b515933d3ba57971f34eb0234f7e8/8ac56/image-20250705232855416.webp 240w,\n/static/658b515933d3ba57971f34eb0234f7e8/d3be9/image-20250705232855416.webp 480w,\n/static/658b515933d3ba57971f34eb0234f7e8/e46b2/image-20250705232855416.webp 960w,\n/static/658b515933d3ba57971f34eb0234f7e8/f992d/image-20250705232855416.webp 1440w,\n/static/658b515933d3ba57971f34eb0234f7e8/882b9/image-20250705232855416.webp 1920w,\n/static/658b515933d3ba57971f34eb0234f7e8/e6ef2/image-20250705232855416.webp 2478w\"\n              sizes=\"(max-width: 960px) 100vw, 960px\"\n              type=\"image/webp\"\n            />\n          <source\n            srcset=\"/static/658b515933d3ba57971f34eb0234f7e8/8ff5a/image-20250705232855416.png 240w,\n/static/658b515933d3ba57971f34eb0234f7e8/e85cb/image-20250705232855416.png 480w,\n/static/658b515933d3ba57971f34eb0234f7e8/d9199/image-20250705232855416.png 960w,\n/static/658b515933d3ba57971f34eb0234f7e8/07a9c/image-20250705232855416.png 1440w,\n/static/658b515933d3ba57971f34eb0234f7e8/29114/image-20250705232855416.png 1920w,\n/static/658b515933d3ba57971f34eb0234f7e8/af975/image-20250705232855416.png 2478w\"\n            sizes=\"(max-width: 960px) 100vw, 960px\"\n            type=\"image/png\"\n          />\n          <img\n            class=\"gatsby-resp-image-image\"\n            src=\"/static/658b515933d3ba57971f34eb0234f7e8/d9199/image-20250705232855416.png\"\n            alt=\"image-20250705232855416\"\n            title=\"image-20250705232855416\"\n            loading=\"lazy\"\n            style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n          />\n        </picture>\n  </a>\n    </span></p>\n<p>Also, if you have already saved ETW trace logs as an ETL file by using tools such as <code class=\"language-text\">logman</code> or <code class=\"language-text\">traceview.exe</code>, you can convert them to a text file with the following command using <code class=\"language-text\">netsh</code> and inspect them that way as well.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">netsh trace convert <span class=\"token assign-left variable\">input</span><span class=\"token operator\">=</span>logging.etl <span class=\"token assign-left variable\">output</span><span class=\"token operator\">=</span>decode.txt</code></pre></div>\n<p>Because <code class=\"language-text\">traceview.exe</code> is not well suited to filtering or searching event data, I think decoding the ETL file into a text file is a good approach when you want to analyze specific events in detail.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>This time, I read through the sample code for an AMSI provider.</p>\n<p>I plan to write another article in the future about more detailed behavior, such as debugging it more deeply.</p>","fields":{"slug":"/amsi-create-provider-en","tagSlugs":["/tag/windows/","/tag/anti-virus/","/tag/amsi/","/tag/english/"]},"frontmatter":{"date":"2025-07-05","description":"This post summarizes how a custom AMSI provider handles AMSI scan requests.","tags":["Windows","AntiVirus","AMSI","English"],"title":"Handling AMSI Scan Requests with a Custom Provider","socialImage":{"publicURL":"/static/7d97f9b4da2ce59b79be04b649fd2e36/amsi-create-provider.png"}}}},"pageContext":{"slug":"/amsi-create-provider-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}