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

发布于 2024-07-12 02:02:36 字数 1228 浏览 6 评论 0原文

背景信息

为了保存故障转储,我将一个脚本传递给 AeDebug 注册表项的 Debugger 值中的 cdb.exe

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

这是因为别名命令失败设置别名。 别名命令是我从 DumpAnalysis.org。 此命令使用 ntdll.dll 从图像的 PEB 标头中提取名称。 如果没有操作系统的符号,它就不知道在哪里可以找到它从 ntdll.dll 调用的函数。

问题

有谁知道或有一个命令来获取图像的名称作为在文件名中使用的别名,在这些情况下仍然有效?

Background Information

For saving out crash dumps, I have a script passed to cdb.exe in the Debugger value of the AeDebug registry key:

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

Here is the first portion of the script:

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

* (...)

The Problem

With symbols, this works exactly as I would like, I get log files with sensible names like:

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

However, if symbols are not available, I get a log file name like this:

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

This is because the alias command has failed to set the alias. The alias command is one that I harvested from DumpAnalysis.org. This command pulls the name out of the PEB Header for the image, using ntdll.dll. Without symbols for the OS, it doesn't know where to find the function it is calling from ntdll.dll.

The Question

Does anyone know or have a command to get the name of the image as an alias for use in filenames which would still work in these situations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沫雨熙 2024-07-19 02:02:36

所以多年后我在这里给出了答案。

答案

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

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

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

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

${}

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

aS

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

aS ${/v:CrashFirstModule} "UnknownModule"

.break

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

End

这就是组成我正在使用的命令的所有部分,我希望其他人能从这个问题和答案中受益!

So here I am years later with an answer.

The Answer

In the absence of symbol files, this is the best way I've found to get the name of the executable that crashed so that it can be used in a filename for writing a log file or crash dump from a script:

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

After these two lines, CrashFirstModule will be aliased to either "UnknownModule" or the name of the executable. This only works if the executable ends in ".exe", but that seems reasonable to me, and works fine in the case where I'm using it. You could add another .if to handle other ending if you need to support things like ".com".

The Answer: Explained

.imgscan

.imgscan gives a list of executable modules, which will include .exe, .dll, .drv etc. This is the starting point for finding the executable name.

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 is used to walk the list of images. /pS specifies how far into the list the first value is. /ps specifies the distance between values. (b = 11 in hex) This is necessary as .foreach will separate on spaces. With these arguments, the list becomes:

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

$spat is the MASM wildcard string match function. It will match the first argument against the pattern in the second argument. It is not case sensitive, so this will match NOTEPAD.EXE as well as NotePad.eXe, etc.

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

${}

${} is the alias interpreter. You embed ${<alias name>} wherever you want the value of your alias written in a string. if you are using the alias in a command, you can just use it, so .echo CrashFirstmodule would echo out notepad.exe. In those cases where you actually mean the name of the alias, you can specify it as ${/v:<alias name>} which will just resolve to the alias name. This expansion prevention is necessary when reassigning an alias. aS CrashFirstModule "${name}" would have resulted in setting the alias UnknownModule to notepad.exe, as CrashFirstModule would have been expanded to its value before the command was executed.

aS

aS is one of the commands to assign aliases. aS is terminated by ; or the end of line and will strip the " from the entry. The following line will alias CrashFirstModule to UnknownModule:

aS ${/v:CrashFirstModule} "UnknownModule"

.break

.break ends the .foreach after a match is found.

End

That's all the pieces that make up the command I'm using. I hope someone else gets some benefit from this question and answer!

指尖微凉心微凉 2024-07-19 02:02:36

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

?? @$peb->ProcessParameters

why not use peb info?
Below is what you need:

?? @$peb->ProcessParameters
是你 2024-07-19 02:02:36

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

无论如何,这应该可以消除换行符:

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

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

ntdll.dll will be present in every process, so I'm guessing the problem is symbol loading.

Anyway, this should work to get rid of the line break:

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

.foreach(Module {lm 1m a $exentry}) { aS CrashApp Module }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文