You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows默认进程堆创建时触发断点并获取调用栈?

如何在Windows默认进程堆创建时触发断点?

我希望观察Windows默认进程堆的创建时机,设置断点并获取其创建时的调用栈,仅用于学习Windows内部机制及验证《Windows Internals》书中内容。

我使用如下简单HelloWorld程序进行调试:

#include <iostream>

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

我的调试步骤如下:

  1. 准备尽早启动的调试会话
    1. 启动WinDbg
    2. 用WinDbg启动HelloWorld程序
    3. 在初始断点执行命令:
      sxe cpr
      sxe ld *
      
    4. 执行.restart启动早期调试流程,此时仅加载了可执行文件
  2. 确认处于早期调试会话,此时ntdll尚未加载:
    0:000> lm
    start    end        module name
    00100000 00122000   HelloWorld   (deferred)  
    
  3. 设置未解析断点(因kernelbase尚未加载):
    bu kernelbase!heapcreate
    
  4. 确认当前无堆存在:
    1. 初始时执行!heap提示无效类型信息
    2. 执行g等待ntdll加载完成:
      0:000> g
      ModLoad: 77940000 77ae4000   ntdll.dll
      [...]
      
    3. 再次执行!heap确认无堆:
      0:000> !heap
              Heap Address      NT/Segment Heap
      

但在加载下一个模块KERNEL32.DLL后,堆已存在,而设置的断点并未触发(此时kernelbase尚未加载,断点未解析):

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

            012d0000              NT Heap

解决方法

问题出在断点目标选择错误:Windows默认进程堆并非通过kernelbase!HeapCreate创建,而是由ntdll在进程初始化阶段通过内部函数调用创建的。需针对ntdll中的堆创建相关函数设置未解析断点,具体步骤如下:

  1. 在仅加载HelloWorld.exe的早期调试会话中,执行以下命令设置未解析断点:
    bu ntdll!RtlCreateHeap
    
    若想捕获更底层的内核态调用,也可设置:
    bu ntdll!NtCreateHeap
    
  2. 执行g继续执行,当ntdll加载完成后,断点会自动解析并触发,此时即可捕获默认进程堆创建时的完整调用栈。

补充说明:进程默认堆的创建逻辑位于ntdll!LdrpInitializeProcess流程中,RtlCreateHeap是用户态封装函数,最终会调用NtCreateHeap进入内核态完成堆的实际创建。前者的调用栈更贴近用户态初始化流程,后者则能看到内核态调用的起点。

内容的提问来源于stack exchange,提问作者Thomas W.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 03:40:11