rn 主要是 js 为核心代码,所以主逻辑在 js 。如果想了解业务,那就 看js 。
怎么找资源代码
首先从应用包里面找到 index.android.bundle 。
也可以加钩子
final Class aClass = XposedHelpers.findClass("com.facebook.react.bridge.CatalystInstanceImpl", lpparam.classLoader);
XposedBridge.hookAllMethods(aClass, "loadScriptFromAssets", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Utils.log("资源名是 %s", param.args[1]);
return null;
}
});
找到文件名之后,就可以提取出来。
怎么看代码?
可以用 IDE 工具来 format , 有的 IDE 不支持大文件格式化。这里我用了 sublime 来格式化。
格式化完之后代码看起来就比较清晰。
熟悉 javascript 的人应该很快可以找到 模块定义的特点。他的定义是
__d(function(g, r, i, a, m, e, d) {
var n = r(d[0]);
Object.defineProperty(e, "__esModule", {
value: !0
}), e.default = void 0;
var t = n(r(d[1])),
o = r(d[2]),
h = r(d[3]),
l = r(d[4]),
...
}, 1861, [1, 10, 907, 549, 658]);
这样的结构。其中 1861 为模块 id , 后面的数组 是引用的模块。 d[?] 为取引用模块的索引。
找界面元素,可以找 render 方法,结合 关键字。
如何调试?
final Class aClass = XposedHelpers.findClass("com.facebook.react.bridge.CatalystInstanceImpl", lpparam.classLoader);
XposedBridge.hookAllMethods(aClass, "loadScriptFromAssets", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
Utils.log("资源名是 %s", param.args[1]);
// 把他改为 从 制定目录下读取. 成功~~~
XposedHelpers.callMethod(param.thisObject, "loadScriptFromFile", "/data/user/0/xxxxxxxxxx/cache/index.android.bundle", "", param.args[2]);
return null;
}
});
把 js 换为从文件读取即可。 如果你要用 远程去读也是可以的。
怎么上传?
把文件提取出来格式化后,做了修改,即可直接用 adb push 来上传。这里用 sdcard 目录中转一下。
cd `dirname $0`
adb push ./index.android.js /sdcard/
adb shell su -c mv /sdcard/index.android.js /data/user/0/xxxxxxxxxxx/cache/index.android.bundle
怎么设置日志?
alert 和 console.log 都可以用。
搜索一下 g.alert
在这个代码之后,我重写了 console.log
g.console.log = (function (oriLogFunc) {
return function () {
oriLogFunc('xposed',...arguments)
}
})(g.console.log);
这样查看日志的时候,直接 adb logcat | grep -i xposed 就可以看到输出的日志。
怎么读逻辑?
结合console.log 给各个关键节点埋日志呗。对象也比较好输出。
注意理解 rn 的 status 的特点