当你写爬虫抓不到APP请求包的时候该怎么办?

2020-11-18 14:34:00

参考地址 当你写爬虫抓不到APP请求包的时候该怎么办?

当你写爬虫抓不到APP请求包的时候该怎么办?【高级篇-混淆导致通用Hook工具失效】

提示:因为高级篇以后的APP将无法使用很通用的方式处理,每种类型甚至是每个APP的反抓包处理方式都会有差别,所以这个系列以后会以【高级篇-具体类型】的形式来写。

这篇文章的主要内容是解决在遇到APP没有使用Android自带的HTTP客户端进行请求,并且对HTTP客户端的代码进行了混淆,导致通用工具JustTrustMe失效的问题。而中级篇中除了JustTrustMe以外的所有方法也都会对这种情况束手无策,原因是中级篇中的1、3、4方法本质上针对的是Android 7.0+系统增加的SSL Pinning方案,而无法对各个HTTP客户端自己实现的检测方案生效。(听说有个叫车速拍的APP就是这种类型呢)

那么应该怎么做才能抓到这类APP的包呢?很简单,依然是使用JustTrustMe之类的Hook工具就好了,只不过我们需要针对混淆后的名字对原来Hook的部分进行特殊处理。


这里我专门写了一个样例APP来进行演示(别抓我,我什么都不知道),这个APP做的事情就是在你点击了按钮之后,对百度首页发起一次请求,但是这个请求在没有破解SSL Pinning的正常情况下是不可能成功的,因为我设置的是一个随便输入的证书哈希,所以在请求的时候会因为正常的证书哈希与我随便输入的哈希不同导致出现请求失败的情况。


样例APP代码


这个APP我已经编译好放到GitHub上了,有两个版本,一个是对代码进行过混淆的,一个是没混淆的,文末会有下载地址,读者可以下载下来自己玩玩。


两个编译好的APK


开始演示之前说一下测试机的配置吧,这里用的测试机是Android 8.1.0的,已经Root+Xposed,同时已经安装并激活了JustTrustMe。


测试机系统信息



Xposed模块管理界面-JustTrustMe已开启



我们先来看一下没混淆过代码的版本,装上之后打开它,然后点击“点击发送请求”按钮。


样例APP界面



请求成功


不出意外的话会出现请求成功的字样,如果出现请求失败的话可能是你网络问题,证书问题会提示“证书验证失败”。

接下来我们看看混淆过代码的版本,操作同上。


证书验证失败


这次就是证书验证失败了,JustTrustMe并没有正常生效。


我们将这两个APK都放到Jadx中反编译一下看看。


在Jadx中反编译两个样例APK


可以看到混淆过的版本里,okhttp3下的所有类名已经变成了abcd这种名字。

然后我们来看一下JustTrustMe的代码。


JustTrustMe代码中Hook okhttp3的证书验证部分


可以看到它的代码中是对okhttp3.CertificatePinner类下的check方法进行Hook的,这个CertificatePinner类和check方法在没混淆过的APK中可以很清楚地看到。


反编译检测代码1



反编译检测代码2


那么现在JustTrustMe面对混淆后的版本就失效的原因已经很清晰了,因为它找不到这个okhttp3.CertificatePinner.check,所以根本就不可能Hook到检测方法,自然不会有任何效果。

所以...应该怎么办呢?这里依然是给出多种方法供读者选择:

  1. 修改JustTrustMe代码中Hook的类名和方法名然后重新编译

很简单,找到对应的检测方法,把JustTrustMe代码中Hook的className和methodName改成混淆后的名字即可,比如在这个混淆后的样例APP里,okhttp3.CertificatePinner.check变成了okhttp3.f.a。


反编译检测代码-混淆后


我们修改JustTrustMe中的Hook部分,同样改为f和a。




修改JustTrustMe对okhttp3的证书检测Hook


改完之后编译一下,安装到手机上替换原来的就好了。

  1. 使用Frida进行Hook

这个方法比方法1要更方便、更直接一些,因为需要的时候直接修改脚本马上就能用,不需要重新编译、重启手机或APP,这里直接拿瘦蛟舞大佬写的解除SSL Pinning脚本修改一下,同样是修改Hook okhttp3.CertificatePinner.check的部分,改成混淆后的名字即可。


修改瘦蛟舞的ObjectionUnpinningPlus脚本


  1. 魔改JustTrustMe,增加一个可以在运行时根据情况调整每种HTTP客户端的SSL Pinning检测部分的类名和方法名的功能

这个我暂时没空弄,感兴趣的同学可以自己实现一下。

  1. 魔改JustTrustMe,对Hook部分增加动态适配功能,做到即使开发者对代码进行了混淆也能自动找到真实的检测类和方法

同上,实现方式可以参考微信巫师框架部分的自动适配代码,实现以后理论上来讲是最方便的办法之一,因为是完全自动的操作,不需要人工介入。

  1. 修改反编译APP得到的代码再打包回去

我觉得应该没人会用这么蠢的办法吧...用Hook的方式做起来要方便太多了。

选择任意一种方法操作后,再打开混淆版本的APP就可以正常请求了。


这时候可能会有同学要问了,怎么样知道APP用的是哪个HTTP客户端?又怎么样快速定位混淆后的检测方法位置呢?

很简单,我们先关掉破解工具,连上代理然后抓个包看看混淆版本APP的请求。


抓包查看请求



User-Agent部分


和平时遇到SSL Pinning的情况一样,这里只会抓到一个CONNECT请求,注意右边的headers,从User-Agent中可以看出这个APP使用的是okhttp3,那么我们在混淆后的代码中定位检测部分代码的位置时,就只需要对照着okhttp3的原始代码来找就好了(其他HTTP客户端同理)。当然了,也不排除有些APP会把User-Agent改掉,如果从User-Agent上看不出来的话,那就看一下反编译出来的源代码部分结构,看看有没有像okhttp3之类的这种特别明显的HTTP客户端的名字,有的话就把它干掉就好了。

点我查看文中样例APP代码|下载编译好的样例APP


  • 2018-11-17 22:44:53

    LeakCanary,30分钟从入门到精通

    在性能优化中,内存是一个不得不聊的话题;然而内存泄漏,显示已经成为内存优化的一个重量级的方向。当前流行的内存泄漏分析工具中,不得不提的就是LeakCanary框架;这是一个集成方便, 使用便捷,配置超级简单的框架,实现的功能却是极为强大的。

  • 2018-11-17 22:53:01

    gc for alloc freed

    在数组中选择图片然后显示,然后。。。logcat不断显示GC回收。最后程序黑屏。

  • 2018-11-17 23:25:38

    Android高效内存1:一张图片占用多少内存

    在做内存优化的时候,我们发现除了解决内存泄露问题,剩下的就只有想办法减少真实的内存占用。而在App中,大部分内存可能被我们图片占用了,所以减少图片的内存占用可以带来直接的效果。本文就简单介绍一张图片到底占用多少内存,我们先假设我们有一张图片时 600 * 800 的,图片占用空间大小假设是 100KB。另外本文知识点也是面试官喜欢问的一个点,看看自己的回答到什么级别了。

  • 2018-11-18 09:06:06

    Android子线程中更新UI的3种方法

    UI的更新必须在主线程中完成,所以不管上述那种方法,都是将更新UI的消息发送到了主线程的消息对象,让主线程做处理。

  • 2018-11-19 15:10:23

    nodemailer的使用,nodejs发送邮件

    前段时间有个很普通的项目需要发邮件的功能,而且是刚开始学nodejs,所以只是搜索了下用什么好的库能实现,就找到了nodemailer了。这篇文章主要是记录一下使用的过程和经验。

  • 2018-11-21 09:07:37

    Android为每个应用分配多少内存?

    熟悉Android内存分配机制的朋友都知道,Android为每个进程分配内存时,采用弹性的分配方式,即刚开始并不会给应用分配很多的内存,而是给每一个进程分配一个“够用”的内存大小。

  • 2018-11-22 21:13:28

    webview之独立进程

    app内存占用大,被系统回收的概率就高,当每次把app切到后台再回到app时,可能每次app都会重启,最常见的是activity或fragment被回收了,导致fragment使用activity的数据时,出现NullPointerException。内存占用大,app越不稳定。运行性能差。webview加载页面后会占用更多的内存,从而导致app内存占用大,最终导致出现以上问题。

  • 2018-11-22 21:14:34

    为什么要采用WebView独立进程

    App中大量Web页面的使用容易导致App内存占用巨大,存在内存泄露,崩溃率高等问题,WebView独立进程的使用是解决Android WebView相关问题的一个合理的方案。