c++windowsheap-memorywindbginternals

Observing the default process heap getting created (breakpoint on heap creation)


I want to observe when the default process heap gets created, i.e. have a breakpoint and get the callstack of the creation. This has no practical background. I just want to understand the Windows internals and explore stuff written in the Windows Internals book.

I am trying this with a simple Hello World application:

#include <iostream>

int main()
{
    std::cout << "Hello World!\n";
}

My debugging procedure is:

  1. Preparing a debug session that starts as soon as possible
    1. Start WinDbg
    2. Launch the HelloWorld application with WinDbg
    3. At the initial breakpoint, run the following commands:
      sxe cpr
      sxe ld *
      
    4. Start the early debug procedure. This will break when only the executable was loaded.
      .restart
      
  2. Confirm that I am in an early debug session. Not even ntdll is present at that point.
    0:000> lm
    start    end        module name
    00100000 00122000   HelloWorld   (deferred)  
    
  3. Set a breakpoint for heap creation. It must be unresolved, because kernelbase was not loaded yet.
    bu kernelbase!heapcreate
    
  4. Confirm that no heaps are present.
    1. Initially, we don't know for sure, because !heap may just not work at all.
      0:000> !heap
      Invalid type information
      
    2. Wait until ntdll is loaded. (We have set sxe ld *)
      0:000> g
      ModLoad: 77940000 77ae4000   ntdll.dll
      [...]
      
    3. Confirm that no heaps are present.
      0:000> !heap
              Heap Address      NT/Segment Heap
      

However, with the next loaded module, there already is a heap, even though the breakpoint wasn't hit (and kernelbase wasn't even loaded, so it isn't even resolved):

0:000> g
ModLoad: 76540000 76630000   C:\Windows\SysWOW64\KERNEL32.DLL
[...]
0:000> !heap
        Heap Address      NT/Segment Heap

            012d0000              NT Heap

How would I break when the default process heap gets created?


Solution

  • The breakpoint needs to be set on ntdll!RtlCreateHeap:

    0:000> .restart
    [...]
    
    0:000> g
    ModLoad: 77940000 77ae4000   ntdll.dll
    [...]
    
    0:000> !heap
            Heap Address      NT/Segment Heap
    
    0:000> g
    Breakpoint 0 hit
    [...]
    
    0:000> k
     # ChildEBP RetAddr      
    00 009bf588 779f2fdf     ntdll!RtlCreateHeap
    01 009bf63c 779eac70     ntdll!LdrpInitializeProcessHeap+0x1b0
    02 009bf8a4 779a6a31     ntdll!LdrpInitializeProcess+0x85c
    03 009bf8fc 779a6921     ntdll!_LdrpInitialize+0xba
    04 009bf908 00000000     ntdll!LdrInitializeThunk+0x11
    
    0:000> lm
    start    end        module name
    00100000 00122000   HelloWorld   (deferred)             
    77940000 77ae4000   ntdll      (pdb symbols) [...]
    
    0:000> gu
    [...]
    ntdll!LdrpInitializeProcessHeap+0x1b0:
    [...]
    
    0:000> !heap
            Heap Address      NT/Segment Heap
    
                00fc0000              NT Heap
    

    The callstack confirms that this is the default process heap.