re-mobile-pack について
re-mobile-packは、保護されたAndroidアプリを解析するためのリバースエンジニアリングスキルです。実行時または静的な方法でDEXを抽出し、成果物を修復・検証する手順を案内します。主に仮想化された強力な保護は対象外です。
主な機能
- 01一般的な保護の特徴を識別
- 02frida-dexdumpによるDEX抽出
- 03代替手段としてBlackDexやYoupkを使用
- 04DEXの整合性を修復・確認
- 05jadxで逆コンパイル結果を検証
活用シーン
- 01保護アプリから実際のDEXを抽出
- 02メソッド本体が空の抽出物に対処
- 03複数DEXの出力漏れを確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dslsdzc/ rev-skills --skill re-mobile-packインストール後、Claude Code で/re-mobile-packを入力して読み込まれたか確認します。
詳細
Android の加固解除(DEX 復元)
使用する場合/使用しない場合
- 使用する:Android の加固(乐固/360/梆梆/爱加密など)が施されたアプリを入手し、静的解析を続けるために本来の DEX を復元する必要がある場合
- 使用する:[[re-apk]] で加固が特定され、解除方法を選ぶ必要がある場合
- 使用する:加固解除後の生成物でメソッド本体が空、または命令抽出が必要で、修復する場合
- 使用しない:加固が確認できていない場合。まず [[re-apk]] で静的に確認してください。通常のアプリなら jadx で十分です
- 使用しない:VMP による仮想化が中心の強固な保護の場合。[[re-anti-analysis]] に進んでください([[re-unpack-advanced]] のアプローチ)
- 使用しない:実行時の hook や検出の回避が必要な場合(それは [[re-frida]] の担当です)
ツールの準備
動的な加固解除は、既定では管理下のデバイス/エミュレーターのスナップショット内で実行します([[re-analyze/platform-tips]] の最優先原則——既定でサンドボックスを使用)。すべてのツールは、使用前に検証してください。
frida + frida-dexdump —— 実行時の加固解除の主力
- frida-tools:全プラットフォームで
pip install frida-tools(Python 3.8+。venv を推奨)。frida-server のバージョンはホストと一致させ、デバイスにプッシュしてください(インストールと検出回避の全手順は [[re-frida]] のツール準備を参照) - frida-dexdump:全プラットフォームで
pip install frida-dexdump(Python 3)——実行時にメモリ内の DEX マジックナンバーを検索して dump します - 検証:
frida --version;frida-dexdump -h(-U/-f/-dパラメーターが表示されること) - 使用方法:
frida-dexdump -U -f <包名>(spawn して加固解除を開始)、frida-dexdump -U <pid>(attach)、frida-dexdump -U -f <包名> -d(詳細検索。複数 DEX や部分的な抽出に対応)
BlackDex —— 静的加固解除ツール(frida 不要。通常の加固で優先する代替手段)
- インストール:GitHub release から APK をダウンロード——
https://github.com/CodingGay/BlackDex/releases。32 ビット版と 64 ビット版は別々の APK です(対象アプリが一覧に表示されない場合は、もう一方のアーキテクチャ版に切り替えてください) - 環境:通常の Android スマートフォンまたはエミュレーター。Android 5.0~12。root/カスタム環境は不要です
- 機能:ディスク上のファイルから読み込むタイプ/メモリから読み込むタイプ/命令抽出の 3 種類の保護に対応。詳細モードでは、命令抽出されたメソッド本体を補完します(実験的機能のため、数分かかったり失敗したりする場合があります)
- 生成物:
hook_*.dex(システム API の hook で取得)とcookie_*.dex(DexFile cookie 技術) - 検証:インストール後、対象アプリが一覧に表示され、加固解除を完了できること
Youpk —— 積極的に呼び出す加固解除ツール(抽出型の加固に対する最も強力な手段)
- ソースコード/ROM:
https://github.com/Youlor/Youpk——Android 7.1.2_r33 をベースに二次開発されています。Google Pixel 1 のみ対応:Android Studio でビルドした後、flash-all.shでカスタム ROM を書き込みます - 使用方法:
adb shell "echo <包名> >> /data/local/tmp/unpacker.config"→ 対象アプリを起動すると、積極的な呼び出しによる加固解除が自動で始まります(ログに「unpack end」と表示されます)→adb pull /data/data/<包名>/unpacker - 修復:
java -jar dexfixer.jar ./unpacker ./out(付属の DEX 修復ツールで、メソッドの命令を補完します) - 検証:
adb shell ls /data/data/<包名>/unpackerで dex/method の生成物が表示されること
jadx —— 加固解除後の逆コンパイル([[re-apk]] を再利用)
- OS ごとのインストールと検証については [[re-apk]] のツール準備を参照してください。jadx は複数 DEX をそのまま解析できるため、手動での結合は不要です
adb —— デバイスとのやり取り
- Android SDK platform-tools に付属します。
adb --versionで検証してください。エミュレーターの場合はadb shellで十分です - dexdump:Android SDK build-tools に付属します(手順 4 の DEX 完全性チェックで使用)。
dexdump -hで検証してください
メモリダンプ([[re-memdump]] のアプローチ)
- frida/objection の
memory dumpを使うか、[[re-memdump]] に従ってダンプから DEX マジックナンバーdex\n0xxを grep して抽出します——frida-dexdump が使えない場合の代替手段です
操作手順
順番に実行し、各手順の生成物(DEX パス + sha256)を保存してください([[re-triage]] を参照)。
-
加固の特定(確認してから作業する):
- クラス名の特徴:jadx で逆コンパイルしても保護用クラスしか見えない——
com.stub.StubApp(爱加密)、com.secneo.apkwrapper/com.bangcle.*(梆梆)など。エントリーポイントの Application が保護用クラスに置き換えられています - 保護用 so の特徴:
ls out/lib/——libjiagu.so/libprotectClass.so(360 加固)、libDexHelper.so/libexec.so(爱加密)、libsecexe.so/libsecmain.so(梆梆) - DEX のサイズ:
ls -la out/classes*.dex——本来の DEX は暗号化されて格納されています(assets/ 内、または実行時に復号)。保護用の classes.dex は異常に小さいサイズです - 特定した保護名に基づいて方法を決めます:一般的な一括保護/抽出型の加固 → このスキル。仮想化が中心 → [[re-anti-analysis]]
- クラス名の特徴:jadx で逆コンパイルしても保護用クラスしか見えない——
-
実行時の加固解除(frida-dexdump、既定の方法):
adb shell monkey -p <包名> 1 # 先启动 App,让壳把真 dex 加载进内存 frida-dexdump -U -f <包名> # 或 spawn 起步 frida-dexdump -U <pid> # 已运行 attach frida-dexdump -U -f <包名> -d # 深度搜索(多 DEX / 部分抽取场景)生成物は現在のディレクトリの
<包名>/<时间戳>/*.dexにあります。タイミング:アプリが業務画面に進んでから dump してください([[re-analyze/platform-tips]] の重要な知見——ダンプのタイミング)。起動直後に dump すると、保護の初期状態しか取得できません。 -
静的な加固解除(BlackDex/Youpk、frida が検出された場合の代替手段):
- BlackDex:対応するアーキテクチャの APK をインストール → 対象アプリを選択 → 加固解除(通常の保護なら数秒。抽出型の保護では詳細モードを有効にします。数分かかり、失敗する可能性があります)→ 生成物をエクスポート
- Youpk(抽出型の加固を優先):Pixel 1 の ROM を書き込む → パッケージ名を設定に書き込む → アプリを起動して自動加固解除を待つ →
unpacker/ディレクトリを pull →java -jar dexfixer.jar ./unpacker ./out - 相互検証:2 つの方法で生成した成果物を比較します(同じメソッド本体は一致するはずです)。一致しない場合は、完全な方を採用します
-
DEX の修復と完全性チェック:
file out/*.dex # 应见 "Dalvik dex file version 035"(magic: dex\n035\0) dexdump out/classes.dex 2>/dev/null | head -30 jadx -d java-out out/ # 反编译验证:业务类是否齐全- メソッド本体が空(CodeItem がすべて nop/直接 throw)→ 命令抽出型の保護で補完されていません。dexfixer(Youpk の生成物に付属)を使うか、BlackDex の詳細モードで再度加固解除してください。それでも解決しない場合 → 積極的な呼び出しでメソッドを実行させてからダンプします([[re-memdump]] のアプローチ)
- 複数 DEX:classes.dex/classes2.dex/... が揃っているか確認します。frida-dexdump の
-dで詳細検索する方法が代替手段です。jadx では複数 DEX をそのまま解析できます - 修復後は、業務分析に進む前に必ず逆コンパイルして抜き取り検査を行ってください(落とし穴 3 を参照)
-
加固解除後の分析([[re-apk]] の全手順に従う):
- manifest のエントリーポイント/権限 → jadx で業務コードを逆コンパイル → 対象ロジック(鍵/プロトコル/検証)を特定
- 動作を変更する必要がある場合 → smali パッチ + 再パッケージ化と署名([[re-apk]] 手順 4)
- ネイティブ so(保護用 so/JNI 業務 so)→ [[re-binary-core]]([[re-format-elf]] + [[re-ghidra]])。保護自体のデバッグ対策/検証への対抗 → [[re-anti-analysis]]
跨域联合
- [[re-mobile]]: 工作流第 5 步加固分支固定调用本技能([[re-apk]] 识别后转入)
- [[re-apk]]: 加固识别(步骤 5)与脱壳后静态分析(manifest / jadx / smali)
- [[re-frida]]: 运行脱壳执行环境 + 反 frida 检测对抗(改名 / 换端口 / gadget)
- [[re-memdump]]: 内存 DEX 提取思路(dump 时机、magic 扫描、多 DEX 兜底)
- [[re-anti-analysis]]: VMP / 虚拟化加固对抗(抽取+虚拟化组合壳转强壳流程)
- [[re-binary-core]]: 壳 so / JNI 原生逻辑分析([[re-format-elf]] / [[re-ghidra]])
- [[re-analyze/platform-tips]]: 默认沙箱(模拟器快照)、转储时机关键经验
- 本技能被 [[re-analyze]] 的 triage「移动 App 分析」路径引用(re-mobile → re-apk 识别加固 → re-mobile-pack)
常见坑与陷阱
- VMP 级加固(抽取+指令虚拟化)脱壳难度大:现象——frida-dexdump / BlackDex 出 DEX 后方法体大量 nop / 空壳,部分方法逻辑在 dex 里永远找不到;原因——壳除抽取指令外把关键方法虚拟化进 so(自定义 VM 解释执行),DEX 层还原不出这部分;对策——识别为抽取+虚拟化组合时:抽取部分用 Youpk 主动调用修复,虚拟化部分放弃 DEX 还原、改为动态 [[re-frida]] hook 观察输入输出,或还原 VM 解释器(成本高,标注范围并转 [[re-anti-analysis]] 强壳思路)
- 反 frida 检测:现象——spawn 即闪退、frida-dexdump 连不上或 dump 出空结果;原因——壳检测 frida-server 端口 27042 / 路径 / 特征线程(gum-js-loop)等指纹;对策——按 [[re-frida]] 反检测章节改名 + 换端口;仍被检测 → 换 BlackDex / Youpk(不依赖 frida)或 frida-gadget 注入
- DEX 修复不完整(方法体空壳):现象——jadx 打开脱壳 DEX,半数方法无反编译内容或直接 throw;原因——指令抽取壳的 CodeItem 未回填(dump 时机早于方法执行 / 修复器未处理);对策——dexfixer 修复(Youpk 产物配套)或 BlackDex 深度模式重脱;主动调用触发方法执行后再 [[re-memdump]] 转储;修复后 dexdump 抽查 + jadx 反编译验证再进分析
- 多 DEX 合并/丢失:现象——只 dump 到单个 classes.dex,jadx 报类缺失 / 引用不存在;原因——加固后多 DEX 由壳运行时加载,frida-dexdump 默认搜索可能漏;对策——
-d深度搜索、hook ClassLoader 枚举已加载 dex([[re-frida]] 枚举)、内存转储全部提取;jadx 直接加载全部 dex 分析 - 转储时机过早:现象——dump 出的 DEX 解不开 / 是壳初始数据;原因——真 dex 尚未解密加载;对策——等 App 进入业务页面再 dump([[re-analyze/platform-tips]] 转储时机关键经验,与"解密数据看到立刻保存"相反的另一端)
- PairIP(Google Play 自动保护)三道门:现象——JADX 拉开关键方法只剩
VMRunner.invoke("...")空壳,模拟器上跑几秒就退;原因——Play 上架自动套的加固三件套:①代码虚拟化:逻辑抽进加密 VM blob(assets 随机名无扩展名文件,\x00IAP头为解密判据)+ native 解释器libpairipcore.so(executeVM等符号名运行时从 XOR 表解码,strings 搜不到);②TEE 密钥:blob 是 AES/GCM 密文,wrapping key 存在设备 TEE(AndroidKeyStore),Play 经importWrappedKey(SecureKeyWrapper ASN.1)下发——三个硬前提:Play 安装(gpdekusplit 载体)、过 Play Integrity、有登录 Google 账号,缺一即 Finsky 日志 FAILURE → 本地伪造isEncryptionKeyPresent()也没用;③运行时反篡改:dl_iterate_phdr/opendir 扫 maps 发现注入 so → 故意给 std::vector 喂非法 length →std::__throw_length_errorabort(tombstone 指纹length_error was thrown in -fno-exceptions mode)→ abort 被中和则执行流落 abort 下一条指令踩内存 SIGSEGV +SIG_DFL复位——信号层 hook 拦不住,根因在检测端(maps 不露脸);对策——先过 Integrity(三绿真机或 PlayIntegrityFix)+ 清掉可见注入模块(Zygisk disable 后重启) - PairIP 脱明文:调用而非 hook:现象——hook
VMRunner任何方法(getVmByteCode/executeVM/readByteCode)进程立刻自毁;原因——PairIP 盯 ArtMethod 完整性:frida hook 改写entry_point_from_quick_compiled_code即命中检测;对策——反射直接调用解密函数(getVmByteCode是 private static,frida 反射可调;blob 名带不带assets/前缀版本间不一致,两种都试),零 hook 零 ArtMethod 改动即可解出全部 blob 明文——脱 PairIP 不需要内核级隐身,只有必须动态跟解释器时才需要 - 加固 APK 直接重打包 → 真机黑屏:现象——对加固 APK 走 apktool 重打包,签名安装后真机黑屏(进程存活、无崩溃),同一 APK 在模拟器上却「看起来正常」;原因——重打包从 smali 重建 DEX,破坏壳的布局与自校验假设,壳定位/验证不了加密载荷 → 不解密 → 真实 DEX 里平台通道 handler 全部抛 MissingPluginException → 未捕获异常拆掉渲染;模拟器上壳校验被放松,「模拟器能跑」不是证据;对策——重打包前先做加固检测(assets 里壳运行时 so(
lib*sec*/lib*shell*风格)、动态 DEX loader so、壳 stub 入口类、单一超大 classes.dex 且无业务字符串、smali→dex 往返拆出多个空 stub DEX);确认加固即放弃 apktool 重打包;转储内存必须卡解密窗口——壳瞬态自卸载,/proc/self/maps里可能都看不到壳,过早/过晚都拿不到解密 DEX;若应用自身还自检「壳是否存在」,脱壳需一并中和该检查(来源:reverse-skills(inliver233),MIT) - 加固目标交付路径:脱壳重打包 / 免重打包注入 / 常驻 gadget:现象——带壳目标直接脱壳重打包后运行异常,或不知选哪条修改交付路径;原因——脱壳重打包后壳工件未清干净,壳运行时与明文 DEX 冲突;对策——按目标状态选:路径 a 脱壳重打包(保真度高):blackdex / FART / frida-dexdump 在解密窗口从活进程取回真实 DEX 再重打包(壳已不需要),重打包前清掉全部壳工件(壳运行时 so、壳目录、DEX loader);路径 b 免重打包注入(不重装 DEX,壳与自校验完全不动,对壳风险低,优先):原位替换 libapp.so + 用 LSPatch 类工具注入 Java hook,注意目标可能检测注入框架本身(检测字符串常见),属需一并处理的完整性信号;路径 c 常驻 gadget(零文件改动):注入 frida-gadget + 开机自启脚本做运行时签名适配与 libapp 内存 patch,注意 gadget 可被检测、运行时翻转检查耦合标志可能反噬;不推荐逆向壳校验逻辑硬过 apktool 重打包——难度高收益低(来源:reverse-skills(inliver233),MIT)
コメント
Markdown 対応