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

您所在的位置:网站首页 splash_preload是什么文件夹 [原创]zygisk原理简单分析和以及zygisk插件开发(1)

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

#[原创]zygisk原理简单分析和以及zygisk插件开发(1)| 来源: 网络整理| 查看: 265

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.cpp 是magisk执行文件,作用是替换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_process到magisk的替换

 

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

 

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

 

加载阶段

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

 

包括hook的实现逻辑

native/jni/zygisk/main.cpp 

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

 

Entrypoint for app_process overlay

 

对着这个注释往下看

app_process_main 函数 

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

 

ZygiskRequest::SETUP是通信的标志

 

 

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

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

native/jni/zygisk/entry.cpp

找到消息接收的地方

 

进入setup_files函数 

 

buf 获取了可执行路径sendfd 发送持有的真正的 app_process 文件 fdwrite_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(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();

pre和post调用用于执行插入的hook code。

 

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

最后

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

 

参考

 

Zygisk 源码分析

物联网安全入门

最后于 2022-4-13 16:02 被小黄鸭爱学习编辑 ,原因: 勘误 #基础理论 #NDK分析 #HOOK注入 #源码框架


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3