堆内存破坏检测实战--附完整调试过程
首先解釋一下,什么是堆內(nèi)存?
堆是一種常見的內(nèi)存管理器,應(yīng)用程序通過(guò)堆來(lái)動(dòng)態(tài)地分配和釋放內(nèi)存,通常使用堆的情況是無(wú)法預(yù)先知道所需要的內(nèi)存大小,或者申請(qǐng)內(nèi)存太大,無(wú)法通過(guò)棧內(nèi)存來(lái)自動(dòng)分配,下面讓我們?cè)賮?lái)看一段英文解釋。
A heap is a form of memory manager that an application can use when it needs to allocate?and free memory dynamically. Common situations that call for the use of a heap?are when the size of the memory needed is not known ahead of time and the size of?the memory is too large to neatly fit on the stack (automatic memory).
常見的情況是由于效率或特殊需求一個(gè)進(jìn)程中同時(shí)使用幾個(gè)堆,如下圖:
?
?
?
下面通過(guò)一個(gè)完整的demo來(lái)帶大家調(diào)試一個(gè)對(duì)破壞問(wèn)題,demo代碼如下:
?
#define SZ_MAX_LEN? 10 void?__cdecl?wmain?(int?argc,?WCHAR*?args[]){
????if(argc==2)
????{
????????wprintf(L"Press?any?key?to?start\n");
????????_getch();
????????DupString(args[1]);
????}
????else
????{
????????wprintf(L"Please?enter?a?string");
????}
}
BOOL?DupString(WCHAR*?psz)
{
????BOOL?bRet=FALSE;
????
????if(psz!=NULL)
????{
????????pszCopy=(WCHAR*)?HeapAlloc(GetProcessHeap(),?0,?SZ_MAX_LEN*sizeof(WCHAR));
????????if(pszCopy)
????????{
????????????wcscpy(pszCopy,?psz);
????????????wprintf(L"Copy?of?string:?%s",?pszCopy);
????????????HeapFree(GetProcessHeap(),?0,?pszCopy);
????????????bRet=TRUE;
????????}
????}
????return?bRet;
?
在應(yīng)用程序驗(yàn)證器下啟用普通頁(yè)堆,配置gflags,?運(yùn)行build出來(lái)的代碼,
輸入?yún)?shù)為:SolidmangoSolidmangoSolidmango
得到如下輸出:
?
CommandLine:?C:\WinXP.x86.chk\06overrun.exe?SolidmangoSolidmangoSolidmangoExecutable?search?path?is:?
ModLoad:?01000000?01005000???06overrun.exe
ModLoad:?7c900000?7c9b2000???ntdll.dll
AVRF:?06overrun.exe:?pid?0x120C:?flags?0x8044B026:?application?verifier?enabled
ModLoad:?5ad10000?5ad59000???C:\WINDOWS\System32\verifier.dll
ModLoad:?10000000?10029000???C:\WINDOWS\System32\vrfcore.dll
ModLoad:?003a0000?003dc000???C:\WINDOWS\System32\vfbasics.dll
ModLoad:?7c800000?7c8f6000???C:\WINDOWS\system32\kernel32.dll
AVRF:?verifier.dll?provider?initialized?for?06overrun.exe?with?flags?0x8044B026?
ModLoad:?77c10000?77c68000???C:\WINDOWS\system32\msvcrt.dll
(120c.1700):?Break?instruction?exception?-?code?80000003?(first?chance)
eax=00391ec4?ebx=7ffd8000?ecx=00000004?edx=00000010?esi=00391f98?edi=00391ec4
eip=7c90120e?esp=0006fb20?ebp=0006fc94?iopl=0?????????nv?up?ei?pl?nz?na?po?nc
cs=001b??ss=0023??ds=0023??es=0023??fs=003b??gs=0000?????????????efl=00000202
ntdll!DbgBreakPoint:
7c90120e?cc??????????????int?????3
0:000>?g0:000>?g
?
我們會(huì)看到一個(gè)訪問(wèn)違例,?繼續(xù)運(yùn)行得到如下輸出,說(shuō)明應(yīng)用程序驗(yàn)證器驗(yàn)證成功:
?
=======================================VERIFIER?STOP?00000008:?pid?0x120C:?Corrupted?heap?block.?
????00081000?:?Heap?handle?used?in?the?call.
????001E2B60?:?Heap?block?involved?in?the?operation.
????00000014?:?Size?of?the?heap?block.
????00000000?:?Reserved
=======================================
This?verifier?stop?is?not?continuable.?Process?will?be?terminated?
when?you?use?the?`go'?debugger?command.
=======================================
(120c.1700):?Break?instruction?exception?-?code?80000003?(first?chance)
eax=1000e848?ebx=1000cd44?ecx=00000001?edx=0006f939?esi=00000000?edi=1000e848
eip=7c90120e?esp=0006f9cc?ebp=0006fbd0?iopl=0?????????nv?up?ei?pl?nz?na?po?nc
cs=001b??ss=0023??ds=0023??es=0023??fs=003b??gs=0000?????????????efl=00000202
ntdll!DbgBreakPoint:
7c90120e?cc??????????????int?????3
?
繼續(xù)調(diào)試,此時(shí)我們已經(jīng)找到了出問(wèn)題的堆快,注意觀察上面的輸出中有這樣一條語(yǔ)句:
001E2B60?:?Heap?block?involved?in?the?operation,好的,讓我們看看這個(gè)堆塊里面是什么東西,
0:000>?dt?_DPH_BLOCK_INFORMATION?001E2B60-0x20ntdll!_DPH_BLOCK_INFORMATION
???+0x000?StartStamp???????:?0xabcdaaaa
???+0x004?Heap?????????????:?0x80081000?Void
???+0x008?RequestedSize????:?0x14
???+0x00c?ActualSize???????:?0x3c
???+0x010?FreeQueue????????:?_LIST_ENTRY?[?0x1e?-?0x0?]
???+0x010?TraceIndex???????:?0x1e
???+0x018?StackTrace???????:?0x00286c3c?Void
???+0x01c?EndStamp?????????:?0xdcbaaaaa
0:000>?dds?0x00286c3c?//callstack
00286c3c??abcdaaaa
00286c40??00000001
00286c44??00000007
00286c48??00000001
00286c4c??00000014
00286c50??00081000
00286c54??00000000
00286c58??00286c5c
00286c5c??7c94b244?ntdll!RtlAllocateHeapSlowly+0x44
00286c60??7c919c0c?ntdll!RtlAllocateHeap+0xe64
00286c64??003afd2c?vfbasics!AVrfpRtlAllocateHeap+0xb1
00286c68??010012f4?06overrun!DupString+0x24?[c:\awd\chapter6\overrun\overrun.cpp?@?41]
00286c6c??010012ab?06overrun!wmain+0x2b?[c:\awd\chapter6\overrun\overrun.cpp?@?28]
00286c70??010014b8?06overrun!__wmainCRTStartup+0x102?[d:\vistartm\base\crts\crtw32\dllstuff\crtexe.c?@?711]
00286c74??7c817077?kernel32!BaseProcessStart+0x23
00286c78??00000000
我們找到了出問(wèn)題的callstack:
0:000>?kb
ChildEBP?RetAddr??Args?to?Child??????????????
0006f9c8?10003b68?10062cb0?00000008?001e2b60?ntdll!DbgBreakPoint
0006fbd0?100078c9?1000c540?00000008?00081000?vrfcore!VerifierStopMessageEx+0x4d1
0006fbf4?7c96c06e?00000008?7c96c314?00081000?vrfcore!VfCoreRedirectedStopMessage+0x81
0006fc70?7c96d147?00081000?00000004?001e2b60?ntdll!RtlpDphReportCorruptedBlock+0x17c
0006fc94?7c96d34a?00081000?01000002?00000010?ntdll!RtlpDphNormalHeapFree+0x2e
0006fce4?7c9703eb?00080000?01000002?001e2b60?ntdll!RtlpDebugPageHeapFree+0x79
0006fd58?7c94bafc?00080000?01000002?001e2b60?ntdll!RtlDebugFreeHeap+0x2c
0006fe40?7c91a1ba?00080000?01000002?001e2b60?ntdll!RtlFreeHeapSlowly+0x37
0006ff10?003afe9c?00080000?00000000?001e2b60?ntdll!RtlFreeHeap+0xf9
0006ff58?01001340?00080000?00000000?00000014?vfbasics!AVrfpRtlFreeHeap+0xf8
0006ff70?010012ab?00a64692?0006ffc0?010014b8?06overrun!DupString+0x70?[c:\awd\chapter6\overrun\overrun.cpp?@?47]
0006ff7c?010014b8?00000002?00a64648?00a66e98?06overrun!wmain+0x2b?[c:\awd\chapter6\overrun\overrun.cpp?@?28]
0006ffc0?7c817077?00daf6ee?00daf784?7ffd8000?06overrun!__wmainCRTStartup+0x102?[d:\vistartm\base\crts\crtw32\dllstuff\crtexe.c?@?711]
0006fff0?00000000?010015f6?00000000?78746341?kernel32!BaseProcessStart+0x23
0:000>?du?00a64692?
00a64692??"SolidmangoSolidmangoSolidmango"
?
總結(jié):
原來(lái)是我們的參數(shù)破壞了了堆內(nèi)存,終于找到了根源,我們代碼中定義的堆的大小為10,而我們使用的時(shí)候,由于堆塊越界,破壞了堆塊的完整性,從而導(dǎo)致了crash的發(fā)生..
?
注:本文的附圖和代碼靈感源自網(wǎng)絡(luò),具體出處不詳,其他內(nèi)容為原創(chuàng)..
總結(jié)
以上是生活随笔為你收集整理的堆内存破坏检测实战--附完整调试过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Vue实现的滑动切换路由组件
- 下一篇: 区块链不适用的若干场景