wenmo8 发布的文章

Microsoft调试工具for Windows提供了两种创建远程调试连接的方法,包括“连接到远程会话”和“连接到远程存根”。连接到远程会话是这两个会话中最常用的,也是您通常需要的全部内容,但是它不允许客户端访问远程上缺少的调试符号。
通常,远程调试会话将在所有用户都可以访问符号信息的公司网络中完成,但是如果我们在无法自由共享符号的安全环境之外进行调试,调试将变得更加困难。
Microsoft调试工具包有两个服务器端命令行应用程序,可通过连接到远程存根来帮助我们完成此操作:Dbgsrv.exe文件用于用户模式调试和Kdsrv.exe文件用于内核模式调试。它们为调试器提供了一个精简的服务器层,以充分利用本地符号和源代码进行附加。

让我们通过展示连接到远程会话时遇到的问题来说明使用远程存根的好处。

此图显示了传统的远程调试会话。调试主机和目标都在运行windbg,不过我们可以使用KD或CDB。目标是调试一个有缺陷的应用程序Getif.exe它在调试目标上运行。我们在调试主机上有应用程序的符号,但是出于安全原因,调试目标没有符号访问权限Getif.exe. 在这两台计算机上,我们都从http://msdl.microsoft.com/download/symbols取符号。
以下是调试目标计算机上的符号路径。因为此系统不在我们的安全环境之外,所以它没有Getif.exe应用程序。这对于调试是有问题的。
这是调试主机上的符号路径,其中包括指向应用程序符号的路径,因为它位于安全位置内

 

 

要在目标计算机上创建远程调试服务器,请使用.server命令指定用于连接的本地端口:.server tcp:port=<localport>

 

 

接下来,我在调试主机上选择“connect to remotesession”。

 

 

然后输入端口和服务器名称:

这就是我们头疼的地方!因为我们没有Getif.exe符号访问位于安全环境外部的计算机上,堆栈getif.exe不显示符号信息。这使得调试应用程序变得很困难,因为我们无法转储数据类型或查看其他符号信息。

如果我们想调试Getif.exe对于符号,我们需要将符号文件复制到调试目标计算机,并将位置添加到目标的符号路径中。在我们的场景中,这可能是不可能的,因为符号通常仅限于内部使用,不允许自由复制。

通过在调试目标计算机上激活Dbgsrv,调试主机上的调试器将通过对目标计算机上用户模式进程的完全符号访问进行连接。上图说明了这个过程。
让我们在调试目标上运行一个使用dbgsrv的示例。在调试目标上输入:<path to debugging tools>\dbgsrv -t tcp:port=<localport>

Dbgsrv返回命令提示符,命令窗口中没有输出,调试端口可以是系统上任何打开的端口。最好用netstat确认我们正在监听我们选择的端口。下面是一个例子

现在让我们把焦点转移到调试主机上。我们没有选择典型的“连接远程会话”,而是使用“文件”菜单中的“连接到远程存根”选项。

接下来输入端口和服务器名称。

选择OK之后,我们将返回到空的命令窗口。在连接到目标进程之前,我们不会看到任何文本:

下一步选择“文件附加到进程”选项

请注意,“附加到进程”对话框显示调试目标计算机上运行的进程列表。

现在让我们来看看这个过程。标题栏确认我们已连接到kdsrv目标上的进程:

在这里您可以看到与远程存根连接的好处。符号getif.exe正在为运行在安全环境之外的计算机上的应用程序工作。

但是如果我需要内核调试呢?您可以使用Kdsrv对内核调试执行相同的操作。

如果需要的话,我们可以使用内核调试器srkdv。与前面的示例非常相似,我们输入命令:kdsrv -t tcp:port=<localport>

我们可以看到我们正在监听我们选择的本地端口:

现在,我们必须在调试主机上启动调试器,命令行包含连接到KdSrv主机所需的信息。从Windbg 6.10.3.233开始,我们无法从Windbg图形界面连接到kdsrv远程存根,然后再将内核连接到调试目标。

我在上面的图中用的是字符串-windbg -k kdsrv:server=@{tcp:server=rodolpho,port=5004},trans=@{com:pipe,port=\\mimi\pipe\2008target}

请注意,我们正在调试运行在Microsoft Hyper-V下的内核调试目标上的命名管道!这是一个很好的调试方法,无需设置第二台计算机和连接空调制解调器电缆。如果我们想用空调制解调器电缆连接到COM1,我们将使用:windbg -k kdsrv:server=@{tcp:server=rodolpho,port=5004},trans=@{com:port=com1,baud=11500}

Windbg启动后,命令窗口看起来就像我们附加了一个本地调试器一样。标题栏将确认我们正在通过调试服务器附加:

我们还可以将上下文更改为Getif.exe连接到远程存根后处理。当我们查看应用程序堆栈时,我们有应用程序的符号:

在我们有了远程存根连接之后,我们就可以作为远程会话共享我们的客户机,但是我们将始终处理远程存根客户机上的符号。一旦你设置了一个远程存根几次,它就像设置一个远程会话一样简单,并且可以使远程调试更加顺利。
安全说明:这些示例使用TCP/IP或命名管道,不受密码保护。如果您需要更高的安全性,调试器远程将允许SSL和安全管道连接以及密码和证书身份验证。

今天我将写一篇关于我如何使用SOS.Net框架调试扩展(和!analyze-v)以轻松解决.NETFramework异常。此异常阻止事件查看器正确显示。事件查看器返回了一个错误,该错误提供了有关导致该问题的实际原因的很少信息。在本例中,我将演示如何使用windbg来获取有关出错的信息。我不必对此问题执行实时调试。相反,我使用进程转储来获取与根本原因相关的非常精确的信息,这些信息由调试器返回。然后我可以使用进程监视器来识别需要检查的文件。这些行动使我找到了问题的根源,很容易就得到了纠正。

报告的问题:打开时遇到以下错误事件vwr.msc(事件查看器)在Windows 2008 Server系统上:

"MMC could not create the snap-in."MMC could not create the snap-in.

The snap
-inmight not have been installed correctly

Name: Event Viewer

CLSID: FX:{b05566ad
-fe9c-4363-be05-7a4cbb7cb510}

六、异常信息流(ExceptionStream)

异常信息流包含异常信息。包括发生异常的线程、异常记录信息、线程上下文等信息。它紧挨着杂项信息流(MiscInfoStream)后面。

MiscInfoStream信息如下:

0x124+0n1365=0x678

我们看看ExceptionStream信息

可知ExceptionStream的RVA为678h=0x124+0n1365。所以,MiscInfoStream后面就是ExceptionStream。大小168字节,ExceptionStream数据如下:

ExceptionStream的数据结构如下:

typedef structMINIDUMP_EXCEPTION_STREAM {
ULONG32 ThreadId;
ULONG32 __alignment;
MINIDUMP_EXCEPTION ExceptionRecord;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
} MINIDUMP_EXCEPTION_STREAM,
*PMINIDUMP_EXCEPTION_STREAM;

七、线程列表流(ThreadListStream)

ThreadListStream流包含线程核心信息。它紧挨着异常信息流(ExceptionStream)。

异常信息流如下

 

0x678+0n168=0x720。而线程列表流如下

 

可知偏移是0x720,即证明杂项信息流是紧挨着系统信息流,大小有3796字节。

ThreadListStream包含的数据结构如下:

typedef struct_MINIDUMP_THREAD_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD Threads[
0];
} MINIDUMP_THREAD_LIST,
*PMINIDUMP_THREAD_LIST;