A melhor forma de Alias ??um nome do executável em uma Bater Script WinDBG?
-
05-07-2019 - |
Pergunta
Informação de fundo
Para salvar a despejos de memória, eu tenho um script passado para cdb.exe
no valor Debugger
da chave do Registro 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"
Aqui está a primeira parte do 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
* (...)
O Problema
Com símbolos, isso funciona exatamente como eu gostaria, eu recebo arquivos de log com nomes sensíveis como:
-
LHCBDRDT.exe_process_147c_2009-01-06_23-10-05-371.log
No entanto, se os símbolos não estão disponíveis, fico com um nome de arquivo de log assim:
-
${CrashFirstModule}_process_17a8_2009-01-06_23-10-01-124.log
Isso ocorre porque o comando de alias não conseguiu definir o alias. O comando alias é um que eu colhidas a partir de DumpAnalysis.org . Este comando puxa o nome fora do cabeçalho PEB para a imagem, usando ntdll.dll
. Sem símbolos para o OS, ele não sabe onde encontrar a função que ele está chamando de ntdll.dll.
A Pergunta ??h3>
Alguém sabe ou tem um comando para obter o nome da imagem como um alias para uso em nomes de arquivos que ainda trabalham nestas situações?
Solução
Por isso estou aqui anos depois com uma resposta.
A resposta ??h1>
Na ausência de arquivos de símbolos, esta é a melhor maneira que eu encontrei para obter o nome do executável que caiu de modo que possa ser usado em um nome de arquivo para escrever um arquivo de log ou despejo de memória a partir de um script:
aS ${/v:CrashFirstModule} "UnknownModule"
.foreach /pS b /ps b (name {.imgscan}) { .if($spat("${name}","*.exe") !=0){aS ${/v:CrashFirstModule} "${name}"; .break} }
Depois destas duas linhas, CrashFirstModule
será alias para qualquer um "UnknownModule" ou o nome do executável. Isso só funciona se as extremidades executáveis ??em ".exe", mas que parece razoável para mim, e funciona bem no caso em que eu estou usando. Você poderia adicionar outro .if
para lidar com outra final, se você precisa para apoiar coisas como ".com".
A Resposta: Explicação
.imgscan
.imgscan
dá uma lista de módulos executáveis, que irá incluir .exe, .dll .drv etc. Este é o ponto de partida para encontrar o nome do executável.
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
é usado para percorrer a lista de imagens. Especifica /pS
o quão longe no a lista o primeiro valor é. especifica /ps
a distância entre os valores. (B = 11 em hexadecimal) Isto é necessário porque .foreach
irá separar em espaços. Com estes argumentos, a lista torna-se:
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
$ cuspiu
$spat
é a função de string match MASM curinga. Ele vai coincidir com o primeiro argumento contra o padrão no segundo argumento. Não é caso sensível, então isso vai corresponder NOTEPAD.EXE, bem como o Notepad.exe, etc.
.if($spat("${name}","*.exe") !=0) {.echo "found it!"}
$ {}
${}
é o intérprete alias. Você incorpora ${<alias name>}
onde quer que você deseja que o valor do seu alias escritos em uma string. se você estiver usando o alias em um comando, você pode simplesmente usá-lo, então .echo CrashFirstmodule
ecoaria fora notepad.exe
. Nos casos em que você realmente quer dizer o nome do alias, você pode especificá-lo como ${/v:<alias name>}
que só vai resolver para o nome de alias. Esta prevenção expansão é necessária quando a reatribuição um alias. aS CrashFirstModule "${name}"
teria resultado na criação do UnknownModule
alias para notepad.exe
, como CrashFirstModule
teria sido expandida para o seu valor antes que o comando foi executado.
AS
aS
é um dos comandos a aliases atribuir. aS
é terminada por; ou a extremidade da linha e irá retirar o "a partir da entrada A seguir linha vontade aliás CrashFirstModule
para UnknownModule
:.
aS ${/v:CrashFirstModule} "UnknownModule"
.BREAK
.break
termina a .foreach
após uma correspondência for encontrada.
Fim
Isso é todas as peças que compõem o comando que estou usando. Espero que alguém recebe algum benefício a partir desta pergunta e resposta!
Outras dicas
por que não usar informações peb? Abaixo está o que você precisa:
?? @$peb->ProcessParameters
ntdll.dll
estará presente em todo processo, então eu estou supondo que o problema é símbolo de carregamento.
De qualquer forma, isso deve funcionar para se livrar da quebra de linha:
.foreach(Module {lm 1m}) { aS CrashApp Module; .break }
.foreach(Module {lm 1m a $exentry}) { aS CrashApp Module }