SCTF跟着Koo师傅学习一波,记录一下学到的新东西
0x00 tcache的counts中存在的数据类型判断漏洞
在tcache涉及的数据结构中
1 | typedef struct tcache_perthread_struct |
counts定义为一个字符数组,记录每个tcache链中tcache的数量,在C语言中并没有char类型的常量(但是在C++中却有,字符常量都是char类型),其实是用int表示char,所以这个counts是一个有符号整型变量(-128~127)
在int_free函数中,把chunk放入tcache时,会判断待放入的tcache链是否小于mp_.tcache_count,一般为7
1 | if (tcache->counts[tc_idx] < mp_.tcache_count) |
查看源码,tcache_count是一个size_t类型的变量,也就是无符号长整型,那么上述的判断就变为 char型的counts 是否小于unsigned long int型的tcache_count ,就会把counts变量转为无符号的长整型进行比较
如果此时的counts大小为-1(0xff),被转成无符号的长整型后就变成255(0xff),那么就会使上述判断失效,在tcache的counts变成-1后,就会将之后free的chunk,放入unsortedbin中
有什么用呢?
当我们double free一个chunk后,tcache会的得到一个自循环的链表,tcache的counts是2
连续申请两次后,counts会变成0
再申请一次后,发现其counts变成了0xff,此时再次free该chunk,chunk就会进入unsortedbin中
0x01 程序分析
2.27版本的libc,保护全开
1 | Arch: amd64-64-little |
程序有两个功能:1. new 2. delete
delete时只能free最近使用的chunk,且free后没有清空指针
程序唯一难点是只能free4次
0x02 利用分析
1、double free tcache,patrial overwrite main_arena的地址,将tcache的fd指针指向 _IO_2_1_stdout_
文件流,修改flags和write_base,泄露libc地址
2、再次double free tcache,因为直接使用one_gadget因为环境变量问题,不能getshell,所以先将tcache的fd指针改写为 __realloc_hook
地址,因为__malloc_hook
和 __realloc_hook
地址相邻,所以改写 __realloc_hook
内容为one_gadget,改写 __malloc_hook
内容为 __libc_realloc
函数的地址,这样程序调malloc时,就会调用 __libc_realloc
,该函数抬栈(push操作)后,会调用 __realloc_hook
中的内容,也就是写入的gadgets
0x03 EXP
1 | from pwn import * |