dimanche 3 février 2008

Stack Watcher/Registers Viewer

Plop all :)
Voilà quelque temps que ce sujet m'intriguais, j'ai décidé de faire un petit programme pour voir l'état des registres d'un thread en temps réel.
Voici comme on va se dépatouiller :

1.La rien de bien compliqué, on récupère l'id du processus voulu.

Les APIs nécessaires :
-CreateToolhelp32Snapshot() -> http://msdn2.microsoft.com/en-us/library/ms682489(VS.85).aspx
-Process32First() -> http://msdn2.microsoft.com/en-us/library/ms684834(VS.85).aspx
-Process32Next() -> http://msdn2.microsoft.com/en-us/library/ms684836(VS.85).aspx
Sans oublier notre structure PROCESSENTRY32. -> http://msdn2.microsoft.com/en-us/library/ms684839(VS.85).aspx

typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32,
*PPROCESSENTRY32;

2.On établit la liste de tous les threads en cour d'execution. Comme pour créer une liste des processus CreateToolhelp32Snapshot() mais avec TH32CS_SNAPTHREAD en premier argument.

3.On parcourt et recherche les threads appartenant à notre processus. On parcourt la liste des threads avec :
-Thread32First() -> http://msdn2.microsoft.com/en-us/library/ms686728(VS.85).aspx
-Thread32Next() -> http://msdn2.microsoft.com/en-us/library/ms686731(VS.85).aspx
Et on remplit la structure THREADENTRY32 -> http://msdn2.microsoft.com/en-us/library/ms686735(VS.85).aspx

typedef struct tagTHREADENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ThreadID;
DWORD th32OwnerProcessID;
LONG tpBasePri;
LONG tpDeltaPri;
DWORD dwFlags;
} THREADENTRY32,
*PTHREADENTRY32;

Ceci reste très similaire à la façon de traiter les processus.

4.On récupère les informations sur la pile. Ce qui nous interresse.
Pour celà on doit stopper l'execution du thread avec SuspendThread() et reprendre son execution avec ResumeThread. Entre temps on aura utilisé la fonction
GetThreadContext() :

BOOL WINAPI GetThreadContext(
__in HANDLE hThread,
__inout LPCONTEXT lpContext
);

qui nous permet de récupérer les inforamtions sur la pile au travers de la structure CONTEXT (à voir dans winnt.h) :

typedef struct _CONTEXT {
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;


Voilà on a donc maintenant un dump des registres de notre processus.
Un petit rappel sur les registres :

Les registres principaux :

EAX : Registre 32 bits. 16 bits : Ax formé par Ah : 8 bits et Al : 8bits. Fonction : Accumulateur

EBX : Registre 32 bits. 16 bits : Bx formé par Bh : 8 bits et Bl : 8bits. Fonction : Base, utilisé lors de l'accès à une zone mémoire.

ECX : Registre 32 bits. 16 bits : Cx formé par Ch : 8 bits et Cl : 8bits. Fonction : Compteur.

EDX : Registre 32 bits. 16 bits : Dx formé par Dh : 8 bits et Dl : 8bits. Fonction : Stockage de données.

EIP (Instruction Pointer) : Registre 32 bits. Pointe sur la prochaine instruction a executer.

ESI (Source Index) : Registre 32 bits. Pointer sur la variable source.

EDI (Destination Pointer) : Registre 32 bits. Pointer sur la variable destinataire.

EBP (Base Pointer) : Registre 32 bits. Pointe sur le premier élémente de la pile.

ESP (Stack Pointer) : Registre 32 bits. Pointe sur le dernier élément de la pile.


Les registres debug :

Une bonne doc ici : http://en.wikipedia.org/wiki/Debug_register

Les registres de Segments :

CS (Code Segment) : Mémorise le segment où se trouve le code en cours d'execution

DS (Data Segment) : Mémorise le segment où se trouvent les données du programme

ES (Extra Segment) : Il peut être utilisé à faire ce que l'on veut.

SS (Stack Segment) : Mémorise le segment où se trouve la pile de données du programme.

Le code : Stack.cpp
Le projet + binaire : StackWatcher.zip

Voilà ce sera tout pour cet article.
Have Fun ;)
lilxam.

Aucun commentaire: