# XposedHook Demo **Repository Path**: brozer/XposedHook-Demo ## Basic Information - **Project Name**: XposedHook Demo - **Description**: Xposed 框架学习demo实例 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2020-08-01 - **Last Updated**: 2025-11-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一 什么是 hook **hook 本质就是劫持函数调用**,但由于处于 linux 用户态,每个进程都有自己独立的进程空间,所以必须先注入到所要 hook 的进程空间,修改其内存中的进程代码,替换其过程表的符号地址。 **Android 中一般通过 ptrace 函数附加进程,然后向远程进程注入 so 库,从而达到监控以及远程进程关键函数挂钩。Hook 的难点在于寻找函数的入口点、替换函数,这就涉及到函数的连接与加载机制。** # 二 Xposed ## 1、Xposed 框架实现 Hook 的原理介绍 ​ zygote是Android 的核心,每运行一个App,Zygote 就会 fork 一个虚拟机实例来运行 app,Xposed Framework 深入到了 Android 核心机制中,通过改造 Zygote 来实现一些很牛逼的功能。Zygote 的启 动配置在 /init.rc 脚 本 中 , 由 系 统 启 动 的 时 候 开 启 此 进 程,对应的执行文件是 /system/bin/app_process,这个文件完成类库加载及一些函数调用的工作。 当系统中安装了 Xposed Framework 之后,会对 app_process 进行扩展,也就是说,Xposed Framework 会拿自己实现的 app_process 覆盖掉 Android 原生提供的 app_process 文件,当系统启动的时候, 就会加载由 Xposed Framework 替换过的进程文件,并且,Xposed Framework 还定义了一个 jar 包, 系统启动的时候,也会加载这个包: /data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar ## 2、Xposed 框架运行的条件 1.Rooted Device / Emulator (已 root 的手机或者模拟器) 2.Xposed Installer (Xposed 安装程序下载) 3.Hooking Android App (要被 Hook 的目标 App) Xposed Framework 就是一个 apk 包也就是上面下载的 Xposed 安装程序,下载后用下面的命令安装到手 机上或者模拟器: adb install Xposed.apk app framework C++ linux内核 linux内核 --> init --> app_process --> Zygote Zygote进程在启动过程中,除了创建一个Dalvik虚拟机实例之外,还会将Java运行时库加载到进程中来,同时还会注册一些Android核心类的JNI方法到前面创建的Dalvik虚拟机实例中去。 一个应用程序被孵化出来的时候,其不仅会获得Zygote进程中的Dalvik虚拟机实例,还会与Zygote一起共享Java运行时库,这也是可以将XposedBridge.jar这个jar包加载到每一个Android应用中的原因。 Xposed_zygote进程启动后会初始化一些so文件(system/lib system/lib64),然后进入XposedBridge.jar中的XposedBridge中加载模块,初始化jar包完成对一些关键Android系统函数的hook。 Hook则是利用修改过的虚拟机将函数注册为native函数,然后再返回zygote中完成原本zygote需要做的工作。 META-INF/ 里面有文件配置脚本 flash-script.sh 配置各个文件安装位置。 system/bin/ 替换zygote进程等文件 system/framework/XposedBridge.jar jar包位置 system/lib system/lib64 一些so文件所在位置 xposed.prop xposed版本说明文件 下载XposedBridge地址:https://github.com/ 现在安装Xposed比较方便,因为Xposed作者开发了一个Xposed Installer App,下载后按照提示傻瓜式安装(前提是root手机)。其实它的安装过程是这个样子的:首先探测手机型号,然后按照手机版本下载不同的刷机包,最后把Xposed刷机包刷入手机重启就好。 # 三 模块 和 实现一个模块 本例中的 module 叫 axht.trade.xposed, 下面是这个实例的 AndroidManifest.xml 文件,注意其中定义了三项 meta-data: - 1. Module name - 2. Module Description - 3. Module Minimum Version ``` ``` 其中 xposedminversion 是指 XposedBridge library 的版本,需要将 Xposed Library 复制到 lib目录 ( **注意是 lib 目录不是 libs 目录**),然后将这个 jar 包添加到 Build PATH 中,[jar 包可以在这里下载](http://forum.xda-developers.com/attachment.php?attachmentid=2748878&d=1400342298)。 然后在 src 目录下面建立一个 java 文件,就叫 bypass.java 吧,并在 assets 目录中新建一个叫 xposed_init 的文件,里面写上刚才建立的 java 文件的包路径,这样,我们的 apk 就可以被识别为一个 Xposed 模块了 `axht.trade.xposed.Test` 现在来看看要 hook 的 apk 包,要 hook,关键是要知道 hook 的点,即要明确要 hook 的函数名,实际使用中可以用 jeb 等反编译工具得到需要 hook 的函数名,我们这里就直接看样例 app 的源码吧: ``` package axht.trade.xposed; import android.view.View; import android.widget.EditText; import java.lang.reflect.Field; import java.security.MessageDigest; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class Test implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam pparam) throws Throwable { // pparam.processName 获取应用程序包名 // XposedBridge.log("当前启动的应用程序是:"+pparam.processName); if (pparam.packageName.equals("com.qianyu.zhuceji")) { XposedBridge.log("进入包名:"+pparam.packageName); //hook 普通方法、静态方法 XposedHelpers.findAndHookMethod( "com.qianyu.zhuceji.MainActivity", //包名+类名 pparam.classLoader, //类的加载器 "checkSN", //方法名 String.class, //参数列表 String.class, new XC_MethodHook() { /** * HOOK之前 * 打印参数信息、修改参数 * */ @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); XposedBridge.log("修改之前userName:" + param.args[0]); XposedBridge.log("修改之前sn:" + param.args[1]); String userName = (String) param.args[0]; MessageDigest digest = MessageDigest.getInstance("MD5"); digest.reset(); digest.update(userName.getBytes()); //主动调用方法 String hexstr = (String) XposedHelpers.callStaticMethod( param.thisObject.getClass(), //获取类 "toHexString", new Object[]{digest.digest(), ""}); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hexstr.length(); i += 2) { sb.append(hexstr.charAt(i)); } //修改参数 //param.args[0]="ke.yijincc.com"; //param.args[1]="3192850648@qq.com"; param.args[1] = sb.toString(); XposedBridge.log("修改之后sn:" + param.args[1]); /** * java反射机制 * */ // 获取类 Class clazz=param.thisObject.getClass(); //XposedBridge.log("clazz:"+clazz); // 获取字段 Field sn=clazz.getDeclaredField("edit_sn"); // 设置可见 sn.setAccessible(true);// 注意 EditText et_sn=(EditText) sn.get(param.thisObject); et_sn.setText(sb.toString()); } /** * HOOK之后 * 打印返回值信息、修改返回值 * */ @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); XposedBridge.log("返回值:" + param.getResult()); //修改返回值之后 //param.setResult(true); } }); //hook 匿名内部类 XposedHelpers.findAndHookMethod( "com.qianyu.zhuceji.MainActivity$1", pparam.classLoader, "onClick", View.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); View view = (View) param.args[0]; XposedBridge.log("view:" + view.getId()); } }); } } } ``` **实现模块还要完成下面几个步骤** - 1.实现 IXposedHookLoadPackage接口 - 2.指定要 hook 的包名(这里是com.attify.vuln) - 3.判断当前加载的包是否是指定的包(在接口方法中判断 - 4.指定要 hook 的方法名 - 5.实现beforeHookedMethod方法和afterHookedMethod方法(hook的具体功能) # 四 安装模块并重启 将需要被hook的app安装到模拟器或真机。将步骤三的模块安装到手机上面。打开 Xposed Installer 应用,点击模块,此时会发现模块列表已经检测到了XposedHookDeme。勾选模块,并返回主界面,点击框架,选中安装/更新,会提示重启手机。重启手机后,就能注入指定包名的app进程劫持对应的函数了。