Xposed 开发之模块调试篇

百度搜索 Xposed断点调试,会发现关于这方面的教程几乎约等于没有,也有很多人说 Xposed 模块没法断点调试,但是经过我一番实践,确定 Xposed 模块是可以断点调试的,不信请往下看。

简单示例

举一个最简单的例子,创建一个空模块,里面包含一个 Activity 和 hook 代码:

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
if (!lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) {
return;
}
XposedHelpers.findAndHookMethod(MainActivity.class.getName(), lpparam.classLoader, "onCreate", Bundle.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
Log.i(TAG, "onCreate in hook");
}
});
}

然后安装运行(Shift+F10),确保模块已经正常生效,然后在 Log.i 那一行打上断点,然后再以 Debug 模式启动(Shift + F9)。

可以看到确实是可以调试的,但是这里调试的是我们自己写的应用,然而在实际开发中,我们一般 hook 的都是别人的应用,所以我们来创建一个新的 hookme 来试一下。

跨应用调试

运行 hookme 发现 hook 代码的确是执行了,但是断点形同虚设,原因很简单,因为我们少了一步 Shift + F9,在没有 hookme 源码的情况下,我们虽然不能直接 Shift + F9 (即使你有源码也没用),但是我们可以手动搞一个出来

Shift + F9 先后干了两件事情:

  1. adb shell am start -n package/activity -D
  2. Attach Debugger to Android Process

我们只需要把里面的包名和 Activity 换成 hookme 的就行了,首先用执行命令以 debug 模式启动 hookme:

1
$ adb shell am start -D -n me.zpp0196.library.hookme/.MainActivity

接着手机上会出现一个 Waiting For Debugger 的对话框提示正在等待调试器连接。

接下来我们手动让 Debugger attach 到这个进程上,点击 Android Studio 右上角的这个小虫子。

在弹出来的对话框里面选择我们的 hookme 进程。

点击 OK,可以看到也是可以调试的。

萌新看了一眼进度条发现事情并不简单。


正文开始

使用上面的 hookme 来测试还不够严谨,因为这个 hookme 是我们自己创建的,我们啥都没有干直接运行, 这个时候安装的默认是 debug 版,正是因为是 debug 版所以可以调试,但其实我们 hook 的应用一般都是 release 版,可以试一下安装 release 版并执行 am start -D -n 命令后并不会出现 Waiting For Debugger 这个对话框,debugger 也 attach 不到它的任何进程,这时候我们有两种做法:

  1. adb shell && su && resetprop ro.debuggable 1 && setprop ctl.restart zygote_secondary

  2. 反编译 hookme 并在 AndroidManifest.xml 里面的 <application> 节点中添加 android:debuggable="true"

这里先采用第一种开启全局调试开关的方式,修改完 ro.debuggable 后按照上面的步骤再试一次,你会发现,这并没有什么用,至于原因嘛我也不知道(是我太菜了)。

接下来是第二种,如果直接反编译修改重新打包安装的话,可能会出现意想不到的惊喜,而且那个时代已经过去了,在 2014 年那会还都是直接反编译改 apk,那会的 apk 基本也都没有签名校验什么的,但是这都过去五年多了,这条路基本已经走不通了。别灰心,上帝为我们关上了一扇门,但也为我们打开了一扇窗,反编译不行了我们还有 Xposed 啊:

1
2
3
4
5
6
7
8
9
10
11
XposedBridge.hookAllMethods(android.os.Process.class, "start", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
String niceName = (String) param.args[1];
int runtimeFlags = (int) param.args[5];
if (!niceName.equals(packageName)) {
return;
}
param.args[5] = runtimeFlags | 1 | 1 << 7 | 1 << 8;
}
});

重启手机后再按上面的步骤试一下,这下应该没问题了吧,不用自己写的 hookme,换一个其他应用试一下也是没有问题的。