

前段时间忽然对内核调试器实现原来发生了兴趣,于是简单分析了一下当前windows下主流内核调试器原理,并模仿原理自己也写了个极其简单的调试器:)
WinDBG
WinDBG和用户调试器一点很大不同是内核调试器在一台机器上启动,通过串口调试另一个相联系的以Debug方式启动的系统,这个系统可以是虚拟机上的系统,也可以是另一台机器上的系统(这只是微软推荐和实现的方法,其实象SoftICE这类内核调试器可以实现单机调试)。很多人认为主要功能都是在WinDBG里实现,事实上并不是那么一回事,windows已经把内核调试的机制集成进了内核,WinDBG、kd之类的内核调试器要做的仅仅是通过串行发送特定格式数据包来进行联系,比如中断系统、下断点、显示内存数据等等。然后把收到的数据包经过WinDBG处理显示出来。
在进一步介绍WinDBG之前,先介绍两个函数:KdpTrace、KdpStub,我在《windows异常处理流程》一文里简单提过这两个函数。现在再提一下,当异常发生于内核态下,会调用KiDebugRoutine两次,异常发生于用户态下,会调用KiDebugRoutine一次,而且第一次调用都是刚开始处理异常的时候。
当WinDBG未被加载时KiDebugRoutine为KdpStub,处理也很简单,主要是对由int 0x2d引起的异常如DbgPrint、DbgPrompt、加载卸载SYMBOLS(关于int 0x2d引起的异常将在后面详细介绍)等,把Context.Eip加1,跳过int 0x2d后面跟着的int 0x3指令。