.cap file format of Microsoft Network Monitor, v2.x: PHP parsing library

Microsoft Network Monitor (AKA Netmon) is a proprietary Microsoft's network packet sniffing and analysis tool. It can save captured traffic as .cap files, which usually contain the packets and may contain some additional info - enhanced network info, calculated statistics, etc.

There are at least 2 different versions of the format: v1 and v2. Netmon v3 seems to use the same file format as v1.

Application

Microsoft Network Monitor, v2.x

File extension

cap

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.7

This page hosts a formal specification of .cap file format of Microsoft Network Monitor, v2.x using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

PHP source code to parse .cap file format of Microsoft Network Monitor, v2.x

MicrosoftNetworkMonitorV2.php

<?php
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

/**
 * Microsoft Network Monitor (AKA Netmon) is a proprietary Microsoft's
 * network packet sniffing and analysis tool. It can save captured
 * traffic as .cap files, which usually contain the packets and may
 * contain some additional info - enhanced network info, calculated
 * statistics, etc.
 * 
 * There are at least 2 different versions of the format: v1 and
 * v2. Netmon v3 seems to use the same file format as v1.
 */

class MicrosoftNetworkMonitorV2 extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \MicrosoftNetworkMonitorV2 $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_signature = $this->_io->ensureFixedContents("\x47\x4D\x42\x55");
        $this->_m_versionMinor = $this->_io->readU1();
        $this->_m_versionMajor = $this->_io->readU1();
        $this->_m_macType = $this->_io->readU2le();
        $this->_m_timeCaptureStart = new \WindowsSystemtime($this->_io);
        $this->_m_frameTableOfs = $this->_io->readU4le();
        $this->_m_frameTableLen = $this->_io->readU4le();
        $this->_m_userDataOfs = $this->_io->readU4le();
        $this->_m_userDataLen = $this->_io->readU4le();
        $this->_m_commentOfs = $this->_io->readU4le();
        $this->_m_commentLen = $this->_io->readU4le();
        $this->_m_statisticsOfs = $this->_io->readU4le();
        $this->_m_statisticsLen = $this->_io->readU4le();
        $this->_m_networkInfoOfs = $this->_io->readU4le();
        $this->_m_networkInfoLen = $this->_io->readU4le();
        $this->_m_conversationStatsOfs = $this->_io->readU4le();
        $this->_m_conversationStatsLen = $this->_io->readU4le();
    }
    protected $_m_frameTable;

    /**
     * Index that is used to access individual captured frames
     */
    public function frameTable() {
        if ($this->_m_frameTable !== null)
            return $this->_m_frameTable;
        $_pos = $this->_io->pos();
        $this->_io->seek($this->frameTableOfs());
        $this->_m__raw_frameTable = $this->_io->readBytes($this->frameTableLen());
        $io = new \Kaitai\Struct\Stream($this->_m__raw_frameTable);
        $this->_m_frameTable = new \MicrosoftNetworkMonitorV2\FrameIndex($io, $this, $this->_root);
        $this->_io->seek($_pos);
        return $this->_m_frameTable;
    }
    protected $_m_signature;
    protected $_m_versionMinor;
    protected $_m_versionMajor;
    protected $_m_macType;
    protected $_m_timeCaptureStart;
    protected $_m_frameTableOfs;
    protected $_m_frameTableLen;
    protected $_m_userDataOfs;
    protected $_m_userDataLen;
    protected $_m_commentOfs;
    protected $_m_commentLen;
    protected $_m_statisticsOfs;
    protected $_m_statisticsLen;
    protected $_m_networkInfoOfs;
    protected $_m_networkInfoLen;
    protected $_m_conversationStatsOfs;
    protected $_m_conversationStatsLen;
    protected $_m__raw_frameTable;
    public function signature() { return $this->_m_signature; }

    /**
     * Format version (minor), BCD
     */
    public function versionMinor() { return $this->_m_versionMinor; }

    /**
     * Format version (major), BCD
     */
    public function versionMajor() { return $this->_m_versionMajor; }

    /**
     * Network topology type of captured data
     */
    public function macType() { return $this->_m_macType; }

    /**
     * Timestamp of capture start
     */
    public function timeCaptureStart() { return $this->_m_timeCaptureStart; }
    public function frameTableOfs() { return $this->_m_frameTableOfs; }
    public function frameTableLen() { return $this->_m_frameTableLen; }
    public function userDataOfs() { return $this->_m_userDataOfs; }
    public function userDataLen() { return $this->_m_userDataLen; }
    public function commentOfs() { return $this->_m_commentOfs; }
    public function commentLen() { return $this->_m_commentLen; }
    public function statisticsOfs() { return $this->_m_statisticsOfs; }
    public function statisticsLen() { return $this->_m_statisticsLen; }
    public function networkInfoOfs() { return $this->_m_networkInfoOfs; }
    public function networkInfoLen() { return $this->_m_networkInfoLen; }
    public function conversationStatsOfs() { return $this->_m_conversationStatsOfs; }
    public function conversationStatsLen() { return $this->_m_conversationStatsLen; }
    public function _raw_frameTable() { return $this->_m__raw_frameTable; }
}

namespace \MicrosoftNetworkMonitorV2;

class FrameIndex extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \MicrosoftNetworkMonitorV2 $_parent = null, \MicrosoftNetworkMonitorV2 $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_entries = [];
        $i = 0;
        while (!$this->_io->isEof()) {
            $this->_m_entries[] = new \MicrosoftNetworkMonitorV2\FrameIndexEntry($this->_io, $this, $this->_root);
            $i++;
        }
    }
    protected $_m_entries;
    public function entries() { return $this->_m_entries; }
}

/**
 * Each index entry is just a pointer to where the frame data is
 * stored in the file.
 */

namespace \MicrosoftNetworkMonitorV2;

class FrameIndexEntry extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \MicrosoftNetworkMonitorV2\FrameIndex $_parent = null, \MicrosoftNetworkMonitorV2 $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_ofs = $this->_io->readU4le();
    }
    protected $_m_body;

    /**
     * Frame body itself
     */
    public function body() {
        if ($this->_m_body !== null)
            return $this->_m_body;
        $io = $this->_root()->_io();
        $_pos = $io->pos();
        $io->seek($this->ofs());
        $this->_m_body = new \MicrosoftNetworkMonitorV2\Frame($io, $this, $this->_root);
        $io->seek($_pos);
        return $this->_m_body;
    }
    protected $_m_ofs;

    /**
     * Absolute pointer to frame data in the file
     */
    public function ofs() { return $this->_m_ofs; }
}

/**
 * A container for actually captured network data. Allow to
 * timestamp individual frames and designates how much data from
 * the original packet was actually written into the file.
 */

namespace \MicrosoftNetworkMonitorV2;

class Frame extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \MicrosoftNetworkMonitorV2\FrameIndexEntry $_parent = null, \MicrosoftNetworkMonitorV2 $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_tsDelta = $this->_io->readU8le();
        $this->_m_origLen = $this->_io->readU4le();
        $this->_m_incLen = $this->_io->readU4le();
        switch ($this->_root()->macType()) {
            case \MicrosoftNetworkMonitorV2\Linktype::ETHERNET:
                $this->_m__raw_body = $this->_io->readBytes($this->incLen());
                $io = new \Kaitai\Struct\Stream($this->_m__raw_body);
                $this->_m_body = new \EthernetFrame($io);
                break;
            default:
                $this->_m_body = $this->_io->readBytes($this->incLen());
                break;
        }
    }
    protected $_m_tsDelta;
    protected $_m_origLen;
    protected $_m_incLen;
    protected $_m_body;
    protected $_m__raw_body;

    /**
     * Time stamp - usecs since start of capture
     */
    public function tsDelta() { return $this->_m_tsDelta; }

    /**
     * Actual length of packet
     */
    public function origLen() { return $this->_m_origLen; }

    /**
     * Number of octets captured in file
     */
    public function incLen() { return $this->_m_incLen; }

    /**
     * Actual packet captured from the network
     */
    public function body() { return $this->_m_body; }
    public function _raw_body() { return $this->_m__raw_body; }
}

namespace \MicrosoftNetworkMonitorV2;

class Linktype {
    const NULL_LINKTYPE = 0;
    const ETHERNET = 1;
    const AX25 = 3;
    const IEEE802_5 = 6;
    const ARCNET_BSD = 7;
    const SLIP = 8;
    const PPP = 9;
    const FDDI = 10;
    const PPP_HDLC = 50;
    const PPP_ETHER = 51;
    const ATM_RFC1483 = 100;
    const RAW = 101;
    const C_HDLC = 104;
    const IEEE802_11 = 105;
    const FRELAY = 107;
    const LOOP = 108;
    const LINUX_SLL = 113;
    const LTALK = 114;
    const PFLOG = 117;
    const IEEE802_11_PRISM = 119;
    const IP_OVER_FC = 122;
    const SUNATM = 123;
    const IEEE802_11_RADIOTAP = 127;
    const ARCNET_LINUX = 129;
    const APPLE_IP_OVER_IEEE1394 = 138;
    const MTP2_WITH_PHDR = 139;
    const MTP2 = 140;
    const MTP3 = 141;
    const SCCP = 142;
    const DOCSIS = 143;
    const LINUX_IRDA = 144;
    const USER0 = 147;
    const USER1 = 148;
    const USER2 = 149;
    const USER3 = 150;
    const USER4 = 151;
    const USER5 = 152;
    const USER6 = 153;
    const USER7 = 154;
    const USER8 = 155;
    const USER9 = 156;
    const USER10 = 157;
    const USER11 = 158;
    const USER12 = 159;
    const USER13 = 160;
    const USER14 = 161;
    const USER15 = 162;
    const IEEE802_11_AVS = 163;
    const BACNET_MS_TP = 165;
    const PPP_PPPD = 166;
    const GPRS_LLC = 169;
    const GPF_T = 170;
    const GPF_F = 171;
    const LINUX_LAPD = 177;
    const BLUETOOTH_HCI_H4 = 187;
    const USB_LINUX = 189;
    const PPI = 192;
    const IEEE802_15_4 = 195;
    const SITA = 196;
    const ERF = 197;
    const BLUETOOTH_HCI_H4_WITH_PHDR = 201;
    const AX25_KISS = 202;
    const LAPD = 203;
    const PPP_WITH_DIR = 204;
    const C_HDLC_WITH_DIR = 205;
    const FRELAY_WITH_DIR = 206;
    const IPMB_LINUX = 209;
    const IEEE802_15_4_NONASK_PHY = 215;
    const USB_LINUX_MMAPPED = 220;
    const FC_2 = 224;
    const FC_2_WITH_FRAME_DELIMS = 225;
    const IPNET = 226;
    const CAN_SOCKETCAN = 227;
    const IPV4 = 228;
    const IPV6 = 229;
    const IEEE802_15_4_NOFCS = 230;
    const DBUS = 231;
    const DVB_CI = 235;
    const MUX27010 = 236;
    const STANAG_5066_D_PDU = 237;
    const NFLOG = 239;
    const NETANALYZER = 240;
    const NETANALYZER_TRANSPARENT = 241;
    const IPOIB = 242;
    const MPEG_2_TS = 243;
    const NG40 = 244;
    const NFC_LLCP = 245;
    const INFINIBAND = 247;
    const SCTP = 248;
    const USBPCAP = 249;
    const RTAC_SERIAL = 250;
    const BLUETOOTH_LE_LL = 251;
    const NETLINK = 253;
    const BLUETOOTH_LINUX_MONITOR = 254;
    const BLUETOOTH_BREDR_BB = 255;
    const BLUETOOTH_LE_LL_WITH_PHDR = 256;
    const PROFIBUS_DL = 257;
    const PKTAP = 258;
    const EPON = 259;
    const IPMI_HPM_2 = 260;
    const ZWAVE_R1_R2 = 261;
    const ZWAVE_R3 = 262;
    const WATTSTOPPER_DLM = 263;
    const ISO_14443 = 264;
}