在WinDBG崩溃脚本中如何最好地替换可执行文件名?

时间:2009-01-07 14:17:50

标签: debugging scripting windbg crash-dumps

背景资料

为了保存崩溃转储,我在cdb.exe注册表项的Debugger值中将脚本传递给AeDebug

C:\progra~1\debugg~1\cdb.exe -p %ld -e %ld -g -y SRV*c:\mss*http://msdl.microsoft.com/download/symbols -c "$<d:\tgticker\Dumps\RDFD.cdbscript"

以下是该脚本的第一部分:

as /c CrashFirstModule .printf "%mu", @@c++((*(ntdll!_LDR_DATA_TABLE_ENTRY**)&@$peb->Ldr->InLoadOrderModuleList.Flink)->BaseDllName.Buffer) 

.logopen /t d:\tgticker\dumps\${CrashFirstModule}_process.log

* (...)

问题

使用符号,这与我想要的完全一样,我得到了具有合理名称的日志文件,如:

  • LHCBDRDT.exe_process_147c_2009-01-06_23-10-05-371.log

但是,如果符号不可用,我会得到一个如下日志文件名:

  • ${CrashFirstModule}_process_17a8_2009-01-06_23-10-01-124.log

这是因为alias命令无法设置别名。别名命令是我从DumpAnalysis.org收获的命令。此命令使用ntdll.dll将名称从图像的PEB标题中拉出。没有操作系统的符号,它不知道在哪里可以找到它从ntdll.dll调用的函数。

问题

有没有人知道或者有命令将图像的名称作为在文件名中使用的别名,在这些情况下仍可以使用?

3 个答案:

答案 0 :(得分:3)

所以我在这里多年以后得到答案。

答案

在没有符号文件的情况下,这是我发现获取崩溃的可执行文件名称的最佳方式,以便可以在文件名中使用它来编写脚本中的日志文件或崩溃转储: / p>

aS ${/v:CrashFirstModule} "UnknownModule"
.foreach /pS b /ps b (name {.imgscan}) { .if($spat("${name}","*.exe") !=0){aS ${/v:CrashFirstModule} "${name}"; .break} }

在这两行之后,CrashFirstModule将别名为“UnknownModule”或可执行文件的名称。这仅在可执行文件以“.exe”结尾时才有效,但这对我来说似乎是合理的,并且在我使用它的情况下工作正常。如果您需要支持“.com”等内容,可以添加另一个.if来处理其他结尾。

答案:解释

.imgscan

.imgscan给出了一个可执行模块列表,其中包括.exe,.dll,.drv等。这是查找可执行文件名的起点。

0:000> .imgscan
MZ at 01000000, prot 00000002, type 01000000 - size 14000
  Name: notepad.exe
MZ at 73070000, prot 00000002, type 01000000 - size 27000
  Name: WINSPOOL.DRV
MZ at 762b0000, prot 00000002, type 01000000 - size 49000
  Name: comdlg32.dll
MZ at 76f50000, prot 00000002, type 01000000 - size 13000
  Name: Secur32.dll
MZ at 77380000, prot 00000002, type 01000000 - size 91000
  Name: USER32.dll
MZ at 77420000, prot 00000002, type 01000000 - size 103000
  Name: COMCTL32.dll
MZ at 77ba0000, prot 00000002, type 01000000 - size 5a000
  Name: msvcrt.dll
MZ at 77c00000, prot 00000002, type 01000000 - size 48000
  Name: GDI32.dll
MZ at 77c50000, prot 00000002, type 01000000 - size a0000
  Name: RPCRT4.dll
MZ at 77e40000, prot 00000002, type 01000000 - size 102000
  Name: KERNEL32.dll
MZ at 7c800000, prot 00000002, type 01000000 - size c3000
  Name: ntdll.dll
MZ at 7c8d0000, prot 00000002, type 01000000 - size 7ff000
  Name: SHELL32.dll
MZ at 7d180000, prot 00000002, type 01000000 - size 52000
  Name: SHLWAPI.dll
MZ at 7d1e0000, prot 00000002, type 01000000 - size 9c000
  Name: ADVAPI32.dll

.foreach

.foreach用于遍历图像列表。 /pS指定列表中第一个值的距离。 /ps指定值之间的距离。 (b = 11十六进制)这是必要的,因为.foreach将在空格上分开。使用这些参数,列表变为:

0:000> .foreach /pS b /ps b (name {.imgscan}) { .echo name }
notepad.exe
WINSPOOL.DRV
comdlg32.dll
Secur32.dll
USER32.dll
COMCTL32.dll
msvcrt.dll
GDI32.dll
RPCRT4.dll
KERNEL32.dll
ntdll.dll
SHELL32.dll
SHLWAPI.dll
ADVAPI32.dll

$卵

$spat是MASM通配符字符串匹配函数。它将匹配第二个参数中的模式的第一个参数。它不区分大小写,因此它将匹配NOTEPAD.EXE以及NotePad.eXe等。

.if($spat("${name}","*.exe") !=0) {.echo "found it!"}

$ {}

${}是别名解释器。您将${<alias name>}嵌入到您希望在字符串中写入别名的值的任何位置。如果您在命令中使用别名,则可以使用它,因此.echo CrashFirstmodule将回显notepad.exe。在您实际上是指别名的情况下,您可以将其指定为${/v:<alias name>},它将解析为别名。在重新分配别名时,必须进行此扩展防护。 aS CrashFirstModule "${name}"会导致将别名UnknownModule设置为notepad.exe,因为CrashFirstModule在执行命令之前会被扩展为其值。

AS

aS是分配别名的命令之一。 aS被终止;或者行尾,并将从条目中删除“。以下行将CrashFirstModule别名为UnknownModule

aS ${/v:CrashFirstModule} "UnknownModule"

。BREAK

.break在找到匹配后结束.foreach

结束

这就是构成我正在使用的命令的所有部分。我希望其他人从这个问题和答案中获得一些好处!

答案 1 :(得分:1)

为什么不使用Peb信息? 以下是您需要的:

?? @$peb->ProcessParameters

答案 2 :(得分:0)

ntdll.dll将出现在每个进程中,所以我猜这个问题是符号加载。

无论如何,这应该可以解决换行问题:

<击>

<击>
.foreach(Module {lm 1m}) { aS CrashApp Module; .break }

<击>

.foreach(Module {lm 1m a $exentry}) { aS CrashApp Module }