首页
社区
课程
招聘
[原创]zygisk原理简单分析和以及zygisk插件开发(1)
发表于: 2022-4-13 15:56 49425

[原创]zygisk原理简单分析和以及zygisk插件开发(1)

2022-4-13 15:56
49425

来自面具作者的文章对于zygisk的介绍

Zygisk是Zygote的Magisk。这将在Zygote进程中运行Magisk的一部分,使Magisk模块更强大。这也是Magisk"退出舞台"理念中非常重要的一部分。当某一个进程位于上述拒绝列表中时,Magisk 将清理该过程的内存空间,以确保不会应用任何修改(P.S.1)。当然,Zygisk 仍然是 WIP(开发中)的,一旦实施准备好测试,会公布更多细节。

在magisk上有一行说明:systemless root

那么这个systemless是什么东西

在了解systemless之前我们还要了解什么是root以及如何获得root

下面是来自网络的root解释,年代已久不过我感觉还是有用的。

root权限就是root(管理员权限)用户的权限,该权限可以修改根目录下的文件

为了让我们的应用使用root权限

首先我们需要一个处理root请求的 su 进程

我们链接手机到电脑 输入adb shell

再输入 su 如果没root就会提示 su文件找不到

ok 既然没有这个文件那我们就push这个su执行文件到
/system/bin 下面吧

不行,因为你没有root权限所以不能向system传输文件

同样的因为你不能传输文件也就不能植入su 应用程序

也就是没法让你获得root权限 这就是死循环

这个不细说了

利用系统漏洞提权注入。这个方式很多,早期版本的系统用的多。现在系统越来越安全基本难以实现。

定制内核修改system分区的方式。

厂商会定制开发版本自带root权限。在于本身ASOP就支持userdebug版本模式去编译的。

之前的root会对system目录做文件修改

而systemless root 则不会对system目录做任何修改

这是为了应对高版本的系统的检测

基于systemless的root就是 systemless root

magisk 是实现 systemless root 的一个方式,实际上在magisk之前就有systemless root。只不过magisk把这个发扬光大了。

在之前做过magisk的分析,我把答案抄过来。

不难得出核心在于针对boot.img文件的修改

那么修改的patch_boot.img具体做了什么是我们最关心的

开机 打开面具的日志这里

可以看到这里在

/sbin/.magisk/mirror 下面建立了一个系统根目录的镜像目录

我们打开文件的时候就会发现 sbin 里面还拥有一个su执行文件和模块插件等其他文件

然后进行 bind mounted 操作,也就是让这个文件系统生效。

这时候ps -A其实就可以看到 su 进程,也就有了授权root的能力。

接下来就可以用magisk来管理root权限,请求root的都会出现在超级用户这个列表里。

同时基于 bind mount 可以针对系统文件进行替换以及在这里执行sh脚本,这就是我们写的magisk模块的实现了。

非常多的细节可以在https://topjohnwu.github.io/Magisk/details.html 里面得到,或许我的理解会有误差。

在了解zygisk之前,先了解magisk的功能实现原理。我这里分析zygisk关于注入Zygote的逻辑。

在分析之前我就在猜想他的实现原理了。

xposed注入Zygote原理是替换 app_process,而magisk可以做到替换系统文件。那么magisk是不是可以替换app_process来注入Zygote。

虽然zygisk是新一点东西 好在已经有人分析过了。可以踩在巨人的肩上了。

在magisk仓库里面搜索 app_process 果然找到了相关代码

打开main.cpp看到一行注释

// Entrypoint for app_process overlay

确认无疑了,对app_process进行了替换


Zygisk 源码分析
实际上这篇文章已经写的非常详细了,我加上了一点自己的理解。算是拾人牙慧了。

先总结一下整个流程

搜索 app_process 出现最多的就是这个module.cpp文件

打开文件看到bind_mount 就知道这个类对文件进行了挂载。

app_process进行处理的函数在magic_mount

mount是Linux下的一个命令,它可以将分区挂接到Linux的一个文件夹下,从而将分区和该目录联系起来,因此我们只要访问这个文件夹,就相当于访问该分区了。

新建文件夹后mount_zygisk处理挂载文件夹

两件事:文件移动和文件夹挂载

app_process 32/64 放到了zygisk下面
magisk 32/64 放到了 MAGISKTMP 下面

完成文件的app_processmagisk的替换

做完这些之后,我们重启手机启动运行的app_process其实就是运行magisk

我们其实可以看到这些文件的

这部分核心研究跑起来的magisk跑起来之后具体做了什么

包括hook的实现逻辑

运行了magisk文件,现在进入他的函数分析他的逻辑。

Entrypoint for app_process overlay

对着这个注释往下看

通过socker通信设置几个变量的值 LD_PRELOAD INJECT_ENV_1
MAGISKTMP_ENV

ZygiskRequest::SETUP是通信的标志

这里非常核心的一个就是 LD_PRELOAD 变量的值设置,这将作用到后面的注入

LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。

找到消息接收的地方

buf 获取了可执行路径
sendfd 发送持有的真正的 app_process 文件 fd
write_string 发送 MAGISKTMP 路径

到这里我开始发现与参考文件不同的地方了

尤其是

根本对不上,zygisk下面也没有对应的so文件

那就是改版了,下面就自己分析新版zygisk的原理吧

zyg_init函数

这里进行两阶段的加载操作

判断INJECT_ENV_1 进行一阶段加载 这个在 app_process_main进行设置的

在一阶段加载加载完成阶段设置二阶段标志 INJECT_ENV_2

下面分析两个阶段的事情

一阶段:好在作者加了大段注释 ,我谷歌翻译一遍

在这里我发现 LD_PRELOAD 是个非常重要的变量

修改这个值就可以加载我们的注入的程序

这里一阶段就是来加载 LD_PRELOAD 的文件

这个文件就是之前 app_process_main设置的

获取fd的值这里最终将这个值写入到 MAGISKFD_ENV

同时进行第一次的 android_dlopen_ext

获取MAGISKFD_ENV的值进行 path

进入 android_dlopen_ext 再一次 dlopen 并立马关闭

恢复 变量 MAGISKTMP_ENV MAGISKFD_ENV

在结束的时候,调用了

sanitize_environ 字面意思就是 消毒环境。就是用于对抗检测的,消灭证据。具体实现这里不是重点。

hook_functions 具体的hook实现部分

我们已经将自己的文件注入进去,现在要实现hook

核心的hook_functions 处于这个类

我们核心关注XHOOK_REGISTER(ANDROID_RUNTIME, jniRegisterNativeMethods); 这部分的逻辑

在之前的riru分析中,我们已经了解过这种hook的实现方法。基于xhook,对register方法进行hook后做个指针的切换。

几个重要的宏定义

XHOOK_REGISTER
使用 xhook register

DCL_HOOK_FUNC
对函数进行hook

DCL_PRE_POST
定义函数的per和post两种

比如 fork定义了 fork_pre 和 fork_post

挑一对 pre和post来分析

可以发现核心就是两个

run_modules_pre(module_fds);

run_modules_post();

也就是运行modules插入的hook代码

这个两个方法需要记得后面继续分析。

执行hook操作的方法 核心的hook逻辑

三个函数的hook

这三个函数是app进程启动的Zygote中三个相关函数,是应用进程或者系统服务进程被fork 出来的时候会调用的方法。

实现hook后引入

实现具体hook的地方,在这里区分了版本和手机类型。将新旧方法做了保存和指针更换处理。

比如这个就是安卓Q版本的hook处理逻辑,这里有个重要的HookContext结构体。

核心的三句

ctx.nativeSpecializeAppProcess_pre();

reinterpret_cast<decltype(&nativeSpecializeAppProcess_q)>(nativeSpecializeAppProcess_orig)( env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name,
is_child_zygote, instruction_set, app_data_dir);

ctx.nativeSpecializeAppProcess_post();

prepost调用用于执行插入的hook code。

而中间那句就是执行原方法orgin

分析到这里差不多,未完待续。后面还有关于如何zygisk屏蔽应用以及如何load moudules 代码的有时间再说。

参考


Zygisk 源码分析

 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-4-13 16:02 被小黄鸭爱学习编辑 ,原因: 勘误
收藏
免费 11
支持
分享
最新回复 (10)
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
6
2022-4-13 19:13
1
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
支持亿下
2022-4-14 20:46
0
雪    币: 15
活跃值: (337)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持大佬
2022-6-11 14:38
0
雪    币: 3355
活跃值: (14008)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
5
好贴,收获了。
2022-6-12 23:34
0
雪    币: 244
活跃值: (266)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好贴
2022-6-13 13:41
0
雪    币: 120
活跃值: (1597)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好贴,感谢大佬分享
2022-6-18 23:14
0
雪    币: 124
活跃值: (72)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
"本身ASOP"
这里是 AOSP 吧?
2022-7-22 04:16
0
雪    币: 5453
活跃值: (1482)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
666
2023-8-22 15:21
0
雪    币: 2141
活跃值: (4522)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
觇望 "本身ASOP" 这里是 AOSP 吧?
是的
2024-8-16 14:44
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
牛 支持 学习
2024-10-18 18:44
0
游客
登录 | 注册 方可回帖
返回
//