wiretap: add support for the mplog capture file format

the mplog format is used by some commercial logging tools that capture
ISO 14443 traffic between a card reader and a contactless smartcard

Change-Id: If359b8f0f671eb2a7c6315e2b8960a5bd581a9e9
Reviewed-on: https://code.wireshark.org/review/14950
Reviewed-by: Martin Kaiser <wireshark@kaiser.cx>
This commit is contained in:
Martin Kaiser 2016-02-09 16:16:15 +01:00
parent 54019ca207
commit fb39f102b9
7 changed files with 302 additions and 1 deletions

View File

@ -83,8 +83,9 @@ DecodeAs it over USB, TCP and UDP.
Too many protocols have been updated to list here.
=== New and Updated Capture File Support
Micropross mplog
_Non-empty section placeholder._
//_Non-empty section placeholder._
--sort-and-group--
--sort-and-group--

View File

@ -54,6 +54,7 @@ set(WIRETAP_FILES
logcat_text.c
merge.c
mpeg.c
mplog.c
mime_file.c
mp2t.c
netmon.c

View File

@ -60,6 +60,7 @@ NONGENERATED_C_FILES = \
libpcap.c \
merge.c \
mpeg.c \
mplog.c \
mp2t.c \
netmon.c \
netscaler.c \
@ -122,6 +123,7 @@ NONGENERATED_HEADER_FILES = \
logcat_text.h \
merge.h \
mpeg.h \
mplog.h \
mp2t.h \
netmon.h \
netscreen.h \

View File

@ -83,6 +83,7 @@
#include "capsa.h"
#include "pcap-encap.h"
#include "nettrace_3gpp_32_423.h"
#include "mplog.h"
/*
* Add an extension, and all compressed versions thereof, to a GSList
@ -333,6 +334,7 @@ static struct open_info open_info_base[] = {
/* Gammu DCT3 trace must come before MIME files as it's XML based*/
{ "Gammu DCT3 trace", OPEN_INFO_MAGIC, dct3trace_open, NULL, NULL, NULL },
{ "MIME Files Format", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL, NULL },
{ "Micropross mplog", OPEN_INFO_MAGIC, mplog_open, "mplog", NULL, NULL },
{ "Novell LANalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL, NULL },
/*
* PacketLogger must come before MPEG, because its files
@ -1583,6 +1585,11 @@ static const struct file_type_subtype_info dump_open_table_base[] = {
{ "3GPP TS 32.423 Trace", "3gpp32423", NULL, NULL,
FALSE, FALSE, 0,
NULL, NULL, NULL },
/* WTAP_FILE_TYPE_MPLOG */
{ "Micropross mplog file", "mplog", "mplog", NULL,
FALSE, FALSE, 0,
NULL, NULL, NULL }
};
/*

256
wiretap/mplog.c Normal file
View File

@ -0,0 +1,256 @@
/* mplog.c
*
* File format support for Micropross mplog files
* Copyright (c) 2016 by Martin Kaiser <martin@kaiser.cx>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
The mplog file format logs the communication between a contactless
smartcard and a card reader. Such files contain information about the
physical layer as well as the bytes exchanged between devices.
Some commercial logging and testing tools by the French company Micropross
use this format.
The information used for implementing this wiretap module were
obtained from reverse-engineering. There is no publicly available
documentation of the mplog file format.
Mplog files start with the string "MPCSII". This string is part of
the header which is in total 0x80 bytes long.
Following the header, the file is a sequence of 8 byte-blocks.
data (one byte)
block type (one byte)
timestamp (six bytes)
The timestamp is a counter in little-endian format. The counter is in
units of 10ns.
*/
#include "config.h"
#include <string.h>
#include <wtap-int.h>
#include <file_wrappers.h>
#include "mplog.h"
/* the block types */
#define TYPE_PCD_PICC_A 0x70
#define TYPE_PICC_PCD_A 0x71
#define TYPE_PCD_PICC_B 0x72
#define TYPE_PICC_PCD_B 0x73
#define TYPE_UNKNOWN 0xFF
#define KNOWN_TYPE(x) \
( \
((x) == TYPE_PCD_PICC_A) || \
((x) == TYPE_PICC_PCD_A) || \
((x) == TYPE_PCD_PICC_B) || \
((x) == TYPE_PICC_PCD_B) \
)
#define MPLOG_BLOCK_SIZE 8
/* ISO14443 pseudo-header, see http://www.kaiser.cx/pcap-iso14443.html */
#define ISO14443_PSEUDO_HDR_VER 0
#define ISO14443_PSEUDO_HDR_LEN 4
/* the two transfer events are the types that include a trailing CRC
the CRC is always present in mplog files */
#define ISO14443_PSEUDO_HDR_PICC_TO_PCD 0xFF
#define ISO14443_PSEUDO_HDR_PCD_TO_PICC 0xFE
#define ISO14443_MAX_PKT_LEN 256
#define PKT_BUF_LEN (ISO14443_PSEUDO_HDR_LEN + ISO14443_MAX_PKT_LEN)
/* read the next packet, starting at the current position of fh
as we know very little about the file format, our approach is rather simple:
- we read block-by-block until a known block-type is found
- this block's type is the type of the next packet
- this block's timestamp will become the packet's timestamp
- the data byte will be our packet's first byte
- we carry on reading blocks and add the data bytes
of all blocks of "our" type
- if a different well-known block type is found, this is the end of
our packet, we go back one block so that this block can be picked
up as the start of the next packet
- if two blocks of our packet's block type are more than 200us apart,
we treat this as a packet boundary as described above
*/
static gboolean mplog_read_packet(FILE_T fh, struct wtap_pkthdr *phdr,
Buffer *buf, int *err, gchar **err_info)
{
guint8 *p, *start_p;
/* --- the last block of a known type --- */
guint64 last_ctr = 0;
/* --- the current block --- */
guint8 block[MPLOG_BLOCK_SIZE]; /* the entire block */
guint8 data, type; /* its data and block type bytes */
guint64 ctr; /* its timestamp counter */
/* --- the packet we're assembling --- */
gint pkt_bytes = 0;
guint8 pkt_type = TYPE_UNKNOWN;
/* the timestamp of the packet's first block,
this will become the packet's timestamp */
guint64 pkt_ctr = 0;
ws_buffer_assure_space(buf, PKT_BUF_LEN);
p = ws_buffer_start_ptr(buf);
start_p = p;
/* leave space for the iso14443 pseudo header
we can't create it until we've seen the entire packet */
p += ISO14443_PSEUDO_HDR_LEN;
do {
if (!wtap_read_bytes_or_eof(fh, block, sizeof(block), err, err_info))
break;
data = block[0];
type = block[1];
ctr = pletoh48(&block[2]);
if (pkt_type == TYPE_UNKNOWN) {
if (KNOWN_TYPE(type)) {
pkt_type = type;
pkt_ctr = ctr;
}
}
if (type == pkt_type) {
if (last_ctr != 0) {
/* if the distance to the last byte of the
same type is larger than 200us, this is very likely the
first byte of a new packet -> go back one block and exit
ctr and last_ctr are in units of 10ns
at 106kbit/s, it takes approx 75us to send one byte */
if (ctr - last_ctr > 200*100) {
file_seek(fh, -MPLOG_BLOCK_SIZE, SEEK_CUR, err);
break;
}
}
*p++ = data;
pkt_bytes++;
last_ctr = ctr;
}
else if (KNOWN_TYPE(type)) {
file_seek(fh, -MPLOG_BLOCK_SIZE, SEEK_CUR, err);
break;
}
} while (pkt_bytes < ISO14443_MAX_PKT_LEN);
if (pkt_type == TYPE_UNKNOWN)
return FALSE;
start_p[0] = ISO14443_PSEUDO_HDR_VER;
if (pkt_type==TYPE_PCD_PICC_A || pkt_type==TYPE_PCD_PICC_B)
start_p[1] = ISO14443_PSEUDO_HDR_PCD_TO_PICC;
else
start_p[1] = ISO14443_PSEUDO_HDR_PICC_TO_PCD;
start_p[2] = pkt_bytes >> 8;
start_p[3] = pkt_bytes & 0xFF;
phdr->rec_type = REC_TYPE_PACKET;
phdr->pkt_encap = WTAP_ENCAP_ISO14443;
phdr->presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN;
phdr->ts.secs = (time_t)((pkt_ctr*10)/(1000*1000*1000));
phdr->ts.nsecs = (int)((pkt_ctr*10)%(1000*1000*1000));
phdr->caplen = ISO14443_PSEUDO_HDR_LEN + pkt_bytes;
phdr->len = phdr->caplen;
return TRUE;
}
static gboolean
mplog_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
*data_offset = file_tell(wth->fh);
return mplog_read_packet(
wth->fh, &wth->phdr, wth->frame_buffer, err, err_info);
}
static gboolean
mplog_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *pkthdr,
Buffer *buf, int *err, gchar **err_info)
{
if (-1 == file_seek(wth->random_fh, seek_off, SEEK_SET, err))
return FALSE;
return mplog_read_packet(wth->random_fh, pkthdr, buf, err, err_info);
}
wtap_open_return_val mplog_open(wtap *wth, int *err, gchar **err_info _U_)
{
gboolean ok;
guint8 str[10];
/* rewind the fh so we re-read from the beginning */
if (-1 == file_seek(wth->fh, 0, SEEK_SET, err))
return WTAP_OPEN_ERROR;
ok = wtap_read_bytes_or_eof(wth->fh, str, 6, err, err_info);
if (!ok)
return WTAP_OPEN_NOT_MINE;
if (strncmp(str, "MPCSII", 6))
return WTAP_OPEN_NOT_MINE;
wth->file_encap = WTAP_ENCAP_ISO14443;
wth->snapshot_length = 0;
wth->file_tsprec = WTAP_TSPREC_NSEC;
wth->priv = NULL;
wth->subtype_read = mplog_read;
wth->subtype_seek_read = mplog_seek_read;
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_MPLOG;
/* skip the file header */
if (-1 == file_seek(wth->fh, 0x80, SEEK_SET, err))
return WTAP_OPEN_ERROR;
*err = 0;
return WTAP_OPEN_MINE;
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

33
wiretap/mplog.h Normal file
View File

@ -0,0 +1,33 @@
/* mplog.h
*
* File format support for Micropross mplog files
* Copyright (c) 2016 by Martin Kaiser <martin@kaiser.cx>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _MPLOG_H
#define _MPLOG_H
#include <glib.h>
#include <wiretap/wtap.h>
wtap_open_return_val mplog_open(wtap *wth, int *err, gchar **err_info);
#endif /* _MPLOG_H */

View File

@ -357,6 +357,7 @@ extern "C" {
#define WTAP_FILE_TYPE_SUBTYPE_JSON 77
#define WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5 78
#define WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 79
#define WTAP_FILE_TYPE_SUBTYPE_MPLOG 80
#define WTAP_NUM_FILE_TYPES_SUBTYPES wtap_get_num_file_types_subtypes()