capinfos.py: Pure Python Pcap Statistics Tool


« 📅 published on 02/Aug/2015 »

🔖 tagged code


Introduction

The capinfos tool from Wireshark parses a pcap file and displays useful statistics like packet count, bitrate, byterate, capture duration, etc. I needed a pure-Python parser to obtain these details and ended up with the following code:

from pprint import pprint
import datetime
import struct
import sys

def capinfos(filename):
  # generates wireshark's capinfos like stats
  # limited features
  # needs additional testing
  file_handle = open(filename, 'rb')
  data = file_handle.read()
  pcapstats = dict()
  endianness = None
  datalink_types = {
    0: 'DLT_NULL',
    1: 'DLT_EN10MB',
    2: 'DLT_EN3MB',
    3: 'DLT_AX25',
    4: 'DLT_PRONET',
    5: 'DLT_CHAOS',
    6: 'DLT_IEEE802',
    7: 'DLT_ARCNET',
    8: 'DLT_SLIP',
    9: 'DLT_PPP',
    10: 'DLT_FDDI',
    18: 'DLT_PFSYNC',
    105: 'DLT_IEEE802_11',
    113: 'DLT_LINUX_SLL',
    117: 'DLT_PFLOG',
    127: 'DLT_IEEE802_11_RADIO'
  }
  # extract pcap magic using host's native endianess
  (pcap_magic, ) = struct.unpack('=I', data[:4])
  # if the pcap is LE
  if pcap_magic == 0xa1b2c3d4:
    (pcap_magic, pcap_version_major, pcap_version_minor, pcap_thiszone, pcap_sigfigs, pcap_snaplen, pcap_network) = struct.unpack('<IHHIIII', data[:24])
    endianness = 'LITTLE'
  # if the pcap is BE
  elif pcap_magic == 0xd4c3b2a1:
    (pcap_magic, pcap_version_major, pcap_version_minor, pcap_thiszone, pcap_sigfigs, pcap_snaplen, pcap_network) = struct.unpack('>IHHIIII', data[:24])
    endianness = 'BIG'
  # for pcaps which are something else (0x4d3c2b1a)?
  else:
    return pcapstats
  starttime = None
  endtime = None
  s = 24
  e = s + 16
  packetscount = 0
  bytescount = 0
  while True:
    if endianness is 'LITTLE':
      (ts_sec, ts_usec, incl_len, orig_len) = struct.unpack('<IIII', data[s:e])
    elif endianness is 'BIG':
      (ts_sec, ts_usec, incl_len, orig_len) = struct.unpack('>IIII', data[s:e])
    packetscount += 1
    bytescount += incl_len
    if not starttime:
      starttime = datetime.datetime.fromtimestamp(ts_sec)
      bytescount += incl_len
    endtime = datetime.datetime.fromtimestamp(ts_sec)
    s = e + incl_len
    e = s + 16
    if e > len(data):
      break
  totsecs = int((endtime - starttime).total_seconds())
  if totsecs < 1:
    totsecs = 1
  pcapstats['totsecs'] = totsecs
  pcapstats['pcapmagic'] = '0x%08X' % pcap_magic
  pcapstats['version_major'] = pcap_version_major
  pcapstats['version_minor'] = pcap_version_minor
  pcapstats['snaplen'] = pcap_snaplen
  pcapstats['pcapencapsulation'] = datalink_types[pcap_network]
  pcapstats['packetscount'] = packetscount
  pcapstats['bytescount'] = bytescount
  pcapstats['capturestarttime'] = starttime.strftime('%c').strip()
  pcapstats['captureendtime'] = endtime.strftime('%c').strip()
  pcapstats['captureduration'] = (endtime - starttime).total_seconds()
  byterate = (bytescount / totsecs) if totsecs > 0 else bytescount
  bitrate = ((bytescount * 8) / totsecs) if totsecs > 0 else (bytescount * 8)
  pcapstats['byterate'] = byterate
  pcapstats['bitrate'] = bitrate
  avgpacketsize = (bytescount / packetscount) if packetscount > 0 else bytescount
  avgpacketrate = (packetscount / totsecs) if totsecs > 0 else packetscount
  pcapstats['avgpacketsize'] = avgpacketsize
  pcapstats['avgpacketrate'] = avgpacketrate
  return dict(pcapstats)


if __name__ == "__main__":
  if len(sys.argv) != 2:
    print "USAGE: %s <filename>" % (sys.argv[0])
    sys.exit(1)

  pprint(capinfos(sys.argv[1]))

Usage

Let's try this script on a HTTP pcap:

$ python capinfos.py /media/shiv/red_third/stoolbox/testfiles/pcaps/layer7/http_espn.pcap
{
 'avgpacketrate': 478,
 'avgpacketsize': 682,
 'bitrate': 2609012,
 'byterate': 326126,
 'bytescount': 652253,
 'captureduration': 2.0,
 'captureendtime': 'Wed Apr  7 22:59:31 2010',
 'capturestarttime': 'Wed Apr  7 22:59:29 2010',
 'packetscount': 956,
 'pcapencapsulation': 'DLT_EN10MB',
 'pcapmagic': '0xA1B2C3D4',
 'snaplen': 65535,
 'totsecs': 2,
 'version_major': 2,
 'version_minor': 4
}

Conclusion

The script accepts a pcap file as input and natively parse its structure to calculate required values. As can be seen in the output file, it shows a quick summary of statistics which could be quite useful for scripting and automation or to have a quick overview of input file. You can get this script here.


« Eindbazen CTF Challenge: bin10... «

» cigma: A Pure Python Filetype ... »

  