python-dpkt: ICMP packet parsing - python

How can I parse a ICMP packet (using dpkt) to check if it is a request or a response coming from A to B?
I found some examples for TCP and UDP packets (below) but I can't find anything for IP packets.
import dpkt
f = open('test.pcap')
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
if tcp.dport == 80 and len(tcp.data) > 0:
http = dpkt.http.Request(tcp.data)
print http.uri
f.close()
Also, is there any good tutorial for dpkt?

This is an old question but for folks coming across this, I've added an ICMP example to the dpkt repo. The docs can be found here: http://dpkt.readthedocs.io/en/latest/print_icmp.html and the example code can be found in dpkt/examples/print_icmp.py
# For each packet in the pcap process the contents
for timestamp, buf in pcap:
# Unpack the Ethernet frame (mac src/dst, ethertype)
eth = dpkt.ethernet.Ethernet(buf)
# Make sure the Ethernet data contains an IP packet
if not isinstance(eth.data, dpkt.ip.IP):
print 'Non IP Packet type not supported %s\n' % eth.data.__class__.__name__
continue
# Now grab the data within the Ethernet frame (the IP packet)
ip = eth.data
# Now check if this is an ICMP packet
if isinstance(ip.data, dpkt.icmp.ICMP):
icmp = ip.data
# Pull out fragment information
do_not_fragment = bool(ip.off & dpkt.ip.IP_DF)
more_fragments = bool(ip.off & dpkt.ip.IP_MF)
fragment_offset = ip.off & dpkt.ip.IP_OFFMASK
# Print out the info
print 'Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp))
print 'Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type
print 'IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)' % \
(inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl,
do_not_fragment, more_fragments, fragment_offset)
print 'ICMP: type:%d code:%d checksum:%d data: %s\n' % (icmp.type,
icmp.code, icmp.sum, repr(icmp.data))
Example Output
Timestamp: 2013-05-30 22:45:17.283187
Ethernet Frame: 60:33:4b:13:c5:58 02:1a:11:f0:c8:3b 2048
IP: 192.168.43.9 -> 8.8.8.8 (len=84 ttl=64 DF=0 MF=0 offset=0)
ICMP: type:8 code:0 checksum:48051 data: Echo(id=55099, data='Q\xa7\xd6}\x00\x04Q\xe4\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567')
Timestamp: 2013-05-30 22:45:17.775391
Ethernet Frame: 02:1a:11:f0:c8:3b 60:33:4b:13:c5:58 2048
IP: 8.8.8.8 -> 192.168.43.9 (len=84 ttl=40 DF=0 MF=0 offset=0)
ICMP: type:0 code:0 checksum:50099 data: Echo(id=55099, data='Q\xa7\xd6}\x00\x04Q\xe4\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567')

Related

Python - Analyze Pcap FIle and extract interrupted connections

I am trying to do these steps :
read pcap file
analyze the packets and show connections that have not been set up properly
is it possible to extract information like this ?
i have write Python classes to extract Packet Header , Packet's Ethernet , Packet IP , Packet TCP information. i need guidance that is it possible to extract information like this ? hva_pcao.py , hva_pckt
rdr = pcap.open_offline('xsupport.pcap')
i = 0
for hdr, data in rdr:
if i ==2:
print(hdr)
eth = Eth.decode(data)
if eth is None: continue
print(str(eth))
ip = Ip.decode(eth.pl)
if ip is None: continue
print(str(ip))
tcp = Tcp.decode(ip.pl)
if tcp is None: continue
print(str(tcp))
print((repr(tcp.flags) + " - " + repr(tcp.kFlags_FIN) + " * " + repr(tcp.kFlags_ACK)))
# break
My expected output is : analyze the packets and show connections that have not been set up properly

scapy remaining packets, not received

I've got an issue with scapy, it says :
Finished to send 1 packets
But I don't receive anything on tcpdump, and when i close scapy:
Received 0 packets, got 0 answers, remaining 1 packets
What does "remaining 1 packets" means?
Here is the code :
#Usage: script.py serveur_ip serveur_port client_ip
from scapy.all import *
import sys
#Création of the filter for the sniffer
filtre="host " + sys.argv[1] + " and port " + sys.argv[2]
print "THe filter used will be : {}".format(filtre)
#Function used by the sniffer for each received packet:
def rst_hijack(p):
#If the source is the remote-host and the destination is the target
if p[IP].src==sys.argv[1] and p[IP].dst==sys.argv[3]:
print "Connexion trouvée"
#We forge a packet for our attack from the received packet
#Ethernet
ether=Ether(dst=p[Ether].src, src=p[Ether].dst)
ether.show()
#IP
ip=IP(src=p[IP].dst, dst=p[IP].src, ihl=p[IP].ihl, flags=p[IP].flags, frag=p[IP].frag, ttl=p[IP].ttl,
proto=p[IP].proto, id=29221)
ip.show()
#TCP
tcp=TCP(sport=p[TCP].dport, dport=p[TCP].sport, seq=p[TCP].ack, ack=p[TCP].seq, dataofs=p[TCP].dataofs,
reserved=p[TCP].reserved, flags="R", window=p[TCP].window, options=p[TCP].options)
tcp.show()
#We forge the final paquet
reset=ether/ip/tcp
reset.show()
#We send it
srp(reset)
exit()
#Sniffer That applies to each packet the rst_hijack function, packet filtered according to the filter
sniff(count=0, iface="ens37", prn=lambda p: rst_hijack(p), filter=filtre, lfilter=lambda x: x.haslayer(IP) and x.haslayer(TCP))

UDP packet headers from socket() are not as expected

I am building a UDP server to parse and verify incoming UDP packets. I am able to receive and parse packets but the header values are not what I expected.
This is structure of incoming packet
Packet ID ( 4 bytes )
Packet Sequence ( 4 bytes )
XOR Key ( 2 bytes )
Number of Checksums in packet ( 2 bytes )
Cyclic checksum CRC32 (variable)
To send the packet,
with open('payloadfile.bin') as op:
payload = pickle.load(op)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for i in payload:
sock.sentto(payload, ('127.0.0.1',4545))
To receive and parse this packet
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind('127.0.0.1',4545)
while 1:
packet = sock.recvfrom(65565)
packet = packet[0]
# parse IP
ip_header = packet[0:20]
iph = struct.unpack('!BBHHHBBH4s4s' , ip_header)
#all the following values are incorrect
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
ttl = iph[5]
protocol = iph[6]
s_addr = socket.inet_ntoa(iph[8]);
d_addr = socket.inet_ntoa(iph[9]);
# parse UDP
packet = packet[20:28]
data = packet[header_length:]
source_port, dest_port, data_length, checksum = struct.unpack("!HHHH", header)
From what I understand so far, this should be the general structure
IP_HEADER ( UDP_HEADER ( PAYLOAD )))
I want to parse the headers correctly, and then extract the payload.
Unfortunately the standard socket interface doesn't give you access to the data frames that your data arrive in, neither does it include the IP Datagram headers nor the TCP/UDP headers from the transport layer.
To get hold of lower-level data you are forced to use the so-called raw socket interface, which Windows for one tries to block you from using because you might be a hacker. This article might give you some clues.

Python dpkt with pcap - how can I print the packet data?

I want to print out the packet data from a pcap file. The code below stores the packet data in an array but I can't figure out how to print each element of the array and then split up the data from there. A for loop on the array just returns an error.
import dpkt
import socket
f = open('test.pcap', 'r')
pcap = dpkt.pcap.Reader(f)
info = []
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
if not hasattr(eth, 'ip'):
continue
info.append(eth.ip)
f.close()
print info
It is not clear what exactly you want to print. It depends on what you are looking for.
If you want to print the tcp data, then here is how you do it:
import dpkt
f = open('test.pcap')
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
If you want to print data in a higher layer, you can extend the above example to do so. HTTP, for example, is as follows:
import dpkt
f = open('test.pcap')
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
if tcp.dport == 80:
http = dpkt.http.Request(tcp.data)
print http.data
For more details, see the example here, or the examples in the dpkt project.

Having trouble building a Dns Packet in Python

I'm trying to build a dns packet to send over a socket. I don't want to use any libraries because I want direct access to the socket variable that sends it. Whenever I send the DNS packet, wireshark says that it's malformed. What exactly am I doing wrong?
Some things that are wrong with the Dns packet itself:
It says it has 256 questions, no class and no type
class DnsPacketBuilder:
def __init__(self):
pass
def build_packet(self, url):
packet = struct.pack("H", 12049) # Query Ids (Just 1 for now)
packet += struct.pack("H", 256) # Flags
packet += struct.pack("H", 1) # Questions
packet += struct.pack("H", 0) # Answers
packet += struct.pack("H", 0) # Authorities
packet += struct.pack("H", 0) # Additional
split_url = url.split(".")
for part in split_url:
packet += struct.pack("B", len(part))
for byte in bytes(part):
packet += struct.pack("c", byte)
packet += struct.pack("B", 0) # End of String
packet += struct.pack("H", 1) # Query Type
packet += struct.pack("H", 1) # Query Class
return packet
# Sending the packet
builder = DnsPacketBuilder()
packet = builder.build_packet("www.northeastern.edu")
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 8888))
sock.settimeout(2)
sock.sendto(bytes(packet), ("208.67.222.222", 53))
print("Packet Sent")
data, addr = sock.recvfrom(1024)
print("Response: " + data)
sock.close()
Your system is using "little endian" byte order natively.
You need to reverse the byte order of the 16-bit fields into "big endian" (aka "network order") using the ">H" format string in struct.pack().

Categories