前言

Android 使用 dex2oat 进行 dex 编译,类 Xposed 框架为了防止方法内联钩子失效,需要设置系统属性 dalvik.vm.dex2oat-flags=--inline-max-code-units=0,这可以很容易被检测到。

解决

方案

套一个假的 wrapper,在其中执行真正的 dex2oat,并添加参数 --inline-max-code-units=0

问题

  1. dex2oat 由 installd 启动,installd 以 root 权限运行,但在 exec dex2oat 前会执行降权,降权后的 dex2oat 权限与普通应用一致,无法直接访问 magisk --path
  2. linker 会识别 /apex/<name>/bin 下的二进制并自动链接一些动态库,original bin 若不在 /apex 下,启动时会找不到库
  3. 需要防止 wrapper 本身被检测到

实现

使用类似 riru 的方案,在 /dev 中建立一个随机目录,并在开机时将路径动态 hexpatch 进 wrapper 的 bin;在 /dev 目录建立建立 socket,由 unshared daemon 打开 origin bin 得到 fd,发送到 wrapper 并 fexecve

不过 /apex/com.android.art/bin/dex2oat* 的 context 是 u:object_r:dex2oat_exec:s0,wrapper 加载会触发 avc: denied { execute_no_trans } ,即使让 wrapper 的 context 为 u:r:installd:s0 仍然会触发,原因未知,因此采取折中方案复制一份 origin bin 放在 tmpdir,chcon u:object_r:magisk_file:s0 并在 daemon mount 到 /apex 再发送 fd。

Impl

最后修改:2022 年 04 月 18 日
如果觉得我的文章对你有用,请随意赞赏