Windbg中查看计算机名

转载注明>> 作者:张佩】【原文:www.yiiyee.cn/blog/


引子


使用Windbg调试目标对象的时候,用户发现到它的一个缺陷,就是不能自动识别目标设备的机器名。实际上Windbg总是标出了Machine Name的关键字,但却从来都没有显示。可以认为Windbg在这个地方有点小缺陷。见下面的例子:

0:000> vertarget
Windows 7 Version 7601 (Service Pack 1) MP (8 procs) Free x64
Product: WinNt, suite: SingleUserTS
kernel32.dll version: 6.1.7601.18015 (win7sp1_gdr.121129-1432)
Machine Name: //空空如也
Debug session time: Thu Aug 22 10:11:04.000 2013 (UTC + 8:00)
System Uptime: 14 days 17:26:44.613
Process Uptime: 14 days 17:14:25.000
  Kernel time: 0 days 0:09:02.000
  User time: 0 days 0:42:36.000
在调试一些很困难问题的时候,比如目标系统boot失败、桌面不能正常显示、dump分析,这些情况下,我们没法通过登录到目标机器上去查看机器名,只能借助Windbg来实现。虽然Windbg没有自动显示功能,但仍然可以通过两种方法来实现手动实现。我们分两种情况来讲:用户调试环境(或用户dump),内核调试环境(或内核dump)。


用户调试环境


在用户调试的时候,可以通过进程的当前查看环境COMPUTERNAME。查看环境变量有下面两种方法:

1. 执行!PEB命令,可列举出当前进程使用的全部环境变量

2. 执行!envvar xxx 命令,查看指定的环境变量,如下所示:

0:000> !envvar computername
        computername = MOZHANG

这台目标设备的机器名是Mozhang。


内核调试环境


用户调试环境中,这是唯一的办法。在内核调试环境中,我们也可以通过查看指定进程的环境变量,来实现。不过步骤略复杂一些,因为如果当前进程是System进程、会话管理器进程、子系统进程等OS的进程,它们这些进程里面的PEB中,是没有COMPUTERNAME环境变量的(System进程则没有PEB),直接执行!peb或!envvar就会无效,这种情况下,需要把当前进程切换到其它进程去。

0: kd> !process 	// 当前进程为System进程
PROCESS fffffa8007288040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00188000  ObjectTable: fffff8a000003000  HandleCount: 364.
    Image: System
    VadRoot fffffa800911a840 Vads 9 Clone 0 Private 16. Modified 6371. Locked 64.
    DeviceMap fffff8a00000c500
0: kd> !envvar computername
0: kd> !peb
PEB NULL...  // PEB为空也

如果遇到这种情况,必须避开这些进程,切换到其它进程去,步骤如下:

6: kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS fffffa8007288040 // System进程不用,PEB为空
    SessionId: none  Cid: 0004    Peb: 00000000 ParentCid: 0000
    DirBase: 00188000  ObjectTable: fffff8a000003000  HandleCount: 385.
    Image: System

PROCESS fffffa800981a540 // 会话管理器进程不用
    SessionId: none  Cid: 013c    Peb: 7f607a64000  ParentCid: 0004
    DirBase: 03dd0000  ObjectTable: fffff8a00029e600  HandleCount:  36.
    Image: smss.exe

PROCESS fffffa8009cc5800 // 子系统进程不用
    SessionId: 0  Cid: 01a0    Peb: 7f65140f000  ParentCid: 0194
    DirBase: 108ad0000  ObjectTable: fffff8a0009ced80  HandleCount:  96.
    Image: csrss.exe

PROCESS fffffa80073c5080 // 此进程可用
    SessionId: 0  Cid: 01f0    Peb: 7f633826000  ParentCid: 0194
    DirBase: 10a276000  ObjectTable: fffff8a00134ed80  HandleCount:  84.
    Image: wininit.exe


6: kd> .process /i fffffa80073c5080
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
6: kd> g
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPointWithStatus:
fffff800`f227b930 cc              int     3
4: kd> !envvar computername
        computername = mozhang
上面是分了三个步骤:

1. 列举进程列表,用!process 0 0 命令。在列出的所有进程中,任意选择一个,只要不是那几个系统的进程即可。

2. 切换到指定进程,通过.proces /i xxx命令,xxx为内核进程对象的地址。进程切换是发送命令给目标设备的系统进行处理的,所以要执行以下go命令,以使目标设备有时间去完成进程切换的工作。

3. 执行!Peb!envvar xxx命令。

上面介绍的是通过环境便来来获取目标机器名。在内核调试的时候,还有另一种更方便的办法,这种办法也是MSDN文档里有说明的。原来在系统的srv.sys模块中,通过一个全局变量srv!srvcomputername保存了本机的机器名。这样的话,我们只要查看这个变量就可以了。此变量的类型为UNICODE_STRING。我们通过下面的方法来实现:

6: kd> x srv!srvcomputername
fffff880`07107048 srv!SrvComputerName = <no type information>

6: kd> dt nt!_unicode_string  fffff880`07107048
 "mozhang"
   +0x000 Length           : 0xE
   +0x002 MaximumLength    : 0xE
   +0x008 Buffer           : 0xfffff8a0`02eaac90  "mozhang"
有人担心,如果我没有srv.sys的符号文件怎么办。这一点是没问题的,srv.sys是微软的系统模块,我们可以通过微软的 公共符号服务器获取它的public符号文件。


参考:http://msdn.microsoft.com/en-us/library/windows/hardware/ff543991(v=vs.85).aspx


你可能感兴趣的:(windbg,envvar,srvcomputername,srv.sys)