java-topology/tools/mc-bench/rcon.py
russell@unturf.com db29a08762 undefect. CWE-407 — 92 sites, 42 ecosystems
B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections.
Squash of 94 local commits onto remote master.
2026-03-26 19:48:18 -04:00

35 lines
1.3 KiB
Python

#!/usr/bin/env python3
"""Minimal RCON client for Minecraft server command injection."""
import socket, struct, sys, time
def rcon(host, port, password, command, timeout=10):
def packet(pid, ptype, body):
b = body.encode() + b'\x00\x00'
return struct.pack('<iii', 4 + 4 + len(b), pid, ptype) + b
def recv_packet(s):
hdr = b''
while len(hdr) < 4:
hdr += s.recv(4 - len(hdr))
length = struct.unpack('<i', hdr)[0]
data = b''
while len(data) < length:
data += s.recv(length - len(data))
return struct.unpack('<ii', data[:8])[0], struct.unpack('<ii', data[:8])[1], data[8:-2].decode('utf-8', errors='replace')
s = socket.socket()
s.settimeout(timeout)
s.connect((host, port))
s.send(packet(1, 3, password)) # auth
recv_packet(s)
s.send(packet(2, 2, command)) # command
_, _, resp = recv_packet(s)
s.close()
return resp
if __name__ == '__main__':
host = sys.argv[1] if len(sys.argv) > 1 else 'localhost'
port = int(sys.argv[2]) if len(sys.argv) > 2 else 25575
password = sys.argv[3] if len(sys.argv) > 3 else 'benchpass'
command = ' '.join(sys.argv[4:]) if len(sys.argv) > 4 else 'list'
print(rcon(host, port, password, command))