mcpField
R
reversing-react-native-apps

reversing-react-native-apps

github.com/trilwuセキュリティ17754 回インストール12 週間前に更新
リポジトリ

reversing-react-native-apps について

React Native モバイルアプリを分析するための実践的なスキルです。JavaScript バンドルの読解、Hermes バイトコード、実行時の挙動を扱い、セキュリティテスターによるアプリロジックや API、シークレット、ネイティブブリッジの調査を支援します。

主な機能

  1. 01バンドル形式の識別
  2. 02JavaScript バンドルの読解と検索
  3. 03Hermes バイトコードの逆コンパイル
  4. 04Frida による実行時ブリッジ呼び出しの確認
  5. 05バイトコードのパッチと再パッケージ

活用シーン

  1. 01アプリバンドルから API エンドポイントやキーを発見
  2. 02JavaScript からネイティブモジュールへの呼び出しを確認
  3. 03許可された評価でバンドルの挙動を変更

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/trilwu/secskills --skill reversing-react-native-apps

インストール後、Claude Code で/reversing-react-native-appsを入力して読み込まれたか確認します。

詳細

React Native アプリのリバースエンジニアリング

React Native アプリは、ネイティブのシェルをまとった JavaScript です。アプリケーションロジックが読み取り可能なバンドルとして含まれているため、これは朗報です。ただし、バンドルが Hermes バイトコードにコンパイルされている場合は、デコンパイラーが必要になり、バージョン互換性の問題が作業の大半を占めます。

使用する場面

  • jadx に ReactActivity や ReactNativeHost が表示され、アプリケーションロジックがほとんど見当たらない
  • APK に assets/index.android.bundle または lib/*/libhermes.so が含まれている
  • IPA に main.jsbundle が含まれている
  • RN アプリ内の API エンドポイント、シークレット、ビジネスロジックを見つける必要がある
  • JavaScript レベルの動作をパッチまたはフックする必要がある

使用しない場面

  • Flutter(libapp.so、libflutter.so)— reversing-flutter-apps を使用してください
  • Unity(global-metadata.dat)— reversing-unity-il2cpp を使用してください
  • ネイティブ Java/Kotlin アプリ — testing-mobile-applications を使用してください
  • C/C++ で記述されたネイティブモジュール — analyzing-binaries を使用してください

バンドル形式の特定

この確認ひとつで、作業が 10 分で終わるか 1 日かかるかが決まります。

unzip -j target.apk 'assets/index.android.bundle' -d ./out
file ./out/index.android.bundle
xxd ./out/index.android.bundle | head -2
先頭のバイト形式パス
読み取り可能な JS(var __BUNDLE_START、__d(function)プレーンな JavaScript整形して直接読み取る
バイナリ、Hermes マジック(リトルエンディアンで c6 1f bc 03)Hermes バイトコードデコンパイルする — 下記を参照
# Plain bundle: beautify, then it reads like any minified web app
npx js-beautify index.android.bundle -o bundle.js
rg -n 'https?://|api[_-]?key|Bearer |secret|token' bundle.js | head -50

プレーンなバンドルはありがたいものです。__d(function(...) の登録情報からモジュールの境界を特定できます。ソースマップが誤って同梱されていることもあるため(index.android.bundle.map — 必ず確認してください)、アプリケーションロジック全体を確認できます。

Hermes バイトコード

Hermes は JS を独自のバイトコード(HBC)にコンパイルします。バイトコードのバージョンはヘッダーに埋め込まれており、React Native のリリースごとに変わります。これが実務上、最大の障害です。HBC 74 に対応するツールは、HBC 96 を拒否するか、誤って解析します。

# Read the version out of the header before choosing a tool
hbctool disasm index.android.bundle ./disasm     # HBC 59, 62, 74 ONLY
hermes-dec ...                                    # decompiler; wider version support

上流の hbctool が対応しているバイトコードバージョンは、59、62、74 の 3 つだけです。それ以外のバージョンでは解析に失敗します。解析エラーを「バンドルが保護されている」と判断する前に、まずヘッダーのバージョンを確認してください。最近の React Native リリースでは通常 74 より新しいため、hermes-dec を使うか、対応する Hermes タグからビルドした hermesc を使用してください。

ツール得られるもの注意点
hbctool逆アセンブルと再アセンブル — パッチを適用して再パッケージできます対応する HBC バージョンが限られています
hermes-decデコンパイルされた疑似 JavaScript読み取り専用で、出力は近似的です
hasmer逆アセンブル/アセンブル、別のバージョン対応範囲hbctool がバージョンを拒否した場合に試してください

どのツールもバージョンを受け付けない場合は、アプリが使用している React Native リリースに対応する hermesc をビルドし、そのツールを使うのが確実です。時間はかかりますが、バージョンが一致します。

出力の活用方法。 不完全なデコンパイルでも、重要な疑問に答えるには十分です。文字列テーブルはそのまま保持されるため、エンドポイント、キー、機能フラグを直接復元できます。

strings -n 6 index.android.bundle | rg -i 'https?://|api|token|secret|firebase' | sort -u

Hermes の文字列テーブルは、ファイル内にある平坦で読み取り可能な領域です。デコンパイルする前に確認してください。多くの場合、それだけで答えが見つかります。

ランタイム解析

RN では、静的解析より Frida を使うほうが早いことがよくあります。注目すべき境界は、JavaScript からネイティブへ呼び出す部分だからです。

# Enumerate the native modules the JS side can reach
frida -U -f com.target.app -l rn-enumerate-modules.js

# Hook the bridge: every JS↔native call, with arguments
# (target the ReactNative bridge / TurboModule dispatch)
objection -g com.target.app explore

有用なフックポイントは、JS ランタイムの fetch/XMLHttpRequest、ネイティブのネットワーキングモジュール(Android の OkHttp — 標準的なピンニング回避手法でフック可能)、AsyncStorage の読み書き、およびアプリが定義する NativeModules.* です。

ここでの TLS インターセプトは一般的です。Flutter と異なり、RN はプラットフォームの HTTP スタックを使用するため、通常のシステム CA とプロキシの設定が機能し、標準的なピンニング回避手法も適用できます。インターセプトに失敗した場合は、独立したトラストストアではなく、ネイティブモジュールのピンニングを疑ってください。

発見事項がよく見つかる場所

React Native アプリでは、いくつかのよくある問題が集中しています。

  • バンドル内のシークレット。 API キー、Firebase の設定、サードパーティーの トークンが「コンパイルされているから」という理由で JS に含まれたまま配布されています。Hermes は暗号化ではありません。
  • クライアント側の認可。 ロールチェックや機能制限が JS に実装されており、 簡単にパッチを適用できるか、API を直接呼び出すだけで無視できます。
  • 認証情報の保存先としての AsyncStorage。 デフォルトでは暗号化されません。トークンや個人情報が 日常的にここへ保存されています。
  • 権限が広すぎるネイティブモジュール。 ファイルシステムやシェルへのアクセスを JS に公開するカスタムブリッジメソッドは、 あらゆるインジェクションスクリプトから到達可能です。
  • デバッグ用の残存物。 ソースマップ、開発モードのバンドル、console.log の出力が リリースビルドに残されています。

パッチの適用と再パッケージ化

hbctool disasm index.android.bundle ./work
# edit ./work/instruction.hasm and ./work/metadata.json
hbctool asm ./work index.android.bundle.patched
# replace in the APK, then re-sign
apktool b target -o patched.apk && apksigner sign --ks debug.keystore patched.apk

必要な箇所に限り、許可を得たうえでパッチを適用してください。再パッケージ化すると、 セキュリティ強化されたアプリでは整合性チェックに引っかかります。アプリが自身のバンドルを検証する場合は、編集によって検証を無効化するのではなく、 チェックをフックしてください。

退けるべき言い訳

  • 「バンドルはバイナリだから、ロジックは保護されている。」 Hermes はコンパイラーであり、 保護機能ではありません。文字列テーブルだけで API が明らかになることもよくあります。
  • 「jadx で何も見つからなかったので、難読化されている。」 dex には何もありません。 assets/ を確認してください。
  • 「この HBC バージョンに対応するツールがないので、行き詰まった。」 対応する React Native リリースから hermesc をビルドするか、文字列テーブルを読み取ってください。
  • 「キーはクライアント側でしか使われない。」 バンドルに含まれているため、公開されています。 バンドル内のシークレットはすべて開示済みとして扱ってください。
  • 「アプリがロールチェックを強制している。」 アプリはクライアントです。ロールチェックなしで API を呼び出し、 サーバー側でチェックされることを確認してください。

参考資料

  • testing-mobile-applications — より広範な評価、ストレージ、プラットフォームに関する問題
  • testing-apis — バックエンド。実際の発見事項がある場所です
  • reversing-flutter-apps — もう一つの一般的なクロスプラットフォームフレームワーク
  • hbctool、hermes-dec、hasmer、Frida/objection、jadx、apktool

コメント