DWORDSHOOT的攻击方法

DWORDSHOOT的攻击方法

本文由《0day安全软件漏洞分析》中的章节总结形成,作为一个笔记。
其实我开始看着书的时候没做啥笔记,但后来调试过程觉得堆块这块挺重要的就返回去把这一章的内容单独摘出来,并把一个叫做DWORDSHOOT的攻击方法作为深入理解的例子记了下来。
DWORDSHOOT的攻击方法

DWORDSHOOT的攻击方法

DWORDSHOOT的攻击方法

堆在内存中的数据结构形式如图,占用态和空闲状态可以由flag标志清楚的分辨。其中大小和前后指针的位置更是一目了然。可以说我们在堆溢出的分析就会由于如此清晰的结构图而变得简单不少。

下面我们来看一下攻击过程
核心原理就是通过堆栈的释放和分配过程溢出堆前后指针,从而控制任意内存地址未任意数据(前提是地址本身可以写)

DWORDSHOOT的攻击方法

如图中setp1.2所示。堆发生溢出,攻击者淹没了第二个堆块的块首,从而控制了其前后向指针的值。其实这里的有一点不形象了,因为前后向的指针都在块首,而不是像图里的画的一前一后。

DWORDSHOOT的攻击方法

最后
Int remove(ListNode * node)
{
node->blink->flink=node->flink;
node->flink->blink=node->blink;
}
通过如上结构的函数在分配堆的过程中出发代码。

当时学的时候,老觉得是似而非。怪怪的,后来看到一个仁兄的文字解释,很形象。如下:
1、双向链表上有a、b、c一共3个连续的堆块,a、b、c三者之间的实际物理地址可能相差很大,但是绝对不会三者之间无其他字节,如果无其他字节,那表示他们三个可以合并成一个物理连接起来的大块,堆管理系统很快会让他们三者搞基成一个大个子堆块,拆下来重新按照其尺寸重新链接到该去的链表位置去。。。而不会放纵其在链表上物理地址紧密链接的同时还分成3个堆块串联在链表上。

2、返回正题,拆下其中一个堆块b时,会产生a、c之间的空缺,导致a、c无法相互知晓。所以堆管理系统会在拆b时,把a和c缝缝补补,连在一起,成为新链表,等待下次拆分、合并等等。
而这个断掉块b过程之前,我们先通过字符串变量溢出,将字符串从其他块溢出到块b中,即覆盖了他的第9~16字节数据,效果就是改了他身上所保管的左、右邻居门牌号地址,一般就是右邻门牌号覆盖为shellcode入口地址,左邻门牌号覆盖为各种特殊地址,比如重要函数调用地址,栈帧中函数返回地址,栈帧中SEH的句柄。这样,在块b断下来时,他会把shellcode地址赋值到某个经常调用的函数的地址上,或栈帧中当前函数返回地址上,或栈帧中距离当前栈最近的SEH异常处理最近的那个句柄。

个人感觉这样清楚多了。