爬虫工程师分享:三步就搞定 Android 逆向

本文源于我近期的一次公司内部分享,通过逆向某款 APP 来介绍逆向过程。由于仅作为学习用途,APP 的相关信息会被遮盖,敬请理解。

关于逆向

逆向——包括但不限于通过反编译、Hook 等手段,来解析一些功能的实现过程。

逆向在很多领域都有应用,比如如今爬虫技术已经遍地走,甚至不用写代码都可以爬取数据,导致前端开发的反爬意识也逐步提升。因此 JS、Android 等领域的逆向,已经成为爬虫开发者必备的技能之一。

本文介绍的是最典型常见的传参加密,在很多应用接口都能见到,如果我们逆向解析出加密过程,就可以模拟出相同的密文,得到后端接口的“认可”。

逆向的准备

这里介绍下关于 Android 的逆向准备:

  • Android 真机或模拟器(最好是真机)
  • 安装 Android 5.0 或 6.0 版本
  • Fiddler、Charles 等抓包工具
  • Jadx、ApkTool 等反编译工具
  • dumpDex、FDex2 等脱壳工具
  • Java、Android 开发基础知识
  • Xposed 框架开发基础知识

逆向步骤

介绍一下本文逆向的步骤:

爬虫工程师分享:三步就搞定 Android 逆向

当然,用三步概括,看上去像“把大象塞进冰箱分为几步”。逆向作为一项与应用开发者对抗的网络安全技术,其手段花样多端,有时甚至不需要代码也可以完成逆向,所以这个概括仅对应文中的遇到情况。

定位目标

本次逆向是针对某款 APP 的订单接口,首先我们使用抓包工具捕获订单列表请求,下图为 Charles 界面:

爬虫工程师分享:三步就搞定 Android 逆向

可以看到参数里的 data 字段是密文,我们就使用这个 API 作为目标切入点。

反编译 APK

这里使用的反编译工具是 Jadx,它可以将 APK 直接反编译成 Java 代码,并且具有 GUI 界面方便操作,如下图所示:

爬虫工程师分享:三步就搞定 Android 逆向

通过包名和一些代码分析,确定是被 360 加固后,接下来需要尝试脱壳。

脱壳使用的是 FDex2,这是一款基于 Xposed 框架的 Hook 插件,对 360 加固比较有效。它的原理是 Hook ClassLoader,然后通过反射调用 getDex 方法获取 Dex 对象并导出,这里的 Dex 就是 APP 真正执行的部分。当然并不是所有加固都可以被 Hook 到,更多脱壳手段还需要进阶研究。

FDex2 使用方式很简单,在 Xposed 框架里**后,选择目标 APP,然后重新打开 APP 后,被捕获的 Dex 文件会被保存下来,如下图所示:

爬虫工程师分享:三步就搞定 Android 逆向

Dex 是什么?简单地说,在 APK 构建过程中,Java 代码编译后产生的 class 文件,需要再转化成 Dex 文件,才能被 Android 虚拟机运行。

因此我们得到的 Dex 文件,就可以再次反编译成 Java 代码,我们还是使用 Jadx,它同样支持 Dex 格式。

由于 Dex 有体积限制,会被分包,如上图我们导出了不止一个文件,可以依次加载它们,通过搜索目标 API 的关键词,来找到目标代码块,如下图所示:

爬虫工程师分享:三步就搞定 Android 逆向

代码一般都会被反混淆,变量和方法名都是 a b c d 这样,然后搜索一个方法名,会发现有一万个同名的变量。还好 Jadx 内置了反混淆,开启后变量和方法被重命名为唯一编号,这样搜索时就不会有重名的情况了。

之后我们通过 Jadx 将代码导出成 Gradle 项目,借助 IDEA 的强大功能开始进行代码分析。

分析代码

由于大部分方法都是被重命名的,导致可读性严重下降,无法推测每个方法到底是什么功能,如下图这些代码:

爬虫工程师分享:三步就搞定 Android 逆向

第一眼你除了知道它是 Google 开发包之外,无法再获得更多信息。

所以分析代码这个步骤,完全是考验你的 Java 基本功 + 耐心,二者缺一不可。

不过不要退缩,我们只要遵循一些技巧,就可以大幅减少工作量。由于分析过程比较繁琐,这里就不结合具体代码了,只做一些理论总结:

  1. 从目标 API 开始入手,跟踪执行流程: 比如我们刚才已经搜索到关键词代码,那就从那一行开始,通过 IDEA 查看方法功能,可以一路向下点击。
  2. 只分析涉及代码块,缩小分析范围: 请求过程通常会构建 Request 对象,那参数加密一定就在构建对象之前,我们只要找到构建 Request 对象的代码,然后查看加密参数被传入之前都经过了怎样的处理,其他代码全部无视。
  3. 将部分代码块复制出来进行执行: 虽然反编译的项目代码无法被整体执行,但对于冗长难懂的方法代码,我们可以连同相关代码一起复制到一个新项目中,进行编译执行,方便我们调试。
  4. 尝试搜索一些关键词: 代码并不会所有都被混淆,可以尝试全局搜索一些关键词。比如 Java 常用的加密算法,我们可以搜索 RSA、AES、MD5、Encrypt、public_*key 这些关键词和正则匹配,能搜到再好不过了。

当你找到了加密方法,那么可以复制出来独立执行,然后自己构建参数传入加密,通过模拟请求,看接口是否正常返回。

需要注意,如果不能正常请求,并不一定是你找错了地方,也有可能代码本身有误,反编译的代码是有几率会出现这种情况的,导致你执行的和 APK 执行的结果不同。遇到这种情况,只能通过其他手段来修正代码,如阅读 Smali 代码、通过 Hook 等手段,这种情况比较复杂,后续会有文章单独介绍。

逆向之后

完成代码分析后,恭喜你已经成功完成一次逆向,接下来就可以实现一些功能,比如模拟登录请求。建议直接使用 Java 代码,因为大部分加密用的是 Java 内置的 RSA / AES 加密算法,其他语言的第三方库实现并不充分。


至此本次逆向分享结束,逆向是一个大课题,本文由于篇幅原因,也只能将常见套路的大致流程介绍一下,后续一定追加更多细节部分的文章。

本文首发自我的微信公众号:面向人生编程

爬虫工程师分享:三步就搞定 Android 逆向

关注后回复以下信息获取更多资源
回复【资料】获取 Python / Java 等学习资源
回复【插件】获取爬虫常用的 Chrome 插件
回复【知乎】获取最新知乎模拟登录