Как лучше всего использовать псевдоним для имени исполняемого файла в сценарии сбоя WinDBG?
-
05-07-2019 - |
Вопрос
Исходная информация
Для сохранения аварийных дампов у меня есть скрипт, переданный 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 не удалось установить псевдоним.Команда псевдонима — это та, которую я собрал из ДампАнализ.орг.Эта команда извлекает имя из заголовка PEB изображения, используя ntdll.dll
.Без символов ОС она не знает, где найти функцию, которую она вызывает из ntdll.dll.
Вопрос
Кто-нибудь знает или имеет команду, чтобы получить имя изображения в качестве псевдонима для использования в именах файлов, которые все равно будут работать в таких ситуациях?
Решение
И вот спустя годы я получил ответ.
Ответ
При отсутствии файлов символов это лучший способ, который я нашел, чтобы получить имя исполняемого файла, который вышел из строя, чтобы его можно было использовать в имени файла для записи файла журнала или аварийного дампа из сценария:
aS ${/v:CrashFirstModule} "UnknownModule"
.foreach /pS b /ps b (name {.imgscan}) { .if($spat("${name}","*.exe") !=0){aS ${/v:CrashFirstModule} "${name}"; .break} }
После этих двух строк CrashFirstModule
будет иметь псевдоним «UnknownModule» или имя исполняемого файла.Это работает только в том случае, если исполняемый файл заканчивается на «.exe», но мне это кажется разумным и отлично работает в случае, когда я его использую.Вы можете добавить еще один .if
для обработки другого окончания, если вам нужно поддерживать такие вещи, как «.com».
Ответ:Объяснено
.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
используется для перемещения по списку изображений. /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
завершается ;или конец строки и удалит " из записи.Следующая строка будет псевдонимом CrashFirstModule
к UnknownModule
:
aS ${/v:CrashFirstModule} "UnknownModule"
.перерыв
.break
завершает .foreach
после того, как совпадение найдено.
Конец
Это все части, составляющие команду, которую я использую.Я надеюсь, что кто-то еще получит пользу от этого вопроса и ответа!
Другие советы
почему бы не использовать информацию о Peb?Ниже указано, что вам нужно:
?? @$peb->ProcessParameters
ntdll.dll
будет присутствовать в каждом процессе, поэтому я предполагаю, что проблема в загрузке символов.
В любом случае, это должно помочь избавиться от разрыва строки:
.foreach(Module {lm 1m}) { aS CrashApp Module; .break }
.foreach(Module {lm 1m a $exentry}) { aS CrashApp Module }