0%

简单使用mitmproxy捕获Android上的通讯内容

起因

tl; dr: 我需要使用mitmproxy截获微信的一些HTTP通讯内容(不需要修改),具体而言是某几个网页的源代码.如果你不知道什么是maimai,那么现在你可以直接跳到第二节啦.

起因其实是顺着某bot找到了这个舞萌 DX 查分器,这里是它的使用方法.很遗憾,这3种方法对此刻的我而言都有某种不便之处……不过,这3种方法的本质显然都是提取微信上某个网页的源代码,因此我研究之后选择用mitmproxy(Fiddler Everywhere要收费)人工截取数据,然后上传给查分器.

启动mitmproxy

首先需要安装mitmproxy,用包管理器当然是最方便的:

1
# pacman -S mitmproxy

mitmproxy提供3个命令:mitmproxymitmwebmitmdump,分别是它的TUI、网页和CLI版本,这里我只用到后两者.直接在终端输入mitmweb即可启动:

1
2
3
# mitmweb
Web server listening at http://127.0.0.1:8081/
Proxy server listening at http://*:8080

它会自动在浏览器中打开http://127.0.0.1:8081/,可以看到一个简单的抓包界面.接下来需要对手机进行配置.

配置Android系统

这里不同厂商/版本/语言的Android肯定有差异,请自行适配.

首先需要让手机使用mitmproxy的代理.先让电脑和手机处于同一个网络下,然后打开Settings→Wi-Fi & Network→Wi-Fi,点按当前使用的wifi右侧的齿轮进入Network details页面,然后点击右上角的铅笔,在Advanced options→Proxy中填入代理信息:种类为Manual,Proxy hostname为电脑的IP,Proxy port为8080.

然后需要导入根证书.在浏览器中打开http://mitm.it这个网址(若不出意外,此时终端里应该显示一些连接的信息),按网页上的提示下载用于Android的证书.对于Android 11以上的版本,安装此证书的步骤为:打开Settings→Security & Lock Screen→Encryption & credentials→Install a certificate,种类选择CA certificate,然后选择刚才下载的证书文件即可.如果使用完毕要删除此证书,则要在Encryption & credentials→Trusted credentials→User下操作.

为了测试配置是否正确,你可以使用Chrome(Firefox一贯只使用它自己的证书数据库)随便访问一个使用HTTPS加密的网站.如果Chrome没有报证书错误,而你在电脑的网页界面中能看到此次通讯的明文,说明你成功了.

进行捕获

首先当然要让微信在使用代理的情况下完成你需要捕获的通讯,因此请自行按需操作.不过如果你本来的目的跟我一样是查分,请回到第一节看链接里的“使用方法”.注意mitmproxy加、解密可能需要一段时间,请耐心等待网页加载完和/或多试几次.

提取需要的数据

估计mitmproxy已经捕获到完整的通讯过程后,就要想办法将真正需要的部分提取出来.

方法一:使用filter

实际上在mitmproxy的网页界面上可以直接过滤出需要的flow.点击最上面的写着Search的搜索框,就会弹出一个各种filter的介绍,这里不详细说明了(因为我没有用过).注意这些filter在mitmproxy的其余两种界面中同样可以使用.

方法二:写一个addon

点击网页界面左上角的蓝色mitmproxy按钮,选择弹出的菜单中的Save一项,将本次捕获的内容保存下来——下文假设你保存在了./flows.(这个文件也可以在网页界面中打开.)

这里只放一段代码,不介绍概念,如果你像我一样只是想查分应当可以原封不动地使用,否则可以按需修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def response(flow):
if 'diff=' in flow.request.path and 'text/html' in flow.response.headers['content-type']:
print(flow.request.path)
if not flow.response.content:
print('Empty reponse, skipping')
return
path = './' + flow.request.path.split('&')[-1] + '.html'
try:
with open(path, 'w') as f:
f.write(flow.response.content.decode())
print('Saved as', path)
except Exception as e:
print('Save error: ')
print(e)

将其保存为./print.py,然后执行如下命令:

1
$ mitmdump -nqr flows -s print.py

当前目录下的diff=*.html就是我们需要的那些网页文件了.

上述代码的作用是:对于每一个flow(其实是对于response这个事件),如果其请求的路径包含diff=,且响应的内容属于text/html类型,就将响应的内容保存在一个HTML文件中.想知道这些变量的具体类型和含义,比如flow.response,请参阅官方文档

上面命令的参数含义如下:-n表示不启动代理服务;-q表示quiet,在这里主要作用是不显示每条flow的介绍(你可以去掉这个参数看看输出是什么样);-r表示加载后面的文件中的flows;-s表示执行后面的脚本.详细的介绍请参看mitmdump --help

结语

因为我的需求仅仅只是提取几个微信局域网生态内的网页的源代码,所以这份介绍就到这里——更深入的我也不会.真正卡住我的其实是安装证书那一步,因为Android 11的“设置”中安装证书的入口至少有两处,然而只有正文中写的那个入口可以成功安装mitmproxy提供的根证书,另外搞懂addon的写法也稍微花了一点工夫.

然而使我大费周章的根源(之一)其实只是这样一句话:

为了你的帐号安全,此微信号不能登录网页微信。

Shame on you, WeChat.