实例目标
我们的目标是 Hook 一个简单的 Android App,使其在启动时弹出一个我们自定义的 Toast 消息,而不是 App 原本的内容。

假设 App 的行为:
App 在 MainActivity 的 onCreate 方法中执行了 Toast.makeText(this, "Hello from Original App", Toast.LENGTH_SHORT).show();。
我们的目标: 将 Toast 的内容修改为 "Hello from Xposed Module!"。
第一步:准备工作
- 一台 Root 的 Android 手机或模拟器:Xposed 框架需要 Root 权限来修改系统文件和进行进程注入。
- 安装 Xposed Installer:这是管理 Xposed 框架和模块的 App,你可以从 Xposed 官方网站或 GitHub 下载最新的 APK 并安装。
- 安装一个 Xposed Bridge 版本:你需要为你的 Android 系统版本下载对应的 Xposed Bridge 版本,并通过 Xposed Installer 的 "模块" -> "安装/更新" 来安装它,安装后需要重启手机。
- Android Studio:用于开发我们的 Xposed Module。
第二步:创建 Xposed Module 项目
-
新建项目:打开 Android Studio,创建一个新的 "Empty Activity" 项目。
-
添加依赖:在你的
app/build.gradle文件中,添加 Xposed API 的依赖,请根据你安装的 Xposed Bridge 版本选择对应的 API 版本。
(图片来源网络,侵删)dependencies { // ... 其他依赖 implementation 'de.robv.android.xposed:api:82' implementation 'de.robv.android.xposed:api:82:sources' // 可选,方便查看源码 } -
配置 Module 信息:在
app/build.gradle文件中,添加xposed块来声明你的模块信息。android { // ... 其他配置 defaultConfig { // ... 其他配置 } // 添加这一块 xposed { compileSdkVersion = 34 // 或者你的 targetSdkVersion moduleName = "MyXposedModule" moduleVersion = "1.0" minSdkVersion = 21 targetSdkVersion = 34 } } -
配置 AndroidManifest.xml:在
app/src/main/AndroidManifest.xml中,声明你的模块需要 Xposed 框架,并指定入口类。<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myxposedmodule"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyXposedModule"> <!-- 关键:声明 Xposed 模块入口 --> <meta-data android:name="xposedmodule" android:value="true" /> <meta-data android:name="xposeddescription" android:value="A simple Xposed module to hook a Toast" /> <meta-data android:name="xposedminversion" android:value="82" /> </application> </manifest>
第三步:编写 Hook 逻辑
这是核心步骤,我们将创建一个类来处理 Hook。
-
创建 Hook 处理类:在
com.example.myxposedmodule包下,创建一个名为HookHandler的新 Java 类。
(图片来源网络,侵删) -
编写 Hook 代码:在
HookHandler中,我们将使用 Xposed API 来 Hook 目标 App 的onCreate方法。package com.example.myxposedmodule; import android.app.Application; import android.content.Context; import android.os.Bundle; import android.widget.Toast; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookHandler implements IXposedHookLoadPackage { // 定义要 Hook 的包名,这里用一个示例 App 的包名 // 请替换成你想要 Hook 的真实 App 的包名 private final String TARGET_PACKAGE_NAME = "com.example.targetapp"; @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { // 只处理我们目标包名的 App if (!lpparam.packageName.equals(TARGET_PACKAGE_NAME)) { return; } XposedBridge.log("MyXposedModule: Hooking package " + TARGET_PACKAGE_NAME); // Hook MainActivity 的 onCreate 方法 // 参数1: 要 hook 的类 // 参数2: 要 hook 的方法名 // 参数3: 方法的参数类型 // 参数4: hook 后要执行的回调 XposedBridge.hookAllMethods( lpparam.classLoader.loadClass("com.example.targetapp.MainActivity"), "onCreate", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // 在原始方法执行前运行 // 'param' 对象包含了方法的所有信息,如参数、返回值等 // 获取 Context 对象,通常在 onCreate 的第一个参数 Context context = (Context) param.args[0]; // 弹出我们自定义的 Toast Toast.makeText(context, "Hello from Xposed Module!", Toast.LENGTH_LONG).show(); XposedBridge.log("MyXposedModule: Toast shown before onCreate()"); } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { // 在原始方法执行后运行 // 如果我们想阻止原始 Toast,可以在这里调用 param.setResult(null) 来阻止其执行 // 但在这个例子中,我们只想在它之前显示一个,所以不需要阻止 XposedBridge.log("MyXposedModule: Original onCreate() finished"); } }); } }代码解释:
implements IXposedHookLoadPackage:这是模块的入口接口,Xposed 会在加载每个 App 时调用其handleLoadPackage方法。TARGET_PACKAGE_NAME:非常重要,这里必须填写你想要 Hook 的那个 App 的包名,你可以通过在手机上运行该 App,然后使用adb shell dumpsys activity top | grep pkg命令来获取。XposedBridge.hookAllMethods(...):这是 Hook 方法的核心。lpparam.classLoader.loadClass("..."):使用目标 App 的类加载器来加载MainActivity类。注意:这里的类名必须是目标 App 中完整的类名。"onCreate":我们要 Hook 的方法名。new XC_MethodHook():定义一个回调,它包含两个关键方法:beforeHookedMethod和afterHookedMethod。beforeHookedMethod:在原始onCreate方法执行前,我们先弹出一个自定义的 Toast。afterHookedMethod:在原始方法执行后,我们打印一条日志。
第四步:激活和测试
-
编译并安装模块:在 Android Studio 中编译你的 Module,然后将生成的 APK (
app/build/outputs/apk/debug/app-debug.apk) 安装到你的手机上。 -
激活模块:
- 打开 Xposed Installer App。
- 进入 模块 列表。
- 找到你的模块 "MyXposedModule",并勾选它激活。
- 重启你的手机或模拟器,这一步至关重要,Xposed 需要重启才能加载新的或已更改的模块。
-
运行目标 App:
- 确保你的目标 App (
com.example.targetapp) 也已经安装。 - 打开这个目标 App。
- 预期结果:App 启动时,你应该会看到两个 Toast。
- 第一个是我们的模块弹出的:"Hello from Xposed Module!"。
- 第二个是目标 App 原本弹出的:"Hello from Original App"。
- 确保你的目标 App (
-
查看日志:Hook 没有生效,可以查看 Xposed Installer 的 日志 选项卡,看看是否有错误信息,这有助于你定位问题(比如包名或类名写错了)。
高级一点:Hook 一个静态方法
Hook 静态方法也很常见,Hook System.currentTimeMillis() 来模拟时间。
目标:让目标 App 调用 `System.currentTimeMillis
