###懒惰是科技的第一生产力
0x00 背景
- 由于Android逆向每次想要使用Xposed进行Hook时,总是需要重复性地操作一遍Android Studio新建项目的流程.ps:当然可以只用一个项目,强迫症需要分开 :)
- 由于Xposed实现的方式,每次修改hook代码后,需要重启机器,这也是白白浪费了很多时间。
- 基于以上两点,参考现有的方案,实现了一个Module,只需在AS中new一下即可解决问题。
0x01 创建XposedModule
1.效果:
2.代码结构:
3.代码解析:
template.xml:
1 |
|
recipe.xml.ftl
1 |
|
xposed_init.ftl 存储的是 Hook类的入口地址
strings.xml.ftl 存储的是 Xpodse模块的描述
XposedMod.java.ftl 创建后的模版代码,可以根据自己的需求,修改模版里面的代码
AndroidManifest.xml.ftl 主要是Xposed的meta字段
build.gradle.ftl 为空
4.bug修复:
由于Xposed会预先加载好jar包,因此,build.gradle中的implements需要修改为provided,才不会出现错误。
具体修改build.gradle.ftl,添加下面依赖:
1 | dependencies { |
0x02 加入免重启功能
原理分析:原理这里不作多描述,实际上就是通过替换Xposed插件生成的APK,然后通过动态加载的方式来调用,以实现免重启的功能。具体可阅读参考文章。
改进:
对上面的AS模版进行改造,以实现免重启。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
65
66
67
68
69
70
71
72
73
74
75
76
77
78package ${packageName};
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import dalvik.system.PathClassLoader;
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;
public class HookLoader implements IXposedHookLoadPackage {
/**
* 当前Xposed模块的包名,方便寻找apk文件
*/
private final String modulePackage = "${packageName}";
/**
* 宿主程序的包名(允许多个),过滤无意义的包名,防止无意义的apk文件加载
*/
private static List<String> hostAppPackages = new ArrayList<>();
/**
* 实际hook逻辑处理类
*/
private final String handleHookClass = ${xposedModClass}.class.getName();
/**
* 实际hook逻辑处理类的入口方法
*/
private final String handleHookMethod = "handleLoadPackage";
static {
// TODO: Add the package name of application your want to hook!
hostAppPackages.add("${hookPackageName}");
}
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (hostAppPackages.contains(loadPackageParam.packageName)) {
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Context context=(Context) param.args[0];
loadPackageParam.classLoader = context.getClassLoader();
invokeHandleHookMethod(context, handleHookClass, handleHookMethod, loadPackageParam);
}
});
}
}
/**
* 安装app以后,通过动态加载这个apk文件,调用相应的方法
* 从而实现免重启
* @param context context参数
* @param handleHookClass 指定由哪一个类处理相关的hook逻辑
* @param loadPackageParam 传入XC_LoadPackage.LoadPackageParam参数
* @throws Throwable 抛出各种异常,包括具体hook逻辑的异常,寻找apk文件异常,反射加载Class异常等
*/
private void invokeHandleHookMethod(Context context, String handleHookClass, String handleHookMethod, XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
String apkPath = context.getPackageManager().getApplicationInfo(this.modulePackage,PackageManager.GET_META_DATA).sourceDir;
PathClassLoader pathClassLoader = new PathClassLoader(apkPath, ClassLoader.getSystemClassLoader());
Class<?> cls = Class.forName(handleHookClass, true, pathClassLoader);
Object instance = cls.newInstance();
Method method = cls.getDeclaredMethod(handleHookMethod, XC_LoadPackage.LoadPackageParam.class);
method.invoke(instance, loadPackageParam);
}
}
文章作者是通过区分不同的sdk以实现找到apk的findapk的方法,实际上这里有很简便的方法:
通过系统API便可找到对应的apk路径:
一行代码即可搞定
1 | String apkPath = context.getPackageManager().getApplicationInfo(this.modulePackage,PackageManager.GET_META_DATA).sourceDir; |
0x03 产出
- XpdModule 需重启
- XpdFreeRebootModule 免重启
公司不让用Github,暂时无法上传代码,以后有机会再上传。
参考文章 & 致谢
Xposed Module Template for Android Studio
感谢参考文章的作者以及同事。