
简介这套面向 Android 应用分析与安全审计场景的 APK 反编译工具合集适合想读懂他人应用实现、排查自身应用漏洞或做二次开发的开发者与逆向初学者。包内以 apktool 承担解包与重打包auto-sign 负责重签名dex2jar 把 DEX 转为 JARjd-gui 图形化查看 Java 源码四者串成从资源文件到字节码的完整链路覆盖清单解析、布局与字符串还原、签名校验等常见环节。压缩包共 58 个文件、约 10.58MB以 17 个 bat 与 14 个 sh 脚本为主搭配 11 个 jar 核心程序、3 个 exe 可执行文件与 9 个说明文档Windows 与类 Unix 双平台脚本齐备并附签名用的 pem 证书、pk8 私钥和 cfg 配置解压即可按目录调用省去逐个搜集组件的时间。目前已有 13978 人学习下载可对照练习资源还原与代码结构阅读也适合作为自查应用调试开关、明文密钥等隐患的入门工具集。1. 三条命令跑完一个 APK先说结论别把四个工具当竞品第一次把 apktool、dex2jar、jd-gui、auto-sign 这四个名字摆在一起时我下意识把它们当成了四个同类候选挨个装、挨个试折腾了一下午才发现方向从一开始就错了——它们根本不在同一个位置上竞争。apktool 管资源和 smali 的拆与装dex2jar 管 dex 到 jar 的搬运jd-gui 管把 jar 读成人能看懂的 Javaauto-sign 管把改完的包装回测试机。APK 反编译工具这套组合真正难的从来不是“选哪个”而是“哪一段该用谁、接缝处为什么会断”。后面要讲清楚的就三件事这套链路怎么分工、每个环节怎么验收、以及我踩过的那些坑到底该怎么绕。2. 四道工序各管一段谁替不了谁谁只是过渡先把分工摆明白后面所有对比才有意义。我见过太多人拿着 jd-gui 去打资源主意或者用 apktool 硬啃混淆后的逻辑最后得出结论“这工具不行”——工具没不行是位置站错了。这一章按工序拆每一段说清楚它吃什么、吐什么、边界在哪。2.1 apktool资源和 smali 的入口能回编译才是它的价值apktool 是整个链路里唯一一个“双向”的工具既能拆也能装回去。拆的时候它干两件事一是把resources.arsc和res/还原成近乎原始的目录结构和 XML二是把classes.dex反汇编成 smali。这两件事的价值不对称——资源还原的可读性极高基本拿到就能看懂布局、字符串、颜色、多语言smali 的可读性则完全取决于有没有混淆没混淆的 smali 能顺着方法名一路读到业务逻辑混淆过的就只剩a.a.a()这种。但 apktool 真正的护城河不是“能拆”而是“能装回去”。这一点决定了它在链路里的位置只要你的目标涉及改资源、改 smali、改清单文件最后都要回到 apktool 来执行bbuild。jd-gui 读得再舒服它也没法把你的修改写回 APK。所以我的判断标准很固定如果这次分析只需要“看”apktool 可以只当拆包器用如果需要“改”apktool 就是不可替代的主干其它三个都是它的辅助。它的短板也很清楚。第一它不负责 Java 源码级还原smali 读起来对不熟寄存器指令的人不友好第二它对外部框架资源有依赖遇到厂商定制过的资源表版本稍旧就直接解不动第三回编译出来的包默认是未签名、未对齐的直接装必失败。这三点后面避坑章节会逐条展开。2.2 dex2jar jd-gui只读源码这条线快但脆dex2jar 和 jd-gui 是一对绑定关系拆开看没意义。dex2jar 做的是格式转换把classes.dex转成标准.jar它不理解 Java 语义只做字节码层面的重打包jd-gui 才是那个把.class反编译成 Java 源码的阅读器。两者合起来构成“只读源码线”特点是上手极快、成品极像源码缺点是脆弱。脆弱体现在三个地方。一是多 dex现代 APK 少则两个 dex 多则十几个dex2jar 一次只吃一个文件你得自己循环二是混淆ProGuard/R8 处理过的代码转出来方法名全是单字母jd-gui 还会在控制流复杂的类上直接吐// INTERNAL ERROR //三是 dex 版本新版本 Android 工具链产出的 dex老版 dex2jar 会直接报不认识的 magic。那为什么还要用它因为在“没混淆 单 dex 逻辑不复杂”的样本上它的效率确实高——转完双击打开就是一棵完整的类树比在 smali 里翻寄存器快太多。我一般把它当成第一轮快速摸底的手段先转出来扫一遍包结构和类名心里有个地图再决定哪些类值得回 apktool 去抠 smali 细节。它是侦察兵不是主力。2.3 auto-sign不是链路核心但没有它验证不了改动严格说 auto-sign 不是“反编译工具”它是签名脚本通常由signapk.jar加一对测试密钥testkey.pk8/testkey.x509.pem组成早期在定制系统圈子里流传很广。它的作用只有一个给 apktool 回编译出来的未签名包盖个章让测试机能装上。放在链路里看它是最后一公里的验收工具。你改完 smali、回编译成功、auto-sign签完装上去闪退这时候才知道改动有问题没有这一步回编译成功只是“语法没错”不等于“逻辑能跑”。所以它的价值不在功能强而在闭环——把“我改对了”从猜测变成可验证的事实。但它的局限必须说清楚这套测试密钥是公开的任何人拿到都能签所以它只能用于本地验证绝不能用于任何对外发布的场景而且它对现代签名方案的支持有限Android 7 之后 v2 签名普及signapk.jar那套老流程在很多机型上会直接装不上。我给的建议很直接新环境用 Android SDK 自带的apksignerauto-sign只在维护老脚本、复现旧流程时保留。3. 逐项对比五个维度把四个工具排一遍选型这件事最怕“凭感觉说好用”。我一般会先定维度再下结论维度定了结论基本是算出来的而不是吵出来的。下面这套维度是我反复用过、能真正区分工具边界的。3.1 输入输出对照表先看谁能吃谁维度apktooldex2jarjd-guiauto-sign输入.apk.dex / .jar.jar / .class.apk输出资源目录 smali 可回编译工程.jar可读 Java 源码已签名 .apk是否双向拆 装双向单向只读只签不改多 dex 支持全量输出到 smali 目录需逐个文件转换可开多个 jar无关混淆样本表现smali 仍可读结构保留名字丢失可转反编译失败率高无关典型耗时中资源多则慢低低极低这张表最该看的是“是否双向”那一行。四个工具里只有 apktool 能把改动写回去其它三个全是单向前进。这意味着链路的形状是“apktool 出发 → 中间工具辅助理解 → 回到 apktool 落地”而不是四个工具平铺着让你挑。第二该看的是“多 dex 支持”。dex2jar 在这一格上是明确的短板它没有批量意识你必须自己写循环。这一点在新版 App 上会被无限放大——现在随便一个中等规模应用classes.dex到classes5.dex是常态手动一个个转非常容易漏。3.2 可读性与可回编译性两条完全不同的路线这两个指标经常被混为一谈其实是两条互斥的路线。可读性追求“像源码”可回编译性追求“结构无损”。jd-gui 在可读性上完胜——它输出的是 Java有 if、有 for、有类继承看一眼就懂但它的产物是不可逆的你没法把 jd-gui 的输出改完再编译回 APK中间隔着一整层编译器和签名语义早就变了。apktool 正相反。smali 读起来费劲但它是“一等公民”格式——你改一行 smali回编译就是把这一行原样汇编回去除了你自己改的地方其余字节码结构完全不动。这种保真度在排查“某个开关默认值到底在哪”这类问题时是刚需因为你要的是精确改动不是大致理解。所以我的实际用法是分工理解逻辑走 jd-gui 这条线落地修改走 apktool 这条线。两条线不互相替代只互相印证——jd-gui 里看到某个方法大概是做什么的再去 apktool 输出里搜对应方法名未混淆的话定位具体 smali改完回编译验证。混淆样本上这条印证链会断就只能纯靠 smali 硬读这也是我为什么强调先跑一遍 dex2jar 摸清包结构。3.3 多 dex、混淆、高版本 Resources谁先翻车三个压力场景下四个工具的表现差异非常明显这也是选型时最该拿真实样本去试的部分。多 dex 场景第一个翻车的是 dex2jar。它不是不支持是不主动得靠外层脚本兜。apktool 在这块最稳不管几个 dex全部反汇编到smali、smali_classes2、smali_classes3这一串目录里一个不落回编译时也自动按目录名重新打包成多个 dex不需要你操心。混淆场景翻车最惨的是 jd-gui。R8 开启后常见的结果是大面积// INTERNAL ERROR //和空方法体某些控制流平坦化的类甚至整个类都反编译不出来。dex2jar 会把类转出来但方法名全变成a、b、c阅读价值骤降。apktool 在这块反而是最坚挺的smali 本来就带寄存器指令混淆只能改名字改不了指令流逻辑还是能顺着invoke-*一路跟下去——费时间但跟得动。高版本 Resources 场景只有 apktool 会翻车因为只有它碰资源表。新版本 aapt2 编译出的resources.arsc在结构与旧版有差异apktool 版本偏旧就会报解析失败。这个坑的解法很单纯升级 apktool或者用-r参数跳过资源只解 smali。另外两三个工具压根不碰资源表在这个场景里“不出错”不是本事是没参与。4. 可复现流程从一份 APK 到可读源码和可装回包讲完对比落到能照着敲的流程。以下全程只针对自有应用、已获授权的测试样本或公开渠道下载且明确允许分析的学习样本任何情况下都不要把回编译产物对外分发签名密钥和测试密钥的边界必须守住。4.1 环境准备与版本对齐这一节最容易被跳过但它决定了后面 80% 的报错。我的习惯是先固定一组版本再动手不在报错时临时升级工具——那样你会同时失去“哪一步出的问题”的判断力。组件用途选择要点JDK 8跑 apktool、dex2jar、signapk兼容性最好新版本 JDK 在部分老脚本上有反射报错apktool 2.x拆包 / 回编译装最新稳定版资源表兼容性靠版本堆出来dex2jar 2.xdex → jarmacOS / Linux 下脚本要chmod xjd-guiJava 源码阅读优先用带 JRE 的发行包省去环境折腾Android SDK build-toolszipalign/apksigner版本要和目标targetSdk对得上JDK 版本这块特别说明一句。apktool 对 JDK 8 到 17 基本都能跑但 dex2jar 的老脚本在高版本 JDK 上会偶发NoSuchMethodError这是因为它内部依赖的一些字节码库版本很老。如果你的机器上装了多个 JDK用JAVA_HOME切到 8 跑 dex2jar跑完再切回来比折腾脚本依赖省事得多。4.2 反编译资源与 smaliapktool 的三个参数组合覆盖了绝大多数场景按目的选就行# 1) 完整拆资源和 smali 都要-f 覆盖已存在目录 apktool d -f -o ./out_full ./target.apk # 2) 只拆 smali-r 跳过资源遇上资源表解析失败时用它绕开 apktool d -f -r -o ./out_smali ./target.apk # 3) 只拆资源-s 不反汇编 dex纯看布局和字符串时最快 apktool d -f -s -o ./out_res ./target.apkd是 decode-f强制覆盖避免残留文件干扰-o指定输出目录-r和-s是两个方向相反的裁剪开关。-s这个参数我用得很多只想确认某个字符串、某个布局文件、某个权限声明的时候跳过 dex 反汇编能省一半以上时间。拆完先别急着改花两分钟做一次结构核对AndroidManifest.xml能不能正常打开、res/values/strings.xml有没有乱码、smali目录数量和unzip -l target.apk | grep classes的结果对不对得上。这三个检查能提前发现大部分版本不兼容问题比改到一半再回退要省事。4.3 dex 转 jar 与源码阅读多 dex 必须批量处理手动一个个转必漏# 先把所有 dex 抽出来注意引号防止 shell 提前展开 unzip -o ./target.apk classes*.dex -d ./dex_all # 循环转换输出文件名与源 dex 一一对应便于回溯 for f in ./dex_all/classes*.dex; do bash ./d2j-dex2jar.sh $f -o ${f%.dex}-dex2jar.jar --force doneunzip那一步的引号不能省classes*.dex交给 unzip 自己展开才能匹配到classes2.dex这种带序号的成员让 shell 展开就只会命中第一个。--force用于覆盖上次的产物避免读到旧 jar。转换完之后不要急着双击先给 jd-gui 分够内存大 jar 用默认堆会直接卡死# 3G 堆视机器内存调整打开大 jar 前先跑这条 java -Xmx3g -jar ./jd-gui.jar ./dex_all/classes-dex2jar.jar阅读顺序上我的习惯是先看AndroidManifest.xml里的application节点和四大组件声明建立“这个 App 有哪些入口”的印象再去 jd-gui 里按包名从外层往里钻。直接从MainActivity顺着调用链读容易陷进去先有地图再走路效率高得多。4.4 回编译、签名、装机验证回编译本身一条命令难的是顺序——对齐必须在签名之前签名之后不能再动包# 1) 回编译产物未签名未对齐 apktool b ./out_full -o ./patched_unsigned.apk # 2) 四字节对齐-p 让 so 库也参与对齐Android 上更稳 zipalign -p -f -v 4 ./patched_unsigned.apk ./patched_aligned.apk # 3) 签名明确指定 v1 v2 apksigner sign --ks ./demo.keystore --ks-pass pass:demo123 \ --ks-key-alias demo --v1-signing-enabled true \ --v2-signing-enabled true \ --out ./patched_signed.apk ./patched_aligned.apk # 4) 验签确认两种方案都通过再装机 apksigner verify --print-certs ./patched_signed.apk四步里最容易错的是第 2 步和第 3 步的顺序。zipalign会重写整个 zip 结构如果先签名再对齐v2 签名块会被破坏装机时报“解析包时出现问题”而不是签名错误很容易误判成 apktool 的问题。第 4 步的verify一定要跑它是唯一能在装机前告诉你签名方案是否完整的检查。如果你的环境里还留着老脚本auto-sign的等价命令是这样# 旧流程signapk 公开测试密钥仅限本地验证 java -jar ./signapk.jar ./testkey.x509.pem ./testkey.pk8 \ ./patched_unsigned.apk ./patched_test.apk这套东西的前提是回编译产物已经对齐过且测试机允许安装测试密钥签名的包。它的适用面正在快速收缩新环境别用它当主力。5. 避坑清单五条踩过的坑和排查顺序下面这五条都是我实际翻过车的按“现象 → 原因 → 解决”写遇到对应现象可以直接对号入座。排查顺序建议从上往下走因为前面的坑会伪装成后面的坑。5.1 反编译阶段Could not decode arsc file现象apktool d跑到一半中断报Could not decode arsc file或一串resource ... not found输出目录里res/是空的或者只有一半。原因目标 APK 的资源表由较新版本的 aapt2 编译产出本地 apktool 的资源解析器不认识新的表结构。厂商定制过的资源表会更容易触发因为它们在标准结构之外还有额外字段。解决先升 apktool 到最新稳定版这是九成情况的答案升级后仍失败就加-r跳过资源只解 smali先把逻辑分析做完资源部分换台装了更新版本 apktool 的机器单独处理。如果只缺框架资源用apktool if framework-res.apk先装框架文件再解。5.2 回编译成功但装不上INSTALL_FAILED_INVALID_APK现象apktool b显示构建成功adb install报INSTALL_FAILED_INVALID_APK或者“解析包时出现问题”换台机器还是同样结果。原因九成是没对齐或者签名方案缺失。apktool 的产物是“裸包”既没有 zipalign 也没有任何签名另一种情况是只做了 v1 签名而目标targetSdk已经要求 v2系统直接拒装。解决严格按 4.4 的顺序走一遍——先zipalign -p -f -v 4再apksigner sign签完必须apksigner verify --print-certs确认 v2 通过。还有一种隐蔽情况是覆盖安装导致签名冲突测试机上先卸载旧包再装别在签名不一致的状态下反复重试。5.3 签名这一环auto-sign签完仍提示签名不一致现象用老脚本signapk.jar签完安装时报签名冲突或者装上去启动即闪退日志里能看到签名校验相关的异常。原因公开测试密钥签出来的证书指纹和你机器上已装的同包名应用完全不同系统按“不同签名”拒绝覆盖另外老脚本只处理 v1v2/v3 区域是空的新系统会视为签名不完整。解决测试机上先卸载同包名的旧应用再装长期方案是彻底切到apksigner用自己的 keystore 签别再用公开测试密钥。这里补一句边界测试密钥签出来的包只能自己验证用不要流传出去。5.4 源码阅读jd-gui 大面积// INTERNAL ERROR //现象dex2jar 转出来没报错jd-gui 打开后大量方法体显示// INTERNAL ERROR //或者方法体是空的、只有一行注释。原因三个可能叠加——R8 混淆改写了控制流、dex 版本高于 dex2jar 内部支持的范围、类文件里有 jd-gui 的反编译器处理不了的指令模式。多 dex 场景下还可能只是因为你打开的是其中一个 jar另一部分类在别的包里。解决先确认是不是多 dex 漏转把所有 jar 都打开对比一下确认不是漏转就换路线——直接上能读 APK 的工具如 jadx 系列绕开 dex2jar 这一层或者在 apktool 输出的 smali 里按方法名反查。混淆严重的样本别在 jd-gui 上死磕投入产出比极低。5.5 阅读工具本身jd-gui 打开大 jar 直接卡死现象双击 jar 之后界面卡住、风扇狂转任务管理器里 Java 进程内存一路涨到顶然后被杀。原因jd-gui 默认堆内存偏小且打开时会尝试索引 jar 内全部类几万个类的包直接把堆吃满。解决用java -Xmx3g -jar jd-gui.jar显式给堆机器内存够就给到 4G还是慢就把 jar 拆开分批看或者改用按需加载的阅读器。这个坑不影响分析结论纯粹是工具配置问题但第一次遇到很容易误以为包损坏了。6. 收尾一条命令模板和我的固定检查顺序把上面所有内容压成一个可复用的动作序列我平时就是这么跑的一次贴完# 0) 先看包结构dex 数量、so 架构、资源规模 unzip -l ./target.apk | grep -E classes.*dex|lib/ # 1) 完整拆包 apktool d -f -o ./out_full ./target.apk # 2) 批量转 dex → jar unzip -o ./target.apk classes*.dex -d ./dex_all for f in ./dex_all/classes*.dex; do bash ./d2j-dex2jar.sh $f -o ${f%.dex}-dex2jar.jar --force done # 3) 改完回编译 → 对齐 → 签名 → 验签 → 装 apktool b ./out_full -o ./patched_unsigned.apk zipalign -p -f -v 4 ./patched_unsigned.apk ./patched_aligned.apk apksigner sign --ks ./demo.keystore --ks-pass pass:demo123 \ --ks-key-alias demo --out ./patched_signed.apk ./patched_aligned.apk apksigner verify --print-certs ./patched_signed.apk adb install -r ./patched_signed.apk这段脚本真正的价值不在命令本身而在顺序。第 0 步的unzip -l是我后来才加上的加了之后省掉大量返工——先知道有几个 dex、有没有 so、资源目录多大再决定用-r还是-s比上来就完整拆要理性得多。第 3 步里zipalign和apksigner的先后关系也不能反反了就是前面说的那个“解析包时出现问题”的坑。最后说一个判断上的习惯。这四个工具里apktool 是唯一值得你花时间研究参数和版本演进的因为它同时承担拆和装dex2jar 和 jd-gui 只需要会用、会批量、会调内存就够遇到反编译失败不要试图修工具直接换路线auto-sign 只当历史包袱处理新环境一律用apksigner。把这层权重分清之后选型就不再是“哪个更强”的问题而是“哪一段该投入精力”。从那以后我每次拿到一份新 APK都强制走一遍“先 unzip 看结构、再 apktool 拆、最后才动 smali”的顺序哪怕再急也不跳步。跳过第 0 步省下的两分钟通常会在后面以半小时的返工还回来。希望帮到你。本文还有配套的精品资源点击获取