睿诚科技协会

Android Hook技术实例如何实现具体功能?

实例目标

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

Android Hook技术实例如何实现具体功能?-图1
(图片来源网络,侵删)

假设 App 的行为: App 在 MainActivityonCreate 方法中执行了 Toast.makeText(this, "Hello from Original App", Toast.LENGTH_SHORT).show();

我们的目标: 将 Toast 的内容修改为 "Hello from Xposed Module!"。


第一步:准备工作

  1. 一台 Root 的 Android 手机或模拟器:Xposed 框架需要 Root 权限来修改系统文件和进行进程注入。
  2. 安装 Xposed Installer:这是管理 Xposed 框架和模块的 App,你可以从 Xposed 官方网站或 GitHub 下载最新的 APK 并安装。
  3. 安装一个 Xposed Bridge 版本:你需要为你的 Android 系统版本下载对应的 Xposed Bridge 版本,并通过 Xposed Installer 的 "模块" -> "安装/更新" 来安装它,安装后需要重启手机。
  4. Android Studio:用于开发我们的 Xposed Module。

第二步:创建 Xposed Module 项目

  1. 新建项目:打开 Android Studio,创建一个新的 "Empty Activity" 项目。

  2. 添加依赖:在你的 app/build.gradle 文件中,添加 Xposed API 的依赖,请根据你安装的 Xposed Bridge 版本选择对应的 API 版本。

    Android Hook技术实例如何实现具体功能?-图2
    (图片来源网络,侵删)
    dependencies {
        // ... 其他依赖
        implementation 'de.robv.android.xposed:api:82'
        implementation 'de.robv.android.xposed:api:82:sources' // 可选,方便查看源码
    }
  3. 配置 Module 信息:在 app/build.gradle 文件中,添加 xposed 块来声明你的模块信息。

    android {
        // ... 其他配置
        defaultConfig {
            // ... 其他配置
        }
        // 添加这一块
        xposed {
            compileSdkVersion = 34 // 或者你的 targetSdkVersion
            moduleName = "MyXposedModule"
            moduleVersion = "1.0"
            minSdkVersion = 21
            targetSdkVersion = 34
        }
    }
  4. 配置 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。

  1. 创建 Hook 处理类:在 com.example.myxposedmodule 包下,创建一个名为 HookHandler 的新 Java 类。

    Android Hook技术实例如何实现具体功能?-图3
    (图片来源网络,侵删)
  2. 编写 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():定义一个回调,它包含两个关键方法:beforeHookedMethodafterHookedMethod
      • beforeHookedMethod:在原始 onCreate 方法执行前,我们先弹出一个自定义的 Toast。
      • afterHookedMethod:在原始方法执行后,我们打印一条日志。

第四步:激活和测试

  1. 编译并安装模块:在 Android Studio 中编译你的 Module,然后将生成的 APK (app/build/outputs/apk/debug/app-debug.apk) 安装到你的手机上。

  2. 激活模块

    • 打开 Xposed Installer App。
    • 进入 模块 列表。
    • 找到你的模块 "MyXposedModule",并勾选它激活。
    • 重启你的手机或模拟器,这一步至关重要,Xposed 需要重启才能加载新的或已更改的模块。
  3. 运行目标 App

    • 确保你的目标 App (com.example.targetapp) 也已经安装。
    • 打开这个目标 App。
    • 预期结果:App 启动时,你应该会看到两个 Toast。
      1. 第一个是我们的模块弹出的:"Hello from Xposed Module!"
      2. 第二个是目标 App 原本弹出的:"Hello from Original App"
  4. 查看日志:Hook 没有生效,可以查看 Xposed Installer 的 日志 选项卡,看看是否有错误信息,这有助于你定位问题(比如包名或类名写错了)。


高级一点:Hook 一个静态方法

Hook 静态方法也很常见,Hook System.currentTimeMillis() 来模拟时间。

目标:让目标 App 调用 `System.currentTimeMillis

分享:
扫描分享到社交APP
上一篇
下一篇