
Androidアプリのリバースエンジニアリングを容易にし、APKのプル、デコード、リビルド、パッチ適用といった反復作業を自動化します。
apk.sh は Android アプリのリバースエンジニアリングを容易にする Bash スクリプトで、APK のプル、デコード、リビルド、パッチ適用といった繰り返し作業を自動化します。
apk.sh は基本的に apktool を使用してリソースの逆アセンブル、デコード、リビルドを行い、一部の bash で frida ガジェット注入プロセスを自動化します。 また、アプリバンドル/スプリット APK もサポートしています。
⬅️ デバイスからの APK プルは ./apk.sh pull <package_name> を実行するだけです。
🔧 APK のデコードは ./apk.sh decode <apk_name> を実行するだけです。
🔩 APK のリビルドは ./apk.sh build <apk_dir> を実行するだけです。
apk.sh pull はデバイスから APK をプルします。
アプリバンドル/スプリット APK をサポートしており、スプリット APK を単一の APK に結合します(これはパッチ適用に便利です)。
パッケージがアプリバンドル/スプリット APK の場合、apk.sh は APK を結合し、すべてのパブリックリソース識別子を修正します。
apk.sh patch は、起動時に frida-gadget.so をロードするように APK にパッチを適用します。
frida-gadget.so は Frida の共有ライブラリであり、プログラムによってロードされ、インストルメント化されることを目的としています(注入モードの操作が適さない場合)。ライブラリをロードするだけで、frida-trace のような既存の Frida ベースのツールを使って操作できるようになります。また、外部との通信なしにファイルシステムからスクリプトを実行する完全自律的なアプローチもサポートしています。
APK へのパッチ適用は ./apk.sh patch <apk_name> --arch arm を実行するだけです。
また、JSON で Frida ガジェット設定を指定することもできます: ./apk.sh patch <apk_name> --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 オプションで 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
Script インタラクションタイプを使用する場合、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