2023年6月30日发(作者:)
对app的反爬测试之apk逆向分析-frida绕过sslpinning检测前⾔:
受⼈所托,需要对他们的产品进⾏反爬测试,所以就有了以下内容。
不过,我知道,针对这⽅⾯的⽂章太多了,是真的多,⽽且好早就有了,但是⽬前为⽌,很多app的防护基本也还是⽤的ssl pinning检测证书。因为,⽬前的app要嘛不⽤ssl,要嘛⽤就是⼀般的ssl,基本就是在⼿机上装个相关软件 的代理即可,⽽且这个代理基本就是fiddler,charlels,burpsuite,mitmproxy(Python环境下的)四个抓包软件⾃带的ssl证书,然后即可抓到ssl(https)的请求以上这些,基本可以解决⼤部分的app(其实很多使⽤ssl的⽹站也是这样处理)
但是因为很多app为了防⽌数据被分析爬取,会做ssl pinning验证
>
ssl painning
SSL Pinning是⼀种防⽌中间⼈攻击(MITM)的技术,主要机制是在客户端发起请求–>收到服务器发来的证书进⾏校验,如果收到的证书不被客户端信任,就直接断开连接不继续求情。所以在遇到对关键请求开启SSL Pinning的APP时,我们抓包就只能看到APP上提⽰⽆法连接⽹络或者请求失败之类的提⽰;⽽在抓包⼯具上⾯,要么就只能看到⼀排 CONNECT 请求,获取到证书却没有后续了,要么就是⼀些⽆关的请求,找不到想要的接⼝
⽐如如下图:
针对这种,如果是web⽹站,我们都知道,在本地装下抓包软件⾃带的ssl证书就⾏了,但是app的话,如此操作之后还是不⾏,⽽且app还会提⽰没⽹(⽐如:⽹络连接失败,⽹络有问题等等的),反正意思就是没⽹的意思,这种就是因为app⾃⾝做了ssl pinning验证处理,验证下当前的ssl证书是否是合法允许的,如果不是就会验证失败
其实使⽤ssl pinning⽬前已经成为了趋势,那么我们的⽬前对象刚好就有这个怎么办呢?
⽬前根据我的经验,最有效的有三个⽅法:
1.使⽤低版本的安卓机抓包2.使⽤ios端⼿机抓包3.使⽤frida绕过证书处理
>
使⽤低版本的安卓机抓包
因为app的话,⽬前主流的都是⽤的前后端分离开发,所以越到后期,app更新新版后,越会有不同版本的后端接⼝存在,⽽且新版接⼝和⽼版接⼝其实返回的数据差异性很⼩,并且有个关键点就是,为了兼容性,会依旧留下旧版接⼝,因为每个⽤户使⽤的⼿机不⼀样,安卓或者ios版本不同,系统版本也就会不同,且⽼款⼿机因为内存太⼩,不会更新新版的app包,种种情况下来,结果就是会留下旧版接⼝,⽽且这个旧版接⼝安全性⽐新版低很多,所以可以⽤低版本的饿安卓机来抓包,就正常的抓包流程即可,不出意外的话,可能还⽤的普通的http请求。为什么⾼版本的安卓就抓不到包呢,因为⾼版本的(安卓7以上)开始,安卓⾃带了⼀些安全机制,本质上就是只信任系统证书,不再信任⽤户⾃⼰安装的证书了,我们装的ssl代理证书就是⾃⼰装的,所以就会验证不通过了
>
使⽤ios端⼿机抓包
这个情况真的很多,因为,苹果端的appstore管理得很严,不能加些⾃⼰独特的东西,但是加ssl是可以的,但是很多app并没有加我就不知道了,这个情况就很简单,需要⼀台iphone,其他都是正常抓包操作,然后安装证书,把证书信任下就⾏了,详细的操作就不说了,⽹上很多教程
>
使⽤frida绕过证书处理
这个⽅法就是本篇⽂章的重点了,这个放到后⾯再说 >
其他⽅法其实也有其他的⽅法,这些⽅法并不是通⽤的,可能运⽓好可以⽤,运⽓不好就没⽤:
>> 安卓模拟器
⽤安卓模拟器,模拟低版本安卓然后抓包
>> 对证书信任,修改APP设置
看这个app是否是⾃有app,如果是⾃有的,⾕歌有debug模式,该模式下让app默认可以信任⽤户域的证书(trust-anchors),如果是⾮⾃有,⽤xposed+JustTrustMe即可,但是使⽤Xposed框架需要root,⽹上那些微信魔改⼩功能,什么⾃动抢红包,防消息撤回之类的就是⽤的xposed框架改的,⽤JustTrustMe来信任⽤户安装的证书⽬前市⾯上有VitualXposed、太极等虚拟的框架,不⽤root也可以操作,太极这个软件挺好的,有太极-阴(免root)和太极-阳(需要root),两个版本都可以⽤,但是针对有些app的话,太极-阴没戏,只能太极-阳,但是既然我都已经root了,我就没必要整这些了。
>> 强制信任证书
具体步骤:
s导出.pem证书,选择.prm类型 保存在pc上
2.修改证书名称系统证书⽬录:/system/etc/security/cacerts/
其中的每个证书的命名规则如下:
⽂件名可以⽤下⾯的命令计算出来:openssl x509 -subject_hash_old -in
后缀名的数字是为了防⽌⽂件名冲突的,⽐如如果两个证书算出的Hash值是⼀样的话,那么⼀个证书的后缀名数字可以设置成0,⽽另⼀个证书的后缀名数字可以设置成1
3. ⽤adb命令把证书推到⼿机上adb push xxxxxxx.0 /sdcard/
4.复制到系统⽬录并修改权限(安卓8.1.0 Magisk Root)
mount -o rw,remount /system 【不修改 没法写⼊】mount -o rw,remount /
mv /sdcard/xxxxxxx.0 /etc/security/cacerts/ 移动⽂件到系统chown root:root /etc/security/cacerts/fc365f9d.0 修改⽤户组chmod 644 /system/etc/security/cacerts/xxxxxxx.0 修改权限
5. 重启⼿机验证即可这时你就发现证书已经在系统级别⾥了
6.进⾏抓包
补充:
这个是安卓端的抓包⼯具,⽹上吹得很⽕,根据我(我⼿机是安卓10)亲⾃操作,发现其实没有⽤,也不知道是不是我的姿势错误,或者我⼿机安卓系统版本太⾼了失效
⽤这个可以免root操作,然后正常抓包,但是这个⽅法我没有实际操作过,⽹上的资料不多,⾃⾏查找
Xposed 是⼀款 Android 端的 Hook ⼯具,利⽤它我们可以 Hook App ⾥⾯的关键⽅法的执⾏逻辑,绕过 HTTPS 的证书校验过程。JustTrustMe 是基于 Xposed ⼀个插件,它可以将 HTTPS 证书校验的部分进⾏ Hook,改写其中的证书校验逻辑,这种思路是属于第⼆种绕过 HTTPS 证书校验的解决⽅案。
当然基于 Xposed 的类似插件也有很多,如 SSLKiller、sslunpining 等等,可以⾃⾏搜索。
不过 Xposed 的安装必须要 ROOT,如果不想 ROOT 的话,可以使⽤后⽂介绍的 VirtualXposed。
Xposed 的使⽤需要 ROOT,如果不想 ROOT 的话,可以直接使⽤⼀款基于 VirtualApp 开发的 VirtualXposed ⼯具,它提供了⼀个虚拟环境,内置了 Xposed。我们只需要将想要的软件安装到 VirtualXposed ⾥⾯就能使⽤ Xposed 的功能了,然后配合 JustTrustMe 插件也能解决 SSL Pining 的问题,这种思路是属于第⼆种绕过 HTTPS 证书校验的解决⽅案。
>> 特殊改写
其实本质上是对⼀些关键的校验⽅法进⾏了 Hook 和改写,去除了⼀些校验逻辑。但是对于⼀些代码混淆后的 App 来说,其校验 HTTPS 证书的⽅法名直接变了,那么JustTrustMe 这样的插件就⽆法 Hook 这些⽅法,因此也就⽆效了。
>> 强制全局代理
⼿机root后,使⽤proxy Droid 实现强制全局代理,让ssl代理证书⽣效,proxy Droid可以在UpToDown,ApkHere等的地⽅下载
抓包免root,在安卓机上安装packet capture,然后抓包,我试了下,我的⼿机(我⼿机是安卓10)没⽤ >> 魔改JustTrustMe在JustTrustMe插件上增加⼀个可以运⾏时根据实际情况调整ssl检测的功能,对hook增加动态适配,这个⽅法我没试过,我在看雪论坛⾥找到⼀个 JustTrustMePlus,
>> 反编译app包⽤apktools修改配置⽂件⾥的ssl证书检测部分,可利⽤jadx等⼯具分析源码,然后重新打包,再抓包分析,这个⽅法是可⾏的,详细的步骤⾃⾏百度吧,后续有时间的话,我单独发⼀篇对app的脱壳重新打包
处理这个⼯具的原理就是把⼀个安卓机在本地作为⼀台服务器,然后找到数据接⼝,这个⽅法没有亲测过,更多的适⽤于获取app的sign/token时去获取接⼝
以上的⽅法就是我所知道的⽅法,各位朋友⾃⾏操作
接下来进⼊正题,frida hook
什么是frida
Frida是个轻量级别的hook框架, 是Python API,⽤JavaScript调试来逻辑Frida的核⼼是⽤C编写的,并将注⼊到⽬标进程中,在这些进程中,JS可以完全访问内存,挂钩函数甚⾄调⽤进程内的本机函数来执⾏。使⽤Python和JS可以使⽤⽆风险的API进⾏快速开发。Frida可以帮助您轻松捕获JS中的错误并为您提供异常⽽不是崩溃。
frida是平台原⽣app的Greasemonkey,说的专业⼀点,就是⼀种动态插桩⼯具,可以插⼊⼀些代码到原⽣app的内存空间去,(动态地监视和修改其⾏为),这些原⽣平台可以是Win、Mac、Linux、Android或者iOS。⽽且frida还是开源的。Greasemonkey可能⼤家不明⽩,它其实就是firefox的⼀套插件体系,使⽤它编写的脚本可以直接改变firefox对⽹页的编排⽅式,实现想要的任何功能。⽽且这套插件还是外挂的,⾮常灵活机动。
frida框架主要分为两部分:1)⼀部分是运⾏在系统上的交互⼯具frida CLI。2)另⼀部分是运⾏在⽬标机器上的代码注⼊⼯具 frida-server
注:以下相关操作,终端⾥凡是 C:UsersAdministrator 开头的都是在pc机上操作的,需要在安卓机⽬录⾥操作的我都有说明,不要搞混了
环境准备
>
安装frida没有python的安装python,然后安装frida:pip install fridapip install frida-tools 安装过程很慢,这个只能耐⼼等待,然后如果你是macbook的话,如果你遇到安装出错,可以看看我这篇⽂章的解决⽅法
然后frida是mac,linux,windows都可以安装使⽤的,这个根据你⾃⼰的条件选择了>
安装adb这个就很简单,去 然后下载这个⼯具:
如果你下载太慢可以在我这⾥下载:下载完毕后,解压,然后放到你想放的路径,然后配置下环境变量即可,此电脑(我的电脑)- 属性-⾼级系统设置-环境变量-系统变量的path,新增即可
然后,打开终端:
敲adb,回车,如果有以下提⽰,说明你adb安装成功
以上配置是windows平台,如果是其他平台的话,⾃⾏查找,这⾥就不展⽰了
>
找⼀个安卓机(已root)根据现在的⾏情,要找到⼀个已root的⼿机,问题不⼤也不⼩,但是很多时候没有必要,所以我这⾥就选择⽤安卓模拟器来辅助操作了安装夜神模拟器,夜神默认是安卓5,你可以⾃⾏选择安卓版本,在夜神⾥设置已root即可
>
打开开发者选项⾥的USB调试
设置⾥⾯,关于本机,然后狂点系统版本号,开启开发者模式:
返回,会多⼀个开发者选项:
打开调试
>
adb连接安卓机(模拟器)
在安装了frida和adb的真机操作系统下,打开终端,⽤ adb connect IP 连接安卓机:
夜神的ip是127.0.0.1:62001,这⾥注意,如果你创建了多个安卓系统的话,那么你待连接的安卓机不⼀定是62001,可能是其他的,可以在安装⽬录⾥⾯找
进⼊后,找⽂件
⽤⽂本编辑器打开,搜索5555就能看到是哪个端⼝了,为什么必须是5555端⼝呢,因为5555就是模拟器挂载在我们windows真机上的端⼝
⽤ adb connect 127.0.0.1:端⼝ 连接
我这⾥已经连接上了,所以提⽰已连接
连接之后可以⽤ adb devices查看已连接的机器:
>
安装frida-serverfrida-server这个需要安装在安卓机上,但是安卓机我们都知道有很多个版本,对应架构才⾏,要查看当前安卓机的架构:adb shell getprop
然后去这⾥下载对应架构的frida-server :
我这⾥是x86,安卓,所以选下⾯我选中那个下载,你的安卓机是什么你就选哪个就⾏了
然后下载很慢,我这⾥也提供了,
但是,⼀定注意,pip安装的frida版本⼀定要跟去frida官⽹下载的frida-server版本对应上,不然连不上
解压,然后⽤adb 传到安卓机上adb push (本机的frida-sever⽂件所在⽬录) (安卓机⽬录)
这⾥提⽰太长了,看不出来,可以⽤adb shell 去那个⽬录下看下是否有frida-server即可:
修改frida-server的权限:chmod 700 frida-server
>
下载⼀个frida hook 的js⽂件
这个⽂件,有好⼏个版本,我选⽤了两个版本,放到下⾯,你们⾃⼰选择吧
版本1:
setTimeout(function(){ m(function (){ (""); ("[.] Cert Pinning Bypass/Re-Pinning"); var CertificateFactory = ("icateFactory"); var FileInputStream = ("putStream"); var BufferedInputStream = ("edInputStream"); var X509Certificate = (".X509Certificate"); var KeyStore = ("re"); var TrustManagerFactory = ("anagerFactory"); var SSLContext = ("text"); // Load CAs from an InputStream ("[+] Loading ") cf = tance("X.509");
try { var fileInputStream = FileInputStream.$new("/data/local/tmp/"); } catch(err) { ("[o] " + err); } var bufferedInputStream = BufferedInputStream.$new(fileInputStream); var ca = teCertificate(bufferedInputStream); (); var certInfo = (ca, X509Certificate); ("[o] Our CA Info: " + jectDN()); // Create a KeyStore containing our trusted CAs ("[+] Creating a KeyStore for "); var keyStoreType = aultType(); var keyStore = tance(keyStoreType); (null, null); tificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore ("[+] Creating a TrustManager that trusts the CA in "); var tmfAlgorithm = aultAlgorithm(); var tmf = tance(tmfAlgorithm); (keyStore); ("[+] Our TrustManager "); ("[+] Hijacking SSLContext ") ("[-] Waiting for the app to invoke ()...") ad("[ager;", "[anager;", "Random").implementation = function(a,b,c) { ("[o] App invoked ..."); ad("[ager;", "[anager;", "Random").call(this, a, stManagers(), c); ("[+] SSLContext initialized with our custom TrustManager!"); } });},0); 版本2:m(function() { var array_list = ("ist"); var ApiClient = ('anagerImpl'); entation = function(a1, a2, a3, a4, a5, a6) { // ('Bypassing SSL Pinning'); var k = array_list.$new(); return k;
}}, 0); 然后你⾃⼰复制以上的任何⼀个版本的代码,然后在本地新建⼀个js⽂件,粘贴进去就⾏了
或者这个:
这⾥补充⼀个完全版:
m(function() {/*hook list:k_security_config (android 7.0+) Http client (support partly)*/ // Attempts to bypass SSL pinning implementations in a number of // ways. These include implementing a new TrustManager that will // accept any SSL certificate, overriding OkHTTP v3 check() // method etc. var X509TrustManager = ('.X509TrustManager'); var HostnameVerifier = ('meVerifier'); var SSLContext = ('text'); var quiet_output = false; // Helper method to honor the quiet flag. function quiet_send(data) { if (quiet_output) { return; } send(data) } // Implement a new TrustManager // ref: /oleavr/3ca67a173ff7d207c6b8c3b0ca65a9d8 // erClass() is only supported on ART for now(201803). 所以android 4.4以下不兼容,4.4要切换成ART使⽤. /*06-07 16:15:38.541 27021-27073/ningdemo W/: lArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing06-07 16:15:38.542 27021-27073/ningdemo W/: at .X509TrustManagerExtensions.
上⾯这个完全版本包含了如下功能,如果你想⼀步到位的话,就可以⽤这个完全版
SSLcontext(ART only)okhttpwebviewXUtils(ART only)httpclientandroidlibJSSEnetwork_security_config (android 7.0+)Apache Http client (support partly)OpenSSLSocketImplTrustKitCronet
任意⼀个都可以,不要三个都⽤,都⽤也没⽤,根据实际情况选⽤
>
安卓机配置代理
配置代理到开启了抓包⼯具的IP上:
长按wiredssid
补充⼀句,当配置完代理后,pc端电脑上⼀定要打开对应的抓包软件,不然安卓机会没⽹
>
安卓机上安装ssl证书
根据你选⽤的抓包⼯具,fiddler,charles,burpsuite,安装证书即可,你可以访问局域⽹下带的ip来下载,然后安装:
配置了代理再执⾏此步骤,不然打不开下载证书的局域⽹址
也可以⽤adb 像传frida-server⼀样,⽤adb push把证书push到安卓机上,然后在安卓机的设置-安全⾥本地导⼊证书:
⽤adb push 之后,还是把代理配置上,不然后⾯操作也⽆法继续,不管怎么操作,反正必须要ssl证书安装上即可
开始hook
hook的本质意思就是钩⼦,在开发⾥⾯通俗的说就是可以在任意流程⾥插⼀⼿,然后做些⼿脚,⽐如打开⼀个app,在启动到完全打开app,显⽰app的⾸页,这个过程就可以hook⼀下,⽐如把本来要打开⾸页的,改成打开第⼆页数据,当然这只是举个例⼦
>
启动frida-server:/data/local/tmp/frida-server
补充下,有的⾼级点的app会检测本地是否启动了frida-server的程序,以及监听是否开启了27042端⼝,所以,如果有反调试的话,建议将frida-server改个⾃定义的名字,⽐如fsx86之类的,反正就是别让app检测到,然后启动:
/data/local/tmp/fsx86 -l 0.0.0.0:6666 (6666就是⾃定义端⼝)
这⾥要⽤绝对路径来启动,我也不知道为啥,启动,如下,warning是个警告,⽆所谓,说明启动成功了,只要没报错就⾏了
>
映射端⼝
在pc端电脑,装adb的机器上使⽤如下命令映射端⼝
adb forward tcp:27042 tcp:27042adb forward tcp:27043 tcp:27043
>
找到需要hook的app包名
这个包名不是app的名字,是安装之后存在⽬录⾥的⽂件夹名,⼀般是之类的,但是有少部分奇葩的报名并不是com开头查看当前所有的包名:frida-ps -U
注意要安卓机⾥先启动了firda-server,然后adb连上了安卓机,才可以调⽤frida命令, 如果不启动的话,运⾏frida这样,Failed,失败的意思
以上查看app包,显⽰出来太多了,你根本不知道哪个才是我们需要的包名,可以使⽤下⾯的命令查看adb shell pm list packages:打印设备上的所有软件包adb shell pm list packages -f:输出包和包相关联的⽂件adb shell pm list packages -d:只输出禁⽤的包由于本机禁⽤没有,输出为空adb shell pm list packages -e:只输出启⽤的包adb shell pm list packages -s:只输出系统的包adb shell pm list packages -3:只输出第三⽅的包adb shell pm list packages -i:只输出包和安装信息(安装来源)adb shell pm list packages -u:只输出包和未安装包信息(安装来源)adb shell pm list packages --user
>
hook操作frida -U -f (app包名) -l (js⽬录) --no-pause
注意了,这段js是放在安装了frida和adb的电脑上,不是放在安卓机上
运⾏完这条命令,安卓机会⾃动打开⽬标app,
app打开界⾯我就不展⽰了
如果打开的就是我们预期的那个app,那就是对的,如果打开错了,请重新获取app包名,打开之后就可以⽤抓包⼯具进⾏抓包了,ssl的⼀样的可以抓:
上⾯看到的https的还是会隧道,但是紧接着就有数据出现,说明还是抓到了数据包了
ok,绕过ssl pinning成功
其实如果你觉得需要做些改动的话,可以写个python脚本来调⽤,js代码就作为⽂件内容读取就⾏了,然后进⾏hook操作
最后得出的结论就是,我朋友他们的产品,其实反爬做得挺好,上⾯的截图也可以看到,其实还是有些数据拿不到的
补充:如果你⽤的模拟器在安装了app之后打不开,说明app有检测是否是模拟器或者对安卓版本做了检测,版本太低直接不给使⽤,那么你就只能⽤真机操作了,adb连接真机操作区别不⼤,详细的⾃⾏百度
>
检测模拟器的办法:
1.检测模拟器上特有的⽂件2.检测qemu pipes驱动程序3.检测⼿机号是否是155552155开头的4.检测设备ID是否是15个05.检测IMSI ID是否是31026+10个06.检测运营商是否是“Android”7.代码⾥⽤getInstance()⽅法调⽤任意⼀个⽅法,返回true就是模拟器8.检测IMEI或者⼊⽹许可证
以上都是我以前搜集的数据,但是,根据现在的时代发展,可能模拟器也早就更新迭代了,把⼀些特征给抹除或者改的跟真机⼀样了,所以有些⽅法并不是有⽤了,这个就只有⾃⾏选择了
>
免root使⽤frida
其实不root也可以使⽤frida,这⾥我就不展开了,给⼀个⼤神写的链接,⾥⾯还有其他⽅法的hook,感兴趣⾃⼰看吧,
>
针对很安全性很强的app——逆向
>> JEB
JEB 是⼀款适⽤于 Android 应⽤程序和本机机器代码的反汇编器和反编译器软件。利⽤它我们可以直接将安卓的 apk 反编译得到 Smali 代码、jar ⽂件,获取到 Java 代码。有了Java 代码,我们就能分析其中的加密逻辑了。
、jd-gui
这两者通常会配合使⽤来进⾏反编译,同样也可以实现 apk ⽂件的反编译,但其⽤起来个⼈感觉不如 JEB、JADX ⽅便。
>> 脱壳
⼀些 apk 可能进⾏了加固处理,所以在反编译之前需要进⾏脱壳处理。⼀般来说可以先借助于⼀些查壳⼯具查壳,如果有壳的话可以借助于 Dumpdex、FRIDA-DEXDump 等⼯具进⾏脱壳。
>> 反汇编
以上的⼀些逆向操作需要较深的功底和安全知识,在很多情况下,如果逆向成功了,⼀些加密算法还是能够被找出来的,找出来了加密逻辑之后,我们⽤程序模拟就⽅便了。
>> 模拟
逆向对于多数有保护 App 是有⼀定作⽤的,但有的时候 App 还增加了风控检测,⼀旦 App 检测到运⾏环境或访问频率等信息出现异常,那么 App 或服务器就可能产⽣防护,直接停⽌执⾏或者服务器返回假数据等都是有可能的。
对于这种情形,有时候我们就需要回归本源,真实模拟⼀些 App 的⼿⼯操作了。
最常规的 adb 命令可以实现⼀些⼿机⾃动化操作,但功能有限。
>> 触动精灵、按键精灵
有很多商家提供了⼿机 App 的⼀些⾃动化脚本和驱动,如触动精灵、按键精灵等,利⽤它们的⼀些服务我们可以⾃动化地完成⼀些 App 的操作。
类似 Selenium,Appium 是⼿机上的⼀款移动端的⾃动化测试⼯具,也能做到可见即可爬的操作。
同样是⼀款移动端的⾃动化测试⼯具,是⽹易公司开发的,相⽐ Appium 来说使⽤更⽅便。
mitmdump 其实是⼀款抓包软件,与 mitmproxy 是⼀套⼯具。这款软件配合⾃动化的⼀些操作就可以⽤ Python 实现实时抓包处理了。
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1688094277a80092.html
评论列表(0条)