抓包详解

介绍

抓包通常是指通过一些手段获取App与服务器之间传输的明文网络数据信息.

抓包分为以下两种情形:

  1. Hook抓包:通过对发包函数的Hook来达到抓包的作用.
  2. 中间人抓包:将原来一段完整的客户端-服务器的通信方式割裂成两段客户端-服务器的通信.

中间人的抓包在OSI七层网络模型的结构中通常又会被分成以下两种情形:

  1. 应用层:Http(s)协议抓包.
  2. 会话层:Socket通信抓包.

Http抓包配置

首先要将计算机和测试手机连接在同一个局域网中并且要确保手机和计算机能够相互访问.

WLAN代理

在手机设置代理时,可以选择"设置"应用中的WLAN设置,长按选择"修改网络"选项,并在弹出的对话框中选择手动代理,设置代理服务器地址为主机的地址以及端口,这里端口为8080.

抓包-WLAN设置1

抓包-WLAN设置2

上述这种配置代理的方式可被下述App代码检测,而导致最终抓不到数据包,因此推荐使用VPN代理方式.

1
2
System.getProperty("http.proxyHost");
System.getProperty("http.proxyPort");

相对于直接从应用层设置WLAN代理的方式,VPN代理则是通过虚拟出一个新的网卡,从网络层加上该层代理,不仅可以绕过上述App代码的检测,而且检测VPN代理的API相对较少,也比较容易绕过.

VPN代理

为了配置VPN代理,首先需要下载一个VPN软件,这里推荐Postern这个App.

  1. adb安装Postern,进入App主页面,然后单击App左上方将菜单调出.

Postern1

  1. 进入"配置代理"页面后单击"代理1:proxy",配置服务器IP地址为主机IP、端口为8080,再选择代理类型为HTTPS/HTTP CONNECT,配置完毕后单击"保存"按钮并退出页面.

Postern2

  1. 配置完代理后,重新单击App左上角,待弹出菜单后选择"配置规则",清空原来的所有规则并创建一个新的规则,分别设置"动作"选项为"通过代理连接" “代理/代理组"为刚才设置的代理(这里为192.168.1.5:8080),并设置"目标地址"为”*“或者直接清空以指定手机所有流量从代理经过.注意,“开启抓包"选项要关闭.

Postern3

  1. 在上述代理和规则都设置完毕后,重新打开菜单项单击"关闭VPN"并开启VPN.这样测试机的配置就完成了.

Postern4

BurpSuite

接下来使用BurpSuite来进行测试抓包.

  1. 打开BurpSuite,单击Proxy->Intercept,再单击Intercept is On按钮关闭拦截模式.

抓包-BurpSuite1

  1. 在关闭拦截模式后,单击Options按钮并把代理地址修改为本机IP地址和端口8080.设置好代理地址后,单击OK按钮完成抓包的全部配置.

抓包-BurpSuite2

  1. 手机和PC端抓包设置完毕后,在手机浏览器上访问任意Http网址,就可以在"HTTP history"页面中看到抓到的Http明文数据了.(这里手机访问的网址为:http://www.jwc.ldu.edu.cn/wlgxk.asp)

抓包-BurpSuite3

Charles

依次单击Proxy->Proxy Settings,在弹出的窗口中对端口进行配置.

抓包-Charles1

注意
如果只是抓取HTTP类型的数据包,要关闭SSL Proxying模式(默认开启).

抓包-Charles2

如果不关掉,抓取HTTP数据包,就会出现上面的问题,明明是HTTP协议却被识别为HTTPS协议.

Https抓包配置

开启SSL Proxying

为了能够成功抓取HTTPS的数据,首先需要通过Ctrl+L快捷键开启Charles的SSL Proxying模式.

SSL-Proxying错误1

为了解决上述错误,我们需要设置下SSL Proxying.

SSL-Proxying设置1

SSL-Proxying设置2

注意
这里要设置下端口,不设置端口,Charles只会做转发,不会解密Https数据.

将Charles证书加入到Android系统信任的证书列表中

在开启SSL Proxying模式后,用VPN代理模式使用手机浏览器访问任意HTTPS站点时,浏览器会显示提示信息"您的连接不是私密连接”,为了解决这个问题,我们需要将Charles证书加入到Android系统信任的证书列表中,具体步骤如下:

  1. Charles导出cer证书,保存在PC上.

charles导出cer证书1

charles导出cer证书2

  1. 修改证书名称.
1
2
3
4
5
6
7
8
//Android系统证书目录
/system/etc/security/cacerts/
//每个证书的命名规则,文件名是一个Hash值,而后缀是一个数字
//后缀名的数字是为了防止文件名冲突的,比如如果两个证书算出的Hash值是一样的话,那么一个证书的后缀名数字可以设置成0,而另一个证书的后缀名数字可以设置成1
<Certificate_Hash>.<Number>
//文件名可以用下面的命令计算出来
openssl x509 -inform DER -subject_hash_old -in <Certificate_File.cer>
openssl x509 -inform PEM -subject_hash_old -in <Certificate_File.pem>

计算证书Hash

  1. 复制证书到Android设备上.
1
adb push xxxxxxx.0 /sdcard/

复制证书到设备上

  1. 复制到Android系统目录,并修改权限.
1
2
3
4
5
6
7
adb shell
su
mount -o remount,rw /
cp /sdcard/1146ce35.0 /system/etc/security/cacerts/
chmod 777 /system/etc/security/cacerts/*
mount -o remount,ro /
adb reboot

执行完上述命令,手机重启之后,Charles的证书就会放在系统证书中被系统信任.

如果运气不好,可能会出现下面的错误,原因是root的不彻底,权限不够,换一种方式root即可.

mount错误

  1. 此时切换为VPN代理模式,用手机浏览器访问任意HTTPS站点,Charles就能够正常抓到数据了.

Socks5抓包配置

如果App不使用HTTP/HTTPS连接方式,那么主机的抓包软件就无法正常抓到数据包,为了绕过对协议的限制,我们选择将VPN代理中的"代理类型"设置为SOCKS5模式,为了区分于HTTPS/HTTP CONNECT代理类型要将服务器端口修改为8888,从而从应用层的下层对所有网络连接进行抓取.

Socks5

与此同时要在Charles上进行配置.

Socks5-2

由于使用的是SOCKS代理模式,因此哪怕App使用Socket进行网络连接,Charles也可以正常抓取.

OSI七层模型

OSI七层网络模型 TCP/IP五层概念模型 对应网络协议
应用层(Application) HTTP、HTTPS、WS、FTP、DNS、SMTP、TFTP、SNMP、POP3、DHCP
表示层(Presentation) 应用层 TELNET、RLOGIN、SNMP、GOPHER
会话层(Session) SMTP、DNS
传输层(Transport) 传输层 TCP、UDP
网络层(Network) 网络层 IP(TPV4、IPV6)、ICMP、IGMP、ARP
数据链路层(Data Link) 数据链路层 FDDI、ETHERNET、APPANET、PDN、SLIP、PPP
物理层(Physical) 物理层 IEEE 802.1A、IEEE 802.2到IEEE 802.11

Http协议

HTTP(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,基于TCP的连接方式.

URL:

URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息.格式如下:

1
http://host[":"port][abs_path]
  • http: 表示要通过HTTP协议来定位网络资源.

  • host: 表示合法的Internet主机域名或者IP地址.

  • port: 指定一个端口号,为空则使用缺省端口80.

  • abs_path: 指定请求资源的URI,如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出.

Http请求:

由以下四部分组成:请求行、请求头部、请求空行、请求数据.

下方的URL其实是abs_path.

Http请求

请求方法:

方法 描述
GET 请求获取Request-URI所标识的资源
POST 在Request-URI所标识的资源后附加新的数据
HEAD 请求获取由Request-URI所标识的资源的响应消息报头
PUT 请求服务器存储一个资源,并用Request-URI作为其标识
DELETE 请求服务器删除Request-URI所标识的资源
TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT 用于某些代理服务器,请求的连接转化为一个安全隧道
OPYIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求
PATCH 是对PUT方法的补充,用来对已知资源进行局部更新

请求头:

请求头 描述
Host 接受请求的服务器地址,可以是IP:端口号,也可以是域名
User-Agent 发送请求的应用程序名称
Connection 指定与连接相关的属性,如Connection:Keep-Alive
Accept-Charset 通知服务端可以发送的编码格式
Accept-Encoding 通知服务端可以发送的数据压缩格式
Accept-Language 通知服务端可以发送的语言

Http响应:

由以下四部分组成:状态行、响应头部、响应空行、响应正文.

Http响应

Https实现原理

Https的整体过程分为证书验证和数据传输阶段.

Https原理图

证书验证阶段:

  1. 浏览器发起Https请求.
  2. 服务端返回Https证书.
  3. 客户端验证证书是否合法,如果不合法则提示警告.

数据传输阶段:

  1. 当证书验证合法后,在本地生成随机数.
  2. 通过公钥加密随机数,并把加密后的随机数传输到服务端.
  3. 服务端通过私钥对随机数进行解密.
  4. 服务端通过客户端传输的随机数构造对称加密算法,对返回结果内容进行加密后传输.

中间人抓包

中间人攻击,实际上是指客户端在传输数据到服务端的中间过程中,被在链路上的一个设备进行抓取过滤甚至篡改,将完整的客户端-服务端通信在客户端和服务器无感的状态下分割成客户端-攻击者和攻击者-服务端两个通信阶段.

中间人攻击1

我们在Https上的应用层抓包原理也是基于中间人攻击的方式.Https上的应用层抓包原理主要"攻破"的是Https传输过程中验证身份的步骤,我们在配置抓包环境时是将Charles证书加入到系统本身信任的证书中,当应用进行通信时,如果没有进一步的安全保护措施,那么客户端接收到的服务器证书即使是Charles证书也会继续通信,整个过程如下:

中间人攻击2

对抗手段

为了应对这一通过手动给系统安装证书从而导致中间人攻击继续生效的风险,App也对该类攻击推出了对抗手段,主要有以下两种方式:

SSL Pinning

原理

也称为证书绑定,该种方式不仅校验服务器证书是否是系统中的可信凭证,在通信过程中甚至连系统内置的证书都不信任而只信任App指定的证书.一旦发现服务器证书为非指定证书即停止通信,最终导致即使将Charles证书安装到系统信任凭据中也无法生效.

绕过方式

客户端在校验服务器的情况时,考虑到对证书验证的代码是写在App内部,自然而然就可以通过Hook修改校验服务器的代码,从而使得判断的机制失效.

前人的研究工作如下:

  1. 可以利用Objection命令完成Bypass.
1
android sslpinning disable
  1. Github开源项目-DroidSSLUnpinning.

https://github.com/WooyunDota/DroidSSLUnpinning/blob/master/ObjectionUnpinningPlus/hooks.js

DroidSSLUnpinning.7z

由于SSL Pinning的功能是开发者自定义的,因此并不存在一个通用的解决方案,Objection和DroidSSLUnpinning也只是对常见的App所使用的网络框架中对证书进行校验的代码逻辑进行了Hook修改,一旦App中的代码被混淆或使用了未知的框架,这些App的客户端校验服务器的逻辑就需要安全人员自行分析.

服务器校验客户端

原理

这种方式发生在Https验证身份阶段,服务器在接受到客户端的公钥后,在发送session key之前先对客户端的公钥进行验证,如果不是信任的证书公钥,服务器就中止和客户端的通信.

绕过方式

服务器并不掌握在分析人员手中,因此在中间人的状态下与服务器进行通信的实际上已经变成抓包软件,比如Charles.通常来说,我们所能做的对抗手段就是将App中内置的证书导入Charles中,使得服务端认为自己仍旧是在与其信任的客户端进行通信,最终达到欺骗服务器的目的.

具体的操作需要完成两项工作:

  1. 分析Apk,找到证书文件和相应的证书密码.

  2. 在找到证书和密码后将其导入到抓包软件中,比如导入Charles.打开Charles,依次单击Proxy->SSL Proxy Settings->Client Certificates->Add 添加新证书,然后输入指定的域名IP以及端口并导入p12或者pem格式的证书,之后即可将Charles伪装成使用特定证书的客户端,最终达到正常抓包的目的.

Charles导入证书1

Charles导入证书2

Hook模拟抓包

这种方式的抓包虽然不如抓包软件抓到的数据包全面,但是如果能够顺利Hook到发包函数,就可以直接无视证书,甚至通过Hook直接得到参数并在Hook的函数中通过打印函数调用栈得到函数的调用链,为后续分析带来便利.

Objection

这里来展示下如何利用Objection快速定位App中的收发包函数.

示例Apk

moveTV.apk

步骤展示

  1. 切换到Objection的目录,删除旧的日志.
1
2
cd ~/.objection
rm *
  1. 启动App,使用Objection附加到App进程.
1
objection.exe -g com.cz.babySister explore
  1. 运行下述命令,获取App已经加载的所有类.
1
android hooking list classes
  1. 输入exit命令,退出Objection,到Objection目录重命名日志文件(objection.log),防止后续操作影响本次生成的日志文件,这里重命名为objection1.log

objection日志

  1. 使用网络框架相关的关键词来过滤相关类.
1
2
3
4
5
6
7
cat .\objection1.log |grep -i HttpURLConnection
cat .\objection1.log |grep -i okhttp3
cat .\objection1.log |grep -i okhttp
...

//看上述哪个过滤的数量比较多,就重定向到文件中,如:
cat .\objection1.log |grep -i okhttp >1.txt 

过滤示例1

  1. 通过一些文件编辑器快速输入多行相同的数据来补全每一行中类的Objection命令.这里使用notepad++通过Shift+Alt对每一行首进行全选,并输入以下命令.
1
android hooking watch class

过滤示例2

  1. 切割上述文件中的命令为多个文件,防止Objection一次性Hook太多类崩溃.

切割命令

  1. 重新使用Objection附加到App上,并使用-c执行文件中的命令.

Objection帮助

1
objection.exe -g com.cz.babySister explore -c ".\1.txt"
  1. 在手机上对App进行操作(这里主要是点击App中的登录按钮,抓通信数据.),如果Objection界面中没有任何函数被调到,就应该回到第8步,更换包含Hook命令的文本文件.如果在Objection界面看到一堆函数被调用,说明框架类型确认成功.

Objection调用结果

  1. 任意选择上图中被调用的函数,比如说选择com.android.okhttp.internal.http.RealResponseBody.source()这个函数.此时退出Objection,重新附加上App,使用下述命令进行单一Hook.
1
2
android hooking watch class_method com.android.okhttp.internal.http.RealResponseBo
dy.source --dump-args --dump-backtrace --dump-return
  1. 此时去点击App中的登录按钮,查看Objection界面.

Objection调用结果2

这样就找到了发包函数com.cz.babySister.c.a.a

  1. Hook上述函数进行验证.
1
2
android hooking watch class_method com.cz.babySister.c.a.a --dump-args --dump-back 
trace --dump-return

Objection调用结果3

这里我们输入的账号和密码分别是123和qwertyuiop

缺点

上述过程过于依赖利用网络通信框架的关键词进行过滤,假如要分析的App本身存在强度非常大的混淆,将App中一些用来快速定位网络框架的关键字混淆成了无意义的字符,那么Hook抓包定位的方式就失效了.

OkHttpLogger

介绍

Github链接: https://github.com/siyujie/OkHttpLogger-Frida

OkHttpLogger-Frida.7z

这是一个能够完成混淆后的okhttp Hook的项目,在该项目中,Hook的方法脱离了直接经过字符串匹配的方式,反而通过反射去获取所有类并利用okhttp3框架的一些特征去验证App中是否使用了okhttp3这个网络通信框架.

示例Apk

春水堂.apk

步骤展示

  1. 将项目中的okhttpfind.dex放到手机的/data/local/tmp目录下,并为之提升权限.
1
2
3
4
adb push .\okhttpfind.dex /data/lcoal/tmp
adb shell
su
chmod 777 /data/lcoal/tmp/okhttpfind.dex
  1. 启动App,使用下述命令将okhttp_poker.js注进去.
1
2
//加入-o LuoHun.txt 可以将Frida一次注入后的所有输出保存到文件中,可供后续
frida -U org.sfjboldyvukzzlpp -l .\okhttp_poker.js -o LuoHun.txt

OkHttpLogger步骤展示1

  1. 按照提示输入find()命令,执行寻找okhttp框架的功能.

OkHttpLogger步骤展示2

  1. 将找到的结果全部复制并覆盖原okhttp_poker.js脚本中关于okhttp类的一些定义.

OkHttpLogger步骤展示3

  1. 执行hold()命令,开启Hook,然后开始操作App,就会发现一堆网络连接的内容.

OkHttpLogger步骤展示4

参考链接

<安卓Frida逆向与抓包实战>

HTTP 消息结构

HTTPS 详解一:附带最精美详尽的 HTTPS 原理图


相关内容

0%