Xposed框架食用指南

 

前言

对于App来说,Hook技术应用非常广泛。比如朋友圈微信步数的修改,其实就是Hook了数据发送的方法实现步数的修改。再比如处理安卓的SSL Pining,也是用Hook技术修改的SSL证书校验结果,实现校验的绕过。Xposed Hook的方式为直接打包并激活插件即可,再某些情况下使用相比于Frida更加方便。

 

Xposed简介

Xposed是一个运行于Android操作系统的钩子框架。其通过替换Android系统的关键文件,可以拦截几乎所有Java函数的调用,并允许通过Xposed模块中的自定义代码更改调用这些函数时的行为。因此,Xposed常被用来修改Android系统和应用程序的功能。
Xposed Installer是Xposed框架的官方安装器,可以在拥有root权限的设备上安装Xposed框架。Xposed Installer也提供模块的下载、管理、日志显示等功能。
该项目地址为:

https://repo.xposed.info/module/de.robv.android.xposed.installer

由于Android新版本的普及,目前新上市的手机基本都是8.0以上。所以Xposed框架已经不适用。EdXposed团队成为Xposed停止更新后的官方接任者。
Xposed衍生品
edxposed、太极、ratel(平头哥)、VA(2B)

准备环境

Google Pixel 3XL手机 欧版
Android 11
Mac
twrp
Magisk

TWRP Recovery

首先电脑准备好新版的adb、fastboot命令工具。
可以通过命令adb devices来验证是否允许adb调试:

➜ adb devices
List of devices attached
FA6XXXXXXX53    device

通过fastboot devices命令验证fastboot是否成功:

➜ fastboot devices
FA6AB0311758    fastboot

在命令提示符窗口键入fastboot flashing unlock并回车,手机进入Bootloader解锁界面。

fastboot flashing unlock
...
OKAY [  0.049s]
finished. total time: 0.049s

由于我的测试机是Android 11,所以要刷EdXposed。大致思路很简单,也是最容易成功的步骤:先刷三方Rec(这里是TWRP),然后装Magisk,最后通过Magisk装EdXposed。
由于Pixel及Pixel XL都采用A/B升级系统,因而可以理解为手机里有2个系统,如果你按照传统刷入Twrp的方法刷入的话,那么你并不会获得一个永久的Twrp。所以需要先刷入一个临时的Twrp,在通过临时的Twrp来刷入永久的Twrp从而来获取Root权限。
首先,前往TWRP官网Devices下载最新版临时TWRP镜像文件.img。

我的Pixel 3XL对应选择从这个页面Download TWRP for crosshatch 下载的3.6.0-11版本:

下载新版Magisk放入手机中

https://github.com/topjohnwu/Magisk/releases

然后手机电脑连起来,先重启手机进入fastboot模式

adb reboot bootloader
# 然后把刚才下载并重命名好的img刷入
fastboot flash recovery bbbbt.img
# 执行完此就会自动进入Recovery模式
fastboot boot bbbbt.img

由于pixel无法刷入永久的twrp,所以使用fastboot boot bbbbt.img输入临时的twrp。

Magisk

通过进入twrp然后找到install,进行安装Magisk.zip文件

经过验证,只要点击顶部的twrp界面的install Zip,蓝色条部分左侧的图标处,就会返回Team Win Recovery Project界面。依照上面的安装步骤安装Magisk.zip文件。
重启发现已成功安装Magisk(脸谱Logo图标)。

这时为了检测一下手机是否root成功,我们安装wifi adb并运行,发现软件请求的超级用户权限。下图为软件开启root权限:

EdXposed

当安装EdXosed时,使用官网给出的办法

https://github.com/ElderDrivers/EdXposed

发现因Magisk更新的原因,并不像老版本一样可以在资深的manage下载模块中搜索安装Riru,需要手动下载Riru进行安装到Magisk模块中。
首先需要进入从Magisk Manage中安装Riru

测试发现新版Riru无法成功安装Riru-EdXposed,选择老版本Riru即可安装成功。

https://github.com/RikkaApps/Riru
https://github.com/ElderDrivers/EdXposed/releases

然后去https://github.com/ElderDrivers/EdXposedManager/releases下载EdXposed Manager的Apk来安装。
打开EdXposed后发现提示框架已激活,证明该EdXposed成果安装了

下面我们尝试一下安装他人编写的EdXposed模块来更改下系统电池显示,首先下载Gravitybox选择对应的安卓版本。

安装之后重启运行,发现可以任意的修改手机设置。

接下来我们要做的就是在不修改APK源码的情况下,通过自己编写的模块来影响程序运行的框架服务,实现类似的功能。

 

Xposed 插件开发

Xposed模块简介

Xposed框架原理是部署在ROOT后的安卓手机上,通过替换/system/bin/app_process程序控制zygote进程,使得app_process在启动过程中会加载XposedBridge.jar,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。可以让我们在不修改APK源码的情况下,通过自己编写的模块来影响程序运行的框架服务,实现类似于自动抢红包、微信消息自动回复等功能。
根据官方tutorial,典型的插件开发流程分为:

加入Xposed Framework API
修改AndroidManifest.xml
编写hook代码
将类注册到assets/xposed_init文件中去

Xposed模块编写

首先使用AndroidStudio新建一个Empty Activity工程。

然后把项目查看方式设置为Project,在 “项目名称/app/src/main/”目录下找到AndroidManifest.xml,并在指定位置插入以下三段代码:

输入代码后,将测试手机连上AndroidStudio ,点击“运行”手机就会启动刚刚编写的这个程序。手机里的Xposed框架中也会显示出这个模块:

接下来需要引入XposedBridgeApi.jar,在 “项目名称/app/src/main/”目录下找到build.gradle,加入如下代码后,AndroidStuido将自动配置XposedBridgeApi.jar。完成之后, build.gradle会提示文件已经修改,点击 “sync now”,同步:

repositories {

    jcenter()

}
compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'

实现hook操作具体代码

首先在界面上增加一个按钮功能,拖动button到界面即可。

然后简单编写一下逻辑。MainActivity界面有个按钮,点击按钮后会弹出一个toast提示,该提示的内容由toastMessage()方法提供,而toastMessage()的返回值为“我未被劫持”:

我们需要做的是hook MainActivity并修改这个类的toastMessage()方法,让它的返回值为“你已被劫持”。
首先在MainActivity的同级路径下新建一个类“HookTest.java”,代码如下:

public class HookTest implements IXposedHookLoadPackage {

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

        if (loadPackageParam.packageName.equals("com.droider.xposed1")) {

            XposedBridge.log(" has Hooked!");

            Class clazz = loadPackageParam.classLoader.loadClass(

                    "com.droider.xposed1.MainActivity");

            XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {

                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

                    super.beforeHookedMethod(param);

                    //XposedBridge.log(" has Hooked!");

                }

                protected void afterHookedMethod(MethodHookParam param) throws Throwable {

                    param.setResult("你已被劫持");

                }

            });

        }

    }

}

编译安装运行

hook的代码编写完成后,进行添加入口点,方法如下:
右键点击 “main ” 文件夹 , 选择new —> Folder —>Assets Folder,新建assets 文件夹:

然后右键点击assets文件夹, new—> file,文件名为xposed_init(文件类型选text),并在其中写上入口类的完整路径自己编写的Hook类,这样Xposed框架就能够从这个 xposed_init 读取信息来找到模块的入口,然后进行Hook操作。

最后在Xposed框架里找到自己写的模块,打开并重启,发现toast的提示已经变为了hook加载后的结果,提示“你已被劫持”。

还可以通过加入过滤子进程的api如loadPackageParam.processName等api来实现相关操作。

如使用loadPackageParam.processName可以看到日志里打印出了该手机的进程

 

Xposed系统定制

市面上大多数App都会或多或少对Xposed框架执行基于特征的检测,而绕过检测的基本思路就是找到检测的特征,无论是在Java层还是Native层,然后通过hook的方式修改返回结果,或者硬编码、直接置零返回通过等方式来通过校验。

Xposed特征修改

首先编译官方原版XPOSED,然后在此基础之上,进行源码的一些魔改,修改之后再编译刷入手机,最后可以根据新源码编译出来的API进行插件开发,实现从源码来bypass框架检测的目的。

XposedInstaller

1、修改整体包名
在包名路径中,将xposed改成xppsed,这样可以保证包名长度是一样,同时xposed特征消失不见,选择Refactor→Rename

然后把所有的de.robv.android.xposed.installe都改成de.robv.android.xpsed.installer
-w760
2、修改xposed.prop
将xposed.prop改成xppsed.prop即可

修改完之后进行编译。

XposedBridge

1、修改整体包名
将xposed进行重构,改成xppsed

2、生成文件
将编译出来的文件复制一份,命名为XppsedBridge.jar

Xposed

将libxposed_common.h、Xposed.h、xposed_service.cpp、xposed_shared.h、ART.mk、libxposed_art.cpp进行修改

#define XPOSED_PROP_FILE "/system/xppsed.prop"
#define XPOSED_LIB_ART XPOSED_LIB_DIR "libxppsed_art.so"
#define XPOSED_JAR "/system/framework/XppsedBridge.jar“
#define XPOSED_CLASS_DOTS_ZYGOTE "de.robv.android.xppsed.XposedBridge"
#define XPOSED_CLASS_DOTS_TOOLS "de.robv.android.xppsed.XposedBridge$ToolEntryPoint"
IMPLEMENT_META_INTERFACE(XposedService, "de.robv.android.xppsed.IXposedService");
#define XPOSED_DIR "/data/user_de/0/de.robv.android.xppsed.installer/"
#define XPOSED_DIR "/data/data/de.robv.android.xppsed.installer/"
libxppsed_art.cpp
LOCAL_MODULE := libxppsed_art

XposedTools

在XposedTools中将build.pl和zipstatic/_all/META-INF/com/google/android/flash-script.sh的字符替换

xposed.prop--->xppsed.prop
XposedBridge.jar--->XppsedBridge.jar
libxposed_art--->libxppsed_art

源码编译

编译后将镜像刷入手机:

fastboot flash system system.img

然后利用XposedCheck进行特征检测

将XPOSED源码的进行魔改之后再编译刷入手机,实现了从源码来Bypass维框架检测的目的。
当然一般情况下,只需要简单修改XPOSED的字符串,过简单的根据字符串特征的XPOSED检测是没有问题的。

 

总结

本文介绍了Xposed的基本理念、安装使用、模块编写、系统定制和特征去除,并通过案例来实现了Xposed Hook App的流程。

 

参考资料

https://cloud.tencent.com/developer/article/1738371
https://www.jianshu.com/p/fdece2fbff1c
https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
http://www.itfanr.cc/2018/10/16/google-pixel-unlock-bl-and-root/
https://blog.csdn.net/ysy950803/article/details/107118656

(完)