现在的日常生活已经离不开微信,难免会生出微信有没有什么API可以使用的想法。那样就可以拿自己微信做个消息聚合、开个投票什么的,可是显然没有这种东西。不过还好,有网页版微信不就等于有了API么,这个项目就是出于这个想法出现的。
目标
看完这一系列教程,你就能从头开始实现自己关于微信以及类似工具的想法,例如一个命令行微信或者微信机器人。
当然,如果你只对使用微信的API感兴趣,可以直接跳到下一篇教程,直接使用我已经完成的接口。
本文为该教程的第一部分,主要讲述抓包与伪造,将会以最简单的方法介绍使用Python模拟登陆抓取数据等内容。
Python与基本的网络基础都不困难,所以即使没有这方面基础辅助搜索引擎也完全可以学习本教程。
教程流程简介
教程将会从如何分析微信协议开始,第一部分将教你如何从零开始获取并模拟扩展个人微信号所需要的协议。
第二部分将会就这些协议进行利用,以微信机器人为例介绍我给出的项目基本框架与存储、任务识别等功能。
第三部分就项目基本框架开发插件,以消息聚合等功能为例对框架做进一步介绍与扩展。
简单成果展示:
目前的样例微信号被扩展为了能够完成信息上传下载的机器人,用于展示信息交互功能。
其支持文件、图片、语音的上传下载、投票等功能,可以扫码尝试使用。
本部分所需环境
本文是这一教程的第一部分,需要配置抓包与Python环境。
本教程使用的环境如下:
- Windows 8.1
- Python 2.7.11 (安装Image, requests)
- Wireshark 2.0.2
- 微信版本6.3.15
Wireshark配置
Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页端的流量。
由于微信网页端使用https,需要特殊的配置才能看到有意义的内容,具体的配置见这里。
配置完成以后开始抓包,载入https://www.baidu.com
后若能看到http请求则配置成功。
分析并模拟扫码,并获取登录状态
微信网页端登陆分为很多步,这里以第一步扫码为例讲解如何从抓包开始完成模拟。
分析过程
在抓包以前,我们需要先想清楚这是一个什么样的过程。
我们都登录过网页端微信,没有的话可以现在做一个尝试:微信网页端。
这个过程简单而言可以分为如下几步:
- 向服务器提供一些用于获取二维码的数据
- 服务器返回二维码
- 向服务器询问二维码扫描状态
- 服务器返回扫描状态
有了这些概念以后就可以开始将这四步和包对应起来。
对应过程与实际的包
开启wireshark抓包后登陆网页端微信,完成扫码登陆,然后关闭wireshark抓包。
筛选http请求(就是菜单栏下面输入的那个http),可以看到这样的界面。
这里需要讲的就是第一列“No.”列的数字就是后文说的几号包,例如第一行就是30号包。数据包的类型则在Info列中可以看到,是GET,POST或是别的请求。
那么我们可以开始分析抓到的包了,我们先粗略的浏览一下数据包。
第325号包引起了我的注意,因为登陆过程当中非常有特征的一个过程是二维码的获取,所以我们尝试打开这一数据包的图片的内容。
325号包是由292号包的请求获取的,292号包又是一个普通的get请求,所以我们尝试直接在浏览器中访问这一网址。(访问自己抓到的网址)
具体的网址通过双击打开292号包即可找到。如需要可以点击这里看图。
我们发现直接在浏览器中获取了一张二维码,所以这很有可能就是上述一、二步的过程了。
那么我们是向服务器提供了哪些数据获取了二维码呢?
- 每次我们登录的二维码会变化,且没有随二维码传回的标识,所以我们肯定提供了每次不同的信息
- 网址中最后一部分看起来比较像标识:https://login.weixin.qq.com/qrcode/4ZtmDT6OPg==
- 为了进一步验证猜想,再次抓包,发现类似292号包的请求url仅最后一部分存在区别
- 所以我们提供了
4ZtmDT6Opg==
获取到了这一二维码。
那么这一标识是随机生成的还是服务器获取的呢?
- 从最近的包开始分析服务器传回的数据(Source是服务器地址的数据),发现就在上一行,286号包有我们感兴趣的数据。
- 打开这个包,可以看到其返回的数据为
window.QRLogin.code = 200; window.QRLogin.uuid = "4ZtmDT6OPg==";
(见下方截图) - 显然导致服务器返回这一请求的284号包就是我们获取标识(下称uuid)所需要伪造的包。
那么284号包需要传递给服务器哪些数据?
- 这是一个get请求,所以我们分析其请求的url:
https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=en_US&_=1453725386008
。 - 可以发现需要给出五个量
appid, redirect_uri, fun, lang, _
。 - 其中除了appid其余都显然是固定的量(_的格式显然为时间戳)。
- 然而搜索284号包之前的包也没有发现这一数值的来源,所以暂且认为其也是固定的量,模拟时如果出现问题再做尝试。
到了这里,1,2步的过程我们已经能够对应上相应的包了。
3,4部的最显著特征是在扫描成功以后会获取扫描用的微信号的头像。
我们还是首先大致的浏览一下服务器返回的数据包,试图找到包含图片的数据包。
- 从325号包(微信头像肯定在二维码之后获取)开始浏览。
- 我们发现338号包中包含一个base64加密的图片,解压后可以看到自己的头像。
- 所以这个数据包就是服务器返回的扫描成功的数据包了,而前面那部分
window.code=201
显然就是表示状态的代码。(见下方截图) - 经过尝试与再次抓包,我们理解状态码的涵义:
200:登陆成功 201:扫描成功 408:图片过期
- 那么第四部我们已经能够完全的理解
我们很容易的找到了在登录过程当中不断出现的请求,那么要怎么模拟呢?
- 首先这是一个简单的get请求,url为:https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=4ZtmDT6OPg==&tip=1&r=-2026440414&_=1453725386009
- 可以发现需要给出五个量
loginicon, uuid, tip, r, _
- 通过多次抓包发现除了r以外都可以找到简单的规律,那么r的规律等待模拟时再尝试处理
至此你应该已经能将四个过程全部与具体的数据包对应。为了避免有遗漏的过程,我们将没有使用到的与服务器交互的数据包标识出来(右键Mark)。经过简单的浏览,认为其中并没有必须的数据包交互。但值得注意的是,如果之后模拟数据包没有问题却无法登陆的话应当再回到这些数据包中搜寻。
这里做一个简单的小结,这一部分简单的介绍了分析数据包的基本思路,以及一些小的技巧。当然这些仅供参考,在具体的抓包中完全可以根据具体的交互过程自由发挥。而目前留下来的问题有:第一步时的appid与第三步时的r,留待模拟时在做研究。
使用Python模拟扫码
这一部分我们使用python的requests模块,可以通过pip install requests
安装。
我们先来简单的讲述一下这个包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import requests # 新建一个session对象(就像开了一个浏览器一样) session = requests.Session() # 使用get方法获取https://www.baidu.com/s?wd=python url = 'https://www.baidu.com/s' params = { 'wd': 'python', } r = session.get(url = url, params = params) with open('baidu.htm') as f: f.write(r.content) # 存入文件,可以使用浏览器尝试打开 # 举例使用post方法 import json url = 'https://www.baidu.com' data = { 'wd': 'python', } r = session.get(url = url, data = json.dumps(data)) with open('baidu.htm') as f: f.write(r.content) # 以上代码与下面的代码不连续 |
如果想要更多的了解这个包,可以浏览requests快速入门。
你可以尝试获取一个你熟悉的网站来测试使用requests,在测试时可以打开抓包,查看你发送的数据包与想要发送的数据包是否一样。
那么我们开始模拟第一、二个过程,向服务器提供一些用于获取二维码的数据,服务器返回二维码。
- 向服务器提交284,292号包
- 从服务器返回数据中提取出uuid与二维码图片
284号包
我们需要模拟的地址为:https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirecturi=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=en_US&=1453725386008 ,所以我们模拟的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#coding=utf8 import time, requests session = requests.Session() url = 'https://login.weixin.qq.com/jslogin' params = { 'appid': 'wx782c26e4c19acffb', 'redirect_uri': 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage', 'fun': 'new', 'lang': 'en_US', '_': int(time.time()), } r = session.get(url, params = params) print('Content: %s'%r.text) |
当然,将模拟的地址全部写在url里面效果完全一样。
值得一提的是requests会帮我们自动urlencode,如果不需要urlencode(/变为了%2F)可以将所有内容都写在url里面。
提取出uuid
这里使用re,如果不了解正则表达式的话可以直接拿来用,毕竟和这一个教程并不相关。
1 2 3 4 5 6 7 |
# 上接上一段程序 import re regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";' # 我们可以看到返回的量是上述的格式,括号内的内容被提取了出来 data = re.search(regx, r.text) if data and data.group(1) == '200': uuid = data.group(2) print('uuid: %s'%uuid) |
如果没能成功获取到uuid可以尝试再运行一次。
292号包
我们需要模拟的url为:https://login.weixin.qq.com/qrcode/4ZtmDT6OPg== ,所以我们模拟的代码如下:
1 2 3 4 5 6 -num" data-line="crayon-5812b21999dec062762200-2">2 3 4 5 6 这种东西。不过还好,有网页版微信不就等于有了API么,这个项目就是出于这个想法出现的。
目标看完这一系列教程,你就能从头开始实现自己关于微信以及类似工具的想法,例如一个命令行微信或者微信机器人。 当然,如果你只对使用微信的API感兴趣,可以直接跳到下一篇教程,直接使用我已经完成的接口。 本文为该教程的第一部分,主要讲述抓包与伪造,将会以最简单的方法介绍使用Python模拟登陆抓取数据等内容。 Python与基本的网络基础都不困难,所以即使没有这方面基础辅助搜索引擎也完全可以学习本教程。 教程流程简介教程将会从如何分析微信协议开始,第一部分将教你如何从零开始获取并模拟扩展个人微信号所需要的协议。 第二部分将会就这些协议进行利用,以微信机器人为例介绍我给出的项目基本框架与存储、任务识别等功能。 第三部分就项目基本框架开发插件,以消息聚合等功能为例对框架做进一步介绍与扩展。 简单成果展示:目前的样例微信号被扩展为了能够完成信息上传下载的机器人,用于展示信息交互功能。 其支持文件、图片、语音的上传下载、投票等功能,可以扫码尝试使用。 本部分所需环境本文是这一教程的第一部分,需要配置抓包与Python环境。 本教程使用的环境如下:
Wireshark配置Wireshark是常见的抓包软件,这里通过一些配置抓取微信网页端的流量。 由于微信网页端使用https,需要特殊的配置才能看到有意义的内容,具体的配置见这里。 配置完成以后开始抓包,载入 分析并模拟扫码,并获取登录状态微信网页端登陆分为很多步,这里以第一步扫码为例讲解如何从抓包开始完成模拟。 分析过程在抓包以前,我们需要先想清楚这是一个什么样的过程。 我们都登录过网页端微信,没有的话可以现在做一个尝试:微信网页端。 这个过程简单而言可以分为如下几步:
有了这些概念以后就可以开始将这四步和包对应起来。 对应过程与实际的包开启wireshark抓包后登陆网页端微信,完成扫码登陆,然后关闭wireshark抓包。 筛选http请求(就是菜单栏下面输入的那个http),可以看到这样的界面。 这里需要讲的就是第一列“No.”列的数字就是后文说的几号包,例如第一行就是30号包。数据包的类型则在Info列中可以看到,是GET,POST或是别的请求。 那么我们可以开始分析抓到的包了,我们先粗略的浏览一下数据包。 第325号包引起了我的注意,因为登陆过程当中非常有特征的一个过程是二维码的获取,所以我们尝试打开这一数据包的图片的内容。 325号包是由292号包的请求获取的,292号包又是一个普通的get请求,所以我们尝试直接在浏览器中访问这一网址。(访问自己抓到的网址) 具体的网址通过双击打开292号包即可找到。如需要可以点击这里看图。 我们发现直接在浏览器中获取了一张二维码,所以这很有可能就是上述一、二步的过程了。 那么我们是向服务器提供了哪些数据获取了二维码呢?
那么这一标识是随机生成的还是服务器获取的呢?
那么284号包需要传递给服务器哪些数据?
到了这里,1,2步的过程我们已经能够对应上相应的包了。 3,4部的最显著特征是在扫描成功以后会获取扫描用的微信号的头像。 我们还是首先大致的浏览一下服务器返回的数据包,试图找到包含图片的数据包。
我们很容易的找到了在登录过程当中不断出现的请求,那么要怎么模拟呢?
至此你应该已经能将四个过程全部与具体的数据包对应。为了避免有遗漏的过程,我们将没有使用到的与服务器交互的数据包标识出来(右键Mark)。经过简单的浏览,认为其中并没有必须的数据包交互。但值得注意的是,如果之后模拟数据包没有问题却无法登陆的话应当再回到这些数据包中搜寻。 这里做一个简单的小结,这一部分简单的介绍了分析数据包的基本思路,以及一些小的技巧。当然这些仅供参考,在具体的抓包中完全可以根据具体的交互过程自由发挥。而目前留下来的问题有:第一步时的appid与第三步时的r,留待模拟时在做研究。 使用Python模拟扫码这一部分我们使用python的requests模块,可以通过 我们先来简单的讲述一下这个包。
如果想要更多的了解这个包,可以浏览requests快速入门。 你可以尝试获取一个你熟悉的网站来测试使用requests,在测试时可以打开抓包,查看你发送的数据包与想要发送的数据包是否一样。 那么我们开始模拟第一、二个过程,向服务器提供一些用于获取二维码的数据,服务器返回二维码。
284号包 我们需要模拟的地址为:https://login.weixin.qq.com/jslogin?appid=wx782c26e4c19acffb&redirecturi=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=en_US&=1453725386008 ,所以我们模拟的代码如下:
当然,将模拟的地址全部写在url里面效果完全一样。 值得一提的是requests会帮我们自动urlencode,如果不需要urlencode(/变为了%2F)可以将所有内容都写在url里面。 提取出uuid 这里使用re,如果不了解正则表达式的话可以直接拿来用,毕竟和这一个教程并不相关。
如果没能成功获取到uuid可以尝试再运行一次。 292号包 |