入门开发

  • 崔大

免root方案: LSpatch

下载:https://github.com/LSPosed/LSPatch

教程:https://www.52pojie.cn/thread-1598175-1-1.html

原理:将编写好的xposed.apk注入到目标apk文件,生成一个新的apk

关于版本问题

image.png

Android Studio 连接夜神

先确保adb能连上虚拟机,连不上运行 adb connect 127.0.0.1:62001,AS直接运行就可以将app装到模拟器

频繁掉线的问题,AS的adb版本和模拟器自带adb版本不一样导致,解决:https://blog.csdn.net/qq910689331/article/details/124115640

基本步骤,详细参考正己课程

  1. libs 导入 XposedBridgeAPI,然后 add as library ...

https://github.com/924587628/XposedBridgeAPI/blob/master/XposedBridgeAPI-89.jar

  1. AndroidManifest 引入下列 meta
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 是否是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="89" />
  1. 修改 build.gradle,改成 compileOnly

image.png

  1. 创建Hook入口,在 Assets新建 xposed_init 文件,标明 hook类的位置

image.png

image.png

  1. 创建第四步中的hook类,初始内容为:

必须继承自 IXposedHookLoadPackage 和 handleLoadPackage 才有hook效果

1
2
3
4
5
6
7
8
9
import de.robv.android.xposed.IXposedHookLoadPackage; 
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class Hook类名 implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {

}
}
  1. 点击 run,等待一段时间,模块编译成功

image.png

  1. 导出 apk 文件

image.png

一些常用操作

  • 添加依赖,在 app > build.gradle > dependencies 添加,然后 sync now ...
  • 重启手机后,查看日志,需要 restart logcat

模板脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.example.xposed_demo_202408;

import android.util.Log;

import com.google.gson.Gson;

import java.io.IOException;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class HookCxs implements IXposedHookLoadPackage {
@Override
// 这几行写法固定
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedHelpers.findAndHookMethod("com.shizhuang.duapp.modules.du_mall_common.utils.product.BaseMallProductItemView", loadPackageParam.classLoader, "update", new Object[]{Object.class, new XC_MethodHook() {
// 具体hook点
protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
}

protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Object resultObj = param.args[0];
Gson gson = new Gson();
String resultObjStr = gson.toJson(resultObj);
Log.d("cxs", resultObjStr);
sendJsonData(resultObjStr);
}
}});
}

private void sendJsonData(String data) {
// 使用okhttp发送拦截的数据,必须在其它线程运行
new Thread(() -> {
try {
String url = "http://10.0.248.77:1427/dewu-hook";
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(data, MediaType.get("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String responseBody = response.body().string();
Log.d("cxs", "JSON POST Response: " + responseBody);
} else {
Log.e("cxs", "JSON POST Error response: " + response.code() + " " + response.message());
}
} catch (IOException e) {
e.printStackTrace();
Log.e("cxs", "JSON POST Error", e);
}
}).start();
}
}
gradle 依赖
1
2
3
compileOnly(files("libs\\XposedBridgeAPI-89.jar"))
implementation("com.google.code.gson:gson:2.8.6")
implementation("com.squareup.okhttp3:okhttp:4.9.0")

Hook 技巧

xposed rpchttps://juejin.cn/post/6970958353673486343

渲染 / 视图组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MyXposedModule implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if ("目标应用包名".equals(lpparam.packageName)) {
XposedHelpers.findAndHookMethod(
View.class,
"setOnTouchListener",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
View view = (View) param.thisObject;
System.out.println("View touched: " + view);
}
}
);
}
}
}

指定类下所有方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class clazz = (Class) param.getResult();
String clazzName = clazz.getName();
// if(clazzName.contains("")){
if(clazzName.equals("com.shizhuang.duapp.modules.du_mall_common.utils.product.BaseMallProductItemView")){
Method[] mds = clazz.getDeclaredMethods();
for(int i =0;i<mds.length;i++){
final Method md = mds[i];
int mod = mds[i].getModifiers();
// 去除抽象、native、接口方法
if(!Modifier.isAbstract(mod)
&& !Modifier.isNative(mod)
&&!Modifier.isAbstract(mod)){
XposedBridge.hookMethod(mds[i], new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d("cxs_call", "传参:" + param.args[0].toString());
Log.d("cxs_call", "方法:" + md.toString());
}
});
}

}
}

}
});