Android 7.0+使用VirtualXposed+Charles进行抓包

Stella981
• 阅读 727

前言

最近在对一个app进行测试的时候,尝试抓取数据包,发现以前的使用方法失效了,原因是随着安卓版本的提高,对证书的限制越发严格,而我身边的老机子放在学,不在身边,没得办法,只好研究一下怎么绕过这种限制。

经过一方查找,终于发现了一个相对比较简单的办法,这里就开一篇文章,记录一下。

过程

首先下载所需要的工具:

● Charles——

https://www.charlesproxy.com/download/

● Charles-Crack(有能力的同学请支持正版)——

https://github.com/8enet/Charles-Crack

● VirtualXposed——

https://github.com/android-hacker/VirtualXposed/releases

● TrustMeAlready——

https://github.com/ViRb3/TrustMeAlready/releases

PC端

PC端下载并安装好之后,运行Charles。

依次点击菜单栏的:Proxy→Proxy Settings,并按如下进行勾选。

Android 7.0+使用VirtualXposed+Charles进行抓包

接着点击菜单栏:Proxy→SSL Proxying Settings

按照下图进行配置:

Android 7.0+使用VirtualXposed+Charles进行抓包

若事先确定要抓取的Host和Port信息,可自行进行更改。

接着点击Proxy→Windows Proxy (注:不同版本名称不同),将不再抓取本地流量。

然后点击Help→SSL Proxying→Install Charles Root Certificate on a Mobile Device or Remote Browser,将证书挂载到chls.pro/ssl这个地址上。

手机端用浏览器打开上述地址,将证书下载到本地。这步也可以选择点击菜单栏:Help→SSL Proxying→Save Charles Root Certificate...,来将证书下载到PC,通过数据线、QQ等方法传到手机。

手机端

首先需要把手机与电脑连接到同一个网络内。

打开WLAN,选择对应的WIFI,进行代理配置。如下图所示:

Android 7.0+使用VirtualXposed+Charles进行抓包

主机名为PC端的内网IP,端口为配置Charles时Proxy Settings配置中的Http Proxy里的Port内容。

PC端内容不清楚的同学可以打开终端运行如下命令:

● Windows: ipconfig

● Linux: ifconfig

● Mac: ifconfig

成功代理上之后,手机端的流量都会经过PC端的Charles。如果是第一次配置,则Charles会弹出一个窗口,提示有新的连接,点击Allow按钮。

其次需要将电脑端Charles的证书给安装上。

若在PC端选择的是Install Charles Root Certificate on a Mobile Device or Remote Browse,则先需要通过手机浏览器访问chls.pro/ssl这个网址获得证书文件。

这里我使用的手机为小米8 Lite,不同的手机品牌/型号安装证书的方法可能有所不同,具体可通过搜索引擎来获得安装的方法。

依次点击:设置→更多设置→系统安全→加密与凭据→从SD卡安装,接着在文件浏览器中选择你下载好的证书。

然后给证书凭据起个名字,可随意填写,凭据用途选择VPN和应用。

安装完毕后依次点击:信任的凭证→用户,即可查看到刚刚添加进来的Charles证书——XK72 Ltd。

以往我们只需要执行到这里,便可以成功抓取到数据包。不过由于Android的版本更新,对用户自身添加的证书进行了限制,导致我们直接地无法抓取的HTTPS数据包,在Charles里会发现HTTPS的流量都显示Unknown。

Android 7.0+使用VirtualXposed+Charles进行抓包

这里我选择的办法是用VirtualXposed工具进行绕过,如果你不想使用这个方法,也可以考虑通过将手机进行Root处理,并将Charles的证书添加到系统级的证书中,不过这并不在本文讨论的范畴。

手机下载好VirtualXposed和TrustMeAlready两个apk文件,安装VirtualXposed.apk之后运行。

在VirtualXposed中,先进入设置页面,点击添加应用,选择你想抓取流量的应用,以及TrustMeAlready.apk文件进行安装。注意:由于TrustMeAlready.apk未安装,需要点击+号按钮,在对应的目录选择apk文件即可。

然后再回到设置页面,点击模块管理,可以看到我们刚刚添加的TrustMeAlready便在其中,点击右边的框框进行勾选,接着回到设置页面,在最下方点击重启、确定。

到这里我们便已经完成了全部的操作,之后你可以在VirtualXposed框架内打开任意的app都可以成功取到HTTPS流量。

Android 7.0+使用VirtualXposed+Charles进行抓包

关于Charles的使用方法,本文不再赘述,网络上已有许多教程,稍微花点时间搜索即可。

分析

Android7.0+为何无法直接截取HTTPS流量

在Android开发者平台文档,我们可以查到这么一段话:

默认情况下,来自所有应用的安全连接(使用 TLS 和 HTTPS 之类的协议)均信任预装的系统 CA,而面向 Android 6.0(API 级别 23)及更低版本的应用默认情况下还会信任用户添加的 CA 存储区。应用可以使用 base-config(应用范围的自定义)或 domain-config(网域范围的自定义)自定义自己的连接。

自定义可信 CA|Android Developer

以上说明了安卓6.0以上的版本,在默认情况下应用是不会相信用户添加的CA证书,导致我们使用老方法无法完整地获取到应用发出的HTTPS数据。

VirtualXposed+TrustMeAlready实现原理

简单的说,VXP相当于手机上的虚拟机,在手机原有的系统上创建一块虚拟空间,类似沙盒般的效果,而通过TrustMeAlready插件,便可HOOK到 APK 中所有用于校验 SSL 证书的 API (详情可以点击参考里的《JustTrustMe原理分析》),从而绕过证书校验,故此达到https抓包的效果。

一、什么是Virtual Xposed?

Xposed

众所周知Xposed是来自国外XDA论坛的rovo89开发的一款开源的安卓系统框架。

它是一款特殊的安卓App,其主要功能是提供一个新的应用平台,玩家们安装Xposed框架后,就能够通过Xposed框架搭建起的平台安装更多系统级的应用,实现诸多神奇的功能。

Xposed框架的原理是修改系统文件,替换了/system/bin/app_process可执行文件,在启动Zygote时加载额外的jar文件(/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar),并执行一些初始化操作(执行XposedBridge的main方法)。然后我们就可以在这个Zygote上下文中进行某些hook操作。

Xposed真正强大的是它可以hook调用的方法.当你反编译修改apk时,你可以在里面插入xposed的命令,于是你就可以在方法调用前后注入自己的代码.

Github开源地址:

https://github.com/rovo89/Xposed

由于Xposed最大的弊端在于设备需要root,并且编写插件模块后需要重启手机(当然也有办法可以不用重启),所以有了VirtualApp。

VirtualApp

VirtualApp是一个App虚拟化引擎(简称VA)。

VirtualApp在你的App内创建一个虚拟空间(构造了一个虚拟的systemserver),你可以在虚拟空间内任意的安装、启动和卸载APK,这一切都与外部隔离,如同一个沙盒。

运行在VA中的APK无需在外部安装,即VA支持免安装运行APK。

熟悉android系统开机流程的应该知道各services是由system server启动一系列的系统核心服务(AMS,WMS,PMS等等)ViratualApp就是构建了一个虚拟system_process进程,这里面也有一系列的核心服务。

VirtualApp主要技术用到了反射和动态代理来实现的

Github开源地址:

https://github.com/asLody/VirtualApp

VirtualXposed

VirtualXposed就是基于VirtualApp和epic 在非ROOT环境下运行Xposed模块的实现(支持5.0~8.1)。

Github开源地址:

https://github.com/android-hacker/VirtualXposed

来源:http://jackzhang.info/2018/04/09/VirtualXposed/

HTTPS抓包为何需要安装抓包工具的CA证书

为了弄清楚这个问题,我们首先得清楚SSL/TLS加密的原理。

通常来说,SSL与TLS都是非对称加密的,有一个公钥与私钥。公钥是公开的,私钥是私密的,存在于服务端。服务器返回的内容会被私钥加密,客户端需要使用公钥进行解密。同样的,用户端的数据便有公钥加密,私钥来解密。

而我们都知道,使用了SSL之后我们便可以保护我们的站点免受中间人攻击。那又何为中间人攻击呢?

举个例子,用户A要使用电脑访问网站http://example.com,而这台电脑已被攻击者B攻陷,那么攻击者B可通过修改A电脑上的hosts文件,将example.com的解析指向B自己的服务器,这样A用户就在”不知情“的情况下中了招。而如果该网站使用了SSL/TLS加密时,用户A在访问https://example.com的时候,需要向服务器请求公钥的内容,又因为公钥是放在CA证书里的,且CA证书通常是由相关的权威CA机构(权威性由微软等操作系统巨头决定)才能发布,类似我们的民政局才能发布身份证。这使得攻击者无法伪造CA证书,因为客户端在收到CA证书之后会根据不同的权威CA机构进行相应的验证,而若颁发该证书的机构不够权威(这使得权威机构也不会随意颁发CA证书,以免自身的权威性被取消),是不会被系统所信任的。这一连串的操作,使得使用了SSL/TLS的网站可以不受中间人攻击的影响。

OK回归正题,那这HTTPS抓包与中间人攻击有何关系呢?其实这两者的原理都是一样的,只不过攻击者的角色变成了抓包工具。

So,这次的问题就变成了中间人攻击如何在HTTPS通信中生效?

我们注意到,中间人攻击的最大难点就在于CA证书的权威性,而我们在没有域名解析权的情况下是不能去向权威CA机构申请证书的。那么既然如此,为何我们不考虑自己“开”一家权威机构呢,这样我们生成的证书不就会被信任了嘛。

这时候,就得需要安装我们抓包工具的CA证书了,这个证书与域名所有者向权威机构申请的证书不同,他是根证书。

因为域名的CA证书的验证过程也是非对称加密验证,也就说,CA证书的验证是由根证书里的公钥来解密验证的。通常操作系统里已经默认信任了一批权威机构的根证书。

所以,当我们把我们自己的根证书添加到操作系统中时,相当于我们自己“开”了一家权威CA机构,这样便可以解决了之前的难题。

借一张网图:

Android 7.0+使用VirtualXposed+Charles进行抓包

源自:图解 HTTPS:Charles 捕获 HTTPS 的原理

结语

别看上边方法好像挺简单的,实际操作起来却挺繁琐,网络上的方法大多抄来吵去且时效性很差,导致在操作过程中也走了许多弯路,许多东西还是自己实验之后才知道。看似简单的东西,其实写起来可学习的东西还是很多的,以前自己在学习的时候没有注意的点,现在看起来也是可以细细研究的。不骄不躁,Stay Hungry, Stay Foolish.

参考

● 通过 HTTPS 和 SSL 确保安全|Android开发者文档

https://developer.android.com/training/articles/security-ssl

● VirtualXposed插件开发-Xposed hook 之入门案例

http://jackzhang.info/2018/04/09/VirtualXposed/

● JustTrustMe原理分析

https://bbs.pediy.com/thread-214012.htm

● 图解 HTTPS:Charles 捕获 HTTPS 的原理

https://github.com/youngwind/blog/issues/108

Android 7.0+使用VirtualXposed+Charles进行抓包

关注我,获取更多干货哦!

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这