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

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

2022-4-13 15:56
42497

zygisk是什么

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

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

对于zygisk的理解

  • zygisk依然是magisk,但是是更高级的版本,带了注入Zygote功能。
  • zygisk的开启是可选的,在magisk设置。如不开启将和原来差不多。
  • zygisk将提供超过之前magisk的功能,尤其是注入hook。所以可以基于zygisk开发出lsp(新的xp框架)而且不基于riru。
  • riru和zygisk对Zygote的修改部分重复了,所以二者不能很好共存。
  • zygisk没有hide,因为作者加入了谷歌之后不再做检测对抗了。

magisk实现原理

在magisk上有一行说明:systemless root

 

那么这个systemless是什么东西

 

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

root原理(来自网络)

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

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

之前的root方式
 

这个不细说了

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

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

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

systemless root

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

 

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

 

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

 

基于systemless的root就是 systemless root

 

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

magisk实现方式

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

magisk刷入过程
  • 安装magisk apk
  • 提取boot.img
  • 制作修改的patch_boot.img
  • 刷入patch_boot.img开机即可

不难得出核心在于针对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实现原理

在了解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 源码分析
实际上这篇文章已经写的非常详细了,我加上了一点自己的理解。算是拾人牙慧了。

太长不看版本

先总结一下整个流程

  • module.cpp中判断是否开启zygisk_enabled,是就进入
    mount_zygisk进行 app_process的 mount,将
    app_process替换成magisk
  • main.cppmagisk执行文件,作用是替换app_process工作(原理是用 LD_PRELOAD 注入)
  • entry.cpp加载Zygisk,分为两个阶段加载。一阶段dlopen载入二阶段,二阶段进行hook。 其他的细节包括hide hook处理看源码分析。
注入阶段
native/jni/core/module.cpp
 

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

 

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

 

app_process进行处理的函数在magic_mount

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

 

 

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

mount_zygisk 函数
 

 

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

 

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

 

完成文件的app_processmagisk的替换

 

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

 

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

 

加载阶段

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

 

包括hook的实现逻辑

native/jni/zygisk/main.cpp
 

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

 

Entrypoint for app_process overlay

 

对着这个注释往下看

app_process_main 函数
 

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

 

ZygiskRequest::SETUP是通信的标志

 

 

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

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

native/jni/zygisk/entry.cpp

找到消息接收的地方

 

进入setup_files函数
 

 

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

 

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

 

尤其是

 

 

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

 

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

native/jni/zygisk/entry.cpp

 

zyg_init函数

 

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

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

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

下面分析两个阶段的事情

first_stage_entry
 

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

 

 

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

 

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

 

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

 

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

 

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

 

同时进行第一次的 android_dlopen_ext

second_stage_entry
 

获取MAGISKFD_ENV的值进行 path

 

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

 

恢复 变量 MAGISKTMP_ENV MAGISKFD_ENV

 

 

在结束的时候,调用了

  • sanitize_environ();
  • hook_functions();

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

 

hook_functions 具体的hook实现部分

hook实现

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

native/jni/zygisk/hook.cpp
 

核心的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来分析

nativeSpecializeAppProcess_pre/nativeSpecializeAppProcess_post

 

可以发现核心就是两个

  • run_modules_pre(module_fds);

  • run_modules_post();

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

 

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

hookAndSaveJNIMethods
 

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

 

HOOK_JNI
 

三个函数的hook

  • HOOK_JNI(nativeForkAndSpecialize)
  • HOOK_JNI(nativeSpecializeAppProcess)
  • HOOK_JNI(nativeForkSystemServer)

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

 

 

实现hook后引入

native/jni/zygisk/jni_hooks.hpp

实现具体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 源码分析


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2022-4-13 16:02 被小黄鸭爱学习编辑 ,原因: 勘误
收藏
点赞10
打赏
分享
最新回复 (8)
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
简单的人生 2022-4-13 19:13
2
1
6
雪    币: 52
活跃值: (495)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
万里星河 2022-4-14 20:46
3
0
支持亿下
雪    币: 15
活跃值: (337)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
科科搞安全 2022-6-11 14:38
4
0
支持大佬
雪    币: 1936
活跃值: (12810)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
珍惜Any 2 2022-6-12 23:34
5
0
好贴,收获了。
雪    币: 244
活跃值: (266)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
数字云信息 2022-6-13 13:41
6
0
好贴
雪    币: 121
活跃值: (1512)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xxRea 2022-6-18 23:14
7
0
好贴,感谢大佬分享
雪    币: 215
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
觇望 2022-7-22 04:16
8
0
"本身ASOP"
这里是 AOSP 吧?
雪    币: 5453
活跃值: (1422)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
DemoCc 2023-8-22 15:21
9
0
666
游客
登录 | 注册 方可回帖
返回