据我所知,妹子图(https://www.mzitu.com
)是很多人学习爬虫的必爬网站之一,而我在进入站点后发现他还提供安卓客户端,因此决定分析一下APP。本文涉及frida工具的使用、360加固应用的简单脱壳、APICloud本地资源的解密和xposed应用的编写等,干货满满!
前言
作为Python的初学者,若想要锻炼自己的代码能力,爬虫肯定是入门的不二选择,通过爬虫既能熟悉语法,又能提高自己的逻辑能力和一些网络编程的技术
但本文不会重点介绍爬虫的知识,而是将重点放在对APP的逆向分析上,因为APP请求的是接口,已经不太属于爬虫的范围了
如果你已经打开了这个网站,或是已经安装好了这个APP,求求你们,请一定要把持住自己
下面开始发车
抓包分析
逆向分析的时候,个人习惯第一步先抓包看看数据的内容。这里使用HttpCanary进行抓包:
请求 | 响应 |
---|---|
![]() | ![]() |
通过抓包可以知道:
- 请求头必须设置Referer:
https://app.mmzztt.com
(实际上是后面分析得到,这里顺带一提) - 响应体是json类型,且list字段被某种方式加密过了,后面需要重点分析
想要知道如何解密服务器返回的数据,看来只能逆向APP分析了
初步分析APP
首先拖入jadx工具中看下代码结构:
看到
com.qihoo.util
和com.stub
出现就知道应用被360加固过了,想要继续分析其代码部分则需要进行脱壳同时还注意到其assets中疑似有网页资源文件,且文件内容被加密了:
脱壳
对360加固的应用进行脱壳网上已经有比较成熟的方案了,我这里使用天鉴
这款App对其进行脱壳,由于篇幅原因,关于360的脱壳有时间我将另写一篇文章分析
脱出来的dex文件重命名为classes.dex
拖进jadx中分析其代码:
现在就可以看到其完整的代码了
重新查看代码结构:
发现该app使用了apicloud开发
APICLOUD简单来说就是:APICloud实现安卓框架,自己开发web就好了
所以app的主要逻辑基本都在js文件中,java代码只是个外壳,所以我们必须要对app的本地资源进行解密
解密本地资源
要知道,如果APP的文件被加密了是不能直接运行的,必须在代码开始运行前进行解密,这也是我们能够逆向解密它的一个关键
这里参考了看雪帖子:APICloud解密本地资源到逆向APP算法到通用资源解密
我们现在有两个方法获得解密后的本地资源:
- 分析源码,编写js脚本,使用frida去hook关键方法得到解密后的文件内容
- 使用看雪帖子中的通用解密代码,编写xposed hook应用来dump文件(实际上也是分析源码)
方法一 使用Frida直接Hook关键方法
分析源代码
首先找到拦截本地文件关键方法WebViewClient.shouldInterceptRequest(WebView, String)
,在jadx中搜索shouldInterceptRequest
:
点进去:
分析这段代码:
跟进b.e():
继续跟进v.d():
可知这是判断是否是需要进行管理的文件类型
回到shouldInterceptRequest
,this.b和this.a分别处理这两种情况:
需要处理文件 | 不需要处理文件 |
---|---|
![]() | ![]() |
到了这里 SDK 接管资源的痕迹就很明显了,再往下应该还可以找到怎么加载&解密文件,但是我们的目的只是dump出原来的明文资源就好,到这里就可以停止跟进分析了
注意到这两个方法的返回都类似于:return new j(c, new com.uzmap.pkg.uzcore.e.d(a2, a));
所以我们跟进j():
这是WebResourceResponse(String mimeType, String encoding,InputStream data)
的实现
再往下就是WebView内部了,SDK也没法做什么改变了,相信InputStream
就是标准的数据了,所以从new com.uzmap.pkg.uzcore.e.d(a2, a)
入手用Frida来Hook出数据看一下
Frida脚本
Frida的安装和配置就不多说了,百度都有的,这里不再赘述
python(基本都是固定写法,没太多要讲的):
1 | import sys |
JavaScript(重点):
1 | // 解密本地资源 |
运行结果:
这样就看到解密后的资源了
方法二 编写Xposed 通用解密程序
上面的代码分析提到,这类程序到最后都会交给Android系统底层的android.webkit.WebResourceResponse
类进行网页文件的处理,所以制作通用资源解密程序就可直接Hook这个类来实现
当然也可以用Frida工具实现(Frida工具太强大了),这里介绍另一个Hook方式:自己编写Xposed程序来实现
- 首先用Android Studio新建一个工程,这个应用不需要用户界面,所以我选择了
Add No Activity
:
- 添加依赖
de.robv.android.xposed:api:53
(根据实际需要选择api版本,这里选择53,它最低支持在Android4.x系统上运行):
- 新建Hook类,实现
IXposedHookLoadPackage
这个接口,并实现handleLoadPackage
方法:
1 | public class Hook implements IXposedHookLoadPackage { |
- 下面编写hook方法和保存文件的方法:
1 |
|
- 修改
AndroidManifest.xml
文件,在application标签下新增:
1 | <meta-data |
- 新建
Assets Floder
- 在
Assets
文件夹下新建文本文件xposed_init
,文件内容为你的Hook类路径:
1 | com.suqir.android.fuckapicloud.Hook |
- 由于程序没有Activity,所以不能直接通过点击运行按钮进行安装,我们使用
Build
->Build bundle(s)/APK(s)
->Build APK(s)
:
- Build完成后会在右下角出现提示,我们点击
location
打开文件所在的位置:
- 将apk文件安装到手机上:
我这里使用adb命令:
1 | adb install app-debug.apk |
- 最后一步,在xposed管理器中激活模块,重启手机后打开妹子图app稍等一会就能在
/data/data/com.kmw.chemeizu/files/decrypt/
目录下找到解密后的文件了:
经过与未加密的文件列表对比,发现并不是所有的加密文件都被dump出来,不过还好不影响我们后面的分析。但是从脱壳后的dex代码中分析,只要找到加密/解密的代码,我们自己写解密脚本也是可以的,那样就可以解密所有加密的文件,这里就不作分析了
数据解密
有了上一步的解密过的资源后,我们就能分析它的逻辑了
打开list.js
文件发现以下代码:
这说明app每次请求数据都会在请求头中设置Referer: 'https://app.mmzztt.com'
,所以我们后面在写爬虫脚本的时候需要设置这个字段
我们现在的目的是想知道抓包抓到的list字段是如何解密的
同样在list.js
文件中,发现可疑代码:
这是一段DES解密的代码,通过apicloud请求到的密钥key和偏移量iv来解密传入的data,这里并没有直接解密,而是将这些参数传递给java部分的方法aesDecodeCBCSync
,让这个方法进行处理。所以我们打开jadx搜索这个方法:
点进去
发现解密方法AESUtils.decrypt()
,跟进
在这里我们使用frida来Hook一下这个方法,看看处理结果是什么:
1 | Java.perform(function () { |
运行结果:
太棒了!通过hook这个方法,我们知道了服务器返回的数据确实是经过AES加密的,而且我们得到了密钥key和偏移量iv,这样我们就可以自己写数据的解密脚本来进行爬取服务器数据了,再一次感叹Frida工具的简单和强大!
结语
通过这一次的逆向分析,我学到了很多东西,比如Frida这个工具的简单上手、Xposed应用的开发、还有后面爬虫的一些细节处理。我始终相信,实战是对提升自己技术和能力的最好方法