Lors de mon dernier poste traitant de la lib winpcap et de ses fonctionnalités, j'avais parlé, en conclusion, d'analyser son fonctionnement. Effectivement, j'étais resté perplexe et me posais une question.
En effet, il faut savoir que Microsoft restreint l'usage des "Raw Socket", où nous sommes en mesure de forger nos propres paquets. On m'a conseillé d'abandonner, et je me suis rendu compte que j'avais bien fait de désobéir ! >:)
Pour ceux qui veulent des infos sur les Raw Socket avec WinSock : http://msdn.microsoft.com/en-us/library/ms740548%28VS.85%29.aspx. Vous comprendrez plus ou moins que si vous voulez balancer un paquet ARP, vous pouvez allez vous faire foutre. Au moins, ça a le mérite d'être clair.
Mais, quand il s'agit de winpcap, on peut faire ce qu'on veut. Etrange, non ? Alors je me suis mis en tête d'analyser ça. La question : "Comment ça fonctionne ?". Question brève pour une réponse qui va se scinder en probablement plusieurs postes.
Dans ce premier poste, j'irai tout en douceur. On n'apprendra pas à balancer / sniffer des paquets, mais juste à récupérer la liste des interfaces réseau (c'est déjà bien pour commencer, non ?)
/!\ Les tests sont menés, ici, sous un windows XP SP3. Il se peut que ça marche sur la série XP, mais je ne garantie rien quant à Vista / Seven et encore moins sous les versions antérieures !
Les interfaces réseau
Sous Windows, on peut avoir une ou plusieurs interfaces réseau. Votre carte ethernet en est une, aussi bien que votre carte Wifi. J'ai même une clé USB Wifi reconnue en tant qu'interface réseau. Il se peut aussi que les machines virtuelles engendrent la création d'interfaces réseau exploitables ; je ne me suis pas penché sur ce genre de chose, mais certains reversers doivent avoir la réponse. ;)
Pour récupérer cette liste d'interfaces réseau, il faut aller chercher dans la base de registre à ce chemin : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}. Dans cette clé figurent des sous-clés ayant pour non 0000, puis 0001, puis 0002, ... A croire qu'on prévoit 10000 noms d'interfaces réseau.
Dans ces sous-clé se trouvent une clé nommée "Linkage", et, enfin, dans cette clé "Linkage" se trouve une valeur de type REG_MULTI_SZ - constante signifiant "plusieurs chaînes terminées par un octet nul", d'où le "SZ" - String Zero - qui correspond au chemin de notre interface réseau.
L'objectif du moment sera d'afficher chacune de ces interfaces. Grâce à l'API Win32 et à sa panoplie de fonctions RegMachiChouette(), ça doit pas être bien dur ! :)
Quelques fonctions utiles :
RegOpenKeyEx() : Permet d'ouvrir une clé existante : http://msdn.microsoft.com/en-us/library/ms724897(VS.85).aspx ;
RegQueryValueEx() : Permet de récupérer la valeur d'une clé. http://msdn.microsoft.com/en-us/library/ms724911(VS.85).aspx ;
CreateFile() : Permet de déterminer si une interface réseau est accessible (un bon indice pour la suite ! :]) : http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx.
Ok, on aura nos interfaces, mais il faudrait aussi la description de chacune d'elles.
Et bien j'ai tout de même trouvé, dans la clé SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards, des sous-clé ayant pour un un numéro sans les 0 devant, cette fois. Mais ce sont les mêmes numéros que nos interfaces réseau de HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}, donc il nous sera facile de faire le lien !
Maintenant, on se tait et on code.
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#define KEY_IF_RESEAUX "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
#define KEY_DESC_RESEAUX "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"
int main(int argc, char **argv) {
// Des handle de clefs
HKEY hKey, hCurrentKey, hDescKey;
// Variables
char* currentPathKey, *currentDescKey;
// Numéro de l'interface sous chaîne de caractères
char currentNumber[5];
// compteur de l'interface
int cpt = 0;
// Handle sur l'interface qui va nous permettre de savoir si on peut l'ouvrir ou pas
HANDLE hDevice;
// Variable dont on se sert pour connaître les octets retournés par une fonction
LONG dwBytesReturned;
// Tampons
char buffer[1024];
char devName[1024];
char desc[1024];
// Première étape : ouverture de la clé en question
LONG Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, KEY_IF_RESEAUX, 0, KEY_ALL_ACCESS, &hKey );
if(Status == ERROR_SUCCESS) {
// On la ferme puisqu'on n'en a plus besoin
RegCloseKey(hKey);
// Les sous-clé s'appellent toutes 0000, 0001, ... Donc il va falloir les parcourir.
// strlen("\\0000\\Linkage") + '\0' = 14
sprintf(currentNumber,"%04d", cpt);
// On prépare le chemin de la clé dans le registre
currentPathKey = (char*)malloc(strlen(KEY_IF_RESEAUX) + 14);
strcpy(currentPathKey, KEY_IF_RESEAUX);
strcat(currentPathKey, "\\");
strcat(currentPathKey, currentNumber);
strcat(currentPathKey, "\\Linkage");
// On ouvre cette clé
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, currentPathKey, 0, KEY_ALL_ACCESS, &hCurrentKey);
// Tant qu'on arrive à ouvrir la clé...
while(Status == ERROR_SUCCESS) {
// La valeur "Export" nous intéresse.
Status = RegQueryValueEx(hCurrentKey, "Export", NULL, NULL, (BYTE*)buffer, (DWORD*)&dwBytesReturned);
// Si on a réussit à lire la valeur, on l'affiche
if(Status == ERROR_SUCCESS) {
// On teste si l'interface est accessible
sprintf(devName, "\\\\.\\Global\\%s", &buffer[8]);
hDevice = CreateFile(devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
if(hDevice != INVALID_HANDLE_VALUE) {
// On essaie de récupérer la description de cette carte
sprintf(currentNumber, "%d", atoi(currentNumber)+1);
//printf("%s %s\n", buffer, currentNumber);
// strlen("\\xxxx") + '\0' = 6
currentDescKey = (char*)malloc(strlen(KEY_DESC_RESEAUX) + 6);
strcpy(currentDescKey, KEY_DESC_RESEAUX);
strcat(currentDescKey, "\\");
strcat(currentDescKey, currentNumber);
// On ouvre la clef de la description
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, currentDescKey, 0, KEY_ALL_ACCESS, &hDescKey);
if(Status == ERROR_SUCCESS) {
// "Description" nous intéresse
Status = RegQueryValueEx(hDescKey, "Description", NULL, NULL, (BYTE*)desc, (DWORD*)&dwBytesReturned);
if(Status == ERROR_SUCCESS) {
printf("%s %s\n", buffer, desc);
RegCloseKey(hDescKey);
}
}
free(currentDescKey);
CloseHandle(hDevice);
}
}
ZeroMemory(currentPathKey, strlen(KEY_IF_RESEAUX) + 14);
// On prépare le chemin de la clé suivante
sprintf(currentNumber,"%04d", ++cpt);
strcpy(currentPathKey, KEY_IF_RESEAUX);
strcat(currentPathKey, "\\");
strcat(currentPathKey, currentNumber);
strcat(currentPathKey, "\\Linkage");
// On la relit.
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, currentPathKey, 0, KEY_ALL_ACCESS, &hCurrentKey);
}
// On libère tout le tralala & on se casse
free(currentPathKey);
RegCloseKey(hCurrentKey);
}
return EXIT_SUCCESS;
}
Pour la source clean, c'est par ici : http://venom630.free.fr/geo/blog/reverse_pcap/part1/getInterfacesReseau.html. Le gros cadeau, c'est qu'il faille simplement compiler un seul fichier ! Pas de lib à linker ni rien.
Le résultat que j'obtiens :
C:\Documents and Settings\Geoffrey\Mes documents\c>getInterfacesReseau.exe
\Device\{8EEB3BBC-655E-4E05-A2DD-92A5325081A6} Belkin Wireless G Plus MIMO USB Network Adapter
\Device\{F9415153-9262-4C55-B0A4-D9D3B9911CB7} Realtek PCIe FE Family Controller
\Device\{8EEB3BBC-655E-4E05-A2DD-92A5325081A6} Belkin Wireless G Plus MIMO USB Network Adapter
\Device\{F9415153-9262-4C55-B0A4-D9D3B9911CB7} Realtek PCIe FE Family Controller
Pour récupérer les adresses IPs, j'ai pas cherché plus loin. Mais ça ne nous gênera pas pour la suite.
Et j'ai pas testé sur d'autres postes, donc je ne vous garantie rien. Mais alors rien du tout.
Conclusion
Certes, l'article a été très court, mais c'était pour vous montrer un aperçu. Là, on saura quelles interfaces emmerder pour pouvoir balancer nos paquets. Et n'importe quel paquet, de surcroit.
Geo
Aucun commentaire:
Enregistrer un commentaire