pwn中利用off by null的一个思路,构造假chunk的难以触及pre_size咋整

题目分享 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)这个文章只讲了利用的手法,但是没有讲原理,接下来我就默认你看过文章了。

pwn中利用off by null的一个思路,构造假chunk的难以触及pre_size咋整_第1张图片

它的文章的这一步也许你会很好奇,为什么我中间要夹一个小堆块呢???

这是由于构造假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位,那咋办?
pwn中利用off by null的一个思路,构造假chunk的难以触及pre_size咋整_第2张图片

解决方法就是去中间加一个小堆块。因为fastbin和tcahche的next_chunk貌似都没有pre_size位,这里我们做一个实验看看
下面是用2.27版本,去实践一个tcache是不是像我们所说的那样。

#include 
#include 

int main()
{
	char* ptr1=malloc(0x500);
	char* ptr2=malloc(0x20);
	char* ptr3=malloc(0x500);
	free(ptr1);
	free(ptr2);
	return 0;
}

ptr3指向的堆块是为了怕unsortedbin被topchunk合并。
我们执行到把两个指针都释放掉。
pwn中利用off by null的一个思路,构造假chunk的难以触及pre_size咋整_第3张图片
 可以看到我们的实验是正确的,tecache并没有在next_chunk有属于自己的pre_size位,这一点可以作为被/x00截断无法构造假的pre_size的一个新思路。

再看看fastbin是如何的(暴力点填满tcache就是fastbin了)

#include 
#include 

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;
}

pwn中利用off by null的一个思路,构造假chunk的难以触及pre_size咋整_第4张图片 可以看到依然如此,因此fastbin和tcache在这一点上都有相同的性质。

ok,希望今天这个有对大家的学习有一点帮助。

 

 

 

 

 

你可能感兴趣的:(链表,数据结构,pwn,堆漏洞利用)