写在前边
在笔者平常测试的过程中,测试的App或小程序经常会遇到无法抓包的情况。测试时有时还能沟通请开发帮忙关掉SSL强校验,但也会遇到有不配合或者无法不能关闭的情况,令人十分头疼。因此本文收集整理了一些方法,希望可以对大家的工作有一定帮助。
Tips:如果在同一个系统存在Android和iOS两个客户端,若后端逻辑一样,在Android无法抓包的时候,可以试一下iOS的客户端,很有可能可以抓到数据包。
01 安装系统级证书
环境准备
1、root手机(具体root方法可根据自己的手机自行查找方法,此处不再赘述)。2、软件:magisk(此处需注意不能是最新版本,最新版本不支持root隐藏,且不能安装插件,会引起root检测无法打开app,笔者使用的版本是22001)、Root Exploer。1.导出burpsuite证书,以DER格式导出证书。
2.转换证书格式,将der格式转换为pem格式:
openssl x509 -inform DER -in cacert.der -out cacert.pem*左右滑动查看更多
3.Android的受信任 CA 以特殊格式存储在 /system/etc/security/cacerts,需要将pem格式的证书保存为hash命名方式,以0结尾。
#查看 openssl版本openssl version#如果是1.0以上的版本openssl x509 -inform PEM -subject_hash_old -in cacert.pem |head -1 >9a5ba575 mv cacert.pem 9a5ba575.0#如果是1.0以下的版本openssl x509 -inform PEM -subject_hash -in cacert.pem |head -1 >9a5ba575 mv cacert.pem 9a5ba575.0*左右滑动查看更多
4.将证书复制到设备,并修改权限。
可以用 Root Exploer 将 9a5ba575.0 复制到 /system/etc/security/cacerts/ 文件夹里,事先要先挂载为可读写,点击红色框,变为挂载为只读即可正常复制,负责完成后长按文件可以修改文件权限,随后重启即可。
也可以使用命令操作:
adb remount adb push 9a5ba575.0 /sdcard/ db shellsumount -o rw,remount /systemmv /sdcard/9a5ba575.0 /system/etc/security/cacerts/chmod 644 /system/etc/security/cacerts/9a5ba575.0reboot*左右滑动查看更多
5.重启设备,WIFI设置代理即可访问。
通过设置以上步骤之后基本上就可以抓取大部分数据包了。
02 客户端代理
此方法是解决一些app不走设置的代理。在Wireshark中可以看到app使用的http(s)请求,某些情况下在设置完代理VPN之后仍无法抓包,那就要结合第一种方法,安装系统级证书。
目录
1.Android 通过开启VPN代理,抓取包
使用软件:Droni。
尝试一下直接抓取某应用数据包,什么都没有。
此时就要用到 Droni,它会把请求流量全部代理到指定端口。
首先关掉刚刚设置好的代理。
1、打开 Droni ,进入设置选择当前的Wi-Fi,之后输入电脑burp的IP和端口。
2、在规则里面选择要代理的程序。
现在就开启代理成功。
成功抓取操作的请求数据。
2、IOS 开启代理操作步骤
可以使用 Shadowrocket 进行全局代理。
03 绕过 SSL Pinning
SSL Pinning 是一种防止中间人攻击的技术,即服务端只信任app端的证书,其他代理证书服务端都不信任,导致app客户端无法进行数据交互。1、xposed + JustTrustMe
(Riru-LSPosed+SSLUpinning)
这种方法手机需要root,安装 Xposed 框架并在框架安装 JustTrustMe ,它几乎hook了所有用于系统证书校验的函数,通过这种方法绕过证书验证。
以笔者自身手机(Android 10,root 方式:magisk)为例。
在面具中安装 Riru 模块 和 Riru-LSPosed(较新版本Android ,xposed已经不支持了,这是替代品)。安装完成这两个模块后重启,重启会提示在桌面添加快捷方式,记得点同意。
在仓库中安装SSLUnpinning。然后在模块设置中选择要启用该模块的应用(也可以单独安装 JustTrustMe.apk 然后在框架里激活)。
之后就可以愉快进行抓包了。
hook的验证函数APIJava Secure Socket Extension (JSSE)- javax.net.ssl.*APACHE- org.apache.http.conn.ssl.*OKHTTP- okhttp3.*Tis:但是如果客户端存在任意软件检测的话,xposed是不容易隐藏的,造成无法打开app。虽然有个插件说可以隐藏应用程序,但是效果一般,不过也可以试试。
2、objection :android sslpinning disable
objection是基于Frida的一个hook工具,功能十分强大,这里只介绍怎么hook绕过 sslpinning 。支持 pip 直接安装,并且会安装 frida。
pip3 install objection安装好后,需要在手机端安装 frida 的server端,需要和刚安装的frida版本匹配。
~% frida --version#查看安装的Frida版本~% adb push frida-server /data/local/tmp/# 将服务端部署到手机上~% adb shellroot@android:/su root@android:/chmod 700 frida-serverroot@android://data/local/tmp/frida-server# 启动 服务端~% frida-ps -U #查看服务的是否启动成功 PIDName----- --------------------------------------------------- 15897信息 7524创建快捷方式 10445商店 9584图库 10296 天气 15898手机搬家 4766 输入法 10440浏览器13466游戏中心 6104 游戏空间*左右滑动查看更多
然后就可以用 objection 框架了。
xxx@xxx ~ % objection -g com.frida.lxh.fridademo explore Using USB device `ONEPLUS A5000`Agent injected and responds ok! _ _ _ _ ___| |_|_|___ ___| |_|_|___ ___| . | . | | -_|_|_| | . | ||___|___| |___|___|_| |_|___|_|_||___|(object)inject(ion) v1.11.0 Runtime Mobile Explorationby: @leonjza from @sensepost[tab] for command suggestionscom.frida.lxh.fridademo on (OnePlus: 10) [usb] # android sslpinning disable#就可以hook sslpining 函数了。之后就正常操作app,不要断开usb连接。(agent) Custom TrustManager ready, overriding SSLContext.init()(agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.verifyChain()(agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.checkTrustedRecursive()(agent) Registering job . Type: android-sslpinning-disable*左右滑动查看更多
3、Frida JavaScript
导出 burp的证书 ,并把它上传到手机目录里。
adb push cacert.der /data/local/tmp/cert-der.crt*左右滑动查看更多
保存下面的js,frida-android-repinning.js。
/* Android SSL Re-pinning frida script v0.2 -pier$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt$ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pausehttps://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/UPDATE : Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !*/setTimeout(function(){ Java.perform(function (){ console.log(""); console.log("[.] Cert Pinning Bypass/Re-Pinning");var CertificateFactory = Java.use("java.security.cert.CertificateFactory"); var FileInputStream = Java.use("java.io.FileInputStream"); var BufferedInputStream = Java.use("java.io.BufferedInputStream"); var X509Certificate = Java.use("java.security.cert.X509Certificate"); var KeyStore = Java.use("java.security.KeyStore"); var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory"); var SSLContext = Java.use("javax.net.ssl.SSLContext");// Load CAs from an InputStream console.log("[+] Loading our CA...") var cf = CertificateFactory.getInstance("X.509"); try { var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt"); } catch(err) {console.log("[o] " + err); } var bufferedInputStream = BufferedInputStream.$new(fileInputStream); var ca = cf.generateCertificate(bufferedInputStream); bufferedInputStream.close(); var certInfo = Java.cast(ca, X509Certificate);console.log("[o] Our CA Info: " + certInfo.getSubjectDN());// Create a KeyStore containing our trusted CAs console.log("[+] Creating a KeyStore for our CA..."); var keyStoreType = KeyStore.getDefaultType(); var keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null);keyStore.setCertificateEntry("ca", ca); // Create a TrustManager that trusts the CAs in our KeyStore console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore..."); var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); var tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); console.log("[+] Our TrustManager is ready..."); console.log("[+] Hijacking SSLContext methods now...") console.log("[-] Waiting for the app to invoke SSLContext.init()...") SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) { console.log("[o] App invoked javax.net.ssl.SSLContext.init..."); SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);console.log("[+] SSLContext initialized with our custom TrustManager!"); }});},0);*左右滑动查看更多
运行app,并用frida-ps -U查看应用程序包名,也可以通过其他方式获取包名。
frida-ps -Ufrida -U -f <应用程序包名> -l frida-android-repinning.js --no-pause例如:frida -U -f com.zhifubao.android -lfrida-android-repinning.js --no-paus*左右滑动查看更多
04 修改app重新打包
修改应用的 XMl 文件,将证书设为信任。
<network-security-config><domain-config><domain includeSubdomains="true">请求域名</domain><trust-anchors><certificates src="@raw/证书"/></trust-anchors></domain-config></network-security-config>*左右滑动查看更多
在AndroidManifest中使用它:
<?xml version="1.0" encoding="utf-8"?><manifest><applicationandroid:networkSecurityConfig="@xml/network_security_config" ... ></application></manifest>*左右滑动查看更多
这种方法没有试过,对于市面上成熟的app来说,几乎都进行了加固处理,重新打包的难度较大,对人员的要求也比较高。
05 找到app的证书和密钥
app的证书可以通过解压app找到相关的证书文件,但是找到证书的密钥需要对app进行脱壳,逆向,从源代码中寻找证书密钥文件。
然后可以到burp或者其他代理工具中,导入p12格式的文件。期间涉及到证书格式的转换。具体操作可在网上搜索,在此不再赘述。
— 往期回顾 —
招聘 | 春暖花开的日子里,翘首期盼你的到来!
九维团队-青队(处置)| 简单宏病毒分析
网安图鉴 | 什么演练,竟能让龙虎市气象局中心网站变成恶意网站?
九维团队-绿队(改进)| 为什么建议企业做代码审计安全服务?
九维团队-红队(突破)| HackThebox-Ophiuchi靶场渗透
END关于安恒信息安全服务团队安恒信息安全服务团队由九维安全能力专家构成,其职责分别为:红队持续突破、橙队擅于赋能、黄队致力建设、绿队跟踪改进、青队快速处置、蓝队实时防御,紫队不断优化、暗队专注情报和研究、白队运营管理,以体系化的安全人才及技术为客户赋能。