1. 服务端监听

代理这一需求主要使用的是mitmproxy来做监听

mitmproxy 项目的工具是一组暴露通用底层功能的前端。

  • mitmproxy 是一个具有 SSL / TLS 功能的交互式拦截代理,具有用于HTTP / 1,HTTP / 2和 WebSockets 的控制台界面。

  • mitmdump 是 mitmproxy 的命令行版本。将 tcpdump 用于 HTTP。

  • mitmweb 是用于 mitmproxy 的基于 Web 的界面。

文档,教程和分发软件包可在 mitmproxy 网站上找到。

我们只用到 mitmproxy, mitmdump ,另一个 mitmweb,可以到官网去查看。

1.1. 创建项目环境

  1. 用 pipenv 新建一个项目环境:

    $ mkdir wechatpay && cd wechatpay
    
  2. 我这里指定环境 python 版本为 3.6:

    $ pipenv --python 3.6
    
  3. 修改 pipenv 使用国内镜像:

    $ sed -i 's/https:\/\/pypi.org\/simple/https:\/\/pypi.tuna.tsinghua.edu.cn\/simple/g' ${PWD}/Pipfile
    

    提示

    mac下使用sed 会出现 extra characters at the end of l command 错误,需要-i 后跟双引号 $ sed -i "" 's' file

  4. 安装 mitmporxy:

    $ pipenv install mitmproxy
    
  5. 测试mitmdump是否正常工作:

    $ pipenv run mitmproxy -p 8081 # -p 指定监听端口号
    

    提示

    关键的几个常用的快捷键 ?: 帮助 q: 返回 或退出 z: 清屏 j: 上一个或向上滑动 k: 下一个或向下滑动 回车键: 查看选中的请求 h: 查看 请求内容 下一个 l: 查看请求内容 上一个 tab: 查看请求内容 下一个

1.2. 手机设置代理抓包

  1. 设置手机的代理,确定连接的是同一个网络,配置代理,设置如下:

https://report-upload.oss-cn-hangzhou.aliyuncs.com/WechatIMG548.jpeg?x-oss-process=image/resize,m_mfit,w_400

接着打开微信 - 支付,观察 mitmproxy 监听命令窗口,会有很多数据包。 我们继续 微信操作进入 钱包 - 账单,这里发现提示安全警告, 该网站的安全证书存在问题,可选择“继续”在浏览器中访问。说明我们https抓包还没成功。 接下来我们给mitmdump配置https抓包

1.3. 设置https抓包

安装mitmproxy证书的最简单方法是使用内置的证书安装应用程序。 现在启动设备上的浏览器,并访问域名mitm.it。您应该会看到以下内容:

提示

如果使用的是iOS设备,则应使用Safari浏览器,以便它打开安装证书的正确提示。

https://report-upload.oss-cn-hangzhou.aliyuncs.com/certinstall-webapp.png

单击相关图标,按照所用平台的设置说明进行操作,安装。

ios 手机设置流程

  1. 访问 mitm.it 后会下载一个描述文件,访问设置-通用-描述文件 安装

  2. 访问设置-关于本机-证书信任设置 启用mitmproxy

1.4. 微信支付抓包

访问微信的账单,发现数据包抓取成功。

https://report-upload.oss-cn-hangzhou.aliyuncs.com/QQ20191226-100702.gif

从中分析出需要的数据请求地址:

https://wx.tenpay.com/userroll/userrolllist?classify_type=0&count=20&csrf_token=gDzdiW8dF7bQ9ekmP2andDPllx%2FukYM&exportkey=AS949HauKUqyrvQsZwuJe3E%3D&sort_type=1

从上面的抓包出来的请求,与cookies,可以很容易拉起请求,因为认证是通过cookies来认证的。 我们拿到请求,我们先来分析下他的参数。从程序开发的角度。这些参数是很重要的:

{
   "classify_type": 0, # 账单的分类,红包,转账,群收款,二维码收款等等。
   "count": 20, # 一页显示的数量。
   "csrf_token": "", # csrf token 一般是表单的东西
   "exportkey": "", # 什么key东西
   "sort_type": "" # 排序的方法
}

从字面意思,先来猜想,要想验证猜想,只要换不同的参数去请求这个地址就能得到验证了。

最后去掉不必要的参数最终得到 url:

https://wx.tenpay.com/userroll/userrolllist?classify_type=0&count=20

因为我们获取到的请求是直接有csrf_token与exportkey了,而cookies才是访问请求的关键。直接有的,并不需要我们去前面的页面获取csrf_token, exportkey 理论都是可行的,怕篇幅太长,这里就不讲了,小伙伴们可以自行研究。

现在我们可以用 curl 命令:

$ curl 请求的链接 --cookie "获取到的Cookies"

也可以用postman 来请求:

https://report-upload.oss-cn-hangzhou.aliyuncs.com/WechatIMG549.png?x-oss-process=image/resize,m_mfit,w_700

这里面有我们需要的数据:

{
   "bill_id": "",
   "bill_type": 10,
   "current_state": "",
   "fee": 2038,
   "fee_attr": "negtive",
   "fee_type": "CNY",
   "icon_url": "",
   "out_trade_no": "",
   "timestamp": "",
   "title": "",
   "trans_id": ""
}

看到数据,就是分析其参数是否有我们可以利用的地方。发现这里的信息并没有我们想要的关联参数,也就是备注。

提示

在做这个文章前,以前的这个列表参数是都在这个API里,在写文章时,微信支付的API有做变化,备注是在订单详情API里,道高一尺,魔高一丈,总有办法。

那我们通过抓包,查到了他的详情API:

$ curl https://wx.tenpay.com/userroll/userrolldetail?trans_id=trans_id --cookie "获取到的Cookies"

请求后看到了我们想要的备注:

{
   ...
   "preview": [
      ...
      {
         "label": {
            "name": "付款方留言",
            "actionsheet": []
         },
         "value": [
            {
               "name": "101",
               "actionsheet": []
            }
         ],
         "sequence": []
      },
      ...
   ]
}

1.5. 抓取微信登陆cookies

代理所需要的功能,就是定时返回支付账单的请求cookies, 并存到某个地方,供服务器读取。所以这里安装redis:

$ pipenv install redis

先写 mitmdump 的解析脚本 fetch_cookies.py

import redis
import json

r = redis.Redis(host='localhost', port=6379, db=3)


# 这个地方必须这么写 函数名:response
def response(flow):
   # 通过抓包软包软件获取请求的接口, 获取到cookies后,存入redis
   if 'userroll/userrolllist' in flow.request.url:
      # 数据的解析
      data = {
            'userroll_encryption': flow.response.cookies.get('userroll_encryption')[0],
            'userroll_pass_ticket': flow.response.cookies.get('userroll_pass_ticket')[0]
      }
      r.set('wechat_cookies', json.dumps(data))
      print('请求成功一次', data)

定义了一个redis client, response 解析函数, 主要是解析到cookies后,存入redis.

我们现在关闭掉 mitmproxy 的监听,并启用 mitmdump 来返回当前请求的 cookies:

$ pipenv run mitmdump -s fetch_cookies.py -p 8081 '~u https://wx.tenpay.com/'

注意: ~u https://wx.tenpay.com/ 的意思是过滤抓包的规则,匹配到这个域名,才进入解析.

再次访问手机账单后,再试试 redis 是否写入成功:

$ redis-cli
127.0.0.1:6379> SELECT 3
OK
127.0.0.1:6379[3]> GET wechat_cookies
"{\"userroll_encryption\": \"mGpO/JhIzKKeplJhBhiD4J4VG1yNvn8mZQ1wyjn3UpZP01uFy1c22s79xxrSilDLhUxQ3p3rxdL+hPkGLDTKD7PwkmSbXwgw7SzMgemcXmuH4t9nTXaxnx4ZDvEdV/BGZx8fJMf3HL3U+l2v59D9qA==\", \"userroll_pass_ticket\": \"g5mdGJCudEJSK0XXvRcPJ1ptaoJONpTaJmg762zsoRh0IO2FGpDjN8SYUyCv9sJp\"}"

当你刷新你微信的支付-账单时,再调用 redis ,会发现 wechat_cookies 会更新最新获取的 cookies