apk.sh 是一个 Bash 脚本,它让 Android 应用的逆向工程更加简单,自动化了一些重复性任务,如拉取、解码、重建和修补 APK。
apk.sh 基本上使用 apktool 来反汇编、解码和重建资源,并使用一些 bash 来自动化 frida gadget 注入过程。它还支持应用束/拆分 APK。
⬅️ 从设备拉取 APK 就像运行 ./apk.sh pull <包名> 一样简单
🔧 解码 APK 就像运行 ./apk.sh decode <APK名> 一样简单
🔩 重建 APK 就像运行 ./apk.sh build <APK目录> 一样简单
apk.sh pull 从设备拉取 APK。它支持应用束/拆分 APK,这意味着拆分 APK 将被合并到一个单个 APK 中(这对修补很有用)。如果包是应用束/拆分 APK,apk.sh 会将 APK 合并成一个单独的 APK,并修复所有公共资源标识符。
apk.sh patch 修补 APK 以在启动时加载 frida-gadget.so。
frida-gadget.so 是 Frida 的一个共享库,旨在由需要被插桩的程序加载(当注入操作模式不适用时)。只需加载该库,你就可以使用现有的基于 Frida 的工具(如 frida-trace)与其交互。它还支持完全自主的方式,可以从文件系统运行脚本,无需任何外部通信。
修补 APK 就像运行 ./apk.sh patch <APK名> --arch arm 一样简单。
你也可以在 JSON 中指定 Frida gadget 配置:./apk.sh patch <APK名> --arch arm --gadget-conf <config.json>
如果你遇到像 #30 中那样的 "already interned" apktool d 错误,可以传递 --only-main-classes 标志,它会在解码 APK 时传递给 apktool。
在默认交互中,Frida Gadget 暴露一个与 frida-server 兼容的接口,默认监听 localhost:27042。为了实现早期插桩,Frida 让 Gadget 的构造函数阻塞,直到你执行 attach() 附加到进程,或者经过通常的 spawn() -> attach() -> ...应用插桩... 步骤后调用 resume()。
如果你不希望这种阻塞行为,想让程序立即启动,或者希望它监听不同的接口或端口,可以通过 JSON 配置文件自定义。
默认配置如下:
{
"interaction": {
"type": "listen",
"address": "127.0.0.1",
"port": 27042,
"on_port_conflict": "fail",
"on_load": "wait"
}
}
你可以通过 --gadget-conf 选项将 gadget 配置文件传递给 apk.sh。
一个典型建议的配置可能是:
{
"interaction": {
"type": "script",
"path": "/data/local/tmp/script.js",
"on_change":"reload"
}
}
script.js 可以是类似这样的内容:
var android_log_write = new NativeFunction(
Module.getExportByName(null, '__android_log_write'),
'int',
['int', 'pointer', 'pointer']
);
var tag = Memory.allocUtf8String("[frida-script][ax]");
var work = function() {
setTimeout(function() {
android_log_write(3, tag, Memory.allocUtf8String("ping @ " + Date.now()));
work();
}, 1000);
}
work();
android_log_write(3, tag, Memory.allocUtf8String(">--(O.o)-<"));
adb push script.js /data/local/tmp
./apk.sh patch <apk_name> --arch arm --gadget-conf <config.json>
adb install file.gadget.apk
添加以下代码,以便在使用脚本交互类型时,将任何来自 frida codeshare 的脚本的 console.log 输出打印到 logcat。
// print to logcat the console.log output
// see: https://github.com/frida/frida/issues/382
var android_log_write = new NativeFunction(
Module.getExportByName(null, '__android_log_write'),
'int',
['int', 'pointer', 'pointer']
);
var tag = Memory.allocUtf8String("[frida-script][ax]");
console.log = function(str) {
android_log_write(3, tag, Memory.allocUtf8String(str));
}
apk.sh [SUBCOMMAND] [APK FILE|APK DIR|PKG NAME] [FLAGS]
apk.sh pull [PKG NAME] [FLAGS]
apk.sh decode [APK FILE] [FLAGS]
apk.sh build [APK DIR] [FLAGS]
apk.sh patch [APK FILE] [FLAGS]
apk.sh rename [APK FILE] [PKG NAME] [FLAGS]
pull 从设备/模拟器拉取 APK。
decode 解码 APK。
build 重建 APK。
patch 修补 APK。
rename 重命名 APK 包。
-a, --arch <arch> 指定目标架构,修补时必选。
-g, --gadget-conf <json_file> 指定 frida-gadget 配置文件,修补时可选的。
-n, --net 在构建时添加宽松的网络安全配置,可选。也可以与 patch、pull 和 rename 一起使用。
-r, --no-res 解码时不解码资源(即 apktool -r),可选。可在修补时使用。
-s, --no-src 解码时不反汇编 dex(即 apktool -s),可选。可在修补时使用。
https://lief-project.github.io/doc/latest/tutorials/09_frida_lief.html
https://koz.io/using-frida-on-android-without-root/
https://github.com/sensepost/objection/
https://github.com/NickstaDB/patch-apk/
https://neo-geo2.gitbook.io/adventures-on-security/frida-scripting-guide/frida-scripting-guide