Heap issues
Windows split the VA space into several parts, one important part is Heaps.
Instead of put the local variables in Stacks, we often allocate the memory in Heaps, use it incorrectly or maybe forget to release it, that's humanity - make mistakes.
Generally there are two kinds of mistakes: Heap corruption and Heap leak
Heap corruptions
================================
use a free block
double free
cross-heap free
random pointer free
buffer over-run
random memory corruption
miscellaneous locking issues
Heap leak
================================
forget to do release the seat...
<><><>
Heap system contains several important structures:
0:018> dt ntdll!_HEAP
+0x000 Entry : _HEAP_ENTRY
+0x008 Signature : Uint4B <<<<< 0xeeffeeff
+0x00c Flags : Uint4B
+0x010 ForceFlags : Uint4B
+0x014 VirtualMemoryThreshold : Uint4B
+0x018 SegmentReserve : Uint4B
+0x01c SegmentCommit : Uint4B
+0x020 DeCommitFreeBlockThreshold : Uint4B
+0x024 DeCommitTotalFreeThreshold : Uint4B
+0x028 TotalFreeSize : Uint4B
+0x02c MaximumAllocationSize : Uint4B
+0x030 ProcessHeapsListIndex : Uint2B
+0x032 HeaderValidateLength : Uint2B
+0x034 HeaderValidateCopy : Ptr32 Void
+0x038 NextAvailableTagIndex : Uint2B
+0x03a MaximumTagIndex : Uint2B
+0x03c TagEntries : Ptr32 _HEAP_TAG_ENTRY
+0x040 UCRSegments : Ptr32 _HEAP_UCR_SEGMENT
+0x044 UnusedUnCommittedRanges : Ptr32 _HEAP_UNCOMMMTTED_RANGE
+0x048 AlignRound : Uint4B
+0x04c AlignMask : Uint4B
+0x050 VirtualAllocdBlocks : _LIST_ENTRY
+0x058 Segments : [64] Ptr32 _HEAP_SEGMENT
+0x158 u : __unnamed
+0x168 u2 : __unnamed
+0x16a AllocatorBackTraceIndex : Uint2B
+0x16c NonDedicatedListLength : Uint4B
+0x170 LargeBlocksIndex : Ptr32 Void
+0x174 PseudoTagEntries : Ptr32 _HEAP_PSEUDO_TAG_ENTRY
+0x178 FreeLists : [128] _LIST_ENTRY <<<<< 1024/8==128
+0x578 LockVariable : Ptr32 _HEAP_LOCK
+0x57c CommitRoutine : Ptr32
+0x580 FrontEndHeap : Ptr32 Void
+0x584 FrontHeapLockCount : Uint2B
+0x586 FrontEndHeapType : UChar
+0x587 LastSegmentIndex : UChar
ntdll!_HEAP_SEGMENT
+0x000 Entry : _HEAP_ENTRY
+0x008 Signature : Uint4B
+0x00c Flags : Uint4B
+0x010 Heap : Ptr32 _HEAP
+0x014 LargestUnCommittedRange : Uint4B
+0x018 BaseAddress : Ptr32 Void
+0x01c NumberOfPages : Uint4B
+0x020 FirstEntry : Ptr32 _HEAP_ENTRY
+0x024 LastValidEntry : Ptr32 _HEAP_ENTRY
+0x028 NumberOfUnCommittedPages : Uint4B
+0x02c NumberOfUnCommittedRanges : Uint4B
+0x030 UnCommittedRanges : Ptr32 _HEAP_UNCOMMMTTED_RANGE
+0x034 AllocatorBackTraceIndex : Uint2B
+0x036 Reserved : Uint2B
+0x038 LastEntryInSegment : Ptr32 _HEAP_ENTRY
ntdll!_HEAP_ENTRY
+0x000 Size : Uint2B <<<<< for direct chain, Size+basePoint = next entry
+0x002 PreviousSize : Uint2B <<<<< for reverse chain, basePoint-PreviousSize = previous entry
+0x000 SubSegmentCode : Ptr32 Void
+0x004 SmallTagIndex : UChar
+0x005 Flags : UChar <<<<< flags
+0x006 UnusedBytes : UChar
+0x007 SegmentIndex : UChar
ntdll!_HEAP_FREE_ENTRY
... _HEAP_ENTRY
+0x008 FreeList : _LIST_ENTRY <<<<< point to next _LIST_ENTRY
About the flags:
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
Do something real:
0:006> !heap -s
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
00150000 00000002 1024 480 480 11 2 1 0 0 L
00250000 00001002 64 24 24 3 1 1 0 0 L
00260000 00008000 64 12 12 10 1 1 0 0
00390000 00000002 64 8 8 0 0 1 0 0 L
00030000 00001002 1088 232 332 31 2 2 0 0 L
003b0000 00001002 64 64 64 1 1 0 0 0 L
00900000 00001002 256 12 12 4 1 1 0 0 L
00940000 00001002 1024 1024 1024 1016 2 0 0 0 L
00a50000 00001002 64 16 16 1 1 1 0 0 L
00a60000 00001002 64 16 16 0 0 1 0 0 L
00ab0000 00001002 256 12 12 4 1 1 0 0 L
00f60000 00001002 64 28 28 3 1 1 0 0 L
00f70000 00001002 64 24 24 5 1 1 0 0 L
01030000 00001002 64 16 16 3 1 1 0 0 L
01140000 00001002 64 24 24 3 1 1 0 0 L
01a90000 00001002 4096 4096 4096 4088 9 0 0 0 L
External fragmentation 99 % (9 free blocks)
01150000 00001002 256 12 12 4 1 1 0 0 L
01190000 00001002 256 12 12 4 1 1 0 0 L
01ea0000 00000002 1024 24 24 3 1 1 0 0 L
01220000 00001002 64 16 16 0 0 1 0 0 L
-----------------------------------------------------------------------------
0:006> !heap -v 00030000
Index Address Name Debugging options enabled
5: 00030000
Segment at 00030000 to 00040000 (00010000 bytes committed)
Segment at 020a0000 to 021a0000 (0002a000 bytes committed)
Flags: 00001002
ForceFlags: 00000000
Granularity: 8 bytes
Segment Reserve: 00200000
Segment Commit: 00002000
DeCommit Block Thres: 00000200
DeCommit Total Thres: 00002000
Total Free Size: 00000fb5
Max. Allocation Size: 7ffdefff
Lock Variable at: 00030608
Next TagIndex: 0000
Maximum TagIndex: 0000
Tag Entries: 00000000
PsuedoTag Entries: 00000000
Virtual Alloc List: 00030050
UCR FreeList: 000305a8
FreeList Usage: 00000004 00000000 00000000 00000000
FreeList[ 00 ] at 00030178: 020a0048 . 0003d468 (2 blocks)
FreeList[ 02 ] at 00030188: 020e2ff8 . 000344d8 (5 blocks)
00030178 point to the _LIST_ENTRY, so we need to decrease 8 offset to dump the _HEAP_ENTRY (_HEAP_FREE_ENTRY)
0:006> dt _HEAP_FREE_ENTRY 00030178-8
ntdll!_HEAP_FREE_ENTRY
+0x000 Size : 0
+0x002 PreviousSize : 0
+0x000 SubSegmentCode : (null)
+0x004 SmallTagIndex : 0 ''
+0x005 Flags : 0 ''
+0x006 UnusedBytes : 0 ''
+0x007 SegmentIndex : 0 ''
+0x008 FreeList : _LIST_ENTRY [ 0x3d468 - 0x20a0048 ]
0:006> dt _HEAP_FREE_ENTRY 0x3d468-8
ntdll!_HEAP_FREE_ENTRY
+0x000 Size : 0x1b3
+0x002 PreviousSize : 0x12
+0x000 SubSegmentCode : 0x001201b3
+0x004 SmallTagIndex : 0x61 'a'
+0x005 Flags : 0 ''
+0x006 UnusedBytes : 0x73 's'
+0x007 SegmentIndex : 0 ''
+0x008 FreeList : _LIST_ENTRY [ 0x20a0048 - 0x30178 ]
0:006> dt _HEAP_FREE_ENTRY 0x20a0048-8
ntdll!_HEAP_FREE_ENTRY
+0x000 Size : 0xdf8
+0x002 PreviousSize : 8
+0x000 SubSegmentCode : 0x00080df8
+0x004 SmallTagIndex : 0xbb ''
+0x005 Flags : 0x10 '' <<<<< last entry
+0x006 UnusedBytes : 0xc ''
+0x007 SegmentIndex : 0x1 ''
+0x008 FreeList : _LIST_ENTRY [ 0x30178 - 0x3d468 ]
it is a circle :) then, let's try to verify the former and latter entry via Size and PreviousSize offset.
0x3d468-8=0x3d460
next entry: 0x3d460 + 0x1b3*8 = 0003e1f8
previous entry: 0x3d460 - 0x12*8 = 0003d3d0
0:006> dt _HEAP_ENTRY 0003e1f8
ntdll!_HEAP_ENTRY
+0x000 Size : 0x22
+0x002 PreviousSize : 0x1b3
+0x000 SubSegmentCode : 0x01b30022
+0x004 SmallTagIndex : 0x8c ''
+0x005 Flags : 0x1 '' <<<<< busy
+0x006 UnusedBytes : 0xc ''
+0x007 SegmentIndex : 0 ''
0:006> dt _HEAP_ENTRY 0003d3d0
ntdll!_HEAP_ENTRY
+0x000 Size : 0x12
+0x002 PreviousSize : 3
+0x000 SubSegmentCode : 0x00030012
+0x004 SmallTagIndex : 0xc9 ''
+0x005 Flags : 0x1 '' <<<<< busy
+0x006 UnusedBytes : 0x8 ''
+0x007 SegmentIndex : 0 ''
When writing data into a free block, it may break the _HEAP_ENTRY->FreeList structure.
When buffer overrun into the next block, it may break the _HEAP_ENTRY whole structure.
<><><>
To enable pageheap to check these heap corruption issues:
"gflags.exe -p APPLICATION_NAME /enable /full /decommit"
https://support.microsoft.com/kb/286470
It will add the NO_ACCESS page after one block.
To troubleshoot the memory/heap leak issue, use command: !heap -l or LeakDiag
Comments
Anonymous
January 01, 2003
thanksAnonymous
February 29, 2008
FrRus2 r u crazzy? I told u! I can't read!Anonymous
March 01, 2008
TJAwZJ r u crazzy? I told u! I can't read!Anonymous
March 06, 2008
A7nXXk r u crazzy? I told u! I can't read, man!Anonymous
March 06, 2008
ulpLM5 r u crazzy? I told u! I can't read!Anonymous
March 07, 2008
WsW0uY r u crazzy? I told u! I can't read!Anonymous
March 07, 2008
wk4FUS r u crazzy? I told u! I can't read!Anonymous
March 07, 2008
i2gWs3 r u crazzy? I told u! I can't read!Anonymous
March 07, 2008
FyiwEu r u crazzy? I told u! I can't read!Anonymous
March 08, 2008
SVOZxt r u crazzy? I told u! I can't read!Anonymous
March 08, 2008
ZnOXcl r u crazzy? I told u! I can't read!