<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>LLeaves Blog</title>
        <link>https://lleavesg.top//</link>
        <description>LLeaves的小窝</description>
        <lastBuildDate>Sun, 10 May 2026 03:33:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>All rights reserved 2026, LLeaves</copyright>
        <item>
            <title><![CDATA[CVE-2024-31317 Zygote命令注入提权system分析]]></title>
            <link>https://lleavesg.top//article/CVE-2024-31317-Zygote</link>
            <guid>https://lleavesg.top//article/CVE-2024-31317-Zygote</guid>
            <pubDate>Thu, 22 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[编号CVE-2024-31317，该漏洞允许拥有WRITE_SECURE_SETTINGS权限的攻击者（该权限由ADB shell和某些特权应用持有）以任意应用的身份执行任意代码。通过这种方式，攻击者可以读取和写入任何应用的数据，更改大多数系统配置，取消注册或绕过移动设备管理等。这个漏洞的利用不涉及内存的破坏，这意味着它可以在几乎任何运行Android 9或更高版本的设备上不加修改地工作，并且在重启后仍然有效。]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-b519b1aa14584dd5a95f595a7554e786"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-blank notion-block-66497c3a72fe4c8a82e93f94ce4a3d13"> </div><div class="notion-blank notion-block-dd1da8c08c014965858eba8a99e92c90"> </div><div class="notion-table-of-contents notion-gray notion-block-b367c1c3785c4dd2b66bc8d10ac63756"><a href="#cbd205c395c94e9f939b97ecf851ec3b" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x00 漏洞说明</span></a><a href="#b57bda0d0a954578b170d2801bb7e611" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. Zygote</span></a><a href="#ff79bffd5b3f418bb6030ec7f03b7a51" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. 漏洞信息</span></a><a href="#abe4074d84f743e6b7a39359685ec2f4" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x01 漏洞利用</span></a><a href="#ec2e99757d104a1f8d0fb98e67be2c82" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. 攻击场景</span></a><a href="#5a52067f4e874f118ea8d603f388be7d" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. Android11-</span></a><a href="#28f188657b544847bef9c8063b0c9956" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">3. Android12+</span></a><a href="#f9577caa839647ac810d4c2b72fc7a3a" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x02 漏洞修复</span></a><a href="#493ac1bc47db4d58bc694bb95934ef69" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">参考</span></a></div><div class="notion-blank notion-block-531f6d7e310a4eceb9ac5ca690360473"> </div><div class="notion-callout notion-blue_background_co notion-block-4fdee2cb2573407aa3cdb07242987c47"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">参考：<a class="notion-link" href="https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html" target="_blank" rel="noopener noreferrer">https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html</a><div class="notion-text notion-block-2eb341bba2d04ba28e10dc0c5107443e"><a class="notion-link" href="https://mp.weixin.qq.com/s/PoGRFwUD736nkLocRGvP_g" target="_blank" rel="noopener noreferrer">https://mp.weixin.qq.com/s/PoGRFwUD736nkLocRGvP_g</a></div><div class="notion-text notion-block-30fc88f1aa2245158385a8f90afbf6be"><b>特别鸣谢：s1nk</b></div></div></div><div class="notion-blank notion-block-26cccfa0b7e242a19359c9135f52b37c"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-cbd205c395c94e9f939b97ecf851ec3b" data-id="cbd205c395c94e9f939b97ecf851ec3b"><span><div id="cbd205c395c94e9f939b97ecf851ec3b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#cbd205c395c94e9f939b97ecf851ec3b" title="0x00 漏洞说明"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x00 漏洞说明</span></span></h3><div class="notion-text notion-block-9498ac02806a4bce817e7c5be1e008ba">首先回顾CVE-2024-0044漏洞，在Android 12和13中，存在一个安全漏洞，即通过<code class="notion-inline-code"><b>pm install</b></code>命令的<code class="notion-inline-code"><b>-i</b></code>标志设置的安装程序包名没有经过适当的校验和清理。这意味着攻击者可以利用特殊字符（如换行符和空格）来注入恶意数据，从而影响系统文件<code class="notion-inline-code"><b>/data/system/packages.list</b></code>的内容。之后可以通过伪造的条目欺骗<code class="notion-inline-code">run-as</code>从而获得受害应用的权限，可以操作内部目录等。</div><div class="notion-text notion-block-df453efbf17b408d88df724963b36ab0">然而，这种方法需要攻击者能够访问 <code class="notion-inline-code">ADB shell</code>，这通常对攻击者来说是一个很高的门槛。为了降低这个门槛，尝试利用 <code class="notion-inline-code">Zygote</code>进程，因为Zygote是另一个可以更改<code class="notion-inline-code">UID</code>的进程。通过利用 <code class="notion-inline-code">Zygote </code>进程的这一特性，攻击者可以尝试模拟具有更高权限的应用程序，从而更容易地实现他们的目标。</div><div class="notion-text notion-block-ba1f0808277b4118ac767703d0c0aff5">于是就引出了该漏洞（编号<code class="notion-inline-code">CVE-2024-31317</code>），该漏洞允许拥有<code class="notion-inline-code">WRITE_SECURE_SETTINGS</code>权限的攻击者（该权限由ADB shell和某些特权应用持有）以任意应用的身份执行任意代码。通过这种方式，攻击者可以读取和写入任何应用的数据，更改大多数系统配置，取消注册或绕过移动设备管理等。这个漏洞的利用不涉及内存的破坏，这意味着它可以在几乎任何运行Android 9或更高版本的设备上不加修改地工作，并且在重启后仍然有效。</div><div class="notion-text notion-block-344023bd55ad4c978e845fabbdc3eebb"><code class="notion-inline-code"><b>Zygote</b></code><b>是 Android 系统中的一个重要进程，它在系统启动时创建，并负责预加载许多常用的类和资源，以便应用程序可以快速启动。与其他进程不同，Zygote 进程允许更改其用户 ID（UID），这使得它成为潜在的攻击目标。</b></div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-b57bda0d0a954578b170d2801bb7e611" data-id="b57bda0d0a954578b170d2801bb7e611"><span><div id="b57bda0d0a954578b170d2801bb7e611" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b57bda0d0a954578b170d2801bb7e611" title="1. Zygote"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. Zygote</span></span></h4><div class="notion-text notion-block-723b5d0c99854738b37b259e69f972fa"><code class="notion-inline-code">Zygote</code>负责创建应用的主进程并设置该进程的身份。尽管只有<code class="notion-inline-code">system_server</code>可以向Zygote发送命令，但这些命令的源头可以是普通应用，例如启动<code class="notion-inline-code">Activty</code>或是<code class="notion-inline-code">Service</code>等，这些普通的请求可以传递到<code class="notion-inline-code">system_server</code>再传递到<code class="notion-inline-code">Zygote</code>。<b>当</b><code class="notion-inline-code">system_server</code><b>收到一个尚未运行的应用的请求时，它通过告诉Zygote生成一个具有适当包名、数据目录、UID、SELinux域等的进程来启动该应用。</b></div><div class="notion-text notion-block-ccc1fe3baeba41268b2aba165b6e44d5">值得注意的是，系统服务器控制着像新应用UID这样的安全关键参数。<b>Zygote可能因为其在启动序列中处在较早期的时期，并不会从Android包数据库中查询这些参数。</b>这意味着如果我们能控制系统服务器发送的命令，就可以冒充任意应用。</div><div class="notion-text notion-block-584644aaaf8e4f1d98c9acadeec8179f">Zygote作为守护进程运行，并在<code class="notion-inline-code">/dev/socket/zygote</code>的UNIX流套接字上接受命令。<b>流套接字不是面向消息的，因此Zygote的线协议必须定义一个命令结束和下一个命令开始的位置。</b>它的实现非常简单：每个命令是UTF-8文本，<b>由一个十进制数字和相应数量的参数组成，每个参数占一行。最后一个参数后的行开始下一个命令。</b></div><div class="notion-text notion-block-8e6e8625423a40d69fe7ba7fce476843">一个命令仅由一系列参数组成。<b>与大多数命令协议不同，Zygote的协议没有“命令类型”的概念。默认情况下，每个命令都会生成一个新进程，参数指定该进程的详细信息</b>。某些特殊参数会覆盖默认行为，使Zygote执行其他操作。</div><div class="notion-text notion-block-6ec34fc8163747b6857ac0c0c1670ea9">以下是一个典型的进程生成命令的示例（省略了许多参数以简洁）（括号中的文本是解释性的，不是协议的一部分）。然后是一个特殊的<code class="notion-inline-code">set API denylist exemptions</code>命令。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-ff79bffd5b3f418bb6030ec7f03b7a51" data-id="ff79bffd5b3f418bb6030ec7f03b7a51"><span><div id="ff79bffd5b3f418bb6030ec7f03b7a51" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ff79bffd5b3f418bb6030ec7f03b7a51" title="2. 漏洞信息"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. 漏洞信息</span></span></h4><div class="notion-text notion-block-53cf2a567475460987389f6c8db03105">在Android中发现的一个全局设置<code class="notion-inline-code"><a class="notion-link" href="https://developer.android.com/reference/android/provider/Settings.Global" target="_blank" rel="noopener noreferrer">hidden_api_blacklist_exemptions</a></code><a class="notion-link" href="https://developer.android.com/reference/android/provider/Settings.Global" target="_blank" rel="noopener noreferrer"> </a>，其值会直接包含在Zygote命令中。<code class="notion-inline-code">system_server</code>并不期望该设置包含换行符，<b>因此既不会对其进行转义，也不会在命令的参数计数中标注它们。</b>通过向该设置写入恶意值，攻击者可以在最后一个声明的参数之后插入自己选择的行。<b>当Zygote看到这些行时，会将其视为一个单独的命令并执行。</b></div><div class="notion-text notion-block-c4cd351307e7457daff7ecc29f7f93ab">漏洞的代码路径始于系统服务器中的一个<code class="notion-inline-code"><a class="notion-link" href="https://cs.android.com/android/platform/superproject/+/android-14.0.0_r11:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;l=2329-2350" target="_blank" rel="noopener noreferrer">ContentObserver</a></code>回调，当<code class="notion-inline-code">hidden_api_blacklist_exemptions</code>因任何原因发生变化时，该回调会被触发。从下面的代码中可以看出，将该设置的值通过逗号分隔后传入<code class="notion-inline-code">setApiDenylistExemptions</code> ，但是并没有对其他符号进行处理。</div><div class="notion-text notion-block-5fab0135ad1743f2a4636a6188eb6ad1">在<code class="notion-inline-code">setApiDenylistExemptions</code>内部调用了<code class="notion-inline-code">maybeSetApiDenylistExemptions</code> ，其中向 <code class="notion-inline-code">state.mZygoteOutputWriter</code> 写入数据，该变量类型为<code class="notion-inline-code">BufferedWriter</code> ，其缓存区大小为<code class="notion-inline-code"><b>8192</b></code>字节。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-abe4074d84f743e6b7a39359685ec2f4" data-id="abe4074d84f743e6b7a39359685ec2f4"><span><div id="abe4074d84f743e6b7a39359685ec2f4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#abe4074d84f743e6b7a39359685ec2f4" title="0x01 漏洞利用"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x01 漏洞利用</span></span></h3><div class="notion-blank notion-block-4e2d2b77d76248069f25310ca23b88b7"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-ec2e99757d104a1f8d0fb98e67be2c82" data-id="ec2e99757d104a1f8d0fb98e67be2c82"><span><div id="ec2e99757d104a1f8d0fb98e67be2c82" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ec2e99757d104a1f8d0fb98e67be2c82" title="1. 攻击场景"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. 攻击场景</span></span></h4><div class="notion-text notion-block-ffe479522a694d7782b9e221866a9b2f"><b>原文提供三种攻击场景</b></div><div class="notion-text notion-block-3a88539c4018453ba62697cc2decfb48"><b>场景 1：权限提升</b></div><div class="notion-text notion-block-3219fe19853346f789ac94ac4f4f2a98">任何具有 <code class="notion-inline-code">android.permission.WRITE_SECURE_SETTINGS</code> 权限的应用程序都可以写入 <code class="notion-inline-code">hidden_api_blacklist_exemptions</code> 并触发漏洞。虽然 Android 将该权限的保护级别声明为 <code class="notion-inline-code">signature|privileged|development|role|installer</code>，这意味着非特权应用无法请求该权限，但某些预装应用持有该权限。如果攻击者能够入侵这些预装应用之一，就可以利用这个漏洞进一步提升权限。</div><div class="notion-text notion-block-aec45c7970d4402e9782475021d4ca9d"><b>场景 2：ADB Shell</b></div><div class="notion-text notion-block-8656b76aab80422daab0d97d587c5f75">ADB shell 也可以读取和写入设置；它甚至有一个 <code class="notion-inline-code">settings</code> 命令来简化这一操作。拥有物理访问权限的攻击者可以通过解锁设备来触发漏洞，或者用户可以在自己拥有的设备上绕过系统策略（例如 MDM 限制）来触发漏洞。</div><div class="notion-text notion-block-a32066b8438c46e8bb51d7d475d93ff9"><b>场景 3：签名配置</b></div><div class="notion-text notion-block-09aebef94c4644bfa15fbc26ef4b6995">还有一种设置 <code class="notion-inline-code">hidden_api_blacklist_exemptions</code> 的方法，这也是它存在的原因：任何应用（即使是即时应用）都可以在其清单中包含一对特殊的 <code class="notion-inline-code">&lt;meta-data&gt;</code> 标签，其中包含：</div><ol start="1" class="notion-list notion-list-numbered notion-block-0552f6d9aa4741c4ab197c8d21818b82" style="list-style-type:decimal"><li>要存储在 <code class="notion-inline-code">hidden_api_blacklist_exemptions</code> 中的 Base64 编码值；</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-531026f3ad934f5c8a340f5075223459" style="list-style-type:decimal"><li>由硬编码的 Google 控制密钥对该值进行的 ECDSA 签名。</li></ol><div class="notion-text notion-block-f7a2a29423f048538eee7aa9f114fdd2">如果安装了这样的应用并且签名有效，Android 会立即应用该设置值，可能会触发漏洞。<b>我们认为签名验证和周围的逻辑是正确实现的，因此可能只有 Google 自己能够通过这种方式利用设备</b>。然而，大多数 Android 设备不是 Google 的一方设备，这个漏洞可能会使 Google 对这些设备的访问权限比 OEM 和用户预期的更大。值得注意的是，CTS 要求接受 Google 签名的元数据，这意味着即使 OEM 想要移除这种利用路径也无法做到。</div><div class="notion-blank notion-block-0c2f87a871664277842a7f78c1515e7b"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-5a52067f4e874f118ea8d603f388be7d" data-id="5a52067f4e874f118ea8d603f388be7d"><span><div id="5a52067f4e874f118ea8d603f388be7d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5a52067f4e874f118ea8d603f388be7d" title="2. Android11-"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. Android11-</span></span></h4><div class="notion-text notion-block-52d3ad9dee884aa2be81732fe1c34dea"><b>在Android 11及以下版本中，利用漏洞的过程相对简单。</b>假设在<code class="notion-inline-code">shell</code>用户下进行利用，只需要通过<code class="notion-inline-code">settings</code>命令设置属性即可，其中<code class="notion-inline-code">payload.txt</code> 是上传到<code class="notion-inline-code">/data/local/tmp</code> 中的文本。</div><div class="notion-text notion-block-345d095d42fd41bb8de6712985b26673">其中<code class="notion-inline-code">payload.txt</code>的内容解释为：其开始有5个换行，之后的8代表后续有8个参数，关键是<code class="notion-inline-code">--invoke-with</code> 后面跟着需要执行的命令，并且注意到在结束有<code class="notion-inline-code">#</code> 符号，用于注释掉后续的命令，后面分析这部分内容的解析时会提到。（为了便于测试，后面的命令执行内容可以替换为<code class="notion-inline-code">/system/bin/logwrapper echo zYg0te $(id)</code> 然后通过<code class="notion-inline-code">logcat</code>即可知道是否利用成功）</div><div class="notion-text notion-block-ae4bb03d20944e7f92ed9f8e0a22141e">当这部分内容通过<code class="notion-inline-code">settings</code>设置后会被<code class="notion-inline-code">setApiDenylistExemptions</code> 解析为五部分</div><div class="notion-text notion-block-436e216ecb1d43c2bea0e708cfff52fc">并且进一步在头部添加两个字段 ，分别是参数数量<code class="notion-inline-code">6</code>和<code class="notion-inline-code">--set-api-denylist-exemptions</code>传入<code class="notion-inline-code">zygote</code>的<code class="notion-inline-code">socket</code>中，最终传入到zygote socket中的数据其实是，而其中的换行符会被<code class="notion-inline-code">zygote</code>直接忽略，所以造成了命令注入。设置后需要打开任意App以触发<code class="notion-inline-code">zygote</code>的读取解析操作，从而执行注入的命令。在注入之后打开任何App都会失败，只需要重新设置<code class="notion-inline-code">hidden_api_blacklist_exemptions</code> 为<code class="notion-inline-code">null</code> 即可</div><blockquote class="notion-quote notion-block-1737ad0d358e4e99a477060c93cf8c15"><div>以及为什么最后一个<code class="notion-inline-code">entry</code>不是空的：<b>Note that the last delay entry isn’t empty like the rest. That’s to work around the fact that Java’s </b><code class="notion-inline-code"><b>String.split()</b></code><b> function, used by System Server to parse the setting value, </b><b><a class="notion-link" href="https://developer.android.com/reference/java/lang/String#split(java.lang.String)" target="_blank" rel="noopener noreferrer">discards trailing empty strings</a></b><b>.</b></div></blockquote><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-83eaf7f9c8b347059a89c1b599673adc"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F3419f678-6d78-4b52-a8d7-749db6f2af6d%2FUntitled.png?table=block&amp;id=83eaf7f9-c8b3-4705-9a89-c1b599673adc&amp;t=83eaf7f9-c8b3-4705-9a89-c1b599673adc&amp;width=827&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-b8cf9f44dedf4d52b3d8eab2c455444b">然后分析<code class="notion-inline-code">--invoke-with</code> 的解析部分可以发现其实就是拼接了一些命令来创建新的进程，如果使用井号注释即可避免后面命令的执行，以避免异常情况的产生。</div><div class="notion-text notion-block-227cb7033e574755b263a8b4cf475e21">同理也可以伪造蓝牙用户，读取其中的数据文件</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-a77f0d79555b4e79a3a1db5351bf4c85"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F2fcdc57f-74c7-493d-ba14-097ce1ba39d9%2FUntitled.png?table=block&amp;id=a77f0d79-555b-4e79-a3a1-db5351bf4c85&amp;t=a77f0d79-555b-4e79-a3a1-db5351bf4c85&amp;width=827&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-ebdf14898c87432aa2765a0a2753af0a"> </div><div class="notion-text notion-block-55dc8cbd6a76475a8d9ab1c30eda7575"><b>反弹shell</b></div><div class="notion-text notion-block-953228003722492ca3c4b6ab4cd78c64">在反弹shell这里遇到了一些问题，在常规情况下可以使用管道的方式去实现安卓环境下的反弹shell，但是很不幸，由于<code class="notion-inline-code">SELinux</code>的限制无法创建管道<code class="notion-inline-code">pipe</code>文件。除此之外还尝试直接写入可执行文件执行，但是也被SELinux拒绝了，因为system写入文件时写入的对象是<code class="notion-inline-code">system_file</code> 类型，不具备执行权限。直到京东<code class="notion-inline-code">flanker</code>发了<b><a class="notion-link" href="https://mp.weixin.qq.com/s/PoGRFwUD736nkLocRGvP_g" target="_blank" rel="noopener noreferrer">公众号文章</a></b>后发现还是大佬玩的骚，直接装一个新的App，在新App的lib目录中放置一个可执行的二进制文件，在安装时会释放到<code class="notion-inline-code">/data/app/xxx/xxx/lib/arm64</code>目录下，此时这个可执行文件的对象类型是<code class="notion-inline-code">apk_data_file</code> 可以被执行，<code class="notion-inline-code">system</code>用户可直接访问这个目录下的内容并且执行，从而实现反弹<code class="notion-inline-code">shell</code></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3a4eda4cda48d1b0c6830ba913a45c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fd26fa801-40d8-41b8-90c5-19a5c75cc798%2Fimage.png?table=block&amp;id=2a3a4eda-4cda-48d1-b0c6-830ba913a45c&amp;t=2a3a4eda-4cda-48d1-b0c6-830ba913a45c&amp;width=708&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-8c7bec6b6bd94da9897dbef0e99e834e"><b>还有很多骚操作可以看flanker大佬的公众号文章，这里不再赘述。</b></div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-28f188657b544847bef9c8063b0c9956" data-id="28f188657b544847bef9c8063b0c9956"><span><div id="28f188657b544847bef9c8063b0c9956" class="notion-header-anchor"></div><a class="notion-hash-link" href="#28f188657b544847bef9c8063b0c9956" title="3. Android12+"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3. Android12+</span></span></h4><div class="notion-text notion-block-d3fb21b986894ea7b400c7f1ac3644ce"><b>下面的内容翻译自原文</b></div><div class="notion-text notion-block-6c03340e7e3c43ae878e60cc98d68a60">然而，在Android 12中，Google增强了Zygote的Java命令解析器，增加了一个快速路径的C++解析器，并通过一个新的类<code class="notion-inline-code"><a class="notion-link" href="https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp;l=141?q=Unreasonable%20argument%20&amp;sq=&amp;ss=android%2Fplatform%2Fsuperproject%2Fmain&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">NativeCommandBuffer</a></code>从套接字读取数据，使得这个漏洞更难利用，不是因为其架构，而是因为一个bug。<code class="notion-inline-code"><a class="notion-link" href="https://cs.android.com/android/platform/superproject/+/android-14.0.0_r11:frameworks/base/core/jni/com_android_internal_os_ZygoteCommandBuffer.cpp;l=52-288" target="_blank" rel="noopener noreferrer">readLine</a></code><code class="notion-inline-code">()</code>方法从套接字读取字节，将字节填充到本地缓冲区，然后从缓冲区中提取行，并在必要时重新填充缓冲区。<b>但在解析完所有命令行后，Zygote会丢弃缓冲区中剩余的字节，并从套接字读取下一个命令。</b>这种行为导致了三个问题：</div><ol start="1" class="notion-list notion-list-numbered notion-block-cabbb1366fea47299645988b756933f3" style="list-style-type:decimal"><li>如果客户端连续写入两个命令，而Zygote还没来得及读取，Zygote会忽略第二个命令。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-6358b4c668be470f8e3f8b88c71fa7a0" style="list-style-type:decimal"><li>如果客户端写入一个半命令（例如，因为第二个命令需要多次write调用），Zygote会忽略第二个命令的开始部分，并将其结尾部分解析为新的命令，这本身就是一个安全漏洞。<b>然而，系统服务器（Zygote的唯一客户端）从不一次写入多个命令，因此这种情况（以及前一种情况）在实践中不会发生。</b></li></ol><div class="notion-text notion-block-d6d614253ee7413bb98e46bd3b71a163">尽管有这个障碍，我们仍然可以在Android 12+上利用这个漏洞！我们需要的是一种方法来避免我们的恶意命令被Zygote的第一次<code class="notion-inline-code">read</code>调用读取。<b>我们最初尝试通过延长payload来超过Zygote传递给read的缓冲区长度限制，但不幸的是，完全填满其缓冲区（在Android 13中扩展到</b><code class="notion-inline-code"><b>32768</b></code><b>字节），Zygote会中止。</b></div><div class="notion-text notion-block-e353c24c57e445aca7dc7d5e597a3b85"><b>因此，我们只能寻找时机：我们可以假设Zygote大部分时间都被阻塞在read，这意味着我们进行的任何写入都可能触发一个立即的短读取，即使我们在第一次</b><code class="notion-inline-code"><b>read</b></code><b>不久后就进行另一次写入。</b></div><ul class="notion-list notion-list-disc notion-block-619d41fd80ed494ba2024eed0da9d241"><li><b>BufferedWriter</b>：<code class="notion-inline-code">maybeSetApiDenylistExemptions()</code> 方法多次调用 <code class="notion-inline-code">state.mZygoteOutputWriter.write()</code>。<code class="notion-inline-code">mZygoteOutputWriter</code> 是一个 <code class="notion-inline-code">BufferedWriter</code>，它在写入到底层传输之前会在内部缓冲区中聚合写入操作。</li></ul><ul class="notion-list notion-list-disc notion-block-8387def5524649a5a0cfe2d7b2c58f12"><li><b>缓冲区大小</b>：<code class="notion-inline-code">BufferedWriter</code> 的缓冲区大小为<b> 8192 字节，比 Zygote 的缓冲区小。这提供了一种方法，可以在两次套接字写入之间产生适当的延迟。</b></li></ul><div class="notion-text notion-block-80d821ac889444aabc6e098f5b502b02"><b>所以原文给出的解决方案是：</b></div><ol start="1" class="notion-list notion-list-numbered notion-block-4106db9b489646a2a3666b85744d6dd5" style="list-style-type:decimal"><li>通过将 System Server 的命令填充到正好 8192 字节，然后插入恶意命令，强制 <code class="notion-inline-code">BufferedWriter</code> 先写入这 8192 字节。Zygote 会忽略填充部分，但不会忽略新到达的恶意命令，因为它会在一个单独的 <code class="notion-inline-code">read()</code> 调用中到达。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-32d19348a80d4eb19b6b77df5070d1dc" style="list-style-type:decimal"><li><b>增加延迟</b>：在设置值的末尾插入大量逗号，使 <code class="notion-inline-code">maybeSetApiDenylistExemptions()</code> 在第一次写入后但在第二次写入前花费时间循环。这些逗号还增加了合法命令的参数数量，但只要确保前 8192 字节包含足够多的换行符号。</li></ol><div class="notion-text notion-block-bd6057828e9b4fa78ca9e87b51194687"><code class="notion-inline-code">Payload</code>如下，需要将执行结果设置为<code class="notion-inline-code">hidden_api_blacklist_exemptions</code></div><div class="notion-text notion-block-2ea7403606084bc2bba2eb5c218a7e7f">经过反复实验发现确实如文中所提到的，必须首先填满8192字节的<code class="notion-inline-code">mZygoteOutputWriter</code> ，然后等待<code class="notion-inline-code">flush</code> 再次写入，这个过程中需要填充大量逗号（需要添加等量的换行符）来使其在<code class="notion-inline-code">maybeSetApiDenylistExemptions</code>中间的循环过程中耗费时间，从而使得<code class="notion-inline-code">Zygote</code>读取端在这个过程中完成了之前写入的8192字节内容的读取，此时<code class="notion-inline-code">read</code>阻塞，等待下一次的输入。</div><div class="notion-text notion-block-3661f0494d954722878c02922a1a746a">下一次的读取从构造好的恶意参数开始，即第一个字节就是恶意命令参数的数目</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-70b785773034493f88209444dd358d36"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fe51bfcda-b6e4-45bd-9ba0-b6aff61f3d1e%2FUntitled.png?table=block&amp;id=70b78577-3034-493f-8820-9444dd358d36&amp;t=70b78577-3034-493f-8820-9444dd358d36&amp;width=827&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-58bb8c72b0f04a718a4495c0874eb113"> </div><div class="notion-text notion-block-89e5dad2c58044b18283cbbc5732c36a">这里还有一个<code class="notion-inline-code"><b>payload</b></code><b>维持</b>的问题，直接粘贴原文，意思就是使注入的命令参数数目超过在<code class="notion-inline-code">scoket</code>中末尾写入的换行数量，强制<code class="notion-inline-code"><b>Zygote</b></code> 解析额外的东西，以一直保持恶意命令的注入并且不影响设备正常运行，但是在原文提出的概念POC中并没有关于这部分的说明。但是我试了很多改法（比如下面的这种改法），都没成功维持，但是由于不会导致设备<code class="notion-inline-code">crash</code>并且能够成功利用，所以暂且搁置。</div><blockquote class="notion-quote notion-block-2448258a2d2f44069bc88d769f5f6aff"><div>A successful exploit degrades or prevents subsequent process launches until a reboot. That’s because the injected Zygote command outputs extra result bytes that System Server doesn’t consume. System Server uses a single connection to Zygote for all non-<a class="notion-link" href="https://cs.android.com/android/platform/superproject/+/android-14.0.0_r11:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp;l=2109-2117" target="_blank" rel="noopener noreferrer">USAP</a> commands, so those bytes stick around until it tries to spawn another process, at which point it reads them instead of that process’s PID. System Server <a class="notion-link" href="https://cs.android.com/android/platform/superproject/+/android-14.0.0_r11:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;l=4496-4498" target="_blank" rel="noopener noreferrer">won’t bind a process</a> without record of its PID, and processes that fail to bind get killed.</div><div class="notion-text notion-block-9ff5d68e37ba4270b1a874e86549c374">We avoided this issue on Android 12+ by slightly modifying our exploit: <b>we declared an argument count for our injected command that exceeded the number of newlines in our final socket write, which forced Zygote to perform an additional socket read while parsing it.</b> That read ate whatever command happened to follow ours (overwhelmingly likely to be a process spawn) and prevented Zygote from executing it. Our malicious command in effect replaced that legitimate command, and System Server consumed its PID (actually our PID) as normal, allowing subsequent PIDs to remain in sync.</div><div class="notion-text notion-block-e9523ef7467a4a8998fa3f6e6ed5f6cc"><b>This modification also made persistence feasible, as the setting can retain its malicious value across reboots without disrupting the boot process.</b></div></blockquote><div class="notion-blank notion-block-711e7fa9c45445bf8edb7f95949504b6"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-f9577caa839647ac810d4c2b72fc7a3a" data-id="f9577caa839647ac810d4c2b72fc7a3a"><span><div id="f9577caa839647ac810d4c2b72fc7a3a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f9577caa839647ac810d4c2b72fc7a3a" title="0x02 漏洞修复"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x02 漏洞修复</span></span></h3><div class="notion-text notion-block-1e63b952e85e494d841f62cae48fc12f">直接改了<code class="notion-inline-code">HiddenApiSettings.update()</code> 添加了对非法字符的过滤，除此之外还添加了在处理进程启动时的非法字符<code class="notion-inline-code">null</code> 过滤。</div><blockquote class="notion-quote notion-block-252030f50c3549a382cf3463076f0af5"><div>Refuse to deal with newlines and null characters in <code class="notion-inline-code">HiddenApiSettings.update()</code>. Also <b>disallow nulls in process start arguments.</b></div></blockquote><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-e6344c1a81be4cd7948925fa1945aecb"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fb138bc33-ee6b-43a8-b378-2c48a33b6b80%2FUntitled.png?table=block&amp;id=e6344c1a-81be-4cd7-9489-25fa1945aecb&amp;t=e6344c1a-81be-4cd7-9489-25fa1945aecb&amp;width=708&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-941df74bf6d649b39ea1fc090fddf056"> </div><div class="notion-text notion-block-552b643f04e446c5bdbe70284cfee381">但是同样的，漏洞发现者认为着治标不治本，给出了建议</div><blockquote class="notion-quote notion-block-6081bfdcf07246c6b4206c209f2aa826"><div>Today’s patch does not address the architectural weaknesses we identified,<b> like Zygote’s use of a hand-rolled stream protocol or ZygoteProcess’s lack of a reusable function to safely serialize commands</b>, as those entail bigger changes and are not directly exploitable. Google has has communicated that they’re considering such changes going forwards, though.</div></blockquote><div class="notion-blank notion-block-a6936b95e3c243148953d73e09a9abff"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-493ac1bc47db4d58bc694bb95934ef69" data-id="493ac1bc47db4d58bc694bb95934ef69"><span><div id="493ac1bc47db4d58bc694bb95934ef69" class="notion-header-anchor"></div><a class="notion-hash-link" href="#493ac1bc47db4d58bc694bb95934ef69" title="参考"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">参考</span></span></h3><ol start="1" class="notion-list notion-list-numbered notion-block-38e9274a421b49d68b210b9840961f57" style="list-style-type:decimal"><li><a class="notion-link" href="https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html" target="_blank" rel="noopener noreferrer">https://rtx.meta.security/exploitation/2024/06/03/Android-Zygote-injection.html</a></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-26340f416fd3428e9392ceaae3a4e569" style="list-style-type:decimal"><li><a class="notion-link" href="https://mp.weixin.qq.com/s/PoGRFwUD736nkLocRGvP_g" target="_blank" rel="noopener noreferrer">https://mp.weixin.qq.com/s/PoGRFwUD736nkLocRGvP_g</a></li></ol><div class="notion-blank notion-block-955da3d391084b8dab42c957edfb5361"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android Data Encryption-从百草园Patch到三味书屋]]></title>
            <link>https://lleavesg.top//article/Android-Data-Encryption</link>
            <guid>https://lleavesg.top//article/Android-Data-Encryption</guid>
            <pubDate>Wed, 10 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Android Data Encryption完整攻击复现]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-630118b3e7604632a0b9f86e1b9a5cc7"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-blank notion-block-61a51029703648daa0c33de96e8f4ca4"> </div><div class="notion-table-of-contents notion-gray notion-block-31f703b6d95b43d6b8adf805dfd23898"><a href="#261295dd6407447b955cefc002659806" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x01 文件级加密FBE(File-Based Encryption)</span></a><a href="#d88eb14868d94d66b36bf313606fb8e0" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. 概念</span></a><a href="#42864838c55f48bd8b6da3aa4b65cc4b" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. 应用处理</span></a><a href="#154f8e71e0194f15a8cddcf54f89b34d" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">3.更新处理</span></a><a href="#37181873832e4d8cabc01977a43329c3" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">4. 存储类别和密钥存储</span></a><a href="#36cf9c14bda74600a1aa398d7b42286b" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x02 TrustZone与CE密钥的派生</span></a><a href="#2fd787c534664dfd8b8787e4c963ee7f" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. TrustZone </span></a><a href="#3fc8541de26f42a5815d652b756fba87" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. CE密钥派生流程</span></a><a href="#ecfef598af144531b33c8f41f7b42bbc" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#身份验证</span></a><a href="#2bc638d245924907a3764e3d61257015" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#CE密钥派生完整流程和相关文件</span></a><a href="#9969db6551c24f78b0adca5fafac992a" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#使用 Gatekeeper 进行身份验证</span></a><a href="#ebf5f68884f943a398cd6e970dc1b4e6" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#合成密码Synthetic Password</span></a><a href="#1747a956e8b94c1c95fd50570872e67c" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x03 漏洞利用</span></a><a href="#8dbf1135a60e47cf880672cad44e4144" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. 设备</span></a><a href="#ba362080bbdd46b1abceed33c5efce81" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. 利用过程</span></a><a href="#1e62800fd3144ba38db49e22c7af6a28" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">3. Patch PreLoader</span></a><a href="#2c4ecfd9f6654e1e86d882503c0e720f" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">4. Patching LK</span></a><a href="#7c8626689f42441ab9f9facad00c54ae" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">5. Patching TEEGRIS</span></a><a href="#ab6244e5dcd24e51a35e4a65fd6f61f6" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#TEEGRIS以及修补方案概述</span></a><a href="#9652fbe196ad43228ab896d6bdbb6eaa" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#Trust Applet(TA)修补</span></a><a href="#77eacf638de54e189701af0120d439dc" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#TrustZone ARchive(TZAR)修补</span></a><a href="#2d1e5bf711754b9d872d1c4ec599a9af" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#Trusted execution environment1 (tee1)修补</span></a><a href="#639e41fe893b41f892daaeea0c6b0a1f" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">6. Patching Gatekeeper</span></a><a href="#71c6f556d8594d868cc55a95ff78f355" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">7. Patch Android boot</span></a><a href="#f57b75bb7bf640b2ac7bc1b2794a8f67" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#Magisk boot设备外修补</span></a><a href="#c672720b7eda40bf82184038bca2f0a0" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#开机自启adb shell</span></a><a href="#3ce6ceb55774480d9f9ad73da1cba32e" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#默认允许root权限授权</span></a><a href="#85aea5a9fc2942e79fdc9182c9bda3c0" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:48px">#TA的动态挂载</span></a><a href="#e9fe5e422b3d4a0a912ed00fd273af91" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">8. 利用脚本和结果</span></a><a href="#baf62f2ffffd47f6b765fb5e726c8262" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">0x0X 参考</span></a></div><div class="notion-blank notion-block-ceba9228ef874c01904ca451200c17be"> </div><div class="notion-callout notion-blue_background_co notion-block-5a3005eb57d84812ab6a0ccdd4ddc883"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><b>本文的完整思路来源与</b><code class="notion-inline-code"><b>Quarkslab</b></code><b>的文章及其汇报，再次表达对</b><b><a class="notion-link" href="http://twitter.com/DamianoMelotti" target="_blank" rel="noopener noreferrer">http://twitter.com/DamianoMelotti</a></b><b> 和 </b><b><a class="notion-link" href="http://twitter.com/max_r_b" target="_blank" rel="noopener noreferrer">http://twitter.com/max_r_b</a></b><b>出色工作的感谢！博客可能存在错误，恳请大佬们留言指正，以防误人子弟。</b><div class="notion-blank notion-block-2843fb9e943280188fa9c7d587385f42"> </div><div class="notion-text notion-block-e69b5eda318e4426aa36bcb39a10c4f4"><b>The complete source of ideas for this article is extremely reported with Quarkslab&#x27;s article, expressing once again the interest in </b><b><a class="notion-link" href="http://twitter.com/DamianoMelotti" target="_blank" rel="noopener noreferrer">http://twitter.com/DamianoMelotti</a></b><b> and </b><b><a class="notion-link" href="http://twitter.com/max_r_b" target="_blank" rel="noopener noreferrer">http://twitter.com/max_r_b</a></b></div><ul class="notion-list notion-list-disc notion-block-02fc97d2555a4a7c9b54d338ab98c4f3"><li><a class="notion-link" href="https://blog.quarkslab.com/android-data-encryption-in-depth.html" target="_blank" rel="noopener noreferrer">https://blog.quarkslab.com/android-data-encryption-in-depth.html</a></li></ul><ul class="notion-list notion-list-disc notion-block-1677e121e05a473ea7e9e2d02be2d93a"><li><a class="notion-link" href="https://hardwear.io/netherlands-2023/presentation/dissecting-the-modern-android-data-encryption-scheme.pdf" target="_blank" rel="noopener noreferrer">https://hardwear.io/netherlands-2023/presentation/dissecting-the-modern-android-data-encryption-scheme.pdf</a></li></ul></div></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-261295dd6407447b955cefc002659806" data-id="261295dd6407447b955cefc002659806"><span><div id="261295dd6407447b955cefc002659806" class="notion-header-anchor"></div><a class="notion-hash-link" href="#261295dd6407447b955cefc002659806" title="0x01 文件级加密FBE(File-Based Encryption)"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x01 文件级加密FBE(File-Based Encryption)</span></span></h2><div class="notion-blank notion-block-d5a3fac4d53f447ca89e79bb356afce9"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-d88eb14868d94d66b36bf313606fb8e0" data-id="d88eb14868d94d66b36bf313606fb8e0"><span><div id="d88eb14868d94d66b36bf313606fb8e0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d88eb14868d94d66b36bf313606fb8e0" title="1. 概念"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. 概念</span></span></h3><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3645e181932c47f58f039e7b76fdb51b"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F21d1614b-2809-4989-bdfe-abaf5852527e%2FUntitled.png?table=block&amp;id=3645e181-932c-47f5-8f03-9e7b76fdb51b&amp;t=3645e181-932c-47f5-8f03-9e7b76fdb51b&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-45b6d138efc3489c9d2920a16af932a5">在设备重启后且并未输入密码解锁设备时文件时加密的，<code class="notion-inline-code">ls -al /data/data</code> 能够发现文件夹名称均为加密的并且文件不可读取。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-90d554e9356144f99a8e6e4c12d0be0a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff7dfbebf-f6fd-4a3c-97c5-b1efcbefa6bf%2FUntitled.png?table=block&amp;id=90d554e9-3561-44f9-9a8e-6e4c12d0be0a&amp;t=90d554e9-3561-44f9-9a8e-6e4c12d0be0a&amp;width=2753&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-30bb9ee6210745d69d8f159ecb4944cc"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fabead055-e523-4bac-b6ec-603eb3857f10%2FUntitled.png?table=block&amp;id=30bb9ee6-2107-45d6-9d8f-159ecb4944cc&amp;t=30bb9ee6-2107-45d6-9d8f-159ecb4944cc&amp;width=2531&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-callout notion-blue_background_co notion-block-2cc103597f1d45e2bc3ff1e61f4e0c56"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">为了安全地使用 AOSP 的 FBE 实现，设备需要满足以下依赖关系：<ul class="notion-list notion-list-disc notion-block-b59597fadaad4887bf51b5fd864099cd"><li>对 Ext4 加密或 F2FS 加密的<b>内核支持</b>。</li></ul><ul class="notion-list notion-list-disc notion-block-af84f6867bf74932913892c70b4f8258"><li>基于 1.0 或更高版本 HAL 的 <b><a class="notion-link" href="https://source.android.google.cn/docs/security/features/keystore?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">Keymaster 支持</a></b>。不支持 Keymaster 0.3，因为它既不提供必要的功能，也不能保证为加密密钥提供充分保护。</li></ul><ul class="notion-list notion-list-disc notion-block-3d1b412064c648a7a9e9cc536a89197f"><li><b>必须在</b><b><a class="notion-link" href="https://source.android.google.cn/docs/security/features/trusty?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">可信执行环境</a></b><b> (TEE) 中实现 Keymaster/</b><b><a class="notion-link" href="https://source.android.google.cn/docs/security/features/keystore?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">Keystore</a></b><b> 和 Gatekeeper，以便为 DE 密钥提供保护，从而使未经授权的操作系统（刷写到设备上的定制操作系统）无法直接请求 DE 密钥。</b></li></ul><ul class="notion-list notion-list-disc notion-block-08eafb00cbb94c578eda2ccfd202053d"><li><b>硬件信任根</b>和<b>启动时验证</b>需要绑定到 Keymaster 初始化进程，以确保未经授权的操作系统无法获取 DE 密钥。</li></ul></div></div><div class="notion-text notion-block-5a1378a9beee4bc3890240b3ca2c7a9a">凭据加密（Credential Encrypted, CE）存储空间和设备加密（Device Encrypted, DE）存储空间是Android设备上用于保护用户数据安全的两种加密存储方式。它们的主要区别在于数据可访问性的时机：</div><ol start="1" class="notion-list notion-list-numbered notion-block-e72851a4386340e58ab14d8778b9e435" style="list-style-type:decimal"><li><b>凭据加密（CE）存储空间</b>：这种加密方式设计用来保护那些需要设备被用户解锁后才能访问的敏感数据。<b>只有在用户输入正确的解锁凭据（如密码、PIN码或图案）后，加密的数据才会被解密并变得可访问，例如</b><code class="notion-inline-code"><b>/data/data</b></code><b>目录下内容即为凭据加密（CE）存储空间</b>。这意味着，如果设备未解锁，即使攻击者物理获取了设备，也无法访问这部分加密的数据。这也就解释了为什么<code class="notion-inline-code"><b>/data/data</b></code><b> 在重启未解锁的情况下是无法访问的。</b></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-782260f049a4439e8318eb9acae46183" style="list-style-type:decimal"><li><b>设备加密（DE）存储空间</b>：DE存储空间的数据在<b>设备启动</b>时就被解密，因此在直接启动模式（Direct Boot mode）期间，即使设备还没有被用户解锁，这部分数据也是可访问的。这允许某些基本功能和应用（如闹钟、电话接收和紧急呼叫）在用户未解锁设备的情况下正常工作。然而，这也意味着这部分数据的安全性相对较低，因为它们在设备启动后即可访问。</li></ol><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-42864838c55f48bd8b6da3aa4b65cc4b" data-id="42864838c55f48bd8b6da3aa4b65cc4b"><span><div id="42864838c55f48bd8b6da3aa4b65cc4b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#42864838c55f48bd8b6da3aa4b65cc4b" title="2. 应用处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. 应用处理</span></span></h3><div class="notion-text notion-block-c31437b44f494fd6bbc8a27108d6fc24">为了实现系统应用的快速迁移，新增了两个可在应用级别设置的属性。<code class="notion-inline-code">defaultToDeviceProtectedStorage</code> 属性仅适用于系统应用，<code class="notion-inline-code">directBootAware</code> 属性则适用于所有应用。</div><div class="notion-text notion-block-ef85a7ebef5248748a7fef42c46ede65">应用级别的 <code class="notion-inline-code">directBootAware</code> 属性的含义是将相应应用中的所有组件均标记为加密感知型组件。</div><div class="notion-text notion-block-1af63fa198994b8c916dbc06c29842e6"><code class="notion-inline-code">defaultToDeviceProtectedStorage</code> 属性用于将默认的应用存储位置重定向到 DE 存储空间（而非 CE 存储空间）。使用此标记的系统应用必须仔细审核存储在默认位置的所有数据，并将敏感数据的路径更改为使用 CE 存储空间。使用此选项的设备制造商应仔细检查要存储的数据，以确保其中不含任何个人信息。</div><div class="notion-text notion-block-39d917019a9342ac9bccf4674ce34599">在这种模式下运行时，以下系统 API 可在需要时用于明确管理由 CE 存储空间支持的 Context（这些 API 与设备保护存储空间适用的同类 API 相对应）。</div><ul class="notion-list notion-list-disc notion-block-1017b69f4c5c4d58ad48429887542253"><li><code class="notion-inline-code">Context.createCredentialProtectedStorageContext()</code></li></ul><ul class="notion-list notion-list-disc notion-block-bd85024f65b540098503ec657ada07d9"><li><code class="notion-inline-code">Context.isCredentialProtectedStorage()</code></li></ul><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-154f8e71e0194f15a8cddcf54f89b34d" data-id="154f8e71e0194f15a8cddcf54f89b34d"><span><div id="154f8e71e0194f15a8cddcf54f89b34d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#154f8e71e0194f15a8cddcf54f89b34d" title="3.更新处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3.更新处理</span></span></h3><div class="notion-text notion-block-4032d24950b84a13b7390c6a5c6be8ee">恢复分区无法访问 userdata 分区中采用 DE 保护的存储空间。强烈建议实现 FBE 的设备使用 <a class="notion-link" href="https://source.android.google.cn/docs/core/ota/ab/ab_implement?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">A/B 系统更新</a>来支持 OTA 机制。由于可以在正常操作期间安装 OTA 更新，因此恢复分区无需访问已加密存储卷中的数据。</div><div class="notion-text notion-block-f285b4e267e04602b2cbe3b5c0fdd470">如果使用旧版 OTA 解决方案（该解决方案要求恢复分区访问 <code class="notion-inline-code">userdata</code> 分区中的 OTA 文件），则需要执行以下操作：</div><ol start="1" class="notion-list notion-list-numbered notion-block-7608922e37044a9fa60c9abdb4e3e769" style="list-style-type:decimal"><li>在 <code class="notion-inline-code">userdata</code> 分区中创建一个顶级目录（例如 <code class="notion-inline-code">misc_ne</code>）。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-7076d0b891ba4438a4caf3ec28367142" style="list-style-type:decimal"><li>将该顶级目录配置为非加密（请参阅<a class="notion-link" href="https://source.android.google.cn/docs/security/features/encryption/file-based?authuser=19&amp;hl=zh-cn#excluding-directories" target="_blank" rel="noopener noreferrer">排除目录</a>）。</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-818c7ea7f2b8440095e6eeda07ea3ed9" style="list-style-type:decimal"><li>在顶级目录中创建一个用于存放 OTA 更新包的目录。</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-1993c1c50859467a8d22105022e32858" style="list-style-type:decimal"><li>添加 SELinux 规则和文件环境，以便控制对该目录及其内容的访问。应当只有接收 OTA 更新的进程或应用能够对该目录进行读取和写入操作。任何其他应用或进程都不应具有访问该目录的权限。</li></ol><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-37181873832e4d8cabc01977a43329c3" data-id="37181873832e4d8cabc01977a43329c3"><span><div id="37181873832e4d8cabc01977a43329c3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#37181873832e4d8cabc01977a43329c3" title="4. 存储类别和密钥存储"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">4. 存储类别和密钥存储</span></span></h3><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-6c048dc408434d8e8e030de38d53917e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F2cf83001-a5ac-4c7d-95b9-1a58f7153f48%2FUntitled.png?table=block&amp;id=6c048dc4-0843-4d8e-8e03-0de38d53917e&amp;t=6c048dc4-0843-4d8e-8e03-0de38d53917e&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-fc9ef3da936b4222bf562ec2f8d0d2ca"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-03268d4b0d0e4ecdb5b4900930041d7f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F5d500d03-7a66-46a2-94d6-22094e9ce299%2FUntitled.png?table=block&amp;id=03268d4b-0d0e-4ecd-b5b4-900930041d7f&amp;t=03268d4b-0d0e-4ecd-b5b4-900930041d7f&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-3c462a47d5964ace82e7ae3ba66580fb">如上表所示，大多数 FBE 密钥都存储在由另一个 FBE 密钥加密的目录中。只有先解锁包含这些密钥的存储类别，才能解锁这些密钥。</div><div class="notion-text notion-block-bcbef640f2b64b388e5be7aa76094005">此外，<code class="notion-inline-code">vold</code> 还会对所有 FBE 密钥应用一层加密。除了用于内部存储设备的 CE 密钥之外，每个密钥都使用自己的 <a class="notion-link" href="https://source.android.google.cn/docs/security/features/keystore?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">Keystore</a> 密钥（该密钥不在 TEE 外部公开）以 AES-256-GCM 加密。这样一来，除非受信任的操作系统已启动（正如<a class="notion-link" href="https://source.android.google.cn/docs/security/features/verifiedboot?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">启动时验证</a>所强制执行的那样），否则便无法解锁 FBE 密钥此外，Keystore 密钥还需要设置<a class="notion-link" href="https://source.android.google.cn/docs/security/features/keystore/implementer-ref?authuser=19&amp;hl=zh-cn#rollback_resistance" target="_blank" rel="noopener noreferrer">抗回滚</a>，以便在 Keymaster 支持抗回滚的设备上也能安全地删除 FBE 密钥。为了在抗回滚不可用时能够尽力回退，系统使用存储在与密钥一起存储的 <code class="notion-inline-code">secdiscardable</code> 文件中的 16384 个随机字节的 SHA-512 哈希作为 Keystore 密钥的<a class="notion-link" href="https://source.android.google.cn/docs/security/features/keystore/tags?authuser=19&amp;hl=zh-cn#application_id" target="_blank" rel="noopener noreferrer">应用 ID 标记</a>。只有将这些字节全部恢复，才能恢复 FBE 密钥。</div><div class="notion-text notion-block-4de85e60b11f463f931a1cec98f22a36">用于内部存储设备的 CE 密钥将获得更高级别的保护，以确保在未掌握用户的锁屏知识因素 (LSKF)（PIN 码、图案或密码）、<a class="notion-link" href="https://developer.android.google.cn/work/dpc/security?authuser=19&amp;hl=zh-cn#secure-passcode-reset" target="_blank" rel="noopener noreferrer">安全密码重置令牌</a>或<a class="notion-link" href="https://source.android.google.cn/docs/core/ota/resume-on-reboot?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">重新启动时恢复</a>操作的客户端密钥及服务器端密钥的情况下，CE 密钥无法解锁。只允许为<a class="notion-link" href="https://developer.android.google.cn/work/managed-profiles?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">工作资料</a>和<a class="notion-link" href="https://developers.google.cn/android/work/requirements/fully-managed-device?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">完全受管设备</a>创建密码重置令牌。</div><div class="notion-text notion-block-e11b857bf20344e4b4a9b707e6d8af72">为此，<code class="notion-inline-code">vold</code> 会使用从用户的合成密码派生的 AES-256-GCM 密钥加密每个用于内部存储设备的 CE 密钥。合成密码是为每个用户随机生成的不可变的高熵加密密钥。<code class="notion-inline-code">system_server</code> 中的 <code class="notion-inline-code"><a class="notion-link" href="https://android.googlesource.com/platform/frameworks/base/+/main/services/core/java/com/android/server/locksettings/LockSettingsService.java" target="_blank" rel="noopener noreferrer">LockSettingsService</a></code> 用于管理合成密码及其保护方式。</div><div class="notion-text notion-block-fe18330fcd3e454b85e7e6993b90f5c0">为了使用 LSKF 保护合成密码，<code class="notion-inline-code">LockSettingsService</code> 首先会扩展 LSKF（方法是通过 <code class="notion-inline-code"><a class="notion-link" href="https://en.wikipedia.org/wiki/Scrypt" target="_blank" rel="noopener noreferrer">scrypt</a></code> 传递 LSKF，目标时间约为 25 毫秒且内存用量约为 2 MiB）。由于 LSKF 通常较短，因此该步骤通常无法提供多少安全性。主要的安全保障是下文所述的<a class="notion-link" href="https://developers.google.cn/android/security/android-ready-se?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">安全元件 (SE)</a> 或由 TEE 强制执行的速率限制。</div><div class="notion-text notion-block-640add2d6a9f420b99448acf37bc6eb1">如果设备具有安全元件 (SE)，则 <code class="notion-inline-code">LockSettingsService</code> 使用 <a class="notion-link" href="https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/weaver/1.0/IWeaver.hal" target="_blank" rel="noopener noreferrer">Weaver HAL</a> 将经过扩展的 LSKF 映射到存储在 SE 中的高熵随机密钥。然后，<code class="notion-inline-code">LockSettingsService</code> 将对合成密码进行两次加密：第一次使用从经过扩展的 LSKF 和 Weaver 密钥派生的软件密钥，第二次使用未经身份验证绑定的 Keystore 密钥。这样即可对 LSKF 猜测施加 SE 强制速率限制。</div><div class="notion-text notion-block-1394b053feba4b24b41e1d8064e6335e">如果设备没有 SE，则 <code class="notion-inline-code">LockSettingsService</code> 会改为使用经过扩展的 LSKF 作为 <a class="notion-link" href="https://source.android.google.cn/docs/security/features/authentication/gatekeeper?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">Gatekeeper</a> 密码。然后，<code class="notion-inline-code">LockSettingsService</code> 将对合成密码进行两次加密：第一次使用从经过扩展的 LSKF 和 secdiscardable 文件的哈希派生的软件密钥，第二次使用经过身份验证绑定至 Gatekeeper 注册的 Keystore 密钥。这样即可对 LSKF 猜测施加 TEE 强制速率限制。</div><div class="notion-text notion-block-bc1eedaf14b240619959cb150bded821">更改 LSKF 后，<code class="notion-inline-code">LockSettingsService</code> 会删除与合成密码和旧 LSKF 的绑定相关的所有信息。在支持 Weaver 或可抗回滚的 Keystore 密钥的设备上，这样做可以保证安全地删除旧绑定。因此，即使用户没有 LSKF，系统也会应用此处所述的保护措施。</div><blockquote class="notion-quote notion-block-89049b71cc8344deadfc24d5d3e5d739"><div><a class="notion-link" href="https://docs.samsungknox.com/admin/knox-platform-for-enterprise/kbas/kba-360039577713/" target="_blank" rel="noopener noreferrer">https://docs.samsungknox.com/admin/knox-platform-for-enterprise/kbas/kba-360039577713/</a></div><div class="notion-text notion-block-ffe4443597104d5d9f362070315b4ca3"><b>FBE 适用于搭载 Android 9.0 或更高版本和 Knox 3.3 或更高版本的所有三星 Galaxy 设备，可保护用户数据 分区中的文件。每个文件均使用</b><code class="notion-inline-code"><b>AES-256-XTS</b></code><b>单独加密，并使用从主密钥派生的唯一文件加密密钥。在 FBE 中，主密钥由基于 TEE 的 Keymaster 组件随机生成和保护，类似于 FDE 实现。</b></div></blockquote><div class="notion-blank notion-block-40a3120d15fc499c9f3f7b6d4024b4fe"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-36cf9c14bda74600a1aa398d7b42286b" data-id="36cf9c14bda74600a1aa398d7b42286b"><span><div id="36cf9c14bda74600a1aa398d7b42286b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#36cf9c14bda74600a1aa398d7b42286b" title="0x02 TrustZone与CE密钥的派生"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x02 TrustZone与CE密钥的派生</span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2fd787c534664dfd8b8787e4c963ee7f" data-id="2fd787c534664dfd8b8787e4c963ee7f"><span><div id="2fd787c534664dfd8b8787e4c963ee7f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2fd787c534664dfd8b8787e4c963ee7f" title="1. TrustZone "><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. <b>TrustZone </b></span></span></h3><div class="notion-text notion-block-223d66fe9d184d6088cfc3d4bafd21e6"><b>TrustZone</b>是ARM针对消费电子设备设计的一种硬件架构，其目的是为消费电子产品构建一个安全框架来抵御各种可能的攻击。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ad9edda7111f4e298d012efdf2047b81"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F5c8f04cb-fed1-4dcb-b927-18d731e50a5b%2FUntitled.png?table=block&amp;id=ad9edda7-111f-4e29-8d01-2efdf2047b81&amp;t=ad9edda7-111f-4e29-8d01-2efdf2047b81&amp;width=709.96875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-3e2c61f8d9784121a706c518c407e509"><code class="notion-inline-code"><b>TrustZone</b></code>在概念上将SoC的硬件和软件资源划分为安全(<code class="notion-inline-code">Secure World</code>)和非安全(<code class="notion-inline-code">Normal World</code>)两个世界，所有需要保密的操作在安全世界执行（如指纹识别、密码处理、数据加解密、安全认证等），其余操作在非安全世界执行（如用户操作系统、各种应用程序等），安全世界和非安全世界通过一个名为<code class="notion-inline-code">Monitor Mode</code>的模式进行转换</div><div class="notion-text notion-block-c63f599dafb8489c9babf60f9ff2c950">处理器架构上，TrustZone将<b>每个物理核虚拟为两个核</b>，一个非安全核（<code class="notion-inline-code">Non-secure Core, NS Core</code>），<b>运行非安全世界的代码；和另一个安全核（Secure Core），运行安全世界的代码。</b></div><div class="notion-text notion-block-96192bcdb4f3477aa55ad95b5519c88d">两个虚拟的核以基于时间片的方式运行，<b>根据需要实时占用物理核，并通过Monitor Mode在安全世界和非安全世界之间切换</b>，类似同一CPU下的多应用程序环境，不同的是多应用程序环境下操作系统实现的是进程间切换，<b>而Trustzone下的Monitor Mode实现了同一CPU上两个操作系统间的切换。</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2fa797d1cd57407c86c41a9b89f9fe73"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff70c5057-be9c-46f8-9e43-7e2e39724618%2FUntitled.png?table=block&amp;id=2fa797d1-cd57-407c-86c4-1a9b89f9fe73&amp;t=2fa797d1-cd57-407c-86c4-1a9b89f9fe73&amp;width=363.9940490722656&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-3a46e946901a4d1e9aae3cf75858acb8"> </div><div class="notion-text notion-block-edf84d8cab0a47da8e74b6ccfa1009d6"><b> 以三星设备为例</b></div><ol start="1" class="notion-list notion-list-numbered notion-block-2853fb9e94328071b88cd02a9d7db757" style="list-style-type:decimal"><li><b>Samsung Knox</b>：这是三星的一套安全解决方案，包括受信任的组件和普通世界的应用程序组件，如Android应用和库。Knox旨在提供一个小而安全的执行环境，即受信任的计算基础（TCB）。</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-2853fb9e9432805aa323ff90927f9c62" style="list-style-type:decimal"><li><b>TEEgris</b>：这是三星在一些基于Exynos的设备上提供的受信任操作系统TEE。在过去，三星曾使用Kinibi作为不同的受信任操作系统，该系统已经成为安全研究的主题。即使是三星的模型也可能搭载高通的SoC和其自己的受信任操作系统QSEE。<b>TEEgris组成部分包括内核、TA和驱动程序。其中内核运行在S-EL1，TA运行在S-EL0。</b></li></ol><div class="notion-text notion-block-d81f6813711049978a2ddafc405c3c46">虽然完全隔离的环境非常安全，但为了实际使用，它需要与 Android 中运行的其他不受信任的组件进行通信。REE 和 TEE 之间的通信是使用名为<code class="notion-inline-code"><b>Secure Monitor Call</b></code>（<code class="notion-inline-code"><b>SMC</b></code>）的专用指令触发的。当 EL &gt; 0 时，两个世界都可以调用此指令，<b>这意味着 Android 应用程序无法直接发起与安全 TEE 的通信</b>。通常情况下，Linux 内核充当代理并公开驱动程序，应用程序可以使用该驱动程序与 TEE 进行交互。这种设计的优势在于，可以应用访问限制策略（例如使用 SELinux）来访问驱动程序，以便只有一部分应用程序可以与 TEE 通信，从而限制攻击面。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-075097cbe2804e0980b1811ccef32485"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:528px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F2d714184-5865-4089-9db5-d8ccb4bd7342%2FUntitled.png?table=block&amp;id=075097cb-e280-4e09-80b1-811ccef32485&amp;t=075097cb-e280-4e09-80b1-811ccef32485&amp;width=528&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-8a2e02320996429581140d0a11a4b538"> </div><div class="notion-blank notion-block-3087be09f9794325b5021d7774e1ebfe"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-3fc8541de26f42a5815d652b756fba87" data-id="3fc8541de26f42a5815d652b756fba87"><span><div id="3fc8541de26f42a5815d652b756fba87" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3fc8541de26f42a5815d652b756fba87" title="2. CE密钥派生流程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. <b>CE密钥派生流程</b></span></span></h3><div class="notion-blank notion-block-18ba9176302d4a38ade2abd1e1d6b657"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ecfef598af144531b33c8f41f7b42bbc" data-id="ecfef598af144531b33c8f41f7b42bbc"><span><div id="ecfef598af144531b33c8f41f7b42bbc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ecfef598af144531b33c8f41f7b42bbc" title="#身份验证"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#身份验证</span></span></h4><div class="notion-text notion-block-2843fb9e94328045982bd21e6669a0dc"><b>首先关注Android身份验证的宏观流程。</b></div><div class="notion-text notion-block-dec0eb16485f43b9bbf1947f56dc0c43"><a class="notion-link" href="https://source.android.com/docs/security/features/authentication?hl=zh-cn" target="_blank" rel="noopener noreferrer">https://source.android.com/docs/security/features/authentication?hl=zh-cn</a></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ee371b603a9544febbe19c24d0fb7bce"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:364px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F96846f29-0d6f-4072-b0d2-b7505149c8ec%2FUntitled.png?table=block&amp;id=ee371b60-3a95-44fe-bbe1-9c24d0fb7bce&amp;t=ee371b60-3a95-44fe-bbe1-9c24d0fb7bce&amp;width=364&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><ol start="1" class="notion-list notion-list-numbered notion-block-5cb25a96acbf43e887bca2e0238e9eda" style="list-style-type:decimal"><li>用户提供身份验证方法，然后关联的服务向关联的守护程序发出请求。</li><ol class="notion-list notion-list-numbered notion-block-5cb25a96acbf43e887bca2e0238e9eda" style="list-style-type:lower-alpha"><ul class="notion-list notion-list-disc notion-block-22df6dd4d47a49bea0cdd3be472f3c72"><li>对于 PIN 码、解锁图案或密码，<code class="notion-inline-code">LockSettingsService</code> 会向 <code class="notion-inline-code">gatekeeperd</code> 发出请求。</li></ul><ul class="notion-list notion-list-disc notion-block-f620b4c9a9ed4d7fb115e3fb91e61ae3"><li>基于生物识别技术的身份验证流程取决于 Android 版本。在搭载 Android 8.x 及更低版本的设备上，<code class="notion-inline-code">FingerprintService</code> 会向 <code class="notion-inline-code">fingerprintd</code> 发出请求。在搭载 Android 9 及更高版本的设备上，<code class="notion-inline-code">BiometricPrompt</code> 会使用合适的 <code class="notion-inline-code"><b>Biometric</b></code><code class="notion-inline-code">Manager</code> 类（如 <code class="notion-inline-code">FingerprintManager</code> 或 <code class="notion-inline-code">FaceManager</code>）向相应的生物识别守护程序发出请求（例如，若是指纹识别身份验证，则向 <code class="notion-inline-code">fingerprintd</code> 发出请求；若是人脸识别身份验证，则向 <code class="notion-inline-code">faced</code> 发出请求）。无论什么版本，生物识别身份验证都会在请求发出后异步进行。</li></ul></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-13dfd447ca974549b1453557acbb6776" style="list-style-type:decimal"><li>守护程序将数据发至其副本，后者生成 AuthToken：</li><ol class="notion-list notion-list-numbered notion-block-13dfd447ca974549b1453557acbb6776" style="list-style-type:lower-alpha"><ul class="notion-list notion-list-disc notion-block-1e5d4bc8cf1146f58bbb0c0ca4281305"><li>对于 PIN 码/解锁图案/密码身份验证，<code class="notion-inline-code">gatekeeperd</code> 将 PIN 码、解锁图案或密码哈希发送到 TEE 中的 Gatekeeper。<b>如果 TEE 中的身份验证成功，TEE 中的 Gatekeeper 会将包含相应用户 SID（已使用 AuthToken HMAC 密钥签名）的 AuthToken 发送到它在 Android 操作系统中的副本。</b></li></ul><ul class="notion-list notion-list-disc notion-block-ae99061413e041b9a90686d2a0d5f1ea"><li>对于指纹识别身份验证，<code class="notion-inline-code">fingerprintd</code> 会监听指纹事件并将数据发送到 TEE 中的 Fingerprint。如果 TEE 中的身份验证成功，TEE 中的 Fingerprint 会将 AuthToken（已使用 AuthToken HMAC 密钥签名）发送到它在 Android 操作系统中的副本。</li></ul><ul class="notion-list notion-list-disc notion-block-59da5bec8e8746a9843143fac5d31837"><li>对于其他生物识别身份验证，相应的生物识别守护程序会监听生物识别事件，并将其发送到相应的生物识别 TEE 组件。</li></ul></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-1a1bd672fa4a4642812a6db7835f9029" style="list-style-type:decimal"><li>守护程序收到经过签名的 AuthToken，并通过密钥库服务 Binder 接口的扩展程序将 AuthToken 传递给密钥库服务。（<code class="notion-inline-code">gatekeeperd</code> 还会在设备被重新锁定以及设备密码发生变化时通知密钥库服务。）</li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-91f10b0d85dd47e391d4bcd94aa12ff3" style="list-style-type:decimal"><li>密钥库服务将 AuthToken 传递给 Keymaster，并使用与 Gatekeeper 和支持的生物识别 TEE 组件共用的密钥来验证这些 AuthToken。Keymaster 会将令牌中的时间戳视为最后一次身份验证的时间，并根据该时间戳做出密钥发布决定（以允许应用使用相应密钥）。</li></ol><div class="notion-text notion-block-da643cf2ff42435098b97528eeda096b">为了确保在各种语言和组件之间实现令牌的共用和兼容，<code class="notion-inline-code"><a class="notion-link" href="https://android.googlesource.com/platform/hardware/libhardware/+/main/include/hardware/hw_auth_token.h" target="_blank" rel="noopener noreferrer">hw_auth_token.h</a></code> 中规定了 AuthToken 的格式。</div><div class="notion-blank notion-block-2843fb9e943280bb9e40cb2f55ce6c50"> </div><div class="notion-callout notion-blue_background_co notion-block-2843fb9e94328091b8cbcf89108343e4"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2843fb9e943280f894b3dcd560141608">总结：
当用户凭据从ROS传递到TEE中，TEE 内部做真正的比对成功后，TEE 组件会用一把在 TEE 内共享的 HMAC 密钥对 AuthToken 签名，然后把这个 AuthToken（含 SID、时间戳等）返回到 Android OS 对应守护进程。<b>SID 是用户在 TEE 世界的“安全身份”，AuthToken 是带签名的“这次确实通过了的凭据票据”，Keymaster据此放行或拒绝密钥操作；</b>若没有旧凭据就改密，会换 SID，从而与旧密钥“断绝亲缘”。<b>注意：设备重新启动后，AuthToken 即作废。</b></div></div></div><div class="notion-blank notion-block-6cd4035df6aa4e27904ef7e7f35141c7"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2bc638d245924907a3764e3d61257015" data-id="2bc638d245924907a3764e3d61257015"><span><div id="2bc638d245924907a3764e3d61257015" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2bc638d245924907a3764e3d61257015" title="#CE密钥派生完整流程和相关文件"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#CE密钥派生完整流程和相关文件</span></span></h4><div class="notion-text notion-block-2843fb9e94328014b01cdcdedcc82f1e"><b>上面解释了Android身份验证的宏观流程，但是还有很多问题没有解决，比如在TEE中是如何对比的？返回authToken到Android OS后的流程又是什么？仅仅在TEE侧校验通过就完成了设备的解锁吗？</b></div><div class="notion-text notion-block-2843fb9e943280308539d4ec4da018dd"><b>首先回答最后一个问题，在获得AuthToken后就意味着设备解锁了吗，当然不是这样的。上文提到了用户数据在FBE机制下会被加密，而设备解锁就是解开用户数据的一把钥匙，在用户输入了正确的密钥的那一刻不仅仅进入了桌面，还完成了用户数据的解锁，否则那么多App就无法使用了，所以就涉及到了用户数据解密的流程，那么就从CE密钥派生的完整流程谈起。</b></div><div class="notion-blank notion-block-2843fb9e943280ba89cbd627db8e0347"> </div><div class="notion-text notion-block-594ea763c1114710a1bb2c0f4d443aac"><b>使用</b><code class="notion-inline-code"><b>TrustZone</b></code><b> 进行CE密钥派生的完整过程如下（以非生物特征解密为例），流程很复杂所以拆分几个部分进行说明。</b></div><ul class="notion-list notion-list-disc notion-block-1f7053d672034911a7e44b8c3c84d405"><li><b>使用 Gatekeeper 进行身份验证</b></li></ul><ul class="notion-list notion-list-disc notion-block-c9f46b86b37f4a66bda854dc847986a1"><li>生成合成密码<b>Synthetic Password</b></li></ul><div class="notion-blank notion-block-b161c2caa3a24877aee1d7fc0d33873a"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-0b9fdd66e7bb4ed5bf80e23c3a66cc9f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F810742ab-88f4-4774-a65a-6515c7622f27%2FUntitled.png?table=block&amp;id=0b9fdd66-e7bb-4ed5-bf80-e23c3a66cc9f&amp;t=0b9fdd66-e7bb-4ed5-bf80-e23c3a66cc9f&amp;width=12432&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-26bcc6b7a80545a1977e1cb3af2ed443"> </div><div class="notion-text notion-block-a21b7d182c2f404392a9af7d9f697486"><code class="notion-inline-code">/data/system_de/0/spblob</code> 目录是 Synthetic Password（合成密码）持久化仓，放在设备加密（DE）空间里。它必须在用户未解锁前就能被访问到，所以存放在 system_de 而不是 system_ce/CE，下面的文件有三个比较重要，分别是<code class="notion-inline-code">&lt;handle&gt;.pwd</code> <code class="notion-inline-code">&lt;handle&gt;.secdis</code> 以及<code class="notion-inline-code">&lt;handle&gt;.spblob</code> 。</div><div class="notion-blank notion-block-2843fb9e9432803a9c7ef59a41f8d3a4"> </div><ul class="notion-list notion-list-disc notion-block-5ded8382e08e4e6e971df83824691f01"><li><code class="notion-inline-code">&lt;handle&gt;.pwd</code> 存储了进行scrypt哈希的<code class="notion-inline-code">N R P</code>以及<code class="notion-inline-code">salt</code>值，除此之外还存储了注册时生成的密钥<code class="notion-inline-code">handle</code> ，其计算方式是<code class="notion-inline-code">HMAC(SHA512(&quot;user-gk-authentication&quot; || scrypt(credentials, N, R, P, salt))</code> ，在<code class="notion-inline-code">gatekeeper</code>进行密钥校验时会读取改<code class="notion-inline-code">handle</code>进行比较。但是需要注意这里的<code class="notion-inline-code">HMAC</code>并未常规的，而是使用依赖于<code class="notion-inline-code">/dev/crypto</code>的<code class="notion-inline-code">KDF</code>实现，由于是硬件相关的，其复杂程度使得爆破<code class="notion-inline-code">handle</code>变得不现实。</li></ul><ul class="notion-list notion-list-disc notion-block-f15fa12824b74bc68f56761d8689b726"><li><code class="notion-inline-code">&lt;handle&gt;.secdis</code> 是密钥注册时随机生成的一组值，用于加密和解密凭据<code class="notion-inline-code">&lt;handle&gt;.spblob</code>  </li></ul><ul class="notion-list notion-list-disc notion-block-838ce0a0a35e4fcc9a83089ca69a74b2"><li><code class="notion-inline-code">&lt;handle&gt;.spblob</code> 存储了<b>合成密码</b><code class="notion-inline-code"><b>Synthetic Password</b></code>的两次AES的加密结果，只要获取合成密码就可以获取CE密钥。</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-7febad456a7a49b1bee98eb12551b5a3"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fa3dce6ab-8e12-4b4c-b8be-11310f365fcc%2FUntitled.png?table=block&amp;id=7febad45-6a7a-49b1-bee9-8eb12551b5a3&amp;t=7febad45-6a7a-49b1-bee9-8eb12551b5a3&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-fcfa20199ebe4c9fae297d5f6d2d052a"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9969db6551c24f78b0adca5fafac992a" data-id="9969db6551c24f78b0adca5fafac992a"><span><div id="9969db6551c24f78b0adca5fafac992a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9969db6551c24f78b0adca5fafac992a" title="#使用 Gatekeeper 进行身份验证"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>#使用 Gatekeeper 进行身份验证</b></span></span></h4><div class="notion-text notion-block-8df0986882424a248625d37a6c2ccba4">首先需要明确<code class="notion-inline-code"><b>Gatekeeper</b></code><b> 是如何进行凭据注册和验证的。</b></div><div class="notion-text notion-block-acac4c75225048a5aaeef8180dafd518"><code class="notion-inline-code"><b>Gatekeeper</b></code>是TEE（受信任执行环境）中的一个<b>受信任应用程序（</b><code class="notion-inline-code"><b>TA</b></code><b>）</b>，在验证用户凭证以进行身份验证方面发挥着关键作用。它通过与相应的Android守护进程和硬件抽象层（<code class="notion-inline-code">HAL</code>）通信来实现这一点。需要注意的是，<b>Gatekeeper仅涉及通过PIN、密码或图案进行的身份验证，而其他TA用于支持生物识别技术。</b>然而，在设备启动时用户首次进行身份验证时，不能使用生物识别技术，这与数据加密直接相关。</div><div class="notion-text notion-block-c2cc2307db714e5197a20fd6a927d59d">Gatekeeper实现了两个概念上简单的命令：Enroll（注册）和Verify（验证）。</div><ul class="notion-list notion-list-disc notion-block-d5d598a1c573454d93b27183241bfd8e"><li><b>Enroll</b>：当用户首次设置认证因素或更改时通常会调用此命令。该命令根据注册时的密码凭据创建blob并对其进行签名，并将其转换为<b>密码句柄</b><code class="notion-inline-code">&lt;handle&gt;.pwd</code>。具体的流程是首先使用<code class="notion-inline-code">scrypt</code>进行扩展，然后与散列字符串组合<code class="notion-inline-code">HMAC(SHA512(&quot;user-gk-authentication&quot; || scrypt(credentials, N, R, P, salt))</code> 。</li></ul><ul class="notion-list notion-list-disc notion-block-8abbc8f5b87d4139bb134da8d0bff2f7"><li><b>Verify</b>：当用户尝试进行身份验证时调用此命令，它验证当前身份验证尝试的密码是否有效。它通过计算HMAC并将其与原始密码句柄进行比较来实现。</li></ul><div class="notion-text notion-block-2843fb9e943280079a6ee852c9bbe3e7"><b>这里其实回答了上面三联问中的第一个问题，即校验是怎么实现的</b></div><div class="notion-callout notion-blue_background_co notion-block-57b1d83c53374406b0f98f9aa9c94a93"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><b>Scrypt</b>是一个密钥派生函数，<b>需要大量内存，用于减缓自定义硬件攻击。其参数与凭证的盐一起存储在文件中。这个非常简单的步骤对每次身份验证尝试造成的延迟可以忽略不计，但对需要多次进行此操作的攻击者来说，却大大减缓了速度。</b></div></div><div class="notion-blank notion-block-6eb68f8e85b54ab9aecdb3dad8393441"> </div><div class="notion-text notion-block-2da802a908d8431db6f40e389fb2d556">下图截取自上面流程图的左上角，其包含了<code class="notion-inline-code"><b>Gatekeeper</b></code><b> 的验证和</b><code class="notion-inline-code">applicationId</code><b>的生成。</b>最左侧的<code class="notion-inline-code">credentials</code>是用户输入的凭据，<code class="notion-inline-code"><b>Gatekeeper</b></code><b> </b>读取<code class="notion-inline-code">&lt;handle&gt;.pwd</code> 中的参数后计算token并进行两次散列，与原本存储在<code class="notion-inline-code">&lt;handle&gt;.pwd</code>中的散列结果比较，如果一致说明身份验证成功，不一致则校验失败，不进行后续的操作。将<code class="notion-inline-code">token</code>与<code class="notion-inline-code">&lt;handle&gt;.secdis</code> 中的内容做哈希后得到<code class="notion-inline-code">applicationId</code> ，这个值是随着用户输入的凭据变化而变化的。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-b8e77c52811b4712a7ebe460aaac8a0e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff566e607-48f2-49ac-9c60-7cc036ae4fd9%2FUntitled.png?table=block&amp;id=b8e77c52-811b-4712-a7eb-e460aaac8a0e&amp;t=b8e77c52-811b-4712-a7eb-e460aaac8a0e&amp;width=3376&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-callout notion-blue_background_co notion-block-2853fb9e943280e2a19dde2d0129342a"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2853fb9e943280408d82d67de4756d37">AuthToken和这里的Token不是一个东西
上图的token是<code class="notion-inline-code">scrypt(credentials, N, R, P, salt)</code>得到的结果，计算出的token会在两次哈希后得到handle并与存储在pwd文件中注册时生成的哈希进行校验<b>（</b><code class="notion-inline-code"><b>HMAC(SHA512(&quot;user-gk-authentication&quot; || token))</b></code><b>是否等于写在pwd文件中注册时生成的handle）</b>，以此判断用户输入凭据是否是正确的，如果正确会根据次token生成applicationId，并且只有校验正确的情况下TEE才会返回一个AuthToken表明校验通过，用于解锁在KeyStore中的一个密钥，这个AuthToken仅仅是一种凭证，而不是用户输入凭据的哈希。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2853fb9e94328064aaaff20a35cb4254"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Afe515e15-ea2d-4fa6-a1a9-d7ca74fc1f8d%3Aimage.png?table=block&amp;id=2853fb9e-9432-8064-aaaf-f20a35cb4254&amp;t=2853fb9e-9432-8064-aaaf-f20a35cb4254" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2853fb9e94328090bd4bcf09a23cfd90"><b>总结就是 authtoken不会随着用户输入的变化而变化，而token会。authToken仅是校验过程中产生的一种凭证，如果校验失败不会产生此凭证。所以如果想要爆破密码关注的不应该是authToken，而是对用户凭据做运算后的token或哈希后的handle，或由其计算得到的applicationId。</b></div><div class="notion-blank notion-block-2853fb9e9432806facc2e4d36d47b4c3"> </div></div></div><div class="notion-text notion-block-2843fb9e943280e4b09bd8acfad71218">
这里的 || 操作是personalised_hash 的意思。也就是“带上下文标签的哈希”（也叫域分离的哈希）。它把一段固定的个性化字符串（personalization）当作“命名空间/上下文”，与要哈希的数据一起送进 SHA-512，这样同一份原始材料在不同用途下会得到完全不同的哈希结果，避免密钥用途混淆与交叉攻击。例如先把 personalization（如 <code class="notion-inline-code">&quot;fbe-key&quot;</code>, <code class="notion-inline-code">&quot;pw-hash&quot;</code>, <code class="notion-inline-code">&quot;secdiscardable-transform&quot;</code> 等）填充到 128 字节；先喂入这段 personalization，再依次喂入后续数据，做 SHA-512</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-804146efacbf4cd7a71a368a9a62c38e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fa67efaa7-0844-4205-b6ec-50d833127f30%2FUntitled.png?table=block&amp;id=804146ef-acbf-4cd7-a71a-368a9a62c38e&amp;t=804146ef-acbf-4cd7-a71a-368a9a62c38e&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-673c30ade4524e7fbad8ce6bb15bda99">这里还有一些细节需要了解。如果身份验证成功，Gatekeeper会创建一个认证令牌(<code class="notion-inline-code">auth</code><code class="notion-inline-code"><b>token</b></code>)。这是一个标准格式的签名令牌，旨在防止重放攻击，其实就是上面提到的AuthToken。<b>该令牌证明用户已经通过身份验证，并需要发送给</b><code class="notion-inline-code"><b>Keymaster TA</b></code><b>以解锁绑定认证的密钥，因为这个密钥是存储在</b><code class="notion-inline-code"><b>Keystore</b></code><b>中的</b><code class="notion-inline-code"><b>SecretKey</b></code><b>，在一般情况下无法通过其他手段读取，后面会再次提到</b>。如果身份验证尝试失败，Gatekeeper的节流机制将启动，使得暴力破解变得不可能。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2e07278d469d4d60b1398a66643aa0e4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fa1869585-14cd-473b-80bf-f0d8344cc943%2FUntitled.png?table=block&amp;id=2e07278d-469d-4d60-b139-8a66643aa0e4&amp;t=2e07278d-469d-4d60-b139-8a66643aa0e4&amp;width=3324&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-e9fb248c61024f5ebc50e898e7f37f17">这部分对应在<code class="notion-inline-code">/system/framework/services.jar</code>中的实现如下</div><div class="notion-text notion-block-19926d82d688465c9cbde95f91501e51">首先是<code class="notion-inline-code">unwrapPasswordBasedSyntheticPassword</code> 中将输入的<code class="notion-inline-code">credential</code> 传递给<code class="notion-inline-code">gatekeeper</code> 校验，如果校验成功则<code class="notion-inline-code">transformUnderSecdiscardable</code> 生成<code class="notion-inline-code">applicationId</code></div><div class="notion-text notion-block-dd6429ea619a4305be7604df50dd0286"><code class="notion-inline-code">transformUnderSecdiscardable</code> 实现就是流程图中靠右的部分，第二个参数为<code class="notion-inline-code">/data/system_de/0/&lt;handle&gt;.secdis</code> 文件内容，第一个参数<code class="notion-inline-code">pwdToken</code> 是通过<code class="notion-inline-code">computePasswordToken</code> 计算得到的</div><div class="notion-text notion-block-3c969829a1c54b0bbb57024c8ee1d084"><b>由此可见，上面的整个流程都是可以离线计算的，所以假设如果能获取到这些密钥相关文件，就可以通过任意的输入密码计算</b><code class="notion-inline-code"><b>applicationId</b></code><b> </b></div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ebf5f68884f943a398cd6e970dc1b4e6" data-id="ebf5f68884f943a398cd6e970dc1b4e6"><span><div id="ebf5f68884f943a398cd6e970dc1b4e6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ebf5f68884f943a398cd6e970dc1b4e6" title="#合成密码Synthetic Password"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#合成密码<b>Synthetic Password</b></span></span></h4><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ff3b033d2b8b489c90f58c100be78cac"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F065d2004-cde7-4917-ab5c-f06a3fdd0193%2FUntitled.png?table=block&amp;id=ff3b033d-2b8b-489c-90f5-8c100be78cac&amp;t=ff3b033d-2b8b-489c-90f5-8c100be78cac&amp;width=4092&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-a9b907f6693747b4883dec01b00f40f7">一旦用户通过身份验证，系统就会获得一个有效的<code class="notion-inline-code">applicationId</code>。这需要经过几个步骤，才能真正成为 CE 密钥。首先就需要生成一个合成密码<code class="notion-inline-code"><b>Synthetic Password</b></code>，但是得到该密码后仍需执行一些其他步骤。重点关注<code class="notion-inline-code"><b>Synthetic Password</b></code><b>的生成</b></div><div class="notion-text notion-block-48c2a9ee10844a00b8b09fdab5c013b7">合成密码存储在 Android 文件系统中，必须使用两个不同的密钥解密。</div><ul class="notion-list notion-list-disc notion-block-e24ceb2216d04a728b55cb6473953ac9"><li><b>第一个是存储在</b><code class="notion-inline-code"><b>Android Keystore</b></code><b>中的常规密钥，受 </b><code class="notion-inline-code"><b>TEE</b></code><b> 保护并与身份验证绑定</b>。由于这些密钥永远不会离开 TEE，因此它们以加密形式存储，<b>需要在 Keymaster TA 内解密，即在上面提到的，只有在</b><code class="notion-inline-code"><b>Gatekeeper</b></code><b>校验成功后才会解密</b>。</li></ul><ul class="notion-list notion-list-disc notion-block-552ce290af52421e9dd5ef98e29da18e"><li>完成第一次解密（在 TEE 中）后，将使用<code class="notion-inline-code">applicationId</code> 的散列值作为密钥再次解密中间值。此处的 AES 是使用<a class="notion-link" href="https://en.wikipedia.org/wiki/Galois/Counter_Mode" target="_blank" rel="noopener noreferrer">GCM 模式</a>完成的：如果密钥出现问题,会因MAC标签不匹配而失败导致异常，利用这一特性就可以进行密钥爆破。</li></ul><div class="notion-text notion-block-47f5406e8ce24b6fa9dae721e77439ce">相关的源码实现如下</div><div class="notion-text notion-block-c17d6814e168422f8c5fefe1cbce2cc2"><code class="notion-inline-code">decryptBlob</code> 从<code class="notion-inline-code">DEFAULT_KEYSTORE</code> 获取一个<code class="notion-inline-code">SecretKey</code> ，而这个<code class="notion-inline-code">keyAlias</code> 其实就是<code class="notion-inline-code">synthetic_password_&lt;handle&gt;</code> 该key值无法直接获取，必须<b>在</b><code class="notion-inline-code"><b>Gatekeeper</b></code><b>校验成功后才会解密并且由</b><code class="notion-inline-code"><b>system_server</b></code><b>获取。之后进行两次</b><code class="notion-inline-code">decrypt</code> </div><div class="notion-text notion-block-37c3237e03274e57ad7e1ddfe55d6cd6">第一次的密钥是<code class="notion-inline-code">decryptionKey</code>固定的，也就是前面提到的<code class="notion-inline-code">SecretKey</code> 的值，两次解密的iv都是<code class="notion-inline-code">&lt;handle&gt;.spblob</code>的前12个字节</div><div class="notion-text notion-block-0e564cb29bfe45ae86c97fcee9e7a10a">第二次的密钥是<code class="notion-inline-code">applicationId</code> 经过<code class="notion-inline-code">personalisedHash</code> 后的哈希值，解密的密文是第一次解密的结果<code class="notion-inline-code">intermediate</code>。</div><div class="notion-text notion-block-e3fe3847339948c493c8097dc9399e3b">可以发现这整个环节中，第一次解密的密钥是无法获取的，必须<code class="notion-inline-code">Gatekeeper</code>校验通过才会由<code class="notion-inline-code">KeyMaster</code>解密，那就导致无法离线计算。从而保证了密钥的安全性。为了能够绕过这一限制，有两个解决方案：</div><ul class="notion-list notion-list-disc notion-block-99603026e34f49a980f25fd8781ddcb4"><li>修改<code class="notion-inline-code">KeyMaster</code> 使攻击者能获取到第一次解密的密钥</li></ul><ul class="notion-list notion-list-disc notion-block-94576743f8c045ff99845f57b237ef02"><li><b>修改</b><code class="notion-inline-code"><b>Gatekeeper</b></code><b> 使其校验永远成功，永远返回token，这样</b><code class="notion-inline-code"><b>KeyMaster</b></code><b> 也会解密密钥，只需要在第一次解密后Hook即可获取到第一次解密后的密文，进而完全解密。</b></li></ul><div class="notion-text notion-block-82ea40bb3e6246d3866d8aca8a287000"><b>这里选择第二种方案，但是无论是采取哪一种方案，攻击的前提是必须要获取这些密钥相关文件，那么设备就必须要root，除此之外还需要具备修补可信应用的能力。</b>
</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-1747a956e8b94c1c95fd50570872e67c" data-id="1747a956e8b94c1c95fd50570872e67c"><span><div id="1747a956e8b94c1c95fd50570872e67c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1747a956e8b94c1c95fd50570872e67c" title="0x03 漏洞利用"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x03 漏洞利用</span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-8dbf1135a60e47cf880672cad44e4144" data-id="8dbf1135a60e47cf880672cad44e4144"><span><div id="8dbf1135a60e47cf880672cad44e4144" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8dbf1135a60e47cf880672cad44e4144" title="1. 设备"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. 设备</span></span></h3><div class="notion-text notion-block-b0993f81a86c4b48aaf89d54d14c4b90">该设备关机状态下同时按住上下音量后插入usb数据线进入下载模式。</div><div class="notion-text notion-block-b793b29d27454ba0a2523a4e10b7b61e">关机状态下同时按音量上+电源长按启动，到看到第一个<code class="notion-inline-code">logo</code>后放手到<code class="notion-inline-code">rec</code>模式。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-e1a386cb95ac45b59acf943c7fceb7bb"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fd0713ec5-f54f-4369-bfe8-b7cf11ffc7ff%2FUntitled.png?table=block&amp;id=e1a386cb-95ac-45b5-9acf-943c7fceb7bb&amp;t=e1a386cb-95ac-45b5-9acf-943c7fceb7bb&amp;width=720&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-0dd4c77f06724a36968d149a347dacda">使用<code class="notion-inline-code">MTKClient</code> 工具，首先启动脚本等待设备连接，这里直接使用<code class="notion-inline-code">Ubuntu 22.04</code>系统，Windows系统可能存在各种各样的问题。然后短接背板上的两个测试点进入<b>强刷模式</b>(<code class="notion-inline-code">BROM</code>)，<code class="notion-inline-code">MTKClient</code> 检测到设备并且进行指定操作。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3bc3fb576dcb478fa22806da6d85781f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:432px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F6d5a3665-a321-470e-bb01-bcb4cb7e70ef%2FUntitled.png?table=block&amp;id=3bc3fb57-6dcb-478f-a228-06da6d85781f&amp;t=3bc3fb57-6dcb-478f-a228-06da6d85781f&amp;width=432&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-b92bc098b76044d09bbaed44695968b2"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F417af5cb-7e0b-4a80-a721-8d32ae59ecdd%2FUntitled.png?table=block&amp;id=b92bc098-b760-44d0-9bba-ed44695968b2&amp;t=b92bc098-b760-44d0-9bba-ed44695968b2&amp;width=2091&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-c15a4ba53d2546bea6b369feac9e561f"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-ba362080bbdd46b1abceed33c5efce81" data-id="ba362080bbdd46b1abceed33c5efce81"><span><div id="ba362080bbdd46b1abceed33c5efce81" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ba362080bbdd46b1abceed33c5efce81" title="2. 利用过程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. 利用过程</span></span></h3><div class="notion-text notion-block-2009ae2aedc94972a0d012e397d5d58f">首先是<code class="notion-inline-code">Android</code>的启动过程如下</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-911262d252d74469a7376661703134ac"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff3df22cc-3d2f-4c15-9f58-91f98f0e648a%2FUntitled.png?table=block&amp;id=911262d2-52d7-4469-a737-6661703134ac&amp;t=911262d2-52d7-4469-a737-6661703134ac&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-061203e4a1df4001b0af9b559f85fc41">实现了<code class="notion-inline-code">ATF(Arm Trust Firmware)</code>的启动过程如下</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-6e085d436ebf478cac573bbf0ec305f1"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff6e180ba-fea3-47f4-9460-926051e8b50e%2FUntitled.png?table=block&amp;id=6e085d43-6ebf-478c-ac57-3bbf0ec305f1&amp;t=6e085d43-6ebf-478c-ac57-3bbf0ec305f1&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-bba8582bb44144c4864b357abaf59056">为了发起攻击，我们需要修补以下组件：</div><ul class="notion-list notion-list-disc notion-block-2853fb9e943280c8bdfedcbf985077bb"><li><code class="notion-inline-code">PreLoader</code>，<code class="notion-inline-code">PreLoader</code>介于<code class="notion-inline-code">boot rom</code>和<code class="notion-inline-code">bootloader</code>之间的桥梁，主要工作是初始化环境，包括c环境，<code class="notion-inline-code">timer,gpio,pmic,uart,i2c</code>等以及装载<code class="notion-inline-code">lk</code>镜像至<code class="notion-inline-code">DRAM</code>中，建立起最基本的运行环境，最重要的就是初始化DRAM。因为<b>要修改后面的镜像，所以需要现修补PreLoader 以绕过对LK等的镜像校验检查。</b></li></ul><ul class="notion-list notion-list-disc notion-block-2853fb9e9432804b900bf40b6215b347"><li><code class="notion-inline-code">the next bootloader BL3</code>，称为 <code class="notion-inline-code">Little Kernel</code>（简称 LK），作为一个小型内核（SMP-aware），提供线程/调度等最小运行环境；作为引导器，完成硬件早期初始化、启动模式选择（正常/Recovery/Fastboot）、加载并跳转内核等。<b>因为想要启动修改后的 Android </b><code class="notion-inline-code"><b>boot.img</b></code><b>，所以需要在这个阶段禁用 </b><code class="notion-inline-code"><b>Android</b></code><b> 安全启动的一系列检查</b></li></ul><ul class="notion-list notion-list-disc notion-block-2853fb9e943280739264cfe7cdb367c3"><li><code class="notion-inline-code">Android</code>系统的<code class="notion-inline-code">boot</code>镜像，授予 <code class="notion-inline-code">root</code>权限，并设置动态挂载，为替换TA做准备。</li></ul><ul class="notion-list notion-list-disc notion-block-2853fb9e943280088c53ff51c3e720dc"><li><code class="notion-inline-code">TEEGRIS</code>，作为三星某些设备的TEE，需要修改内核以用于禁用受信任应用程序的验证，还需要修改其内部的TA，通过动态挂载能够实现这一目标。</li></ul><div class="notion-text notion-block-2853fb9e9432808ba076f8048639a2c3"><b>而真正的攻击入口是Boot ROM，通过利用联发科芯片的BROM漏洞从最底层开始攻击，逐层向上攻击，以突破安全边界。</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2b206c78f7aa43679a1c91bbd42e51cc"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.so/f/f/3d9d581b-1cbe-449e-9723-f2162662aa76/7616019c-acc0-4862-9197-efb1cd9a108d/fbe_mediatek_boot_patch.gif?table=block&amp;id=2b206c78-f7aa-4367-9a1c-91bbd42e51cc&amp;spaceId=3d9d581b-1cbe-449e-9723-f2162662aa76&amp;expirationTimestamp=1778320800000&amp;signature=RhX2djIBhbBf0Xk_If5EhNOFS18_KgP6ghNh9883pdE&amp;t=2b206c78-f7aa-4367-9a1c-91bbd42e51cc" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-15db6cbe9e894d2b8003c9afc43620ae"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-1e62800fd3144ba38db49e22c7af6a28" data-id="1e62800fd3144ba38db49e22c7af6a28"><span><div id="1e62800fd3144ba38db49e22c7af6a28" class="notion-header-anchor"></div><a class="notion-hash-link" href="#1e62800fd3144ba38db49e22c7af6a28" title="3. Patch PreLoader"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3. Patch PreLoader</span></span></h3><div class="notion-text notion-block-ca522f87b6544e598252c4baa57f7af4">通过<code class="notion-inline-code">mtkclient</code>提取<code class="notion-inline-code">PreLoader</code> ，然后查看<code class="notion-inline-code">mtkclient</code> 是如何解析<code class="notion-inline-code">PreLoader</code> 二进制的结构，发现其<code class="notion-inline-code">jump_offset</code> 是<code class="notion-inline-code">0x30:0x34</code> 的四字节，<code class="notion-inline-code">daaddr</code> 是<code class="notion-inline-code">0x1C:0x20</code> 的四字节加上<code class="notion-inline-code">jump_offset</code> 。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-74ae587da35d4b8bb9faf7ce22443089"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F0d0ffcf3-8e0a-4edf-b0a9-45b783dd846f%2FUntitled.png?table=block&amp;id=74ae587d-a35d-4b8b-b9fa-f7ce22443089&amp;t=74ae587d-a35d-4b8b-b9fa-f7ce22443089&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-0e30d504be1649eab1303be28f0548a3">IDA加载时加载地址设为<code class="notion-inline-code">0x201000</code>，文件偏移设为<code class="notion-inline-code">0xF0</code> ，同时同步上下两个<code class="notion-inline-code">size</code> ，在入口处按c将会自动开始分析，过程和下面LK的加载一致，可以看下面。</div><div class="notion-text notion-block-696646fd619f48639d08ca25fb6c2cb9"><b>在Patch LK镜像时输入发现无法开机，但是又没有日志，去查资料才发现，联发科的芯片可以直接dump </b><code class="notion-inline-code"><b>expdb</b></code><b>分区获取日志信息</b>。这里还是使用<code class="notion-inline-code">mtkclient</code>dump，问题似乎出在<code class="notion-inline-code">sbc</code>校验，但是通过修改lk中相关字符串，发现这个报错不在这里，而是在<code class="notion-inline-code"><b>preloader</b></code>，所以才需要去patch <code class="notion-inline-code"><b>preloader</b></code><b> 绕过相关校验。</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-d5a6617d248c4620b33ca24f913354bf"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F2c70c6df-8a10-4140-a1e0-13890738dd6e%2FUntitled.png?table=block&amp;id=d5a6617d-248c-4620-b33c-a24f913354bf&amp;t=d5a6617d-248c-4620-b33c-a24f913354bf&amp;width=709.96875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-6e31580f2ffd4a3aa78d838f107341d1">patch <code class="notion-inline-code"><b>sbc_img_auth</b></code><b> 以绕过对lk镜像的校验，避免无法开机的情况</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-44ad79a7176b4807a5fd0a9b44c515fe"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F4912111d-12ae-4b25-b350-0eb840a20d4f%2FUntitled.png?table=block&amp;id=44ad79a7-176b-4807-a5fd-0a9b44c515fe&amp;t=44ad79a7-176b-4807-a5fd-0a9b44c515fe&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ead4175bfadc471f80f779ec800dd050"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F29931f67-8456-4418-80f5-0f3aa2c39e3f%2FUntitled.png?table=block&amp;id=ead4175b-fadc-471f-80f7-79ec800dd050&amp;t=ead4175b-fadc-471f-80f7-79ec800dd050&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-5a76f04c90b1449da11d28427b87573a">使用<code class="notion-inline-code">patch</code>后的二进制启动设备，发现能够成功出现三星<code class="notion-inline-code">log</code> 说明绕过了<code class="notion-inline-code">lk</code>镜像校验，之后启动设备都需要使用补丁后的<code class="notion-inline-code">preloader</code>来启动</div><div class="notion-blank notion-block-dcbddb29cfff469b852570d9f87d488e"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2c4ecfd9f6654e1e86d882503c0e720f" data-id="2c4ecfd9f6654e1e86d882503c0e720f"><span><div id="2c4ecfd9f6654e1e86d882503c0e720f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2c4ecfd9f6654e1e86d882503c0e720f" title="4. Patching LK"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">4. <b>Patching LK</b></span></span></h3><div class="notion-text notion-block-4bbaaa9d462c47ef98048b6ef86a5ece">首先需要说明IDA如何正确加载<code class="notion-inline-code"><b>LK</b></code><b> 镜像并进行分析</b></div><div class="notion-callout notion-blue_background_co notion-block-aab7c4c9416a4e87b263685f1fd88051"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">IDA如何正确加载<code class="notion-inline-code"><b>LK</b></code><b> 镜像并进行分析</b><div class="notion-text notion-block-552cfe09c2cf48a2a01cb9afb5478e2c">首先LK位于<code class="notion-inline-code">BL_xxxx.tar</code> 解压得到<code class="notion-inline-code">lk-verified.img.lz4</code> 再次解压得到<code class="notion-inline-code">img</code> 。为了能让IDA正确的加载img并进行分析必须获取的值</div><ul class="notion-list notion-list-disc notion-block-346d890d3f2e46ef9c4fc5af85eecee0"><li><code class="notion-inline-code"><b>ROM Start Address/Loading Address</b></code><b> ：</b>对应LK镜像而言，<code class="notion-inline-code">0x002C</code>偏移位置是镜像的加载地址，在这里为<code class="notion-inline-code">0xFFFFFFFF</code> ，即为<code class="notion-inline-code">-1</code>，所以是无效的地址，这是因为新的联发科镜像不会从这里选取地址加载，直接搜索<code class="notion-inline-code">10 FF 2F E1</code> 十六进制字节，<b>跳过其后四个字节，再取四字节即为</b><code class="notion-inline-code"><b>Loading Address</b></code><b>  ，这里小端序，所以加载地址即为</b><code class="notion-inline-code"><b>0x4C400000</b></code></li><ul class="notion-list notion-list-disc notion-block-346d890d3f2e46ef9c4fc5af85eecee0"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-d9388b6387254b54935f478c8194c743"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:528px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F98ef6b02-073c-4686-8c44-0c54de4447cd%2FUntitled.png?table=block&amp;id=d9388b63-8725-4b54-935f-478c8194c743&amp;t=d9388b63-8725-4b54-935f-478c8194c743&amp;width=528&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-33f72709d6dc4d53a8575ab043dd60a1"><li><code class="notion-inline-code"><b>File Offset</b></code><b> ：</b>联发科的所有分区镜像都有<code class="notion-inline-code">0x200</code>字节的头部，从<code class="notion-inline-code">0x200</code>开始为可执行的部分。</li><ul class="notion-list notion-list-disc notion-block-33f72709d6dc4d53a8575ab043dd60a1"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-315c29ee789d46fc8196d0588a0020da"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:576px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fc3d78b7a-80a3-4a6a-be41-281a8320e973%2FUntitled.png?table=block&amp;id=315c29ee-789d-46fc-8196-d0588a0020da&amp;t=315c29ee-789d-46fc-8196-d0588a0020da&amp;width=576&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><div class="notion-blank notion-block-4501e089285b4ac088bde5f6de0417a9"> </div><div class="notion-text notion-block-ae12bcd33949478085ea6f595dc64423"><code class="notion-inline-code"><b>IDA 32bit</b></code>打开后选择ARM小端序架构，然后填写参数信息，<b>其中</b><code class="notion-inline-code"><b>Loading size</b></code><b>会根据填入的值自动调整，调整完成后将其复制到</b><code class="notion-inline-code"><b>ROM size</b></code><b> 保持同步即可。</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-cc80fd29c924499aa750bd6511e4a607"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:480px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fec6826bb-e5dd-4897-bb98-691d41ca6e4d%2FUntitled.png?table=block&amp;id=cc80fd29-c924-499a-a750-bd6511e4a607&amp;t=cc80fd29-c924-499a-a750-bd6511e4a607&amp;width=480&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-d0adffdc1f3c44f6bc25959eedc06964">代码从文件偏移量<code class="notion-inline-code">0x200</code> 开始，但 IDA 不知道它是入口点。在<b>IDA-View A</b>中单击行<code class="notion-inline-code">DCB 7</code>at <code class="notion-inline-code">ROM:</code><code class="notion-inline-code"><b>4C400000</b></code>。将光标移到那里后，按键盘上的<b>[C] 。之后IDA会自动分析出更多内容。</b></div><div class="notion-text notion-block-1135f537f73a4f77899fea098f3823ce">之前查找的4字节特征即为<code class="notion-inline-code">BX R0</code>指令，可以发现在后面8字节即为<code class="notion-inline-code"><b>ROM</b></code>加载的地址</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-723824e100f440efafe30087c2dfea84"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:528px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ffeae2fe6-4680-46a8-aa53-8e05e77456e0%2FUntitled.png?table=block&amp;id=723824e1-00f4-40ef-afe3-0087c2dfea84&amp;t=723824e1-00f4-40ef-afe3-0087c2dfea84&amp;width=528&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></div><div class="notion-blank notion-block-46bd2417a0ee49b2aa2f2641f651fe81"> </div><ul class="notion-list notion-list-disc notion-block-63f811d0016d4f0dbf4fc7fa6b3b9190"><li>patch在<code class="notion-inline-code">load_and_verify_vbmeta</code>中的<code class="notion-inline-code">avb_safe_memcmp</code> 绕过LK镜像的Hash校验</li><ul class="notion-list notion-list-disc notion-block-63f811d0016d4f0dbf4fc7fa6b3b9190"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-c52b1c489da14229b11cf260bc8a168d"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F37f673cc-230a-4e04-afa0-5b7a724201eb%2FUntitled.png?table=block&amp;id=c52b1c48-9da1-4229-b11c-f260bc8a168d&amp;t=c52b1c48-9da1-4229-b11c-f260bc8a168d&amp;width=681.9375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-e054eae740de4612bb6ea41742554784"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fdf825839-e983-4303-adbf-fc6ab3cf0b5f%2FUntitled.png?table=block&amp;id=e054eae7-40de-4612-bb6e-a41742554784&amp;t=e054eae7-40de-4612-bb6e-a41742554784&amp;width=681.96875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-8810467f423f4a4c8e3cb64de9420d2c">包括patch <code class="notion-inline-code">sub_4C4A61B4</code>内部的<code class="notion-inline-code">avb_safe_memcmp</code> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-10395c600d674bddbf4aa7a44c133d45"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fc23ef8b1-be8f-4bc8-b7a1-6554d6db1904%2FUntitled.png?table=block&amp;id=10395c60-0d67-4bdd-bf4a-a7a44c133d45&amp;t=10395c60-0d67-4bdd-bf4a-a7a44c133d45&amp;width=680&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-4781adde7a5d49e3b74b674b88593fe7">patch <code class="notion-inline-code">avb_slot_verify</code> 中的<code class="notion-inline-code">avb_memcmp</code> 对<code class="notion-inline-code">vbmate</code>的哈希校验</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-c8da0238a64e41a1b2d77227d53cb481"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F551defdb-1bb1-44f1-9024-309eeb8ed9cd%2FUntitled.png?table=block&amp;id=c8da0238-a64e-41a1-b2d7-7227d53cb481&amp;t=c8da0238-a64e-41a1-b2d7-7227d53cb481&amp;width=3316&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-ccabcd8819d24e698207dfb93d244e6f">patch <code class="notion-inline-code">load_and_verify_vbmeta</code>中的另一处<code class="notion-inline-code">avb_safe_memcmp</code></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-c4e2e4a502524e0fa6ed844cc81179a8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F943b8f24-108b-4d1f-8683-1ff7e14a3d18%2FUntitled.png?table=block&amp;id=c4e2e4a5-0252-4e0f-a6ed-844cc81179a8&amp;t=c4e2e4a5-0252-4e0f-a6ed-844cc81179a8&amp;width=680&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-31d0642fed0545559710c2bab5534f5b"><li>patch调用<code class="notion-inline-code">show_dm_verity_error</code> 的位置，否则会出现<code class="notion-inline-code">dm_verity</code> 错误并且在5s后关机。</li><ul class="notion-list notion-list-disc notion-block-31d0642fed0545559710c2bab5534f5b"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-52bf38a727b5435b8e472f949b668e9e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fd85f55e3-8a36-435c-8049-a422d456aede%2FUntitled.png?table=block&amp;id=52bf38a7-27b5-435b-8e47-2f949b668e9e&amp;t=52bf38a7-27b5-435b-8e47-2f949b668e9e&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-4f876b784f764d5b98d0fb374f7f4867"><li>patch <code class="notion-inline-code">get_efuse_blow_status</code> ，使其返回0，以使上面检测保险丝熔断状态时返回正常的状态。</li><ul class="notion-list notion-list-disc notion-block-4f876b784f764d5b98d0fb374f7f4867"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-fb14fb145f2e4c1f9c96b18575da4d3b"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F70f9a845-0fa3-4110-8894-e4b8621e00f1%2FUntitled.png?table=block&amp;id=fb14fb14-5f2e-4c1f-9c96-b18575da4d3b&amp;t=fb14fb14-5f2e-4c1f-9c96-b18575da4d3b&amp;width=3378&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-f8bd302a92134d6e8d668e90612314df"><li>patch <code class="notion-inline-code">do_decision</code> 中的三个内容，保证其返回值为0，且不会出现关机的情况</li><ul class="notion-list notion-list-disc notion-block-f8bd302a92134d6e8d668e90612314df"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-56e0d66b6c1f4abba4e4c98cacad03c2"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F3e679976-9258-4233-bee2-b876fb3074f9%2FUntitled.png?table=block&amp;id=56e0d66b-6c1f-4abb-a4e4-c98cacad03c2&amp;t=56e0d66b-6c1f-4abb-a4e4-c98cacad03c2&amp;width=3426&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-4b22bd65f7074deaa2f557a9b2806817"><li>patch <code class="notion-inline-code">avb</code>校验时的逻辑，NOP掉一个跳转</li><ul class="notion-list notion-list-disc notion-block-4b22bd65f7074deaa2f557a9b2806817"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-f6036c2eb5064ddfb8a887da9e3168d4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F97f55bda-8a15-4437-9f07-8bdebbff61f0%2FUntitled.png?table=block&amp;id=f6036c2e-b506-4ddf-b8a8-87da9e3168d4&amp;t=f6036c2e-b506-4ddf-b8a8-87da9e3168d4&amp;width=680&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-f311b3d29d584aae9d149a97457d5061"><li>patch擦除数据的函数，防止意外清除用户数据（例如在测试解锁时会自动调用擦除数据的函数）</li><ul class="notion-list notion-list-disc notion-block-f311b3d29d584aae9d149a97457d5061"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-86f7bea8fada4b0bb39bf81f0046d0cf"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F1807d3a8-b4f3-47b8-a05f-305752c0f90f%2FUntitled.png?table=block&amp;id=86f7bea8-fada-4b0b-b39b-f81f0046d0cf&amp;t=86f7bea8-fada-4b0b-b39b-f81f0046d0cf&amp;width=3441&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-97003c6d08744a50a7afc43206882f7f"><li>patch <code class="notion-inline-code">is_sbc</code> 返回0以绕过sbc检查</li><ul class="notion-list notion-list-disc notion-block-97003c6d08744a50a7afc43206882f7f"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-58818be9f26743d896d6b07630c37e26"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fdff72048-8742-411a-a5f3-811378b9e9a2%2FUntitled.png?table=block&amp;id=58818be9-f267-43d8-96d6-b07630c37e26&amp;t=58818be9-f267-43d8-96d6-b07630c37e26&amp;width=3414&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-8bf8b044ca9f4d6d8eb45ab32937743d"><li>patch <code class="notion-inline-code">set_warrant_bit</code> 使其返回0</li><ul class="notion-list notion-list-disc notion-block-8bf8b044ca9f4d6d8eb45ab32937743d"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-8f128b38dcd545289817c66946a2d276"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F1a234139-796d-4f4f-bb3e-73ad07b6fb64%2FUntitled.png?table=block&amp;id=8f128b38-dcd5-4528-9817-c66946a2d276&amp;t=8f128b38-dcd5-4528-9817-c66946a2d276&amp;width=3391&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><div class="notion-blank notion-block-fca9fba524ff4218a3b9f5e4e02e86f7"> </div><ul class="notion-list notion-list-disc notion-block-7e93ba767e7745db843b9d997a54b031"><li>patch 其他镜像的<code class="notion-inline-code">sha256</code>校验</li><ul class="notion-list notion-list-disc notion-block-7e93ba767e7745db843b9d997a54b031"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2fb04ed688c44ced9962373d12fe557c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F1dc40a71-d125-49a5-b508-b3bc087e90d2%2FUntitled.png?table=block&amp;id=2fb04ed6-88c4-4ced-9962-373d12fe557c&amp;t=2fb04ed6-88c4-4ced-9962-373d12fe557c&amp;width=681.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-bcb0e283d79f44c09c74ee43687a868c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F4e5eddc1-39cd-48cc-aa87-db7842aaace5%2FUntitled.png?table=block&amp;id=bcb0e283-d79f-44c0-9c74-ee43687a868c&amp;t=bcb0e283-d79f-44c0-9c74-ee43687a868c&amp;width=681.96875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><ul class="notion-list notion-list-disc notion-block-458cd42767b447a5ab71fb35991b02f2"><li>patch启动时的安全检查<code class="notion-inline-code">check_secure_boot</code>，将<code class="notion-inline-code">authinfo</code>的两个字段修改为0，并且将函数返回值强制设置为0。</li><ul class="notion-list notion-list-disc notion-block-458cd42767b447a5ab71fb35991b02f2"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-7941db43caa34cf19c75a642a832a354"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fd7f15f77-1f3f-4b38-95d3-c8ee523020a2%2FUntitled.png?table=block&amp;id=7941db43-caa3-4cf1-9c75-a642a832a354&amp;t=7941db43-caa3-4cf1-9c75-a642a832a354&amp;width=3318&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><div class="notion-blank notion-block-a0ff62deeb904e788b9868f90d068142"> </div><div class="notion-text notion-block-9a63be86be374ba48489deb08d6849a1"><b>下面的两块拓展内容可以跳过，但是如果想更全面的学习，还是需要了解一下。</b></div><div class="notion-text notion-block-2853fb9e943280459fc3e00a24dc38c3">由于设备是未解锁的（攻击场景就是未解锁设备），刷入boot镜像进行root会显示不允许刷入非官方的镜像。<b>所以可以直接patch LK中获取设备锁状态的部分，一般解锁后设备会自动擦除数据，为了避免数据被擦除也需要patch擦除数据的部分。</b></div><div class="notion-text notion-block-2853fb9e943280bb84abce82118e3b60">但是更好的办法是直接patch 检查镜像的部分，即上面提到的authinfo ，但是随之而来的问题是如果不采用解锁的Patch方案，<b>刷入第三方REC镜像会导致开不了机并且也无法进入REC模式查看日志信息。</b></div><div class="notion-text notion-block-2853fb9e9432801ea8e4fe24eae4362b">为了方便学习调试可以先直接给设备解锁，等到攻击验证阶段再把锁加回来，这样就不会出现因为没解锁导致的日志难以查看的问题。</div><div class="notion-text notion-block-2853fb9e9432801ca2c2e66b3a550554">下面的解锁内容属于题外话，前面提到的无法开机的原因是加密分区挂载失败，加密分区挂载失败就是因为设备安全验证没通过，所以为了方便直接处理<code class="notion-inline-code">authinfo</code> 即可，所以这部分仅当拓展。</div><div class="notion-text notion-block-2853fb9e94328021bd24fb863d6a05c2">在解锁状态下直接刷入magisk修补的boot会开机失败并且自动进入rec模式，原因是fs_mgr_mount_all 。尝试禁用vbmeta 也无效。刷入TWRP然后使用adb查看/proc/last_kmsg 发现其实也是挂载加密分区/data失败导致的问题，而本质是因为检测到设备损坏，和上面的结论一致，即安全检测未通过。解决方案就是patch 掉/vendor/tee/00000000-0000-0000-0000-4b45594d5354 (Keymaster)这个可信应用 ，使其认为设备是正常的，从而正常解密，后面修补部分详细展开。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2853fb9e943280d69ac0f1ca41d127a8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A364f6d4a-627b-4c49-97bd-6f4e202381d3%3Aimage.png?table=block&amp;id=2853fb9e-9432-80d6-9ac0-f1ca41d127a8&amp;t=2853fb9e-9432-80d6-9ac0-f1ca41d127a8" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2853fb9e943280a79ebcfa2de72c7492">联发科机型使用 <code class="notion-inline-code">seccfg</code>分区存储设备BL锁等状态关键信息，分区大小一般为<code class="notion-inline-code">8MB</code>，实际使用空间远小于此，<code class="notion-inline-code">1024</code>字节都用不完。其中<code class="notion-inline-code">MTK</code>定义的<code class="notion-inline-code">seccfg</code>头部结构仅为<code class="notion-inline-code">60B</code> ，包括28字节数据部分和32字节的校验部分。剩下的32位校验码因为使用了设备硬件相关的加密，除非设备密钥泄露否则没有办法脱机计算（实现可以参照<a class="notion-link" href="https://github.com/bkerler/mtkclient/blob/main/mtkclient/Library/Hardware/hwcrypto_sej.py" target="_blank" rel="noopener noreferrer">https://github.com/bkerler/mtkclient/blob/main/mtkclient/Library/Hardware/hwcrypto_sej.py</a>）。</div><ul class="notion-list notion-list-disc notion-block-2853fb9e9432805ea61cc224b43aa812"><li>如果设备已解锁，lock_state = 3</li></ul><ul class="notion-list notion-list-disc notion-block-2853fb9e943280f1902bf9910f6b8dcf"><li>如果设备未解锁，lock_state = 4或1</li></ul><div class="notion-text notion-block-2853fb9e943280d7b18cde6b35e9e00b">如下图提取设备中的seccfg分区，观察第0xc开始的四个字节，值为1符合未解锁的定义。但是mtkclient的解锁功能是Patch此处的两个DWORD ，也就是将dm_verity_state Patch为1为解锁，这样就会导致dm_verity 是校验失败的，查看mtkclient 源码此处的字段被解读为critical_lock_state ，通过逆向可以发现显然是dm_verity_state ，所以认为实现可能有问题。<b>而无论是通过mtkclient解锁还是Patch LK都需要擦除用户数据，因为默认keymaster是可信的，其检测到设备损坏后强制要求擦除数据。</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2853fb9e943280b6ae8af8443e327503"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Abf59d46c-af53-416f-9b8c-f11d9c690d4e%3Aimage.png?table=block&amp;id=2853fb9e-9432-80b6-ae8a-f8443e327503&amp;t=2853fb9e-9432-80b6-ae8a-f8443e327503" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2853fb9e94328034bcf1f3aa37605ba2">根据这些已知知识对LK符号进行恢复，能够发现seccfg_get_lock_state是获取设备锁状态的函数，通过读取的ROM内存偏移来识别。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2853fb9e94328015a31fe94f588f2f6d"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A9048a07e-bfcb-4efe-a73a-7ad274cb26b3%3Aimage.png?table=block&amp;id=2853fb9e-9432-8015-a31f-e94f588f2f6d&amp;t=2853fb9e-9432-8015-a31f-e94f588f2f6d" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2853fb9e943280a08506cea54bf66d21">Patch该函数，使其a1读取的值永远为3，以实现使LK认为设备已经解锁，从而不对镜像进行检查。虽然能够进入rec模式，但是开机出现问题，这就和前面说的加密分区挂在失败是一个事情了，不再赘述。
</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2853fb9e943280c18360e69a6ea4de8a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ad219310c-d14a-41ad-aca6-737322738f4c%3Aimage.png?table=block&amp;id=2853fb9e-9432-80c1-8360-e69a6ea4de8a&amp;t=2853fb9e-9432-80c1-8360-e69a6ea4de8a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-2853fb9e94328034a9c0cf57bfdff321"> </div><div class="notion-blank notion-block-2853fb9e943280ab8781e9ad8c95d68c"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-7c8626689f42441ab9f9facad00c54ae" data-id="7c8626689f42441ab9f9facad00c54ae"><span><div id="7c8626689f42441ab9f9facad00c54ae" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7c8626689f42441ab9f9facad00c54ae" title="5. Patching TEEGRIS"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">5. <b>Patching TEEGRIS</b></span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-ab6244e5dcd24e51a35e4a65fd6f61f6" data-id="ab6244e5dcd24e51a35e4a65fd6f61f6"><span><div id="ab6244e5dcd24e51a35e4a65fd6f61f6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#ab6244e5dcd24e51a35e4a65fd6f61f6" title="#TEEGRIS以及修补方案概述"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#<b>TEEGRIS以及</b>修补方案概述</span></span></h4><div class="notion-text notion-block-2853fb9e9432805784a6d1680c6e2226">TEEGRIS内核是一个在安全EL1中运行的小型组件。即使小，但它从严格意义上说并不是微内核。举例来说，其中集成了很多可以由TA使用的驱动程序。它以64位模式运行，并支持在用户空间中运行的64位和32位TA和驱动程序。由于内核以明文存储在引导分区中，因此我们可以轻松提取它并进行反汇编。内核实现了许多POSIX兼容的系统调用，还添加了一些TEEGRIS特定的系统调用。<b>在Alexander Tarasikov的文章中我们注意到，有两个共享库中实现的系统调用包装器（请参考下面的TA章节，详细介绍了如何处理共享库），分别是</b><code class="notion-inline-code"><b>libtzsl.so</b></code><b>和</b><code class="notion-inline-code"><b>libteesl.so</b></code><b>。这让我们可以快速地识别内核中的两个表，分别适用于64位和32位TA的系统调用处理程序。</b></div><ul class="notion-list notion-list-disc notion-block-2853fb9e94328049bd2bcc7675d289aa"><li><code class="notion-inline-code"><b>libtzsl.so</b></code>
“TZ System Library”。给 TA 提供<b>系统调用封装</b>（wrapper）：把 TA 的 POSIX 风格调用（如 <code class="notion-inline-code">open/read/write/mmap/epoll/sendmsg/recvmsg</code> 等）按 TEEGRIS 约定打包成<b>内核系统调用</b>并进入 TEEGRIS 内核（S-EL1）。研究者在 S10 的镜像中看到，三星把<b>每个 syscall 的封装函数</b>都放在这库里，甚至可据此恢复 syscall 表；AArch64 下还约定 <b>X7</b> 寄存器携带系统调用号。</li></ul><ul class="notion-list notion-list-disc notion-block-2853fb9e9432800a8c36db6860cdde8e"><li><code class="notion-inline-code"><b>libteesl.so</b></code>
“TEE System Library”。更像 TA 的<b>运行时框架</b>：很多 TA 的 <code class="notion-inline-code">main()</code> 实际实现在这库中，它会完成<b>与根任务/内核的消息通道初始化</b>，用 <b>epoll</b> 驱动的事件循环接收来自 REE/其他 TA 的请求，然后把事件<b>转发到 TA 的 GP 入口函数</b>（<code class="notion-inline-code">TA_Create/OpenSession/Invoke/Close/Destroy</code>）。因此，<b>TA 的业务代码主要写在这些入口里</b>，而调度/收发在 <code class="notion-inline-code">libteesl.so</code>。</li></ul><div class="notion-blank notion-block-2853fb9e9432805ebbb0f0d25a2e88b1"> </div><div class="notion-text notion-block-2853fb9e943280ad9c85dc1f2afdde8d">这两库通常随 <b>startup.tzar</b> 或系统分区一起下发，供 TA 动态链接；它们把 <b>POSIX 子集 + TEEGRIS 专用调用</b>统一给 TA 使用。<code class="notion-inline-code">libtzsl.so</code> 是“进内核”<b>的门（syscall ABI/封装），</b><code class="notion-inline-code"><b>libteesl.so</b></code><b> 是</b>“跑 TA”的脚手架（入口与事件循环/IPC）。</div><div class="notion-blank notion-block-2853fb9e9432804e9776f7f736b2c8c3"> </div><div class="notion-text notion-block-2853fb9e943280468605fd7fff4f195f">引导分区中包含一个特殊的压缩包（<code class="notion-inline-code">startup.tzar</code>）一般存放在<code class="notion-inline-code">tzar.img (TrustZone ARchive, TZAR)</code>，其中包含TA所需的所有共享库以及在Android完全引导之前早期系统所需的一些特殊TA和驱动程序，包括TSS（用于管理共享内存）、ACSD（用于支持TA身份验证的驱动程序）和root_task（用于加载TA，与ACSD共同对其进行验证）。tzar压缩包中的二进制文件是标准的ELF文件，可以直接加载到反汇编程序中进行分析。由于压缩包是启用映像的一部分，因此在启动时会验证它的签名。  TA也可以在运行时从Android加载。可加载的TA存储在<code class="notion-inline-code">/vendor/tee</code>和<code class="notion-inline-code">/system/tee</code>分区中。提取压缩包并且解压可以得到完整的文件系统，可以看到其中存在root_task和其他可能用到的动态链接库，包括<code class="notion-inline-code">libtzsl.so</code>和<code class="notion-inline-code">libteesl.so</code></div><div class="notion-blank notion-block-2853fb9e943280068039e962a7572a25"> </div><div class="notion-text notion-block-2853fb9e9432807c8572fe1a3b011dd6"><code class="notion-inline-code">TEEGRIS</code>的修补涉及到下面几个镜像</div><ul class="notion-list notion-list-disc notion-block-db7fbb1b41e84ad9948d76dbbf66ad56"><li><code class="notion-inline-code">tee1.img</code>: it contains the <b>Arm Trusted Firmware</b> (which is executed in monitor mode with the highest privileges - EL3), the<b> Secure World kernel</b>, and a<b> binary called </b><code class="notion-inline-code"><b>userboot.so</b></code>. This last one is quite important for us, as it is used to load and verify the root filesystem of TEEGRIS.</li></ul><ul class="notion-list notion-list-disc notion-block-9684606dc3eb437eabf6199a6b40f129"><li><code class="notion-inline-code">tzar.img</code>: this is the root filesystem of TEEGRIS, stored in a custom archive format that has been <a class="notion-link" href="https://allsoftwaresucks.blogspot.com/2019/05/reverse-engineering-samsung-exynos-9820.html" target="_blank" rel="noopener noreferrer">reversed engineered</a>. It contains libraries that can be used by other libraries but also by the TAs, and binaries including one called <code class="notion-inline-code">root_task</code>, that is in charge of verifying and running the TAs provided by Android.</li></ul><ul class="notion-list notion-list-disc notion-block-366f7eb3cf804d9cac0be1bf0fe5bdf2"><li><code class="notion-inline-code">super.img</code> which is the Android main partition containing several logical partitions. One of them is the vendor partition and contains most of the TAs, including Gatekeeper.</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3aaeeed5c3084e39996f481ca2336a5e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.so/f/f/3d9d581b-1cbe-449e-9723-f2162662aa76/a6e9deb2-04e3-48d9-9bcb-63b12c32d7de/fbe_teegris_patch.gif?table=block&amp;id=3aaeeed5-c308-4e39-996f-481ca2336a5e&amp;spaceId=3d9d581b-1cbe-449e-9723-f2162662aa76&amp;expirationTimestamp=1778320800000&amp;signature=d5Z_sxLZauHSGl5pQtZUEBEO4w-5fqFr9P7urgqZSwA&amp;t=3aaeeed5-c308-4e39-996f-481ca2336a5e" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-d630b7bb3eef4b33ad89364d76465efb"> </div><div class="notion-blank notion-block-0e2fdcd6ffab4f62a5c2972395f5564f"> </div><div class="notion-text notion-block-1695c3ef97f243118434085d5bf6c809">采取倒着修补的方法，逐步往上<code class="notion-inline-code">patch</code>·</div><ul class="notion-list notion-list-disc notion-block-3f89369beb1b44ddb95e0f806295e9a8"><li>首先TA的修补可以通过与<code class="notion-inline-code">magisk</code>的<code class="notion-inline-code">magic_mount</code>类似的挂载动态分区实现。可以利用到设备中的一个<code class="notion-inline-code">spu</code>分区，该分区是一个<code class="notion-inline-code">ext4</code>文件系统，一般情况下不存储内容，可以直接在该文件系统下创建同样的目录结构，然后修改Magisk源码，将spu分区提前挂载，然后动态挂载到根目录，这样就会将spu分区底下的文件挂载到对应的目录，但是还需要处理的是<code class="notion-inline-code">selinux</code> 标签，因为<b>magisk daemon</b>是root权限的并且Selinux允许设置标签，所以可以通过chcon设置。</li></ul><ul class="notion-list notion-list-disc notion-block-0615f1f64a74499f9d85ed5d2175f0ed"><li>其次修补<code class="notion-inline-code">tzar</code> ，修补其中的<code class="notion-inline-code">root_task</code>以绕过对可信应用的校验</li></ul><ul class="notion-list notion-list-disc notion-block-a2890ea97b0540a8a348a9dc3bb85a9a"><li>最后修补<code class="notion-inline-code">tee1</code>，修补其中的<code class="notion-inline-code">userboot.so</code>绕过对<code class="notion-inline-code">tzar</code>的校验</li></ul><ul class="notion-list notion-list-disc notion-block-03c5b422cd41446c8b80394d05124e4b"><li>需要注意的是<code class="notion-inline-code">preloader</code>负责对<code class="notion-inline-code">tee1</code>进行加载校验，所以还是需要使用<code class="notion-inline-code">mtkclient</code>绕过对<code class="notion-inline-code">tee1</code>分区的校验（使用自定义<code class="notion-inline-code">preloader</code>完成分区的装载）</li></ul><div class="notion-blank notion-block-88be1944d38241519d78144e5c1ff0d6"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-9652fbe196ad43228ab896d6bdbb6eaa" data-id="9652fbe196ad43228ab896d6bdbb6eaa"><span><div id="9652fbe196ad43228ab896d6bdbb6eaa" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9652fbe196ad43228ab896d6bdbb6eaa" title="#Trust Applet(TA)修补"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#Trust Applet(TA)修补</span></span></h4><div class="notion-text notion-block-917dc1d2d5494d30954bbb4fc2f431e5">实际只需要修补一个可信应用<code class="notion-inline-code">GateKeeper</code> ，二进制文件均放置于<code class="notion-inline-code">/vendor/tee</code>下。命名如下：</div><ul class="notion-list notion-list-disc notion-block-cdfbb1fa774a48e98fc103ad476cd44e"><li><code class="notion-inline-code">00000000-0000-0000-0000-474154454b45</code> 同理后面的数字为<code class="notion-inline-code">GATEKE</code>的ascii码</li></ul><div class="notion-text notion-block-2fb373bb2a4742dcb2549c409c9d8f49"><b>但是在这一节不谈如何修补</b><code class="notion-inline-code"><b>GateKeeper</b></code><b> ，放到最后一节，先按顺序介绍基本知识和修补流程</b></div><div class="notion-blank notion-block-8d050ba1bd3a46bf9035e17ba236965c"> </div><div class="notion-text notion-block-f1e8bf110342476e8de04900d23f43d0">TA文件格式为<b>SEC头 + 标准ELF文件内容 + 附加信息(Metadata + Signature)。</b></div><ul class="notion-list notion-list-disc notion-block-af25ccb311774f58bd133e0b6e08f13c"><li>头部长 8 个字节，包含 4 个字节的版本（SEC2、SEC3或SEC4）和4字节内容部分的长度。</li></ul><ul class="notion-list notion-list-disc notion-block-7ea63e1d74af420d8ab563f40237d7a7"><li>在SEC4的情况下，ELF文件为加密格式，否则为明文。</li></ul><ul class="notion-list notion-list-disc notion-block-45cf003feed94e6fbfed83a2372c0f5f"><li><b>其中附加信息包含签名信息等内容</b>。从版本SEC3开始，<b>有一个包含版本号的附加字段。root_task 将此版本字段与 ACSD 结合使用</b>，以管理 TA 防回滚保护。每当加载 SEC3 或 SEC4 TA 时，都会提取版本号并将其与存储在 RPMB 存储中的版本进行比较。如果版本号较低，则无法加载 TA，并返回错误。如果版本号较高，则 RPMB 中的版本号会增加以匹配 TA 版本，以便无法再加载同一 TA 的旧副本。<b>签名部分包含对图像其余部分的 RSA 签名。它遵循 X.509 格式，并由 ACSD 解析</b></li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-6764bb89d9f145d88fd39a4be164801e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fa6af07f8-674e-4bcf-8f7a-687e299e1f2a%2FUntitled.png?table=block&amp;id=6764bb89-d9f1-45d8-8fd3-9a4be164801e&amp;t=6764bb89-d9f1-45d8-8fd3-9a4be164801e&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-b2dd3a38cb2c4543bfac6274899c7507"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fae05806e-3ba9-46f2-82de-e4404ddd6bd4%2FUntitled.png?table=block&amp;id=b2dd3a38-cb2c-4543-bfac-6274899c7507&amp;t=b2dd3a38-cb2c-4543-bfac-6274899c7507&amp;width=672&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-a3a2dd9c69fc4726a1ef4242671bf0b1"><b>在对TA进行分析的时候可以直接删去开头的前八字节拖入IDA分析，对TA的修补直接在二进制文件上直接修补即可，但是修补完直接加载肯定是失败的，这就需要patch </b><code class="notion-inline-code"><b>tzar</b></code><b>中的</b><code class="notion-inline-code"><b>root_task</b></code><b>以绕过对TA的校验。</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-edd00879ad5f40a08bcb0eae57f60349"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fd68bb301-0f9b-454e-b189-9e5e492a4c6b%2FUntitled.png?table=block&amp;id=edd00879-ad5f-40a0-8bcb-0eae57f60349&amp;t=edd00879-ad5f-40a0-8bcb-0eae57f60349&amp;width=2581&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a8878fc2fe0488db0016088280a5b3d">在探索TA的过程中也可以直接使用下面的脚本将TA文件直接转为可以分析的二进制文件</div><div class="notion-callout notion-blue_background_co notion-block-17926e1449d14c13af1ba0bc02bfec78"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">拓展：在前期探索的过程中也动过另一个TA，就是<code class="notion-inline-code">00000000-0000-0000-0000-4b45594d5354</code> 即<code class="notion-inline-code">keymaster</code>，用于密钥分发等等一系列功能，在前期修补LK镜像时有的地方没有修补并且在解锁状态下刷入了第三方REC，导致无法开机，查看日志发现是<code class="notion-inline-code">keymaster</code>的问题<figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3aeb8d030a0348c883b5daf4c3d8651b"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ffede20aa-e636-4c74-94c8-dc8c22cb1877%2FUntitled.png?table=block&amp;id=3aeb8d03-0a03-48c8-83b5-daf4c3d8651b&amp;t=3aeb8d03-0a03-48c8-83b5-daf4c3d8651b&amp;width=644&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-9bee933998094df695ef4261f5775ac0">出现了解密失败的问题，而这里的解密失败和之前的问题一致。libfs_mgr尝试挂载data分区，但是是加密的所以跳过，然后由<code class="notion-inline-code">vdc</code>使用<code class="notion-inline-code">cryptfs mountFstab</code>命令挂载加密的文件系统。这里的<code class="notion-inline-code">/dev/block/platform/bootdevice/by-name/userdata</code>和<code class="notion-inline-code">/data</code>分别是加密分区的设备路径和挂载点。
找到第一个错误<code class="notion-inline-code">[274:tz_iwlog_thread]SW&gt; keymaster [ERR] (tz_check_oem:72) Device is compromized: status=0, value=1</code></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-173b6d35f46e4c74878d791f936ec18f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F26489f28-40f7-4a08-acca-549013f65af2%2FUntitled.png?table=block&amp;id=173b6d35-f46e-4c74-878d-791f936ec18f&amp;t=173b6d35-f46e-4c74-878d-791f936ec18f&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-e17d56d23c9649708ffd6ef1343084a6">从IDA中索引找到逻辑后直接patch <code class="notion-inline-code">check_compromized</code> 。<b>原本从</b><code class="notion-inline-code"><b>TEES_GetIrsFlagValue</b></code><b> 获取一个</b><code class="notion-inline-code"><b>state</b></code><b>和一个</b><code class="notion-inline-code"><b>value</b></code><b>，如果两者有一者为1就说明设备出现了损坏，后面的解密就会失败，直接patch，让这两个值均为0即可。</b>这里需要注意，这两个全局变量虽然在IDA看起来没有更多引用，但是既然其作为全局变量，大概率存在其他引用，认为IDA可能出现识别问题。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-016ad8c3bfed4230b63ceecf82b59ec8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ffbb0d9d3-2d09-4f48-a61c-7fd938f94f8c%2FUntitled.png?table=block&amp;id=016ad8c3-bfed-4230-b63c-eecf82b59ec8&amp;t=016ad8c3-bfed-4230-b63c-eecf82b59ec8&amp;width=3130&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1d50db14ba344b0f893d563a431b1984"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F42d0fb44-fec5-430b-ba2a-1541b6eef775%2FUntitled.png?table=block&amp;id=1d50db14-ba34-4b0f-893d-563a431b1984&amp;t=1d50db14-ba34-4b0f-893d-563a431b1984&amp;width=3077&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-a3c7b84718504cec8e4b8533a91b000a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F72d4ace0-3fb2-4bb3-ba75-8bae7c526f96%2FUntitled.png?table=block&amp;id=a3c7b847-1850-4cec-8e4b-8533a91b000a&amp;t=a3c7b847-1850-4cec-8e4b-8533a91b000a&amp;width=643.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-03992cdd39794a268c31e5c48b1af3f1">成功挂载加密分区</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-9b06afdf80cd48d9b59e0d0568f8dd39"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ffe7bf3b3-22ee-4970-89f3-26c13f40c82d%2FUntitled.png?table=block&amp;id=9b06afdf-80cd-48d9-b59e-0d0568f8dd39&amp;t=9b06afdf-80cd-48d9-b59e-0d0568f8dd39&amp;width=2796&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></div><div class="notion-blank notion-block-b5c161b860824f6ba25d5b7569d43644"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-77eacf638de54e189701af0120d439dc" data-id="77eacf638de54e189701af0120d439dc"><span><div id="77eacf638de54e189701af0120d439dc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#77eacf638de54e189701af0120d439dc" title="#TrustZone ARchive(TZAR)修补"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>#T</b>rust<b>Z</b>one <b>AR</b>chive(TZAR)修补</span></span></h4><div class="notion-text notion-block-1300c8dce27b4b10b68456d808b280f4">首先需要了解<code class="notion-inline-code"><b>T</b></code><code class="notion-inline-code">rust</code><code class="notion-inline-code"><b>Z</b></code><code class="notion-inline-code">one </code><code class="notion-inline-code"><b>AR</b></code><code class="notion-inline-code">chive</code> <code class="notion-inline-code"><b>TZAR</b></code>分区镜像的格式</div><div class="notion-text notion-block-ae578f578892465d8b72e5070cc16d2c">提取<code class="notion-inline-code"><b>tzar.img</b></code>镜像后需要进行简单的处理，即去除三星镜像的固定格式，这里去除到<code class="notion-inline-code">0x204</code> ，剩余部分即为镜像的实际内容部分，但是还需要进行一次<code class="notion-inline-code">lz4</code>解压才能得到真正的内容。需要注意的是这里的lz4<code class="notion-inline-code">magic number</code>为<code class="notion-inline-code">0x184c2102</code>，也就是旧(<code class="notion-inline-code">legacy</code>)的格式，其中<code class="notion-inline-code">0x002e2781</code>是压缩的字节，要从<code class="notion-inline-code">0x20C</code>开始(因为<code class="notion-inline-code">lz4</code>头部占8字节)往后数<code class="notion-inline-code">0x002e2781</code> 结束，取这部分数据作为lz4，结尾还有一些其他数据不在解压的范畴。然后使用脚本以特定的格式解压文件能得到完整的文件目录和结构<div class="notion-text-children"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-a8a71ef758f74939b9d7139284362c16"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F8c55aba0-291f-4a15-af46-822e1d029e2f%2FUntitled.png?table=block&amp;id=a8a71ef7-58f7-4939-b9d7-139284362c16&amp;t=a8a71ef7-58f7-4939-b9d7-139284362c16&amp;width=680&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-6b74d9c7e24d40babbea3bfb90862f49">解压后即可找到<code class="notion-inline-code">root_task</code> 等文件内容。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-994ff1562fc548c0989cecac416361b2"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F49ae4019-a7ff-4427-a141-664307019a4d%2FUntitled.png?table=block&amp;id=994ff156-2fc5-48c0-989c-ecac416361b2&amp;t=994ff156-2fc5-48c0-989c-ecac416361b2&amp;width=687.484375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></div><div class="notion-text notion-block-e56ed099e5bc483b9f1c6f094a8f4169">修改<code class="notion-inline-code">root_task</code>的汇编相当于直接在特殊归档文件之上进行修改，修改完成之后重新使用<code class="notion-inline-code">lz4 -l -9 tzar tzar_new</code>进行压缩，然后重新打包进入<code class="notion-inline-code">tzar</code>分区镜像中，这里还需要处理联发科镜像的固定格式的问题。因为<code class="notion-inline-code">lz4</code>重新压缩后和原本的压缩件大小不一致，但是联发科镜像固定格式中存在长度字段，那么在重新打包时必须要修改分区字段，这样才能使其成功加载。</div><div class="notion-text notion-block-d8f44abc5dd24900941e043baf71d81c">联发科镜像头部定义如下，需要修改的就是<code class="notion-inline-code">dsize</code> 字段，这个字段指明了分区的大小，但是不包括头部的<code class="notion-inline-code">512</code>字节。</div><div class="notion-text notion-block-8a5232aeb49242e1a576b910ef8e22e9">也就是下图中的<code class="notion-inline-code">0x2E917B</code> 需要根据新的压缩部分的大小变化进行修改</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ec323c282dd54e4b8f8ed39f2581e272"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fa4f59e1d-1990-49ff-911f-b3fd0f12f85c%2FUntitled.png?table=block&amp;id=ec323c28-2dd5-4e4b-8f8e-d39f2581e272&amp;t=ec323c28-2dd5-4e4b-8f8e-d39f2581e272&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-1188391e38ea4d2cb8d1f7fdf22c27b9"><code class="notion-inline-code">patch</code>的完整脚本如下，输出镜像为<code class="notion-inline-code">tzar_new.img</code> 如果刷写后日志有<code class="notion-inline-code"> [tzar] start sp, ret=-22</code> 就说明<code class="notion-inline-code">tzar</code>镜像格式有问题。</div><div class="notion-text notion-block-9715efea66ac413e9ab15378370fc6ef">然后修补tzar，主要修补其中的<code class="notion-inline-code">root_task</code> 中的<code class="notion-inline-code">ta_pkg_verify</code> 调用，将其patch掉，patch为<code class="notion-inline-code">MOV W0, #0</code> ，修补方法就是直接修补在<code class="notion-inline-code">lz4</code>解压后的<code class="notion-inline-code">tzar</code> ，然后重新<code class="notion-inline-code">lz4 -l -9 tzar tzar_new</code>压缩，然后运行上面的脚本打包为<code class="notion-inline-code">tzar_new.img</code></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-cab27a51e9df45d79ee98781594dd807"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff983d724-356f-4e55-be25-8fb6a9a39e2e%2FUntitled.png?table=block&amp;id=cab27a51-e9df-45d7-9ee9-8781594dd807&amp;t=cab27a51-e9df-45d7-9ee9-8781594dd807&amp;width=2896&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-6cf1aaf77811450eba5d3e854eb4a8f2"> </div><div class="notion-text notion-block-3e09523b2ecc43b7a8bf58d52917878f">刷入修补后的tzar开机瞬间关机，查看日志提示<code class="notion-inline-code"><b>hash mismatch</b></code>，就说明已经成功加载<code class="notion-inline-code">tzar</code>了，只是<code class="notion-inline-code">tee1</code>中的<code class="notion-inline-code">userboot</code>还对<code class="notion-inline-code">tzar</code>进行了校验，这就需要patch tee1。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-8800c33da2dd467ca4ed136c535db30e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F5d752591-b0ae-425d-b60b-c3bfbcda4957%2FUntitled.png?table=block&amp;id=8800c33d-a2dd-467c-a4ed-136c535db30e&amp;t=8800c33d-a2dd-467c-a4ed-136c535db30e&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-c4a72c7c0685409e81b3c354109754d6"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-2d1e5bf711754b9d872d1c4ec599a9af" data-id="2d1e5bf711754b9d872d1c4ec599a9af"><span><div id="2d1e5bf711754b9d872d1c4ec599a9af" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2d1e5bf711754b9d872d1c4ec599a9af" title="#Trusted execution environment1 (tee1)修补"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#Trusted execution environment1 (tee1)修补</span></span></h4><div class="notion-text notion-block-745b0f71db8d4af4aa0fc2f307ae44e9">接上节，已经成功加载<code class="notion-inline-code">tzar</code>了，只是<code class="notion-inline-code">tee1</code>中的<code class="notion-inline-code">userboot</code>还对<code class="notion-inline-code">tzar</code>进行了校验。从tee1分区镜像中能够直接脱出一个<b>ARM 64 ELF</b>文件。查找字符串引用，patch <code class="notion-inline-code">memcmp</code>的参数。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2bdce5e2b4b24b2e9280b12c3a4e7185"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F99156485-2156-4fda-9de5-db969a136cc0%2FUntitled.png?table=block&amp;id=2bdce5e2-b4b2-4b2e-9280-b12c3a4e7185&amp;t=2bdce5e2-b4b2-4b2e-9280-b12c3a4e7185&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-4dfb05f7a99e457eaa9bf0e2d65119dd">直接赋使第一个参数和第二个参数一致绕过检测。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-113d0c9db420463ca5fc8d3135aa6938"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F4dce61ce-8bda-4c5f-914c-4f70df06653b%2FUntitled.png?table=block&amp;id=113d0c9d-b420-463c-a5fc-8d3135aa6938&amp;t=113d0c9d-b420-463c-a5fc-8d3135aa6938&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-b5826a560d85434a9aa5747039b4de5b">修补的方法就是直接在tee1.img中找对应的汇编改掉就行，因为tee1.img中的该elf并未进行任何加密或压缩处理。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-0efdca7ca6574c98aa4b39abaa755ed0"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F48cc1171-14d9-44c1-9387-c8cd265ba9d9%2FUntitled.png?table=block&amp;id=0efdca7c-a657-4c98-aa4b-39abaa755ed0&amp;t=0efdca7c-a657-4c98-aa4b-39abaa755ed0&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-639e41fe893b41f892daaeea0c6b0a1f" data-id="639e41fe893b41f892daaeea0c6b0a1f"><span><div id="639e41fe893b41f892daaeea0c6b0a1f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#639e41fe893b41f892daaeea0c6b0a1f" title="6. Patching Gatekeeper"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">6. <b>Patching Gatekeeper</b></span></span></h3><div class="notion-text notion-block-3b7ba07d63a34dd6b40d657828a3e447">到这里就是最关键的一步，前面提到<b>修改</b><code class="notion-inline-code"><b>Gatekeeper</b></code><b> 使其校验永远成功，永远返回AuthToken，这样</b><code class="notion-inline-code"><b>KeyMaster</b></code><b> 也会解密密钥，只需要在第一次解密后Hook即可获取到第一次解密后的密文，进而完全解密。</b></div><div class="notion-blank notion-block-3e5d87144488415ab2b3190c55ac2643"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-e74cd3f15d0e4f26b9c6edeaa185e2ee"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F6e8dd568-0201-43ec-8107-9d92934be82b%2FUntitled.png?table=block&amp;id=e74cd3f1-5d0e-4f26-b9c6-edeaa185e2ee&amp;t=e74cd3f1-5d0e-4f26-b9c6-edeaa185e2ee&amp;width=708&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-9f75dd99509241e8b9b194c7974676b4">找到<code class="notion-inline-code"><b>Gatekeeper</b></code><b> TA中的相关逻辑，下面的函数是在计算HMAC，查找其引用</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-48a4c2b6b4484e0d9d501b3c6a778dfc"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fdcc1176a-448b-41d4-b47c-719ff93c6539%2FUntitled.png?table=block&amp;id=48a4c2b6-b448-4e0d-9d50-1b3c6a778dfc&amp;t=48a4c2b6-b448-4e0d-9d50-1b3c6a778dfc&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-6686d6cca87542e3819468b96a595c93">找到前面有一个<code class="notion-inline-code">MemCompare</code>的调用，直接修改，使其前两个参数一致。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-d397698390054adc8187ef0d1a23203c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F39a1741f-682e-4a28-882a-4e210124c2da%2FUntitled.png?table=block&amp;id=d3976983-9005-4adc-8187-ef0d1a23203c&amp;t=d3976983-9005-4adc-8187-ef0d1a23203c&amp;width=2059&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-a4fdedce6d0f4733ac03ecaf77de7661">在二进制层面的修补如下</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-a3c87a2a4e904ae4b90dccbbc2301261"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fe6477dc1-2947-4bbf-bfed-555a1efc8cb2%2FUntitled.png?table=block&amp;id=a3c87a2a-4e90-4ae4-b90d-ccbbc2301261&amp;t=a3c87a2a-4e90-4ae4-b90d-ccbbc2301261&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-f5f3729f14644100bb9a58c764c5dc9c">修补完成后就可以直接使用较高的权限覆盖<code class="notion-inline-code">/vendor/tee/</code>下面的二进制文件吗？答案是否定的，因为<code class="notion-inline-code">/vendor</code>目录是只读的，为了更加安全便捷的替换，采用动态挂载的方式。即使用<code class="notion-inline-code">mount</code> 挂载修改后的TA到目标挂载点。这就需要探究<code class="notion-inline-code">Android boot</code> 的修补了，顺便还可以root设备，获取密钥相关文件。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-71c6f556d8594d868cc55a95ff78f355" data-id="71c6f556d8594d868cc55a95ff78f355"><span><div id="71c6f556d8594d868cc55a95ff78f355" class="notion-header-anchor"></div><a class="notion-hash-link" href="#71c6f556d8594d868cc55a95ff78f355" title="7. Patch Android boot"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">7. Patch Android boot</span></span></h3><div class="notion-blank notion-block-9c48a080f05d42cc94def5383d4a33f4"> </div><div class="notion-text notion-block-5be1f8cdc87c47ada946dbca8d02f2c3">为了实现下面两个目标，就需要<code class="notion-inline-code">ROOT</code>设备：</div><ul class="notion-list notion-list-disc notion-block-ca0d9889865e42709986907dc0ddd7b2"><li>获取<code class="notion-inline-code">/data/system_de/0/spblob</code>下的文件，并且由于需要Hook，所以采用<code class="notion-inline-code">frida</code>来Hook <code class="notion-inline-code">system_server</code></li></ul><ul class="notion-list notion-list-disc notion-block-2f1a15b72c3e4ea59f0ab71a3c0355ae"><li>动态挂载文件以实现替换TA</li></ul><div class="notion-blank notion-block-f80e26db79c94aaaafcb7d2a28597e98"> </div><div class="notion-text notion-block-eb7d04cd7b3044dc9685824d85008c82">为了方便直接使用成熟的ROOT方案Magisk，但是不是开箱即用的，我们需要对其进行一些修改以适应我们的攻击场景：</div><ul class="notion-list notion-list-disc notion-block-9836fca77a26450ea450d30a1c070212"><li><b>在PC设备上修补</b><code class="notion-inline-code"><b>boot.img</b></code><b> ，</b>Magisk原本支持在设备上的Magisk App内对boot.img的修补，但是攻击场景的设备屏幕未解锁且不能安装App，必须在外部设备实现修补。</li></ul><ul class="notion-list notion-list-disc notion-block-d55a6b8f8c1d4cb3800246c9827ed202"><li><b>必须在未解锁屏幕的情况下获取</b><code class="notion-inline-code"><b>adb shell</b></code>，一般情况下获取<code class="notion-inline-code">adb shell</code>需要手动打开开关并且授权相应设备访问权限，在屏幕未解锁的情况下无法开启调试选项以及点击授权。</li></ul><ul class="notion-list notion-list-disc notion-block-b167b0607c634a859ce6a5d485de1e28"><li><b>adb shell必须能够直接获取root权限而不需要任何点击允许</b>，在现成的Magisk方案中，授权应用使用root权限需要用户手动点击弹窗以允许，但是在屏幕未解锁的情况下无法点击。</li></ul><ul class="notion-list notion-list-disc notion-block-138e348d88a242fb9f235c85db3456fd"><li><b>实现对TA的动态挂载</b></li></ul><div class="notion-blank notion-block-ce737a3eeeff491da23060ff130a26e1"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-f57b75bb7bf640b2ac7bc1b2794a8f67" data-id="f57b75bb7bf640b2ac7bc1b2794a8f67"><span><div id="f57b75bb7bf640b2ac7bc1b2794a8f67" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f57b75bb7bf640b2ac7bc1b2794a8f67" title="#Magisk boot设备外修补"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#Magisk boot设备外修补</span></span></h4><div class="notion-text notion-block-15466ff17fc346128f2b01b57c89cb6b">编译<code class="notion-inline-code">Magisk</code>，将编译后的部分产物移动到工作目录，除此之外还需要移动<code class="notion-inline-code">scripts</code> 目录下的<code class="notion-inline-code">util_functions.sh</code> 和<code class="notion-inline-code">boot_patch.sh</code> </div><div class="notion-text notion-block-d09aba699aba4bb080980ce7ea00d495">修改<code class="notion-inline-code">util_functions.sh</code>脚本的内容，因为里面含有一些在设备上才能执行的命令，直接强制指定即可。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-ffce4bbdbdaf409189afdf26bb8d07a0"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F785070e9-7b88-43a3-ae5d-b4e8d8f91537%2FUntitled.png?table=block&amp;id=ffce4bbd-bdaf-4091-89af-df26bb8d07a0&amp;t=ffce4bbd-bdaf-4091-89af-df26bb8d07a0&amp;width=363.9940490722656&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-3dffbeb7dbf04cde86985e13dbda312e">修改<code class="notion-inline-code">boot_patch.sh</code> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3dca6049cbaa49c8bee3108c6892504e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F533efd99-0bc2-44aa-8559-397b2b374e16%2FUntitled.png?table=block&amp;id=3dca6049-cbaa-49c8-bee3-108c6892504e&amp;t=3dca6049-cbaa-49c8-bee3-108c6892504e&amp;width=709.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-422b0ea178314c55b6f397be138e311c"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-c672720b7eda40bf82184038bca2f0a0" data-id="c672720b7eda40bf82184038bca2f0a0"><span><div id="c672720b7eda40bf82184038bca2f0a0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#c672720b7eda40bf82184038bca2f0a0" title="#开机自启adb shell"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#开机自启adb shell</span></span></h4><div class="notion-text notion-block-9f2502909d554e729e550988b72911b4">在<code class="notion-inline-code">native/src/core/daemon.cpp</code>的<code class="notion-inline-code">daemon_entry</code> 设置<code class="notion-inline-code">ro.debuggable=1</code>以开启adb，设置<code class="notion-inline-code">ro.adb.secure=0</code> 以禁用adb的校验，从而不需要任何授权使用adb</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-19aa36290c54423eaf4b05f8ac0033ec"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F59f09a7f-45e8-4596-be08-21a81eb59b63%2FUntitled.png?table=block&amp;id=19aa3629-0c54-423e-af4b-05f8ac0033ec&amp;t=19aa3629-0c54-423e-af4b-05f8ac0033ec&amp;width=3212&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2665deaeefed40738de37b9746436041">除此之外，由于设置了<code class="notion-inline-code">ro.adb.secure=0</code> ，在重启adbd时会出现<code class="notion-inline-code">selinux</code>拒绝的问题，需要在<code class="notion-inline-code">native/src/init/selinux.cpp</code> 的<code class="notion-inline-code">hijack_sepolicy</code> 中添加一些权限的允许规则，否则<code class="notion-inline-code">adbd</code>重启会失败</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-57071fb3169f47c19df97d8307754cc6"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F78f90505-4bb3-4b5f-b9ef-21a38af17d52%2FUntitled.png?table=block&amp;id=57071fb3-169f-47c1-9df9-7d8307754cc6&amp;t=57071fb3-169f-47c1-9df9-7d8307754cc6&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-46763ba2c1e14f7a95965cf3827bb2d9"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-3ce6ceb55774480d9f9ad73da1cba32e" data-id="3ce6ceb55774480d9f9ad73da1cba32e"><span><div id="3ce6ceb55774480d9f9ad73da1cba32e" class="notion-header-anchor"></div><a class="notion-hash-link" href="#3ce6ceb55774480d9f9ad73da1cba32e" title="#默认允许root权限授权"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#默认允许root权限授权</span></span></h4><div class="notion-text notion-block-6c85f1fca1af444cae054fb3f0b3dbac">注释掉<code class="notion-inline-code">native/src/core/daemon.cpp</code>的<code class="notion-inline-code">handle_request</code> 中部分权限拒绝代码</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-fb5b7eec4b2e4e3e9e665ceb2fb06b18"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fa8cfd0ab-0818-4600-89d7-2a62ede62fb7%2FUntitled.png?table=block&amp;id=fb5b7eec-4b2e-4e3e-9e66-5ceb2fb06b18&amp;t=fb5b7eec-4b2e-4e3e-9e66-5ceb2fb06b18&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-9a012aaab12d4566add23779c9a45354">注释掉<code class="notion-inline-code">native/src/core/su/su_daemon.cpp</code>的 <code class="notion-inline-code">su_daemon_handler</code> 中的部分代码，默认允许授权。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-f689a3f089914c06adf6e27c36a95fef"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Feb075907-11dd-4085-8032-0cb617c4ae80%2FUntitled.png?table=block&amp;id=f689a3f0-8991-4c06-adf6-e27c36a95fef&amp;t=f689a3f0-8991-4c06-adf6-e27c36a95fef&amp;width=3270&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-7c104c5d86964ad1a2d794480b6eb009"> </div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-85aea5a9fc2942e79fdc9182c9bda3c0" data-id="85aea5a9fc2942e79fdc9182c9bda3c0"><span><div id="85aea5a9fc2942e79fdc9182c9bda3c0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#85aea5a9fc2942e79fdc9182c9bda3c0" title="#TA的动态挂载"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">#TA的动态挂载</span></span></h4><div class="notion-text notion-block-843b3a19468f4d1599eb7dae871ae86b">首先在<code class="notion-inline-code">native/src/init/rootdir.cpp</code> 中的<code class="notion-inline-code">patch_ro_root</code>添加部分代码用于挂载SPU分区，首先<code class="notion-inline-code">makedev</code> 和<code class="notion-inline-code">xmknod</code>创建设备节点，然后将其挂载到根目录，<code class="notion-inline-code">magic_mount</code> 会暂时的将同样目录下的文件挂载到对应的位置，但是这在后面会被取消挂载，需要再次进行挂载。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-21e6a44a15114825af9bef2bb2df3113"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F4bd544a5-259a-476c-a2c2-121cdadde7a5%2FUntitled.png?table=block&amp;id=21e6a44a-1511-4825-af9b-ef2bb2df3113&amp;t=21e6a44a-1511-4825-af9b-ef2bb2df3113&amp;width=3265&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-8f7116b07d6f40a883e51b0254e2293f">在<code class="notion-inline-code">native/src/core/bootstages.cpp</code> 的<code class="notion-inline-code">post_fs_data</code> 中添加<code class="notion-inline-code">load_ta</code>的调用，其挂载<code class="notion-inline-code">/spu/vendor/tee/</code> 下的可信二进制文件到<code class="notion-inline-code">/vendor/tee</code> 中，并且设置权限和<code class="notion-inline-code">Selinux</code>标签。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-10ee6a57e7f941d8b154456c3adcbe5c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F999da49b-a8b6-4c7a-a393-842d985d9a39%2FUntitled.png?table=block&amp;id=10ee6a57-e7f9-41d8-b154-456c3adcbe5c&amp;t=10ee6a57-e7f9-41d8-b154-456c3adcbe5c&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-9d73e59f22cc41e1a3be5513660839e3">对应的要在spu镜像中创建指定文件夹并且复制对应的二进制文件，然后刷入</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-65e773d55d844f58b8823521d3401723"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:363.9821472167969px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Ff386e7b2-6742-4181-80d4-1f0c66258419%2FUntitled.png?table=block&amp;id=65e773d5-5d84-4f58-b882-3521d3401723&amp;t=65e773d5-5d84-4f58-b882-3521d3401723&amp;width=363.9821472167969&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-c04d28c006a9442482e367fbefc0c78f"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-e9fe5e422b3d4a0a912ed00fd273af91" data-id="e9fe5e422b3d4a0a912ed00fd273af91"><span><div id="e9fe5e422b3d4a0a912ed00fd273af91" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e9fe5e422b3d4a0a912ed00fd273af91" title="8. 利用脚本和结果"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">8. 利用脚本和结果</span></span></h3><div class="notion-text notion-block-6aa77316a6e849d0938c4f2a5e8cf86a">刷入各种镜像</div><div class="notion-text notion-block-884f2c8f1e0c4d7497a5dc03748ef262"><b>Frida Hook</b>脚本如下</div><div class="notion-text notion-block-e07a79d695124cad852b5a0572dd7b54">在完成第一次解密后进行第二次解密，但是由于密码错误，出现异常，导致crash，但是已经获取到第一次解密后的结果<code class="notion-inline-code">intermediate</code> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-594b5f5bfbca4b3d845dd517d852e41e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fed964ad8-cdcf-4c2f-8e94-72e4cb9496b4%2FUntitled.png?table=block&amp;id=594b5f5b-fbca-4b3d-845d-d517d852e41e&amp;t=594b5f5b-fbca-4b3d-845d-d517d852e41e&amp;width=2347&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-03a0c757c9124e1a8b679aabbb04f353"><b>爆破成功获取密钥为2356</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2b41e897d5184b2388075b418807dc2e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F46e64015-50b8-4e81-a353-f0b33d2d79a5%2FUntitled.png?table=block&amp;id=2b41e897-d518-4b23-8807-5b418807dc2e&amp;t=2b41e897-d518-4b23-8807-5b418807dc2e&amp;width=708.0000610351562&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-7b5c7f80be384a3797034249e0852115"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-baf62f2ffffd47f6b765fb5e726c8262" data-id="baf62f2ffffd47f6b765fb5e726c8262"><span><div id="baf62f2ffffd47f6b765fb5e726c8262" class="notion-header-anchor"></div><a class="notion-hash-link" href="#baf62f2ffffd47f6b765fb5e726c8262" title="0x0X 参考"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">0x0X 参考</span></span></h2><ol start="1" class="notion-list notion-list-numbered notion-block-46c0f272d61b4a4281e985ad06c69f0d" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog.quarkslab.com/android-data-encryption-in-depth.html" target="_blank" rel="noopener noreferrer">https://blog.quarkslab.com/android-data-encryption-in-depth.html</a></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-7d1850ef86f94750937ab8b0eeffebce" style="list-style-type:decimal"><li><a class="notion-link" href="https://source.android.google.cn/docs/security/features/encryption/file-based?authuser=19&amp;hl=zh-cn" target="_blank" rel="noopener noreferrer">文件级加密 | source.android.google</a></li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-2ab5cef1f76841dcaa355ec12a54f480" style="list-style-type:decimal"><li><a class="notion-link" href="https://www.kernel.org/doc/html/latest/filesystems/fscrypt.html" target="_blank" rel="noopener noreferrer">文件系统级加密（fscrypt）| kernel.org</a></li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-595db10fb3e346c2b390ea73258ba453" style="list-style-type:decimal"><li><a class="notion-link" href="https://kernel.meizu.com/2018/07/12//android-p-fbe.html/" target="_blank" rel="noopener noreferrer">Android FBE</a></li></ol><ol start="5" class="notion-list notion-list-numbered notion-block-2b024391ddaf4e529ceff25b475040a8" style="list-style-type:decimal"><li><a class="notion-link" href="https://kernel.meizu.com/2018/07/12//android-p-fbe.html/" target="_blank" rel="noopener noreferrer">https://kernel.meizu.com/2018/07/12//android-p-fbe.html/</a></li></ol><ol start="6" class="notion-list notion-list-numbered notion-block-173b9773822c486993c34fc0024f096d" style="list-style-type:decimal"><li><a class="notion-link" href="https://vddcore.eu/loading-lk-img-from-mediatek-devices-into-ida-for-analysis" target="_blank" rel="noopener noreferrer">Loading lk.img from Mediatek devices into IDA for analysis</a></li></ol><ol start="7" class="notion-list notion-list-numbered notion-block-ae4b627052ca44fcae27c9a582135433" style="list-style-type:decimal"><li><a class="notion-link" href="https://www.synacktiv.com/sites/default/files/2022-04/THCON22_Android_Encryption.pdf" target="_blank" rel="noopener noreferrer">https://www.synacktiv.com/sites/default/files/2022-04/THCON22_Android_Encryption.pdf</a></li></ol><ol start="8" class="notion-list notion-list-numbered notion-block-3601e574532b428d9b93c7dda076026b" style="list-style-type:decimal"><li><a class="notion-link" href="https://github.com/flyleaf91/RaspberryPi/blob/ebe8ee63a036761f7c73dd2aa721a871d1e2f4c2/docs/0147_Android_AVB_vbmeta_public_key.md" target="_blank" rel="noopener noreferrer">Android AVB启动vbmeta如何确保安全？</a></li></ol><ol start="9" class="notion-list notion-list-numbered notion-block-f400f95586bc4941887a3c81401e9bbb" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog.r0rt1z2.com/patch-mediatek-bootloader-images-lk.html#patch-mediatek-bootloader-images-lk" target="_blank" rel="noopener noreferrer">修补联发科引导加载程序映像 (LK)</a></li></ol><ol start="10" class="notion-list notion-list-numbered notion-block-0c9369ff549d47f59aebad4ebe7807d6" style="list-style-type:decimal"><li><a class="notion-link" href="https://o0xmuhe.github.io/2022/11/23/%E8%AE%AE%E9%A2%98%E8%A7%A3%E8%AF%BB-MOSEC2022-MediAttack-break-the-boot-chain-of-MediaTek-SoC/" target="_blank" rel="noopener noreferrer">议题学习:MOSEC2022 MediAttack - break the boot chain of MediaTek SoC</a></li></ol><ol start="11" class="notion-list notion-list-numbered notion-block-100520ae5e06417ea3fe3adb0f3634d6" style="list-style-type:decimal"><li><a class="notion-link" href="https://www.cnblogs.com/wen123456/p/14034493.html" target="_blank" rel="noopener noreferrer">MTK6735 pre-loader源代码分析</a></li></ol><ol start="12" class="notion-list notion-list-numbered notion-block-f4a90b265c6c4d4e8b287f2e732d6ce6" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog.csdn.net/u011784994/article/details/104898430" target="_blank" rel="noopener noreferrer">[MT6765]Preloader_流程分析--基于android 10</a></li></ol><ol start="13" class="notion-list notion-list-numbered notion-block-183847d9973940c19169ea1c5d3e8864" style="list-style-type:decimal"><li><a class="notion-link" href="https://zhuanlan.zhihu.com/p/538441745" target="_blank" rel="noopener noreferrer">MTK平台的seccfg分区和dm-verity error</a></li></ol><ol start="14" class="notion-list notion-list-numbered notion-block-d57bf7fa3d974f468b24d5eca169fa9a" style="list-style-type:decimal"><li><a class="notion-link" href="https://zhuanlan.zhihu.com/p/609572545" target="_blank" rel="noopener noreferrer">联发科通用解锁工具流程分析</a></li></ol><ol start="15" class="notion-list notion-list-numbered notion-block-839ea72fd5b84fae9a93d98efddca28f" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog.xhyeax.com/2019/09/13/android-kernel-reverse-anti-antidebug/" target="_blank" rel="noopener noreferrer">逆向修改安卓内核 x64 过TracerPID反调试</a></li></ol><ol start="16" class="notion-list notion-list-numbered notion-block-40afe4b8c17140a3bd48553cc4005a1d" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog4jimmy.com/2018/04/472.html" target="_blank" rel="noopener noreferrer">(原创)Android FBE加密源码分析（一）</a></li></ol><ol start="17" class="notion-list notion-list-numbered notion-block-ba2bf336fc03460da830bed6e4a91716" style="list-style-type:decimal"><li><a class="notion-link" href="https://github.com/topjohnwu/Magisk/issues/6230" target="_blank" rel="noopener noreferrer">Bootloop after ODIN flash (update) #6230</a></li></ol><ol start="18" class="notion-list notion-list-numbered notion-block-860271afe63d4b7891f9a3238c41f9c5" style="list-style-type:decimal"><li><a class="notion-link" href="https://media.defcon.org/DEF%20CON%2031/DEF%20CON%2031%20presentations/Christopher%20Wade%20-%20Physical%20Attacks%20Against%20Smartphones.pdf" target="_blank" rel="noopener noreferrer">https://media.defcon.org/DEF CON 31/DEF CON 31 presentations/Christopher Wade - Physical Attacks Against Smartphones.pdf</a></li></ol><ol start="19" class="notion-list notion-list-numbered notion-block-0f17dc84ab30453b92509354fa28102c" style="list-style-type:decimal"><li><a class="notion-link" href="https://security.stackexchange.com/questions/196230/connection-between-pin-password-and-encryption-keys-in-android/247954#247954" target="_blank" rel="noopener noreferrer">Connection between PIN/password and encryption keys in Android</a></li></ol><ol start="20" class="notion-list notion-list-numbered notion-block-0f3affac2266492298f4e27e157a0b24" style="list-style-type:decimal"><li><a class="notion-link" href="https://github.com/salvogiangri/KnoxPatch/issues/26" target="_blank" rel="noopener noreferrer">https://github.com/salvogiangri/KnoxPatch</a></li></ol><ol start="21" class="notion-list notion-list-numbered notion-block-f54fcc8ce4aa409981b1e364058d8af9" style="list-style-type:decimal"><li><a class="notion-link" href="https://allsoftwaresucks.blogspot.com/2019/05/reverse-engineering-samsung-exynos-9820.html" target="_blank" rel="noopener noreferrer">对三星 S10 TEEGRIS TrustZone OS 进行逆向工程</a></li></ol><ol start="22" class="notion-list notion-list-numbered notion-block-fef3196115024f9798f8c581ccb66496" style="list-style-type:decimal"><li><a class="notion-link" href="https://github.com/shakevsky/keybuster/blob/main/writeup.md" target="_blank" rel="noopener noreferrer">keybuster - writeup.md</a></li></ol><ol start="23" class="notion-list notion-list-numbered notion-block-3c00c40ab51044138a7224e6980c4ceb" style="list-style-type:decimal"><li><a class="notion-link" href="https://github.com/tcc0lin/awsome-magisk/blob/main/%E9%87%8D%E8%AF%BBMagisk%E5%86%85%E9%83%A8%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%822.md" target="_blank" rel="noopener noreferrer">https://github.com/tcc0lin/awsome-magisk/blob/main/重读Magisk内部实现细节2.md</a></li></ol><ol start="24" class="notion-list notion-list-numbered notion-block-a5a1b433e4404d8b8f64452b3f075498" style="list-style-type:decimal"><li><a class="notion-link" href="https://liwugang.github.io/2021/07/11/magisk_enable_adbr_root.html" target="_blank" rel="noopener noreferrer">Magisk 环境下增加 adb root 功能</a></li></ol><div class="notion-blank notion-block-8a98492145064b789d899173a393f457"> </div><blockquote class="notion-quote notion-block-2853fb9e9432802e9f7cd5dfb5c9d2af"><div>[!important]</div><div class="notion-text notion-block-2853fb9e94328011a62ded7a316253a7">由于设备是未解锁的（攻击场景就是未解锁设备），刷入boot镜像进行root会显示不允许刷入非官方的镜像。<b>所以可以直接patch LK中获取设备锁状态的部分，一般解锁后设备会自动擦除数据，为了避免数据被擦除也需要patch擦除数据的部分。</b></div><div class="notion-text notion-block-2853fb9e9432801f8795df0eaddc1a6b">但是更好的办法是直接patch 检查镜像的部分，即上面提到的authinfo ，但是随之而来的问题是如果不采用解锁的Patch方案，<b>刷入第三方REC镜像会导致开不了机并且也无法进入REC模式查看日志信息。</b></div><div class="notion-text notion-block-2853fb9e943280b69337cf17e79c8544">为了方便学习调试可以先直接给设备解锁，等到攻击验证阶段再把锁加回来，这样就不会出现因为没解锁导致的日志难以查看的问题。</div><div class="notion-text notion-block-2853fb9e94328056ac10dd68947e392b">下面的解锁内容属于题外话，前面提到的无法开机的原因是加密分区挂载失败，加密分区挂载失败就是因为设备安全验证没通过，所以为了方便直接处理<code class="notion-inline-code">authinfo</code> 即可，所以这部分仅当拓展。</div><div class="notion-text notion-block-2853fb9e9432804b8f28fa812b55d35c">在解锁状态下直接刷入magisk修补的boot会开机失败并且自动进入rec模式，原因是fs_mgr_mount_all 。尝试禁用vbmeta 也无效。刷入TWRP然后使用adb查看/proc/last_kmsg 发现其实也是挂载加密分区/data失败导致的问题，而本质是因为检测到设备损坏，和上面的结论一致，即安全检测未通过。解决方案就是patch 掉/vendor/tee/00000000-0000-0000-0000-4b45594d5354 (Keymaster)这个可信应用 ，使其认为设备是正常的，从而正常解密，后面修补部分详细展开。</div><div class="notion-text notion-block-2853fb9e943280e688bcec960351bb34">![[TEE安全/Android Data Encryption-从百草园Patch到三味书屋/attachments/Untitled 44.png]]</div></blockquote><div class="notion-text notion-block-2853fb9e943280c7a75ef12770adc149">联发科机型使用 <code class="notion-inline-code">seccfg</code>分区存储设备BL锁等状态关键信息，分区大小一般为<code class="notion-inline-code">8MB</code>，实际使用空间远小于此，<code class="notion-inline-code">1024</code>字节都用不完。其中<code class="notion-inline-code">MTK</code>定义的<code class="notion-inline-code">seccfg</code>头部结构仅为<code class="notion-inline-code">60B</code> ，包括28字节数据部分和32字节的校验部分。剩下的32位校验码因为使用了设备硬件相关的加密，除非设备密钥泄露否则没有办法脱机计算（实现可以参照<a class="notion-link" href="https://github.com/bkerler/mtkclient/blob/main/mtkclient/Library/Hardware/hwcrypto_sej.py" target="_blank" rel="noopener noreferrer">https://github.com/bkerler/mtkclient/blob/main/mtkclient/Library/Hardware/hwcrypto_sej.py</a>）。</div><ul class="notion-list notion-list-disc notion-block-2853fb9e943280ceb03fc7a264b09177"><li>如果设备已解锁，lock_state = 3</li></ul><ul class="notion-list notion-list-disc notion-block-2853fb9e9432809ab80ded984b0383c0"><li>如果设备未解锁，lock_state = 4或1</li></ul><div class="notion-text notion-block-2853fb9e943280368800d0fe465423d8">如下图提取设备中的seccfg分区，观察第0xc开始的四个字节，值为1符合未解锁的定义。但是mtkclient的解锁功能是Patch此处的两个DWORD ，也就是将dm_verity_state Patch为1为解锁，这样就会导致dm_verity 是校验失败的，查看mtkclient 源码此处的字段被解读为critical_lock_state ，通过逆向可以发现显然是dm_verity_state ，所以认为实现可能有问题。<b>而无论是通过mtkclient解锁还是Patch LK都需要擦除用户数据，因为默认keymaster是可信的，其检测到设备损坏后强制要求擦除数据。</b></div><div class="notion-text notion-block-2853fb9e9432807cb894c654da810c51">![[TEE安全/Android Data Encryption-从百草园Patch到三味书屋/attachments/Untitled 45.png]]</div><div class="notion-text notion-block-2853fb9e943280958cd9ff4386733cda">根据这些已知知识对LK符号进行恢复，能够发现seccfg_get_lock_state是获取设备锁状态的函数，通过读取的ROM内存偏移来识别。</div><div class="notion-text notion-block-2853fb9e9432801d9910f5a1fdfb1c0d">![[TEE安全/Android Data Encryption-从百草园Patch到三味书屋/attachments/Untitled 46.png]]</div><div class="notion-text notion-block-2853fb9e94328059944dece7d122148f">Patch该函数，使其a1读取的值永远为3，以实现使LK认为设备已经解锁，从而不对镜像进行检查。虽然能够进入rec模式，但是开机出现问题，这就和前面说的加密分区挂在失败是一个事情了，不再赘述。
![[TEE安全/Android Data Encryption-从百草园Patch到三味书屋/attachments/Untitled 47.png]]</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Magisk V26.1源码分析]]></title>
            <link>https://lleavesg.top//article/Magisk-src</link>
            <guid>https://lleavesg.top//article/Magisk-src</guid>
            <pubDate>Sun, 16 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[文章对MagiskV26.1 源码 进行了大致分析]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-2a55fd9308a24f0098df85fb16462603"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-blank notion-block-a1621a8666ab427ab0e49373eb7fb19f"> </div><div class="notion-blank notion-block-3ffd266f6e104d15b33fcb3c60c61c0a"> </div><div class="notion-table-of-contents notion-gray notion-block-17e2f343d1234b7bb369d788b7a305ba"><a href="#f64f226026484b34a0fc2bd677d53b48" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">一、正常Android启动流程</span></a><a href="#231446de6cb9443f96b5e299b99b5c1c" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">二、几种Boot方式</span></a><a href="#bf8b41b457f4425c97a60dc8c21f669f" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">三、boot_patch.sh打补丁</span></a><a href="#aed17fdbf4da4573998a0b3734a16a14" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">四、Magisk-Preinit预初始化</span></a><a href="#e65e68ffdb4b44c291cc68164add1fc9" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1.magisk劫持init第一阶段执行</span></a><a href="#84942fd63f384376aa4cf1fcbfb03da1" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. init第一阶段执行</span></a><a href="#96b012cac2fa4fb1ab1ba49e749ecb73" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">3. Magisk劫持init第二阶段执行</span></a><a href="#8a389d9a0a304d19a62225bbbc311458" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">4.  init第二阶段</span></a><a href="#dcf27694d17e48cfb26a7e62c1f8a0ce" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">5. 流程总结</span></a><a href="#49ec3e0386004187a8fc89e90adfa784" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">五、Magisk-post-fs-data</span></a><a href="#04b2186089d645ab9ca65cc611b7ab1d" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. init.rc</span></a><a href="#71d51a5d24a0453fbece84bab022e87c" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. magisk启动</span></a><a href="#da55c4db76494195a26730ca95f8c61a" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">六、Magisk-late_start </span></a><a href="#65ac55a88aec4e49aaafff59339d0169" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">七、Magisk-boot-complete</span></a><a href="#d85a3f329799445888bb62ab6eb02dd1" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">参考：</span></a></div><div class="notion-blank notion-block-8befe08c9d15443a8b21e59040aafd9f"> </div><div class="notion-callout notion-blue_background_co notion-block-0442bc52bfc4495494ed8ac93aa6dd2c"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text"><b>Magisk的Patch操作和实际的工作流程</b>涉及到Android启动的不同方法，<b>对不同设备不同系统有着不同的启动方式</b>，这是一个很复杂的问题，将会直接决定<b>Magisk的工作流程</b>，有时间需要进行细致分析。<span class="notion-red"><b>在这里仅给出一种实现方式的解析，其他类比起来看就行。</b></span></div></div><div class="notion-callout notion-blue_background_co notion-block-d899df442f654ffcbf4349ed6b84b113"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">测试设备为<b>RedMI Note7(lavender)，非A/B分区设备，刷入Android 12类原生系统。</b></div></div><div class="notion-blank notion-block-23554f9d412c4fff9a9fc284ca94b209"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-f64f226026484b34a0fc2bd677d53b48" data-id="f64f226026484b34a0fc2bd677d53b48"><span><div id="f64f226026484b34a0fc2bd677d53b48" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f64f226026484b34a0fc2bd677d53b48" title="一、正常Android启动流程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">一、正常Android启动流程</span></span></h3><div class="notion-text notion-block-26b702570f4d4ae9b93851de314d4068"><div class="notion-text-children"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-957d24f56c3f4c81ae1b470f36440638"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:57.5px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fda504a70-24ca-4486-ba96-8f282163c030%2FUntitled.png?table=block&amp;id=957d24f5-6c3f-4c81-ae1b-470f36440638&amp;t=957d24f5-6c3f-4c81-ae1b-470f36440638&amp;width=57.5&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></div><details class="notion-toggle notion-block-d1425f7e79a449c7853aca912c4e41ef"><summary>Step1 BootROM</summary><div><div class="notion-text notion-block-87f7e4b7dbae4067acd1c517e381728f">启动ROM代码从预先定义的位置开始执行。它将引导加载程序加载到RAM中并开始执行。</div><ul class="notion-list notion-list-disc notion-block-bedcbb8a0257446fa3de76356a4b71ef"><li>A.引导ROM代码将使用映射到ASIC上的一些物理球的系统寄存器来检测引导介质。这是为了确定在何处找到引导加载程序的第一阶段。</li></ul><ul class="notion-list notion-list-disc notion-block-e6c4d8f3f4c54ebdbd6f6271e85e1756"><li>B.一旦引导介质序列建立，引导ROM将尝试加载第一阶段的引导加载程序到内部RAM。一旦引导加载程序就位，引导ROM代码将执行跳转并继续在引导加载程序中执行。</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-c318c916749742048d29b468dd79c495"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F64ad6ee2-6e86-423a-93fa-ef9ffea7536e%2FUntitled.png?table=block&amp;id=c318c916-7497-4204-8d29-b468dd79c495&amp;t=c318c916-7497-4204-8d29-b468dd79c495&amp;width=794&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details><details class="notion-toggle notion-block-88ecdd4193a541efba42ac8dd01b9aff"><summary>Step2 BootLoader</summary><div><div class="notion-text notion-block-33234590eecf419e8c42a95ba35f324e">引导加载程序的执行分为两个阶段，第一阶段是检测外部RAM并加载程序以帮助第二阶段的执行。在第二阶段，引导加载程序设置网络、内存等，这些都需要运行内核。引导加载程序能够为特定目的向内核提供配置参数或输入。</div><ul class="notion-list notion-list-disc notion-block-b6fc10d1f75d4beeae5827ae3cbd3131"><li>A. 第一阶段引导加载程序将检测并设置外部RAM。</li></ul><ul class="notion-list notion-list-disc notion-block-b30acd31dee54014bf97023da8a64856"><li>B. 一旦外部RAM可用并且系统已准备好运行更重要的东西，第一阶段将加载主引导加载程序并将其放置在外部RAM中。</li></ul><ul class="notion-list notion-list-disc notion-block-c47011a365804881a80544079326943d"><li>C. 引导加载程序的第二阶段是第一个将运行的主要程序。它可能包含用于设置文件系统、附加内存、网络支持和其他事项的代码。在手机上，它还可能负责加载调制解调器CPU的代码并设置低级内存保护和安全选项。</li></ul><ul class="notion-list notion-list-disc notion-block-0f8d22bfa9b44ee5b7b64140a75d8f0c"><li>D. 一旦引导加载程序完成了任何特殊任务，它将寻找要引导的Linux内核。它将从引导介质（或其他依赖于系统配置的来源）加载内核并将其放置在RAM中。它还会将一些引导参数放置在内存中，供内核在启动时读取。</li></ul><ul class="notion-list notion-list-disc notion-block-8ab664cd290d4977853aa8e38386ae64"><li>E. 一旦引导加载程序完成，它将执行跳转到Linux内核，通常是一些解压缩例程，然后内核就承担了系统责任。</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-7d91e93487d647eaa1cd62a2c48b310e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F2da0e793-ba51-4731-89db-7b57b13f5aff%2FUntitled.png?table=block&amp;id=7d91e934-87d6-47ea-a1cd-62a2c48b310e&amp;t=7d91e934-87d6-47ea-a1cd-62a2c48b310e&amp;width=794&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-9e8d967720e54f3abbc5da883f2242e8"> </div></div></details><details class="notion-toggle notion-block-56d4c9e12e7d43d7ac04736c02acf9b0"><summary>Step3 Linux kernel</summary><div><div class="notion-text notion-block-16dfb205d0864b748eb7df6d073ef140">Linux内核在Android系统上的启动方式与其他系统类似。它会设置系统运行所需的所有内容，包括初始化中断控制器、设置内存保护、缓存和调度。</div><ul class="notion-list notion-list-disc notion-block-337b6aa9dd424a308fdcd2e2d5e0140b"><li>A. 一旦内存管理单元和缓存已经初始化，系统将能够使用虚拟内存并启动用户空间进程。</li></ul><ul class="notion-list notion-list-disc notion-block-623652ad8f0b47189b68480bc820aa2b"><li>B. 内核将在根文件系统中查找init进程（在Android开源树中的system/core/init目录下）并将其启动为初始的用户空间进程。</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3140250def2240f892bcd45ab0465dfa"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ffdf4e03d-9107-4e85-b595-f049a9e74205%2FUntitled.png?table=block&amp;id=3140250d-ef22-40f8-92bc-d45ab0465dfa&amp;t=3140250d-ef22-40f8-92bc-d45ab0465dfa&amp;width=794&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details><details class="notion-toggle notion-block-6ba37d046b5c428aad205ab7484875e1"><summary>Step4 Init Process</summary><div><div class="notion-text notion-block-643201effab844ec89b76fc2f2cc4e98">init是非常重要的第一个进程，可以说它是所有进程的祖先进程。init进程有两个责任：1. 挂载目录，如/sys，/dev，/proc等；2. 运行init.rc脚本。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-3cfcda18c65e4d03b008f48e24a1eac7"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ff8e49c53-00fc-487b-8745-d152a0d476bf%2FUntitled.png?table=block&amp;id=3cfcda18-c65e-4d03-b008-f48e24a1eac7&amp;t=3cfcda18-c65e-4d03-b008-f48e24a1eac7&amp;width=794&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details><details class="notion-toggle notion-block-84543750162945f7b51c4f0c6fc54ecd"><summary>Step5 Zygote and Dalvik(ART)</summary><div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-1823219f4ea44e93ac44491d9b0eab97"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fbf8e6c65-5faa-49b2-ab66-4aca0e6118d3%2FUntitled.png?table=block&amp;id=1823219f-4ea4-4e93-ac44-491d9b0eab97&amp;t=1823219f-4ea4-4e93-ac44-491d9b0eab97&amp;width=969&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-9eafd698ee1c419f9f438e2edaa12669"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fefad3c5f-82ad-4891-8020-a0c037dded52%2FUntitled.png?table=block&amp;id=9eafd698-ee1c-419f-9f43-8e2edaa12669&amp;t=9eafd698-ee1c-419f-9f43-8e2edaa12669&amp;width=794&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details><details class="notion-toggle notion-block-8d2bb09605934ee09151980265c0ca49"><summary>Step6 system server</summary><div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-449dc999f1864cb0808570817f7586a9"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F575554b0-7366-482f-8ada-170cd5ee8388%2FUntitled.png?table=block&amp;id=449dc999-f186-4cb0-8085-70817f7586a9&amp;t=449dc999-f186-4cb0-8085-70817f7586a9&amp;width=794&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details><div class="notion-blank notion-block-37c4c6d59a3a41709fc8a4596a574418"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-231446de6cb9443f96b5e299b99b5c1c" data-id="231446de6cb9443f96b5e299b99b5c1c"><span><div id="231446de6cb9443f96b5e299b99b5c1c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#231446de6cb9443f96b5e299b99b5c1c" title="二、几种Boot方式"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">二、几种Boot方式</span></span></h3><div class="notion-callout notion-blue_background_co notion-block-0805b4e2a1e544189f3774d2ce362436"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">由于测试机为<b>RedMI Note7(lavender)(非A/B分区设备，即A-only设备)，</b>即使刷入了Android12的类原生系统，但是其出场<b>Android版本API=28，即LV=28，设备属于第三类设备，</b>分区中没有包含有<code class="notion-inline-code"><b>ramdisk</b></code><b>，</b>但是后面会讲到<code class="notion-inline-code"><b>测试设备刚好是红米，幸运的是它居然可以接受手动添加到boot中的ramdisk</b></code><b>，但是Magisk 实际上不可能知道设备引导加载程序是否接受虚拟硬盘，因此假设始终通知用户使用恢复模式，因此在Magsik界面Ramdisk后面显示否。</b>
理论上来说测设设备启动是采用<b>MethodB：</b><span class="notion-red"><b> Legacy SAR</b></span>方式进行启动，<b>内核直接挂载到system分区作为根目录并且直接运行/init进行启动。通过后面日志分析也可以发现，</b><span class="notion-red"><code class="notion-inline-code"><b>[2.686814] magiskinit: LegacySARInit</b></code></span> 这里第一阶段进入了<span class="notion-red"><code class="notion-inline-code"><b>LegacySARInit</b></code></span><span class="notion-red"><b> </b></span>分支。因此本文重点分析这种启动方式，其次<span class="notion-red"><b>Method C</b></span>是现如今Android设备常规启动方式，因此也进行分析。</div></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-bf8b41b457f4425c97a60dc8c21f669f" data-id="bf8b41b457f4425c97a60dc8c21f669f"><span><div id="bf8b41b457f4425c97a60dc8c21f669f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#bf8b41b457f4425c97a60dc8c21f669f" title="三、boot_patch.sh打补丁"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">三、boot_patch.sh打补丁</span></span></h3><blockquote class="notion-quote notion-block-c66a59dc5bdb4e0d963c35eb8e759e8e"><div>在该Shell脚本中有如下代码，就是使用<b>magiskboot</b>对Android的<code class="notion-inline-code"><b>ramdisk</b></code>进行<b>patch</b>，<b>重点替换</b><code class="notion-inline-code"><b>init</b></code><b>为</b><code class="notion-inline-code"><b>magiskinit</b></code><b> ，</b>然后创建一些文件夹以用于临时存放<b>Magisk</b>相关的文件。</div><div class="notion-text notion-block-4353eae63f3443e49554acdc9845f44f">在绝大多数设备上，Magisk可以通过直接对<code class="notion-inline-code"><b>boot</b></code>分区进行补丁操作或在自定义Recovery中刷入zip包来安装。这是因为这些设备的分区中都包含有<code class="notion-inline-code"><b>ramdisk</b></code>，可以在其中安装Magisk。</div><div class="notion-text notion-block-ea94a4d53d174a329afacf63af938967">但是，在某些设备类型<b>（Type III）</b>中，因为<code class="notion-inline-code"><b>boot分区</b></code>中没有包含有<code class="notion-inline-code"><b>ramdisk</b></code>，因此无法在其中安装Magisk。在这种情况下，Magisk只能安装到<code class="notion-inline-code"><b>recovery</b></code>分区中，而不能直接安装到<code class="notion-inline-code"><b>boot</b></code>分区中。这些设备在正常启动时无法访问Magisk，需要每次重启都进入<code class="notion-inline-code"><b>recovery</b></code>模式才能使用Magisk。</div><div class="notion-text notion-block-65c99b1fb6474e11b75a00503b95fc90">在下面的节选部分脚本中，除了使用<span class="notion-red"><code class="notion-inline-code"><b>magiskboot</b></code></span> 替换<code class="notion-inline-code"><b>init→magiskinit</b></code>、创建overlay.d文件夹、放入magisk守护进程和壳APP并且进行备份外，还需要将<code class="notion-inline-code"><b>skip_initramfs</b></code>修改为<code class="notion-inline-code"><b>want_initramfs</b></code><b>。</b></div><div class="notion-text notion-block-e394e35d1dc24b9a9d17e38630857f46">linux调用<code class="notion-inline-code"><b>populate_rootfs</b></code>默认会并加载boot分区自带的<code class="notion-inline-code"><b>ramdisk（recovery）</b></code>，但如果<code class="notion-inline-code">do_skip_initramfs</code>被设置为1，则会调用<code class="notion-inline-code"><b>default_rootfs</b></code>生成一个极小的rootfs，并在其中创建出<code class="notion-inline-code">/dev/console</code>文件,除此之外没有其他文件。正因如此，当设备正常启动到系统时读取<code class="notion-inline-code"><b>/proc/cmdline</b></code>，其中会出现<code class="notion-inline-code"><b>skip_initramfs</b></code><b> </b>的参数，但是启动到recovery时不会有此参数。</div><div class="notion-callout notion-blue_background_co notion-block-08e21d8a2ab4437791b64abaaebdb566"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text">重点来了，某些Type III设备的引导程序仍然会接受手动添加到boot中的<code class="notion-inline-code"><b>ramdisk</b></code>，例如部分小米手机，但许多设备不会，例如三星S10，Note 10等。<code class="notion-inline-code"><b>测试设备刚好是红米，它居然可以接受手动添加到boot中的ramdisk，因此我们无需每次重启到rec模式才能使用Magisk,可以直将Magisk装入ramdisk。</b></code><b>(根据看雪论坛“残页”大佬的说法，小米Type III设备都可以直接修补boot.img，而非需要修补Recovery )</b></div></div></blockquote><blockquote class="notion-quote notion-block-c7cf362df87f4b739818ca08bc3d51e8"><div><b>boot_patch.sh</b></div><div class="notion-text notion-block-7e7eca30b9b1497cb4c999038cb9671a"><code class="notion-inline-code">boot_patch.sh</code>脚本将kernel中的<code class="notion-inline-code"><b>skip_initramfs</b></code>修改为<code class="notion-inline-code"><b>want_initramfs</b></code>，因为如果设置了<code class="notion-inline-code"><b>skip_initramfs</b></code>代表着Method B启动方式中进入到正常系统而不是<code class="notion-inline-code">recovery</code>，magisk也就无法启动了，修改为<code class="notion-inline-code"><b>want_initramfs</b></code>屏蔽掉<code class="notion-inline-code"><b>skip_initramfs</b></code>让系统可以从恢复模式中的ramdisk中启动。</div><div class="notion-callout notion-blue_background_co notion-block-5fba1a6a54094d1f9c505f7344766a2e"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text">但是需要注意：<code class="notion-inline-code"><b>skip_initramfs</b></code>修改为<code class="notion-inline-code"><b>want_initramfs</b></code>的操作发生了两次，<b>但是patch的位置不同，目的也不同。</b><div class="notion-text notion-block-bf3afdac99b54ba683d747d36859dbf1">第一次发生在<code class="notion-inline-code"><b>./magiskboot dtb $dt patch; then</b></code><b> 即通过magiskboot对dtb进行patch，在其中调用</b><code class="notion-inline-code">dtb_patch</code><b>对dtb中的</b><code class="notion-inline-code"><b>skip_initramfs</b></code>修改为<code class="notion-inline-code"><b>want_initramfs </b></code><b> ，但是注意这里修改的目的是因为</b><code class="notion-inline-code"><b>三星部分机型不支持 SAR 但是 cmdline 里却有这个参数，正常启动的时候内核会直接忽略，但是 Magisk 会因为有这个参数而判断这台设备是 Legacy SAR，进入 Legacy SAR 流程导致手机循环启动。这里 Patch 的本质是不让 magisk 自己看到错误的参数 https://github.com/topjohnwu/Magisk/pull/4788</b></code><b>(看雪论坛“残雪”)。</b></div><div class="notion-text notion-block-4ebd4277d36c4185abfef070f318ef9f">第二次Patch才是对kernel内部<code class="notion-inline-code"><b>skip_initramfs</b></code><b> </b>进行修改，从而使得在<code class="notion-inline-code"><b>legacy SAR devices</b></code>设备中Magisk能正常启动。</div></div></div></blockquote><blockquote class="notion-quote notion-block-bb40db7b469349d984b70c0a970efeb0"><div><b>从boot.img解出的kernel来看，确实对skip进行了patch，patch为want</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-39012be009b742f39a7a477d52ad64cc"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F999f2589-6f1f-4555-9075-0a86bb21b0fc%2FUntitled.png?table=block&amp;id=39012be0-09b7-42f3-9a7a-477d52ad64cc&amp;t=39012be0-09b7-42f3-9a7a-477d52ad64cc&amp;width=674.9921875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></blockquote><div class="notion-callout notion-blue_background_co notion-block-98fcef2280ca42029e181570cb0d17b7"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text">因为测试设备是小米手机，所以magisk直接修补boot.img，<b>无法对“Magisk修补Recovery分区的ramdisk，每次启动从rec模式启动，然后init执行再启动到系统”这一情况进行测试</b>。<code class="notion-inline-code">摘自参考1</code>：<ul class="notion-list notion-list-disc notion-block-a0398153cf9d47d98a193ae829429f6f"><li>如果要启动的是正常系统,直接进入无magisk的原始系统。</li></ul><ul class="notion-list notion-list-disc notion-block-7e12ff6442ec41718e4f093fa2d78a80"><li>如果要启动的是recovery模式,会导致<code class="notion-inline-code"><b>magiskinit</b></code>执行，<code class="notion-inline-code"><b>magiskinit</b></code>读取<code class="notion-inline-code"><b>/.backup/.magisk</b></code>配置文件得到<code class="notion-inline-code"><b>RECOVERYMODE=true</b></code>知道它自己是在recovery分区启动,然后调用<code class="notion-inline-code"><b>check_key_combo()</b></code>判断是否长按音量键上,如果长按则进入<b>REC系统，</b>否则进入到<b>带有Magisk的正常系统</b>。进入magisk系统仍然进入到<code class="notion-inline-code"><b>init = new LegacySARInit(argv, &amp;config);</b></code>进入recovery模式会进入<code class="notion-inline-code"><b>init = new RecoveryInit(argv, &amp;config);</b></code></li></ul><div class="notion-text notion-block-5965a7c5d1954cc4888afee97e38a3db">这部分在Magisk官方安装文档中也有提及：<a class="notion-link" href="https://topjohnwu.github.io/Magisk/install.html#magisk-in-recovery" target="_blank" rel="noopener noreferrer">Installation | Magisk (topjohnwu.github.io)</a></div></div></div><div class="notion-blank notion-block-7732bc3f68d04592a7c27eb619f23096"> </div><div class="notion-blank notion-block-af5fd2e4f445436380a5b62b991721b4"> </div><div class="notion-callout notion-blue_background_co notion-block-2982fe121e5f4d08863c8b8f7860ab89"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text">Magisk启动整体分为三个阶段
<b>Pre-Init→post-fs-data→late_start→boot_complete</b></div></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-aed17fdbf4da4573998a0b3734a16a14" data-id="aed17fdbf4da4573998a0b3734a16a14"><span><div id="aed17fdbf4da4573998a0b3734a16a14" class="notion-header-anchor"></div><a class="notion-hash-link" href="#aed17fdbf4da4573998a0b3734a16a14" title="四、Magisk-Preinit预初始化"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">四、Magisk-<code class="notion-inline-code">Preinit预初始化</code></span></span></h3><blockquote class="notion-quote notion-block-0b260de269a04153b1f68acf2e380505"><div>源码位于<code class="notion-inline-code"><b>native/src/init/init.cpp</b></code><b> ,由于在补丁阶段将magiskinit替换为init，所以系统启动时会启动实际上的magiskinit。</b>然后是使用<b>Debug版本</b>的<b>Magisk</b>进行测试时<b>，</b>系统在启动时的日志输出(<span class="notion-red"><b>主要关注标红加粗位置</b></span>)，通过输出分析具体的流程。</div></blockquote><div class="notion-blank notion-block-febeeb8f4b834c2893cd033d670c1b1d"> </div><div class="notion-callout notion-blue_background_co notion-block-6b92de046c6746b9a1fc2dc998807844"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text"><span class="notion-red"><b>以下提到的第一阶段与第二阶段是Magiskinit的阶段而言，而非系统init正常的阶段，千万不要搞混了</b></span></div></div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-e65e68ffdb4b44c291cc68164add1fc9" data-id="e65e68ffdb4b44c291cc68164add1fc9"><span><div id="e65e68ffdb4b44c291cc68164add1fc9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#e65e68ffdb4b44c291cc68164add1fc9" title="1.magisk劫持init第一阶段执行"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1.magisk劫持init第一阶段执行</span></span></h4><blockquote class="notion-quote notion-block-9e422df64e2641eda1cc7e4eeae2f462"><div><b>如果按MethodB的方法启动，</b>整个<code class="notion-inline-code"><b>init过程</b></code>实际上分为<b>两个阶段</b>，第一阶段直接执行<code class="notion-inline-code"><b>magiskinit</b></code>，即<code class="notion-inline-code"><b>劫持了init</b></code><b> ，</b>在main内存在一个<code class="notion-inline-code"><b>if else判断</b></code><b> ，如果是第一个阶段则会执行到else内部。如果按MethodB的方法启动，则第一阶段调用流程应当是:</b></div><ul class="notion-list notion-list-disc notion-block-7f4fd02c14a54f329edf7688d55eead2"><li><code class="notion-inline-code"><b>prepare_data</b></code><b> </b>将会将创建data目录并且将magisk挂载到data，然后将关键文件和文件夹复制到<code class="notion-inline-code"><b>/data</b></code>目录下。这里的<code class="notion-inline-code"><b>init</b></code><b> 实际是patch到ramdisk中的magiskinit，这里</b>  <code class="notion-inline-code"><b>cp_afc(&quot;/init&quot;, &quot;/data/magiskinit&quot;);</b></code><b>实际上就是将</b><code class="notion-inline-code"><b>magiskinit</b></code><b>本身放到</b><code class="notion-inline-code"><b>/data/magiskinit</b></code></li><ul class="notion-list notion-list-disc notion-block-7f4fd02c14a54f329edf7688d55eead2"></ul></ul><ul class="notion-list notion-list-disc notion-block-c6cdb25eaae9435ea6987cb84106c0ff"><li>然后<code class="notion-inline-code"><b>mount_system_root</b></code><b> 尝试挂载系统根目录并且通过apex判断是否进行第二阶段的init,通过日志分析可以发现</b><span class="notion-red"><code class="notion-inline-code"><b>is_two_stage: [1]</b></code></span><span class="notion-red"><b> ，</b></span><b>即需要进入第二阶段init。</b></li><ul class="notion-list notion-list-disc notion-block-c6cdb25eaae9435ea6987cb84106c0ff"></ul></ul><ul class="notion-list notion-list-disc notion-block-1041965683194edf8a448c356b3567b4"><li><code class="notion-inline-code"><b>first_stage_prep</b></code><b> 实际就是将</b><code class="notion-inline-code"><b>/dev/root</b></code><b>根目录的</b><code class="notion-inline-code"><b>init</b></code><b>进行patch操作，将其内部的</b><code class="notion-inline-code"><b>/system/bin/init</b></code><b> 字符串改为</b><code class="notion-inline-code"><b>/data/magiskinit</b></code><b> ，这里根目录的init是原始的系统init二进制文件，</b><span class="notion-red"><code class="notion-inline-code"><b>[2.815494] magiskinit: Patch @ 0001C840 [/system/bin/init] -&gt; [/data/magiskinit]</b></code></span><span class="notion-red"><b>，</b></span><b>输出到</b><code class="notion-inline-code"><b>/data/init</b></code><b> ,并且挂载到</b><code class="notion-inline-code"><b>/init</b></code></li><ul class="notion-list notion-list-disc notion-block-1041965683194edf8a448c356b3567b4"></ul></ul><div class="notion-blank notion-block-cbd85099b8194cee9a8c695c0d678895"> </div><ul class="notion-list notion-list-disc notion-block-d6bdc74d76064f3a9f085f362781bace"><li>完成上述操作后<code class="notion-inline-code"><b>exec_init</b></code><b> 通过execv执行init，这里的init是经过patch的</b><code class="notion-inline-code"><b>系统init</b></code><b>，实际是</b><code class="notion-inline-code"><b>/data/init</b></code><b>,而非</b><code class="notion-inline-code"><b>magiskinit</b></code><b>，但是注意这里的参数还是空的，所以在执行系统init时还是第一阶段，相对于在原本的init执行之前magiskinit劫持了一会，但是完事后还是会将控制权交还原本init进行执行。</b></li><ul class="notion-list notion-list-disc notion-block-d6bdc74d76064f3a9f085f362781bace"></ul></ul></blockquote><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-84942fd63f384376aa4cf1fcbfb03da1" data-id="84942fd63f384376aa4cf1fcbfb03da1"><span><div id="84942fd63f384376aa4cf1fcbfb03da1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#84942fd63f384376aa4cf1fcbfb03da1" title="2. init第一阶段执行"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. init第一阶段执行</span></span></h4><blockquote class="notion-quote notion-block-e6126f1ead194ab8a274f9b402cd180d"><div>根据日志和前面分析可知，magiskinit打完patch后执行<code class="notion-inline-code"><b>patch后的init</b></code><b> </b></div><div class="notion-text notion-block-49f74ed66b0e40faa52f1e057af84d7f">下面两个代码块为Android源码中init部分源码，可以看到<code class="notion-inline-code">init</code>会查看是否有参数。如果没有参数，也就是当前的这种情况，执行<code class="notion-inline-code"><b>FirstStageMain</b></code><b>，执行原本的第一阶段初始化操作(省略)。</b></div><div class="notion-text notion-block-29ca68a292714630baf0e1406c67d0a6">然后再次通过<code class="notion-inline-code"><b>execv</b></code>执行<code class="notion-inline-code"><b>&quot;/system/bin/init&quot;</b></code><b> ，并且将参数设置</b><code class="notion-inline-code"><b>selinux_setup</b></code>， 但是由于对其进行了patch，所以这里执行完初始化操作后会到<code class="notion-inline-code"><b>/data/magiskinit</b></code>进行执行，并且带有参数<code class="notion-inline-code"><b>selinux_setup</b></code><b>。</b></div></blockquote><div class="notion-blank notion-block-dad6d57f9f0844a6bc10a807492ce5bc"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-96b012cac2fa4fb1ab1ba49e749ecb73" data-id="96b012cac2fa4fb1ab1ba49e749ecb73"><span><div id="96b012cac2fa4fb1ab1ba49e749ecb73" class="notion-header-anchor"></div><a class="notion-hash-link" href="#96b012cac2fa4fb1ab1ba49e749ecb73" title="3. Magisk劫持init第二阶段执行"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3. Magisk劫持init第二阶段执行</span></span></h4><blockquote class="notion-quote notion-block-126ef05a58d24aa49fd4545077a69f0e"><div>在执行到<code class="notion-inline-code"><b>FirstStageMain</b></code>结尾时会带<code class="notion-inline-code"><b>selinux_setup</b></code><b> 参数再次执行</b><code class="notion-inline-code"><b>/system/bin/init</b></code><b> ,</b>但是由于对init进行了patch，所以这里字符串实际是<code class="notion-inline-code"><b>/data/magiskinit</b></code><b> ，因此magisk会再次劫持。</b>日志也显示magiskinit接着执行并输出<span class="notion-red"><code class="notion-inline-code"><b>SecondStageInit</b></code></span><span class="notion-red"><b> </b></span></div><ul class="notion-list notion-list-disc notion-block-182df2758127481c88598aeff09d6296"><li>在Magisk的main中new了一个<code class="notion-inline-code"><b>SecondStageInit</b></code><b>, 接着执行流程应当是</b></li><ul class="notion-list notion-list-disc notion-block-182df2758127481c88598aeff09d6296"></ul></ul><ul class="notion-list notion-list-disc notion-block-fc492812007147c7a19ddc5fb859ea0d"><li><code class="notion-inline-code"><b>prepare</b></code><b> </b>取消挂载 <code class="notion-inline-code"><b>init</b></code><b>，这里的</b><span class="notion-red"><b>init实际上是</b></span><span class="notion-red"><code class="notion-inline-code"><b>/data/init</b></code></span><span class="notion-red"><b>，而</b></span><span class="notion-red"><code class="notion-inline-code"><b>/data/init</b></code></span><span class="notion-red"><b>实际是经过Patch的系统init</b></span><span class="notion-red"> ，</span>为了防止 init 的 dmesg 日志被干扰，将 argv[0] 参数设置为 <code class="notion-inline-code"><b>/system/bin/init</b></code>然后检查当前根文件系统是否为 <code class="notion-inline-code">RAMFS </code>或 <code class="notion-inline-code">TMPFS</code>，如果是，说明当前仍然在 <code class="notion-inline-code"><b>rootfs</b></code>下，需要在第二阶段重新执行 init，删除 <code class="notion-inline-code"><b>/init</b></code><b>链接</b>并创建一个符号链接，指向第二阶段的 <code class="notion-inline-code"><b>init</b></code>程序，这里的<code class="notion-inline-code"><b>init</b></code>程序实际是<code class="notion-inline-code"><b>未经过Patch的系统init</b></code>，其位置是<code class="notion-inline-code"><b>/system/bin/init</b></code>，以便在第二阶段执行 init。否则返回false。</li><ul class="notion-list notion-list-disc notion-block-fc492812007147c7a19ddc5fb859ea0d"></ul></ul><ul class="notion-list notion-list-disc notion-block-11177a8efc614e7394035f640d881610"><li><code class="notion-inline-code"><b>patch_ro_root</b></code><b> </b>则进行一些初始化任务，主要是在系统启动时对文件系统进行修改和挂载，以便 Magisk 可以正确地运行和隐藏自己。它涉及的操作包括创建临时目录、加载 overlay 文件、修改 init.rc 文件、提取 Magisk 文件、修改 sepolicy 文件等。</li><ul class="notion-list notion-list-disc notion-block-11177a8efc614e7394035f640d881610"><div class="notion-text notion-block-86a8e8f88a98453cb6c4620a6c72feca"><code class="notion-inline-code"><b>patch_init_rc</b></code>实现了对 init.rc 文件的修改。具体来说，它使用 <code class="notion-inline-code">file_readline </code>函数逐行读取源文件<code class="notion-inline-code"><b> init.rc</b></code>，并根据不同的匹配规则进行不同的修改，然后将修改后的内容写入目标文件 。除了修改 init.rc 文件外，这段代码还向目标文件 dest 中注入了一些自定义的 rc 脚本，这些脚本用于执行一些 Magisk 相关的操作，<b>如在 post-fs-data 阶段启动 Magisk、在系统启动完成后启动 Magisk 等。当然如果在目录下寻找init.rc是找不到的，</b><span class="notion-red"><b>因为等待注入完成后magisk就会删除rootdir目录以及下面的东西，防止被检测到。如果想要保留就需要</b></span><span class="notion-red"><code class="notion-inline-code"><b>native/src/core/daemon.cpp</b></code></span><span class="notion-red"><b> 中patch</b></span><span class="notion-red"><code class="notion-inline-code"><b>rm_rf((MAGISKTMP + &quot;/&quot; ROOTOVL).data());</b></code></span></div><div class="notion-text notion-block-8378524f4e3c4ca5a5471ccc88c04820">在<code class="notion-inline-code"><b>patch_ro_root</b></code>里还调用了一个函数<code class="notion-inline-code"><b>hijack_sepolicy()</b></code><b>， 这个函数就是劫持sepolicy作用。</b></div><div class="notion-callout notion-blue_background_co notion-block-eddf50296f8642c8b42649750346c68f"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">在使用 <code class="notion-inline-code">monolithic </code>策略的设备上，Magisk 直接从 <code class="notion-inline-code"><b>/sepolicy</b></code>文件中加载 sepolicy 规则。这个文件通常位于系统的根目录下，用于存储 selinux 策略。这种方式比较简单直接，不需要进行额外的 hook 操作。<div class="notion-text notion-block-f12fe7726e1946bb99e2727e2f1ef628">在其他的设备上，<code class="notion-inline-code"><b>Magisk 使用 FIFO（命名管道）劫持 selinuxfs 中的节点</b></code>，以实现 selinux hook。具体来说，Magisk 会创建一个 FIFO 文件，<b>并挂载到 selinuxfs 中的 &quot;load&quot; 和 &quot;enforce&quot; 节点上</b>，用于接收 selinux 策略和 enforce 值。这样一来，即使系统中没有 /sepolicy 文件，Magisk 也可以通过劫持 selinuxfs 中的节点，来实现 selinux hook。</div><div class="notion-text notion-block-415722d56cba41f5800bd1ad4ba6cc5c">在 2SI 设备上，<b>由于第二阶段的 init 文件是一个动态可执行文件</b>，而不是静态的 /init 可执行文件，因此 Magisk 还需要协助劫持 selinuxfs。具体来说，Magisk 会在 init 进程启动之前，通过<code class="notion-inline-code"> </code><code class="notion-inline-code"><b>LD_PRELOAD </b></code>的方式，将自己的 <code class="notion-inline-code">preload.so </code>库注入到 init 进程中，并<b>替换 security_load_policy 函数为自己的</b>实现，以实现 selinux hook。然后，Magisk 启动守护程序，等待 init 进程尝试加载 selinux 策略文件。当 init 进程启动时，Magisk 的钩子函数会拦截 security_load_policy 的调用，并将 selinux 策略文件和 enforce 值写入 FIFO 文件中，以实现自定义的 selinux 策略。</div></div></div><div class="notion-text notion-block-8b86e7fca72e41bebc48c365554ff559">在<code class="notion-inline-code">selinux.cpp</code>中，加粗部分较为重要，其中hijack则是通过<code class="notion-inline-code"><b>FIFO劫持 selinuxfs 中的节点</b></code>，以实现<code class="notion-inline-code">selinux hook</code> 。之后通过<code class="notion-inline-code"><b>xfork()</b></code><b> 创建子进程，父进程直接返回继续执行，执行到</b><code class="notion-inline-code"><b>exec_init</b></code><b> 后继续执行</b><code class="notion-inline-code"><b>系统未经过patch的init</b></code><b>， 在执行init的过程中会触发</b><code class="notion-inline-code"><b>security_getenforce</b></code><b> ，此时子进程才会从</b><code class="notion-inline-code"><b>xopen</b></code><b>的阻塞中脱离继续执行，也就是此时以及可以获取到</b><code class="notion-inline-code">selinux 策略和 enforce 值</code>。</div></ul></ul><ul class="notion-list notion-list-disc notion-block-6efcca7e5cd9433496ef638bd9a8b3ee"><li><code class="notion-inline-code"><b>exec_init</b></code><b> </b>就不再赘述了，还是将执行权归还系统<code class="notion-inline-code"><b>init</b></code><b> </b>继续执行，<code class="notion-inline-code"><b>注意此处的init是系统并未经过patch的init</b></code>，<b>前面讲到在</b><code class="notion-inline-code"><b>SecondStageInit::prepare()</b></code><span class="notion-red"><b>会取消挂载并且重新链接到系统原本的未经过patch的init</b></span><a class="notion-link" href="/fc492812007147c7a19ddc5fb859ea0d"><span class="notion-page-title"><span class="notion-page-title-text"><code class="notion-inline-code"><b>prepare</b></code><b> </b>取消挂载 <code class="notion-inline-code"><b>init</b></code><b>，这里的</b><span class="notion-red"><b>init实际上是</b></span><span class="notion-red"><code class="notion-inline-code"><b>/data/init</b></code></span><span class="notion-red"><b>，而</b></span><span class="notion-red"><code class="notion-inline-code"><b>/data/init</b></code></span><span class="notion-red"><b>实际是经过Patch的系统init</b></span><span class="notion-red"> ，</span>为了防止 init 的 dmesg 日志被干扰，将 argv[0] 参数设置为 <code class="notion-inline-code"><b>/system/bin/init</b></code>然后检查当前根文件系统是否为 <code class="notion-inline-code">RAMFS </code>或 <code class="notion-inline-code">TMPFS</code>，如果是，说明当前仍然在 <code class="notion-inline-code"><b>rootfs</b></code>下，需要在第二阶段重新执行 init，删除 <code class="notion-inline-code"><b>/init</b></code><b>链接</b>并创建一个符号链接，指向第二阶段的 <code class="notion-inline-code"><b>init</b></code>程序，这里的<code class="notion-inline-code"><b>init</b></code>程序实际是<code class="notion-inline-code"><b>未经过Patch的系统init</b></code>，其位置是<code class="notion-inline-code"><b>/system/bin/init</b></code>，以便在第二阶段执行 init。否则返回false。</span></span></a><span class="notion-red"><b> </b></span>，这次<code class="notion-inline-code"><b>execv</b></code>带有参数<code class="notion-inline-code"><b>selinux_setup</b></code><b> 因此会执行源码中的</b><code class="notion-inline-code"><b>SetupSelinux</b></code><b>，于是也就有了日志里init的那些输出(加粗)。</b></li><ul class="notion-list notion-list-disc notion-block-6efcca7e5cd9433496ef638bd9a8b3ee"><div class="notion-callout notion-blue_background_co notion-block-730e84024b834882abba694ddb723c23"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="⚠️">⚠️</span></div><div class="notion-callout-text">大伙可能会比较好奇为什么中间有两行输出是<code class="notion-inline-code">magiskinit</code>的输出，其实就是上面讲到的子进程会一直阻塞直到<code class="notion-inline-code">init </code>触发<code class="notion-inline-code">security_getenforce</code> ，此刻解阻塞后就会输出<code class="notion-inline-code">magiskinit</code> 信息，但是父进程早就执行完成了，到此为止<code class="notion-inline-code">magiskinit</code>的初始化职责就完成了，<b>再往后的执行都是系统未经过patch的init进行继续初始化。</b></div></div></ul></ul></blockquote><div class="notion-blank notion-block-1e6a47efb80548378bd89f5626f104ba"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-8a389d9a0a304d19a62225bbbc311458" data-id="8a389d9a0a304d19a62225bbbc311458"><span><div id="8a389d9a0a304d19a62225bbbc311458" class="notion-header-anchor"></div><a class="notion-hash-link" href="#8a389d9a0a304d19a62225bbbc311458" title="4.  init第二阶段"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">4.  init第二阶段</span></span></h4><blockquote class="notion-quote notion-block-c5ca710d06b947a5bb48628fd65bdc91"><div>由于这次<code class="notion-inline-code"><b>execv</b></code>带有参数<code class="notion-inline-code"><b>selinux_setup</b></code><b> 因此会执行源码中的</b><code class="notion-inline-code"><b>SetupSelinux</b></code></div><div class="notion-text notion-block-3a9958af10c345719091b788a020cf8d">当<code class="notion-inline-code"><b>SetupSelinux</b></code>执行完成后，又会再次通过execv到<code class="notion-inline-code"><b>init</b></code>执行，参数为<code class="notion-inline-code"><b>second_stage</b></code><b> ，这里的init是系统原本的未经过patch的</b><code class="notion-inline-code"><b>init</b></code><b>，当</b><code class="notion-inline-code"><b>magiskinit</b></code><b>父进程执行完execv后就会退出，之后的初始化都是系统自己的初始化</b><code class="notion-inline-code"><b>init</b></code><b> 。</b></div></blockquote><div class="notion-blank notion-block-81acf7e93f6949f284de8ce8f3002b68"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-dcf27694d17e48cfb26a7e62c1f8a0ce" data-id="dcf27694d17e48cfb26a7e62c1f8a0ce"><span><div id="dcf27694d17e48cfb26a7e62c1f8a0ce" class="notion-header-anchor"></div><a class="notion-hash-link" href="#dcf27694d17e48cfb26a7e62c1f8a0ce" title="5. 流程总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">5. 流程总结</span></span></h4><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-a119168f62214baa95502c85e25d2997"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7403fea5-6681-49ef-a2a3-b5daf62f5843%2FUntitled.png?table=block&amp;id=a119168f-6221-4baa-9550-2c85e25d2997&amp;t=a119168f-6221-4baa-9550-2c85e25d2997&amp;width=8484&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-f973bdb39e5842518a55c2f46e071779">PS:  <b>SELinux劫持和父子进程分叉就不画进去了</b></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-49ec3e0386004187a8fc89e90adfa784" data-id="49ec3e0386004187a8fc89e90adfa784"><span><div id="49ec3e0386004187a8fc89e90adfa784" class="notion-header-anchor"></div><a class="notion-hash-link" href="#49ec3e0386004187a8fc89e90adfa784" title="五、Magisk-post-fs-data"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">五、Magisk-<code class="notion-inline-code"><b>post-fs-data</b></code></span></span></h3><blockquote class="notion-quote notion-block-56e49f99c6ee42da8665c1fe4294bfb1"><div><b>当 </b><code class="notion-inline-code"><b>/data</b></code><b> 被解密和装载时会在 </b><code class="notion-inline-code"><b>post-fs-data</b></code><b> 上触发。守护程序 </b><code class="notion-inline-code"><b>magiskd</b></code><b> 将被启动，执行 post-fs-data 脚本，并安装模块文件。</b></div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-04b2186089d645ab9ca65cc611b7ab1d" data-id="04b2186089d645ab9ca65cc611b7ab1d"><span><div id="04b2186089d645ab9ca65cc611b7ab1d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#04b2186089d645ab9ca65cc611b7ab1d" title="1. init.rc"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. init.rc</span></span></h4><blockquote class="notion-quote notion-block-4ddb3f63710d40279e94f15ca4ece994"><div>上文讲到magisk在初始化阶段也就是<code class="notion-inline-code"><b>preinit</b></code>阶段对<code class="notion-inline-code"><b>init.rc</b></code>进行修改，在原本的<code class="notion-inline-code"><b>init.rc</b></code>后添加下面的内容。<code class="notion-inline-code">&quot;u:r:magisk:s0 0 0&quot; </code>表示 Magisk 进程的安全上下文，表示该进程在用户空间中扮演 &quot;magisk&quot; 角色，类型级别为默认级别，用户 ID 和组 ID 均为 0，即以 root 用户身份运行。<b>在不同时机触发magisk进行不同的活动，例如在</b><code class="notion-inline-code">post-fs-data</code> 阶段运行<code class="notion-inline-code">magisk --post-fs-data</code><b>。</b></div></blockquote><div class="notion-blank notion-block-d16ee0f10b16430b84fad17facfaedf5"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-71d51a5d24a0453fbece84bab022e87c" data-id="71d51a5d24a0453fbece84bab022e87c"><span><div id="71d51a5d24a0453fbece84bab022e87c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#71d51a5d24a0453fbece84bab022e87c" title="2. magisk启动"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. magisk启动</span></span></h4><blockquote class="notion-quote notion-block-8e0bc9ce45964dd98f55a31c60bce14f"><div>在<code class="notion-inline-code"><b>native/src/core/magisk.cpp</b></code><b> 中</b><code class="notion-inline-code"><b>magisk_main</b></code><b>即为magisk入口。</b></div><ul class="notion-list notion-list-disc notion-block-f41a49eb482e432b9672b64ec1906dab"><li>通过<code class="notion-inline-code"><b>connect_daemon</b></code><b> 创建守护进程daemon进程，</b>由于此时守护进程还未建立，所以<code class="notion-inline-code">if</code>中的<code class="notion-inline-code">connect</code>会返回<code class="notion-inline-code">-1</code>，从而进入if<code class="notion-inline-code"><b>成功的分支</b></code><b> ，</b>进入后进行一次fork，父进程会继续向下等待连接，子进程则通过<code class="notion-inline-code">daemon_entry</code> 成为守护进程，之后父进程连接到守护进程后到<code class="notion-inline-code">write_int(fd, req)</code>，守护进程会一直监听请求。</li><ul class="notion-list notion-list-disc notion-block-f41a49eb482e432b9672b64ec1906dab"></ul></ul><ul class="notion-list notion-list-disc notion-block-7da9da23b7124fda9c173e0a5227bc97"><li><code class="notion-inline-code">boot_stage_handler</code> 来处理<code class="notion-inline-code">POST_FS_DATA</code>  <code class="notion-inline-code">LATE_START</code> <code class="notion-inline-code">BOOT_COMPLETE</code>三种请求</li><ul class="notion-list notion-list-disc notion-block-7da9da23b7124fda9c173e0a5227bc97"><div class="notion-text notion-block-088de60fedf045dc9acf29c19f1fea70"><code class="notion-inline-code"><b>unlock_blocks</b></code><b> 将解锁所有块设备的写保护，</b><code class="notion-inline-code"><b>mount_mirrors</b></code><b> 挂载各种镜像文件系统，</b><code class="notion-inline-code"><b>prune_su_access</b></code><b> 用于在数据库中检查授权的APP并对已经不存在的APP的数据进行删除。</b><code class="notion-inline-code"><b>magisk_env</b></code><b> 对Magisk环境进行初始化。最后</b><code class="notion-inline-code"><b>load_modules</b></code><b>对模块进行加载。</b></div><div class="notion-text notion-block-0bad317548b4450e9ed0a292e784007e">这段代码首先调用了<code class="notion-inline-code">get_prop()</code>函数来获取系统属性<code class="notion-inline-code">persist.sys.safemode</code>和<code class="notion-inline-code">ro.sys.safemode</code>的值。如果<code class="notion-inline-code">get_prop()</code>函数的第二个参数为<code class="notion-inline-code">true</code>，表示在没有找到这些属性时返回默认值<code class="notion-inline-code">&quot;1&quot;</code>。如果获取到的值为<code class="notion-inline-code">&quot;1&quot;</code>，或者按键组合被触发（通过调用<code class="notion-inline-code">check_key_combo()</code>函数），则将<code class="notion-inline-code">boot_state</code>的<code class="notion-inline-code">FLAG_SAFE_MODE</code>位置1，表示启动处于安全模式，将会禁用所有模块并且禁用禁止列表，<b>这有助于在手机安装一些模块导致手机无法正常启动时对系统进行修复。</b></div><div class="notion-text notion-block-59422b0193b842fcb92f8b8b34df4ca7">如果启动不处于安全模式，那么首先调用<code class="notion-inline-code">exec_common_scripts()</code>函数执行<code class="notion-inline-code">/data/adb/post-fs-data.d</code>目录下的脚本。接着，定义了一个名为<code class="notion-inline-code">dbs</code>的<code class="notion-inline-code">db_settings</code>结构体，调用<code class="notion-inline-code">get_db_settings()</code>函数将系统属性<code class="notion-inline-code">ZYGISK_CONFIG</code>的值存储在<code class="notion-inline-code">dbs</code>中。然后，通过检查<code class="notion-inline-code">dbs[ZYGISK_CONFIG]</code>的值来确定是否启用了<code class="notion-inline-code">zygisk</code>。最后，调用<code class="notion-inline-code">initialize_denylist()</code>函数初始化拒绝列表，并调用<code class="notion-inline-code">handle_modules()</code>函数处理模块的<code class="notion-inline-code">post-fs-data</code> 脚本、收集模块以及创建模块动态链接库内存描述符为后续模块动态链接库加载做准备</div><div class="notion-text notion-block-4340d5d8adad402e8b7373fcbcd12192"><code class="notion-inline-code"><b>mount_mirrors</b></code><b> 进行镜像的挂载操作，</b>如果当前系统版本小于24或者安全目录<code class="notion-inline-code">SECURE_DIR(/data/adb)</code>存在，则执行绑定重新挂载的操作。具体来说，函数创建<code class="notion-inline-code">MAGISKTMP + &quot;/&quot; MODULEMNT(/debug_ramdisk/.magisk/modules)</code>目录，然后将模块根目录<code class="notion-inline-code">MODULEROOT(/data/adb/modules)</code>绑定挂载到该目录中，并将挂载点重新挂载为只读文件系统，最后将挂载点设置为私有的，并将<code class="notion-inline-code">/data/adb</code>的权限设置为0700。</div><div class="notion-callout notion-blue_background_co notion-block-590a3c1e53394cef99e85b561e3c3320"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">Magisk官方文档中提到使用<code class="notion-inline-code">/data/adb</code>作为安全目录的原因：<div class="notion-text notion-block-5fb18416386d40d9bd104650cb32038c">一些二进制文件和文件应存储在 <code class="notion-inline-code">/data</code> 中的非易失性存储中。为了防止检测，所有东西都必须存储在 <code class="notion-inline-code">/data</code> 中安全且不可检测的地方。选 <code class="notion-inline-code">/data/adb</code> 文件夹是因为其具有以下优点：</div><ul class="notion-list notion-list-disc notion-block-b3a9f328d0074274b3bcf12e9e6a97f5"><li>它是现代安卓系统上的一个现有文件夹，因此不能作为 Magisk 存在的标志。</li></ul><ul class="notion-list notion-list-disc notion-block-125ac6eaee8f4e97b8a54f062f2a16a3"><li>文件夹的权限默认为 <code class="notion-inline-code">700</code>，所有者为 <code class="notion-inline-code">root</code>，因此非 root 进程无法以任何可能的方式进入、读取和写入文件夹。</li></ul><ul class="notion-list notion-list-disc notion-block-6a53de22daf64fcc8d5911c7112b85be"><li>文件夹 secontext 标记为 <code class="notion-inline-code">u:object_r:adb_data_file:s0</code>，很少有进程有权与该 secontext 进行任何交互。</li></ul><ul class="notion-list notion-list-disc notion-block-f818fb743cdf4b6ca0d2fdab0477956f"><li>该文件夹位于<em>设备加密存储区</em>中，因此一旦数据正确装载到 FBE（File-Based Encryption，基于文件的加密）设备中，即可访问该文件夹。</li></ul></div></div><div class="notion-text notion-block-771249fc1d4e47a9a5c4582e8d39df53">然后检查是否需要挂载预初始化镜像文件系统。如果预初始化镜像文件系统的块设备文件存在，则尝试在当前的挂载信息中查找已经挂载了该块设备的目录，并将目标目录绑定挂载到预初始化镜像文件系统的目录中。然后挂载worker目录，最后函数通过递归绑定挂载的方式将根目录<code class="notion-inline-code">&quot;/&quot;</code>绑定挂载到一个名为<code class="notion-inline-code">MAGISKTMP + &quot;/&quot; MIRRDIR(/debug_magisk/.magisk/mirror)</code>的目录中。</div><div class="notion-text notion-block-1c2ccb31dfa4472ead11c048aa25ba23"><code class="notion-inline-code">MagiskV26.0</code>更新了 Magic Mount 功能的后端，支持将模块加载到系统中并注入 overlayfs 文件。Magic Mount是指通过模块修改系统文件的功能。在这个更新之前，Magisk 通过叠加文件系统来实现 Magic Mount 功能，但是一些设备厂商在他们的系统中注入了 overlayfs 文件，导致 Magic Mount出现问题。 </div><div class="notion-text notion-block-82ee5aede8464ccab424cccc6a50d099">需要注意的是，Magisk 的模块挂载是在 Android 系统启动时进行的，因此在安装或卸载 Magisk 模块时需要重启系统才能生效。</div><div class="notion-text notion-block-c79baf8ba7fe48b5b4ad5b9a49a91b0c">这里对<code class="notion-inline-code"><b>zygisk</b></code>进行挂载 ，成功实现了对<code class="notion-inline-code">/system/bin/app_process32</code> 和 <code class="notion-inline-code">/system/bin/app_process64</code> 的替换，替换为对应的<code class="notion-inline-code"><b>magisk</b></code>，分析日志也可以发现，通过系统目录的挂载<code class="notion-inline-code"><b>root-&gt;mount();</b></code>将会实现这种替换。官方之前的说法：<code class="notion-inline-code">尽管安装逻辑非常复杂，但Magic挂载的最终结果实际上非常简单。对于每个模块，目录/system将被递归地合并到真实的/system中;即:将真实system中的现有文件替换为模块“system”中的文件，并将模块“system”中的新文件添加到真实system中。</code></div></ul></ul></blockquote><div class="notion-blank notion-block-cfe7bbd909aa4f8b973ca0c036984080"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-da55c4db76494195a26730ca95f8c61a" data-id="da55c4db76494195a26730ca95f8c61a"><span><div id="da55c4db76494195a26730ca95f8c61a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#da55c4db76494195a26730ca95f8c61a" title="六、Magisk-late_start "><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">六、Magisk-<code class="notion-inline-code"><b>late_start</b></code><b> </b></span></span></h3><blockquote class="notion-quote notion-block-a8c0c3e5542f46ab9c5e134085ccfaeb"><div><b>在稍后的引导过程中，将触发 </b><code class="notion-inline-code"><b>late_start</b></code><b> ，并启动 Magisk “服务”模式。在此模式下，执行服务（service）脚本。在这个阶段将会对</b><code class="notion-inline-code"><b>service.d</b></code><b>目录下的以及模块中的service脚本进行执行。</b></div></blockquote><div class="notion-blank notion-block-295ea22aec5d42bfb606e6f227e44423"> </div><div class="notion-blank notion-block-3c7d5a1770f24f4dab29961228d5cb10"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-65ac55a88aec4e49aaafff59339d0169" data-id="65ac55a88aec4e49aaafff59339d0169"><span><div id="65ac55a88aec4e49aaafff59339d0169" class="notion-header-anchor"></div><a class="notion-hash-link" href="#65ac55a88aec4e49aaafff59339d0169" title="七、Magisk-boot-complete"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">七、Magisk-<code class="notion-inline-code">boot-complete</code></span></span></h3><blockquote class="notion-quote notion-block-c83c8b16a443431988115ead25c1640f"><div>启动完成时<code class="notion-inline-code"><b>sys.boot_completed=1</b></code> 触发<code class="notion-inline-code">boot-complete</code></div></blockquote><div class="notion-blank notion-block-3cde05d5bd9b455d8e13febc48d516bf"> </div><div class="notion-blank notion-block-ef45bb8636134608b553ed0941100e1d"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-d85a3f329799445888bb62ab6eb02dd1" data-id="d85a3f329799445888bb62ab6eb02dd1"><span><div id="d85a3f329799445888bb62ab6eb02dd1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d85a3f329799445888bb62ab6eb02dd1" title="参考："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">参考：</span></span></h3><ol start="1" class="notion-list notion-list-numbered notion-block-d838be273aef4d199c6e5f1fb0e6f3b5" style="list-style-type:decimal"><li><a class="notion-link" href="https://bbs.kanxue.com/thread-275939-1.htm#msg_header_h2_3" target="_blank" rel="noopener noreferrer">[原创] 云手机底层技术揭密 : Android系统启动与Magisk原理-Android安全-看雪-安全社区|安全招聘|kanxue.com</a></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-ba91aa10713c4f68a445cb648860a1af" style="list-style-type:decimal"><li><a class="notion-link" href="https://topjohnwu.github.io/Magisk/boot.html" target="_blank" rel="noopener noreferrer">Android Booting Shenanigans | Magisk (topjohnwu.github.io)</a></li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-71ef8d3d2d974df69e696bbf3dfd4baa" style="list-style-type:decimal"><li><a class="notion-link" href="https://jesse205.github.io/MagiskChineseDocument/details.html" target="_blank" rel="noopener noreferrer">内部细节 | Magisk 中文文档 (jesse205.github.io)</a></li></ol><ol start="4" class="notion-list notion-list-numbered notion-block-0aff12af1b614a1eac47a44a1916e03b" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog.csdn.net/zhonglunshun/article/details/128791807" target="_blank" rel="noopener noreferrer">(71条消息) Magisk内部实现原理_magisk原理_疯人院的院长大人的博客-CSDN博客</a></li></ol><ol start="5" class="notion-list notion-list-numbered notion-block-4994f7cd191348b1844bc23e39908759" style="list-style-type:decimal"><li><a class="notion-link" href="https://learnlinuxconcepts.blogspot.com/2014/02/android-boot-sequence.html?m=0" target="_blank" rel="noopener noreferrer">LINUX KERNEL INTERNALS: Android Boot Sequence (learnlinuxconcepts.blogspot.com)</a></li></ol><ol start="6" class="notion-list notion-list-numbered notion-block-70ba1c92ffcb47669d2b56a734c8c697" style="list-style-type:decimal"><li><a class="notion-link" href="https://zhuanlan.zhihu.com/p/127074795" target="_blank" rel="noopener noreferrer">Android操作系统启动过程概览 - 知乎 (zhihu.com)</a></li></ol><ol start="7" class="notion-list notion-list-numbered notion-block-54542009261046bea4d5fbac33fcde3e" style="list-style-type:decimal"><li><a class="notion-link" href="https://pshocker.github.io/2022/07/18/Magisk%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E4%BA%8C/" target="_blank" rel="noopener noreferrer">Magisk源码分析(二) | Shocker (pshocker.github.io)</a></li></ol><ol start="8" class="notion-list notion-list-numbered notion-block-735fcbe5dbcb40cbaee738f18b0a6281" style="list-style-type:decimal"><li><a class="notion-link" href="https://pshocker.github.io/2022/07/22/Magisk%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E4%B8%89/" target="_blank" rel="noopener noreferrer">Magisk源码分析(三) | Shocker (pshocker.github.io)</a></li></ol><ol start="9" class="notion-list notion-list-numbered notion-block-f40ff9aad0b24219a4733aef8d1ad65d" style="list-style-type:decimal"><li><a class="notion-link" href="https://cs.android.com/android/platform/superproject/main/+/refs/heads/main:system/core/init/main.cpp;bpv=0;bpt=0?hl=zh-cn" target="_blank" rel="noopener noreferrer">main.cpp - Android Code Search</a></li></ol><ol start="10" class="notion-list notion-list-numbered notion-block-d7073171a22e4e54ba5567f79b8c0e78" style="list-style-type:decimal"><li><a class="notion-link" href="https://cs.android.com/android/platform/superproject/main/+/refs/heads/main:system/core/init/selinux.cpp;drc=ecfcb0f2762403667ab6883d32b916cbc3fa6556;bpv=0;bpt=0;l=1031?hl=zh-cn" target="_blank" rel="noopener noreferrer">selinux.cpp - Android Code Search</a></li></ol><div class="notion-blank notion-block-a42b83d5fdf74e7fa75abe0adde4d659"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android ART虚拟机执行流程示意图]]></title>
            <link>https://lleavesg.top//article/ART</link>
            <guid>https://lleavesg.top//article/ART</guid>
            <pubDate>Tue, 26 Aug 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-25b3fb9e943280b58399f47a15ec8835"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-text notion-block-25b3fb9e943280b88be7fa95dcee22f5">从Linkcode设置方法开始阐述</div><div class="notion-text notion-block-25b3fb9e94328022946cf9db2b6902ee">但是可能存在一些问题或错误，感谢指正</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-25b3fb9e94328042831ffa0ba120988f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A1af02331-4773-42d3-989b-1f4b98b1d85f%3Aimage.png?table=block&amp;id=25b3fb9e-9432-8042-831f-fa0ba120988f&amp;t=25b3fb9e-9432-8042-831f-fa0ba120988f" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-25b3fb9e943280889af4cf78f69eecf3"> </div><div class="notion-text notion-block-25b3fb9e943280878b30e4eda2ad55eb">如果走Nterp模式以直接跳转的方式解释执行指令，那么在调用函数的过程中会执行到<code class="notion-inline-code">nterp_op_invoke_*</code> 最终会执行到中间的10个绿色框中的函数。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-25b3fb9e9432809f8e43c2e303e0bee4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A85f26b64-a4a8-454b-b960-d4d42bf55f54%3Aimage.png?table=block&amp;id=25b3fb9e-9432-809f-8e43-c2e303e0bee4&amp;t=25b3fb9e-9432-809f-8e43-c2e303e0bee4" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-25b3fb9e9432806c8bd8c4d74fd249a0"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[eBPFDexDumper更新-添加抽取代码dump功能]]></title>
            <link>https://lleavesg.top//article/eBPFDexDumper-dump</link>
            <guid>https://lleavesg.top//article/eBPFDexDumper-dump</guid>
            <pubDate>Tue, 26 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[eBPFDexDumper更新]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-25b3fb9e9432807fb8d9eb7a87384f22"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><a class="notion-external notion-external-block notion-row notion-block-25b3fb9e94328061b4c5e66b8cddc9d6" href="https://github.com/LLeavesG/eBPFDexDumper" target="_blank" rel="noopener noreferrer"><div class="notion-external-image"><svg viewBox="0 0 260 260"><g><path d="M128.00106,0 C57.3172926,0 0,57.3066942 0,128.00106 C0,184.555281 36.6761997,232.535542 87.534937,249.460899 C93.9320223,250.645779 96.280588,246.684165 96.280588,243.303333 C96.280588,240.251045 96.1618878,230.167899 96.106777,219.472176 C60.4967585,227.215235 52.9826207,204.369712 52.9826207,204.369712 C47.1599584,189.574598 38.770408,185.640538 38.770408,185.640538 C27.1568785,177.696113 39.6458206,177.859325 39.6458206,177.859325 C52.4993419,178.762293 59.267365,191.04987 59.267365,191.04987 C70.6837675,210.618423 89.2115753,204.961093 96.5158685,201.690482 C97.6647155,193.417512 100.981959,187.77078 104.642583,184.574357 C76.211799,181.33766 46.324819,170.362144 46.324819,121.315702 C46.324819,107.340889 51.3250588,95.9223682 59.5132437,86.9583937 C58.1842268,83.7344152 53.8029229,70.715562 60.7532354,53.0843636 C60.7532354,53.0843636 71.5019501,49.6441813 95.9626412,66.2049595 C106.172967,63.368876 117.123047,61.9465949 128.00106,61.8978432 C138.879073,61.9465949 149.837632,63.368876 160.067033,66.2049595 C184.49805,49.6441813 195.231926,53.0843636 195.231926,53.0843636 C202.199197,70.715562 197.815773,83.7344152 196.486756,86.9583937 C204.694018,95.9223682 209.660343,107.340889 209.660343,121.315702 C209.660343,170.478725 179.716133,181.303747 151.213281,184.472614 C155.80443,188.444828 159.895342,196.234518 159.895342,208.176593 C159.895342,225.303317 159.746968,239.087361 159.746968,243.303333 C159.746968,246.709601 162.05102,250.70089 168.53925,249.443941 C219.370432,232.499507 256,184.536204 256,128.00106 C256,57.3066942 198.691187,0 128.00106,0 Z M47.9405593,182.340212 C47.6586465,182.976105 46.6581745,183.166873 45.7467277,182.730227 C44.8183235,182.312656 44.2968914,181.445722 44.5978808,180.80771 C44.8734344,180.152739 45.876026,179.97045 46.8023103,180.409216 C47.7328342,180.826786 48.2627451,181.702199 47.9405593,182.340212 Z M54.2367892,187.958254 C53.6263318,188.524199 52.4329723,188.261363 51.6232682,187.366874 C50.7860088,186.474504 50.6291553,185.281144 51.2480912,184.70672 C51.8776254,184.140775 53.0349512,184.405731 53.8743302,185.298101 C54.7115892,186.201069 54.8748019,187.38595 54.2367892,187.958254 Z M58.5562413,195.146347 C57.7719732,195.691096 56.4895886,195.180261 55.6968417,194.042013 C54.9125733,192.903764 54.9125733,191.538713 55.713799,190.991845 C56.5086651,190.444977 57.7719732,190.936735 58.5753181,192.066505 C59.3574669,193.22383 59.3574669,194.58888 58.5562413,195.146347 Z M65.8613592,203.471174 C65.1597571,204.244846 63.6654083,204.03712 62.5716717,202.981538 C61.4524999,201.94927 61.1409122,200.484596 61.8446341,199.710926 C62.5547146,198.935137 64.0575422,199.15346 65.1597571,200.200564 C66.2704506,201.230712 66.6095936,202.705984 65.8613592,203.471174 Z M75.3025151,206.281542 C74.9930474,207.284134 73.553809,207.739857 72.1039724,207.313809 C70.6562556,206.875043 69.7087748,205.700761 70.0012857,204.687571 C70.302275,203.678621 71.7478721,203.20382 73.2083069,203.659543 C74.6539041,204.09619 75.6035048,205.261994 75.3025151,206.281542 Z M86.046947,207.473627 C86.0829806,208.529209 84.8535871,209.404622 83.3316829,209.4237 C81.8013,209.457614 80.563428,208.603398 80.5464708,207.564772 C80.5464708,206.498591 81.7483088,205.631657 83.2786917,205.606221 C84.8005962,205.576546 86.046947,206.424403 86.046947,207.473627 Z M96.6021471,207.069023 C96.7844366,208.099171 95.7267341,209.156872 94.215428,209.438785 C92.7295577,209.710099 91.3539086,209.074206 91.1652603,208.052538 C90.9808515,206.996955 92.0576306,205.939253 93.5413813,205.66582 C95.054807,205.402984 96.4092596,206.021919 96.6021471,207.069023 Z" fill="#161614"></path></g></svg></div><div class="notion-external-description"><div class="notion-external-title">eBPFDexDumper</div><div class="notion-external-block-desc">LLeavesG<span> • </span>Updated Aug 27, 2025</div></div></a><div class="notion-text notion-block-25b3fb9e943280658bf1e39c22ff7c15">之前写的基于eBPF的Android应用程序脱壳工具有一些bug和问题，包括但不限于</div><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280be91cacb3facf19b74"><li>未开启CONFIG_DEBUG_INFO_BTF的设备无法使用</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280ddac41dea2f89c45bf"><li>执行路径覆盖不全导致部分dex无法成功dump</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e9432801c83d6df86cc0281e1"><li>高版本Android去除了libart.so的符号，工具兼容做的不好</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e9432800aa649e834d8084a1f"><li>工具使用起来不人性化，参数选定困难</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280baaf0ccb62abefa94a"><li>仅能脱整体Dex，无法dump抽取方法的代码</li></ul><div class="notion-blank notion-block-25b3fb9e943280db9ac2cfc2a3ac0b02"> </div><div class="notion-text notion-block-25b3fb9e943280b883e4da3f8714bbc3">在更新版本中解决了上述问题。</div><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280a9a706d32b677a1e1a"><li>参考Stackplz将btf文件嵌入到二进制可执行程序，动态加载btf文件，避免了没开启CONFIG_DEBUG_INFO_BTF的内核无法使用的问题</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280cfb9fae7985b61fe8c"><li>重新理顺了ART虚拟机的执行路径，覆盖全执行路径，以避免漏掉方法的执行</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280ef8c6ac89141bbda61"><li>自动寻找函数偏移，但是关于Execute函数的偏移还是需要通过IDA手动找</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280b0bd20d73e5c77ce94"><li>重构了项目代码，包括参数解析部分</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280b4a0e9fbc655a95056"><li>引入了ArtMethod的code item的dump以及Dex修复功能。这样就能把应用场景拓展到抽取壳的dump。</li></ul><ul class="notion-list notion-list-disc notion-block-25b3fb9e943280ea8031ece837b0eb0d"><li>引入了方法的追踪，在完全覆盖执行路径后就能准确的捕获每一个方法的执行，只需要在bpf侧获取方法的idx，然后即可通过解析dex文件获取方法签名，实现方法的追踪</li></ul><div class="notion-blank notion-block-25b3fb9e94328042b268f986ecbe2253"> </div><div class="notion-blank notion-block-25b3fb9e943280ba9dc7ce7b8f58b209"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ByteCTF2021 EasyDroid复现]]></title>
            <link>https://lleavesg.top//article/ByteCTF-2021-EasyDroid</link>
            <guid>https://lleavesg.top//article/ByteCTF-2021-EasyDroid</guid>
            <pubDate>Sun, 23 Jul 2023 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-full-width notion-block-7384b1e7006f410db2c5c1d678b86fb9"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-blank notion-block-2260ee2db7924fe597fd39f73f3248e0"> </div><div class="notion-table-of-contents notion-gray notion-block-864343af5ead4406bf57f37c59eed176"><a href="#b70829973bb54b60be5aeab8dc18c5a5" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">一、漏洞APP分析</span></a><a href="#fc3ac9cf44994f54920b2e80f7997f1f" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. AndroidManifest.xml分析</span></a><a href="#9dbec7577fe346efa841d2f259df7e39" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. MainActivity</span></a><a href="#631779f71fa749d9bf08d862f80be25d" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">3. TestActivity</span></a><a href="#d7877e615fc44c25a9993a9f0866f296" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">4.FlagReceiver</span></a><a href="#7f27728e2c5949f8b631ec4229c3c354" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">二、攻击APP构造</span></a><a href="#d5f1266a01f04e1280829f2000dd8022" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">1. 构造demo验证可行性</span></a><a href="#fa28a4cac3464829b12e8965bd440d12" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:24px">2. 攻击方案</span></a><a href="#44c02239c6d24a80aeae3fdf62ae8b26" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">三、总结</span></a><a href="#f6eb8a52fe494914b36c8e08e0108434" class="notion-table-of-contents-item"><span class="notion-table-of-contents-item-body" style="display:inline-block;margin-left:0">四、参考</span></a></div><hr class="notion-hr notion-block-a3eda22b0d3f4c4ca52afc343da27127"/><div class="notion-blank notion-block-b091afe620584ff8836ac19f197e6c81"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-b70829973bb54b60be5aeab8dc18c5a5" data-id="b70829973bb54b60be5aeab8dc18c5a5"><span><div id="b70829973bb54b60be5aeab8dc18c5a5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#b70829973bb54b60be5aeab8dc18c5a5" title="一、漏洞APP分析"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">一、漏洞APP分析</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-fc3ac9cf44994f54920b2e80f7997f1f" data-id="fc3ac9cf44994f54920b2e80f7997f1f"><span><div id="fc3ac9cf44994f54920b2e80f7997f1f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#fc3ac9cf44994f54920b2e80f7997f1f" title="1. AndroidManifest.xml分析"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. AndroidManifest.xml分析</span></span></h4><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-8517cfce69e64d088528b09a8f56ec17"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F3c71d0f7-721d-41b3-9545-3cd7153cc35b%2FUntitled.png?table=block&amp;id=8517cfce-69e6-4d08-8528-b09a8f56ec17&amp;t=8517cfce-69e6-4d08-8528-b09a8f56ec17&amp;width=792.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-e68d23869caa4c7091542c37b10851d1"><code class="notion-inline-code"><b>AndroidManifest.xml</b></code><b> 中声明了三个组件，两个</b><code class="notion-inline-code"><b>Activity</b></code><b>和一个</b><code class="notion-inline-code"><b>Receiver</b></code><b> ，其中只有</b><code class="notion-inline-code"><b>MainActivity</b></code><b>是导出的</b></div><div class="notion-blank notion-block-3b511eabdbbb4c84b18397b642f7b2bf"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-9dbec7577fe346efa841d2f259df7e39" data-id="9dbec7577fe346efa841d2f259df7e39"><span><div id="9dbec7577fe346efa841d2f259df7e39" class="notion-header-anchor"></div><a class="notion-hash-link" href="#9dbec7577fe346efa841d2f259df7e39" title="2. MainActivity"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. MainActivity</span></span></h4><div class="notion-text notion-block-1f8ab0add989449d8810be8af9fa1151"><code class="notion-inline-code"><b>MainActivity </b></code><b> 先是获取intent的数据，然后经过校验后使用</b><code class="notion-inline-code"><b>webView.loadUrl(data.toString())</b></code><b>进行加载，而且设置了</b><code class="notion-inline-code"><b>setJavaScriptEnabled(true)</b></code><b> 这意味着启用了</b><code class="notion-inline-code"><b>JavaScript</b></code><b> 。除此之外设置了</b><code class="notion-inline-code"><b>setWebViewClient</b></code><b> ，并且通过</b><code class="notion-inline-code"><b>shouldOverrideUrlLoading</b></code><b> 拦截请求，在内部校验</b><code class="notion-inline-code"><b>intent</b></code><b> 并且可以进行跳转。因此这里存在攻击点，即可以绕过</b><code class="notion-inline-code"><b>getAuthority </b></code><b> 校验加载恶意html，在html内部使用</b><code class="notion-inline-code"><b>JavaScript</b></code><b> 构造重定向请求，然后跳转到指定的非导出Activity</b></div><div class="notion-blank notion-block-c195465d153347b2a032bd2e246411df"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-631779f71fa749d9bf08d862f80be25d" data-id="631779f71fa749d9bf08d862f80be25d"><span><div id="631779f71fa749d9bf08d862f80be25d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#631779f71fa749d9bf08d862f80be25d" title="3. TestActivity"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3. TestActivity</span></span></h4><div class="notion-text notion-block-c8652283ff7b47a19d9ff2f92d44c81a"><code class="notion-inline-code"><b>TestActivity</b></code><b> 则通过</b><code class="notion-inline-code"><b>getStringExtra(&quot;url&quot;)</b></code><b> 直接拿到一个url并且使用</b><code class="notion-inline-code"><b>webview</b></code><b>进行加载，没有进行任何校验，因此存在攻击点，即通过</b><code class="notion-inline-code"><b>TestActivity</b></code><b>进行恶意网页的加载。</b></div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-d7877e615fc44c25a9993a9f0866f296" data-id="d7877e615fc44c25a9993a9f0866f296"><span><div id="d7877e615fc44c25a9993a9f0866f296" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d7877e615fc44c25a9993a9f0866f296" title="4.FlagReceiver"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">4.FlagReceiver</span></span></h4><div class="notion-text notion-block-f87933d57e804d1c8fadaf27806a7b16"><code class="notion-inline-code"><b>FlagReceiver</b></code><b> 则通过</b><code class="notion-inline-code"><b>cookieManager </b></code><b> 设置了一个</b><code class="notion-inline-code"><b>cookie</b></code><b>值，该值就是</b><code class="notion-inline-code"><b>flag</b></code><b> ，而该cookie值存储在</b><code class="notion-inline-code"><b>/data/data/com.bytectf.easydroid/app_webview/Cookies</b></code><b>中，该组件在环境启动时收到flag从而设置flag，因此攻击目标即为获取该</b><code class="notion-inline-code"><b>Cookies</b></code><b>文件</b></div><div class="notion-blank notion-block-8de943313b1c4446893547d9b828c8e9"> </div><hr class="notion-hr notion-block-909a2931f92447e0ad6fb67956f12a0d"/><div class="notion-blank notion-block-54b2ee354576487fa35a78e2c80d5604"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-7f27728e2c5949f8b631ec4229c3c354" data-id="7f27728e2c5949f8b631ec4229c3c354"><span><div id="7f27728e2c5949f8b631ec4229c3c354" class="notion-header-anchor"></div><a class="notion-hash-link" href="#7f27728e2c5949f8b631ec4229c3c354" title="二、攻击APP构造"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">二、攻击APP构造</span></span></h3><div class="notion-blank notion-block-7e72c5440ff24565952f891c94fd3df9"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-d5f1266a01f04e1280829f2000dd8022" data-id="d5f1266a01f04e1280829f2000dd8022"><span><div id="d5f1266a01f04e1280829f2000dd8022" class="notion-header-anchor"></div><a class="notion-hash-link" href="#d5f1266a01f04e1280829f2000dd8022" title="1. 构造demo验证可行性"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. 构造demo验证可行性</span></span></h4><div class="notion-text notion-block-ccd6e1c4dd254bb7836d0779c72afcb6">首先编写一个APP用于验证攻击的可行性，设置三个<code class="notion-inline-code">Activity</code>，验证能否绕过<code class="notion-inline-code">url校验</code>并且顺利实现跳转。</div><div class="notion-text notion-block-f35450fb601d452f8964dd94db5a341a"><b>绕过方案：</b><code class="notion-inline-code"><b>http://toutiao.com@xxx.xxx.xxx.xxx/evil.html</b></code> 则可以实现对<code class="notion-inline-code">getAuthority().contains(&quot;toutiao.com&quot;)</code> 的绕过，并且实际访问的是<code class="notion-inline-code"><b>xxx.xxx.xxx.xxx/evil.html</b></code>， 而访问的<code class="notion-inline-code"><b>evil.html</b></code><b> 中可以通过</b><code class="notion-inline-code">location.href</code> 使app获取到<code class="notion-inline-code"><b>Intent Url </b></code>：</div><div class="notion-text notion-block-44789e14908549fcbf0138f4f0e9833f"><code class="notion-inline-code">&quot;intent:pwneasydroid#Intent;launchFlags=0x3;package=com.bytectf.pwneasydroid;component=com.bytectf.pwneasydroid/.Third;end&quot;</code></div><div class="notion-text notion-block-6d2af5b762a049089f76861c1d4eff31">当<code class="notion-inline-code"><b>shouldOverrideUrlLoading</b></code><b> </b>拦截到该<code class="notion-inline-code"><b>url</b></code>时通过<code class="notion-inline-code">startActivity(Intent.parseUri(url,1))</code> 跳转到目标Activity。</div><div class="notion-text notion-block-8239260798984a6dbca3099d5e79a5f2">编写<code class="notion-inline-code"><b>evil.html</b></code><b> </b>使APP跳转到<code class="notion-inline-code"><b>Third</b></code><b> </b></div><div class="notion-text notion-block-eccd39715f39448ca3156a9821f31d46"><code class="notion-inline-code"><b>logcat</b></code>输出验证了绕过方案的可行性并且能够成功跳转至<code class="notion-inline-code"><b>Third</b></code></div><div class="notion-text notion-block-7235578565dc478d9f0a70e9f445253c">在实际攻击中可以设置<code class="notion-inline-code"><b>S.url</b></code>，控制被攻击APP 跳转到百度，因为在被攻击的<code class="notion-inline-code"><b>TestActivity</b></code>中获取了额外的属性<code class="notion-inline-code"><b>url</b></code>并且进行加载</div><div class="notion-blank notion-block-3c4cf8baf2e34bc98711492148a4d38e"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-fa28a4cac3464829b12e8965bd440d12" data-id="fa28a4cac3464829b12e8965bd440d12"><span><div id="fa28a4cac3464829b12e8965bd440d12" class="notion-header-anchor"></div><a class="notion-hash-link" href="#fa28a4cac3464829b12e8965bd440d12" title="2. 攻击方案"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. 攻击方案</span></span></h4><div class="notion-text notion-block-4405e7832dad438bb6e07fe95df4a5fe">总的来说，<b>首先肯定是绕过校验并且使被攻击APP跳转至TestActivity然后加载不经过任何校验的恶意网页，然后想办法窃取被攻击APP私有目录下的Cookies文件</b></div><div class="notion-blank notion-block-5b0d079df17445b6a665b8ba1f5ef761"> </div><blockquote class="notion-quote notion-block-e02da2f125e04e3fba8fec7f783850fc"><div><s><span class="notion-red"><b>方案一：符号链接延迟跨源攻击，</b></span></s>操纵WebView去访问一个攻击APP自己公开出来的网页，<b>然后这个网页执行的内容其实就是延时去读取自身</b>。在延时读取自身的时间窗口内，<b>这个文件悄悄被进行了替换，替换成了软链接，指向受害APP的一个私有文件</b>，最终读取窃取其内容。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-272be997a379455aabe301cbbd7ced53"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F6476846c-a974-4b89-8f88-7765116e595b%2FUntitled.png?table=block&amp;id=272be997-a379-455a-abe3-01cbbd7ced53&amp;t=272be997-a379-455a-abe3-01cbbd7ced53&amp;width=757.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-43d41b05ccea449baff59fdef042ada7"><b>限制：该漏洞在Android7.0及以上修复，而题目环境为Android8.1，因此无法使用该方法进行攻击，但是在搭建的Android6.0环境上成功实施了攻击</b></div><table class="notion-simple-table notion-block-6d74f0ff89944362b813ed632a99d059"><tbody><tr class="notion-simple-table-row notion-block-95e4a651022c45da84bde4962a26d3f5"><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>方法</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>作用/风险</b></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell"><b>默认策略</b></div></td></tr><tr class="notion-simple-table-row notion-block-84611dbbe4b34ea3ac65e8ff14ed55a7"><td class="" style="width:120px"><div class="notion-simple-table-cell">setAllowFileAccess(true)</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">设置是否允许 WebView<span class="notion-red"><b> 使用 File 协议访问文件系统</b></span></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell"><span class="notion-red"><b>在API29及以下默认设置为 true</b></span></div></td></tr><tr class="notion-simple-table-row notion-block-61b26b5b62214224bc4c3a34eb898f6e"><td class="" style="width:120px"><div class="notion-simple-table-cell">setAllowFileAccessFromFileURLs(true)</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">方法用于设置是否允许在文件方案URL的上下文中的跨源请求访问其他文件URL的内容。该方法在API级别30中已被弃用，并且不安全。相反，应使用<code class="notion-inline-code"><b>androidx.webkit.WebViewAssetLoader</b></code>以安全方式加载文件内容</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">在 Android <b>4.1</b> 后默认禁止 
在<b>API30</b>中已被弃用</div></td></tr><tr class="notion-simple-table-row notion-block-50321285ecb04ddf9cf7654bf2bfcac8"><td class="" style="width:120px"><div class="notion-simple-table-cell">setAllowUniversalAccessFromFileURLs(true)</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">用于设置是否允许在文件方案URL的上下文中的跨源请求访问任何其他来源的内容。如果应用程序需要访问文件系统，最好避免使用<code class="notion-inline-code"><b>file://</b></code>URL。而是使用通过HTTPS加载文件的替代方法，例如<code class="notion-inline-code"><b>androidx.webkit.WebViewAssetLoader</b></code></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">在 Android 4.1 后默认禁止</div></td></tr><tr class="notion-simple-table-row notion-block-f87e5d7790904975acbe6b43697e9fac"><td class="" style="width:120px"><div class="notion-simple-table-cell">setJavaScriptEnabled(true)</div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">设置是否允许 WebView <span class="notion-red"><b>使用 JavaScript</b></span></div></td><td class="" style="width:120px"><div class="notion-simple-table-cell">默认不允许</div></td></tr></tbody></table><div class="notion-callout notion-blue_background_co notion-block-8a69e3b50b89405db9ce752019cff1de"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">注意：在Android10及以下默认<code class="notion-inline-code"><b>setAllowFileAccess(true)</b></code><b>  ，而该漏洞不需要</b><code class="notion-inline-code"><b>setAllowFileAccessFromFileURLs</b></code>和<code class="notion-inline-code"><b>setAllowUniversalAccessFromFileURLs</b></code><b> 设置为True即可进行攻击，即绕过了</b><span class="notion-red"><b>同源检测（必须File读取File本身，读取其他文件还是无法绕过同源策略）</b></span><b>，但是依旧需要</b><code class="notion-inline-code"><b>setJavaScriptEnabled</b></code><b>设置为True</b></div></div><details class="notion-toggle notion-block-7ba2803ea9cd477785fcfeed28398a8b"><summary>MainActivity源码</summary><div></div></details><details class="notion-toggle notion-block-5fdddf1f5c8a478489e99f394d9f5bfa"><summary>evil.html源码</summary><div></div></details><details class="notion-toggle notion-block-f483c4c06d954f6ea32177cb3054faa3"><summary>Android6.0攻击结果</summary><div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-39efee073b984e2f913af61e46639d6c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F57100f49-7449-459e-b98a-d56ce885579b%2FUntitled.png?table=block&amp;id=39efee07-3b98-4e2f-913a-f61e46639d6c&amp;t=39efee07-3b98-4e2f-913a-f61e46639d6c&amp;width=729.9921875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details></blockquote><div class="notion-blank notion-block-2431f045a678401da9120b01c3ce9854"> </div><div class="notion-blank notion-block-1bfb4639317e498b851eea4145bbf3fa"> </div><blockquote class="notion-quote notion-block-4404c722b80d42e8838fcb93f7c8fbac"><div><span class="notion-red"><b>方案二：污染Cookies窃取数据</b></span></div><div class="notion-text notion-block-6ad94491232147589860d00983bd95e3">在这个方案里，需要先通过访问恶意HTML将恶意js插入Cookies中，然后控制被攻击APP访问Cookies本身，触发恶意代码造成数据泄露</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-b3e19be4085e44a7bba761ec4dec9296"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fcfc509a5-11ad-4fcc-80eb-262cab832260%2FUntitled.png?table=block&amp;id=b3e19be4-085e-44a7-bba7-61ec4dec9296&amp;t=b3e19be4-085e-44a7-bba7-61ec4dec9296&amp;width=757.984375&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-ccbdd6470380408c8ccd7b2a4d3c651e"><span class="notion-red"><b>具体的攻击思路:  </b></span><b>首先攻击者APP跳转到被攻击APP的</b><code class="notion-inline-code"><b>MainActivity</b></code><b>，使其访问</b><code class="notion-inline-code"><b>evil.html</b></code><b> 在该恶意html中设置cookies并且延时40s执行intent跳转，设置cookies即设置恶意代码，等待后续被读取渲染时运行恶意代码，即等待cookies写入到被攻击APP目录下的</b><code class="notion-inline-code"><b>Cookies</b></code><b>文件中后跳转到</b><code class="notion-inline-code"><b>TestActivity</b></code><b> ，然后</b><code class="notion-inline-code"><b>TestActivity</b></code><b> 加载url：</b><code class="notion-inline-code"><b>file:///data/data/com.bytectf.pwneasydroid/files/symlink.html</b></code><b> ，这个url将会读取</b><code class="notion-inline-code"><b>pwneasydroid</b></code><b> 数据目录下的一个symlin.html，该html创建于跳转到被攻击</b><code class="notion-inline-code"><b>MainActivity</b></code><b> 至跳转到</b><code class="notion-inline-code"><b>TestActivity</b></code><b> 这段时间，使其指向</b><code class="notion-inline-code"><b>/data/data/com.bytectf.easydroid/app_webview/Cookies</b></code><b> ，然后</b><code class="notion-inline-code"><b>TestActivity</b></code><b> 中</b><code class="notion-inline-code"><b>webview</b></code><b>加载时触发到插入到Cookies里的恶意代码，使其读取Cookies本身并且发送到远程，即可成功实现Cookies泄露，flag就在Cookies中</b></div><div class="notion-callout notion-blue_background_co notion-block-7829b3c06b8e4751b21e40650c002100"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">这里需要格外注意<span class="notion-red"><b>权限问题：</b></span><b>不仅需要给</b><code class="notion-inline-code"><b>/data/data/com.bytectf.pwneasydroid/files</b></code><b> 及目录下的文件777权限，而且还要给</b><code class="notion-inline-code"><b>/data/data/com.bytectf.pwneasydroid</b></code><b> 这个目录的777权限，否则将会访问失败</b></div></div><details class="notion-toggle notion-block-8a7d2fff02e147d0ac7799d1da2735cb"><summary>MainActivity</summary><div></div></details><details class="notion-toggle notion-block-f081cba580c4434e8ee7f6e2d883f93c"><summary>evil.html</summary><div></div></details><details class="notion-toggle notion-block-70bf8dfa677f4eecaf31d2bbaf983e88"><summary>Android8.1攻击效果</summary><div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-9137075e80a243ce851e315dd60fd550"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:293px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F033dff2d-cb2b-48b6-8d1d-0aa54c11ccdf%2FUntitled.png?table=block&amp;id=9137075e-80a2-43ce-851e-315dd60fd550&amp;t=9137075e-80a2-43ce-851e-315dd60fd550&amp;width=293&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-b0e2d6cf31f5488c986c4fcf28c389d4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fb63f90ed-239a-4979-a3d2-a3de8e246420%2FUntitled.png?table=block&amp;id=b0e2d6cf-31f5-488c-986c-4fcf28c389d4&amp;t=b0e2d6cf-31f5-488c-986c-4fcf28c389d4&amp;width=1343&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure></div></details></blockquote><div class="notion-blank notion-block-0d0b37e7270a48389b41640c5f2deec0"> </div><div class="notion-blank notion-block-bd3e43a6e40d48589f36ff686d859363"> </div><hr class="notion-hr notion-block-1c7bc828010b4486a176185e60238ebe"/><div class="notion-blank notion-block-06e1de420e0a4c63adf8a345296951df"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-44c02239c6d24a80aeae3fdf62ae8b26" data-id="44c02239c6d24a80aeae3fdf62ae8b26"><span><div id="44c02239c6d24a80aeae3fdf62ae8b26" class="notion-header-anchor"></div><a class="notion-hash-link" href="#44c02239c6d24a80aeae3fdf62ae8b26" title="三、总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">三、总结</span></span></h3><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-cadfd7652d544450a1ab5f9f24a5156a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F3e71a656-9895-4d17-a498-222d6db12c97%2FUntitled.png?table=block&amp;id=cadfd765-2d54-4450-a1ab-5f9f24a5156a&amp;t=cadfd765-2d54-4450-a1ab-5f9f24a5156a&amp;width=792.96875&amp;cache=v2" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-callout notion-blue_background_co notion-block-035551f606cf4aed9714518712352967"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">虽然题目本身考点不难，但是操作起来很费劲，尤其需要关注Android环境
然后就是目录的权限问题，如果不设置<code class="notion-inline-code"><b>/data/data/packagename</b></code><b> 为777，那被攻击APP就无法读取到目录下的恶意html，导致攻击失败</b></div></div><hr class="notion-hr notion-block-d3d57a25fb6b4bcbad9e06bde90622fc"/><div class="notion-blank notion-block-1e68928dbc8f4cf3b100369c82a09eff"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-f6eb8a52fe494914b36c8e08e0108434" data-id="f6eb8a52fe494914b36c8e08e0108434"><span><div id="f6eb8a52fe494914b36c8e08e0108434" class="notion-header-anchor"></div><a class="notion-hash-link" href="#f6eb8a52fe494914b36c8e08e0108434" title="四、参考"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">四、参考</span></span></h3><ol start="1" class="notion-list notion-list-numbered notion-block-141ebaed76214561bb6943b1ebe8d532" style="list-style-type:decimal"><li><a class="notion-link" href="https://shvu8e0g7u.feishu.cn/docs/doccndYygIwisrk0FGKnKvE0Jhg#" target="_blank" rel="noopener noreferrer">Docs (feishu.cn)</a></li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-31573780ab2a441da54c63e48ce7d2c1" style="list-style-type:decimal"><li><a class="notion-link" href="https://blog.csdn.net/qq_35993502/article/details/121371049" target="_blank" rel="noopener noreferrer">(72条消息) Android安全检测－WebView File域同源策略绕过漏洞_webview同源策略漏洞_asjhan的博客-CSDN博客</a></li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-e9de5ccbd2d04eac839478899f9ed573" style="list-style-type:decimal"><li><a class="notion-link" href="https://bbs.kanxue.com/thread-273867.htm" target="_blank" rel="noopener noreferrer">[原创]Android APP漏洞之战（13）——WebView漏洞详解-Android安全-看雪-安全社区|安全招聘|kanxue.com</a></li></ol><div class="notion-blank notion-block-95f27421068b403589ba92486206c164"> </div><div class="notion-blank notion-block-bb2cc50637e5411a8ce5cc2ea94e3392"> </div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>