⬢ DragonFlyBSD Kernel Audit
DF-3017 / rsp.py
← back to finding ↓ download raw
#!/usr/bin/env python3
"""Minimal GDB remote-serial-protocol client (no host gdb needed).
Usage: rsp.py <hex-cmd> [hex-cmd...]  e.g. rsp.py mfffff8008dab0f00,140
Also helpers: rsp.py regs
"""
import socket, sys, time

def rsp(cmd_bytes: bytes) -> bytes:
    s = socket.create_connection(("127.0.0.1", 1235), timeout=10)
    s.settimeout(2.0)
    # send packet
    pkt = b"$" + cmd_bytes + b"#"
    csum = sum(cmd_bytes) & 0xFF
    pkt += b"%02x" % csum
    s.sendall(pkt)
    # wait for '+'
    buf = b""
    while True:
        d = s.recv(4096)
        if not d:
            raise RuntimeError("no ack")
        buf += d
        if b"+" in buf:
            break
    # read reply
    out = b""
    while True:
        try:
            d = s.recv(65536)
        except socket.timeout:
            break
        if not d:
            break
        out += d
        if b"#" in out and out.rstrip().endswith((b"+",)):
            pass
        # reply format: $data#cs possibly followed by +
        if out.startswith(b"$") and b"#" in out[1:]:
            # check for stop-reply or end
            body = out[1:out.index(b"#", 1)]
            # ack
            try:
                s.sendall(b"+")
            except Exception:
                pass
            s.close()
            return body
    s.close()
    return out

def hexdump(addr, data):
    for i in range(0, len(data), 16):
        chunk = data[i:i+16]
        qwords = " ".join("%016x" % int.from_bytes(chunk[j:j+8][::-1] if False else chunk[j:j+8], "little") for j in range(0, len(chunk), 8))
        print("%016x: %s" % (addr + i, qwords))

def main():
    args = sys.argv[1:]
    if not args:
        return
    if args[0] == "regs":
        body = rsp(b"g")
        # x86-64 'g' packet: rax rbx rcx rdx rsi rdi rbp rsp ...
        names = ["rax","rbx","rcx","rdx","rsi","rdi","rbp","rsp","r8","r9",
                 "r10","r11","r12","r13","r14","r15","rip"]
        for i, n in enumerate(names):
            off = i * 16
            if off + 16 <= len(body):
                v = int.from_bytes(bytes.fromhex(body[off:off+16].decode()), "little")
                print("%-4s %016x" % (n, v))
        return
    if args[0].startswith("m"):
        addr_s, _, len_s = args[0][1:].partition(",")
        addr = int(addr_s, 16)
        length = int(len_s, 16)
        body = rsp(b"m%s,%s" % (addr_s.encode(), len_s.encode()))
        data = bytes.fromhex(body.decode())
        hexdump(addr, data)
        return
    for a in args:
        print(rsp(a.encode()).decode("utf-8", "replace"))

if __name__ == "__main__":
    main()