Android逆向15-抓包
Android逆向15-抓包
来自吾爱破解-正己
https://www.52pojie.cn/thread-1701353-1-1.html
抓包基础知识
在计算机网络中,“包”通常指的是在网络上传输的数据单元,也被称为数据包。在互联网协议(IP)的语境下,数据包是由报头(Header)和载荷(Payload)组成,其中报头包含了源地址、目的地址、长度等信息,而载荷则是实际要传输的数据。
抓包具体指的是通过某些工具获取安卓App与服务器之间传输的网络数据,这些数据通常用于逆向分析、协议接口分析或App渗透测试,帮助安全工程师理解App与服务器之间的通信细节,如请求和响应的具体内容,从而进行安全评估或逆向工程。
- 帮助定位加密或混淆的代码中的关键部分
- 逆向接口(比如:一些第三方影视app的解析接口、分析是否为服务器校验)
- 篡改数据包实现免重打包破解&屏蔽广告
- 协议分析&爬虫需求
网络协议可以分层,每层都有特定的任务和责任,最著名的分层模型是OSI七层模型和TCP/IP四层模型。常见的网络协议包括:
- TCP/IP(Transmission Control Protocol/Internet Protocol):这是互联网的基础协议,包括了IP协议(用于寻址和路由数据包)、TCP协议(用于建立可靠的数据流)和UDP协议(用于不需要确认的快速数据传输)。
- HTTP(Hypertext Transfer Protocol):用于从Web服务器向浏览器传输超文本文档(如HTML文件)。
- FTP(File Transfer Protocol):用于在互联网上传输文件。
- SMTP(Simple Mail Transfer Protocol):用于电子邮件的传输。
- DHCP(Dynamic Host Configuration Protocol):自动分配IP地址和其他网络配置参数给网络上的设备。
- DNS(Domain Name System):将域名转换为IP地址。
URL 的规则定义如下:
https://www.52pojie.cn/forum.php
https 表示资源需要通过 HTTPS 这个协议才能够获取,换句话说,客户端需要通过 HTTPS这个协议请求这个资源。
www.52pojie.cn 表示服务器地址,在互联网中每个服务器都有一个 IP 地址,但对于用户来说 IP 地址很难记住,用户一般只会记住服务器主机(比如www.52pojie.cn)名称。
在 HTTPS 中,客户端发送 HTTPS 请求的时候,必须通过 DNS 协议将服务器主机名转换为IP 地址,这样客户端才能找到服务器。
443 是 HTTPS 协议的默认端口(可以省略不输入),表示服务器通过 443 端口提供 HTTPS服务。
/forum.php 表示服务器在/根目录下有一个 forum.php 资源。
数字证书是网络安全领域的一个重要组成部分,主要用于身份验证和加密通信。它基于公钥基础设施(Public Key Infrastructure, PKI)的原理,由证书颁发机构(Certificate Authority, CA)签发,用于证明公钥的所有者身份。
工具名称 | 类型 | 下载链接 | 简介 |
---|---|---|---|
Charles | 代理抓包工具 | https://www.52pojie.cn/thread-1600964-1-1.html | Charles 是一个HTTP代理/HTTP监视器/反向代理,它允许开发人员查看所有的HTTP和SSL/HTTPS流量。 |
Fiddler | 代理抓包工具 | https://www.alipan.com/s/2W8r2ko7UWz | Fiddler 是一个Web调试代理,能够记录和检查从任何浏览器和客户端到服务器的所有HTTP流量。 |
Burp Suite | 代理抓包工具(理论上应该叫渗透必备工具) | https://www.52pojie.cn/thread-1544866-1-1.html | Burp Suite 是用于攻击web 应用程序的集成平台,包含了许多工具。Burp Suite为这些工具设计了许多接口,以加快攻击应用程序的过程。所有工具都共享一个请求,并能处理对应的HTTP 消息、持久性、认证、代理、日志、警报。 |
Reqable | 代理抓包工具 | https://reqable.com/zh-CN/download | Reqable = Fiddler + Charles + Postman Reqable拥有极简的设计、丰富的功能、高效的性能和桌面手机双端平台。 |
ProxyPin | VPN抓包工具 | https://github.com/wanghongenpin/network_proxy_flutter/releases/tag/V1.1.0 | 开源免费抓包工具,支持Windows、Mac、Android、IOS、Linux 全平台系统 可以使用它来拦截、检查和重写HTTP(S)流量,ProxyPin基于Flutter开发,UI美观易用。 |
WireShark | 网卡抓包工具 | https://www.wireshark.org/download.html | Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程各种问题定位。 |
r0Capture | Hook抓包工具 | https://github.com/r0ysue/r0capture | 安卓应用层抓包通杀脚本 |
tcpdump | 内核抓包工具 | https://github.com/the-tcpdump-group/tcpdump | cpdump 是一个强大的命令行网络数据包分析工具,允许用户截获并分析网络上传输的数据包,支持多种协议,包括但不限于TCP、UDP、ICMP等。tcpdump基于libpcap库,该库提供了从网络接口直接访问原始数据包的能力。 |
eCapture(旁观者) | 内核抓包工具 | https://github.com/gojue/ecapture/releases | 基于eBPF技术实现TLS加密的明文捕获,无需CA证书。 |
证书安装
选择适合自己的方式安装证书
Reqable使用经典的中间人(MITM)技术分析HTTPS流量,当客户端与Reqable的代理服务器(下文简称中间人
)进行通信时,中间人需要重签远程服务器的SSL证书。为了保证客户端与中间人成功进行SSL握手通信,需要将中间人的根证书(下文简称CA根证书
)安装到客户端本地的证书管理中心。
- 状态:表示请求的状态,这里是”Completed”,意味着请求已经完成。
- 方法:HTTP 请求的方法(也称为动词),这里为 “GET”,说明这是一个获取资源的请求。
- 协议:使用的 HTTP 协议版本,此处为 “HTTP/1.1”。(Reqable支持HTTP1、HTTP2和HTTP3(QUIC)协议)
- Code:HTTP 状态码,200 表示服务器成功处理了请求。
- 服务器地址:请求的目标服务器的 IP 地址和端口号,这里是 “180.76.198.77:443”。
- Keep Alive:是否保持连接 alive,值为 “true” 意味着会保持连接。
- Content Type:返回内容的数据类型,这里没有指定具体的类型。
- 代理协议:如果使用了代理,则显示代理协议,此例中为 “https”。
1 | HTTP方法 |
方法 | 描述 |
---|---|
GET | 请求指定的页面信息并返回实体主体 |
HEAD | 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件),数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或对已有资源的修改 |
PUT | 从客户端向服务器传送的数据取代指定文档的内容 |
DELETE | 请求服务器删除指定的页面 |
HTTP常见状态码
名 称 | 释 义 |
---|---|
200 OK | 服务器成功处理了请求。 |
301 Moved Permanently | 请求的URL已被永久移动。Response应包含Location URL指向新位置。 |
302 Moved Temporarily | 请求的URL被暂时移动。Response应包含Location URL指向临时位置。 |
304 Not Modified | 客户端缓存的资源是最新的,无需重新发送,客户端应使用缓存。 |
404 Not Found | 请求的资源未在服务器上找到。 |
401 Unauthorized | 请求要求用户的身份认证。 |
500 Internal Server Error | 服务器遇到了意外的情况,无法完成请求。 |
- 第一行是请求行,包含了请求方法(GET)、请求路径以及HTTP协议版本(HTTP/1.1)。在这个例子中,请求方法是GET,表明这是一个获取操作;请求路径是
/ZJ2595/wuaijie/raw/master/movie/list1.json
,这意味着请求的目标资源位于gitee.com网站的某个特定目录下,具体来说是在ZJ2595/wuaijie
仓库下的master分支中的movie/list1.json
文件;HTTP/1.1表示使用的HTTP协议版本。 - 第二行
Host: gitee.com
是一个HTTP头字段,指明了请求要访问的具体主机名,即gitee.com。 - 第三行
Connection: Keep-Alive
表示客户端希望保持持久连接。这意味着一旦TCP连接建立之后,可以重复使用该连接来发送多个HTTP请求,而不需要为每个请求单独建立一个新的连接。 - 第四行
Accept-Encoding: gzip
告诉服务器客户端支持的压缩编码类型。在这个例子中,客户端表示它可以接受gzip压缩编码的内容。 - 最后一行
User-Agent: okhttp/3.12.0
提供了关于发起请求的应用程序的信息。User-Agent头字段通常用于标识发出请求的浏览器或应用程序的类型、版本和其他相关信息。在这里,User-Agent是okhttp/3.12.0,这表示请求是由OkHttp库的一个版本3.12.0发出的。
请求头 (Request Headers)
名称 | 描述 |
---|---|
Accept | 指定客户端能接收的媒体类型。 |
Accept-Charset | 指定客户端能接收的字符集。 |
Accept-Encoding | 指定客户端能解码的编码方式,如gzip或deflate。 |
Accept-Language | 指定客户端首选的语言。 |
Authorization | 包含用于访问资源的认证信息。 |
Cache-Control | 控制缓存行为,如no-cache或max-age。 |
Connection | 控制HTTP连接是否保持活动状态,如keep-alive或close。 |
Content-Length | 指明请求体的长度。 |
Content-Type | 指明请求体的数据类型,如application/json。 |
Cookie | 包含客户端的cookie信息。 |
Date | 请求生成的时间。 |
Expect | 指定客户端期望服务器执行的操作。 |
From | 发送请求的用户邮箱地址。 |
Host | 请求的目标服务器的域名和端口号。 |
If-Modified-Since | 用于条件性GET,如果资源自指定日期后未被修改则返回304。 |
If-None-Match | 用于条件性GET,如果资源的ETag与提供的不匹配则返回资源。 |
Origin | 指明请求来源的源站地址,常用于跨域资源共享(CORS)。 |
Pragma | 包含与特定代理有关的指令。 |
Referer | 指明请求前一个页面的URL,可用于跟踪引用页面。 |
TE | 表示客户端能处理的传输编码方式。 |
Trailer | 指明报文主体之后的尾部字段。 |
Transfer-Encoding | 指明报文主体的传输编码方式,如chunked。 |
Upgrade | 指示客户端希望升级到另一种协议。 |
User-Agent | 包含客户端软件的名称和版本信息。 |
Via | 记录请求经过的中间节点,用于追踪和诊断。 |
Warning | 包含非致命问题的警告信息。 |
响应头 (Response Headers)
名称 | 描述 |
---|---|
Age | 响应对象在代理或缓存中的存储时间。 |
Cache-Control | 控制缓存行为,如public、private、no-store、no-cache等。 |
Connection | 指示连接是否保持打开,如keep-alive或close。 |
Content-Encoding | 指明响应体的编码方式,如gzip或deflate。 |
Content-Length | 响应体的长度。 |
Content-Type | 响应体的数据类型,如text/html。 |
Date | 服务器生成响应的时间。 |
ETag | 响应资源的实体标签,用于判断资源是否已被修改。 |
Expires | 响应过期时间,之后缓存不应再使用。 |
Last-Modified | 资源最后修改的时间。 |
Location | 用于重定向,包含资源的新位置。 |
Pragma | 与特定代理有关的指令。 |
Proxy-Authenticate | 当代理服务器需要认证时使用。 |
Retry-After | 在重试之前等待的时间。 |
Server | 服务器软件的名称和版本。 |
Set-Cookie | 用于设置或更新客户端的cookie。 |
Trailer | 指明响应尾部字段。 |
Transfer-Encoding | 响应体的传输编码方式,如chunked。 |
Upgrade | 用于协议升级。 |
Vary | 指明哪些请求头会影响响应的内容,用于缓存控制。 |
WWW-Authenticate | 当服务器需要认证时使用。 |
X-Frame-Options | 控制页面是否可以在iframe中显示。 |
抓包检测
代理检测
定义
代理检测是用于检测设备是否设置了网络代理。这种检测的目的是识别出设备是否尝试通过代理服务器(如抓包工具)来转发网络流量,从而可能截获和分析App的网络通信。
原理
App会检查系统设置或网络配置,以确定是否有代理服务器被设置为转发流量。例如,它可能会检查系统属性或调用特定的网络信息API来获取当前的网络代理状态。
1 | return System.getProperty("http.proxyHost") == null && System.getProperty("http.proxyPort") == null |
强制不走代理
1 | connection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); |
Charles安装与配置
证书安装的问题:WIN 11的 charles 安装SSL证书提示 此文件作为下列运行是无效的:安全证书_测试-CSDN问答
安装教程:https://blog.csdn.net/qq_45005145/article/details/141132846
key:
1 | Registered Name: 52pojie |
anti脚本:
1 | function anti_proxy() { |
透明代理
透明代理(Transparent Proxy)是一种特殊的代理服务类型,它可以在客户端(如浏览器或应用程序)不知道的情况下拦截、转发和处理网络请求。与传统的代理服务不同,透明代理不需要客户端进行任何配置就能工作。
VPN检测
定义
VPN检测是指应用程序或系统检查用户是否正在使用虚拟专用网络(Virtual Private Network, VPN)的一种技术。当用户使用VPN时,他们的网络流量会被加密并通过一个远程服务器路由,这可以隐藏用户的实际IP地址和位置信息,同时保护数据的安全性和隐私。
原理
当客户端运行VPN虚拟隧道协议时,会在当前节点创建基于eth
之上的tun0
接口或ppp0
接口。这些接口是用于建立虚拟网络连接的特殊网络接口。
根据OSI七层模型,二者分别支持的协议:
VPN | OpvenVPN、IPsec、IKEv2、PPTP、L2TP、WireGuard等 |
---|---|
代理 | HTTP、HTTPS、SOCKS、FTP、RTSP等 |
VPN 协议大多是作用在 OSI 的第二层和第三层之间,由此可见VPN能抓到代理方式的所有的包
1 | public final boolean Check_Vpn1() { |
anti
1 | function hook_vpn() { |
SSL Pinning
SSL Pinning 也称为证书锁定,是Google官方推荐的检验方式,意思是将服务器提供的SSL/TLS证书内置到移动客户端,当客户端发起请求的时候,通过对比内置的证书与服务器的证书是否一致,来确认这个连接的合法性。 PS:这里还要提到一个概念:
单向校验,本质上二者没区别,
SSL Pinning可以理解为加强版的
单向校验
1 | 1.客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。 |
SSL Pinning
主流的三套方案:公钥校验
、证书校验
、Host校验
因为是客户端做的校验,所以可以在本地进行hook对抗,参考以下的两个项目:
指纹校验
在网站中我们可以看到网站的证书相关信息,其中就包含了指纹信息
常见安卓网络开发框架
框架名称 | 描述 | GitHub 地址 |
---|---|---|
Volley | 由Google开源的轻量级网络库,支持网络请求处理、小图片的异步加载和缓存等功能 | https://github.com/google/volley |
Android-async-http | 基于Apache HttpClient的一个异步网络请求处理库 | https://github.com/android-async-http/android-async-http |
xUtils | 类似于Afinal,但被认为是Afinal的一个升级版,提供了HTTP请求的支持 | https://github.com/wyouflf/xUtils3 |
OkHttp | 一个高性能的网络框架,已经被Google官方认可,在Android 6.0中底层源码已经使用了OkHttp来替代HttpURLConnection | https://github.com/square/okhttp |
Retrofit | 提供了一种类型安全的HTTP客户端接口,简化了HTTP请求的编写,通常与OkHttp配合使用 | https://github.com/square/retrofit |
OkHttp和Retrofit是非常流行的组合,被广泛应用于现代Android应用开发中
原理(以okhttp框架为例):
在CertificatePinner类里有一个check方法
1 | /** |
实现方案:
1 | //指纹检测 |
安装openssl,OpenSSL Windows 版本
cmd窗口输入以下命令获取
1 | openssl s_client -connect www.52pojie.cn:443 -servername www.52pojie.cn | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 |
anti脚本
1 | function anti_ssl_key() { |
证书校验
通过trustManager
类实现的checkServerTrusted接口,核心在于验证服务器证书的公钥。具体步骤包括:获取服务器返回的证书,将其公钥编码为 Base64 字符串;同时从本地资源加载预存的可信客户端证书,并将其公钥也编码为 Base64 字符串。然后,比较这两个公钥是否匹配,以此确认服务器的身份是否合法。最后,使用自定义的 SSLSocketFactory
发起 HTTPS 请求,确保通信过程中只信任预定义的服务器证书,从而有效抵御中间人攻击。
1 | // 定义一个函数用于检查SSL证书 |
cmd窗口输入以下命令获取证书信息
1 | openssl s_client -connect 52pojie.cn:443 -servername 52pojie.cn | openssl x509 -out wuai.pem |
1 | 证书信知识补充: |
名词 | 含义 | |
---|---|---|
X.509 | 一种通用的证书格式,包含证书持有人的公钥、加密算法等信息 | |
PKCS1~PKCS12 | 公钥加密(非对称加密)的一系列标准(Public Key Cryptography Standards),.p12 是包含证书和密钥的封装格式 | |
*.der | 证书的二进制存储格式(不常用) | |
*.pem | 证书或密钥的 Base64 文本存储格式,可以单独存放证书或密钥,也可以同时存放证书和密钥 | |
*.key | 单独存放的 pem 格式的私钥文件,一般保存为 *.key | |
.cer / .crt | 两者指的都是证书,Linux 下叫 crt,Windows 下叫 cer;存储格式可以是 pem,也可以是 der | |
*.csr | 证书签名请求(Certificate Signing Request),包含证书持有人的信息,如:国家、邮件、域名等 | |
*.pfx | 微软 IIS 的实现,包含证书和私钥 |
有的证书内容是只包含公钥(服务器的公钥),如.crt、.cer、.pem
有的证书既包含公钥又包含私钥(服务器的私钥),如.pfx、.p12
另外有些app的证书不走寻常路,不是上面所罗列到的格式,它有可能伪装成png等其他格式
anti脚本
思路:实例化一个trustManager类,然后里面什么都不写,当上面两处调用到这个类时hook这两个地方,把自己定义的空trustManager类放进去
1 | function anti_ssl_cert() { |
双向认证
双向验证,顾名思义就是客户端验证服务器端证书的正确性,服务器端也验证客户端的证书正确性
1 | 1.客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。 |
实现方案:
- 首先借助openssl生成服务端证书
1 | # 生成CA私钥 |
- 生成服务端证书
1 | openssl genrsa -out server.key 2048 |
这个指令生成一个2048位的RSA私钥,并将其保存到名为server.key
的文件中
这个指令基于第一步生成的私钥创建一个新的证书签名请求(CSR)。CSR包含了公钥和一些身份信息,这些信息在证书颁发过程中用于识别证书持有者。-out server.csr
指定了CSR的输出文件名。
执行这个指令时,系统会提示你输入一些身份信息,如国家代码、组织名等,这些信息将被包含在CSR中。(我们这边测试直接全部按回车键默认即可)
字段名称 | 描述 | 默认值/示例值 | 是否必填 |
---|---|---|---|
Country Name (2 letter code) | 国家代码,两位字母代码。 | AU | 否 |
State or Province Name | 州或省份的全名。 | 否 | |
Locality Name (eg, city) | 城市或地区名称。 | 否 | |
Organization Name | 组织名称,通常是公司或机构的名称。 | 否 | |
Organizational Unit Name (eg, section) | 组织单位名称,可以是部门或团队的名称。 | 否 | |
Common Name (CN) | 完全限定的域名(FQDN)或个人名称,用于标识证书持有者。 | 是 | |
Email Address | 与证书持有者关联的电子邮件地址。 | 否 | |
Challenge Password | 挑战密码,用于CSR的额外安全措施。 | 否 | |
Optional Company Name | 可选的公司名称字段。 | 否 |
-config server_cert.conf
创建一个OpenSSL配置文件(如 server_cert.conf
)并指定IP地址,具体的ip地址可以由ipconfig获取
1 | 这个指令基于第一步生成的私钥创建一个新的证书签名请求(CSR)。CSR包含了公钥和一些身份信息,这些信息在证书颁发过程中用于识别证书持有者。-out server.csr指定了CSR的输出文件名。 |
1 | openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile server_cert.conf -extensions v3_req |
使用CA证书签发服务器证书。
生成cer证书供服务端验证。
客户端证书:
1 | openssl genrsa -out client.key 2048 |
生成客户端带密码的p12证书(这步很重要,双向认证的话,浏览器访问时候要导入该证书才行;可能某些Android系统版本请求的时候需要把它转成bks来请求双向认证):
1 | openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -certfile ca.crt |
到这一步的时候,设置密码和验证密码光标不会显示,直接输入即可
环境配置
PS:因为双向认证是本地搭建,所以需要完成几个前置条件:
- 确保电脑和手机处于同一wifi连接下
- 重打包替换生成的server.cer(路径在res/raw),替换ssl_verify方法里的ip地址以及res/xml/network_config.xml的ip地址(通过ipconfig获取实际的ipv4地址)
- 运行服务端代码,然后再请求看看是否能正常输出
服务端代码:
1 | from flask import Flask, jsonify |
dump内置证书:
1 | function hook_KeyStore_load() { |