
简介「Android逆向助手」是一套面向Android开发与安全学习者的逆向分析工具合集整合apktool、dex2jar、jd-gui、autosign等常用组件可用于APK反编译、资源提取、Java字节码查看、重签名及安装测试服务于安全审计、功能分析、性能排查与授权机制研究等场景适合具备一定Android基础的中级开发者。压缩包共69个文件、约15.21MB涵盖18个jar核心工具库、17个bat与14个sh脚本、8个exe可执行程序、6个txt说明文档以及签名证书、配置文件和so库等辅助文件Windows与Linux环境下均有对应入口。已有145人学习包内工具链较完整便于读者搭建从反编译、代码查看到重签名的分析流程并借助说明文档快速定位组件用途减少零散收集与版本匹配成本。1. 装 android 逆向助手之前先认清三件套各管哪一段很多人搜 android 逆向助手心里期待的是一个双击安装、拖进 APK 就出源码的绿色软件。真把环境搭起来会发现这套能力是三件工具串成的一条链apktool 负责拆包和还原资源、dex2jar 负责把 dex 转成 jar、jd-gui 负责把 jar 读成带包名的 Java 代码。链上任何一环版本对不上整条就断在中间——最常见的翻车现场是 dex2jar 在 JDK 17 下静默产出一个几百字节的空 jarjd-gui 打开一片空白人还以为样本加壳了白白折腾一下午。这套环境适合三类人排查自己团队开发的应用在特定机型上的兼容问题、做移动安全课程实验、审计集成进项目的第三方 SDK 到底干了什么。前提只有一个分析对象必须是你有权处置的 APK。下面按我实际搭的顺序写从 JDK 选型一路写到跑通验证。2. 环境准备JDK 版本、目录规划和 apktool 落地装这套东西最容易忽略的不是工具本身是 Java 运行时。三件套里有两件是 Java 程序还有一个是 shell 脚本包着 jar 跑JDK 版本选错后面所有步骤都会以一种很难看懂的方式失败。2.1 JDK 到底选 8、11 还是 17先给结论主力用 JDK 11另备一份 JDK 8。apktool 2.9.x 官方要求 Java 8 及以上实测 8、11、17 都能正常拆包和回编译它是三者里最不挑的。jd-gui 1.6.6 有自带运行时的打包版也有纯 jar 版纯 jar 版在 JDK 8 和 11 上表现一致。真正挑食的是 dex2jar2.4 版本内部依赖的老版本字节码库对 JDK 17 的模块系统不友好在 17 上跑d2j-dex2jar有时直接抛NoClassDefFoundError有时更坏——不报错但输出的 jar 里只剩一个空的META-INF。我一般会同时装两个 JDK用环境变量切换而不是把系统默认 JDK 改来改去那样迟早会影响别的项目。检查当前版本# 先看默认 JDK三件套里所有 Java 相关的报错都从这个输出开始排查 java -version 21 javac -version 21 # Linux / macOS 下如果有多个 JDK看看装了哪些 /usr/libexec/java_home -V 2/dev/null || ls /usr/lib/jvm 2/dev/nulljava -version输出里的第一行就是版本号1.8.0_xxx是 JDK 811.0.x是 JDK 1117.0.x是 JDK 17。第二段命令在 macOS 上列出所有已安装的 JDK 路径Linux 上直接列/usr/lib/jvm目录。Windows 下对应的是C:\Program Files\Java\和C:\Program Files\Eclipse Adoptium\这类目录看一眼就知道了。切换靠JAVA_HOME不靠改 PATH 里的顺序# 临时切到 JDK 8 跑 dex2jar只影响当前终端会话 export JAVA_HOME/usr/lib/jvm/java-8-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH java -version # 切回 JDK 11 跑 apktool export JAVA_HOME/usr/lib/jvm/java-11-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH这种写法叫会话级切换关掉终端就失效好处是不会污染系统。参数上唯一要注意的是 PATH 必须把$JAVA_HOME/bin放在最前面否则系统里残留的/usr/bin/java软链会抢先命中java -version显示的还是老版本人会以为自己没切成功。Windows 下我更推荐写两个批处理文件放在工具目录里需要哪个点哪个rem jdk8.bat —— 只改当前命令行窗口的环境变量 echo off set JAVA_HOMEC:\Java\jdk1.8.0_381 set PATH%JAVA_HOME%\bin;%PATH% java -versionset在批处理里是会话变量不会写进系统环境变量双击运行的窗口关掉就恢复。这一点比在「系统属性 → 高级 → 环境变量」里反复改要安全得多那些改动是全局的改错了影响的是整台机器上的其他 Java 项目。提示不要用 JDK 21 及以上去跑 dex2jar 2.4。我试过一次脚本能启动、进度条也走完输出文件大小正常但 jd-gui 打开后每个类都只有一行注释排查了两个小时才怀疑到 JDK 头上。凡是「工具跑完了但结果是空的」这种玄学现象第一件事就是换 JDK 8 重跑。2.2 目录规划把三件套和产物分开工具装得散是后面所有混乱的源头。我在用户目录下建一个固定根目录工具、工作区、签名文件三块严格分开这样清理产物的时候不会误删工具迁移机器的时候打包一个目录就走。# 建目录骨架 mkdir -p ~/re/android-re/{bin,tools,work,keys} cd ~/re/android-re # 最终结构长这样 # ~/re/android-re/ # ├── bin/ 自己写的包装脚本加入 PATH # ├── tools/ apktool / dex2jar / jd-gui 的原始文件 # ├── work/ 每次分析的产物按 APK 名字建子目录 # └── keys/ 自己的调试签名回编译时用bin单独放包装脚本是为了把所有工具统一成「一条命令」的调用方式不用每次cd到工具目录再执行。work按样本名分子目录是因为 apktool 拆包会生成几十个文件夹混在一起根本分不清哪个是哪个版本的产物。把bin加进 PATH写进 shell 配置文件里# 追加到 ~/.bashrc 或 ~/.zshrc export ANDROID_RE_HOME$HOME/re/android-re export PATH$ANDROID_RE_HOME/bin:$PATHANDROID_RE_HOME这个变量后面所有脚本都会引用好处是换机器时只改这一行脚本里的相对路径不用动。2.3 apktool 的安装与两个配套文件apktool 的发布物是一个 jar 加一个启动脚本官方不提供安装程序。下载apktool_2.9.x.jar之后重命名为apktool.jar放进tools/apktool/目录。重命名不是强迫症是为了让启动脚本里写死的文件名固定下来将来升级版本只换 jar 不改脚本。Linux / macOS 的包装脚本#!/usr/bin/env bash # 保存为 ~/re/android-re/bin/apktool并 chmod x set -euo pipefail APKTOOL_HOME${ANDROID_RE_HOME:-$HOME/re/android-re}/tools/apktool JAR$APKTOOL_HOME/apktool.jar if [ ! -f $JAR ]; then echo 找不到 $JAR检查 apktool.jar 是否放对位置 2 exit 1 fi # -Xmx1g 是给大型 APK 留的堆默认堆拆大包容易 OOM exec java -Xmx1g -jar $JAR $set -euo pipefail让脚本遇到错误立即退出避免 apktool 失败后脚本继续往下跑。-Xmx1g把最大堆设成 1GB拆带大量资源的包时默认堆会抛OutOfMemoryError这个参数是最省事的预防。$把用户输入的所有参数原样透传给 apktool所以apktool d xxx.apk和直接java -jar的效果完全一样。Windows 的对应版本rem 保存为 apktool.bat和 apktool.jar 放同一目录 echo off java -Xmx1g -jar %~dp0apktool.jar %*%~dp0是批处理所在目录的绝对路径带上反斜杠结尾。用它拼 jar 路径脚本放哪都能跑不用写死盘符。装完立刻验证别等到拆包时才发现脚本有问题chmod x ~/re/android-re/bin/apktool apktool --version # 期望输出类似 2.9.3--version能打出版本号说明 java 能找到、jar 路径正确、脚本权限到位三件事一次验完。apktool 还有两个配套文件要提一句。一个是framework-res.apk反编译系统应用或者带厂商定制的包时需要用它提供资源表命令是apktool if framework-res.apk装一次就缓存在用户目录下。另一个是 smali/baksmaliapktool 内部已经内置了对应版本不需要单独下载但如果你的目的是改代码而不是读代码那走的是apktool d出来的smali/目录这条路跟 dex2jar 那条路是并行的两套方案别混着用。3. dex2jar 与 jd-gui 配置把 dex 变成能读的 Java 源码apktool 拆完你拿到的是资源和 smali 汇编可读性很差。想把逻辑读成 Java得靠 dex2jar 转格式、jd-gui 看结果这两步的配置问题比 apktool 多。3.1 dex2jar 解压即用但要先给脚本加执行权限dex2jar 是绿色包下载dex-tools-2.4.zip解压到tools/dex2jar/就算装完没有安装程序也没有环境变量。它的入口是一批d2j-*.sh和d2j-*.bat脚本压缩包解开后默认没有执行权限直接跑会报Permission deniedcd ~/re/android-re/tools/dex2jar chmod x *.sh # Linux / macOS 必须做这一步 ls d2j-*.sh # 确认 d2j-dex2jar.sh 在里面 # 用一个空 dex 试跑验证脚本本身能起来 ./d2j-dex2jar.sh --helpchmod x *.sh把目录下所有 shell 脚本加上可执行位。--help能打出用法说明说明脚本里的 java 调用链是通的这一步比直接拿真实 APK 试要快得多出问题也容易定位。最常用的命令是直接从 APK 转# -f 覆盖同名输出-o 指定输出文件名--force 忽略内部错误继续 ./d2j-dex2jar.sh -f -o ~/re/android-re/work/demo/demo.jar ~/re/android-re/work/demo/demo.apk参数逐个说清楚-f是强制覆盖已存在的输出文件不加这个参数第二次跑会直接报错退出。-o指定输出路径不指定的话 jar 会落在当前工作目录多跑几次就分不清哪份是最新的。--force在遇到个别无法解析的指令时继续转换而不是中断反编译第三方加固过的包时几乎是必加项。多 dex 的包要注意classes.dex、classes2.dex、classes3.dex是分开的dex2jar 一次只处理一个# 先解压出所有 dex cd ~/re/android-re/work/demo unzip -o demo.apk classes*.dex -d dex/ # 逐个转换输出名带序号 for f in dex/classes*.dex; do n$(basename $f .dex) ~/re/android-re/tools/dex2jar/d2j-dex2jar.sh -f -o jar/${n}.jar $f doneunzip -o的-o是覆盖-d指定解压目录引号里的classes*.dex是通配只解 dex 不碰资源。循环里basename取的是不带后缀的文件名输出到jar/目录下这样classes.jar和classes2.jar不会互相覆盖。很多人在这一步只转了主 dex然后在 jd-gui 里找不到某个类误以为代码被抽走了其实类就在第二个 dex 里。3.2 jd-gui 的启动方式与 JDK 绑定jd-gui 有两种发布形态带运行时的jd-gui-osx/jd-gui.exe打包版和纯jd-gui-1.6.6.jar。打包版开箱即用但绑死了自带的 JRE遇到需要调堆大小的情况没法改jar 版灵活前提是你得指定 java。# jar 版启动-Xmx 调大一点大 jar 反编译很吃内存 java -Xmx2g -jar ~/re/android-re/tools/jd-gui/jd-gui-1.6.6.jar-Xmx2g给到 2GB 堆。jd-gui 打开几十 MB 的 jar 时默认堆会卡在加载界面或者直接抛OutOfMemoryError: Java heap space这不是文件损坏纯粹是内存不够。启动后从菜单打开前面生成的 jar左侧树按包名展开双击类名就能看源码。jd-gui 有两个已知的显示问题值得提前知道。一是 Java 8 之后的 lambda 表达式和内部类反编译结果经常显示成// 反编译失败或者synthetic方法这是 jd-gui 的解析能力限制不是你的操作失误。二是大型混淆包打开后类名全是a、b、c这属于正常现象需要配合 apktool 拆出来的资源文件里的字符串去对。遇到 jd-gui 打不开的类兜底方案是用 JDK 自带的javap看字节码# 从 jar 里看某个类的结构不需要反编译成源码 javap -p -c -classpath ~/re/android-re/work/demo/demo.jar com.example.demo.MainActivity-p显示私有成员-c反汇编出字节码指令。字节码可读性差但胜在绝对准确jd-gui 显示异常时用它确认真实的方法签名和调用顺序比反复猜测靠谱。3.3 把三步串成一条链路手动敲三遍命令容易漏步骤我习惯在每个样本目录下放一个脚本输入 APK 名字输出拆包目录、jar 和一份检查清单#!/usr/bin/env bash # 保存为 ~/re/android-re/bin/analyzechmod x 后加入 PATH set -euo pipefail APK${1:?用法: analyze apk路径 [输出目录名]} NAME${2:-$(basename $APK .apk)} ROOT${ANDROID_RE_HOME:-$HOME/re/android-re}/work/$NAME mkdir -p $ROOT/dex $ROOT/jar echo 1/3 apktool 拆包 apktool d -f -o $ROOT/apktool $APK echo 2/3 提取 dex unzip -o $APK classes*.dex -d $ROOT/dex /dev/null echo 3/3 dex2jar 转换 for f in $ROOT/dex/classes*.dex; do n$(basename $f .dex) $ANDROID_RE_HOME/tools/dex2jar/d2j-dex2jar.sh -f -o $ROOT/jar/$n.jar $f done echo 完成产物在 $ROOT echo apktool 输出: $ROOT/apktool echo jar 输出: $ROOT/jar${1:?...}是参数必填检查不传 APK 路径时直接打印用法并退出不会带着空变量往下跑。${2:-...}是默认值第二个参数不传就用 APK 文件名作为输出目录名。mkdir -p保证目录存在重复跑不会报错。脚本里没有把 jd-gui 也串进去因为它是 GUI 程序串进脚本只会阻塞在那里等窗口关闭人工打开更合适。注意脚本里apktool d用的是-f而不是-r。-r表示不反编译资源速度确实快但你会同时失去AndroidManifest.xml的可读版本和所有字符串资源后面在混淆代码里想查个关键词就完全没线索了。除非你只做纯代码分析否则别省这一步。4. 避坑与排查五个真实踩过的坑这套环境的问题有个共同特点报错信息要么不出现要么出现的地方跟真正的原因隔着好几层。下面五条按我遇到的频率排序每条都写清现象、原因和处理办法。4.1 apktool 拆包报资源解析失败现象apktool d跑到一半抛出W: Could not decode attr value或者直接Exception in thread main brut.androlib.AndrolibException: Could not decode arsc file产物目录里只有半个res/。原因基本是两种。一种是 apktool 版本比目标 APK 的编译工具链老新版 aapt2 生成的资源表格式有变化老 apktool 认不出来。另一种是这个包用了厂商定制的资源表需要先导入framework-res.apk才能解析。解决先升 apktool 到最新 2.9.x 再试。仍失败的话用apktool d -r跳过资源解码先拿到smali/和AndroidManifest.xml的二进制版本代码分析照样能做需要看资源的话再单独用aapt2 dump resources导出。4.2 dex2jar 跑完jd-gui 打开是空壳现象命令正常结束进度条走完输出的 jar 文件大小也就几百 KBjd-gui 打开后每个类只有一行注释或者干脆什么都没有。原因JDK 版本太高dex2jar 2.4 在老字节码库上转换失败但不报错。这是最坑的一种失败模式因为它把错误伪装成了成功。解决把JAVA_HOME切到 JDK 8 重跑注意是会话级切换并重新java -version确认生效。第二可能是 APK 本身被加固过dex 只是壳真实代码在运行时才释放。判断方法是看 dex 文件大小——加固包的classes.dex通常只有几十 KB正常应用的 dex 动辄几 MB。4.3 jd-gui 双击没反应或者闪一下就退现象双击jd-gui.exe或运行java -jar后窗口不出现命令行窗口一闪而过。原因打包版 jd-gui 自带的是 32 位 JRE在 64 位系统上偶尔起不来jar 版则是 java 没在 PATH 里或者系统装的是 JRE 而不是 JDK缺javaw。解决改用 jar 版明确指定 java 绝对路径启动把堆调大并且在命令行里运行以便看到真实报错而不是双击。如果报java.lang.UnsupportedClassVersionError说明启动用的 java 版本比 jar 编译版本还低换 JDK 8 或 11 即可。4.4 Windows 下路径带中文或空格脚本全体失效现象apktool 报文件未找到dex2jar 报The system cannot find the path specified明明路径肉眼看着是对的。原因这些工具内部大量使用字符串拼接路径遇到中文和空格时没做转义。C:\Users\张三\Desktop\我的工具\这种路径几乎必炸。解决根目录建在纯英文无空格的路径下比如D:\re\android-re\。工作产物也放这里桌面和「我的文档」不要用来跑这些工具。这是血泪经验前期省的一次搬家后面要花几倍时间去排查莫名其妙的路径错误。4.5 apktool 回编译后装不上现象apktool b显示构建成功adb install报INSTALL_PARSE_FAILED_NO_CERTIFICATES或INSTALL_FAILED_UPDATE_INCOMPATIBLE。原因前者是产物没签名apktool 只负责打包不负责签名后者是设备上已经装了同包名的应用签名不一致导致覆盖安装被拒。解决用keytool生成一个自己的调试签名apksigner签完再装# 第一次生成调试用的 keystore之后复用即可 keytool -genkeypair -v -keystore ~/re/android-re/keys/debug.keystore \ -alias debug -keyalg RSA -keysize 2048 -validity 10000 \ -storepass android -keypass android -dname CNdebug # 对回编译产物签名 apksigner sign --ks ~/re/android-re/keys/debug.keystore \ --ks-pass pass:android --out signed.apk dist/app-release-unsigned.apk # 签名后必须验签这一步别省 apksigner verify --verbose signed.apk-validity 10000是有效期天数调试签名设长一点免得过一阵又要重来。-storepass和-keypass设成一样的省得每次输两遍。apksigner verify会逐项打印摘要算法和证书链看到Verified using v2 scheme: true才算真的签上了。5. 装完怎么验证跑通拿一个自己写的 Demo 走一遍全链路工具装完不等于环境可用。我的验证习惯是写一个最小的 Demo APK——一个 Activity 加一个工具类类里放一个能认出来的字符串常量——然后完整走一遍拆包到看源码的流程全部环节都对得上才算装好。用自己编译的包做验证有个额外好处你事先知道正确答案任何环节出偏差都能立刻发现。验证步骤和判定标准环节命令通过标准apktool 可用apktool --version打出版本号无异常堆栈apktool 拆包apktool d -f -o out demo.apkout/AndroidManifest.xml是明文 XMLout/res/有内容dex2jar 转换d2j-dex2jar.sh -f -o demo.jar demo.apkjar 大小在 MB 级不是几百 KBjd-gui 可读打开 demo.jar能搜到那个字符串常量类名带完整包名回编译apktool b out -o rebuilt.apk输出文件存在大小和原包接近签名安装apksigner sign后adb install设备上能正常启动第三步的判定标准值得展开讲一句。很多人在这一步栽跟头就是因为只看命令有没有报错不看输出文件大小。正常的 jar 应该是 MB 级如果只有几百 KB几乎可以断定转换失败直接回去查 JDK 版本别在 jd-gui 那边浪费时间。代码层面的自检可以写成一句话跑一次就知道链路通不通# 从 jar 里直接搜出预先埋好的字符串搜到就说明 dex→jar 这一步是通的 unzip -p ~/re/android-re/work/demo/jar/demo.jar *.class | strings | grep -i verify-me-2024unzip -p把内容输出到标准输出而不落盘*.class匹配 jar 里所有类文件strings抽出可读文本grep找那个预先埋好的标记串。这一条比打开 GUI 点半天更客观适合写成脚本放进 CI 里当回归检查。回编译那一步经常会漏。很多人拆包、转 jar、看代码一路顺畅真改了一行 smali 想装回去才发现 apktool 的入口没配好或者签名工具根本没装。所以验证必须包含「拆—读—改—回编译—签名—安装」的完整闭环缺任何一段都算没装好。从那以后我每次搭这套环境都强制先跑一遍这个 Demo 验证清单通过了才开始碰真实样本。省下来的不是验证的十分钟而是后面在「到底是工具没装好还是样本有问题」这个岔路口反复犹豫的几个小时。希望帮到你。本文还有配套的精品资源点击获取