题目分享 children_tcache
链接:https://pan.baidu.com/s/1jARmxmGaoN_VADlb6m0D8A?pwd=ra0l
提取码:ra0l
参考博客:
tcache在pwn题中常见的利用姿势 - 先知社区 (aliyun.com)
开始:
这道题的具体写法我就不说了,主要是讲讲我这个新手从这道题里学到了什么。
首先一个off by null,通常咱都可以做到堆重叠,然后配合题目的输出函数打出比如像main_arena的地址之类的东西。这种思路就是去创建大于0x408大小的堆块,然后free掉,这样在bins里这个unsourtedbin就会指向main_arena固定偏移处,然后我们要想办法利用程序自带的输出函数把这个地址给打出来。这个一般就是常见的use after free,但是这种漏洞算是比较初级的了。
但是如果这个程序比较精明,把指针的free掉的时候清空了,这就需要好好利用这个off by null了,也就是利用这个off by null,去借助假的堆块把东西东西打出来,有时甚至能够double free(在2.27的glibc中直接double free的方法似乎已经不多见了,现在检查都很严格)。
那咋办呢?如何进行堆重叠实现这个呢?
tcache在pwn题中常见的利用姿势 - 先知社区 (aliyun.com)这个文章只讲了利用的手法,但是没有讲原理,接下来我就默认你看过文章了。
它的文章的这一步也许你会很好奇,为什么我中间要夹一个小堆块呢???
这是由于构造假chunk的时候,如果学过unlink这个攻击手法你应该会留意到
/* Take a chunk off a bin list. */
static void
unlink_chunk (mstate av, mchunkptr p)
{
//检查chunk的size和next_chunk的prev_size是否一致
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr (“corrupted size vs. prev_size”);
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
//检查fd和bk(双向链表完整性)
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr (“corrupted double-linked list”);
fd->bk = bk;
bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{
//检查largebin中next_size双向链表的完整性
if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p)
malloc_printerr (“corrupted double-linked list (not small)”);
if (fd->fd_nextsize == NULL)
{
if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd;
else
{
fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd;
}
}
else
{
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
}
}
}
以上是unlink的源码,可以注意到,进行unlink操作的时候,构造假的fd,bk指针还不够呢,它还要去检查chunk的size和next_chunk的prev_size是否一致
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr (“corrupted size vs. prev_size”);
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
但是很多程序其实我们控制不了chunk的pre_size的大小,比如像这题有个 /x00的截断,让我们不好去控制next chunk的pre_size位,那咋办?
解决方法就是去中间加一个小堆块。因为fastbin和tcahche的next_chunk貌似都没有pre_size位,这里我们做一个实验看看
下面是用2.27版本,去实践一个tcache是不是像我们所说的那样。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* ptr1=malloc(0x500);
char* ptr2=malloc(0x20);
char* ptr3=malloc(0x500);
free(ptr1);
free(ptr2);
return 0;
}
ptr3指向的堆块是为了怕unsortedbin被topchunk合并。
我们执行到把两个指针都释放掉。
可以看到我们的实验是正确的,tecache并没有在next_chunk有属于自己的pre_size位,这一点可以作为被/x00截断无法构造假的pre_size的一个新思路。
再看看fastbin是如何的(暴力点填满tcache就是fastbin了)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* ptr1=malloc(0x500);
char* ptr2=malloc(0x70);
char* ptr3=malloc(0x70);
char* ptr4=malloc(0x70);
char* ptr5=malloc(0x70);
char* ptr6=malloc(0x70);
char* ptr7=malloc(0x70);
char* ptr8=malloc(0x70);
char* ptr9=malloc(0x70);
char* ptr10=malloc(0x500);
free(ptr1);
free(ptr2);
free(ptr3);
free(ptr4);
free(ptr5);
free(ptr6);
free(ptr7);
free(ptr8);
free(ptr9);
return 0;
}
可以看到依然如此,因此fastbin和tcache在这一点上都有相同的性质。
ok,希望今天这个有对大家的学习有一点帮助。