<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>文件格式 on CloudLake</title><link>https://cloudlake.eu.org/tags/%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/</link><description>Recent content in 文件格式 on CloudLake</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Tue, 13 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://cloudlake.eu.org/tags/%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/index.xml" rel="self" type="application/rss+xml"/><item><title>拆开 TI-Nspire 的 .tns 看里面</title><link>https://cloudlake.eu.org/p/zehnscope/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://cloudlake.eu.org/p/zehnscope/</guid><description>&lt;img src="https://cloudlake.eu.org/p/zehnscope/cover.jpg" alt="Featured image of post 拆开 TI-Nspire 的 .tns 看里面" /&gt;&lt;p&gt;这台机器上有一个真实的 TI-Nspire 开发环境：OS 3.9.0.463 classic Touchpad、Ndless、从源码构建的 ARM 工具链。&lt;/p&gt;&#10;&lt;p&gt;目录里躺着 &lt;strong&gt;1055 个 &lt;code&gt;.tns&lt;/code&gt; 文件&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;.tns&lt;/code&gt; 不是一个格式。它是一层 &lt;code&gt;PRG\0&lt;/code&gt; 外壳，里面是 &lt;strong&gt;Zehn 容器&lt;/strong&gt;——Ndless 自己的可执行容器格式。而这个格式&lt;strong&gt;没有公开文档&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;这个项目把它读懂了，并且用「&lt;strong&gt;能不能逐字节重建&lt;/strong&gt;」来证明。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="自己解出来的格式"&gt;&lt;a href="#%e8%87%aa%e5%b7%b1%e8%a7%a3%e5%87%ba%e6%9d%a5%e7%9a%84%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;自己解出来的格式&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.tns 文件&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── 装载器桩 0 ~ 0x1EC 字节（常见；也有 0/480/604/616/632 字节的变体）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── Zehn 容器&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── 头 32 字节 8 个小端 u32：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ &amp;#34;Zehn&amp;#34; / version=1 / file_size / reloc_count /&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ flag_count / extra_size / alloc_size / entry_offset&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── 重定位表 reloc_count × 4 字节&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 低 8 位 = 类型，高 24 位 = 偏移&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── 标志表 flag_count × 4 字节（同样的 8/24 位切分）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── 额外数据 extra_size 字节（名字/作者/声明等字符串住在这里）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 代码 剩下的；若首个重定位是 FILE_COMPRESSED 则为 zlib 流&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="两个坑我都先踩了"&gt;&lt;a href="#%e4%b8%a4%e4%b8%aa%e5%9d%91%e6%88%91%e9%83%bd%e5%85%88%e8%b8%a9%e4%ba%86" class="header-anchor"&gt;&lt;/a&gt;两个坑，我都先踩了&#10;&lt;/h2&gt;&lt;h3 id="坑一zehn这个字符串会骗你"&gt;&lt;a href="#%e5%9d%91%e4%b8%80zehn%e8%bf%99%e4%b8%aa%e5%ad%97%e7%ac%a6%e4%b8%b2%e4%bc%9a%e9%aa%97%e4%bd%a0" class="header-anchor"&gt;&lt;/a&gt;坑一：「Zehn」这个字符串会骗你&#10;&lt;/h3&gt;&lt;p&gt;最直接的思路是——搜文件里 &lt;code&gt;Zehn&lt;/code&gt; 这四个字节，从那里开始解。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;但装载器桩里也出现了这个字符串。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;只搜这 4 个字节会找到诱饵。真正的头必须同时满足三个条件：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;version == 1&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;各表长度放得下（不越界）&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;file_size&lt;/code&gt; 确实落在文件范围内&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;光靠一个魔数是不够的。&lt;/strong&gt; 得用那些字段之间的一致性来互相验证。&lt;/p&gt;&#10;&lt;h3 id="坑二能力不等于要求"&gt;&lt;a href="#%e5%9d%91%e4%ba%8c%e8%83%bd%e5%8a%9b%e4%b8%8d%e7%ad%89%e4%ba%8e%e8%a6%81%e6%b1%82" class="header-anchor"&gt;&lt;/a&gt;坑二：「能力」不等于「要求」&#10;&lt;/h3&gt;&lt;p&gt;genzehn 的 &lt;code&gt;--color-support&lt;/code&gt; &lt;strong&gt;默认是 true&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;它的含义是「&lt;strong&gt;支持&lt;/strong&gt; CX/CM 彩屏」，不是「&lt;strong&gt;需要&lt;/strong&gt;彩屏」。&lt;/p&gt;&#10;&lt;p&gt;我一开始理解反了，于是&lt;strong&gt;每一个正常程序都被判成「需要彩屏，所以在这台黑白机上跑不了」&lt;/strong&gt;——一个完全反向的结论，而且看起来非常合理。&lt;/p&gt;&#10;&lt;p&gt;正确判据必须看值为 &lt;strong&gt;0&lt;/strong&gt;：0 才表示&amp;quot;不支持这类机器&amp;quot;。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;这个坑值得单独说：&lt;strong&gt;当一个字段名叫 &lt;code&gt;supports&lt;/code&gt;，人们会下意识把它读成 &lt;code&gt;requires&lt;/code&gt;。&lt;/strong&gt;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="验证逐字节重建"&gt;&lt;a href="#%e9%aa%8c%e8%af%81%e9%80%90%e5%ad%97%e8%8a%82%e9%87%8d%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;验证：逐字节重建&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;rebuild()&lt;/code&gt; 从解析出来的字段把容器&lt;strong&gt;重新拼回去&lt;/strong&gt;，然后和原文件比字节。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ python -m zehnscope --rebuild &amp;#34;E:\QA\nspire-dev&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;11/11 containers rebuilt byte for byte&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ python tests/test_zehn.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ok all 100 containers rebuild identically&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;这比&amp;quot;解析没崩溃&amp;quot;强得多。&lt;/p&gt;&#10;&lt;p&gt;因为偏移、计数、位域切分、字节序、字符串在额外数据里的定位——&lt;strong&gt;任何一处理解错，字节就对不上&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;它一次同时检验所有假设。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h3 id="语料是-1055-个真实文件不是精选样本"&gt;&lt;a href="#%e8%af%ad%e6%96%99%e6%98%af-1055-%e4%b8%aa%e7%9c%9f%e5%ae%9e%e6%96%87%e4%bb%b6%e4%b8%8d%e6%98%af%e7%b2%be%e9%80%89%e6%a0%b7%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;语料是 1055 个真实文件，不是精选样本&#10;&lt;/h3&gt;&lt;p&gt;其中 100 个是真正的 Ndless 程序，955 个只是沿用了 &lt;code&gt;.tns&lt;/code&gt; 扩展名的文档/资源（&lt;code&gt;boot1.img.tns&lt;/code&gt;、Hitori 关卡、Liero 素材……）。&lt;/p&gt;&#10;&lt;p&gt;一个只见过&amp;quot;干净样本&amp;quot;的解析器，证明力弱得多。&lt;strong&gt;跨十年、多个工具链、8 种不同桩的 100 个真实容器&lt;/strong&gt;，才是像样的考验。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="手写一个-deflate-解码器"&gt;&lt;a href="#%e6%89%8b%e5%86%99%e4%b8%80%e4%b8%aa-deflate-%e8%a7%a3%e7%a0%81%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;手写一个 DEFLATE 解码器&#10;&lt;/h2&gt;&lt;p&gt;Zehn 的压缩用 zlib。&lt;/p&gt;&#10;&lt;p&gt;但语料里&lt;strong&gt;没有一个压缩容器&lt;/strong&gt;——光靠真实文件测不到这条路。&lt;/p&gt;&#10;&lt;p&gt;所以自己按格式&lt;strong&gt;造一个&lt;/strong&gt;再读回来。&lt;/p&gt;&#10;&lt;p&gt;解码器是手写的 RFC 1951 + 1950：stored / fixed / dynamic 三种块、LZ77 回引用、Adler-32 校验。&lt;/p&gt;&#10;&lt;p&gt;然后对照系统 zlib，在 &lt;strong&gt;40 组&lt;/strong&gt;样本上比对输出（10 种载荷 × 4 个压缩级别）。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&lt;strong&gt;一个实现自己和自己一致，说明不了什么。两个独立实现一致，才算证据。&lt;/strong&gt;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="一个被窄样本骗过的断言"&gt;&lt;a href="#%e4%b8%80%e4%b8%aa%e8%a2%ab%e7%aa%84%e6%a0%b7%e6%9c%ac%e9%aa%97%e8%bf%87%e7%9a%84%e6%96%ad%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;一个被窄样本骗过的断言&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;tests/test_zehn.py&lt;/code&gt; 打印出来的实测结果：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;桩大小&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;容器数&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;0x1EC (492)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;53&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;17&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;632&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;11&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;480&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;8&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;616&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;6&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;604&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;5&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;strong&gt;17 个容器完全没有桩&lt;/strong&gt;——容器就在文件偏移 0。&lt;/p&gt;&#10;&lt;p&gt;我最初写了一条「所有程序共用一个桩」的断言，在 14 个 &lt;code&gt;samples-tns&lt;/code&gt; 上&lt;strong&gt;全部通过&lt;/strong&gt;，在全语料上&lt;strong&gt;直接失败&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;这正是把断言写在窄样本上会骗人的例子：&lt;strong&gt;样本越小，错误越自信。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="兼容性判定一个被推翻的直觉"&gt;&lt;a href="#%e5%85%bc%e5%ae%b9%e6%80%a7%e5%88%a4%e5%ae%9a%e4%b8%80%e4%b8%aa%e8%a2%ab%e6%8e%a8%e7%bf%bb%e7%9a%84%e7%9b%b4%e8%a7%89" class="header-anchor"&gt;&lt;/a&gt;兼容性判定：一个被推翻的直觉&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;compat.py&lt;/code&gt; 拿程序&lt;strong&gt;自己声明的能力&lt;/strong&gt;和&lt;strong&gt;具体机器&lt;/strong&gt;对判。&lt;/p&gt;&#10;&lt;p&gt;这台机器的约束很紧：classic 非 CX、320×240 黑白、Touchpad、Ndless r2016、64MB。&lt;/p&gt;&#10;&lt;p&gt;原本的直觉解释是：「SDK 是 r2022、设备是 r2016，所以自写的程序被拒载重启」。&lt;/p&gt;&#10;&lt;p&gt;但实测结论是：&lt;strong&gt;这 100 个程序里，没有一个声明 Ndless 版本窗口&lt;/strong&gt;（&lt;code&gt;NDLESS_VERSION_MIN&lt;/code&gt; / &lt;code&gt;REVISION_MIN&lt;/code&gt; 全缺）。&lt;/p&gt;&#10;&lt;p&gt;也就是说 &lt;strong&gt;版本不匹配不会导致装载被拒&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;那条&amp;quot;合理&amp;quot;的解释，直接被数据否掉了。真正的原因得往别处找——&lt;code&gt;ut_read_os_version_index()&lt;/code&gt; 的地址哈希、&lt;code&gt;sc_addrs_ptr&lt;/code&gt; 查表、或者 classic 上看门狗没关。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;这是这个项目最值钱的一条：&lt;strong&gt;一个解释听起来越合理，越要拿数据去撞它。&lt;/strong&gt;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="还能往哪走"&gt;&lt;a href="#%e8%bf%98%e8%83%bd%e5%be%80%e5%93%aa%e8%b5%b0" class="header-anchor"&gt;&lt;/a&gt;还能往哪走&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;容器写入器&lt;/strong&gt;：现在只会重建&lt;strong&gt;已有&lt;/strong&gt;容器。接上 ELF 解析就能把任意 ARM ELF 打包成合法 &lt;code&gt;.tns&lt;/code&gt;——包括 genzehn 那部分（扫 &lt;code&gt;.rel.text&lt;/code&gt;、发 &lt;code&gt;ADD_BASE&lt;/code&gt;/&lt;code&gt;ADD_BASE_GOT&lt;/code&gt;、处理 GOT 回滚）&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;OS 镜像&lt;/strong&gt;：&lt;code&gt;boot1.img.tns&lt;/code&gt; / &lt;code&gt;boot2.img.tns&lt;/code&gt; / &lt;code&gt;diags.img.tns&lt;/code&gt; 不是 Zehn 容器，是 TI 的 OS/引导镜像，格式完全不同&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;syscall 面&lt;/strong&gt;：把容器里的重定位和 &lt;code&gt;syscall-list.h&lt;/code&gt; 的 ID 表关联，就能静态列出每个程序用到的 syscall，再和 r2016 的表做差集——&lt;strong&gt;那才是&amp;quot;为什么重启&amp;quot;的正确问法&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;p style="text-align:center;margin:2.5em 0"&gt;&#13;&#10;&lt;a href="https://cloudlake.eu.org/lab/zehn/" style="display:inline-block;padding:12px 26px;border-radius:8px;background:var(--accent-color);color:var(--accent-color-text);text-decoration:none;font-weight:600"&gt;看 100 个程序的容器报告 →&lt;/a&gt;&#13;&#10;&lt;/p&gt;&#13;&#10;&lt;hr&gt;&#10;&lt;h2 id="技术细节"&gt;&lt;a href="#%e6%8a%80%e6%9c%af%e7%bb%86%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;技术细节&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;文件&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;作用&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;zehnscope/core.py&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;容器解析 + &lt;strong&gt;逐字节重建&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;zehnscope/inflate.py&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;手写 DEFLATE/zlib 解码器&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;zehnscope/__main__.py&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CLI：inspect / &lt;code&gt;--rebuild&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;compat.py&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;能力 vs 机型判定（含&amp;quot;能力≠要求&amp;quot;的说明）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;tests/test_zehn.py&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;18 项断言&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;逆向工程真正的方法论，不是&amp;quot;猜对格式&amp;quot;。&lt;/p&gt;&#10;&lt;p&gt;是&lt;strong&gt;找到一种只有完全理解它才能通过的检验&lt;/strong&gt;，然后不断撞上去。&lt;/p&gt;&#10;&lt;p&gt;逐字节重建就是这样一种检验。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;</description></item></channel></rss>