[.net2] winpcap wrapper

Soyez le premier à donner votre avis sur cette source.

Vue 20 256 fois - Téléchargée 1 802 fois

Description

Ce wrapper de WinPcap fait parti d'un de mes projets professionnels, cela faisait un bout de temps que je le trainais sur mon disque.
Comme c'est noel je me suis décidé à partager ce petit cadeau :)

Vous devez installer le driver WinPcap auparavant: http://www.winpcap.org/ (peut importe la version,3 ou 4 beta du driver fonctionne correctement)
Si vous recherchez la doc du driver elle se trouve ici http://www.winpcap.org/devel.htm
Dans la solution se trouve un dossier Public, ces classes sont extraitent de JPcap une librairie Java exploitant WinPcap http://sourceforge.net/projects/jpcap (et oui je n'invente rien).

J'ai également joint un fichier dump.txt que j'ai capturé avec cette source. Vous pouvez le visualiser dans la partie Dump -> Ouvrir.

La source est commentée mais sans plus, je me suis beaucoup inspiré des exmples fournis dans la doc de WinPcap.

Apercu de la classe WinPcapWrapper:

-Evénements:
--InnerMessage //Evénement pour les messages d'erreur internes.
--PacketArrival //Evénement d'arrivée d'un paquet.
--EndCapture //Evénement de fin de capture d'un paquet.
--StatisticsPackets //Evénement où sont recu les statistiques.

-Propriétés:
--DeviceHandle //Obtient le handle du matériel branché.
--Mode //Mode de capture du driver.
--IsEnabledDump //Indique si un dump sur la capture est ouvert.
--DumpHandle //Obtient le handle du dump.

-Méthodes publiques:
--GetDevices() //Obtient la liste des matériels réseaux présent.
--OpenDevice(PcapDevice device) //Ouverture d'un handle sur le matériel.
--OpenDevice(PcapDevice device, bool promisc) //Ouverture d'un handle sur le matériel.
--OpenDevice(PcapDevice device, bool promisc, int timeout) //Ouverture d'un handle sur le matériel.
--CloseDevice() //Libère le handle tenu sur le matériel.
--CloseDump() //Libère le handle tenu sur le fichier de dump.
--StartCapture() //Démarre la capture.
--StartCapture(string filter) //Démarre la capture en mettant un filtrage des paquets à capturer. (similaire à la méthode SetFilter(string filter)
--StartCapture(int packetcount) //Démarre la capture en se limitant à capturer un certains nombre de paquets.
--StartCapture(string filter, int packetcount) //Reprend les 2 méthodes ci-dessus.
--SetFilter(string filter) //Compile au niveau kernel une expression de filtre et associe le filtre au matériel.
--StopCapture() //Arrête la capture.
--OpenDump(string filename) //Ouverture d'un handle pour un dump de la capture.
--DumpPacket(Packet packet) //Ecriture d'un paquet dans le fichier dump.
--ReadDump(string filename) //Lecture d'un fichier de dump.

-Méthodes privées:
--WaitForStop() //Méthode bloquante sur le processus de capture tant que celui-ci n'est pas terminée ou arrêtée.
--CapturePacketLoop() //Méthode exécutant les procédures du processus de capture.
--GetNextPacket(out Packet packet) //Récupère le paquet suivant capturé.
--GetNextPacketOffline(IntPtr p, out Packet packet) //Récupère le paquet suivant capturé en mode dump (offline).
--SetMode(PcapMode value) //Applique un mode de capture supporté par le driver.
--InvokePacketArrivalEvent(Packet packet) //Méthode traitant l'arrivée d'un paquet suivant son mode de capture.
--InvokeEndCaptureEvent(DateTime date, bool error) //Méthode traitant la fin de réception d'un paquet.
--GetDatalink() //Récupère la couche réseau.
--GetErr(string prefix) //Traduit les erreurs internes de WinPcap.

-Apercu des autres classes
--WinPcapNative //Classe définissant les méthodes, structures, constantes du mode utilisateur du driver WinPcap (wpcap.dll).
--PcapHeader //Classe fournissant les données d'en-tête d'un paquet (wrapper de la structure pcap_pkhdr). Non héritable.
--PcapDevice //Classe fournissant les données sur un matériel réseau. Non héritable.
--EndCaptureEventArgs //Classe fournissant les données pour l'événement EndCapture.
--InnerMessageEventArgs //Classe fournissant les données pour l'événement InnerMessage.
--PacketArrivalEventArgs //Classe fournissant les données pour l'événement PacketArrival.
--StatisticsEventArgs //Classe fournissant les données pour l'événement StatisticsPackets.

Conclusion :


Voila....
J'attend vos critiques, notes, etc....

Bon dév à tous :)

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
3
Date d'inscription
samedi 30 décembre 2000
Statut
Membre
Dernière intervention
30 octobre 2010

Je me permet de relancer cette superbe source. par contre petite question, comment capturer les paquets qui utilisent le protocole FTP, SMTP, POP ou tout autre protocole du genre ?
Messages postés
3
Date d'inscription
vendredi 1 mai 2009
Statut
Membre
Dernière intervention
10 août 2009

Voila ma fonction de traitement d'arriver de paquet. Elle utilise une listview pour afficher les details du paquet.

void PaquetRecu(object sender, EventArgs e)
{
if (InvokeRequired)
{
this.Invoke(this.mydelegate, new Object[] { sender, e });
}
else
{
ThreadT T = (ThreadT)sender;
ListViewItem Paquet = null;
WinPcap.Public.Packets.Packet P = T.Paquet;
bool Reconnu = true;
EthernetPacket Peth = (EthernetPacket)P; if (Peth.EthernetProtocol EthernetProtocols_Fields.IP)// || Peth.EthernetProtocol EthernetProtocols_Fields.IPV6 )
{
IPPacket PIP = (IPPacket)P;
if (PIP.IPProtocol == IPProtocols_Fields.TCP)
{
TCPPacket PTCP = (TCPPacket)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PTCP.Timeval.Date.TimeOfDay.ToString(), PTCP.SourceAddress, PTCP.SourcePort.ToString(), PTCP.DestinationAddress, PTCP.DestinationPort.ToString(), "IP/TCP", PTCP.PcapHeader.PacketLength.ToString() }, -1);
}
else if (PIP.IPProtocol == IPProtocols_Fields.ICMP)
{
ICMPPacket PICMP = (ICMPPacket)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PICMP.Timeval.Date.TimeOfDay.ToString(), PICMP.SourceAddress, "none", PICMP.DestinationAddress, "none", "IP/ICMP", PICMP.PcapHeader.PacketLength.ToString() }, -1);
}
else if (PIP.IPProtocol == IPProtocols_Fields.UDP)
{
UDPPacket PUDP = (UDPPacket)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PUDP.Timeval.Date.TimeOfDay.ToString(), PUDP.SourceAddress, PUDP.SourcePort.ToString(), PUDP.DestinationAddress, PUDP.DestinationPort.ToString(), "IP/UDP", PUDP.PcapHeader.PacketLength.ToString() }, -1);
}
else
{
//MessageBox.Show("Arrivée d'un paquet de protocole de couche 4 inconnu\n\n Numero Protocol: " + PIP.Protocol.ToString(), "Protocole non reconnu", MessageBoxButtons.OK);
//Reconnu = false;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PIP.Timeval.Date.TimeOfDay.ToString(), PIP.SourceAddress, "Unknown", PIP.DestinationAddress, "Unknown", "IP/Unknown", PIP.PcapHeader.PacketLength.ToString() }, -1);
}
}
else if (Peth.EthernetProtocol == EthernetProtocols_Fields.IPV6)
{
IP6Packet PIP6 = (IP6Packet)P;
if (PIP6.Protocol == IP6Protocols_Fields.TCP)
{
TCPPacketIP6 PTCP = (TCPPacketIP6)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PTCP.Timeval.Date.TimeOfDay.ToString(), PTCP.SourceAddress, PTCP.SourcePort.ToString(), PTCP.DestinationAddress, PTCP.DestinationPort.ToString(), "IPv6/TCP", PTCP.PcapHeader.PacketLength.ToString() }, -1);
}
else if (PIP6.Protocol == IP6Protocols_Fields.ICMP)
{
ICMPPacketIP6 PICMP = (ICMPPacketIP6)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PICMP.Timeval.Date.TimeOfDay.ToString(), PICMP.SourceAddress, "none", PICMP.DestinationAddress, "none", "IPv6/ICMP", PICMP.PcapHeader.PacketLength.ToString() }, -1);
}
else if (PIP6.Protocol == IP6Protocols_Fields.UDP)
{
UDPPacketIP6 PUDP = (UDPPacketIP6)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PUDP.Timeval.Date.TimeOfDay.ToString(), PUDP.SourceAddress, PUDP.SourcePort.ToString(), PUDP.DestinationAddress, PUDP.DestinationPort.ToString(), "IPv6/UDP", PUDP.PcapHeader.PacketLength.ToString() }, -1);
}
else
{
//MessageBox.Show("Arrivée d'un paquet de protocole de couche 4 inconnu\n\n Numero Protocol: " + PIP6.Protocol.ToString(), "Protocole non reconnu", MessageBoxButtons.OK);
//Reconnu = false;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PIP6.Timeval.Date.TimeOfDay.ToString(), PIP6.SourceAddress, "Unknown", PIP6.DestinationAddress, "Unknown", "IPv6/Unknown", PIP6.PcapHeader.PacketLength.ToString() }, -1);
}
}

else if (Peth.EthernetProtocol == EthernetProtocols_Fields.ARP)
{
ARPPacket PARP = (ARPPacket)P;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), PARP.Timeval.Date.TimeOfDay.ToString(), PARP.SourceHwAddress, "none", PARP.DestinationHwAddress, "none", "ARP", PARP.PcapHeader.PacketLength.ToString() }, -1);
}
else
{
if (Peth.DestinationHwAddress == "01:80:c2:00:00:00") //verification de STP par l'adresse de destination
{
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), Peth.Timeval.Date.TimeOfDay.ToString(), Peth.SourceHwAddress, "none", Peth.DestinationHwAddress, "none", "STP", Peth.PcapHeader.PacketLength.ToString() }, -1);
}
else
{
//MessageBox.Show("Arrivée d'un paquet de protocole de couche 3 inconnu\n\n Numero Protocol: " + Peth.EthernetProtocol.ToString(), "Protocole non reconnu", MessageBoxButtons.OK);
//Reconnu = false;
Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), Peth.Timeval.Date.TimeOfDay.ToString(), Peth.SourceHwAddress, "none", Peth.DestinationHwAddress, "none", "Ethernet Unknown", Peth.PcapHeader.PacketLength.ToString() }, -1);
}
}

//Paquet = new ListViewItem(new string[] { NumPaquet.ToString(), P.Timeval.Date.TimeOfDay.ToString(), Peth.PcapHeader, "", "", "", "" }, -1);
NumPaquet++;

if (Reconnu)
{
ListePaquets.Items.Add(Paquet);
Paquet.EnsureVisible();
}
Reconnu = true;
}
}

Ce qu'il faut retenir c'est que pour avoir les informations intéressantes il faut caster le paquet en fonction des champs de la couche protocolaire inférieure.
Mon code te donne de bons exemples. Concernant la listview, rien de plus simple comme tu peux le voir.
"Paquet.EnsureVisible();" permet d'effectuer le defilement.

PS: Je n'ai toujours pas pris le temps de m'occuper de la partie emission de mon programme mais je vous tiendrais informé quand cela sera fait.
Messages postés
1
Date d'inscription
samedi 6 mars 2004
Statut
Membre
Dernière intervention
5 août 2009

Bonjour ,
Tres Interessant , encore un peu complique pour moi car je suis debutant en C# et en analyse de protocole.
Je n'arrive pas a extraire les IP Source et Destination des packets (ou headers ?)et les visualiser dans une listview.
J 'utilise votre example "test" et essaye de mettre le code dans LibWinPcap_PacketArrival mais je ne vois pas comment extraire les IP des packets. Je suppose qu'on peut aussi utiliser le dossier public et les classes Java pour analyser les packets.
J 'aimerais que vous completiez "test" avec des examples d'interpretation de packet (protocol, adresses, etc..)



Merci Daniel
sK
Messages postés
3
Date d'inscription
vendredi 1 mai 2009
Statut
Membre
Dernière intervention
10 août 2009

Je viens aussi d'implémenter la classe IP6Packet (pff c'est lourd à faire).

Sinon pour les erreurs IRQ j'arrive a en avoir autant que je veux ce soir. As tu déjà utiliser plusieurs LibWinPcap en parallèle? Personnellement j'ai plusieurs threads qui tournent (un pour chaque interface) et c'est au moment ou je les désactive que ça plante.(en général quand je rapproche activation et désactivation).

J'ai aussi réussi à lever une exception AccesViolationException lors de l'utilisation de la méthode StopCapture de la classe LibWinPcap. Pourtant le paramètre en entrée de pcap_close (c'est la que ça bloque précisément) semble correct...

Je vais y réfléchir et voir ce que ça donne.
Messages postés
2375
Date d'inscription
jeudi 12 juillet 2001
Statut
Modérateur
Dernière intervention
15 décembre 2018
22
J'avoue ne pas avoir prêter attention aux fonctions winpcap d'émission de paquet voila pourquoi je ne l'ai est pas utilisé.
Pour l'écran je n'en ai jamais levé :).
Afficher les 9 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.