31(53)---windows internals mark david alex

内核调试
内核调试,指的是检查内核数据结构并且跟踪内核函数的执行。这是了解windows内部机制的一种有用方式。通过这种方式,可以得到其他工具所不能显示的内部系统信息,以便更清楚的了解内核代码流程。
在介绍调试内核的各种方法之前,首先介绍一下必须的一些文件。
内核调试符号
符号由链接器生成,包含了函数,变量的名字和数据结构的定义。调试器依赖符号来引用和显示名字。符号一般不会和二进制映像文件一起显示,因为它对于运行代码来说不是必须的。这种分离存储机制可以让二进制更小,更快,但这也同时意味着你必须保证调试器在调试时必须能够访问正确的符号。
利用任何工具来检查windows内核数据结构(进程列表,线程块,驱动程序列表,内存使用情况等)时,必须至少有ntoskrnl.exe的符号。(第二章有详细描述)。符号必须和exe匹配。如果安装了windows服务包或者通过热修补更新了内核,必须获取对应的符号。
为不同的windows版本安装符号是比较容易的,但是热补丁对应的符号却不一定总有。获取符号的最简单办法是以下面的语法使用微软符号服务器。
它代表了从网络符号服务器下载,并且本地缓存在c:\symbols.
进一步信息可参考调试工具的帮助文件或者 http://msdn.microsoft.com/en-us/windows/hardware/gg462988.aspx
windows调试工具集合
windows调试工具集合包含一些探索windows内部机制的有用工具。它的最新版本随着SDk发行。这些工具可以调试内核模式代码和用户模式代码。
windows调试工具集合经常更新,和操作系统的发布是独立的,你可以经常看看有没有最新版本。
用户模式调试
调试工具可以连接到用户模式进程并且访问内存。有两种方式连接到进程:
侵入式。默认情况下,windows调用DebugActiveProcess来连接调试器和被调试进程。这种方式允许调试器进行内存读写,设定断点等工作。可以通过断开连接的方式停止调试,这样不会杀掉被调试进程。
非侵入式 通过OpenProcess打开调试进程。不作为调试器连接上去。可以读写目标进程的内存,但是不能设置断点。
调试工具也可以用来分析崩溃转储文件。第三章有详细描述。
内核模式调试有两个调试器:命令行模式(kd.exe)和GUI模式(windbg.exe)。两者提供了相同的命令,所以选择哪个纯属个人风格。它可以进行三种调试:
调试windows崩溃转储文件(第二部分第14章进一步描述)
连接到正在运行的系统并且检查系统状态(如果调试驱动代码,可以设置断点)。这种方式需要两台电脑,目标机和主机。目标机是指需要被调试的系统,主机是值运行调试器的系统。两者之间通过调制解调器,IEEE1394或者usb2.0调试电缆连接(目标系统必须以调试方式启动)。它们也可以通过命名管道连接,这在调试虚拟机比如说hyper-v,virtual pc或者vmware的时候比较方便(通过将虚拟机操作系统的端口暴露为命名管道)。
连接到本地检查系统状态,称为本地内核调试。在WinDbg下,选择File->Kernal Debug->Local,然后点击OK。目标系统必须通过调试方式启动。在本地内核调试模式下有些命令不能正常工作,比如通过.dump创建内存dump,但是这可以通过livekd完成,后面会有讲述。
当通过内核调试模式连接时,你可以使用很多调试器扩展命令(!开头)来展示内部数据的内容,比如说线程,进程,IRP,内存管理信息等。WinDbg的帮助文件提供了很多有用信息,强烈建议通读一边。通过符号文件的帮助,dt命令可以显示1000多个内核数据结构。
实验:显示内核数据结构的信息
dt nt!*可以显示内核符号文件支持的数据结构列表。下面是部分输出。
lkd> dt nt!_*
nt!_LIST_ENTRY
nt!_LIST_ENTRY
nt!_IMAGE_NT_HEADERS
nt!_IMAGE_FILE_HEADER
nt!_IMAGE_OPTIONAL_HEADER
nt!_IMAGE_NT_HEADER
dt命令也支持通配符。比如说dt nt!_*interrupt*显示所有包含interrupt的结构。
lkd> dt nt!_*interrupt*
nt!_KINTERRUPT
nt!_KINTERRUPT_MODE
nt!_KINTERRUPT_POLARITY
nt!_UNEXPECTED_INTERRUPT
dt命令也可以用于格式化数据结构
lkd> dt nt!_kinterrupt
nt!_KINTERRUPT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x008 InterruptListEntry : _LIST_ENTRY
+0x018 ServiceRoutine : Ptr64 unsigned char
+0x020 MessageServiceRoutine : Ptr64 unsigned char
+0x028 MessageIndex : Uint4B
+0x030 ServiceContext : Ptr64 Void
+0x038 SpinLock : Uint8B
+0x040 TickCount : Uint4B
+0x048 ActualLock : Ptr64 Uint8B
+0x050 DispatchAddress : Ptr64 void
+0x058 Vector : Uint4B
+0x05c Irql : UChar
+0x05d SynchronizeIrql : UChar
+0x05e FloatingSave : UChar
+0x05f Connected : UChar
+0x060 Number : Uint4B
+0x064 ShareVector : UChar
+0x065 Pad : [3] Char
+0x068 Mode : _KINTERRUPT_MODE
+0x06c Polarity : _KINTERRUPT_POLARITY
+0x070 ServiceCount : Uint4B
+0x074 DispatchCount : Uint4B
+0x078 Rsvd1 : Uint8B
+0x080 TrapFrame : Ptr64 _KTRAP_FRAME
+0x088 Reserved : Ptr64 Void
+0x090 DispatchCode
注意dt没有显示子结构。-r命令支持递归显示。如下所示:
lkd> dt nt!_kinterrupt -r
nt!_KINTERRUPT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x008 InterruptListEntry : _LIST_ENTRY
+0x000 Flink : Ptr64 _LIST_ENTRY
+0x000 Flink : Ptr64 _LIST_ENTRY
+0x008 Blink : Ptr64 _LIST_ENTRY
+0x008 Blink : Ptr64 _LIST_ENTRY
+0x000 Flink : Ptr64 _LIST_ENTRY
+0x008 Blink : Ptr64 _LIST_ENTRY
 
帮助文件和WDK中有更进一步的信息。
LiveKd
LiveKd是Sysinternals提供的免费工具,它让你在非debug方式启动系统的情况下,也能使用内核调试器来检查系统。当需要解决内核级别的问题,而机器又不是以debug方式启动时(有些bug以debug方式不一定能重现),Livekd会非常有用。
运行LiveKd和windbg/Kd一样。livekd将所有的命令行参数传递给指定的调试器。默认情况下,livekd启动kd,通过指定-w参数,livekd可以启动windbg,-?可以查看livekd的帮助文件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值