Monday 6 January 2014

Debugging Heaps and Heap Internals Part 2

Heap Segments

Heap Segments refer to the Heap Segment of a program, much like when you have a Code Segment and a Data Segment, there is a Heap Segment which is for the Heap.


 Our heap blocks live within this heap segment. Each heap segment belongs to a certain running process. We can use the !heap -stat extension in WinDbg to gather more information about each segment.

The !heap -m extension will show us information about all the segment entries within the heap.

Debugging the Heap

We can use the !address -summary extension to gather a summary of what is consuming the address space of the process, and then check for any heap exhaustion.

Busy refers to the number of allocated heap blocks, let's examine further with the !heap -s extension, whilst omitting the address of the heap. This will give us general information about all the heaps within the process address space. Note, that the heap example I have been using, is the default process heap.

Using the s command with some parameters, we can search through the specified heap, and hopefully find some modules. We can then use the ln command with address of modules to find which .DLL or process is consuming all the heap memory.

The important part is the L? syntax which disables WinDbg's address range limit of 256MB. The -q specifies that we're searching for Quad Words (64-bits), we can change it to -d.

The other option is to use Global Flags, and then set the debugging features for a process.

Heap Tail Checking - Each heap block will be assigned with a signature, if a buffer overrun occurs and then damaged this signature, then the heap will report this error.


Heap Free Checking - Each freed heap block will be stored on the heap free list, each free block will then be filled with a certain pattern, and see pattern will be checked to see if there are any changes within the pattern. For example, process continuing to write data to that block when it's free.

Heap Parameter Checking - Checks parameters passed to any heap function calls.

Heap Validation - The heap is validated at each heap function call, and checks if it's still within a consistent state.

Additionally, if your going to use the HeapValidate function call, then ensure the _HEAP_ENTRY_BUSY flag has been set for that heap entry. We can view this in WinDbg with the !heap -i extension. You must set the context of the heap first.



Heap Tagging - Supports the specification of tags for heap allocations.

Page Heap

The next important debugging feature is the page heap. Page Heap is primarily used for detecting heap corruption, whereby a process writes upon it's allocation and thus corrupts the data within the heap. It can also occur as a result of a process writing to a free heap block.

Page Heap is managed by the Page Heap Manager, and there are Page Heap debugging features it provides: Full Page and Normal Page.

Normal Page Heap works by applying a pattern when the allocation has been freed. The pattern will be disrupted because of buffer overflows and writes to free blocks.

The Full Page Heap works differently, and should be used with caution, each allocation is given it's own page and adds a guard page at the end of allocation. This will produce a access violation, and the exact line of code which caused the error. This information can be gathered along with a stack trace using the dds command and the DPH_BLOCK_INFORMATION data structure.

You will need to apply the dds command to the StackTrace field.

You can debug for memory leaks in the heap with !heap -l extension.

References:

The Structure of the Page Heap Block

GFlags and PageHeap

Troubleshooting Memory Leaks With Just A Dump

1 comment: