抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

抓包技术分类:

业务层:Hook 框架,SDK 分析

应用层:中间人代理抓包,

传输层:socket 通信抓包

网络层:网卡抓包

我们接下来主要考虑应用层

HTTPS 原理

HTTPS(HyperText Transfer Protocol Secure)是 HTTP 协议的安全版本,通过加密数据的传输来保护用户的隐私和数据完整性。HTTPS 通信的安全性主要依赖于 SSL/TLS(Secure Sockets Layer/Transport Layer Security)协议。

  • CA 证书校验: CA 证书校验发生在 TLS 的前两次握手,客户端和服务端通过 Client Hello、Server Hello 等报文获得服务端 CA 证书,客户端验证 CA 证书合法性,从而确认 CA 证书中的公钥合法性(大多数场景不会做双向认证,即服务端不会认证客户端合法性,这里先不考虑);
  • 密钥协商: 在确认服务器的身份后,客户端和服务器开始 SSL/TLS 握手,协商出一个对称加密密钥(称为会话密钥)。握手的过程使用非对称加密算法(如 RSA、ECDHE 等)来确保密钥传输的安全性。
  • 数据传输: 客户端和服务器使用生成的对称会话密钥对后续通信的数据进行加密。

CA 的主要作用

1)颁发证书,颁发证书其实就是使用 CA 的私钥对证书请求 签名文件 进行签名;

2)颁发的证书浏览器要信任,浏览器只需要用 CA 的公钥进行验签成功就表示这个证书是合法可信的,这就需要浏览器内置 CA 的公钥,也就是内置 CA 的证书。一般来说,操作系统都会内置权威 CA 的证书,有的浏览器会使用操作系统内置的 CA 证书列表,有的浏览器则自己维护的 CA 证书列表,比如 Firefox。

抓包原理-中间人攻击

原理:

截获通信:攻击者拦截用户到服务器的流量,以便对 HTTPS 通信进行操控。

伪造 SSL 证书:为了绕过客户端对服务器的身份认证,攻击者会生成伪造的 SSL 证书,将其伪装成目标服务器的合法证书。

中断 TLS 握手:攻击者在客户端和服务器之间劫持 TLS 握手,通过伪造的证书来欺骗客户端,同时与服务器建立独立的 TLS 连接。

解密和篡改数据:攻击者能够解密通信内容并篡改数据后再发送给目标。

中间人攻击(Man-in-the-MiddleAttack,MITM)的方案: 将客户端的网络流量代理到 MITM 主机,再通过一系列的面板或工具将网络请求结构化地呈现出来。

第一个问题 —— 加密:

  • 加密: 由于 HTTPS 通信中对称密钥 Master Secret 只有通信双方才持有,MITM 无法解密密文,导致在抓包工具上也只能看到一堆无意义的乱码。

    代理抓包工具通过伪造一个与真实服务器同名的证书,攻击者欺骗客户端,使其认为连接的服务器可信。这样子就可以发送一个自己的公钥,客户端拿抓包工具的公钥去加密对称密钥,而抓包工具可以用自己的私钥去解密。相当于把浏览器的对称密钥骗了出来。而如果不进行证书替换,抓包工具是没有私钥的,这样子就无法进行解密。

要解决这个问题,只能想办法让 MITM 也获得这个对称密钥。此时,MITM 不仅要做流量拦截,还需要伪装成真实的客户端和服务端,与真实的通信双方分别建立独立的连接。我们来看下在中间人攻击下,HTTPS 的三阶段:

连接 1:客户端与中间人的 HTTPS 连接:

  • CA 证书校验: 客户端与 MITM 握手,MITM 返回一个 “调包” 的 CA 证书(为了让客户端验证 CA 证书通过,需要提前在系统上安装 MITM 的证书);
  • 密钥协商: 客户端和 MITM 基于 “调包” 的公钥和私钥进行非对称加密通信,协商获得对称密钥;
  • 数据传输: 客户端和 MITM 基于协商的对称密钥进行对称加密通信,此时 MITM 就可以解密出明文。

连接 2:中间人与服务端的 HTTPS 连接:

  • CA 证书校验: MITM 与 服务端握手,服务端返回 CA 证书,由于服务端证书本来就是合法的,因此 MITM 可以拿到服务端公钥;
  • 密钥协商: MITM 和服务端分别基于公钥和私钥进行非对称加密通信,协商获得 Master Secret 对称加密私钥;
  • 数据传输: MITM 和服务端基于协商的对称密钥进行对称加密通信。

到这里,MITM 就成功与真实的客户端和服务端建立了独立的连接,发送的密文在 MITM 上就可以成功解密出来了。

抓包实践

工具

burpsuite 抓取手机 APP 的 http、https 数据包——教程_burpsuite 怎么抓取手机请求-CSDN 博客

charles 安卓手机抓包——配置——超详细_charles 安卓手机抓包-CSDN 博客

frida hook

优点:无视证书,基于 hook 直接得到参数,找调用栈

缺点:不如抓包软件全面

实用 FRIDA 进阶:内存漫游、hook anywhere、抓包-安全客 - 安全资讯平台 (anquanke.com)

R0capture

r0ysue/r0capture: 安卓应用层抓包通杀脚本

先安装依赖 pip install hexdump

命令:

  • Spawn 模式:
1
$ python3 r0capture.py -U -f com.coolapk.market -v
  • Attach 模式,抓包内容保存成 pcap 文件供后续分析:
1
$ python3 r0capture.py -U 酷安 -v -p iqiyi.pcap

建议使用 Attach 模式,从感兴趣的地方开始抓包,并且保存成 pcap 文件,供后续使用 Wireshark 进行分析。

客户端证书导出功能:默认开启;必须以 Spawm 模式运行;

ecapture:基于 epbf

ecapture/README_CN.md at master · gojue/ecapture

中间人抓包对抗

高版本安卓如何导入证书:

1 Magisk-Move Certifivates 模块

2 AOSP 编译

中间人抓不到包如何确认:

  • C 校验 S(单向时),没有将抓包工具证书放在手机种

    400Badrequest

  • S 校验 C(双向时)没有向抓包工具配置 APP 证书

    NorequiredSSLcertificatewassent

  • 3SSLPINNING

    告诉你证书没配置好,其实你已经配置好了

单向证书认证:客户端校验服务器证书–SSL Pinning

SSL Pinning 是在客户端侧通过“固化”服务器的公钥或证书,确保客户端只信任与预期一致的服务器。即使攻击者拥有合法的证书或其他 CA 签署的证书,也无法通过 SSL Pinning 机制的校验,从而增强安全性。

SSL Pinning 的实现方式

SSL Pinning 主要有以下几种实现方式:

  • 证书固定(Certificate Pinning):将服务器的证书直接存储在客户端应用中。连接时,客户端会将服务器返回的证书与存储的证书进行比对。
  • 公钥固定(Public Key Pinning):将服务器的公钥存储在客户端中,验证时仅比对公钥。这种方式即使证书更新,只要公钥不变,依然能通过校验。

SSL Pinning 的流程

SSL Pinning 的工作流程如下:

  1. 存储证书或公钥:在应用开发时,将服务器的证书或公钥指纹(hash 值)预先存储在客户端代码或配置文件中。
  2. 连接和比对:在客户端与服务器建立 SSL 连接时,客户端会获取服务器的证书并提取公钥或证书的指纹。
  3. 验证证书或公钥
    • 客户端将从服务器获取的证书/公钥指纹与预存的指纹进行比对。
    • 如果指纹匹配,说明服务器是合法的,连接成功;否则连接失败。

对抗

针对 sslpinning 这种,可以先用市面上已有的 sslunpinning 工具进行尝试,如果遇到都无法进行成功的情况,那就需要我们去手工进行 hook 了,大致有两种思路,一是对所有 HTTP 字符串相关类进行 Hook,二是考虑到 App 在验证证书时会打开证书文件判断是否是 App 自身所信任的,因此一定会使用 File 类的构造函数打开证书文件获得文件的句柄,所以我们在测试时可以 Hook 上所有 File 类的构造函数,即对 File.$init 函数进行 hook

双向证书认证:服务器校验客户端证书。

双向证书认证需要在客户端和服务器上分别配置证书。客户端和服务器的证书通常由同一个 CA 机构签发,保证双方互信。

APP 双向验证情况下,如何进行中间人抓包? 答:将客户端证书配置到抓包工具即可。

如何获取 APP 的客户端证书和密码? 答//通过 HOOK 证书相关类包//在服务器校验客户端的情形下,帮助 dump 客户端证书

代理检测

原理:

通过系统 API 获取代理状态

安卓系统通过 Proxy 类或 System 属性可以读取系统代理配置。这是最直接的方法,通过检测当前网络环境中的代理设置来判断是否配置了代理。

通过 System.getProperty 获取 host 和 port,可以知道是否进行了代理。对于 Android 9.0 及以上版本,可以通过 ConnectivityManagerLinkProperties 来获取 Wi-Fi 代理的配置情况。此方法可以判断是否存在 Wi-Fi 网络下的代理。

在检测到代理设置后,应用可以尝试绕过代理与服务器建立直连,通过特定的超时机制识别代理的存在。如果超时或连接失败,则可能存在代理干扰。

绕过:

Hook 相关 API,使其返回“无代理”或“未检测到代理”的结果。

直接在系统底层使用 iptables 强制转发流量(ProxyDroid:全局模式)

证书绑定:

什么是证书绑定

  1. 在开发时就将服务端证书一块打包到客户端里这样在 HTTPS 建立时与服务端返回的证书比对一致性,进而识别出中间人攻击后直接在客户端侧中止连接

绕过:

定位客户端证书绑定的代码位置,并通过 Hook 修改其执行逻辑。编写相应的 Hook 代码,或者使用自动化框架进行操作。

逆向 APP 取出证书,导入到抓包程序中:证书通常在 /assets 里,jadx 反编译后搜索 .p12 .pem .cer ssl 等关键词

JustTruetMe:手机上部署 xposed 框架,然后安装此模块,对目标 APP 生效即可

如何定位/绕过已知网络通信框架的证书绑定代码?

1 思路:
去熟悉各种框架的证书绑定相关 API 然后编写 HOOK 代码
2 各种框架进行证书绑定操作的源代码:
https://appmattus.medium.com/android-security-ssl-pinning-1db8acb6621e
3HOOK 工程:
https://github.com/WooyunDota/DroidSSLUnpinning
objection 下运行 androidsslpinningdisable

如何定位/绕过未知框架的证书绑定代码?:
客户端证书不管隐藏的再好,也要从磁盘读取到内存中,可通过 HOOKJava 的 File 类构造函数,检测客户端证书的读取,从此处线索切入,进一步分析调用栈,定位证书绑定代码.

VPN 抓包对抗:

工具: postern 下载地址 VProxid 下载地址

VPN 抓包和中间人抓包的区别:VPN 抓包本质是在网络层/路由层抓包

检测与对抗

java.net.NetworkInterface.getName//判断网络接口名字包含 pppO 或 tuno

hook getName 方法,判断如果得到的 name 是 tun0 或者 ppp0,就返回 rmnet_data0。

android.net.ConnectivityManager.getNetworkCapabilities//获取当前网络 Transpoart 字样

getNetworkCapabilities 会返回 NetworkCapabilities 对象,其中包含 TRANSPORT_VPN 等表示 VPN 状态的标志位。通过 hook 这个方法,可以让其在应用检测时返回不包含 TRANSPORT_VPN 的值。

Hook 抓包对抗

如何通过 HOOK 抓到 HTTP 包:

原理:HTTP 直接走了 Socket, 没有加解密,直接是明文,将内容 dump 下来即可.

hook 点:

1
2
java.netSocketOutputStream.socketWriteO(java.io.FileDescriptor',‘[B','int',int)
java.netSocketlnputStream.socketReadO(java.io.FileDescriptor', '[B', 'int', 'int', 'int')

如何通过 HOOK 抓到 HTTPS 明文数据?(或其他应用层协议+SSL 框架)

原理:

[http 明文]—-> [SSL 库 API]—> [https 密文]
[SSL 库 API] 调用前这个时机,即加密前,HOOK 截取 http 明文
[https 密文]—-> [SSL 库 API]—-> [http 明文]
在 [SSL 库 API] 调用后这个时机,即解密后,HOOK 截取 http 明文

结论:hook ssl 库的某个关键 API

协议使用了系统中的 SSL 类库

hook 点源代码:

java:

1
2
3
4
5
6
// Java.androidVersion > 8
com.android.org.conscryptConscryptFileDescriptorSocket$SSLOutputStream.write([B',int',int)
com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read([B', int', int)
// Java.androidVersion <= 8
com.android.org.conscrypt.OpenSSLSocketlmpl$SSLOutputStream.write([B',int,'int)
.read([B’,int',“int)

native:

1
/system/lib/libssl.so库中的SSL_readO和SSL_write0

说明:
JAVA 中的 SSLOutputStream.writeO 和 SSLInputStream.read0
实际上就是对 libssl.so 库的 SSL_write(和 SSL_read(包装调用

协议使用了自我集成的 SSL 类库

哪些 APP 使用自我集成:

(1)chrome
Android L & M libchrome.so
Android N, O & P libmonochrome.so
(2)系统内置 webview
使用(pm path
com.google.android.webview)得到 webview 的路径
(3)浏览器 APP 的 webview
OPPO libheytapwebview.so
华为 libhwwebviewchromium.so
小米 libmiui_chromium.so
vivolibwebviewchromium_vivo.so
(4)基于 Chromium 的第三方浏览器内核
腾讯系的 APPlibmttwebview.sox5 内核
阿里小的 APPlibwebviewuc.soUC 的 U4 内核
各种小程序 libxwalkcore.so CrossWalk 内核
(5)微信(使用多内核的 APP)
有些 APP 会使用多个内核,以微信为例,同时使用了 X5 和 CrossWalk 内核:
x5com.tencent.mm: tools 进程
聊天页面点开的 webview、支付里的页面(长按下拉提示使用 x5 内核的都可以)
CrossWalk(长按下拉未提示 x5)
com.tencent.mm: toolsmp 进程 公众号文章、搜一搜
com.tencent.mm: appbrand 进程 小程序

如何定位它们的 SSL 关键 API(即 HOOK 点):

对于 native 库,写脚本定位 APP 自带 SSL 库的 SSL_read 和 SSL_write 的偏移量

参考来自 r0capture/pic/summary2.jpg at main · r0ysue/r0capture

Socket 通信抓包

Java 层 TCP:
1 hook 点 socketReado、socketWrite0
Java 层 Udp:
1 hook 点 sendtoBytes、readBytes
Java 层 SSL:
1 hook 点 NativeCrypto.SSL_write、NativeCrypto.SSL_read
Jni 层 Tcp:
1hook 点 recvfrom、sendto
Jni 层 Udp:
1 hook 点 recvfrom、sendto
Jni 层 SSL:
1 hook 点 read、write

评论