Partager via


Exemples de programme de commandes de débogueur

Les sections suivantes décrivent les programmes de commande du débogueur.

Utilisation du jeton .foreach

L’exemple suivant utilise le jeton .foreach pour rechercher des valeurs WORD de 5a4d. Pour chaque valeur 5a4d trouvée, le débogueur affiche 8 valeurs DWORD, en commençant à l’adresse de l’emplacement où le DWORD 5a4d a été trouvé.

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

L’exemple suivant utilise le jeton .foreach pour rechercher des valeurs WORD de 5a4d. Pour chaque valeur 5a4d trouvée, le débogueur affiche 8 valeurs DWORD, commençant 4 octets avant l’adresse où le DWORD 5a4d a été trouvé.

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

L’exemple suivant affiche les mêmes valeurs.

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

Note Si vous souhaitez utiliser le nom de la variable dans la partie OutCommands de la commande, vous devez ajouter un espace après le nom de la variable. Par exemple, dans l’exemple précédent, il existe un espace entre l’emplacement de la variable et l’opérateur de soustraction.

L’option -[1] ainsi que la commande s (Rechercher dans la mémoire) font en sorte que sa sortie n’inclue que les adresses qu’elle trouve, et non les valeurs trouvées à ces adresses.

La commande suivante affiche des informations de module détaillées pour tous les modules qui se trouvent dans la plage de mémoire de 0x77000000 à 0x7F000000.

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

L’option 1m et la commande lm (Liste des modules chargés) entraînent une sortie qui n’inclut que les adresses des modules, et non la description complète des modules.

L’exemple précédent utilise le jeton ${ } (Alias Interpreter) pour s’assurer que les alias sont remplacés même s’ils sont en regard d’un autre texte. Si la commande n’a pas inclus ce jeton, la parenthèse d’ouverture à côté de la place empêche le remplacement de l’alias. Notez que le jeton ${} fonctionne sur les variables utilisées dans .foreach et sur les alias true.

Parcourir la liste des processus

L’exemple suivant décrit la liste des processus en mode noyau et affiche le nom exécutable de chaque entrée de la liste.

Cet exemple doit être stocké sous forme de fichier texte et exécuté avec la commande $$>< (Exécuter le fichier de script). Cette commande charge l’ensemble du fichier, remplace tous les retours chariot par des points-virgules et exécute le bloc résultant. Cette commande vous permet d’écrire des programmes lisibles en utilisant plusieurs lignes et mise en retrait, au lieu d’avoir à presser l’ensemble du programme sur une seule ligne.

Cet exemple illustre les fonctionnalités suivantes :

  • Les pseudo-registres $t 0, $t 1 et $t 2 sont utilisés comme variables dans ce programme. Le programme utilise également des alias nommés Procc et $ImageName.

  • Ce programme utilise l’évaluateur d’expression MASM. Toutefois, le jeton @@c++( ) s’affiche une fois. Ce jeton amène le programme à utiliser l’évaluateur d’expression C++ pour analyser l’expression entre parenthèses. Cette utilisation permet au programme d’utiliser directement les jetons de structure C++.

  • L’indicateur ? est utilisé avec la commande r (Registres). Cet indicateur affecte des valeurs typées au pseudo-registre $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
}

Parcourir la liste des LDR_DATA_TABLE_ENTRY

L’exemple suivant décrit la liste de LDR_DATA_TABLE_ENTRY en mode utilisateur et affiche l’adresse de base et le chemin d’accès complet de chaque entrée de liste.

Comme dans l’exemple précédent, ce programme doit être enregistré dans un fichier et exécuté avec la commande $$>< (Exécuter le fichier de script).

Cet exemple illustre les fonctionnalités suivantes :

  • Ce programme utilise l’évaluateur d’expression MASM. Toutefois, à deux endroits, le jeton @@c++( ) s’affiche . Ce jeton amène le programme à utiliser l’évaluateur d’expression C++ pour analyser l’expression entre parenthèses. Cette utilisation permet au programme d’utiliser directement les jetons de structure C++.

  • L’indicateur ? est utilisé avec la commande r (Registres). Cet indicateur affecte des valeurs typées aux pseudo-registres $t 0 et $t 1. Dans le corps de la boucle, $t 1 a le type ntdll !_LDR_DATA_TABLE_ENTRY\*, ce qui permet au programme d’effectuer des références directes aux membres.

  • Les alias nommés par l’utilisateur $Base et $Mod sont utilisés dans ce programme. Les signes dollar réduisent la possibilité que ces alias aient été utilisés précédemment dans la session actuelle du débogueur. Les signes du dollar ne sont pas nécessaires. Le jeton ${/v : } interprète littéralement l’alias, ce qui empêche son remplacement s’il a été défini avant l’exécution du script. Vous pouvez également utiliser ce jeton avec n’importe quel bloc pour empêcher l’utilisation des définitions d’alias avant le bloc.

  • Le jeton .block est utilisé pour ajouter une étape de remplacement d’alias supplémentaire. Le remplacement de l’alias se produit une fois pour l’ensemble du script lorsqu’il est chargé et une fois lorsque chaque bloc est entré. Sans le jeton .block et ses accolades, la commande .echo ne reçoit pas les valeurs des $Mod et $Base alias qui sont affectés dans les lignes précédentes.

$$ 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}
}