Windows 2000 SP4 内核调试初窥

本文介绍了使用WinDbg对Windows 2000 SP4进行内核调试的经验,包括如何查看_EPROCESS结构,理解ActiveProcessLinks链接表,以及设置断点观察KiRetireDpcList函数的调用。通过调试,揭示了系统在忙碌和空闲时如何处理DPC任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天又试了两个 Windows 版本。首先尝试的是虚拟机上安装的 Windows 2000 RTM,也是用 WinDbg 连接到它的 COM2 口的命名管道上进行调试(在 Virtual PC 上指定 COM2 为 \\.\pipe\nt5com2,并在 WinDbg 中连接它)。发现系统已经比昨天调试  NT 4 的情况要好了——系统已经能正常运行了(我猜测是 NT 4 也许要用它那个老版本的 i386kd.exe 才能正常调试,只是个猜测,但那个命令是否支持命名管道还是个疑问,所以放弃了)。但是,在 WinDbg 中 dt nt!_EPROCESS 仍然拿不到任何数据,依然是找不到符号。键入 lm 显示,WinDbg 已经从 Microsoft Symbol Server 上拿到对应的符号文件(PDB)。换用从 Microsoft 网站上下载到的 Windows 2000 RTM Symbol Package 并重新加载,依然没有 _EPROCESS。

然后,试着把 Windows 2000 RTM 升级到 SP4,再作试验。结果,试验成功。

此处先推荐一个网页:http://www.codeproject.com/Articles/7913/Debug-Tutorial-Part-6-Navigating-The-Kernel-Debugg

下面,我记录一下我初步认识 _EPROCESS(执行体进程,Executive Process)结构的一些经历。执行体进程结构是 Windows 执行体用来表示进程的结构。

1. !process 是个扩展命令。它有一个语法 !process 0 <Flags>。其中 <Flags> 可以是 0,表示只显示最基本的信息。!process 0 0 将列出所有进程的 _EPROCESS 结构的地址。
2. 随便抓一个进程,例如我们选择位于 0×81231580 地址(虚拟内存地址)的 sol.exe(Solitaire,纸牌,你懂的)。如果这个程序并没有运行的话,你可以先在 WinDbg 中键入 g,让系统运行,启动这个进程,然后再重新让 WinDbg break(打断执行)。

PROCESS 81231580  SessionId: 0  Cid: 0228    Peb: 7ffdf000  ParentCid: 0128
    DirBase: 07c6c000  ObjectTable: 81253108  TableSize:  23.
    Image: sol.exe

3. 使用 dt _EPROCESS 81231580 来查看它的 _EPROCESS 结构。_EPROCESS 结构很大,所以这里只列几个有趣的项:

nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
...
   +0x09c UniqueProcessId  : 0x00000228 
...
   +0x1b0 Peb              : 0x7ffdf000 _PEB
...
   +0x1fc ImageFileName    : [16]  "sol.exe"

4. 当我们知道结构中域的名字的时候,我们可以只列一个域。例如,dt _EPROCESS Pcb 81231580,即可列出 Pcb 域的内容。这里面每一行 + 右边的数字是结构中的偏移量(16 进制)。再右边是类型。可以看到,Pcb 是 _KPROCESS(内核进程)类型,所以如果对它的地址(即 81231580 + 000 = 81231580)显示 _KPROCESS,就能得到 _KPROCESS 结构的内容。键入:dt _KPROCESS 81231580。

5. ActiveProcessLinks 域是一个链接表。它是怎样的结构呢?我分析了一下,发现它有两个域。

   +0x0a0 ActiveProcessLinks : _LIST_ENTRY [ 0x8046e460 - 0x81245a80 ]

5.1 先计算基址加偏移量。

kd> dt _LIST_ENTRY 81231620
nt!_LIST_ENTRY
 [ 0x8046e460 - 0x81245a80 ]
   +0x000 Flink            : 0x8046e460 _LIST_ENTRY [ 0x814a71c0 - 0x81231620 ]
   +0x004 Blink            : 0x81245a80 _LIST_ENTRY [ 0x81231620 - 0x812496a0 ]

5.2 再查看它的内容。

kd> dt _LIST_ENTRY 81231620
nt!_LIST_ENTRY
 [ 0x8046e460 - 0x81245a80 ]
   +0x000 Flink            : 0x8046e460 _LIST_ENTRY [ 0x814a71c0 - 0x81231620 ]
   +0x004 Blink            : 0x81245a80 _LIST_ENTRY [ 0x81231620 - 0x812496a0 ]

5.3 可见,它等效于 C/C++ 中的结构体:

struct _LIST_ENTRY
{
    DWORD_PTR Flink;
    DWORD_PTR Blink;
};

5.4 其中,Flink 的值是 8046e460。Blink 是 81245a80。那么,它们到底链接到哪里呢?我仔细想了想,它的前后链接所指的地址上也是个 _LIST_ENTRY 结构。猜一下,后来发现果然猜中了:它链接的是 _EPROCESS 结构体中的 ActiveProcessLinks 域。也就是说,如果 81245a80 – a0,就是另一个 _EPROCESS 的地址。我们可以验证一下:

kd> ?? 0x81245a80 - 0xa0
unsigned int 0x812459e0
kd> dt _EPROCESS 812459e0
...
   +0x09c UniqueProcessId  : 0x000002f8 
...
   +0x1fc ImageFileName    : [16]  "internat.exe"
...

有趣的是 FLink 8046e460 – a0 如果显示它为 _EPROCESS 的话,看出来像是个空进程。可能是因为 sol.exe 是我最后启动的一个进程的缘故吧。

好了,时间有限,浅尝辙止,以后有机会继续。

====

第二次尝试:断点 KiRetireDpcList。该函数的任务是把等待处理的 DPC 任务交付给目标函数,让它们处理(若有讹误敬请指正)。客户机仍然是单 CPU 的。步骤:

1. 先在不设断点的情况下让系统运行起来。即使用 g 命令。
2. 然后在客户机内运行一个死循环程序。这个的做法就仁者见仁智者见智了。
3. WinDbg 内菜单 Debug -> Break。
4. 然后设置断点:

kd> bp nt!KiRetireDpcList
kd> g

5. 过一会儿就会运行到断点。再查看调用栈:

kd> kb
ChildEBP RetAddr  Args to Child              
f7423ff4 804042be be20fd44 00000000 00000000 nt!KiRetireDpcList
f7423ff8 be20fd44 00000000 00000000 00000000 nt!KiDispatchInterrupt+0x2a
WARNING: Frame IP not in any known module. Following frames may be wrong.
804042be 00000000 00000008 bb835275 00000128 0xbe20fd44

6. 多尝试几次。基本上都是这个位置。KiDispatchInterrupt 也许是在中断发生时把任务分发到实际的中断处理程序的这位。

7. 禁用断点。然后运行。

kd> bl
 0 e 80464ba4     0001 (0001) nt!KiRetireDpcList
kd> bd 0
kd> g

8. 在客户机内把死循环程序关闭。
9. 再使用 Debug -> Break 菜单项把机器中止。
10. 执行 be 0(启用断点)。再执行 g(运行)。
11. 然后会运行到断点。查看它的调用栈:

kd> kb
ChildEBP RetAddr  Args to Child              
80473b64 80464b6f 0000000e 00000000 00000000 nt!KiRetireDpcList
80473b68 00000000 00000000 00000000 00000000 nt!KiIdleLoop+0x26

结论:可见在忙碌时,KiRetireDpcList 是通过中断来调用的,而空闲时,KiRetireDpcList 是通过空闲线程来调用的。

鸣谢:潘老师,高老板,Mark Russinovich 博士,John Robbins 老师,我现在的经理,和许多帮助过我的人。


1,GHOST内核11.2/11.5及硬盘接口IDE/SATA任意切换,分区格式FAT/NTFS自动识别. 2,硬盘版特别适于无软驱/无光驱/无USB接口/无人值守的台式机/笔记本/服务器使用. 3,支持WIN7/WIN8/WIN10等新系统,以及GRUB4DOS菜单可引导本地Windows或ISO映像. 4,支持压缩/分卷及GHOST辅助性参数自定义,以满足光盘刻录和RAID等其它特殊需要. 5,安装快速,只需1-2分钟;卸载彻底,不留垃圾文件,安全绿色无公害. 6,不破坏系统原有结构,不向BIOS和硬盘保留扇区写入任何数据,无需划分隐藏分区. 7,WINDOWS下(鼠标)/开机菜单(方向键)/开机热键(K键)多种启动方案任由你选择. 8,安装程序即便被误删除,也可使用同一版本的光盘版/优盘版进行恢复. 9,一键备份系统的映像防止误删除处理,以保证不被误删除或病毒恶意破坏. 10,允许装机人员(网管/售后)通过设置限制功能,仅允许用户"恢复",不允许"备份". 11,界面友好,全中文操作,无需英语和计算机专业知识. 12,危险操作之前贴心提示,明明白白放心使用. 13,附带GHOST浏览器,能打开GHO映像,任意添加/删除/提取其中的文件. 14,映像导入/导出/移动等功能,便于GHO映像传播交流和多次/多系统备份. 15,密码设置功能,让多人共用一台电脑情况下,不被非法用户侵入. 16,多种引导/内存/版本模式,以兼容各种型号电脑,让特殊机型也能正常启动本软件. 17,诊断报告功能可自动收集系统信息,为问题回复及软件日后改进提供线索. 18,帮助文档,图文并茂,易学易会,网上论坛,在线答疑. 19,支持一键GHOST备份/恢复系统到U盘或移动硬盘. 20,附带"个人文件转移工具",再也不用担心恢复系统后"桌面"等文件丢失了.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值