声明
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号【K哥爬虫】联系作者立即删除!
前言
近期有粉丝私信,提到了某网站抓不到包的问题,之前还有不少新手粉丝提到不会 webpack。经过分析,发现这个网站属于 ws 协议,同时还是一个简单的 webpack,正好借此案例,解答粉丝们的疑惑:
逆向目标
-
目标:某赚网
-
地址:
aHR0cDovL3dhcC54dXp1YW4uY24vIy9ob21l
抓包分析
进入首页,随机选择某个商品点击接单,然后进入订单列表,会发现有不同的订单在一直刷新,会发现 /GetPendingOrderStatus
这个数据包在不断的下发:
同时该数据是密文状态,经过断点调试发现这个接口并不是我们需要的,那么它的数据应该是从何而来呢?大胆猜测应该是走了不同的协议,因为这种实时获取数据的接口,一般大概率都是走的 ws 协议, 避免了每次通信都需要重新建立连接的开销。
再次刷新列表页,我们发现有一个 ws 通信的数据包 /api/market
:
同时在消息接收里面,不断加载服务器给我们返回的消息,同样这个消息也是密文的状态,大胆猜测这个应该就是我们需要的列表数据:
其中协议头中的参数,是 ws 特有的:
-
Upgrade: websocket:表明这是 WebSocket 类型请求;
-
Sec-WebSocket-Key:
Sec-WebSocket-Key
则是用于握手协议的密钥,是 Base64 编码的 16 字节随机字符串。服务器的 WebSocket 回应如下:
HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= Sec-WebSocket-Origin: null Sec-WebSocket-Location: ws://example.com/
服务器同样用
Connection
字段通知浏览器,需要改变协议。Sec-WebSocket-Accept
字段是服务器在浏览器提供的Sec-WebSocket-Key
字符串后面,添加 RFC6456(http://tools.ietf.org/html/rfc6455)标准规定的“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”
字符串,然后再取 SHA-1 的哈希值。浏览器将对这个值进行验证,以证明确实是目标服务器回应了 WebSocket 请求。 -
Sec-WebSocket-Location 字段表示进行通信的 WebSocket 网址。
完成握手以后,WebSocket 协议就在 TCP 协议之上,开始传送数据。
WebSocket 回顾
关于 WebSocket 在往期文章有过介绍,不过时间久远,可能部分新粉不知道:
协议对比
HTTP
- 协议类型:无状态的请求-响应型协议。
- 通信方式:单向通信,客户端发起请求,服务器返回响应。
- 持久连接:支持通过 HTTP Keep-Alive 持久连接,允许在一个连接内进行多次请求和响应。
WebSocket
- 协议类型:全双工通信协议。
- 通信方式:双向通信,客户端和服务器可以随时发送消息。
- 持久连接:使用单个 TCP 连接保持长时间连接,避免了每次通信都需要重新建立连接的开销。
连接方式对比
HTTP
- 连接建立:每次请求需要建立一个新的连接。
- 连接关闭:服务器在发送完响应后关闭连接,客户端需要为每个新请求重新建立连接。
WebSocket
- 连接建立:初始连接通过 HTTP 建立,然后升级为 WebSocket 协议,连接建立后保持开放状态。
- 连接关闭:连接可以由客户端或服务器随时关闭,且不需要为每次通信重新建立连接。
简单一句话总结,就是 WS 是长连接,HTTP 是短连接。
逆向分析
WebSocket 流程分析
再次刷新页面,按下 F12 选择 ws 选项,可以看到有关 WebSocket 协议的发包:
进入堆栈查看,从第一个堆栈进入:
我们找到 initWebSocket 与 websocketonopen 的地方:
我们发现在调用 open 建立连接时,会向服务器发送一段 y.a.encryptDes(r()(t))
数据,所以我们构造这个 ws 请求就必须完成里面加密参数的生成。
参数加密分析
上面分析可知,ws 向服务器发送了一段密文数据,该数据是由 y.a.encryptDes
生成的,所以我们需要将 y 函数导出,经过分析 y 是一个 webpack 打包的一个模块:
在该处打上断点,重新刷新列表页,成功在此断住,还是进入 a 中将分发器扣下来,导出到 windows:
window = global;
!function(e) {
var f = window.webpackJsonp;
window.webpackJsonp = function(c, b, n) {
for (var r, t, o, i = 0, u = []; i < c.length; i++)
t = c[i],
a[t] && u.push(a[t][0]),
a[t] = 0;