2026年1月16日 【Androidセキュリティ】fridaを用いたBypassについてめっちゃ簡単に基礎から書いてみた!! Android セキュリティ 検索する Popular tags 生成AI(Generative AI) Vertex AI Search Looker Studio BigQuery AlloyDB Google Workspace 事例紹介 Cloud SQL Category モバイル Author はる SHARE 目次 私が持っていたサイバーセキュリティの知識レベル OWASP-MASTGとは fridaについて 実践学習 まとめ Content こんにちは、はるです! 今回はAndroidにてfridaというツールを用いた関数バイパス技術についてお話ししていきます! 念のためですが、この記事はAndroidエンジニアである私がモバイルセキュリティにおける防衛方法を知るために学習過程を明記したものです。 「防衛を知るには攻撃から」だと思っています。 技術研究を目的とするものであり、決して違法な攻撃を助長するものではありません。 悪用厳禁です。(といっても悪用は難しいと思いますが...) ⭐️対象読者 ・Androidアプリ開発経験がある方 ・モバイルアプリセキュリティに興味がある方 ・fridaを触ったことがない方 ⭐️この記事でわかること ・OWASP-MASTGについて ・fridaの基本的な使い方 ・jadx-GUIの使い方 私が持っていたサイバーセキュリティの知識レベル ・情報処理安全確保支援士 合格済み ・Kali Linuxを用いたCTF学習(主にrevだがいわゆるscript kiddie) ・基礎的なツール(msfvenom, metasploitable, nmap)の使い方 ・Androidの基礎知識(Dalvik vs ART、DEXなどビルドプロセスの簡単な知識) 元々、高校生の頃から趣味で学習していたので全く無いわけではありませんが、 実務では一切触りませんから決して深い知見などは一切なく表面的な情報のみです。 OWASP-MASTGとは 公式サイトです。 端的に表現すれば、モバイル開発におけるセキュリティ技術(静的解析・動的解析・リバースエンジニアリングなど)を包括的にまとめたマニュアルです。 fridaについて ⭐️ 概要 fridaは実行中のアプリが持つ関数の動きなどをリアルタイムで書き換えることが可能です。 よく使われるのは実行端末がroot済みかどうかをチェックしてる関数を書き換えて強制的にrootしてない判定にするなど。 例えば下記のような実装があるとします。 fun isRooted(): Boolean { // root済みかどうか色々見る hogehoge() return result } これをfridaを使用することで fun isRooted(): Boolean { // 確認処理は全て消して問答無用でrootしてない判定 return False } このように書き換えることが出来ます。 しかも端末がroot化してなくても出来るという…。 正直、私はこの時点でもうわくわくしてました。 ⭐️ 強み ・非root端末で動作可能(root化してれば尚やりやすいが) ・リアルタイムで関数書き換え(フック)が可能 ・難読化されていない場合は対策が困難 ⭐️ 弱み ・初回はハードル高く感じる ・ProGuardやR8で難読化されていると難しい(フック自体は可能だがフックする関数が不明) ⭐️ 仕組み 難しい説明はあまりしませんが、fridaはホストとクライアント両方の関係で成立します。 クライアント側にfrida-gadgetというネイティブライブラリファイルを仕込みapkをインストール。 こうすると、アプリ起動時にホストとクライアントが通信を開始。 これでホスト側から関数の挙動変更を指示できたりします。 実践学習 ⭐️ 問題の概要 今回は、MASTG-TECH-0026を学習材料とします。 リンク先で配布されているアプリを開くと下記のような画面が登場します。 ここで画面上部の「VERIFY」ボタンを押下すると下記のようなダイアログが。 つまり正しいパスワードのようなものを入力しろっていうのがこの問題の概要のようですね。 早速解いちゃいましょう! ⭐️ 筆者の環境 作業マシン:M3 Macbook Air 256GB 作業端末:Google Pixel 7a(実機・非root・Android16) ⭐️ 作業の流れ ・必要ツールのインストール ・アプリを逆コンパイルしVERIFYボタンのクリックイベントを探す ・apkにfrida-gadget(クライアントサイド)を組み込む ・署名の再設定を行いリビルド ・ホスト側からアタッチを行い通信を確立 ・VERIFYボタンのクリックイベントをフックしてバイパス ⭐️ 必要ツールのインストール brewやpip系などはインストール済みの前提で進めます。 ▫️adb これはお馴染みなので言わずもがな。 androidデバイスとの通信ではよく使う。android studio入っていれば基本通ってるので割愛。 ▫️apktool apkファイルの分解(デコンパイル)及びリビルド役として使用。 「brew install apktool」 これでインストール可能 ▫️uber-apk-signer apk作成時の署名設定として使用する。 普段keystoreとかdebugビルドだったらdebug署名などが組み込まれてますよね。あんな感じです。 こちらからjarファイルを取得 ▫️frida 今回の主役ですね。 クライアント側は後ほど作業手順内でインストールしますのでホストを先に。 「(pip3またはpip) install frida-tools」 環境に合わせて実行してください。 ▫️jadx-gui apkを逆コンパイルして中身のソースコードを閲覧可能にするツールです。 フックしたい関数を特定するために必須ですね。 「brew install jadx」 これで完了です。 ⭐️ アプリを逆コンパイルしVERIFYボタンのクリックイベントを探す 普段見ているapkファイルの中身です。 逆コンパイルではこの辺りの情報から元のKotlin/Javaコードを再生成し色々表示してくれます。 ターミナルで「jadx-gui」と入力すると下記のようなウィンドウが立ち上がるはずです。 中央の「Open file」を押下するとファイル選択ウィンドウが表示されるのでダウンロードしたapk(UnCrackable-Level1)を指定します。 そうすると、左側にソースツリーが出来上がるので下記を開いてみます。 MainActivity!!見慣れた単語ですね、開きましょう。 public void verify(View view) { String str; String string = ((EditText) findViewById(R.id.edit_text)).getText().toString(); AlertDialog alertDialogCreate = new AlertDialog.Builder(this).create(); if (a.a(string)) { alertDialogCreate.setTitle("Success!"); str = "This is the correct secret."; } else { alertDialogCreate.setTitle("Nope..."); str = "That's not it. Try again."; } alertDialogCreate.setMessage(str); alertDialogCreate.setButton(-3, "OK", new DialogInterface.OnClickListener() { // from class: sg.vantagepoint.uncrackable1.MainActivity.2 @Override // android.content.DialogInterface.OnClickListener public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }); alertDialogCreate.show(); } 「That’s not it. Try again.」、さっき見た文字列!! ということはこの辺りが絡んでいそうですね。 よく見ると、if (a.a(string))という処理の結果で結果が分岐していそうです。 追ってみましょう。 package sg.vantagepoint.uncrackable1; import android.util.Base64; import android.util.Log; /* loaded from: classes.dex */ public class a { public static boolean a(String str) { byte[] bArrA; byte[] bArr = new byte[0]; try { bArrA = sg.vantagepoint.a.a.a(b("8d127684cbc37c17616d806cf50473cc"), Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0)); } catch (Exception e) { Log.d("CodeCheck", "AES error:" + e.getMessage()); bArrA = bArr; } return str.equals(new String(bArrA)); } public static byte[] b(String str) { int length = str.length(); byte[] bArr = new byte[length / 2]; for (int i = 0; i < length; i += 2) { bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16)); } return bArr; } } 引数strとbArrAの結果が一致しているかどうかを返していますね。 AESという単語も含まれているあたり、暗号/復号が絡んでいそうです。 sg.vantagepoint.a.a.a関数も追ってみましょうか。 package sg.vantagepoint.a; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; /* loaded from: classes.dex */ public class a { public static byte[] a(byte[] bArr, byte[] bArr2) { SecretKeySpec secretKeySpec = new SecretKeySpec(bArr, "AES/ECB/PKCS7Padding"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(2, secretKeySpec); return cipher.doFinal(bArr2); } } やはり暗号ですね。 つまり与えられた文字列strと"8d127684cbc37c17616d806cf50473cc"を復号した結果があっていればOK、違っていればNGという判定ですね。 しかし、暗号処理云々は些細な問題です。 要は、a.a関数が常にtrueを返せばいいだけです。 つまり、フックすべき関数はsg.vantagepoint.uncrackable1.a.aの関数だと分かります。 ⭐️ apkにfrida-gadget(クライアントサイド)を組み込む UnCrackable-Level1.apkにfrida-gadget.so(クライアントサイド)を入れます。 やることは2つです。 ・soファイルの配置 ・MainActivityにてsoファイルを読み込むように設定 まず、1つ目からやります。 apktool d UnCrackable-Level1.apk -o decompiled apktool dは指定したapkをデコンパイルするコマンドで、-oでデコンパイル結果を格納するフォルダを指定してます。 decompiledフォルダを見ると、 ・AndroidManifest.xml ・apktool.yml ・originalフォルダ ・resフォルダ ・smaliフォルダ があります。 ではここにsoファイルを配置します。 cd decompiled mkdir lib/arm64-v8a cd lib/arm64-v8a wget https://github.com/frida/frida/releases/download/17.5.1/frida-gadget-17.5.1-android-arm64.so.xz unxz frida-gadget-17.5.1-android-arm64.so.xz mv frida-gadget-17.5.1-android-arm64.so libfrida-gadget.so ここで、17.5.1というのはfridaのバージョンですが必ずホストとクライアントで合わせてください。 frida --versionを実行し、17.5.1であれば問題ありませんがもし違えば修正してください。 また、arm64-v8aという命名も重要です。 これは実行端末によります。 作業端末をadb接続した状態で adb shell getprop ro.product.cpu.abi と試してarm64-v8aと表示されたらコピペでいいですがもし違えばフォルダ名や取得するsoファイルを修正してください。 decompiled/lib/arm64-v8a内にlibfrida-gadget.soが配置されれば完了です。 次、2つ目はMainActivityにsoファイルを読み込むように宣言していきます。 ただし、ここではktやjavaファイルではなくsmaliという特殊なファイルを変えていきます。 vscodeで、decompiled/smali/sg/vantagepoint/uncrackable1/MainActivity.smaliを開きましょう。 smaliとはアイスランド語で「アセンブラ」を意味します。 つまり、smaliはdexファイルを人間が読みやすいようにAndroidに特化したアセンブラ言語に変換したものです。(正確に言えばDalvik/AndroidRunTime向けのアセンブラ言語) 開くと .method protected onCreate(Landroid/os/Bundle;)V .locals 1 // 色々処理 という部分がありますね。 これがMainActivityのonCreateです。ここの先頭に下記を追加します。 const-string v0, "frida-gadget" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V これ、やってることは非常にシンプルで、Javaに搭載されているネイティブライブラリロード機能(System.loadLibrary)を呼んでいるだけです。 詳細はこちら そして引数としてfrida-gadgetを指定しています。 これが先ほど1つ目に配置したsoファイルを指しています。 つまり、onCreateの先頭でfrida-gadgetを読み込みますよ!っていう宣言をしているだけです。 保存して終了しましょう。 ⭐️ 署名の再設定を行いリビルド frida-gadgetを組み込んだのでバラしたapkをリビルドします。 apktool b decompiled/ -o UnCrackable-Level1-frida.apk java -jar --apk UnCrackable-Level1-frida.apk これをすると「UnCrackable-Level1-frida-aligned-debugSigned.apk」こんな名前のapkが出来上がるはずです。 ここまでできればOKです。 ⭐️ ホスト側からアタッチを行い通信を確立 いよいよ、ホストとクライアント間の接続を確立させます。 まずはインストールしておいてください(adb install UnCrackable-Level1-frida-aligned-debugSigned.apk)。 アプリを起動すると、アイコン画面で止まるはずです。 これは、クライアントがホストと通信確立するのを待っているためです。 そこで、 frida-ps -U | grep UnCrackable1 と実行してデバイスで実行されているプロセス一覧を出力します。 その中に、 「14146 Uncrackable1」 というプロセスが稼働していることがわかるはずです。 14146(プロセスid)は環境によって変わるので異なると思いますがUncrackable1という名前は同じはずです。 プロセスidがわかったら ! ~/D/d/s/OWASP-MASTG tech-0026 frida -U 14146(プロセスid) 日 11/ 9 22:29:29 2025 ____ / _ | frida 17.5.1 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at https://frida.re/docs/home/ . . . . . . . . Connected to Pixel 7a (id=36141JEHN19666) [Pixel 7a::PID::14146 ]-> frida -U とすることでアタッチが成功するとこんな感じでシェルが取れます!!! 筆者はこの辺りでもう興奮が止まらなかったです。 これはホストとクライアントが接続を確立できた証拠です。 ⭐️ VERIFYボタンのクリックイベントをフックしてバイパス [Pixel 7a::PID::29812 ]-> Java.perform(function() { var check =Java.use("sg.vantagepoint.uncrackable1.a"); check.a.overload('java.lang.String').implementation = function(input) { return true; }; }); このfridaスクリプトが要です。 先ほど、フックすべき関数はsg.vantagepoint.uncrackable1.a.aだと分かりましたね。 まさにそれを指定しています。 a関数を.overloadで中身を書き換えてreturn true;だけにしてますね。 これをするとさっきは暗号やら復号やらで色々比較してましたが全て帳消ししてtrue返すようになります。 これを実行してVERIFYボタンを押すと...? おお!!!!見事にチェック処理をバイパスして正解扱いになってます! これがroot無しで出来るって凄すぎませんか...? まとめ 今回はfridaを用いた関数バイパスを試してみました。 これはAndroidアプリのサイバーセキュリティにおいて非常に基礎となる技術だと思います。 これが出来れば既存実装にログ出力処理を追加したりもできます。 fridaスクリプトはAIに書いてもらえばいいですし楽です。 ただし、弱点にも挙げたように難読化されているとやりづらいです。 それはフックすべき関数が全く分からなくなるからです。 こう見ると難読化(ProGuardやR8)の重要性が分かります。 そして、いかにモバイルアプリ側での対策が信頼に値しないか分かるのではないでしょうか。 例え、frida検出を目的としてfridaスレッドが存在しているかどうか?などを確認するコードを書いてfrida対策を行ったとしてもそれすら書き換えてバイパスすれば良いわけです。 ですから重要なビジネスロジックや状態管理はサーバ側で行うことが大切です。 いかがでしたか? 攻撃者視点で学ぶことで防衛者としての視点も深まったのではないでしょうか。 次は、DexClassLoaderを用いた動的プログラム実行の執筆を考えています! 関連コンテンツ 【iOS】大規模フルスタック個人アプリ、4度のリジェクトを超えてリリースした話 by はるon 2025年10月29日 SwiftUI + Firebase使用時プレビューが使えないことがある現象について by はるon 2025年6月9日 【Xcode 16 / Swift 6.0】SPMを用いたSwiftLintの導入方法について by はるon 2025年4月23日 頂きましたご意見につきましては、今後のより良い商品開発・サービス改善に活かしていきたいと考えております。 非常に分かった とても分かった どちらでもない あまり分からなかった 全く分からなかった Author はる 入社日:2023年12月 職種:Androidネイティブアプリエンジニア チェスが趣味 Android セキュリティ 2026年1月16日 【Androidセキュリティ】fridaを用いたBypassについてめっちゃ簡単に基礎から書いてみた!! Category モバイル 前の記事を読む 【Looker】導入2分でスパゲッティ化したモデルを一刀両断「LookML Diagram Extension」導入・活用完全ガイド 次の記事を読む 【Looker】ガバナンスの要、LookMLこそ美しく!静的解析ツールLook at me sideways(LAMS)のすすめ【CI/CD】 Recommendation オススメ記事 2023年9月5日 Google Cloud 【Google Cloud】Looker Studio × Looker Studio Pro × Looker を徹底比較!機能・選び方を解説 2023年8月24日 Google Cloud 【Google Cloud】Migrate for Anthos and GKEでVMを移行してみた(1:概要編) 2022年10月10日 Google Cloud 【Google Cloud】AlloyDB と Cloud SQL を徹底比較してみた!!(第1回:AlloyDB の概要、性能検証編) BigQuery ML ワークショップ開催のお知らせ 生成AI導入支援パッケージ Discovery AI導入支援パッケージ Google Cloud ホワイトペーパー 新着記事 2026年1月16日 Google Cloud 【Looker】ガバナンスの要、LookMLこそ美しく!静的解析ツールLook at me sideways(LAMS)のすすめ【CI/CD】 2026年1月16日 モバイル 【Androidセキュリティ】fridaを用いたBypassについてめっちゃ簡単に基礎から書いてみた!! 2026年1月14日 Google Cloud 【Looker】導入2分でスパゲッティ化したモデルを一刀両断「LookML Diagram Extension」導入・活用完全ガイド HOME モバイル 【Androidセキュリティ】fridaを用いたBypassについてめっちゃ簡単に基礎から書いてみた!!