前言
最近公司有个小程序要提测,研发提测,体验,发现有个疑似 bug 的东西,想着抓包看下是不是接口数据的问题,结果问题出现了,按照以前的常规操作,打开 fiddler,设置 ip 代理(https 证书已经安装了),结果一看,fiddler 居然这样显示:
再看看手机,居然没数据?:
一脸疑问号,一开始以为是自己问题,折腾半天,不对,之前都是没问题的话,同样的环境,同样的设备,有毒?
等下,之前的没问题,最近微信好像更新了 7.0,那是不是这个导致的?
怎么解决?
一开始遇到这问题,不知道怎么处理,满脑子想着就是安装低版本微信,但是用过安卓系统的同学都知道,4.X 以后系统不允许降级安装,如果要安装低版本微信,意味着要删除微信再安装,这样会延伸出另外的问题,删除微信后我的聊天记录跟照片视频怎么办?
问题本身就是如何完整备份微信数据,咨询朋友圈,有不同大佬提供了方式:
- 微信 - 设置 - 聊天 - 聊天记录里面有数据迁移的功能
之前功能之前没使用过,但是从描述上看,感觉只能迁移聊天记录,那些图片跟小视频怎么办?
- 钛备份数据
这个是另外的同学说的,之前没了解过,上网查了下,这玩意号称是目前为最强悍的程序和系统备份工具,需 ROOT 权限运行;
这就尴尬啦,需要 root,小米华为 vivo 这种不好搞 root,怎么办?
那就看看这个钛备份的原理是啥,其实钛备份的原理很简单,就是把整个目录的内容都保存下来,当然包括 data 里面的数据,这就不难理解为什么要 root 权限了,当然里面要用到的技术很多,自行网上查询吧;
既然这条路,那就找台测试机安装旧版本试试吧;
安卓微信旧版本
试过好几个网址,最后选择的是wdj,那就挑了个 6.7.3 来试试了;
安装,配置手机抓包环境,试了下;
你看吧,都说旧版本可以的,你们不信,打脸了吧?
别人中毒了吗?
这问题肯定不止 jb 一个人遇到的,直接 Google 了,微信小程序无法抓包,果不出其然,大家都中毒了;
很开心,原因我不是一个人,认真看下该问题,咦,原来都是因为微信 7.0 导致的,跟我一样啊啊啊;
那再用微信 7.0 无法抓包 https为关键字,又发现新的东西了;
这两张图,认真看到,发现两个有意思的点:
第一点:
- 安卓系统 7.0 以下版本,不管微信任意版本,都会信任系统提供的证书
- 安卓系统 7.0 以上版本,微信 7.0 以下版本,微信会信任系统提供的证书
- 安卓系统 7.0 以上版本,微信 7.0 以上版本,微信只信任它自己配置的证书列表
第二点:
- 苹果机可以用
看到这里,莫名有点感动;
看到这里,第二种解决方案也出现了,用苹果就行了;
然后顺延上面的思路,安卓 7.0,让 jb 想起以前的事;
之前我司的一个产品,在新版本也会出现无法抓取 http 的情况,出现的情形跟上面的一致,直接看当时提交的内容吧;
由此看到,的确只有安卓才有问题,而且还是 7.0 开始引入的;
那一起来看看,这问题根源是什么吧;
问题根源
Google 一下,很多类似的帖子,问题的根源是:
在 Android7.0 及以上的系统中,每个应用可以定义自己的可信 CA 集集。
默认情况下,应用只会信任系统预装的 CA 证书,而不会信任用户安装的 CA 证书。
而回想我们抓包的过程,无论是 fiddler 还是 Charles,想抓 https,都必须手机安装对应的证书,通过 fiddler/Charles 安装的证书恰恰正属于用户安装的 CA 证书,因此会被视作不安全的证书。
解决方案 1:修改 APP 配置文件
如上代码提交的那样,直接修改 APP的android:networkSecurityConfig
属性,前提是可以获取到 APP 的源码。
在 AndroidManifest.xml 中
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
配置文件:res/xml/network_security_config.xml
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" overridePins="true" /> <!--信任系统证书-->
<certificates src="user" overridePins="true" /> <!--信任用户证书-->
</trust-anchors>
</base-config>
</network-security-config>
然后重新打包抓包就可以了;
这种做法,除了在源码上修改,还有其他法子吗?
肯定的,如下:
先脱壳,也可以直接下载 wdj 的包,然后用 apktool 反编译 apktool,就能看到包内容了,修改 AndroidManifest.xml,同时新增 network-security-config,修改完以后重新签名打包就可以;
解决方案 2:将证书安装到系统证书中(需要 root)
如果没有源码权限,怎么办?那就把证书安装到系统证书里面,但是这个操作需要 root 权限;
系统证书的目录是:/system/etc/security/cacerts/
每个证书的命名规则为:<Certificate_Hash>.<Number>
Certificate_Hash
表示证书文件的 hash 值,Number
是为了防止证书文件的 hash 值一致而增加的后缀;
证书的 hash 值可以由命令计算出来,在终端输入openssl x509 -subject_hash_old -in <Certificate_File>
,其中Certificate_File
为证书路径,将证书重命名为hash.0
放入系统证书目录,之后你就可以正常抓包了。
注意事项
小米手机自带 root 为不完整 root,需要进行完整 root(即解锁 system)。
方法如下:
安装 adb 工具
brew install Caskroom/cask/android-platform-tools
#没有安装homebrew的先安装homebrew
root
adb devices # 测试adb是否安装成功,成功了会出现设备的hash值
adb root
adb disable-verity # 禁用系统验证
注明,本方法 jb 未尝试过,因为手机没有 root 权限,方法来源于网上 ;
还有吗?
当然,假如你的手机没有 root,而且也不是自己的 APP,那怎么办?
别笑,这种情况很多,比如你想爬别人 APP 的数据,就会遇到这种情况了;
package capture
直接贴ka的介绍,这是一款无 root 抓包的工具;
产品特点:
- 抓包并记录
- 通过中间人技术抓取 ssl
- 不需要 root
- 易于使用
- 直接显示文本或显示 16 进制
界面很简单,如下图,下面显示的记录,右上有 1 的表示只做一个应用,点击会让你选择应用,右边无 1 的就是全部都抓;
如果不是 https 的能马上看到内容;
那试试除微信外的 APP,这里会延伸出另外的问题,就算别的 APP 不对证书做检验,给你抓到又如何?反正返回的数据是加密的;
选择微信,试试,发现还是不行,依然没有数据,就跟不信任证书一样;
所以,这个不行;
whistle
whistle是基于 Node 实现的跨平台抓包调试代理工具,但是仔细看了下原理,也是通过信任证书实现的,因此还是无法解决上面的问题;
AndroidHttpCapture
AndroidHttpCapture是在 testerhome 有人提及到的一款软件,号称是 Android 版的"Fiddler";
官网有 demo,下载下来后,看了下,功能是挺全的,但是,怎么感觉有点山寨的感觉?而且好像不能抓某个 APP 或者所有,对比上面的有点逊色的感觉?弃坑~
tcpdump + Wireshark
tcpdump 是一款强大的网络抓包工具,运行在 linux 平台上。
熟悉 tcpdump 的使用能够帮助你分析、调试网络数据。
如果想在 android 上使用 tcpdump,就需要 root 权限,但是 jb 手机没 root 权限,这块就跳过,理论上是可行的;
tcpdump 是有个文件的,把手机连接到电脑(要有 adb 环境哈)
adb root
adb remount
adb push /wherever/you/put/tcpdump /system/xbin/tcpdump
adb shell chmod 6755 /system/xbin/tcpdump
然后再执行adb shell tcpdump -p -vv -s 0 -w /sdcard/capture.pcap
,在手机上进行操作,操作完毕后,Ctrl+C
退出即可;
然后把生成的capture.pcap
用 Wireshark 打开;
wireshark 的界面是这样的:
这里不详细说明了,因为 tcpdump+wireshark 后面会单独写一篇文章;
反正,这两个组合是个神器,理论上来说,这种情况是能抓到数据的;
VirtualApp + HttpCanary
HttpCanary是一款强大的 Android 端抓包和注入工具,同样不需要 root,软件本身支持安装证书,如果只是单独使用,依然跟其他 APP 一样;
这里还要介绍另外的一个产品,VirtualApp是一个开源的 Android App 虚拟化引擎,允许在其中创建虚拟空间,并在这个虚拟空间中运行其他应用。
简单的说,就是一个容器,可以进行双开处理,市面上很多双开的软件,原理就是这个;
点击后,就是双开了,然后再打开 HttpCanary 进行转包,比如点击微信的小程序,啧啧啧,发现啥了?
如果服务端没有加密的话,终于可以了,有点心累啊;
最后,把两个 apk 的下载方式都贴一下:
HttpCanary:
链接:https://pan.baidu.com/s/1ViRJBZrUecdNU8DuegCphQ
提取码:9jzs
VirtualApp:
链接:https://pan.baidu.com/s/1k7i87xlY61z8is_foVPmQw
提取码:kh1y
VirtualApp 到底是什么
上面的例子证实 VirtualApp + HttpCanary 是可以抓到 https 的包,那这玩意到底是什么啊?为什么就能做到?
要介绍 VirtualApp,要先介绍Java 的反射机制;
Java 的反射机制
举个例子,通过反射修改private
的成员变量值,调用private
方法;
public class Person {
private String mName = "Hello";
private void sayHi() {
// dont care
}
}
如上的类,有一个私有成员变量mName
,和一个私有方法sayHi()
。讲道理,在代码中是无法访问到他们的。但反射能做到。
Person person = new Person();
// person.mName = "world!"; // impossible
// person.sayHi(); // no way
Field fieldName = Person.class.getDeclaredField("mName");
fieldName.setAccessible(true);
fieldName.set(person, "world!");
Method methodSayHi = Person.class.getDeclaredMethod("getDeclaredMethod");
methodSayHi.setAccessible(true);
methodSayHi.invoke(person);
简单来说,反射就是可以做到调用私有变量、方法的效果,还是不懂?
在来个通俗的例子:
对于男生,去嫖娼:
妈咪是class类,小姐是私有方法或成员,因为扫黄的关系,现在的小姐都是私有的,但是呢,你还是可以通过妈咪来找到小姐,这里面,通过妈咪的方式就是反射啦~
对于女生,买包包:
很多名牌店里面有一条潜规则,有点瑕疵的产品,内部人员是可以低价购买的,但是一般人是买不到的,那如果你有闺蜜在里面工作或者有熟人的情况下,你就可以通过这个渠道来买到这些瑕疵产品,这这个能方式就是反射;
反正就是不能光明正大做的,然后有个代理,可以这样做,你通过代理去做,就行啦;
这懂了吧?
hook
hook 是什么?hook 就是在应用运行过程中,注入外部的代码,从而改变原有的执行流程。
因此,应用中必须存在注入代码的窗口。
例如,使用了热修复技术的应用,就是在启动时加载并应用外部的补丁代码,这类应用便是本身自带了注入代码的窗口。
但是,对于逆向分析或安全研究而言,所面对的通常是一个黑盒 App,我们并不知道其是否存在注入代码的窗口,或者存在但无法被利用。
为此,我们必须要额外地为应用添加注入代码的窗口。
Xposed 便是这样做的:它修改了系统库,对所有应用在启动时添加了注入窗口。但是,这就需要具有 root 权限。
那么,如何在不具有 root 权限的情况下实现呢?这就需要用到 VirtualApp 了。
VirtualApp 的工作原理,简而言之,它通过代理常用系统服务的方式,在系统服务层与应用层之间添加了一层虚拟空间,从而允许在不安装应用的情况下运行应用。特别地,VirtualApp 本身并不需要 root 权限。
VirtualApp 之所以能够实现虚拟空间,是因为其对许多系统服务进行了代理和替换,而这部分是核心;
如果对原理感兴趣的同学,可以点击此处了解更多;
试试看
启动 VirtualApp 后,界面是这样的。
显示的是已经通过 VirtualApp 安装的 APK,可以直接从 SD 卡或者系统中已有的 APK 中选择安装。安装后直接点开图标,就能跟安装在外部的应用一样打开 APP。
简单尝试了一下,知乎和微博都能正常工作,并且运行速度跟外部安装的差异不大。而且还可以安装多个相同的应用,实现多开的效果。
看下数据
首先,来看一下它在开启 APP 后的进程信息:
u0_a200 22932 494 1034396 84008 SyS_epoll_ 0000000000 S io.virtualapp
u0_a200 22955 494 1064388 70408 SyS_epoll_ 0000000000 S io.virtualapp:x
u0_a200 22983 494 1530416 266948 0000000000 R com.zhihu.android
u0_a200 23320 494 1410736 214680 SyS_epoll_ 0000000000 S com.sina.weibo
u0_a200 23387 494 1174928 76848 SyS_epoll_ 0000000000 S com.sina.weibo.image
u0_a200 23415 494 1186076 81648 SyS_epoll_ 0000000000 S com.sina.weibo:remote
u0_a200 23455 494 1173888 76572 SyS_epoll_ 0000000000 S com.sina.weibo.imageservant
u0_a200 24028 494 1182780 74408 SyS_epoll_ 0000000000 S com.sina.weibo.servant
u0_a200 24425 494 1027636 66116 SyS_epoll_ 0000000000 S com.taobao.sophix_android
u0_a200 24492 494 1334412 174708 SyS_epoll_ 0000000000 S com.zhihu.android
可以看到,所有被 ViralApp 打开的应用,都和 VirtalApp 属于同一个 uid:u0_a200
。
其中,VirtualApp 本身有两个进程:io.virtualapp
和 io.virtualapp:x
io.virtualapp
就是可见的交互界面,同时也负责 APK 包的管理和安装;
io.virtualapp:x
作为一个单独的服务进程,虚拟了一些系统服务;
因此,VirtualApp 在运行时,包含以下三部分:
- Main Process,进程名
io.virtualapp
,主要负责 VirtualApp 用户界面及应用管理; - Server Process,进程名
io.virtualapp:x
,主要负责系统服务的代理,是通过 Content Provider 启动的; - VApp Process,进程名
io.virtualapp:p[0-…]
,作为将来运行 client 应用的进程,当 client 应用启动后,其进程名会更新为 client 应用的包名;
client 应用是通过 VirtualApp 安装的应用;
host 应用是 VirtualApp;
以这里安装的微博为例,查看一下它的进程的内存空间,可以看到相关路径全都被映射到了/data/data/io.virtualapp/virtual 下面,
... ...
b6d0f000-b7017000 r--p 00000000 fd:00 410335 /data/data/io.virtualapp/virtual/data/user/0/com.sina.weibo/Plugin/com.weibo.app.movie/dalvik-cache/base-1.dex
b7017000-b71d4000 r-xp 00308000 fd:00 410335 /data/data/io.virtualapp/virtual/data/user/0/com.sina.weibo/Plugin/com.weibo.app.movie/dalvik-cache/base-1.dex
... ...
bb745000-bb831000 r--p 00000000 fd:00 410247 /data/data/io.virtualapp/virtual/data/user/0/com.sina.weibo/code_cache/secondary-dexes/composer1312fd1cbada0e5074c9f9961b16aefb.dex
bb831000-bb8f0000 r-xp 000ec000 fd:00 410247 /data/data/io.virtualapp/virtual/data/user/0/com.sina.weibo/code_cache/secondary-dexes/composer1312fd1cbada0e5074c9f9961b16aefb.dex
... ...
bf448000-bf978000 r-xp 00000000 fd:00 410129 /data/data/io.virtualapp/virtual/data/app/com.sina.weibo/lib/libweiboffmpeg.so
bf978000-bf979000 ---p 00000000 00:00 0
bf979000-bf9ab000 r--p 00530000 fd:00 410129 /data/data/io.virtualapp/virtual/data/app/com.sina.weibo/lib/libweiboffmpeg.so
bf9ab000-bf9af000 rw-p 00562000 fd:00 410129 /data/data/io.virtualapp/virtual/data/app/com.sina.weibo/lib/libweiboffmpeg.so
... ...
c335a000-c33a9000 r-xp 00000000 fd:00 410127 /data/data/io.virtualapp/virtual/data/app/com.sina.weibo/lib/libweiboplayer.so
c33aa000-c33ad000 r--p 0004f000 fd:00 410127 /data/data/io.virtualapp/virtual/data/app/com.sina.weibo/lib/libweiboplayer.so
c33ad000-c33ae000 rw-p 00052000 fd:00 410127 /data/data/io.virtualapp/virtual/data/app/com.sina.weibo/lib/libweiboplayer.so
... ...
可见,这里面对路径做过了重新映射;
这块就到此为止吧,主要是想简单介绍下 VirtualApp,知道是怎么一回事;
服务器响应加密
上面的例子,就可以看到,现在越来越多的 APP 会对返回的结果进行加密处理,那这个是怎样的一个流程?
- 客户端正常发起请求
- 服务端进行业务处理,对 response 加密
- 客户端对 response 解密
这样做的好处是什么?
对 Response 加密之后,即使第三方抓取到了我们的数据,也无法解密,保证了我们的数据安全;
从开发的角度,需要注意几点:
- 加密算法要可逆算法,因为需要加解密,如 AES、RSA;
- 秘钥需要安全;
- 可以整个 response 加密,也可以某个部分加密;
那这种怎么搞?
这里说的没法搞,是指没现成的工具直接处理,如果非要这么搞,那就是反编译,因为想破解别人加密的算法,必须知道用什么方式加密,如果连加密方式都不知道,怎么解密?
还有个例子:
这样算加密吗?肯定算啦,但是这种加密是不是不可以处理?
并不是,直接网上找点代码试试看,理论上是可破,一般来说,MD5 和 RSA 是网络传输中最常用的两个算法,网上也有大量的网页提供在线解密;
小结
至此,本文结束,本文的主要收获是VirtualApp + HttpCanary 可以抓到 https 的数据,但同时的,如果是服务器返回乱码,这种情况暂时没办法解决;
本文提及到的抓包工具有以下几款:
- fiddler,一般用于 windows;
- charles,一般用于 Mac;
- package capture、VirtualApp + HttpCanary、AndroidHttpCapture,这几款都是安卓的;
- whistle,pc 的,基于 node;
- tcpdump + Wireshark,Linux 的,一般用于安卓;
- Stream、Thor 是用于 iOS 手机抓包;
希望大家都会上面场景的抓包工具都有所了解,留个印象,方式需要的时候再翻出来使用;
最后,谢谢大家~