堆溢出原理
1 编辑源文件
#include <windows.h>
#include <stdio.h>
int main(void)
{
char szStr[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
HANDLE hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0x1000, 0x4000);
getchar();
char * lpHeap = (char *)HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, 10);
printf("heap addr:0x%08x\r\n", lpHeap);
strcpy(lpHeap, szStr);
HeapFree(hHeap, HEAP_NO_SERIALIZE, lpHeap);
HeapDestroy(hHeap);
return 0;
}
2 调试
2.1 Windbg附加运行
0:001> g
(17dc.6c0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=006a05a8 ebx=00000000 ecx=41414141 edx=006a0590 esi=006a0588 edi=006a0000
eip=778d2e65 esp=0018fdf0 ebp=0018fed0 iopl=0 nv up ei ng nz na po cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010283
ntdll!RtlQueryPerformanceCounter+0x581:
778d2e65 8b19 mov ebx,dword ptr [ecx] ds:002b:41414141=????????
2.2 查看栈
0:000> k
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
0018fed0 778d2b65 ntdll!RtlQueryPerformanceCounter+0x581
0018fef0 76e614bd ntdll!RtlQueryPerformanceCounter+0x281
0018ff04 00401094 kernel32!HeapFree+0x14
0018ff48 00401327 _____+0x1094
0018ff88 76e6337a _____+0x1327
0018ff94 778d9882 kernel32!BaseThreadInitThunk+0x12
0018ffd4 778d9855 ntdll!RtlInitializeExceptionChain+0x63
0018ffec 00000000 ntdll!RtlInitializeExceptionChain+0x36
2.3 查看异常附近的反汇编
0:000> ub 00401094
_____+0x107f:
0040107f 6a01 push1
00401081 c1e902 shr ecx,2
00401084 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
00401086 8bc8 mov ecx,eax
00401088 55 push ebp
00401089 83e103 and ecx,3
0040108c f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
0040108e ff1504604000 calld word ptr [_____+0x6004 (00406004)]
2.4 重载在00401084处下断,运行
0:001> g
Breakpoint 0 hit
eax=00000021 ebx=00680590 ecx=00000008 edx=0008e3c8 esi=0018ff28 edi=00680590
eip=00401084 esp=0018ff10 ebp=00680000 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
_____+0x1084:
00401084 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:000> dd esi
0018ff28 41414141 41414141 41414141 41414141
0018ff38 41414141 41414141 41414141 41414141
0018ff48 00407000 00401327 00000001 00520fc8
0018ff58 00521030 00000000 00000000 7efde000
0018ff68 00000000 00000000 0018ff5c 00000000
0018ff78 0018ffc4 00402c50 004060b8 00000000
0018ff88 0018ff94 76e6337a 7efde000 0018ffd4
0018ff98 778d9882 7efde000 77d29e08 00000000
0:000> dd edi
00680590 006800c4 006800c4 00000000 00000000
006805a0 46102e99 00002cd0 006800c4 006800c4
006805b0 00000000 00000000 00000000 00000000
006805c0 00000000 00000000 00000000 00000000
006805d0 00000000 00000000 00000000 00000000
006805e0 00000000 00000000 00000000 00000000
006805f0 00000000 00000000 00000000 00000000
00680600 00000000 00000000 00000000 00000000
2.5 查询包含地址00680590的堆信息
0:000> !heap -p -a 00680590
address 00680590 found in
_HEAP @ 680000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
00680588 0003 0000 [00] 006805900 000a - (busy)
看到UserSize大小为0Ah
2.6 查看ecx的值
0:000> r ecx
ecx=00000008
2.7 计算拷贝数据大小
8 * 4 = 32 = 0x20
缓冲区只有0xA
造成溢出