From a1c24c6c7df20ec205e4859a278f088332eecc90 Mon Sep 17 00:00:00 2001 From: Uli Heilmeier Date: Thu, 9 May 2019 16:34:06 +0200 Subject: [PATCH] Cmdtrace: Show trace ouput in hexdump format Adding option 'x' to show trace output for 14a in hexdump format. This output can be imported into Wireshark using the 'Import from Hex Dump' option. Encapsulation type should be set to 'ISO 14443' and Max Frame Length to 256. Format defined at https://www.kaiser.cx/pcap-iso14443.html --- client/cmdtrace.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/client/cmdtrace.c b/client/cmdtrace.c index e50a2b2c4..eb0c70732 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -20,6 +20,8 @@ static int usage_trace_list() { PrintAndLogEx(NORMAL, "Usage: trace list [f][c| <0|1>"); PrintAndLogEx(NORMAL, " f - show frame delay times as well"); PrintAndLogEx(NORMAL, " c - mark CRC bytes"); + PrintAndLogEx(NORMAL, " x - show hexdump to convert to pcap(ng) or to import into Wireshark using encapsulation type \"ISO 14443\""); + PrintAndLogEx(NORMAL, " syntax to use: `text2pcap -t \"%%S.\" -l 264 -n `"); PrintAndLogEx(NORMAL, " <0|1> - use data from Tracebuffer, if not set, try reading data from tag."); PrintAndLogEx(NORMAL, "Supported values:"); PrintAndLogEx(NORMAL, " raw - just show raw data without annotations"); @@ -102,6 +104,90 @@ static bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, ui return true; } +static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol) { + // sanity check + if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen; + + bool isResponse; + uint16_t data_len, parity_len; + uint32_t timestamp; + + timestamp = *((uint32_t *)(trace + tracepos)); + tracepos += 4; + + + // currently we don't use duration, so we skip it + tracepos += 2; + + data_len = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + + if (data_len & 0x8000) { + data_len &= 0x7fff; + isResponse = true; + } else { + isResponse = false; + } + parity_len = (data_len - 1) / 8 + 1; + + if (tracepos + data_len + parity_len > traceLen) { + return traceLen; + } + uint8_t *frame = trace + tracepos; + tracepos += data_len; + //currently we don't use parity bytes, so we skip it + tracepos += parity_len; + + if (data_len == 0) { + PrintAndLogEx(NORMAL, ""); + return tracepos; + } + + switch (protocol) { + case ISO_14443A: + { + /* https://www.kaiser.cx/pcap-iso14443.html defines a pseudo header: + * version (currently 0x00), event (Rdr: 0xfe, Tag: 0xff), length (2 bytes) + * to convert to pcap(ng) via text2pcap or to import into Wireshark + * we use format timestamp, newline, offset (0x000000), pseudo header, data + * `text2pcap -t "%S." -l 264 -n ` + */ + char line[(data_len *3) + 1]; + char *ptr = &line[0]; + + for (int j = 0; j < data_len ; j++) { + ptr += sprintf (ptr, "%02x", frame[j]); + ptr += sprintf (ptr, " "); + } + + char data_len_str[5]; + char temp_str1[3] = {0}; + char temp_str2[3] = {0}; + + sprintf(data_len_str, "%04x", data_len); + strncat(temp_str1, data_len_str, 2); + temp_str1[2] = '\0'; + strncat(temp_str2, data_len_str + 2, 2); + temp_str2[2] = '\0'; + + PrintAndLogEx(NORMAL, "0.%010u", timestamp); + PrintAndLogEx(NORMAL, "000000 00 %s %s %s %s", + (isResponse ? "ff" : "fe"), + temp_str1, + temp_str2, + line); + return tracepos; + } + default: + PrintAndLogEx(NORMAL, "Currently only 14a supported"); + return traceLen; + } + + if (is_last_record(tracepos, trace, traceLen)) return traceLen; + + return tracepos; +} + static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes) { // sanity check if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen; @@ -592,6 +678,7 @@ int CmdTraceList(const char *Cmd) { bool showWaitCycles = false; bool markCRCBytes = false; + bool showHex = false; bool isOnline = true; bool errors = false; uint8_t protocol = 0; @@ -618,6 +705,10 @@ int CmdTraceList(const char *Cmd) { markCRCBytes = true; cmdp++; break; + case 'x': + showHex = true; + cmdp++; + break; case '0': isOnline = true; cmdp++; @@ -695,6 +786,10 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(INFO, ""); if (protocol == FELICA) { printFelica(traceLen, trace); + } else if (showHex) { + while (tracepos < traceLen) { + tracepos = printHexLine(tracepos, traceLen, trace, protocol); + } } else { PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); if (protocol == ISO_14443A || protocol == PROTO_MIFARE)