分析“微信小程序游戏”并用python脚本自动登录领取所有默认奖励

【注意:此文章为博主原创文章!转载需注意,请带原文链接,至少也要是txt格式!】
wireshark 抓包https \ wss
在开始之前,首先你需要明白如何通过wireshark 抓包 https \ wss 并解析其明文方法,因为文中使用的就是wireshark方法。
wss websocket数据包分析
这里直接从头到尾进行抓包登录,因为已经详细梳理过,所以很多步骤可以直接略过的。例如游戏选区什么的。
所以直接可以从开始界面进行真正的逐步分析。
如图所示,第一步建立了一个websocket连接,地址是:https://wss-bxxxo-yxxs.fxxxxngame.net:31052/
然后紧接着就进行了登录,但是并非websocket登录,而是一个post的网页登录请求。请求是 https://bxxxo-yxx.fxxxxgame.net/game/login.php?ac=212342&sid=8123457&appid=wx0123456789f
通过分析发现sid=8123457应该是游戏的服务区,ac=212342疑似是角色ID,appid=wx0123456789f它是微信的openid,具备唯一属性,估计在这个游戏里应该起到身份校验的密码作用。
不过这些都不是重点,在这个请求之后就出现了大量的websocket数据包,具体如下:
具体To server的代码如下:
\x00\xe6\x009\x00\r812347-212342\x00\x00\x00\x00\x00\x00\x00\x02cn\x00\x02CN\x00\r101.201.214.131\x00\xb8{"appid":"wx0123456789f","pf":"wx","pfkey":"","zoneid":0,"serverid":812347,"openid":212342,"openkey":"","phpChanelID":"","platform":2,"gdt_vid":"","weixinadinfo":"","embedgame":0}
虽然里面有部分数据,如\x00\xe6\x009\x00\r
这个不好分析,但是还是能明显看出一些格式。如812347-212342
代表游戏服务区-角色ID
,后门接着cn
、CN
,然后是IP:101.201.214.131
,在然后是一个json数据{"appid":"wx0123456789f","pf":"wx","pfkey":"","zoneid":0,"serverid":812347,"openid":212342,"openkey":"","phpChanelID":"","platform":2,"gdt_vid":"","weixinadinfo":"","embedgame":0}
这个是第一个To server的数据包,紧接着有一次发送到服务端一个数据包,具体如下000000db
,如图:
然后剩下就是服务端返回,返回了很多很多数据,To client如下图:
下一步就是点游戏里的每个功能,然后发送对应的数据包,然后服务端回包。
整体看下来数据属于未加密(或半加密)状态,因为里面很多空字符并不好理解在服务端如何去转换这些数据。也只能通过表面做大致猜测。
python 复写发送wss websocket数据包
下一步可以尝试用python写一下自动登录脚本,然后根据点击功能提交的数据包然后写出对应的操作。
写python脚本前需要先看一下此游戏websocket数据传输具体的数据包,如图:
这里其实有一个重点,就是Opcode
它对应的值是0010
(二进制),对应十六进制就是%x2
,其实也有提示Binary
也就是说,传输的所有数据包都是以十六进制字节形式传输。
这里针对WebSocket 协议中的操作码(Opcode)的含义做一下解读:
操作码占据了 WebSocket 消息头中的 4 个比特位,用来定义“负载数据”(Payload data)的解释方式。如果接收到未知的操作码,接收端必须关闭 WebSocket 连接。以下是已定义的操作码:
- %x0:表示一个继续帧(Continuation frame)
- %x1:表示一个文本帧(Text frame)
- %x2:表示一个二进制帧(Binary frame)
- %x3-7:保留给未来的非控制帧
- %x8:表示一个连接关闭帧(Connection close frame)
- %x9:表示一个 Ping 帧(Ping frame)
- %xA:表示一个 Pong 帧(Pong frame)
- %xB-F:保留给未来的控制帧
换句话说,操作码告诉接收端如何解释传输的数据。例如,如果操作码为 %x1,那么接收端会将负载数据解释为文本数据。如果操作码为 %x8,那么接收端会将其视为关闭连接的指令。
。
下一步就是开始正式写脚本,首先通过wirshark获取到的数据包如下:
E7 81 B5 E5 85 94 E7 AC A6 02 00 28 E4 BB 8E E4 BB A5 E4 B8
8A E5 9F BA E7 A1 80 E5 B1 9E E6 80 A7 E4 B8 AD E9 9A 8F E6
9C BA E8 8E B7 E5 BE 97 31 E6 9D A1 00 25 3C 62 72 2F 3E 3C
62 72 2F 3E E8 AF A5 E5 93 81 E8 B4 A8 E6 97 A0 E6 B3 95 E6
90 BA E5 B8 A6 E6 8A 80 E8 83 BD 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 01 00 01 38 81 00 00 00 01 00 01 00 00
E7 AC A6 02 00 28 E4 BB 8E E4 BB A5 E4 B8 8A E5 9F BA E7 A1
80 E5 B1 9E E6 80 A7 E4 B8 AD E9 9A 8F E6 9C BA E8 8E B7 E5
BE 97 31 E6 9D A1 00 25 3C 62 72 2F 3E 3C 62 72 2F 3E E8 AF
A5 E5 93 81 E8 B4 A8 E6 97 A0 E6 B3 95 E6
首先要把这个数据中的空格进行替换hex_data.replace(" ", "")
替换之后还需要进行一下字节转换,这里推荐使用bytes.fromhex()
具体原因查看“bytes.fromhex() 与 binascii.unhexlify() 的区别”。数据已经转换完剩下就是提交了,在使用ws.send()
一定需要注意,加入opcode
参数,根据上面所说,它的值对应的就是websocket.ABNF.OPCODE_BINARY
,所以整体就是ws.send(date, opcode=websocket.ABNF.OPCODE_BINARY)
。
到此基本也就完结了。
下面给出部分代码如下:
import asyncio
import websockets
async def send_data(data, uri):
async with websockets.connect(uri) as websocket:
await websocket.send(data, opcode=websocket.ABNF.OPCODE_BINARY)
print(f"Data sent: {data}")
async def main():
uri = "ws://example.com/ws" # 替换成实际的 WebSocket 地址
hex_data = "E7 81 B5 E5 85 94 E7 AC A6 02 00 28 E4 BB 8E E4 BB A5 E4 B8 8A E5 9F BA E7 A1 80 E5 B1 9E E6 80 A7 E4 B8 AD E9 9A 8F E6 9C BA E8 8E B7 E5 BE 97 31 E6 9D A1 00 25 3C 62 72 2F 3E 3C 62 72 2F 3E E8 AF A5 E5 93 81 E8 B4 A8 E6 97 A0 "
hex_data = hex_data.replace(" ", "") # 去除空格
data = bytes.fromhex(hex_data)
await send_data(data, uri)
asyncio.run(main())
其实下一步可以比较多的方式来研究研究这个游戏的漏洞。
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏