这里封装了 hook 逻辑和转换逻辑,本质上是对 Activity 对应的 Intent 对象进行了规则的提取和转换,这里我绘制了一张逻辑图,只需要 hook 之后点击界面即可获得这个界面的 am 启动命令。
有一种特殊情况,是界面本身通过 Fragment 实现而不是 Activity 实现,这种方式本身就不能通过 am 命令实现。
image_1680860454809_0.png (52.54 KB, 下载次数: 0)
下载附件
2023-4-7 18:38 上传
就是,只要结果输出了,那么就是可用的 am 命令。
记得删除其中的一些无用的东西,如带有时间戳信息的可能会被 onCreate 方法中的逻辑判断为过期,从而崩溃;
也可以替换其中的一些东西,比如一个 app 的搜索页,可以替换为默认关键词,从而可以节省一步 set_text
image_1680848776242_0.png (46.46 KB, 下载次数: 0)
下载附件
2023-4-7 18:38 上传
[JavaScript] 纯文本查看 复制代码
function intentToAmCommand(intent) {
let amCommand = "am start"
let action = intent.getAction()
let categories = intent.getCategories()
let type = intent.getType()
let component = intent.getComponent()
let flags = intent.getFlags()
let extras = intent.getExtras()
if (action !== null) {
amCommand += ` -a ${action}`
}
if (categories && categories.length > 0) {
categories.forEach(category => {
amCommand += ` -c ${category}`
})
}
if (type !== null) {
amCommand += ` -t ${type}`
}
if (component !== null) {
amCommand += ` -n ${component.getPackageName()}/${component.getClassName()}`
}
if (flags !== 0) {
amCommand += ` -f ${flags}`
}
if (extras !== null) {
amCommand += ` -e`
let iter = extras.keySet().iterator()
while (iter.hasNext()) {
let key = iter.next()
let value = extras.getString(key)
amCommand += ` "${key}" "${value}"`
}
}
return amCommand
}
function logIntentAm(intent) {
// 打印对应 am 命令
console.log(`
}
function hookOnCreate() {
let Activity = Java.use("android.app.Activity");
console.log("
Activity.onCreate.overload('android.os.Bundle').implementation = function (arg1) {
let theIntent = this.getIntent()
logIntentAm(theIntent)
return this.onCreate(arg1)
};
}
setTimeout(() => {
Java.perform(() => {
console.log("----- FRIDA start mocking -----");
try { hookOnCreate(); } catch (err) { console.error(err.stack); }
console.log("----- FRIDA finish mocking ----");
})
}, 2000)