百趣云 百趣云的博客

jadx 反混淆技巧:在 a.b.c 的迷宫里找路

混淆后的代码为什么难读

ProGuard/R8 混淆后,类名方法名全变成 a.b.ca.a.a——不同类同名、同类不同方法同名,全局搜索基本报废。但混淆只改名字,改不了结构:字符串常量、API 调用关系、继承体系都还在。反混淆的核心思路就是用结构特征替代名字特征

技巧一:字符串是永不混淆的路标

无论怎么混淆,字符串常量必须保留(运行时要真用)。逆向第一步永远是搜字符串:

# 在 jadx 里全局搜(Text search)
"sign"           → 找签名相关
"token"          → 找鉴权相关
"AES/CBC/PKCS5Padding"  → 直接定位加密代码
"/api/"          → 找接口定义
"deviceId"       → 找设备指纹

搜到字符串后按 X(交叉引用)查谁在用——使用点往往就是业务逻辑所在,类名再混淆也无所谓。

技巧二:从入口顺藤摸瓜

混淆改不了 AndroidManifest.xml(系统要按原名找组件)。从 Manifest 里的入口 Activity 开始:

  1. Manifest 找到主 Activity(即使类名混淆,路径是明确的)
  2. 进 onCreate 看它初始化了什么
  3. 网络层、加密层都会在启动链上露面

四大组件、Application 入口都是同理——Manifest 是混淆代码的地图

技巧三:批量重命名,自己建立秩序

jadx 支持重命名(N 键),且重命名会保存到项目文件。分析时养成习惯:

  • 认出 a.b.c 是签名工具类 → 重命名 SignUtils
  • 认出 a.a(String) 是 md5 → 重命名 md5

半小时后,你面对的就不再是乱码而是自己命名的清晰结构。重命名的另一个好处:交叉引用会跟着更新,越分析越清晰。

技巧四:用 API 调用反查业务类

想找"谁在做网络请求",别搜类名,搜 API:

# 搜 OkHttp 的使用
okhttp3.Request.Builder   → 查这个类的交叉引用 → 所有构造请求的地方
# 搜加解密 API
javax.crypto.Cipher       → 交叉引用 → 所有加解密点
# 搜 SharedPreferences
getSharedPreferences      → 找本地存储的 token/配置

系统 API 类名不会被混淆,它们是锚点,业务类是挂在锚点上的藤蔓。

技巧五:对付 R8 的激进优化

R8 比 ProGuard 更狠:内联短方法、删除未用代码、合并类。表现为:

  • 方法找不到:可能被内联了。搜方法内的特征字符串,在调用方里找展开的逻辑
  • 类消失了:可能被合并。看继承关系,找"胖得异常"的类
  • switch 变 if:枚举/常量的 switch 被优化。jadx 的 deobf 模式(Preferences → Deobfuscation)能缓解一部分

技巧六:jadx 命令行批量导出

GUI 适合交互分析,批量处理用命令行:

# 导出全部源码供 grep
jadx -d out_dir target.apk

# 然后上 ripgrep
rg -l "Cipher.getInstance" out_dir/
rg "getSign|makeSign|calcSign" out_dir/ -A 3

配合脚本批量分析几十个 APK 时,这条流水线比 GUI 点来点去快一百倍。

精髓:反混淆的心法

  1. 名字是假的,结构是真的——字符串、API 调用、Manifest 入口永不混淆
  2. 先找锚点再顺藤摸瓜,别试图通读代码
  3. 边分析边重命名,分析成果即时固化
  4. GUI 交互 + 命令行批量,按场景选工具

总结

  1. 字符串搜索 + 交叉引用是第一板斧
  2. Manifest 入口是混淆代码的地图
  3. 系统 API 是锚点,业务类挂在其上
  4. 重命名建立秩序,R8 优化用特征字符串破解

交流微信:run1255

By 百趣云 阅读量:2 On