更多>>关于我们
西安鲲之鹏网络信息技术有限公司从2010年开始专注于Web(网站)数据抓取领域。致力于为广大中国客户提供准确、快捷的数据采集相关服务。我们采用分布式系统架构,日采集网页数千万。我们拥有海量稳定高匿HTTP代理IP地址池,可以有效获取互联网任何公开可见信息。
您只需告诉我们您想抓取的网站是什么,您感兴趣的字段有哪些,你需要的数据是哪种格式,我们将为您做所有的工作,最后把数据(或程序)交付给你。
数据的格式可以是CSV、JSON、XML、ACCESS、SQLITE、MSSQL、MYSQL等等。
更多>>技术文章
EASI是一款澳洲的外卖APP(饭团外卖,UI跟国内的美团外卖相似度很高,官网:https://easi.com.au/),尝试对其抓包,失败。APP提示证书错误,信息如下图所示:
根据经验,这应该是ssl pinning机制搞的鬼(App认为Fidder颁布的证书是无效的)。
如果你对ssl pinning不熟悉,可以看一下这篇文章https://www.jianshu.com/p/22b56d977825。
之前曾处理过其它APP的ssl pinning问题(例如 小红书),根据经验做如下尝试:
(1)尝试使用Xposed + JustTrustMe插件,问题依旧。
(2)尝试Frida ssl unpinnin脚本(https://github.com/WooyunDota/DroidDrops/blob/master/2018/Frida.Android.Practice.md#okhttp-ssl-pinning),问题依旧。
常规的应对方法竟然无效,它是怎么做到的?让我们一探究竟。
反编译EASI.apk,根据之前APP上看到的提示信息中的关键词"not verified"搜索,很快找到okhttp3.internal.connection.c中的如下代码(如下图所示):
可以看出来,只有当a.j().verify(a.a().g(), session)的返回值是false时才会给出"...not verified..."提示。说明ssl pinning的检测方法就是verify()了。
通过搜索"verify("找到了verify()定义在okhttp3.internal.g.d类中, 如下图所示:
因此,只要我们hook上okhttp3.internal.g.d的verify()方法,使其始终返回true,就能绕过ssl pinning验证。
用Frida脚本可以轻松实现,代码如下:
# coding: utf-8 # 通过Frida实现ssl unpinning import sys import os import threading import subprocess import frida jscode = """ Java.perform(function () { var d = Java.use('okhttp3.internal.g.d'); try { d.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(p0, p1){ console.log('ssl unpinning for "' + p0 + '"'); return true; }; } catch (e) { console.log(e); } }); """ def start_frida_server(): """启动Frida服务端 """ # 判断/data/local/tmp/frida是否存在 cmd_ret = subprocess.check_output('adb shell ls /data/local/tmp/frida', shell=True) if not cmd_ret or 'No such file' in cmd_ret: print u'Frida server端不存在! 将复制到/data/local/tmp/frida' subprocess.check_output('adb push frida /data/local/tmp', shell=True) subprocess.check_output('adb shell chmod 777 /data/local/tmp/frida', shell=True) print u'Frida server端已复制到/data/local/tmp/frida.' # 判断frider是否在运行 cmd_ret = subprocess.check_output('adb shell ps', shell=True) if 'frida' not in cmd_ret: print u'Frida server端未启动!开始启动...' def run_frida_server(): os.system('adb shell ./data/local/tmp/frida') threading.Thread(target=run_frida_server).start() print u'Frida server端已启动.' else: print u'Fraida server端已经在运行中...' # 启动端口转发 os.system('adb forward tcp:27042 tcp:27042') os.system('adb forward tcp:27043 tcp:27043') if __name__ == '__main__': # 启动模拟器内的Frida server start_frida_server() # 启动目标APP,并注入hook代码 APP_NAME = 'com.easi.customer' device = frida.get_remote_device() pid = device.spawn([APP_NAME]) device.resume(pid) time.sleep(1) session = device.attach(pid) script = session.create_script(jscode) script.load() raw_input('')
如果你对Frida还不熟悉,建议读一下这篇文章:https://www.freebuf.com/articles/system/190565.html
启动Frida脚本之后,APP内不再有证书错误提示,而且Fiddler成功抓到包了,ssl unpinning成功。
如下图所示为上述Frida脚本运行输出截图:
如下图所示为Fidder成功抓取到APP的HTTP交互数据截图:
最后再回过来想一下为什么JustTrustMe和Github上的Frida ssl unpinning脚本对这个APP不起作用呢?因为JustTrustMe(和Frida ssl unpinning脚本) HOOK的函数是固定的一些,比如 okhttp3.CertificatePinne的check()方法,而这个APP改写了okhttp3库,里面根本就找不到okhttp3.CertificatePinne类,所以肯定HOOK不成功了。
看来,JustTrustMe之类插件也不是万能的,具体情况还要具体分析。我们不光要会使用工具,还应知道工具的原理,这样才能灵活应对各种问题。