背景: 改变系统方法、统计方法调用栈、点击事件打点上报等等,在这些需求场景,需要用到Hook技术,Xposed框架可以帮助我们实现Hook方案。
Xposed的使用有2点限制条件 1 需要Root 2 适用于Android4~Android9, 在Android10会有无法访问网络的问题
无法Root问题:使用用VitualXposed
建立一个Android工程 app/build.gradle文件中添加xposed依赖
compileOnly 'de.robv.android.xposed:api:82'新建一个Java类,实现IXposedHookLoadPackage接口,用来Hook方法
package com.example.test; import android.telephony.TelephonyManager; 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.LoadPackageParam; /** * Created by zhengwei on 2020/9/2. */ public class HookUtil implements IXposedHookLoadPackage { @Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { XposedBridge.log("hook app: " + lpparam.packageName); // 检测自己demo工程中getDevice()方法的引用,并打印调用堆栈 if (lpparam.packageName.contains("com.xxx.demo")) { XposedHelpers.findAndHookMethod(TelephonyManager.class, "getDeviceId", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); printStackTrace(); } }); } } private void printStackTrace() { XposedBridge.log("--------------->"); Throwable ex = new Throwable(); StackTraceElement[] stackElements = ex.getStackTrace(); for (int i = 0; i < stackElements.length; i++) { StackTraceElement element = stackElements[i]; XposedBridge.log("at " + element.getClassName() + "." + element.getMethodName() + "(" + element .getFileName() + ":" + element.getLineNumber() + ")"); } } }assets目录新建xposed_init文件,没有后缀名,将IXposedHookLoadPackage的实现类添加其中
com.example.test.HookUtilapp/src/main/AndroidManifest.xml文件配置Xposed模块属性
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test"> <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/AppTheme"> <!-- 是否是xposed模块,xposed根据这个来判断是否是模块 --> <meta-data android:name="xposedmodule" android:value="true" /> <!-- 模块描述,显示在xposed模块列表那里第二行 --> <meta-data android:name="xposeddescription" android:value="测试Xposed模块" /> <!-- 最低xposed版本号(lib文件名可知) --> <meta-data android:name="xposedminversion" android:value="53" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>未Root的设备,有VirtualXposed、taichi等方案来实现Hook。
VirtualXposed方案 https://github.com/android-hacker/VirtualXposed/releases
太极方案: https://taichi.cool/zh/download.html https://github.com/taichi-framework/TaiChi/releases
本文采用VirtualXposed方案演示, 环境:Android9.0, 没有Root
https://github.com/android-hacker/VirtualXposed/releases
下载VirtualXposed应用,安装至测试设备,VirtualXposed主界面类似launcher的样子。
VirtualXposed安装成功后,会默认安装Xposed Installer,可以通过设置-应用管理查看。 将实现了Xposed接口的app、待检测的app添加至VirtualXposed
设置-模块管理 检查Xposed模块是否能被检测到,然后按照指示,重启VirtualXposed
打开待检测应用,用Xposed过滤Logcat日志。