JADX 看不到算法之后,公开脱壳工具还能走多远:一次御盾加固 APK 实测
原文承接页:JADX 能不能还原原始算法?御盾加固 APK 的静态还原难度实测
这篇稿按看雪读者的习惯写:先给目标,再给过程,再给失败边界。结论不是“不可逆”,而是普通静态反编译没有还原原始算法,公开运行态 dump 工具也没有产出可用 DEX。测评继续走到了动态层,但没有把未验证的启动、二次打包和危险环境写成通过。
看雪版本重点保留工具链过程和失败尝试。它不会给出可复现 dump 步骤,但会说明为什么这轮不是只看原始 DEX。
测评目标与非目标
本轮不是泛扫 APK,也不是把“反编译看不到”直接包装成安全结论。目标被限定为:在常规静态反编译之后,继续使用公开工具和隔离运行环境,观察是否能进一步还原原始算法或形成可用 DEX dump。
目标
本轮动作
可公开结论
非目标与边界
原始算法还原
使用 JADX 观察 Java 可读面,再用 apktool 看 smali 结构。
普通源码面没有直接形成原始算法链,恢复结果集中在壳层、桥接、代理、装载和完整性相关结构。
不公开类名、源码片段、真实调用链。
DEX 动态 dump
安装公开 dexdump 工具并尝试运行态 dump。
公开工具链没有产出可用 DEX dump 文件。
不写动态 dump 已完成,不公开执行细节。
安装验证
在干净运行环境里安装候选 APK。
安装阶段成立,可以作为动态专项的前置条件。
不把安装成功写成业务通过。
稳定启动
拉起入口并观察进程状态。
运行期进入 native 快速闭合,不能声明完整稳定启动结论。
不公开日志栈、设备、组件、进程。
二次打包与危险环境
本轮只作为下一步计划。
需要单独专项验证。
不写二次打包闭合、危险环境闭合。
SO/Assets 载体
观察 native stripped、assets 大体量载荷和字符串面。
核心材料不在普通 Java 面直接展开,native 和 assets 是下一步重点。
不公开 SO 名、assets 名、构建标识、偏移。
这个目标矩阵的作用,是防止报告把“安装成功”“入口被拉起”“JADX 没有源码”混成一个大结论。每一行都只回答自己能回答的问题。
证据与测评依据
#
公开证据
复核方式
支撑判断
公开边界
1
APK 容器呈现双 DEX、双 native、多组 assets。
静态枚举容器结构。
样本不是单一 DEX 混淆形态,保护材料分布在多层载体。
不公开文件清单和真实名称。
2
JADX 生成 43 个 Java 文件,并报告 2 个反编译错误。
使用公开 Java 反编译工具观察恢复面。
普通源码面没有直接还原原始算法。
不公开源码目录、类名和代码片段。
3
apktool 生成 43 个 smali 文件,smali 体量约 9.2 万行。
资源解包和 smali 反汇编。
壳层、桥接、装载和控制逻辑体量明显。
不公开 smali 内容和方法名。
4
Manifest 呈现 release 配置、代理启动链和 native 不普通展开。
读取脱敏后的 Manifest 角色。
防护介入更早,native 载体不按普通资源方式暴露。
不公开 Application、Activity、Provider、factory 名称。
5
静态检索观察到 ClassLoader、ByteBuffer、native bridge、MessageDigest、签名摘要和 System.load 类痕迹。
按功能类别归纳恢复面。
DEX 还原需要跨越内存载入、native 桥接和完整性链。
不公开真实函数名、字符串和常量。
6
最大 assets 载体约 62 MB。
统计 assets 载体体量。
核心材料主要不在普通 Java 源码面直接展开。
不公开 assets 名、格式和内容。
7
native 载体为 arm64 ELF 且 stripped。
静态读取 native 表面。
native 低成本符号导航线索被收敛。
不公开 SO 名、构建标识、符号和偏移。
8
常见 secret、token、password、api-key 类明文模式未形成有效泄露证据。
字符串面模式扫描。
发布面明文暴露风险较低。
不公开完整 strings 输出。
9
干净环境下安装成功。
隔离环境安装烟测。
安装阶段可验证,不再沿用纯静态空结论。
不公开设备、包名、命令和安装路径。
10
入口拉起后进入 native 快速闭合,没有稳定业务界面。
最小动态启动观察。
不能公开声明完整稳定启动结论。
日志、栈、组件、进程只保留内部。
11
frida-dexdump 已安装并尝试,未产出可用 DEX dump。
公开工具 attach/spawn 两类路径尝试。
公开工具链未形成动态脱壳结果。
不公开具体命令、连接方式和原始错误。
12
Frida 能观察到短生命周期进程,但稳定 attach 窗口不足。
运行态进程枚举与状态观察。
运行期闭合速度对常规动态 dump 形成压力。
不公开进程号、应用标识和标签。
这些证据的共同点是:可以支撑“公开工具链未直接还原原始算法”,但不能支撑“所有动态对抗都完成”。这就是公开技术文章必须保留的边界。
攻击工具矩阵:本轮覆盖了什么,没有覆盖什么
这次补充的关键,不是把更多工具名堆上去,而是把攻击者的常规路线按阶段排清楚。每个阶段都要回答三个问题:这类工具想拿什么、这轮观察到了什么、为什么还不能写成最终通过或最终失败。
攻击阶段
常见工具/方案类别
攻击者目标
本轮纳入方式
本轮结论
后续专项
Java 源码恢复
JADX、JEB 类 Java 反编译器
直接恢复业务类、算法类和常量。
已用公开 Java 反编译工具观察恢复面。
恢复到的 Java 面有限,未形成原始算法链。
换工具交叉确认,但不公开源代码。
smali 反汇编
apktool、baksmali 类工具
绕过 Java 反编译失败,直接看 Dalvik 指令。
已做 smali 解码并统计体量。
smali 面主要支撑壳层、桥接、装载和控制流判断。
做控制流类别归纳,不公开方法级细节。
DEX dump/脱壳
frida-dexdump、运行态 dump、内存提取类工具
在类加载之后拿到内存中的 DEX 或修复后的 DEX。
已尝试公开 dump 工具。
没有产出可用 DEX dump。
需要可控运行窗口、Gadget 或真机矩阵专项。
注入/Hook
Frida、Xposed/LSPosed、inline hook、Java 层 hook
挂载关键加载点、签名点、解密点或业务函数。
本轮只做运行态观测和短生命周期进程确认。
能观察到窗口,但未形成稳定 hook 证据。
下一轮做防御型 observer,不公开真实 hook 点。
调试/跟踪
JDWP、ptrace、gdb/lldb、IDA/Ghidra 静态辅助
暂停进程、看调用栈、追 native 分支和解密时机。
本轮没有做完整调试链,只把 native stripped 和快速闭合作为调试难点记录。
不写“调试已阻断”,只写“低成本调试线索不足”。
单独做 native 调试抗性和符号恢复专项。
二次打包
apktool 回包、签名替换、资源改写、入口替换
改包、重签、绕完整性或替换入口。
本轮没有执行二次打包闭环。
不写二次打包通过或失败。
单独测回包、重签、安装、启动和 fail-closed。
危险环境
root、模拟器、Magisk、调试镜像、Hook 框架环境
放大动态观测能力,降低注入和 dump 门槛。
本轮只做干净环境安装启动,不写危险环境结论。
危险环境抗性未验证。
后续做环境矩阵,结论按环境分层。
这张表解决的是“知识面太窄”的问题:文章不再只围绕一个反编译器和一个 dump 工具,而是把脱壳、注入、调试、重打包、危险环境全部放进攻击路径。已经执行的写结果,没执行的明确写成后续专项,避免伪造事实。
测评经过
这轮测评重新补上了上一版缺失的内容:不是只看原始 DEX,也不是只跑 JADX 就收工。流程先做容器枚举,再做 JADX 和 apktool;随后进入隔离运行环境完成干净安装;最后尝试公开 dexdump 工具。最终结论也因此变得更克制:安装阶段成立,公开工具未产出可用 DEX dump,启动后进入 native 快速闭合,所以不能写稳定启动结论。
现象复核链:看到效果以后,至少再核实一次
上一版的问题是:看到一个现象后很快跳到下一步,没有解释它是否被复核。本版把每个现象都拆成“首次观察、复核动作、仍然不能证明什么”三段。
首次观察
复核动作
复核后的判断
仍然不能证明
Java 面没有出现原始算法链。
用 smali 面再看壳层、桥接和装载体量。
这不是单纯反编译器失败,smali 面也没有直接给出完整业务算法。
不能证明所有算法不可恢复。
smali 体量明显。
结合 Manifest 入口代理和 ClassLoader/native bridge 类别观察。
smali 主要价值在证明启动链和运行态装载复杂,而不是直接恢复算法。
不能把 smali 数量写成安全强度。
assets 存在大体量载体。
对照 Java 面和 native 面,确认核心材料没有在普通源码面直接展开。
资产化承载是原始算法不可直接读取的重要原因之一。
不能公开 assets 名称和格式,也不能断言其具体内容。
native 载体 stripped。
对照静态符号面和加载痕迹。
低成本符号导航线索被收敛,静态追 native 成本上升。
不能写成 native 不可分析。
干净环境安装成功。
继续执行入口拉起,不把安装成功当业务成功。
安装阶段成立,但业务稳定启动没有成立。
不能写二次打包、兼容性和危险环境通过。
启动后快速闭合。
用运行态枚举确认存在短生命周期窗口,再看 dump 工具是否产出。
闭合现象对 attach/dump 时间窗形成压力。
不能公开日志、栈、进程、包名,也不能写成所有注入失败。
公开 dump 工具未产出。
检查输出侧没有得到可用 DEX 文件,并回看进程稳定性。
失败更可能来自运行窗口不足、运行态闭合和材料不在普通 Java 面。
不能写成“永远无法脱壳”。
这条复核链把“看到效果”变成“看到现象、复查一次、收住结论”。真正专业的测评不是每一步都赢,而是每一步都知道自己能证明什么。
原始报告事实映射
报告事实
公开转述
支撑判断
未公开边界
本轮从本地最新加固 APK 候选开始,而不是使用人工整理稿。
有明确样本输入,测评不是凭空写作。
文章具备事实源。
路径、文件名、摘要。
静态结构包含 DEX、native、assets 多层载体。
加固结果呈现多层承载,不是单点混淆。
需要跨层评估。
文件清单、资产名称。
JADX 只恢复有限 Java 面并有错误。
普通 Java 反编译未直接恢复算法。
静态还原难度被抬高。
源码路径和片段。
apktool 能反汇编,但 smali 主要表现为壳层、装载和桥接面。
反汇编结果不等于原始算法可读。
需要运行态和载体专项。
smali 方法名。
Manifest 有代理链和 release 配置。
保护介入更早,发布形态更收敛。
启动链前置。
真实组件。
assets 存在大体量载体。
核心材料可能转入资产化承载。
普通 Java 面不能代表全貌。
assets 细节。
干净安装成立。
动态验证不是空白,安装阶段已确认。
可进入下一轮动态专项。
设备和命令。
启动后进入快速闭合。
不能写稳定启动或业务通过。
保留事实边界。
原始日志和栈。
frida-dexdump 未产出 dump。
公开工具没有拿到可用 DEX。
动态 dump 未形成,不夸大。
attach/spawn 细节。
短生命周期进程可被观察但不稳定。
普通 attach 时间窗不足。
后续需要可控环境专项。
进程与应用标识。
动态时间线
阶段
做了什么
观察结果
判断
公开边界
1
选择最新候选
得到一个约 63 MB 的加固 APK。
输入明确。
不公开文件名和摘要。
2
静态容器枚举
双 DEX、双 native、多组 assets。
多载体结构成立。
不公开清单。
3
JADX 反编译
43 个 Java 文件,2 个错误。
Java 面未直接还原算法。
不公开源码。
4
apktool 反汇编
43 个 smali 文件,约 9.2 万行。
反汇编可见但以壳层和装载为主。
不公开方法名。
5
Manifest 观察
release 配置、代理链、native 不普通展开。
启动链前置。
不公开组件。
6
安装烟测
干净环境安装成功。
安装阶段成立。
不公开设备和命令。
7
启动观察
入口拉起后 native 快速闭合。
不能写稳定启动结论。
不公开日志和栈。
8
Frida 枚举
可观察到短生命周期进程。
具备运行态窗口,但窗口不足。
不公开进程与应用标识。
9
frida-dexdump 尝试
未产出可用 DEX dump。
公开工具链未形成动态脱壳结果。
不公开运行方式。
10
专项规划
Gadget、真机、二次打包、DEX 修复、SO 载体进入后续。
当前文章只保留本轮事实。
不公开可复现路径。
攻防逻辑
攻击者做低成本还原,通常不会一开始就写复杂工具。他会先用 JADX 看 Java 面,再用 apktool 看 smali 和 Manifest,然后检查 native、assets 和字符串面。如果这些都没有直接给出算法,才会进入运行态 dump、Hook、Gadget、内存提取或定制环境。
本轮走到了公开工具的运行态尝试,而不是停在 JADX。这个差别很关键:只说“JADX 看不到”,懂行的人会认为证据很薄;写清楚 JADX、apktool、安装、Frida、frida-dexdump 的实际结果,才像真实测评记录。
攻击步骤
本轮观察
防守侧意义
不能公开的内容
Java 反编译
只恢复有限 Java 面。
原始算法没有直接摊在普通源码层。
源码和类名。
smali 反汇编
反汇编可见,但以壳层/桥接/装载为主。
需要跨层还原,不能只看 smali。
方法名和控制流细节。
Manifest 定位
有代理链和 release 配置。
防护介入靠前。
真实组件。
native 定位
native stripped。
低成本符号线索收敛。
符号和偏移。
assets 提取
大体量载体存在。
核心材料不在普通 Java 面。
文件名和格式。
动态 dump
公开工具未形成可用 DEX dump。
常规工具链没有直接拿到材料。
attach/spawn 细节。
稳定运行
入口拉起后快速闭合。
不能把安装成功写成业务通过。
日志与栈。
这里的“好话”不是硬夸,而是只写被验证的正向事实:静态源码面没有直接还原、公开 dump 工具未形成结果、安装阶段成立、运行边界被如实保留。没有证据的好话不写。
主因链:为什么没有复现出原始算法和可用 dump
本轮现象可以收束成一条主因链,而不是散点结论:
普通 Java 反编译没有直接恢复原始算法,说明核心逻辑没有以低成本源码面完整暴露。
smali 面能看到较大体量的壳层、桥接、装载和控制结构,但它更像“运行态材料调度层”,不是业务算法明文层。
Manifest 代理链、ClassLoader 类别、native bridge 类别和大体量 assets 共同指向同一件事:关键材料被放到跨 DEX、native、assets 和运行态加载路径里。
干净环境安装成功以后,入口拉起进入 native 快速闭合,说明动态分析不能只依赖普通 attach 时机。
公开 dump 工具没有产出可用 DEX,更可能是“可见 Java 面不足 + 运行态窗口短 + native/asset 载体参与 + 完整性/闭合路径介入”共同导致,而不是某一个工具单点失败。
所以,本轮最准确的结论是:常规静态还原无法直接复现原始算法;公开运行态 dump 工具在这个运行窗口下没有拿到可用 DEX;后续若要继续推进,必须把目标拆成 DEX dump 抗性、native 调试抗性、二次打包闭合和危险环境矩阵四个专项。文章不应该把这四个专项提前写成已通过。
public_evidence:
measurement_scope:
target: "static recovery plus public runtime dump attempt"
non_goal:
- "no claim of full business startup"
- "no claim of completed dynamic unpacking"
- "no claim of repackaging closure"
observations:
jadx_java_files: 43
jadx_errors: 2
apktool_smali_files: 43
smali_volume: "about 92k lines"
container_shape: "two DEX, two native carriers, multiple asset carriers"
install_result: "clean install succeeded"
runtime_result: "native fast closure after launch"
public_dexdump_result: "no usable DEX dump produced"
publish_boundary:
allowed:
- "tool categories"
- "redacted counts"
- "measurement sequence"
- "supported positive observations"
private:
- "package identifiers"
- "local paths"
- "raw commands"
- "class and component names"
- "logs, stacks, symbols, offsets"
defensive_assessment_flow:
1. classify_sample_without_publishing_identifiers
2. run_static_decompiler_and_record_visible_surface
3. run_resource_and_smali_decoder_for_shell_structure
4. inspect_native_and_asset_carriers_without_naming_them
5. install_in_clean_environment
6. observe_startup_boundary
7. attempt_public_runtime_dump_tooling
8. publish_only_supported_positive_findings
9. keep raw operational details private
过程证据行
#
过程
观察
支撑判断
公开边界
1
候选选择
找到最新可见加固 APK,体量约 63 MB。
本轮有明确输入。
不公开路径和文件摘要。
2
容器枚举
双 DEX、双 native、多组 assets。
多载体结构成立。
不公开清单。
3
JADX
43 个 Java 文件,2 个反编译错误。
普通源码面未直接还原算法。
不公开源码。
4
apktool
43 个 smali 文件,约 9.2 万行。
壳层、桥接、装载体量明显。
不公开 smali 内容。
5
Manifest
release 配置、代理链、native 不普通展开。
保护介入更前置。
不公开组件名。
6
native
arm64 stripped ELF。
native 符号线索收敛。
不公开 SO 名和构建标识。
7
assets
最大载体约 62 MB。
核心材料不在普通 Java 面。
不公开 assets 名。
8
字符串面
常见敏感明文模式未形成有效泄露。
发布面更干净。
不公开完整输出。
9
安装
干净环境安装成功。
动态验证不再空白。
不公开设备和命令。
10
启动
入口拉起后 native 快速闭合。
不能写稳定启动结论。
不公开日志、栈和进程。
11
Frida
可观察短生命周期进程。
有运行态窗口,但不稳定。
不公开应用标识。
12
dexdump
公开工具未产出可用 DEX dump。
动态脱壳结果未形成。
不公开 attach/spawn 细节。
平台化写法说明
看雪读者通常会追问:有没有跑动态?有没有跑 dump?有没有解释失败?本稿把这三件事放在正文核心位置。安装成功只写安装成功,运行期闭合只写闭合,frida-dexdump 未产出就写未产出。这样的文字不如“全都通过”好看,但更接近专业测评记录。
结论边界
这篇平台稿只发布可验证的正向事实:普通静态反编译没有直接还原原始算法,公开 dexdump 工具没有形成可用 dump,干净安装阶段成立,运行期边界被保留。它不发布未验证结论,不把安装成功写成稳定业务通过,不把工具未产出写成绝对不可还原,也不提供任何可复现脱壳或绕过步骤。
下一步适合拆成四个专项:DEX dump anti-repair、二次打包 fail-closed、危险环境矩阵、SO 载体分析。每个专项都需要单独目标、单独证据和单独边界,不应混在同一篇里。