-
-
[原创]看雪CTF2019Q1题目提交
-
发表于:
2019-3-8 00:51
6012
-
最近学校事情多,抽出的时间做的一道水题,漏洞倒是比较新颖(至少我打ctf没见过):malloc
,free
,new[]
,delete[]
的混用
起因是我之前在知乎回答过的一个问题在C++里是怎么实现delete[]的,写完之后我就想,因为内存布局并不一样(delete[]有一个记录大小的header),所以如果把C与C++的内存分配混用,是否能导致任意代码执行
然后拖了很久,终于在这次比赛做出了这道题。本来我是想直接用new char[]
的,但是发现对于基本类型,delete[]
和free
行为完全一致,具体可以跟一下跟进delete[]
,会发现几个got
表跳转跳到了free
。原因是基本类型不需要在delete[]
的时候调用析构函数。
然后我就试着写了一个有析构函数的类,一开始不是虚析构函数。我一开始的利用思路是利用house of spirit来把C++ object array的size当作堆块的chunk free
掉,或者把prev_size
当作size
free
掉。但是仔细一想这个+8
-8
一定会导致内存不对齐所以这样释放一定会abort
。虽然可以重载new
和delete
强制让他对齐,但是这不美观,有种为了pwn而写程序的感觉了,而我不喜欢这种题目。
所以就决定加了一个虚析构函数,可以在delete
一个malloc
出来的array的时候能够实现虚表劫持。但是搞了半天发现没法leak,所以自己加了一个leak的后门,这个逆向menu
函数的时候就能发现,所以不guessy。如果有哪个师傅能不用这个后门做出来请务必分享一下方法让我这个菜鸟学习一下。
简单起见PIE也没开,所以最后就基本已经很简单了:首先malloc然后直接free
第一次让我能控制堆中的某些数据,因为free
的时候不会清空内存数据(本来在delete[]
里是会的,在析构函数里清0了buffer,但是编译器给我优化掉了。。。),然后两次malloc
使得第二次malloc
能够让虚表够到我能控制的内存,最后delete[]
调用已经被劫持的虚析构函数。至于调用什么,name
一开始放main
和leak后门,然后先调用leak后门,再调用回main
,然后name
改成one gadget
,然后调用one gadget
。这里可能要注意,因为析构函数调用是从后往前调用的,所以先调用的要放在后面。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-3-13 17:58
被holing编辑
,原因: