分类 调试 下的文章

Windbg命令脚本一文里,我们介绍了命令脚本语言的的组成要素,在本文里将对语句进行展开的讲解。这些语句主要是流程控制的语句,比如我们常见的条件分子和循环语句等。

; (命令分隔符)

分号(;)字符用于在一行中分隔多个命令。

Command1 ; Command2 [; Command3 ...] 

简介

STATUS_INVALID_PARAMETER,值为0xC000000D。代表的意思是把一个无效的参数传递给了服务或函数(这里的服务是指Windows系统自身的服务,函数是指Windows系统内核函数)。它定义在 ntstatus.h头文件里,如下:

//
// MessageId: STATUS_INVALID_PARAMETER
//
// MessageText:
//
// An invalid parameter was passed to a service or function.
//
#define STATUS_INVALID_PARAMETER         ((NTSTATUS)0xC000000DL)    // winnt

异常填充结构

ExceptionAddress: 778e199f (ntdll!TppRaiseInvalidParameter+0x00000037)
ExceptionCode: c000000d//异常代码
ExceptionFlags: 00000000//这是一个可继续的异常
NumberParameters: 0

 

命令脚本,就是将完成某个特定任务的相关命令组合在一起,保存在脚本文件里,加载到Windbg里执行,达到我们的目的。你可以理解为脚本就是一种语言,就像c或者汇编,但是他不需要编译器将其编译为可执行文件,而是由解释器将其内容翻译为对应的动作。而Windbg的脚本就是利用Windbg作为解释器,将脚本内容翻译为实际的动作。
既然可以作为一种语言,那么它就具有一般语言通常包含的要素:数据类型、变量、表达式、语句、函数等,下面我们分别简单讲一下。


一、数据类型
关于数据类型,Windbg的帮助里没有明确列举,但是,在使用时一般会遇到,数值和字符串这两种。

  • 数值
    数值没有太多需要解释的,和所有编程语言里的整数含义一样,在表示的时候有进制之分。
    代码:

    2进制  0b
    8进制  0n
    10进制  0t
    16进制  0x
  • 字符串
    字符串用一对 ” 括起来。比如上面的 ”hello windbg”。

二、变量
在windbg中变量的定义很特别,实际上,它并没有变量这个概念,所以,在学习的时候会觉得很别扭。不过,我们换个思路就容易了,变量实际上就是为了保存临时结果, 如果只想保存一些数值,那么伪寄存器(参考Windbg命令的语法规则系列)应该是比较好的选择,windbg提供了20个伪寄存器$t0-$t19,供命令保存临时数值变量。称他们为伪寄存器是有原因的,首先对他们的操作和寄存器一样,都是使用r命令,在C++表达式里都前面需要加@符,但是他们又不是真正的寄存器,只是windbg定义的名字而已。使用这些伪寄存器也是很方便的:

代码:

0:000> r $t0=0x123
0:000> r $t0
$t0=00000123

0:000> r eax
eax=004c1b89

0:000> r $t0=@eax
0:000> r $t0
$t0=004c1b89

如果您有一个WER处理过的崩溃进程,但您知道JIT调试器设置错误,或者根本没有设置(因此崩溃对话框上没有“调试”按钮),则可以保持对话框打开,并将您选择的任何调试器附加到挂起的崩溃进程。
不过,有个问题。通过将调试器附加到挂起的进程,进程的最后异常信息已丢失;这是因为调试器成功附加到挂起(或挂起)进程的方式是插入一个新的正在运行的线程并使该线程崩溃。因此,调试器及其使用.dump生成的任何小型转储都将无法找到原始程序的异常信息。哎呀!怎么办?
从kb的堆栈跟踪开始:

RetAddr           : Args to Child                                                           : Call Site
000007f9`d88212d2 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!NtWaitForMultipleObjects+0xa
000007f9`dae8d20e : 00000000`02300000 000007f6`96e75000 00000000`00000000 00000000`000001dc : KERNELBASE!WaitForMultipleObjectsEx+0xe5
000007f9`dae8cfd2 : fffff8a0`00000080 00000000`80004005 00000000`000001ec 00000000`00000000 : KERNEL32!WerpReportFaultInternal+0x1fa
000007f9`d889fc87 : 00000000`00000000 00000000`00195c30 00000000`00000030 00000000`00195c30 : KERNEL32!WerpReportFault+0x42
000007f9`db56a43d : 00000001`00000000 00000000`00196990 00000000`0019f620 00000000`003441d0 : KERNELBASE!UnhandledExceptionFilter+0x1d7
000007f9`db4b4ad4 : 000007f9`d8eeabdd 00000000`00196990 00000000`00000000 00000000`00000000 : ntdll!LdrpLogFatalUserCallbackException+0x4d
000007f9`db4d464d : 00000000`00000000 00000000`00195de8 00000000`00195da0 000007f9`d8f7f000 : ntdll!KiUserCallbackDispatcherHandler+0x20
000007f9`db4d567c : 000007f9`d8ee0000 00000000`0019f5c0 000007f9`0000e4f0 00000000`00000000 : ntdll!RtlpExecuteHandlerForException+0xd
000007f9`db4b4bba : 00000000`00000000 00000000`00000000 000007f6`96e7e300 00000000`00000000 : ntdll!RtlDispatchException+0x392
000007f9`db4b2acd : 000007f9`d8bbc36c 00000000`00360f00 00000000`00360f00 00000000`00360f00 : ntdll!KiUserExceptionDispatch+0x2e
000007f9`d8bbc36c : 00000000`00360f00 00000000`00360f00 00000000`00360f00 00000000`00000000 : ntdll!memcpy+0x21a

EXCEPTION_POINTERS结构地址似乎作为调用KERNEL32!WerpReportFault的参数2和4传递。由此,可以显示异常和上下文记录-但我们只需要在小型转储中包含异常指针地址,因为添加这一地址将允许 !analyze命令以工作。
使用命令“.dump/ma/xp 00195c30 dump.dmp”创建小型转储,就完成了。