-
-
[原创]看雪CTF2019Q2题目提交
-
2019-5-15 04:46
3507
-
0x00 概要
题目实现了一个多线程free
的功能,这道题目关键点在于多线程所导致的uint8_t
类型的整型溢出,进而导致double free。然后构造UAF泄漏Libc地址,再poison tcache写__free_hook
可getshell
。
0x01 漏洞点
这题比上次那题还要简单,灵感来源于上architecture课教授slides里面的一个pseudocode,大概长这样
if (myThreadId() == 0)
i = 0;
barrier();
// on each thread
while (true)
{
local_i = FetchAndAdd(&i);
if (local_i >= N) break; //integer overflow
C[local_i] = 0.5*(A[local_i] + B[local_i]);
}
barrier();
然后我就在想这个如果FetchAndAdd
函数能导致整型溢出的话,是否可以导致可利用的漏洞,于是就有了我这道题。
然后漏洞点在这里,代码跟上面的伪代码很像,只不过一些无关的东西删掉了。
void* free_thread(void* varg)
{
thread_arg* arg = (thread_arg*)varg;
uint8_t* i = &arg->iter;
volatile size_t idx;
while(true)
{
idx = __sync_fetch_and_add(i, 1);
if (idx >= arg->bound) //整型溢出
break;
if (data[idx])
free(data[idx]);
else
exit(-1);
}
return NULL;
}
当bound
的值很大的时候,比方说,删除范围254-255的时候,如果有两个线程,线程1free
了data[254]
,线程2255 >= 255
所以退出,而线程1这个时候__sync_fetch_and_add
溢出到0,这个时候会把0到254的所有elements又free
了一次,等于导致了double free。
0x02 利用
这里我稍微增加了一下难度,就是如果有空指针就会退出,所以得先把那些项都占满先。
然后注意,在线程中free
chunk时会加到那个线程自己的tcache,然后线程退出时这些chunks会被放回fastbin或者unsortedbin而不是主线程的tcache。所以把index 0设置为unsortedbin大小可以直接leak libc的地址。
然后因为所有indeces都被占满了,这样就没有能用的index可以做poison了,所以得先把他们clear掉,但是在那之前得把最顶上的chunk(这时是index 1)先拿出来(所以data[254]==data[1]
),方便到时候做poison利用。
然后用fastbin dup把0x70的fastbin污染了,创造出这种情况a -> b -> a
,但这个时候tcache也是满的,这个时候malloc
4个tcache可以创造出这种情况a -> b -> &__free_hook
,然后就可以写free hook执行system了。
不过有一点要注意,因为多线程,难免会有条件竞争,所以成功率并不是100%,不过也不低就是了。
环境libc2.27,md5=50390b2ae8aaa73c47745040f54e602f
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2019-6-24 18:22
被kanxue编辑
,原因: