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コマンドは、 DumpAnalysis.org 。このコマンドは、ntdll.dll
を使用して、画像のPEBヘッダーから名前を引き出します。 OSのシンボルがないと、ntdll.dllから呼び出している関数の場所がわかりません。
質問
このような状況でも機能するファイル名で使用するエイリアスとして画像の名前を取得するコマンドを知っているか、持っていますか?
解決
だから、ここで私は数年後に答えがあります。
答え
シンボルファイルがない場合、これは、クラッシュした実行可能ファイルの名前を取得して、ログファイルまたはスクリプトからクラッシュダンプを書き込むためのファイル名で使用できるようにする最良の方法です:
aS ${/v:CrashFirstModule} "UnknownModule"
.foreach /pS b /ps b (name {.imgscan}) { .if($spat("${name}","*.exe") !=0){aS ${/v:CrashFirstModule} "${name}"; .break} }
これらの2行の後、CrashFirstModule
は<!> quot; UnknownModule <!> quot;のいずれかにエイリアスされます。または実行可能ファイルの名前。これは、実行可能ファイルが<!> quot; .exe <!> quot;で終わっている場合にのみ機能しますが、それは私にとって理にかなっているようで、使用している場合は正常に機能します。 <!> quot; .com <!> quot;のようなものをサポートする必要がある場合は、別の.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
は、値間の距離を指定します。 (16進数でb = 11)$spat
はスペースで区切られるため、これが必要です。これらの引数を使用すると、リストは次のようになります。
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ワイルドカード文字列一致関数です。最初の引数を2番目の引数のパターンと照合します。大文字と小文字は区別されないため、これは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
は、コマンドが実行される前にaS
がその値に展開されるため、エイリアス.break
を<=>に設定することになります。
aS
<=>は、エイリアスを割り当てるコマンドの1つです。 <=>は;で終了しますまたは行末で<!> quotを削除します。エントリーから。次の行は、<=>を<=>にエイリアスします:
aS ${/v:CrashFirstModule} "UnknownModule"
.break
<=>は、一致が見つかった後に<=>を終了します。
終了
これが、私が使用しているコマンドを構成するすべての要素です。他の誰かがこの質問と回答の恩恵を受けることを願っています!
他のヒント
peb情報を使用しない理由 以下が必要なものです:
?? @$peb->ProcessParameters
ntdll.dll
はすべてのプロセスに存在するため、問題はシンボルの読み込みにあると推測しています。
とにかく、これは改行を取り除くために動作するはずです:
.foreach(Module {lm 1m}) { aS CrashApp Module; .break }
.foreach(Module {lm 1m a $exentry}) { aS CrashApp Module }