Condividi tramite


Esempi di programma di comando debugger

Le sezioni seguenti descrivono i programmi di comando del debugger.

Uso del token foreach

Nell'esempio seguente viene usato il token foreach per cercare i valori word di 5a4d. Per ogni valore 5a4d trovato, il debugger visualizza 8 valori DWORD, a partire dall'indirizzo in cui è stato trovato il DWORD 5a4d.

0:000> .foreach (place { s-[1]w 77000000 L?4000000 5a4d }) { dc place L8 } 

Nell'esempio seguente viene usato il token foreach per cercare i valori word di 5a4d. Per ogni valore 5a4d trovato, il debugger visualizza 8 valori DWORD, a partire da 4 byte prima dell'indirizzo in cui è stato trovato il DWORD 5a4d.

0:000> .foreach (place { s-[1]w 77000000 L?4000000 5a4d }) { dc place -0x4 L8 } 

Nell'esempio seguente vengono visualizzati gli stessi valori.

0:000> .foreach (place { s-[1]w 77000000 L?4000000 5a4d }) { dc ( place -0x4 ) L8 } 

Nota Se si vuole operare sul nome della variabile nella parte OutCommands del comando, è necessario aggiungere uno spazio dopo il nome della variabile. Nell'esempio di preceeding, ad esempio, esiste uno spazio tra la posizione della variabile e l'operatore di sottrazione.

L'opzione -[1] insieme al comando s (Memoria di ricerca) determina che l'output includa solo gli indirizzi trovati, non i valori trovati in tali indirizzi.

Il comando seguente visualizza informazioni dettagliate sul modulo per tutti i moduli che si trovano nell'intervallo di memoria da 0x77000000 a 0x7F000000.

0:000> .foreach (place { lm1m }) { .if ((${place} >= 0x77000000) & (${place} <= 0x7f000000)) { lmva place } } 

L'opzione 1m insieme al comando lm (List Loaded Modules) causa l'output in modo che includa solo gli indirizzi dei moduli, non la descrizione completa dei moduli.

Nell'esempio precedente viene usato il token ${ } (Alias Interprete) per assicurarsi che gli alias vengano sostituiti anche se sono accanto ad altri testo. Se il comando non include questo token, la parentesi di apertura accanto al posto impedisce la sostituzione dell'alias. Si noti che il token ${} funziona sulle variabili usate in .foreach e su alias true.

Procedura per l'elenco dei processi

Nell'esempio seguente viene illustrato l'elenco dei processi in modalità kernel e viene visualizzato il nome eseguibile per ogni voce dell'elenco.

Questo esempio deve essere archiviato come file di testo ed eseguito con il comando $$>< (Run Script File). Questo comando carica l'intero file, sostituisce tutti i ritorni a capo con punti e virgola ed esegue il blocco risultante. Questo comando consente di scrivere programmi leggibili usando più righe e rientro, anziché dover spremere l'intero programma in una singola riga.

Questo esempio illustra le funzionalità seguenti:

  • I $t 0, $t 1 e $t 2 pseudoregistri vengono usati come variabili in questo programma. Il programma usa anche alias denominati Procc e $ImageName.

  • Questo programma usa l'analizzatore di espressioni MASM. Tuttavia, il token @@c++( ) viene visualizzato una sola volta. Questo token fa sì che il programma usi l'analizzatore di espressioni C++ per analizzare l'espressione all'interno delle parentesi. Questo utilizzo consente al programma di usare direttamente i token di struttura C++.

  • Il flag ? viene usato con il comando r (Registers). Questo flag assegna valori tipizzati alla pseudoregistrata $t 2.

$$  Get process list LIST_ENTRY in $t0.
r $t0 = nt!PsActiveProcessHead

$$  Iterate over all processes in list.
.for (r $t1 = poi(@$t0);
      (@$t1 != 0) & (@$t1 != @$t0);
      r $t1 = poi(@$t1))
{
    r? $t2 = #CONTAINING_RECORD(@$t1, nt!_EPROCESS, ActiveProcessLinks);
    as /x Procc @$t2

 $$  Get image name into $ImageName.
 as /ma $ImageName @@c++(&@$t2->ImageFileName[0])

 .block
    {
        .echo ${$ImageName} at ${Procc}
    }

    ad $ImageName
    ad Procc
}

A piedi l'elenco di LDR_DATA_TABLE_ENTRY

Nell'esempio seguente viene illustrato l'elenco LDR_DATA_TABLE_ENTRY in modalità utente e viene visualizzato l'indirizzo di base e il percorso completo di ogni voce dell'elenco.

Come nell'esempio precedente, questo programma deve essere salvato in un file ed eseguito con il comando $$>< (Esegui file script).

Questo esempio illustra le funzionalità seguenti:

  • Questo programma usa l'analizzatore di espressioni MASM. Tuttavia, in due posizioni, viene visualizzato il token @@c++( ). Questo token fa sì che il programma usi l'analizzatore di espressioni C++ per analizzare l'espressione all'interno delle parentesi. Questo utilizzo consente al programma di usare direttamente i token di struttura C++.

  • Il flag ? viene usato con il comando r (Registers). Questo flag assegna valori tipizzati ai registri pseudo-registrati $t 0 e $t 1. Nel corpo del ciclo , $t 1 ha il tipo ntdll!_LDR_DATA_TABLE_ENTRY\*, quindi il programma può fare riferimenti ai membri diretti.

  • Gli alias denominati dall'utente $Base e $Mod vengono usati in questo programma. I segni del dollaro riducono la possibilità che questi alias siano stati usati in precedenza nella sessione del debugger corrente. I segni del dollaro non sono necessari. Il token ${/v: } interpreta l'alias letteralmente, impedendone la sostituzione se è stato definito prima dell'esecuzione dello script. È anche possibile usare questo token insieme a qualsiasi blocco per impedire l'uso delle definizioni alias prima dell'uso del blocco.

  • Il token con estensione block viene usato per aggiungere un passaggio aggiuntivo di sostituzione alias. La sostituzione dell'alias si verifica una volta per l'intero script quando viene caricato e una volta che ogni blocco viene immesso. Senza il token con estensione blocke le relative parentesi graffe, il comando .echo non riceve i valori dei $Mod e degli alias $Base assegnati nelle righe precedenti.

$$ Get module list LIST_ENTRY in $t0.
r? $t0 = &@$peb->Ldr->InLoadOrderModuleList
 
$$ Iterate over all modules in list.
.for (r? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t0;
 (@$t1 != 0) & (@$t1 != @$t0);
      r? $t1 = (ntdll!_LDR_DATA_TABLE_ENTRY*)@$t1->InLoadOrderLinks.Flink)
{
    $$ Get base address in $Base.
 as /x ${/v:$Base} @@c++(@$t1->DllBase)
 
 $$ Get full name into $Mod.
 as /msu ${/v:$Mod} @@c++(&@$t1->FullDllName)
 
 .block
    {
        .echo ${$Mod} at ${$Base}
    }
 
    ad ${/v:$Base}
    ad ${/v:$Mod}
}