Android 调试无源码的 APK 应用

  购买了《游戏机实用技术》的《塞尔达传说 旷野之息 中文版完全攻略本》电子版本,需要使用手机上的 UCG 应用才能阅读,但是其阅读体验不是很友好,结合其阅读前需要预下载,猜测是一个 PDF 文件,故想提取到电脑上进行查看。
  经过一番搜索,发现这个 PDF 文件是被加密的,又刚巧碰上公司内部举办 CTF 比赛,故借此机会研究一下 Android 逆向调试的方法。这里再说明一下,自己购买了使用权,解密 PDF 文件后,仅自己使用不传播不分享,我认为是没有问题的。《游戏机实用技术》杂志作为一个老牌刊物,目前碰到一些政策上的问题,多多支持正版也可以为其挺过难关尽一份微薄之力。

反编译源代码

  这里推荐一个非常好用的工具 jadx,可以直接打开一个 APK 文件,支持查找用例跳到声明等功能,甚至可以一键导出 Gradle 工程。
  刚开始反编译后,找不到任何有关 PDF 的代码,才发现 UCG 经过今年的风波,重新做了一个新版本 App,其不再采用本地下载 PDF 的方式,而是通过接口下载每一页的图片,目前 Android 端和微信小程序已上线,iOS 尚无,因此需要找到一个旧版本的 APK 安装包。新版本的包名是 com.bard.ucgm,旧版本的包名是 com.bard.vgmagazine,最新版本似乎是 1.9.1 尚能正常使用。
  这里找到最关键的计算密码的方法是:将商品的两个变量和一个常量拼接计算 MD5 然后再拼接一个 / 符号,因此接下来的目标就是通过调试找到这两个变量的值。

1
this.core.authenticatePassword(MD5Util.MD5(this.a + this.b + "c") + "/");

重新打包 APK 文件

  这里需要预先准备一个 APK 解包工具 Apktool

  1. 解包 APK:apktool.bat d "ucg_v1.9.1.apk" -o ucg
  2. 编辑 AndroidManifest.xml 文件,在 application 节点中加入 android:debuggable="true" 属性:<application android:debuggable="true" ... />
  3. 重新打包 APK:apktool.bat b -d "./ucg/" -o unsigned.apk
  4. 创建签名密钥:keytool -genkeypair -v -keystore debug.keystore -alias debug -keyalg RSA -keysize 2048 -validity 10000,这个 keytool 是 JDK 提供的工具
  5. 验证 APK:zipalign -f -v 4 unsigned.apk ready.apk,这个 zipalign 在 Android SDK 的 build-tools 中
  6. 签名 APK:apksigner sign --ks debug.keystore --ks-key-alias debug --out signed.apk ready.apk,这个 apksigner 也在 Android SDK 的 build-tools 中
  7. 安装 APK:adb install signed.apk
  8. 调试 APK:开发人员选项 -> 等待调试器 -> 选择待调试应用

使用 Android Sutdio 调试

  1. 首先要安装 smalidea 插件
  2. 使用 Android Studio 打开 “重新打包 APK 文件” 中第①步导出的目录
  3. smali 目录设为 Sources Root
  4. 在合适的位置设置断点
  5. 手机上启动 App
  6. Android Studio 选择附加到进程
  7. 手机上执行流程
  8. 命中断点,成功找到变量 ab

获取 PDF 文件

  • Android:可以参考附录的参考文献
  • iOS:同理,用越狱过的 iPhone,访问 App 的目录获取 PDF 文件

删除 PDF 文件的密码

  1. 使用 Adobe Acrobat 打开
  2. 保护
  3. 高级选项
  4. 删除安全性设置
  5. 保存

参考文献