re-apk について
re-apkは、Androidのセキュリティ分析向けAPK静的解析スキルです。パッケージの展開、Javaコードの逆コンパイル、マニフェスト確認、smaliパッチに加え、パッカーやリソース難読化、AABとsplit APKの分析範囲も扱います。
主な機能
- 01APK内容の展開
- 02Javaコードの逆コンパイル
- 03権限とコンポーネントの確認
- 04パッカーとリソース難読化の特定
- 05smali編集とパッケージ再構築
活用シーン
- 01APKの権限とエントリーコンポーネントの確認
- 02アプリの検証ロジックの特定
- 03保護を見分けてアンパックを検討
- 04smaliを修正して再構築パッケージを検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dslsdzc/ rev-skills --skill re-apkインストール後、Claude Code で/re-apkを入力して読み込まれたか確認します。
同梱ファイルreferences/commands.mdreferences/gotchas.md
詳細
APK 静的解析
使用时机/不使用时机
- 使用:取得 APK/Android アプリパッケージがあり、マニフェスト、Java コード、リソース、権限、コンポーネント構造を確認する必要がある場合
- 使用:難読化対策(シェル、リソースの難読化)を特定し、シェル解除やパッチ適用の準備をする必要がある場合
- 不使用:ランタイムフック/復号/バイパスが必要な場合([[re-frida]] を使用)
- 不使用:対象がネイティブライブラリ .so のロジックの場合([[re-binary-core]] の [[re-format-elf]] を使用)
- 不使用:ランタイムメモリから DEX を抽出する必要がある場合([[re-memdump]] を使用)
ツールの準備
純粋な静的解析(展開/逆コンパイル)はサンドボックス不要です([[re-analyze/platform-tips]] の最優先原則)。動的解析/シェル解除が関わる場合は [[re-frida]]/シェル解除の領域に進んでください。すべてのツールは使用前に検証してください。
jadx —— Java 逆コンパイルの主力(JADX GUI を含む)
- 公式/GitHub release:
https://github.com/skylot/jadx/releasesからjadx-<版本>.zipをダウンロードし、展開後にbin/jadx(Linux/macOS)またはbin\jadx.bat(Windows)を実行します。GUI はbin/jadx-guiです - macOS:
brew install jadx;Arch:pacman -S jadx - Java 11+ が必要です(公式要件は 11+ かつ 64 ビット):Linux
apt install openjdk-17-jre/dnf install java-17-openjdk/pacman -S jre17-openjdk;macOSbrew install openjdk - Windows/WSL: WSL 内で Linux 版 zip を使用します
- 検証:
jadx --version;バージョン注記——release zip と brew/pacman パッケージは同期して更新されるため、実際に確認したバージョンを基準にしてください
apktool —— 展開/再ビルド(公式/GitHub release)
- Java 8+ が必要です(公式インストールページの最低要件。jar は Java 8 を対象にコンパイルされています)。公式 wrapper:
https://github.com/iBotPeaches/Apktool/releasesからapktool_<版本>.jarと wrapper スクリプト(Linux/macOSapktool、Windowsapktool.bat)をダウンロードし、スクリプトと jar を同じディレクトリに配置します - バージョンモデル:3.x が現在のメインライン、2.x がメンテナンスラインです——両ラインのコマンドには完全な互換性がなく、公式ドキュメントも 3.x/2.x 別に分かれています。ダウンロード後、まず
apktool --versionでメジャーバージョンを確認してください。2.x 時代のコマンドやチュートリアルをそのまま 3.x で使うとUnrecognized optionエラーが発生します(変更一覧は [[gotchas]] のバージョン差異を参照) - Debian/Ubuntu:
apt install apktool(リポジトリ版は古い場合がありますが、コマンドの動作に互換性があれば問題ありません) - macOS:
brew install apktool - Windows/WSL: WSL 内で Linux 版を使用します
- 検証:
apktool --version
aapt2 —— リソースのダンプ/難読化されたリソースの復元
- Android SDK の build-tools に付属します。cmdline-tools のインストール後:
sdkmanager "build-tools;34.0.0"、パス$ANDROID_HOME/build-tools/34.0.0/aapt2 - macOS:
brew install --cask android-commandlinetoolsの後にsdkmanager "build-tools;34.0.0" - Windows: Android Studio → SDK Manager で build-tools にチェックを入れます
- 検証:
aapt2 version;バージョン注記——build-tools のバージョンは SDK の更新に応じて変わります(例は 34.0.0。新しい SDK にはさらに新しいバージョンが付属します)。コマンドインターフェースは安定しているため、インストール済みのバージョンを使用してください
dex2jar(任意)—— dex → jar
- GitHub release:
https://github.com/pxb1988/dex2jar/releasesから zip をダウンロードし、展開後にd2j-dex2jar.sh classes.dexで jar を生成し、jd-gui で閲覧します - Java が必要です
- 検証:
d2j-dex2jar.sh --version
apksigner / keytool —— 再パッケージ化の署名(smali パッチと併用)
- apksigner は Android SDK build-tools にあります(aapt2 と同じパス)。keytool は Java に付属します
- 検証:
apksigner --version;keytool -help
adb —— デバイスへのインストール/再パッケージ化の一連の流れを検証
- Android SDK platform-tools に付属します(
sdkmanager "platform-tools") - Linux:
apt install adb(Debian/Ubuntu);macOS:brew install --cask android-platform-tools;Arch:pacman -S android-tools - Windows: platform-tools の zip を公式サイトからダウンロードします
- 検証:
adb version
操作步骤
按顺序执行,每步记下结果(证据路径 + sha256,见 [[re-triage]])。
-
解包(apktool d):
apktool d app.apk -o out/解出
AndroidManifest.xml、smali/(可回编译的字节码)、res/、assets/、lib/。-s(--no-src)不解码源码(只出资源)、-r(--no-res)不解码资源(只出 smali),补丁时按需组合。产物比 jadx 更适合改后回编译。 -
AndroidManifest 入口/权限/组件:
grep -E 'application|activity|service|receiver|provider' out/AndroidManifest.xml | head -40记录:主入口(
application/ 首个activity的android:name)、uses-permission(短信 / 通话记录 / 设备管理权限是恶意或敏感信号)、exported 组件、android:debuggable="true"(可调试应用可直接 [[re-frida]] attach)。加固后入口常被替换成壳类(见坑 1)。 -
jadx 反编译 Java:
jadx -d java-out app.apk # 批量反编译全部 dex 类 jadx app.apk # 或 GUI 模式逐类浏览先看入口类(Application / MainActivity)与算法 / 校验类;敏感串(密钥、URL、校验逻辑)按
grep -rE 'key|secret|sign|license' java-out/定位。dex2jar 等价替代:d2j-dex2jar.sh app.apk得 jar 后用 jd-gui,jar 也可转 [[re-java]] 流程(CFR/JD-GUI 浏览、Java 加固识别)。反编译不出业务代码 → 加固识别(步骤 5)。 -
smali 补丁思路:
# 改 smali 后回编译、对齐、签名、安装(用 apksigner 时 zipalign 必须在签名之前,签名后不得再改包) apktool b out/ -o patched.apk keytool -genkey -v -keystore ks.jks -alias r -keyalg RSA -validity 3650 -storepass 123456 zipalign -P 16 -f -v 4 patched.apk aligned.apk apksigner sign --ks ks.jks --out signed.apk aligned.apk adb install signed.apk常用改法:条件跳转取反(
if-eqz↔if-nez)、把const/4 v0, 0x0改成返回常量、把校验方法直接return-void。先jadx定位逻辑再在对应 smali 里改。目标含签名自校验时补丁可能被拦(见坑 2)。 -
加固/混淆识别:
- 壳特征:jadx 只见壳类(
com.stub.StubApp=爱加密、com.secneo.apkwrapper/com.bangcle.*=梆梆,乐固等);lib/多一个壳 so(libjiagu.so=360 加固、libDexHelper.so=爱加密…);classes.dex体积异常小(真 dex 运行时解密) - 资源混淆特征:
res/资源路径被随机改名、resources.arsc结构异常 - 识别为加固 → 转脱壳域([[re-anti-analysis]] / [[re-mobile-pack]])或动态取内存 DEX([[re-frida]] / [[re-memdump]]);壳名/节区/熵的细粒度指纹对照走 [[re-packer-id]];资源混淆用 aapt2 还原:
aapt2 dump badging app.apk # 包名 / 入口 / 权限速览 aapt2 dump resources app.apk # 混淆后的资源映射
- 壳特征:jadx 只见壳类(
-
AAB 与 split APK(分发形态边界):
.aab(Android App Bundle):本质是 zip,内含 dex 与资源——jadx 可直接打开读代码;真机安装需经 bundletool 生成 APKS,拿到 .aab 按步骤 1-3 走即可- split APK(
base.apk+config.*.apk):主 dex 与代码在 base,语言/密度等配置在 split——静态分析以 base 为主,资源差异在 split 中比对;apktool 对 base 与 split 分别解包
跨域联合
- [[re-mobile]]:工作流第 2 步(APK 静态分支)固定调用本技能
- 需要运行时(解密 / hook / 绕过)→ [[re-frida]];运行时内存取 DEX → [[re-memdump]]
- 加固 / 带壳 → [[re-anti-analysis]](脱壳域)与 [[re-mobile-pack]](加固脱壳专项);原生 .so → [[re-binary-core]]([[re-format-elf]] / [[re-ghidra]])
- dex→jar 后的 Java 层深挖(混淆 / Java 加固)→ [[re-java]]
- 本技能被 [[re-analyze]] 的 triage「移动 App 分析」路径调用(re-mobile → re-apk)
常见坑与陷阱
-
加固样本 jadx 只看到壳壳:现象——反编译出来只有 StubApp 之类壳类,业务代码全无;原因——真 dex 加密存放在 assets/ 或运行时才解密;对策——按步骤 5 识别壳,转 [[re-anti-analysis]] 脱壳,或 [[re-frida]] / [[re-memdump]] 运行时取内存 DEX
-
签名校验拦补丁:现象——重打包安装后闪退或报"签名不一致 / 未签名";原因——应用内自校验签名(对比 PackageManager 的签名信息);对策——定位校验点打补丁绕过(smali 改返回值 / 跳转),或 [[re-frida]] hook
PackageManager.getPackageInfo调用链 -
资源混淆后无法直接看资源:现象——
res/路径与资源 ID 对不上、strings 定位不到目标资源;原因——资源被混淆随机改名;对策——aapt2 dump 还原映射(步骤 5),必要时结合动态分析对照 -
原生 .so 被当 Java 分析:现象——Java 层找不到核心逻辑(算法 / 反调试);原因——敏感逻辑写在 JNI 的 .so 里;对策——
lib/下 so 转 [[re-format-elf]] + [[re-ghidra]]([[re-binary-core]]),用导出表 /Java_<包名>_<类名>_<方法名>风格符号对 JNI 函数 -
apktool 回编译失败:现象——
apktool b报资源编译错误;原因——解包时资源被解码、部分资源格式不兼容回编译;对策——apktool d -r保留原资源不解码,只改 smali 后回编译 -
split APK 只分析 base 会缺资源:现象——目标字符串/资源在 base 里找不到;原因——语言/密度配置拆在
config.*.apksplit 里;对策——apktool 对 base 与各 split 分别解包,资源差异按 split 比对(步骤 6) -
自写 dex 解析四细节:opcode 是 u16 低字节(高字节是寄存器位,读完整 u16 当 opcode 全错位);
fill-array-data是 0x26(31t)、goto 是 0x28(0x24 是 filled-new-array,凭记忆必错);string_data_item 有 uleb128 长度前缀(不跳过会把长度当字符);code_item 的insns_size在 +12(+4 是 outs_size)——手写解析器前先对照 dex 规范核对布局 -
jadx 目录只剩启动脚本:现象——
jadx报 ClassNotFound;原因——安装不完整(jar 缺失/被清理);对策——从 GitHub release 重下完整 zip(codeload.github.com 比 github.com 稳),或直接用 baksmali 等单一工具 -
容器/双开(VirtualApp 类)样本分析:现象——样本跑在双开容器里行为异常、hook 不到目标进程,或要分析容器本身;原因——VA/Blackbox 容器通过"代理桩 + 动态注册"模拟系统:启动 Activity 走容器内假 AMS(Binder 动态代理拦截,把 VAPP 请求参数还原后再转发真实系统);IO 重定向把写死的绝对路径转向容器内安装路径;ContentProvider 的
onCreate作为容器初始化入口(handleBindApplication主动调用);原理同老版 Android(VA 只支持老版本,Blackbox 为现代参考实现);对策——分析容器内应用时注意进程真实归属(容器进程 vs 宿主进程)、hook 点选在容器框架层(假 AMS/IO 重定向函数)而非应用层;识别双开环境(双开检测)看/proc/self/maps容器 so、假包名路径特征;这类原理对免安装运行/插件化分析也通用 -
重打包后
install -r不生效(重打包陷阱):现象——重打包签名安装后行为毫无变化,误判「patch 无效」;原因——同包名同签名时-r会替换既有应用并保留数据,versionCode 未递增不阻止内容更新(它主要影响降级安装规则),「patch 未生效」应排查:签名校验链(见下条)、split APK 不一致、多用户/profile 的安装目标、构建产物缓存(apktool 回编译 build 缓存未清理)、目标进程未重启;对策——装机后做闭环验证:adb shell pm path <包名>取回已装 APK,对 patch 地址做字节级比对,字节确认在位后再排查逻辑层(消费点错误等)(来源:reverse-skills(inliver233),MIT) -
签名校验跨层链与系统版本漂移:现象——重打包后仍弹「签名不一致」类提示,或复用旧式签名适配 hook 后在新系统上反而误报篡改;原因——签名校验常是跨层链(Java 层取签名信息 → 摘要计算 → 原生层与硬编码基线比对,任一层不匹配即判失败),只中和单点不够;应用自带 PackageManager 签名适配 hook 可复用(拦截 getPackageInfo 系列、同时替换 signatures 与 signingInfo、只作用于自身包),但其反射构造的内部签名对象(如 SigningDetails)构造器签名随系统版本变化,抛异常返回 null 后触发误判;对策——优先复用应用自带的签名适配 hook,版本漂移时用 Frida 探测活构造器、改走公开构造器重建;带壳目标优先免重打包(运行时签名适配),无壳再考虑重打包;静态侧找原生比对函数中和失败分支(来源:reverse-skills(inliver233),MIT)