Debugging Windows, WinDbg, Driver Verifier et Tracing kernel

Ce cours dédiée au développement de drivers en kernel mode sans Framework

Moderator: Rick

Post Reply
Hydraxx
Site Admin
Posts: 124
Joined: Mon Jan 12, 2026 4:04 pm
Location: France
Contact:

Debugging Windows, WinDbg, Driver Verifier et Tracing kernel

Post by Hydraxx »

Debugging Windows, WinDbg, Driver Verifier et Tracing kernel

Objectif

Ce cours regroupe les techniques essentielles de debugging Windows en user mode et en kernel mode, l’utilisation de WinDbg, la validation de drivers avec Driver Verifier, ainsi que les mécanismes de logging et de tracing comme DbgPrintEx et ETW.

L’objectif est de disposer d’un workflow cohérent pour diagnostiquer un programme natif ou un driver : observer, instrumenter, provoquer les erreurs latentes, analyser les crashes et confirmer la correction.

1. Debugging user mode et kernel mode

Le debugging user mode agit sur un processus utilisateur.

Le debugging kernel agit sur le noyau, les drivers et les objets système.

La différence principale est l’impact d’une erreur :
  • en user mode, un bug provoque généralement le crash d’un processus ;
  • en kernel mode, une erreur peut provoquer un bugcheck et arrêter tout le système.
Le debugging kernel demande donc davantage de précautions, notamment l’utilisation d’une machine virtuelle.

Pour l’apprentissage et les tests de drivers, une VM avec snapshot est fortement recommandée.

2. Outils principaux

Les outils importants sont :
  • Code: Select all

    WinDbg
    : debugger principal pour Windows ;
  • Code: Select all

    Driver Verifier
    : vérifie dynamiquement le comportement d’un driver ;
  • Code: Select all

    Process Explorer
    : observation des processus, handles, modules et threads ;
  • Code: Select all

    Process Monitor
    : observation filesystem, registre et processus ;
  • Code: Select all

    GFlags
    : activation de paramètres de debug ;
  • Code: Select all

    DumpChk
    : vérification de dumps ;
  • Code: Select all

    UMDH
    : analyse de fuites mémoire user mode ;
  • Code: Select all

    TraceView
    : visualisation de traces ETW.
3. Architecture générale de WinDbg

Une session de debugging contient généralement :

Code: Select all

Host
  |
  | connexion de debug
  v
Target
Le host exécute le debugger.

Le target est la machine ou le processus observé.

En user mode, host et target peuvent être la même machine.

En kernel mode complet, il est courant d’utiliser une VM comme target et la machine principale comme host.

4. Types de commandes WinDbg

WinDbg utilise plusieurs familles de commandes.

Les commandes natives du debugger :

Code: Select all

r
u
k
lm
bp
bl
Les meta-commandes commencent souvent par un point :

Code: Select all

.symfix
.sympath
.reload
Les extensions commencent par :

Code: Select all

!
Exemples :

Code: Select all

!process
!thread
!irp
!pool
!locks
!verifier
!analyze -v
5. Les symboles

Les symboles sont essentiels pour obtenir des noms de fonctions, types, structures et variables.

Sans symboles, une stack ressemble davantage à :

Code: Select all

fffff800`12345678
fffff800`1234abcd
Avec les symboles :

Code: Select all

nt!KeBugCheckEx
MyDriver!DispatchDeviceControl
MyDriver!HandleRequest
Les commandes essentielles sont :

Code: Select all

.symfix
.reload
La commande

Code: Select all

.symfix
configure un chemin de symboles Microsoft standard.

Puis

Code: Select all

.reload
force le rechargement des symboles.

6. Modules

La commande

Code: Select all

lm
liste les modules chargés.

Pour obtenir davantage de détails :

Code: Select all

lmv
lmvm MyDriver
Les informations utiles comprennent :
  • adresse de base ;
  • taille ;
  • nom ;
  • chemin ;
  • symboles ;
  • timestamp ;
  • version.
7. Registres x64

La commande

Code: Select all

r
affiche les registres.

Les plus importants sont :

Code: Select all

RAX
RBX
RCX
RDX
R8
R9
RSP
RBP
RIP

Code: Select all

RIP
contient l’adresse de l’instruction courante.

Code: Select all

RSP
pointe vers le sommet de la stack.

Code: Select all

RAX
contient généralement la valeur de retour d’une fonction.

8. Convention d’appel x64 Windows

Les quatre premiers arguments d’une fonction sont généralement passés dans :

Code: Select all

RCX = argument 1
RDX = argument 2
R8  = argument 3
R9  = argument 4
Les arguments suivants se trouvent sur la stack.

La valeur de retour se trouve dans

Code: Select all

RAX
.

Exemple :

Code: Select all

CreateFileW(
    lpFileName,
    dwDesiredAccess,
    dwShareMode,
    ...
);
Au breakpoint sur la fonction :

Code: Select all

RCX = lpFileName
RDX = dwDesiredAccess
R8  = dwShareMode
9. Inspection mémoire

Les commandes

Code: Select all

d*
permettent d’afficher la mémoire.

Exemples :

Code: Select all

db adresse
dw adresse
dd adresse
dq adresse
da adresse
du adresse

Code: Select all

db
affiche des octets.

Code: Select all

dq
affiche des qwords.

Code: Select all

da
affiche une chaîne ASCII.

Code: Select all

du
affiche une chaîne Unicode.

Exemple :

Code: Select all

du @rcx
permet d’afficher une chaîne Unicode pointée par

Code: Select all

RCX
.

10. Désassemblage

La commande

Code: Select all

u
désassemble le code.

Exemple :

Code: Select all

u ntdll!NtCreateFile
On rencontre souvent :

Code: Select all

mov
call
jmp
cmp
test
jne
syscall
ret
Pour du debugging bas niveau, il est important de savoir lire le flux général sans forcément connaître chaque instruction par cœur.

11. Call stack

Les commandes :

Code: Select all

k
kb
kv
affichent la stack.

Code: Select all

k
donne une stack simple.

Code: Select all

kv
ajoute davantage d’informations.

Une stack permet de répondre à la question :

comment le programme est-il arrivé jusqu’à cette fonction ?

C’est souvent l’information la plus importante lors d’un crash.

12. Threads

La commande

Code: Select all

~
liste les threads.

On peut changer de thread puis analyser sa stack.

L’objectif est de repérer :
  • un thread bloqué ;
  • un thread en attente ;
  • un thread fautif ;
  • un thread qui détient un verrou.
13. Processus et contexte

En kernel debugging, le contexte processus est important.

La commande

Code: Select all

!process
permet d’afficher des informations sur les processus.

Elle peut révéler :
  • EPROCESS ;
  • PID ;
  • PEB ;
  • threads ;
  • token ;
  • handle count ;
  • working set ;
  • temps CPU.
Un driver peut s’exécuter dans le contexte de différents processus. Il faut donc toujours savoir dans quel contexte une adresse user mode ou un handle est interprété.

14. PEB et EPROCESS

Le

Code: Select all

PEB
est une structure user mode associée au processus.

Il contient notamment :
  • informations de loader ;
  • liste des modules ;
  • paramètres du processus ;
  • adresse de base de l’image.
L’

Code: Select all

EPROCESS
est la représentation kernel du processus.

Il contient des informations beaucoup plus larges sur le processus du point de vue du noyau.

Le schéma mental :

Code: Select all

User mode   -> PEB
Kernel mode -> EPROCESS
15. Debugging user mode

Deux méthodes principales :
  • lancer directement un programme avec WinDbg ;
  • attacher WinDbg à un processus déjà lancé.
Une fois attaché, le programme peut être en exécution, suspendu dans le debugger ou terminé.

On peut poser des breakpoints, inspecter les registres, la mémoire et les stacks.

16. Breakpoints

Les commandes essentielles sont :

Code: Select all

bp
bu
bl
bc
bd
be

Code: Select all

bp
crée un breakpoint résolu immédiatement.

Code: Select all

bu
crée un breakpoint différé basé sur un symbole.

Code: Select all

bl
liste les breakpoints.

Code: Select all

bc
supprime.

Code: Select all

bd
désactive.

Code: Select all

be
réactive.

17. Breakpoint sur CreateFileW

Exemple :

Code: Select all

bp kernel32!CreateFileW
g
Lorsque le breakpoint est atteint :

Code: Select all

r rcx
du @rcx
permet d’afficher le chemin du fichier.

La stack :

Code: Select all

k
permet de voir qui a appelé

Code: Select all

CreateFileW
.

18. De CreateFileW à NtCreateFile

Les API Win32 finissent souvent par appeler une API native.

Exemple conceptuel :

Code: Select all

CreateFileW
   |
   v
KernelBase
   |
   v
ntdll!NtCreateFile
   |
   v
syscall
   |
   v
kernel
Un breakpoint sur

Code: Select all

ntdll!NtCreateFile
permet d’observer la transition vers la couche native.

19. Stub syscall

Une fonction native x64 ressemble conceptuellement à :

Code: Select all

mov r10, rcx
mov eax, ServiceNumber
syscall
ret
Le numéro dans

Code: Select all

EAX
identifie le service système correspondant pour cette version de Windows.

Ces numéros ne doivent pas être codés en dur comme une interface stable.

20. Retour NTSTATUS

Une fonction native retourne généralement un

Code: Select all

NTSTATUS
dans

Code: Select all

RAX
.

Exemple :

Code: Select all

r rax
En code :

Code: Select all

if (!NT_SUCCESS(status))
{
    ...
}
21. Kernel debugging

Le kernel debugging complet permet :
  • breakpoints kernel ;
  • breakpoints dans un driver ;
  • inspection des objets kernel ;
  • analyse d’IRP ;
  • inspection de mémoire kernel ;
  • pas à pas dans DriverEntry ;
  • analyse de bugchecks.
22. Local kernel debugging

Le local kernel debugging permet certaines inspections sans utiliser de deuxième machine.

Il est utile pour observer certaines structures, mais il est plus limité que le debugging kernel complet.

Pour développer un driver, un vrai host/target reste préférable.

23. Full kernel debugging

Le full kernel debugging permet au host de suspendre complètement le target.

Lorsque le target est cassé dans le debugger :

la machine cible est gelée jusqu’à reprise de l’exécution.

C’est ce qui permet d’inspecter précisément l’état du noyau.

24. Connexion host / target

Plusieurs transports existent :
  • réseau ;
  • port série ;
  • named pipe avec VM ;
  • USB dans certains scénarios.
Avec une VM, un port série virtuel exposé comme named pipe est un scénario classique.

Pour des environnements modernes, le debugging réseau est également fréquent.

25. VM de debug

Un environnement pratique :

Code: Select all

PC principal
   |
   | WinDbg
   |
   +----> VM Windows
             |
             +-> driver testé
Avantages :
  • snapshot ;
  • reboot rapide ;
  • isolation ;
  • récupération après BSOD ;
  • possibilité de tester Driver Verifier sans risquer l’hôte.
26. Breakpoint sur DriverEntry

Si le driver n’est pas encore chargé :

Code: Select all

bu MyDriver!DriverEntry
Puis :

Code: Select all

g
Lorsque le driver se charge, WinDbg résout le symbole et stoppe dans

Code: Select all

DriverEntry
.

27. Breakpoints dans un driver

Exemples :

Code: Select all

bu MyDriver!DispatchDeviceControl
bu MyDriver!Unload
bu MyDriver!MyFunction
Un breakpoint peut aussi être placé à un offset ou sur une adresse précise.

28. !process

La commande :

Code: Select all

!process 0 0
peut lister les processus.

Un niveau de détail plus élevé permet d’afficher les threads et stacks.

Cette commande est essentielle pour comprendre le contexte d’exécution kernel.

29. !thread

La commande :

Code: Select all

!thread adresse
permet d’examiner un thread kernel.

Informations utiles :
  • état ;
  • raison d’attente ;
  • priorité ;
  • processus propriétaire ;
  • stack ;
  • IRP associés.
30. !irp

La commande :

Code: Select all

!irp adresse
affiche un IRP.

Elle permet de voir :
  • major function ;
  • minor function ;
  • stack locations ;
  • driver courant ;
  • completion routine ;
  • état de l’IRP.
Très utile pour les problèmes d’I/O WDM.

31. Logging kernel simple

Les macros classiques sont :

Code: Select all

KdPrint
DbgPrint
Exemple :

Code: Select all

KdPrint(("Driver loaded\n"));
Exemple avec variable :

Code: Select all

KdPrint(("Status = 0x%08X\n", status));
32. Limites de DbgPrint/KdPrint

Le logging simple a plusieurs limites :
  • beaucoup de bruit ;
  • filtrage limité ;
  • coût potentiel ;
  • peu adapté à la production ;
  • messages difficiles à structurer.
Pour de gros drivers,

Code: Select all

DbgPrintEx
ou ETW sont plus adaptés.

33. DbgPrintEx et KdPrintEx

Code: Select all

DbgPrintEx
ajoute :
  • ComponentId ;
  • Level ;
  • filtrage.
Exemple :

Code: Select all

DbgPrintEx(
    DPFLTR_IHVDRIVER_ID,
    DPFLTR_INFO_LEVEL,
    "DriverEntry called\n"
);
Les niveaux classiques comprennent :

Code: Select all

DPFLTR_ERROR_LEVEL
DPFLTR_WARNING_LEVEL
DPFLTR_TRACE_LEVEL
DPFLTR_INFO_LEVEL
34. Fonctions de logging personnalisées

Un driver peut créer des wrappers :

Code: Select all

LogInfo(...)
LogWarning(...)
LogError(...)
Exemple :

Code: Select all

LogInfo("DriverEntry called");
LogError("IoCreateDevice failed: 0x%08X", status);
Cela améliore la lisibilité et centralise le format des messages.

35. ASSERT

Une assertion vérifie qu’une condition censée être toujours vraie l’est effectivement.

Exemple :

Code: Select all

ASSERT(DeviceExtension != NULL);
ou :

Code: Select all

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
Une assertion ne remplace jamais une vraie gestion d’erreur pour des données ou états pouvant être invalides en production.

36. NT_ASSERT

Code: Select all

NT_ASSERT
est une macro moderne destinée au même type d’usage.

Exemple :

Code: Select all

NT_ASSERT(NT_SUCCESS(status));
Les assertions servent surtout à vérifier des invariants internes.

37. Checked et Free builds

Historiquement, Windows proposait notamment :
  • Free build ;
  • Checked build.
Le checked build contenait davantage de vérifications et d’assertions.

Cette distinction est aujourd’hui surtout historique.

Pour le développement moderne, on utilise plutôt symboles, WinDbg, Driver Verifier, assertions et instrumentation ciblée.

38. Driver Verifier

Driver Verifier est un outil qui surveille le comportement des drivers et force certains bugs latents à devenir visibles.

Il peut provoquer volontairement un bugcheck lorsqu’une violation grave est détectée.

Le but est de transformer un bug aléatoire en erreur déterministe et analysable.

39. Configuration de Driver Verifier

L’outil graphique peut être lancé avec :

Code: Select all

verifier
On peut choisir :
  • options standard ;
  • options personnalisées ;
  • drivers spécifiques.
Il est préférable de sélectionner uniquement le driver testé plutôt que tous les drivers du système.

40. Désactivation

Commande utile :

Code: Select all

verifier /reset
Puis redémarrage.

Il faut connaître cette commande avant d’activer Verifier.

En cas de boucle de BSOD, le mode sans échec peut être nécessaire.

41. Special Pool

Special Pool aide à détecter :
  • buffer overflow ;
  • buffer underrun ;
  • use-after-free ;
  • corruption de pool.
Le principe consiste à placer certaines allocations près de pages de garde pour rendre les accès invalides immédiatement visibles.

42. Pool Tracking

Pool Tracking surveille les allocations du driver.

Il aide à détecter :
  • fuites de pool ;
  • allocations jamais libérées ;
  • mauvaise gestion des pool tags.
Un pool tag clair facilite énormément le diagnostic.

43. Force IRQL Checking

Cette option détecte des violations liées à l’IRQL.

Exemple :

Code: Select all

KeAcquireSpinLock(...);

// IRQL = DISPATCH_LEVEL
// accès paged memory -> dangereux
Elle permet aussi de détecter certains appels de routines incompatibles avec le niveau courant.

44. I/O Verification

I/O Verification vérifie la gestion des IRP.

Erreurs typiques :
  • double completion ;
  • IRP jamais complété ;
  • mauvaise stack location ;
  • mauvais forwarding ;
  • mauvaise completion routine ;
  • mauvais

    Code: Select all

    IoStatus.Information
    .
45. Deadlock Detection

Deadlock Detection surveille l’ordre d’acquisition des locks.

Exemple classique :

Code: Select all

Thread A :
Lock1
Lock2

Thread B :
Lock2
Lock1
Cela peut produire un cycle.

46. Low Resources Simulation

Cette option provoque volontairement des échecs d’allocation.

Exemple :

Code: Select all

PVOID p = ExAllocatePool2(...);

if (p == NULL)
{
    ...
}
Un driver robuste doit correctement gérer ce cas.

47. DMA Verification

DMA Verification concerne surtout les drivers qui utilisent directement le DMA.

Elle est moins importante pour un driver logiciel simple sans DMA.

48. Security Checks

Les vérifications de sécurité peuvent détecter certaines mauvaises pratiques :
  • mauvais paramètres ;
  • mauvaise gestion de handles ;
  • violations de règles d’accès ;
  • mauvaises hypothèses dans le code.
49. Analyse d’un crash

Après un bugcheck, la première commande importante est :

Code: Select all

!analyze -v
Elle fournit notamment :
  • bugcheck ;
  • arguments ;
  • module suspect ;
  • stack ;
  • contexte probable.
Ensuite, on utilise des commandes ciblées selon le problème.

50. Analyse d’une corruption mémoire

Workflow typique :

Code: Select all

Driver Verifier
   |
   +-> Special Pool
   |
   +-> crash au moment de la violation
   |
   +-> !analyze -v
   |
   +-> !pool
   |
   +-> stack
L’objectif est d’identifier l’endroit où la mémoire a été mal utilisée, pas seulement l’endroit où le crash final apparaît.

51. Analyse d’une fuite

Une fuite de pool peut être révélée par :
  • Pool Tracking ;
  • pool tags ;
  • augmentation progressive de mémoire ;
  • inspection avec les extensions WinDbg.
Le code doit maintenir une correspondance logique :

Code: Select all

allocation -> utilisation -> libération
52. Analyse d’un mauvais IRQL

Lorsqu’un bugcheck indique une erreur IRQL :
  • lire la stack ;
  • identifier l’API appelée ;
  • identifier le niveau IRQL ;
  • vérifier si la mémoire utilisée est paginée ;
  • corriger l’architecture.
Souvent, la correction consiste à déplacer le travail vers un contexte à

Code: Select all

PASSIVE_LEVEL
.

53. Analyse d’un deadlock

Commandes utiles :

Code: Select all

!locks
!thread
k
Il faut identifier :
  • quel thread attend ;
  • quel verrou il attend ;
  • quel thread détient ce verrou ;
  • quel autre verrou ce second thread attend.
54. Analyse d’un IRP bloqué

Commandes :

Code: Select all

!irp adresse
!thread adresse
k
On cherche à comprendre où l’IRP est bloqué et quelle stack location est active.

55. ETW

ETW signifie :

Code: Select all

Event Tracing for Windows
C’est un système de tracing haute performance.

Concepts :

Code: Select all

Provider
Session
Event
Consumer
Un provider émet des événements.

Une session collecte.

Un consumer lit ou affiche.

56. Pourquoi ETW

ETW est préférable à

Code: Select all

DbgPrint
lorsqu’on veut :
  • beaucoup d’événements ;
  • faible coût ;
  • traces structurées ;
  • filtrage ;
  • analyse temporelle ;
  • utilisation hors debugger ;
  • journalisation en production.
57. Provider ETW

Un provider est identifié par un GUID.

Le driver :
  • enregistre le provider ;
  • émet des événements ;
  • désenregistre le provider au cleanup.
Le GUID distingue un provider des autres sources de traces.

58. Sessions ETW

Une session peut fonctionner :
  • en temps réel ;
  • vers un fichier ETL.
Le temps réel est pratique pour le debugging.

Le fichier ETL est utile pour une analyse ultérieure.

59. TraceView

TraceView peut :
  • créer une session ;
  • ajouter un provider ;
  • utiliser un GUID ;
  • afficher les événements ;
  • enregistrer dans un fichier.
Le principe général est plus important que l’interface exacte, qui peut évoluer avec les outils.

60. Comparaison logging / debugging / tracing

Code: Select all

KdPrint / DbgPrint
Simple, rapide, idéal pendant le développement.

Code: Select all

DbgPrintEx
Ajoute niveaux et filtrage.

Code: Select all

WinDbg
Permet l’inspection interactive de l’état.

Code: Select all

Driver Verifier
Force les mauvaises pratiques à devenir visibles.

Code: Select all

ETW
Permet un tracing performant et structuré.

61. Workflow de debug conseillé
  • reproduire le bug ;
  • ajouter des logs ciblés ;
  • observer la stack et l’état ;
  • activer Driver Verifier ;
  • reproduire sous Verifier ;
  • analyser le dump ;
  • identifier la vraie cause ;
  • corriger ;
  • retenter avec Verifier ;
  • désactiver Verifier quand les tests sont terminés.
62. Workflow de validation d’un driver

Avant de considérer un driver comme stable :
  • tester

    Code: Select all

    DriverEntry
    ;
  • tester unload ;
  • tester plusieurs load/unload ;
  • tester les IOCTL valides ;
  • tester les IOCTL invalides ;
  • tester erreurs d’allocation ;
  • tester concurrence ;
  • tester IRQL ;
  • tester Driver Verifier ;
  • tester crash dump ;
  • tester les traces.
63. Bonnes pratiques
  • Toujours utiliser une VM pour les tests risqués.
  • Garder un snapshot propre.
  • Utiliser des pool tags compréhensibles.
  • Vérifier chaque

    Code: Select all

    NTSTATUS
    .
  • Éviter les logs excessifs.
  • Utiliser les symboles correspondant au binaire.
  • Ne pas ignorer un bugcheck provoqué par Verifier.
  • Tester les chemins d’erreur.
  • Documenter les invariants avec des assertions.
64. Pièges classiques

Symboles incorrects

La stack devient trompeuse ou incomplète.

Mauvais contexte processus

Une adresse user mode peut être interprétée dans le mauvais processus.

Breakpoint non résolu

Le module n’est peut-être pas encore chargé : utiliser

Code: Select all

bu
.

Trop de logs

Le signal utile est perdu dans le bruit.

Verifier sur tous les drivers

Cela complique inutilement le diagnostic.

Tester sur la machine principale

Un mauvais driver peut rendre le système instable.

65. Historique

Certaines notions anciennes restent utiles comme culture générale :
  • checked builds ;
  • Windows 98/Me ;
  • anciens transports de debug ;
  • anciens outils secondaires.
Mais elles ne doivent pas être prioritaires dans un environnement Windows moderne.

66. Commandes WinDbg essentielles

À connaître en priorité :

Code: Select all

r
u
db
du
k
kv
lm
lmvm
bp
bu
bl
bc
~
.symfix
.reload
!process
!thread
!irp
!pool
!locks
!verifier
!analyze -v
67. APIs et macros essentielles

À retenir :

Code: Select all

KdPrint
DbgPrint
DbgPrintEx
KdPrintEx
ASSERT
NT_ASSERT
Et les outils :

Code: Select all

WinDbg
Driver Verifier
TraceView
ETW
68. Schéma mental global

Code: Select all

Bug
 |
 v
Logs
 |
 v
WinDbg
 |
 v
Driver Verifier
 |
 v
Crash déterministe
 |
 v
!analyze -v
 |
 +-> stack
 +-> IRP
 +-> pool
 +-> locks
 +-> IRQL
 |
 v
Correction
 |
 v
Re-test
 |
 v
ETW / validation finale
69. Exercices pratiques

Exercice 1 :

Code: Select all

bp kernel32!CreateFileW
Afficher le chemin avec :

Code: Select all

du @rcx
Exercice 2 :

Code: Select all

bp ntdll!NtCreateFile
Observer les registres et la transition vers

Code: Select all

syscall
.

Exercice 3 :

Code: Select all

bu MyDriver!DriverEntry
Charger le driver et inspecter les arguments.

Exercice 4 :

Code: Select all

!process 0 0
Choisir un processus puis examiner un thread.

Exercice 5 :

Créer volontairement une fuite de pool dans une VM et utiliser Driver Verifier pour la détecter.

Exercice 6 :

Créer une trace ETW minimale et la visualiser dans TraceView.

70. À retenir en priorité
  • WinDbg sert à comprendre l’état réel du programme ou du noyau.
  • Les symboles sont indispensables.
  • La convention d’appel x64 permet de retrouver rapidement les arguments.
  • Code: Select all

    k
    ,

    Code: Select all

    r
    ,

    Code: Select all

    u
    ,

    Code: Select all

    du
    et

    Code: Select all

    lm
    sont des commandes de base.
  • Code: Select all

    !process
    ,

    Code: Select all

    !thread
    ,

    Code: Select all

    !irp
    ,

    Code: Select all

    !pool
    et

    Code: Select all

    !locks
    sont essentielles en kernel.
  • Code: Select all

    bu
    est utile pour les fonctions de drivers non encore chargés.
  • Code: Select all

    KdPrint
    et

    Code: Select all

    DbgPrintEx
    servent à instrumenter rapidement.
  • Code: Select all

    ASSERT
    et

    Code: Select all

    NT_ASSERT
    servent à vérifier des invariants.
  • Driver Verifier détecte des violations difficiles à reproduire autrement.
  • Special Pool aide pour les corruptions mémoire.
  • Pool Tracking aide pour les fuites.
  • Force IRQL Checking aide pour les erreurs d’IRQL.
  • I/O Verification aide pour les erreurs d’IRP.
  • Deadlock Detection aide pour les problèmes de locks.
  • Low Resources Simulation teste les chemins d’échec.
  • ETW est adapté au tracing structuré et performant.
71. Conclusion

Le debugging Windows bas niveau ne repose pas sur un seul outil.

WinDbg permet d’observer et d’analyser.

Driver Verifier transforme de nombreux bugs silencieux en erreurs explicites.

Les assertions permettent de détecter immédiatement les états impossibles pendant le développement.

Les fonctions de debug permettent une instrumentation rapide.

ETW permet un tracing structuré et performant.

Un workflow solide consiste à combiner ces outils plutôt qu’à les utiliser séparément.

Who is online

Users browsing this forum: No registered users and 0 guests