快速掌握任意 Android 应用的抓包

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

抓包是流量分析的基础也是安全研究重要的一环。抓包软件有很多种如 Burpsuite、mitmproxy 以及 Fiddle抓包方式常见的有设置系统代理、AP 热点抓包、透明代理等。不同方式有不同优缺点也有不同的应用场景。相信很多安全研究者一定会遇到各种无法抓取流量的问题本次就来简单总结一下 Android 环境中常用的抓包技术包括一些应用常用的 SSLpinning、不走系统代理等对抗逆向技术。

这里不会重复搬运大部分博客已经总结过的抓包原理和经验主要是想总结一下如何抓取任意应用的流量包按照常规思路假设现在我们想抓取某个应用的流量。

设置系统代理

设置系统代理是最为常见的一种方法Android 提供了相应的设置功能将系统代理指向 Burpsuite 所在的 IP 地址即可使用 Burpsuite 抓取流量。抓包步骤如下

这种方式可以解决部分应用的抓包问题但是如今很多应用使用了 SSL Pinning即证书绑定应用只会信任自己本地绑定的证书并不会信任系统根证书也就是即使导入了 CA仍然可能无法抓包。

OWASP 安全验证标准中将对抗逆向称之为韧性要求属于额外的管控方法根据应用敏感性开发者选择需不需要添加。而 SSL Pinning 就属于对抗逆向的一种手段。

绕过 SSL Pinning

在设置系统代理抓包无果后需要继续尝试 SSL Pinning 绕过。绕过证书绑定并不难但是需要有系统 root 权限使用 Frida 对相应校验证书的函数进行 Hook。已有多个现成的 Frida 脚本 可以解决此问题以下是一个简单示例。

// $ frida --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f YOUR_BINARY
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);

当然笔者正常使用的方法是在 Linux 环境中直接使用 objection已经集成了绕过 SSL pinning 等多个有用的 Frida 脚本两行脚本搞定 SSL Pinning。

objection -g com.android.phone explore
Using USB device `Android Emulator 5554`
Agent injected and responds ok!

     _   _         _   _
 ___| |_|_|___ ___| |_|_|___ ___
| . | . | | -_|  _|  _| | . |   |
|___|___| |___|___|_| |_|___|_|_|
      |___|(object)inject(ion) v1.11.0

     Runtime Mobile Exploration
        by: @leonjza from @sensepost

[tab] for command suggestions
com.android.phone on (Android: 11) [usb] # android sslpinning disable

利用 iptables 设置透明代理

尽管绕过了 SSL pinning仍然有可能无法抓到 App 的流量这是因为应用开发者完全可以不使用系统或其他的 HTTP 库不理睬系统变量如 HTTP_PROXY也就是应用不会理会我们设置的系统代理。这个时候就可以使用终极方法了iptables + Burpsuite 透明代理步骤如下

iptables 是一个在应用层实现内核框架 Netfilter 的工具常见于防火墙配置而 Netfilter 是内核处理网络数据包的模块。

通过如下命令即可将内核 OUTPUT 数据转发到我们的目标设备上。

D:\> adb shell iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination 127.0.0.1:8080

此时再利用 adb 反向代理功能将 Android 手机某个网卡流量通过 adb 的方式转发到我们使用的 PC 上。

D:\> adb reverse tcp:8080 tcp:8080

设置 Burpsuite 透明代理即可抓包。

Burpsuite设置透明代理

当然也可以指定抓包特定应用加入如下 iptables 参数即可

-m owner --uid-owner 4000

参数简介

iptables [-t table] {-A|-C|-D} chain rule-specification
-t nat设置iptables表为网络地址地址转发
-A Append附加后续规则到相应的表上
chain, PREROUTING/INPUT/OUTPUT/POSTROUTING来源于内核中的Netfilter模块OUTPUT表示所有从本地发往远端的数据包
rule-specification, -j DNAT, 修改数据包的目标地址

adb reverseadb forward 的区别就是前者是反向代理后者是正向代理前者是将所有手机流量导入到 PC后者是将所有 PC 流量导入到手机。

关于 iptables 的原理以及更多配置透明代理入门iptables在Android抓包中的妙用 等文章已经给了很好的解释不再赘述。

总结

撰写本文最大目的在于快速掌握任意 Android 应用的抓包因为现实场景中往往会遇到常规方法无法抓包的问题。而只需要通过 iptables 即可解决绝大多数问题。除了设置系统代理、iptables路由转发还可以通过 tcpdump + keylog 以及 SSL read/write 的方式但是这两种都需要 Hook因此对于大多数安全研究者来说掌握 iptables 设置透明代理的方式就足够了。

参考文献

  1. 终端应用安全之网络流量分析
  2. 快应用调试器研究1前置知识
  3. 透明代理入门
  4. iptables在Android抓包中的妙用
  5. android手机安装burp证书
  6. 从原理到实战全面总结 Android HTTPS 抓包
  7. Frida CodeShare
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: android