5.4 堆溢出利用(上)——DWORD SHOOT

目录

一、预备知识

二、实验环境

三、实验代码

四、实验步骤


一、预备知识

        堆管理系统的三类操作:堆块分配、堆块释放和堆快合并归根结底都是对链表的修改。堆溢出利用的精髓就是用精心构造的数据溢出下一个堆块的块首,改写块首中的前向指针(flink)和后向指针(blink),然后在分配、释放、合并等操作发生时伺机获得一次向内存任意地址写入任意数据的机会。这种能够向内存任意地址写入任意数据的机会称之为“DWORD SHOOT”。

        通过DWORD SHOOT,攻击者可以劫持进程,运行shellcode,主要有如下情形:

点射目标(target)子弹(payload)改写后的结果
栈帧中的函数返回地址shellcode的起始地址函数返回时,跳去执行shellcode
栈帧中S.E.H句柄shellcode的起始地址异常发生时,跳去执行shellcode
重要函数调用地址shellcode的起始地址函数调用时,跳去执行shellcode

        举一个例子说明DWORD SHOOT究竟时如何发生的。将一个结点从双向链表中“卸下”的函数很可能是这样的:(参考数据结构)

int remove (ListNode * node) 
{ 
    node -> blink -> flink = node -> flink; 
    node -> flink -> blink = node -> blink; 
    return 0; 
}
        当堆溢出发生时,非法数据可以淹没下一个堆块的块首。这时,块首是可以被攻击者控制 的,即块 首中存放的前向指针( flink )和后向指针( blink )是可以被攻击者伪造的。当这个堆 块被从双向链表中“卸下”时, node -> blink -> flink = node -> flink 将把伪造的 flink 指针值写入伪造的 blink 所指的地址中去,从而发生 DWORD SHOOT。过程如下:
        注:图5.3.1为正常“拆卸”,图5.3.2为异常拆卸!!!

 

         !!!另外,请特别注意实际内存中的前向指针和后向指针示意图:(与数据结构中有一点点不一样,图中释放顺序为h1、h3、h4)

二、实验环境

        操作系统:Windows 2000 professional

        软件版本:原版OD(实时调试状态)、VC++6.0(release)

三、实验代码

#include <windows.h>

main()
{
	HLOCAL h1, h2,h3,h4,h5,h6; 
    HANDLE hp; 
    hp = HeapCreate(0,0x1000,0x10000); 
    h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); 
    h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); 
    h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); 
    h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); 
    h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); 
    h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);
	

	_asm int 3//used to break the process 
    //free the odd blocks to prevent coalesing 
    
    HeapFree(hp,0,h1); 
    HeapFree(hp,0,h3); 
    HeapFree(hp,0,h5); //now freelist[2] got 3 entries 
    //will allocate from freelist[2] which means unlink the last entry h5
    
    h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); 

    return 0;
}
        注意:
        (1 )程序首先创建了一个大小为 0x1000 的堆区,并从其中连续申请了 6 个大小为 8 字节
的堆块(加上块首实际上是 16 字节),是从初始的尾块中“切”下来的。
        (2)释放奇数次申请的堆块是为了防止堆块合并的发生。
        (3)三次释放结束后, freelist[2] 所标识的空表中应该链入了 3 个空闲堆块,它们依次是 h1 h3 h5 。 (链入尾部)
        (4)再次申请 8 字节的堆块,应该从 freelist[2] 所标识的空表中分配,这意味着最后一个堆
h5 被从空表中“拆下”。
        (5)如果我们手动修改 h5 块首中的指针,应该能够观察到 DWORD SHOOT 的发生。

四、实验步骤

        1、编译程序,直接进入OD界面,停在断点处:

         2、F8释放三次内存,手动更改H5的前向指针为0x44444444,后向指针为0x00000000.

         3、执行内存申请的指令,会发现编译器运行错误。

         根据:

node->blink->flink=node->flink
        无法将0x44444444写入0x00000000。

 
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值