初次接触Xposed开发[Xposed]
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
更新时间:
2020-09-07 22:53:15
温馨提示:
学无止境,技术类文章有它的时效性,请留意文章更新时间,如发现内容有误请留言指出,防止别人"踩坑",我会及时更新文章
开发环境
xposed文档 http://api.xposed.info/reference/de/robv/android/xposed/package-summary.html
android 5.1
androidStudio 3.0.1
需要的文件
XposedInstaller xposed框架安装地址 https://forum.xda-developers.com/showthread.php?t=3034811
手机要root下载完成后直接按提示安装就可以
XposedBridge api下载地址 https://bintray.com/rovo89/de.robv.android.xposed/api
下载后有两个jar包
一个示例
打开androidstudio新建一个项目,实现检测系统中所有app启动的时候输出包的路径到日志中
修改AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.keli.wechatx"> <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"> <meta-data android:name="xposedmodule" android:value="true"/> <meta-data android:name="xposeddescription" android:value="hello xposed"/> <meta-data android:name="xposedminversion" android:value="82"/> <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>
添加api库
把下载的两个jar文件放入libs目录中,然后从androidstudio中添加进去
添加完后还要修改一个地方,在编译的时候这两个库是不能编译进去的,因为xposed框架里已经有这些库啦,编译进去就导致重复,会报错
找到app的构建脚本 build.gradle文件
dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2' implementation files('libs/api-82.jar') implementation files('libs/api-82-sources.jar') }
改为
dependencies { // implementation fileTree(include: ['*.jar'], dir: 'libs') compileOnly fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2' //源码 implementation files('libs/api-82.jar') //文档,方便查看说明 implementation files('libs/api-82-sources.jar') }
新建XModule类,继承IXposedHookLoadPackage
这个类是在所有app重启的时候都会调用的类
public class XModule implements IXposedHookLoadPackage { @Override public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { XposedBridge.log("load app:"+lpparam.packageName); if (lpparam.packageName.equals("com.tencent.mm")) { XposedBridge.log("...........find it............"); } } }
功能就是输出启动的app包路径
添加xposed的启动包引入文件
新建assets文件夹
然后在这个文件夹中新建一个xposed_init的文件输入com.example.XModule
运行效果
实现修改指定app界面上TestView的值
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.keli.wechatx.MainActivity"> <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
java hook
public class XModule implements IXposedHookLoadPackage { @Override public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { XposedBridge.log("load app:"+lpparam.packageName); //如果是指定包的话,就hook这个包里的MainActivity类的onCreate这个方法,修改文字 if (lpparam.packageName.equals("com.xxx")) { XposedHelpers.findAndHookMethod("com.xxx.MainActivity", lpparam.classLoader, "onCreate", Bundle.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { //不能通过Class.forName()来获取Class ,在跨应用时会失效 Class c=lpparam.classLoader.loadClass("com.xxx.MainActivity"); Field field=c.getDeclaredField("textView"); field.setAccessible(true); //param.thisObject 为执行该方法的对象,在这里指MainActivity TextView textView= (TextView) field.get(param.thisObject); textView.setText("Hello Xposed"); } }); } } }
添加钩子的另一种写法
if (lpparam.packageName.equals("com.xxx")) { Class clazz; //加载对应的类 clazz = lpparam.classLoader.loadClass("com.xxx.MainActivity"); //hook类中对应的方法 XposedHelpers.findAndHookMethod(clazz, "onCreate", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { //不能通过Class.forName()来获取Class ,在跨应用时会失效 Class c=lpparam.classLoader.loadClass("com.xxx.MainActivity"); Field field=c.getDeclaredField("textView"); field.setAccessible(true); //param.thisObject 为执行该方法的对象,在这里指MainActivity TextView textView= (TextView) field.get(param.thisObject); textView.setText("Hello Xposed"); } }); }
强制okhttp3走系统代理
原理为hook okhttp3的proxy方法,设置的时候直接返回
// hook okhttp3 Class Builder = lpparam.classLoader.loadClass("okhttp3.OkHttpClient$Builder"); Class Proxy = lpparam.classLoader.loadClass("java.net.Proxy"); XposedHelpers.findAndHookMethod(Builder, "proxy", Proxy, new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable { return methodHookParam.thisObject; } });