Il y a des tas de raisons de vouloir lire soi-même les
Souvent les articles sur la question parlent ensemble de la
L'outil d'analyse le plus fréquent pour les programmeurs
pcapy peut faire la capture et la lecture des fichiers au format
pcap. Ses capacités d'analyse sont limitées, on utilise en général la
bibliothèque impacket,
des mêmes auteurs, ou bien carrément
Voici un programme simple de lecture d'un fichier pcap, tel que
produit par tcpdump :
import pcapy
reader = pcapy.open_offline("mydata.pcap")
while True:
try:
(header, payload) = reader.next()
print "Got a packet of length %d" % header.getlen()
except pcapy.PcapError:
break
Il ne semble pas y avoir de moyen de détecter la fin du fichier à part
en récupérant l'erreur très générique
import pcapy
reader = pcapy.open_offline("mydata.pcap")
while True:
try:
(header, payload) = reader.next()
# Ethernet type is two-bytes long and starts at 12 (before, you
# have the MAC addresses)
if payload[12:14] == '\x86\xDD': # 0x86DD is the Ethernet type for IPv6
ip_payload = payload[14:]
ip_version = (ord(ip_payload[0]) & 0xf0) >> 4
if (ip_version != 6):
raise Exception("Packet has ethernet type of IPv6 but internal IP version is %d" % ip_version)
next_header = ord(ip_payload[6]) # RFC 2460, section 3 to know the offset
print "Next header (probably the transport protocol) is %d" % next_header
except pcapy.PcapError:
break
Ici, on teste le type indiqué dans l'en-tête
Mais il peut être plus simple d'utiliser la bibliothèque impacket,
conçue pour faciliter le décodage :
import pcapy
import impacket.ImpactDecoder as Decoders
reader = pcapy.open_offline("mydata.pcap")
decoder = Decoders.EthDecoder()
while True:
try:
(header, payload) = reader.next()
result = decoder.decode(payload)
# https://www.iana.org/assignments/ethernet-numbers
if result.get_ether_type() == 0x86DD: # IPv6
print "Got an IPv6 packet of length %d" % header.getlen()
except pcapy.PcapError:
break
Ici, plus besoin de connaître la structure de l'en-tête Ethernet, on
peut utiliser
Cela va permettre de s'attaquer à des protocoles de plus haut
niveau, souvent plus complexes à décoder. Commençons par
import pcapy
import impacket.ImpactDecoder as Decoders
import impacket.ImpactPacket as Packets
reader = pcapy.open_offline("mydata.pcap")
eth_decoder = Decoders.EthDecoder()
ip_decoder = Decoders.IPDecoder()
udp_decoder = Decoders.UDPDecoder()
while True:
try:
(header, payload) = reader.next()
ethernet = eth_decoder.decode(payload)
if ethernet.get_ether_type() == Packets.IP.ethertype:
ip = ip_decoder.decode(payload[ethernet.get_header_size():])
if ip.get_ip_p() == Packets.UDP.protocol:
udp = udp_decoder.decode(
payload[ethernet.get_header_size()+ip.get_header_size():])
print "IPv4 UDP packet %s:%d->%s:%d" % (ip.get_ip_src(),
udp.get_uh_sport(),
ip.get_ip_dst(),
udp.get_uh_dport())
except pcapy.PcapError:
break
Ce programme affiche les paquets UDP sur IPv4 en indiquant les
adresses et ports de source et de destination. On note qu'il n'y a pas
eu besoin de lire le
Pour le décodage de l'en-tête IP, Impacket ne dispose malheureusement que d'un décodeur IPv4. Pour IPv6, il faut l'écrire soi-même, peut-être plutôt en utilisant Scapy. Ce sera pour un autre article.