2018-03-19 01:00:41 +08:00
//-----------------------------------------------------------------------------
// Copyright (C) 2018 iceman <iceman at iuse.se>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Trace commands
//-----------------------------------------------------------------------------
# include "cmdtrace.h"
2019-08-08 22:57:33 +08:00
# include <ctype.h>
# include "cmdparser.h" // command_t
# include "protocols.h"
# include "parity.h" // oddparity
# include "cmdhflist.h" // annotations
2021-01-27 06:14:20 +08:00
# include "commonutil.h" // ARRAYLEN
# include "mifare/mifaredefault.h" // mifare default key array
2019-08-08 22:57:33 +08:00
# include "comms.h" // for sending cmds to device. GetFromBigBuf
2019-08-21 20:41:33 +08:00
# include "fileutils.h" // for saveFile
2020-01-20 18:37:10 +08:00
# include "cmdlfhitag.h" // annotate hitag
2020-05-19 08:14:43 +08:00
# include "pm3_cmd.h" // tracelog_hdr_t
2020-10-10 01:45:29 +08:00
# include "cliparser.h" // args..
2019-08-08 22:57:33 +08:00
2018-03-19 01:00:41 +08:00
static int CmdHelp ( const char * Cmd ) ;
2018-03-19 02:58:22 +08:00
// trace pointer
2020-05-04 03:43:03 +08:00
static uint8_t * g_trace ;
2020-06-02 02:45:37 +08:00
static long g_traceLen = 0 ;
2019-03-09 15:59:13 +08:00
2020-05-19 06:25:40 +08:00
static bool is_last_record ( uint16_t tracepos , uint16_t traceLen ) {
return ( ( tracepos + TRACELOG_HDR_LEN ) > = traceLen ) ;
2018-03-19 01:00:41 +08:00
}
2019-04-11 06:10:21 +08:00
static bool next_record_is_response ( uint16_t tracepos , uint8_t * trace ) {
2020-05-19 06:25:40 +08:00
tracelog_hdr_t * hdr = ( tracelog_hdr_t * ) ( trace + tracepos ) ;
2020-05-19 08:14:43 +08:00
return ( hdr - > isResponse ) ;
2018-03-19 01:00:41 +08:00
}
2019-04-11 06:10:21 +08:00
static bool merge_topaz_reader_frames ( uint32_t timestamp , uint32_t * duration , uint16_t * tracepos , uint16_t traceLen ,
2019-04-11 13:40:50 +08:00
uint8_t * trace , uint8_t * frame , uint8_t * topaz_reader_command , uint16_t * data_len ) {
2019-03-10 06:35:06 +08:00
# define MAX_TOPAZ_READER_CMD_LEN 16
uint32_t last_timestamp = timestamp + * duration ;
if ( ( * data_len ! = 1 ) | | ( frame [ 0 ] = = TOPAZ_WUPA ) | | ( frame [ 0 ] = = TOPAZ_REQA ) ) return false ;
memcpy ( topaz_reader_command , frame , * data_len ) ;
2020-05-19 06:25:40 +08:00
while ( ! is_last_record ( * tracepos , traceLen ) & & ! next_record_is_response ( * tracepos , trace ) ) {
tracelog_hdr_t * hdr = ( tracelog_hdr_t * ) ( trace + * tracepos ) ;
2020-06-08 09:15:10 +08:00
2020-05-19 08:14:43 +08:00
* tracepos + = TRACELOG_HDR_LEN + hdr - > data_len ;
2020-05-19 06:25:40 +08:00
2020-05-19 08:14:43 +08:00
if ( ( hdr - > data_len = = 1 ) & & ( * data_len + hdr - > data_len < = MAX_TOPAZ_READER_CMD_LEN ) ) {
memcpy ( topaz_reader_command + * data_len , hdr - > frame , hdr - > data_len ) ;
* data_len + = hdr - > data_len ;
last_timestamp = hdr - > timestamp + hdr - > duration ;
2019-03-10 06:35:06 +08:00
} else {
// rewind and exit
2020-05-19 08:14:43 +08:00
* tracepos = * tracepos - hdr - > data_len - TRACELOG_HDR_LEN ;
2019-03-10 06:35:06 +08:00
break ;
}
2020-05-19 08:14:43 +08:00
* tracepos + = TRACELOG_PARITY_LEN ( hdr ) ;
2019-03-10 06:35:06 +08:00
}
* duration = last_timestamp - timestamp ;
return true ;
2018-03-19 01:00:41 +08:00
}
2019-05-09 22:34:06 +08:00
static uint16_t printHexLine ( uint16_t tracepos , uint16_t traceLen , uint8_t * trace , uint8_t protocol ) {
// sanity check
2020-05-19 06:25:40 +08:00
if ( is_last_record ( tracepos , traceLen ) ) return traceLen ;
2019-05-09 22:34:06 +08:00
2020-05-19 05:49:45 +08:00
tracelog_hdr_t * hdr = ( tracelog_hdr_t * ) ( trace + tracepos ) ;
2019-05-09 22:34:06 +08:00
2020-05-19 08:14:43 +08:00
if ( TRACELOG_HDR_LEN + hdr - > data_len + TRACELOG_PARITY_LEN ( hdr ) > traceLen ) {
2019-05-09 22:34:06 +08:00
return traceLen ;
}
2020-05-19 05:49:45 +08:00
//set trace position
2020-05-19 08:14:43 +08:00
tracepos + = TRACELOG_HDR_LEN + hdr - > data_len + TRACELOG_PARITY_LEN ( hdr ) ;
2020-05-19 05:49:45 +08:00
if ( hdr - > data_len = = 0 ) {
2019-05-09 22:34:06 +08:00
PrintAndLogEx ( NORMAL , " <empty trace - possible error> " ) ;
return tracepos ;
}
2019-10-09 21:23:58 +08:00
uint16_t ret ;
2019-05-09 22:34:06 +08:00
switch ( protocol ) {
2019-05-13 02:38:03 +08:00
case ISO_14443A : {
2019-05-09 22:34:06 +08:00
/* 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 < input - text - file > < output - pcapng - file > `
*/
2020-05-19 05:49:45 +08:00
char line [ ( hdr - > data_len * 3 ) + 1 ] ;
2019-05-09 22:34:06 +08:00
char * ptr = & line [ 0 ] ;
2020-05-19 05:49:45 +08:00
for ( int i = 0 ; i < hdr - > data_len ; i + + ) {
ptr + = sprintf ( ptr , " %02x " , hdr - > frame [ i ] ) ;
2019-05-09 22:34:06 +08:00
}
char data_len_str [ 5 ] ;
char temp_str1 [ 3 ] = { 0 } ;
char temp_str2 [ 3 ] = { 0 } ;
2020-06-08 09:15:10 +08:00
2020-05-19 05:49:45 +08:00
sprintf ( data_len_str , " %04x " , hdr - > data_len ) ;
2020-10-06 20:39:36 +08:00
memmove ( temp_str1 , data_len_str , 2 ) ;
memmove ( temp_str2 , data_len_str + 2 , 2 ) ;
2019-05-09 22:34:06 +08:00
2020-05-19 05:49:45 +08:00
PrintAndLogEx ( NORMAL , " 0.%010u " , hdr - > timestamp ) ;
2019-05-09 22:34:06 +08:00
PrintAndLogEx ( NORMAL , " 000000 00 %s %s %s %s " ,
2020-05-19 08:14:43 +08:00
( hdr - > isResponse ? " ff " : " fe " ) ,
2019-05-13 02:38:03 +08:00
temp_str1 ,
temp_str2 ,
line ) ;
2019-10-09 21:23:58 +08:00
ret = tracepos ;
2019-10-10 18:34:11 +08:00
break ;
2019-05-13 02:38:03 +08:00
}
default :
2019-05-09 22:34:06 +08:00
PrintAndLogEx ( NORMAL , " Currently only 14a supported " ) ;
2019-10-09 21:23:58 +08:00
ret = traceLen ;
2019-10-10 18:34:11 +08:00
break ;
2019-05-09 22:34:06 +08:00
}
2019-10-09 21:23:58 +08:00
return ret ;
2019-05-09 22:34:06 +08:00
}
2021-02-09 23:56:55 +08:00
static uint16_t printTraceLine ( uint16_t tracepos , uint16_t traceLen , uint8_t * trace , uint8_t protocol , bool showWaitCycles , bool markCRCBytes , uint32_t * prev_eot , bool use_us ,
2021-01-27 06:14:20 +08:00
const uint64_t * mfDicKeys , uint32_t mfDicKeysCount ) {
2019-03-10 06:35:06 +08:00
// sanity check
2020-07-10 01:43:00 +08:00
if ( is_last_record ( tracepos , traceLen ) ) {
PrintAndLogEx ( DEBUG , " last record triggered. t-pos: %u t-len %u " , tracepos , traceLen ) ;
return traceLen ;
}
2019-03-10 06:35:06 +08:00
2020-07-13 19:55:19 +08:00
uint32_t end_of_transmission_timestamp = 0 ;
2020-05-19 08:14:43 +08:00
uint32_t duration ;
uint16_t data_len ;
2019-03-10 06:35:06 +08:00
uint8_t topaz_reader_command [ 9 ] ;
2020-05-06 18:14:05 +08:00
char explanation [ 40 ] = { 0 } ;
2019-03-10 06:35:06 +08:00
uint8_t mfData [ 32 ] = { 0 } ;
size_t mfDataLen = 0 ;
2020-05-19 06:36:30 +08:00
tracelog_hdr_t * first_hdr = ( tracelog_hdr_t * ) ( trace ) ;
tracelog_hdr_t * hdr = ( tracelog_hdr_t * ) ( trace + tracepos ) ;
2019-03-10 06:35:06 +08:00
2020-05-19 06:36:30 +08:00
duration = hdr - > duration ;
data_len = hdr - > data_len ;
2019-03-10 06:35:06 +08:00
2020-05-19 08:14:43 +08:00
if ( tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN ( hdr ) > traceLen ) {
2020-10-05 19:33:24 +08:00
PrintAndLogEx ( DEBUG , " trace pos offset % " PRIu64 " larger than reported tracelen %u " , tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN ( hdr ) , traceLen ) ;
2019-03-10 06:35:06 +08:00
return traceLen ;
}
2020-07-13 19:55:19 +08:00
2020-08-13 18:25:04 +08:00
// adjust for different time scales
if ( protocol = = ICLASS | | protocol = = ISO_15693 ) {
duration * = 32 ;
}
2020-07-13 19:55:19 +08:00
2020-05-19 06:36:30 +08:00
uint8_t * frame = hdr - > frame ;
uint8_t * parityBytes = hdr - > frame + data_len ;
2020-05-19 08:14:43 +08:00
tracepos + = TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN ( hdr ) ;
2019-03-10 06:35:06 +08:00
2020-05-19 08:14:43 +08:00
if ( protocol = = TOPAZ & & ! hdr - > isResponse ) {
2019-03-10 06:35:06 +08:00
// topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
// merge them:
2020-05-19 08:14:43 +08:00
if ( merge_topaz_reader_frames ( hdr - > timestamp , & duration , & tracepos , traceLen , trace , frame , topaz_reader_command , & data_len ) ) {
2019-03-10 06:35:06 +08:00
frame = topaz_reader_command ;
}
}
//Check the CRC status
uint8_t crcStatus = 2 ;
if ( data_len > 2 ) {
switch ( protocol ) {
case ICLASS :
2020-05-19 08:14:43 +08:00
crcStatus = iclass_CRC_check ( hdr - > isResponse , frame , data_len ) ;
2019-03-10 06:35:06 +08:00
break ;
case ISO_14443B :
case TOPAZ :
2020-12-18 09:37:31 +08:00
crcStatus = iso14443B_CRC_check ( frame , data_len ) ;
break ;
2019-03-10 06:35:06 +08:00
case FELICA :
2019-11-01 22:19:09 +08:00
crcStatus = ! felica_CRC_check ( frame + 2 , data_len - 4 ) ;
2019-03-10 06:35:06 +08:00
break ;
case PROTO_MIFARE :
2020-05-19 08:14:43 +08:00
crcStatus = mifare_CRC_check ( hdr - > isResponse , frame , data_len ) ;
2019-03-10 06:35:06 +08:00
break ;
case ISO_14443A :
case MFDES :
2019-12-24 07:57:15 +08:00
case LTO :
2020-05-19 08:14:43 +08:00
crcStatus = iso14443A_CRC_check ( hdr - > isResponse , frame , data_len ) ;
2019-03-10 06:35:06 +08:00
break ;
2020-12-18 09:37:31 +08:00
case ISO_7816_4 :
crcStatus = iso14443A_CRC_check ( hdr - > isResponse , frame , data_len ) = = 1 ? 3 : 0 ;
crcStatus = iso14443B_CRC_check ( frame , data_len ) = = 1 ? 4 : crcStatus ;
break ;
2019-08-02 02:06:07 +08:00
case THINFILM :
2019-08-02 06:26:48 +08:00
frame [ data_len - 1 ] ^ = frame [ data_len - 2 ] ;
frame [ data_len - 2 ] ^ = frame [ data_len - 1 ] ;
frame [ data_len - 1 ] ^ = frame [ data_len - 2 ] ;
2019-08-02 02:06:07 +08:00
crcStatus = iso14443A_CRC_check ( true , frame , data_len ) ;
2019-08-02 06:26:48 +08:00
frame [ data_len - 1 ] ^ = frame [ data_len - 2 ] ;
frame [ data_len - 2 ] ^ = frame [ data_len - 1 ] ;
frame [ data_len - 1 ] ^ = frame [ data_len - 2 ] ;
2019-08-02 02:06:07 +08:00
break ;
2019-03-10 06:35:06 +08:00
case ISO_15693 :
crcStatus = iso15693_CRC_check ( frame , data_len ) ;
break ;
2020-08-16 15:59:41 +08:00
case PROTO_CRYPTORF :
2020-01-20 18:37:10 +08:00
case PROTO_HITAG1 :
case PROTO_HITAG2 :
case PROTO_HITAGS :
2019-03-10 06:35:06 +08:00
default :
break ;
}
}
//0 CRC-command, CRC not ok
//1 CRC-command, CRC ok
//2 Not crc-command
2020-06-08 09:15:10 +08:00
//--- Draw the data column
2020-05-06 18:14:05 +08:00
char line [ 18 ] [ 120 ] = { { 0 } } ;
2019-03-10 06:35:06 +08:00
2020-06-08 09:15:10 +08:00
if ( data_len = = 0 ) {
2020-07-13 19:55:19 +08:00
if ( protocol = = ICLASS & & duration = = 2048 ) {
2020-08-13 18:25:04 +08:00
sprintf ( line [ 0 ] , " <SOF> " ) ;
} else if ( protocol = = ISO_15693 & & duration = = 512 ) {
sprintf ( line [ 0 ] , " <EOF> " ) ;
} else {
2020-07-13 19:55:19 +08:00
sprintf ( line [ 0 ] , " <empty trace - possible error> " ) ;
}
2020-05-19 06:46:10 +08:00
}
2019-03-10 07:00:59 +08:00
for ( int j = 0 ; j < data_len & & j / 18 < 18 ; j + + ) {
2019-03-10 06:35:06 +08:00
uint8_t parityBits = parityBytes [ j > > 3 ] ;
2019-03-14 19:30:32 +08:00
if ( protocol ! = LEGIC
& & protocol ! = ISO_14443B
2019-09-11 20:03:14 +08:00
& & protocol ! = ISO_15693
& & protocol ! = ICLASS
2019-03-14 19:30:32 +08:00
& & protocol ! = ISO_7816_4
2020-01-20 18:37:10 +08:00
& & protocol ! = PROTO_HITAG1
& & protocol ! = PROTO_HITAG2
& & protocol ! = PROTO_HITAGS
2019-08-02 02:06:07 +08:00
& & protocol ! = THINFILM
2019-10-30 20:42:52 +08:00
& & protocol ! = FELICA
2019-12-24 07:57:15 +08:00
& & protocol ! = LTO
2020-08-16 15:59:41 +08:00
& & protocol ! = PROTO_CRYPTORF
2021-03-10 20:52:26 +08:00
& & ( hdr - > isResponse | | protocol = = ISO_14443A | | protocol = = PROTO_MIFARE )
2019-03-14 19:30:32 +08:00
& & ( oddparity8 ( frame [ j ] ) ! = ( ( parityBits > > ( 7 - ( j & 0x0007 ) ) ) & 0x01 ) ) ) {
2019-03-10 06:35:06 +08:00
2020-05-06 18:14:05 +08:00
snprintf ( line [ j / 18 ] + ( ( j % 18 ) * 4 ) , 120 , " %02x! " , frame [ j ] ) ;
2020-05-19 08:14:43 +08:00
} else if ( protocol = = ICLASS & & hdr - > isResponse = = false ) {
2019-09-11 20:03:14 +08:00
uint8_t parity = 0 ;
2019-09-13 22:32:37 +08:00
for ( int i = 0 ; i < 6 ; i + + ) {
2019-09-11 20:03:14 +08:00
parity ^ = ( ( frame [ 0 ] > > i ) & 1 ) ;
}
2019-09-13 22:32:37 +08:00
if ( parity = = ( ( frame [ 0 ] > > 7 ) & 1 ) ) {
2020-05-06 18:14:05 +08:00
snprintf ( line [ j / 18 ] + ( ( j % 18 ) * 4 ) , 120 , " %02x " , frame [ j ] ) ;
2019-09-11 20:03:14 +08:00
} else {
2020-05-06 18:14:05 +08:00
snprintf ( line [ j / 18 ] + ( ( j % 18 ) * 4 ) , 120 , " %02x! " , frame [ j ] ) ;
2019-09-11 20:03:14 +08:00
}
2019-09-11 22:22:37 +08:00
2019-09-13 22:32:37 +08:00
} else {
2020-05-06 18:14:05 +08:00
snprintf ( line [ j / 18 ] + ( ( j % 18 ) * 4 ) , 120 , " %02x " , frame [ j ] ) ;
2019-03-10 06:35:06 +08:00
}
}
if ( markCRCBytes ) {
//CRC-command
2019-03-10 07:00:59 +08:00
if ( crcStatus = = 0 | | crcStatus = = 1 ) {
2021-03-10 21:08:33 +08:00
char * pos1 = line [ ( data_len - 2 ) / 18 ] + ( ( ( data_len - 2 ) % 18 ) * 4 ) - 1 ;
2019-03-10 06:35:06 +08:00
( * pos1 ) = ' [ ' ;
2021-03-10 21:08:33 +08:00
char * pos2 = line [ ( data_len ) / 18 ] + ( ( ( data_len ) % 18 ) * 4 ) - 1 ;
2019-03-10 06:35:06 +08:00
sprintf ( pos2 , " %c " , ' ] ' ) ;
}
}
// Draw the CRC column
2020-12-18 09:37:31 +08:00
const char * crcstrings [ ] = { " !crc " , " ok " , " " , " A ok " , " B ok " } ;
const char * crc = crcstrings [ crcStatus ] ;
2019-03-10 06:35:06 +08:00
2020-09-07 16:35:09 +08:00
// mark short bytes (less than 8 Bit + Parity)
if ( protocol = = ISO_14443A | |
protocol = = PROTO_MIFARE | |
protocol = = THINFILM ) {
2020-08-17 18:35:42 +08:00
// approximated with 128 * (9 * data_len);
uint16_t bitime = 1056 + 32 ;
if ( duration < bitime ) {
uint8_t m = 7 ;
while ( m > 0 ) {
2020-09-07 16:35:09 +08:00
bitime - = 128 ;
if ( duration > bitime ) {
2020-08-17 18:35:42 +08:00
break ;
2020-09-07 16:35:09 +08:00
}
2020-08-17 18:35:42 +08:00
m - - ;
}
2021-04-20 04:18:37 +08:00
if ( data_len ) {
line [ ( data_len - 1 ) / 16 ] [ ( ( data_len - 1 ) % 16 ) * 4 + 2 ] = ' ( ' ;
line [ ( data_len - 1 ) / 16 ] [ ( ( data_len - 1 ) % 16 ) * 4 + 3 ] = m + 0x30 ;
line [ ( data_len - 1 ) / 16 ] [ ( ( data_len - 1 ) % 16 ) * 4 + 4 ] = ' ) ' ;
}
2020-09-07 16:35:09 +08:00
}
}
2020-08-17 18:35:42 +08:00
2020-07-13 19:55:19 +08:00
2020-08-12 03:39:51 +08:00
uint32_t previous_end_of_transmission_timestamp = 0 ;
2020-07-13 19:55:19 +08:00
if ( prev_eot ) {
2020-08-13 18:25:04 +08:00
if ( * prev_eot ) {
previous_end_of_transmission_timestamp = * prev_eot ;
} else {
previous_end_of_transmission_timestamp = hdr - > timestamp ;
}
2020-08-12 03:39:51 +08:00
}
2020-07-13 19:55:19 +08:00
end_of_transmission_timestamp = hdr - > timestamp + duration ;
2020-08-12 03:39:51 +08:00
if ( prev_eot )
2020-07-13 19:55:19 +08:00
* prev_eot = end_of_transmission_timestamp ;
2019-03-10 06:35:06 +08:00
2020-08-16 15:59:41 +08:00
// Always annotate these protocols both reader/tag messages
switch ( protocol ) {
case PROTO_MIFARE :
annotateMifare ( explanation , sizeof ( explanation ) , frame , data_len , parityBytes , TRACELOG_PARITY_LEN ( hdr ) , hdr - > isResponse ) ;
break ;
case PROTO_HITAG1 :
annotateHitag1 ( explanation , sizeof ( explanation ) , frame , data_len , hdr - > isResponse ) ;
break ;
case PROTO_HITAG2 :
annotateHitag2 ( explanation , sizeof ( explanation ) , frame , data_len , hdr - > isResponse ) ;
break ;
case PROTO_HITAGS :
annotateHitagS ( explanation , sizeof ( explanation ) , frame , data_len , hdr - > isResponse ) ;
break ;
2020-08-20 03:51:10 +08:00
case ICLASS :
2020-09-07 16:35:09 +08:00
annotateIclass ( explanation , sizeof ( explanation ) , frame , data_len , hdr - > isResponse ) ;
break ;
2020-08-16 15:59:41 +08:00
default :
break ;
2020-08-12 03:39:51 +08:00
}
2019-10-30 20:35:03 +08:00
2020-08-12 03:39:51 +08:00
if ( hdr - > isResponse = = false ) {
2020-08-16 15:59:41 +08:00
2019-03-10 07:00:59 +08:00
switch ( protocol ) {
2020-08-16 15:59:41 +08:00
case LEGIC :
annotateLegic ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
2019-03-10 07:00:59 +08:00
case ISO_14443A :
annotateIso14443a ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
case MFDES :
annotateMfDesfire ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
case ISO_14443B :
annotateIso14443b ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
case TOPAZ :
annotateTopaz ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
case ISO_7816_4 :
2020-09-06 17:32:03 +08:00
annotateIso14443a ( explanation , sizeof ( explanation ) , frame , data_len ) ;
2019-03-10 07:00:59 +08:00
annotateIso7816 ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
case ISO_15693 :
annotateIso15693 ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
case FELICA :
annotateFelica ( explanation , sizeof ( explanation ) , frame , data_len ) ;
2020-01-04 01:19:42 +08:00
break ;
2019-12-24 07:57:15 +08:00
case LTO :
annotateLTO ( explanation , sizeof ( explanation ) , frame , data_len ) ;
2019-03-10 07:00:59 +08:00
break ;
2020-08-16 15:59:41 +08:00
case PROTO_CRYPTORF :
annotateCryptoRF ( explanation , sizeof ( explanation ) , frame , data_len ) ;
break ;
2019-03-10 07:00:59 +08:00
default :
break ;
2019-03-10 06:35:06 +08:00
}
}
2019-03-10 07:00:59 +08:00
int num_lines = MIN ( ( data_len - 1 ) / 18 + 1 , 18 ) ;
2019-03-10 06:35:06 +08:00
for ( int j = 0 ; j < num_lines ; j + + ) {
if ( j = = 0 ) {
2020-08-12 03:39:51 +08:00
2020-07-13 19:55:19 +08:00
uint32_t time1 = hdr - > timestamp - first_hdr - > timestamp ;
2020-08-13 18:25:04 +08:00
uint32_t time2 = end_of_transmission_timestamp - first_hdr - > timestamp ;
if ( prev_eot ) {
time1 = hdr - > timestamp - previous_end_of_transmission_timestamp ;
time2 = duration ;
}
2020-08-12 03:39:51 +08:00
2021-04-20 04:18:37 +08:00
if ( hdr - > isResponse ) {
// tag row
if ( use_us ) {
PrintAndLogEx ( NORMAL , " %10.1f | %10.1f | Tag |%-72s | %s| %s " ,
2021-05-06 03:04:48 +08:00
( float ) time1 / 13.56 ,
( float ) time2 / 13.56 ,
line [ j ] ,
( j = = num_lines - 1 ) ? crc : " " ,
( j = = num_lines - 1 ) ? explanation : " "
) ;
2021-04-20 04:18:37 +08:00
} else {
PrintAndLogEx ( NORMAL , " %10u | %10u | Tag |%-72s | %s| %s " ,
2021-05-06 03:04:48 +08:00
( hdr - > timestamp - first_hdr - > timestamp ) ,
( end_of_transmission_timestamp - first_hdr - > timestamp ) ,
line [ j ] ,
( j = = num_lines - 1 ) ? crc : " " ,
( j = = num_lines - 1 ) ? explanation : " "
) ;
2021-04-20 04:18:37 +08:00
}
2020-07-13 19:55:19 +08:00
} else {
2021-04-20 04:18:37 +08:00
// reader row
if ( use_us ) {
2021-05-06 03:04:48 +08:00
PrintAndLogEx ( NORMAL ,
_YELLOW_ ( " %10.1f " ) " | " _YELLOW_ ( " %10.1f " ) " | " _YELLOW_ ( " Rdr " ) " | " _YELLOW_ ( " %-72s " ) " | " _YELLOW_ ( " %s " ) " | " _YELLOW_ ( " %s " ) ,
( float ) time1 / 13.56 ,
( float ) time2 / 13.56 ,
line [ j ] ,
( j = = num_lines - 1 ) ? crc : " " ,
( j = = num_lines - 1 ) ? explanation : " "
) ;
2021-04-20 04:18:37 +08:00
} else {
PrintAndLogEx ( NORMAL ,
2021-05-06 03:04:48 +08:00
_YELLOW_ ( " %10u " ) " | " _YELLOW_ ( " %10u " ) " | " _YELLOW_ ( " Rdr " ) " | " _YELLOW_ ( " %-72s " ) " | " _YELLOW_ ( " %s " ) " | " _YELLOW_ ( " %s " ) ,
( hdr - > timestamp - first_hdr - > timestamp ) ,
( end_of_transmission_timestamp - first_hdr - > timestamp ) ,
line [ j ] ,
( j = = num_lines - 1 ) ? crc : " " ,
( j = = num_lines - 1 ) ? explanation : " "
) ;
2021-04-20 04:18:37 +08:00
}
2020-08-12 03:39:51 +08:00
}
2020-07-13 19:55:19 +08:00
2019-03-10 06:35:06 +08:00
} else {
2021-04-20 04:18:37 +08:00
if ( hdr - > isResponse ) {
PrintAndLogEx ( NORMAL , " | | |%-72s | %s| %s " ,
2021-05-06 03:04:48 +08:00
line [ j ] ,
( j = = num_lines - 1 ) ? crc : " " ,
( j = = num_lines - 1 ) ? explanation : " "
) ;
2021-04-20 04:18:37 +08:00
} else {
PrintAndLogEx ( NORMAL , " | | | " _YELLOW_ ( " %-72s " ) " | " _YELLOW_ ( " %s " ) " | " _YELLOW_ ( " %s " ) ,
2021-05-06 03:04:48 +08:00
line [ j ] ,
( j = = num_lines - 1 ) ? crc : " " ,
( j = = num_lines - 1 ) ? explanation : " "
) ;
2021-04-20 04:18:37 +08:00
}
2019-03-10 06:35:06 +08:00
}
}
2020-07-13 18:25:44 +08:00
if ( protocol = = PROTO_MIFARE ) {
2021-01-27 06:14:20 +08:00
if ( DecodeMifareData ( frame , data_len , parityBytes , hdr - > isResponse , mfData , & mfDataLen , mfDicKeys , mfDicKeysCount ) ) {
2020-07-13 18:25:44 +08:00
memset ( explanation , 0x00 , sizeof ( explanation ) ) ;
2020-08-12 03:39:51 +08:00
if ( hdr - > isResponse = = false ) {
2020-07-13 18:25:44 +08:00
annotateIso14443a ( explanation , sizeof ( explanation ) , mfData , mfDataLen ) ;
}
uint8_t crcc = iso14443A_CRC_check ( hdr - > isResponse , mfData , mfDataLen ) ;
PrintAndLogEx ( NORMAL , " | | * |%-72s | %-4s| %s " ,
sprint_hex_inrow_spaces ( mfData , mfDataLen , 2 ) ,
( crcc = = 0 ? " !crc " : ( crcc = = 1 ? " ok " : " " ) ) ,
explanation ) ;
2019-03-10 06:35:06 +08:00
}
2019-10-30 20:35:03 +08:00
}
2019-03-10 06:35:06 +08:00
2020-07-13 18:25:44 +08:00
if ( is_last_record ( tracepos , traceLen ) ) {
return traceLen ;
}
2019-03-10 06:35:06 +08:00
2020-08-12 03:39:51 +08:00
if ( showWaitCycles & & hdr - > isResponse = = false & & next_record_is_response ( tracepos , trace ) ) {
2020-06-08 09:15:10 +08:00
2020-05-19 06:46:10 +08:00
tracelog_hdr_t * next_hdr = ( tracelog_hdr_t * ) ( trace + tracepos ) ;
2020-06-08 09:15:10 +08:00
2020-08-12 03:39:51 +08:00
PrintAndLogEx ( NORMAL , " %10u | %10u | %s |fdt (Frame Delay Time): " _YELLOW_ ( " %d " ) ,
2020-07-13 19:55:19 +08:00
( end_of_transmission_timestamp - first_hdr - > timestamp ) ,
2020-05-19 08:14:43 +08:00
( next_hdr - > timestamp - first_hdr - > timestamp ) ,
2019-03-10 07:00:59 +08:00
" " ,
2020-07-13 19:55:19 +08:00
( next_hdr - > timestamp - end_of_transmission_timestamp ) ) ;
2019-03-10 07:00:59 +08:00
}
2019-03-10 06:35:06 +08:00
return tracepos ;
2018-03-19 01:00:41 +08:00
}
2020-06-04 17:50:41 +08:00
static int download_trace ( void ) {
2020-06-08 09:15:10 +08:00
2020-07-13 18:25:44 +08:00
if ( IfPm3Present ( ) = = false ) {
2021-06-23 15:52:29 +08:00
PrintAndLogEx ( FAILED , " You requested a trace upload in offline mode, consider using parameter '-1' for working from Tracebuffer " ) ;
2020-06-04 17:50:41 +08:00
return PM3_EINVARG ;
}
// reserve some space.
if ( g_trace )
free ( g_trace ) ;
g_traceLen = 0 ;
g_trace = calloc ( PM3_CMD_DATA_SIZE , sizeof ( uint8_t ) ) ;
if ( g_trace = = NULL ) {
PrintAndLogEx ( FAILED , " Cannot allocate memory for trace " ) ;
return PM3_EMALLOC ;
}
2020-07-13 18:25:44 +08:00
PrintAndLogEx ( INFO , " downloading tracelog data from device " ) ;
2020-06-04 17:50:41 +08:00
// Query for the size of the trace, downloading PM3_CMD_DATA_SIZE
PacketResponseNG response ;
if ( ! GetFromDevice ( BIG_BUF , g_trace , PM3_CMD_DATA_SIZE , 0 , NULL , 0 , & response , 4000 , true ) ) {
PrintAndLogEx ( WARNING , " timeout while waiting for reply. " ) ;
free ( g_trace ) ;
return PM3_ETIMEOUT ;
}
g_traceLen = response . oldarg [ 2 ] ;
// if tracelog buffer was larger and we need to download more.
if ( g_traceLen > PM3_CMD_DATA_SIZE ) {
free ( g_trace ) ;
g_trace = calloc ( g_traceLen , sizeof ( uint8_t ) ) ;
if ( g_trace = = NULL ) {
PrintAndLogEx ( FAILED , " Cannot allocate memory for trace " ) ;
return PM3_EMALLOC ;
}
if ( ! GetFromDevice ( BIG_BUF , g_trace , g_traceLen , 0 , NULL , 0 , NULL , 2500 , false ) ) {
PrintAndLogEx ( WARNING , " command execution time out " ) ;
free ( g_trace ) ;
return PM3_ETIMEOUT ;
}
}
return PM3_SUCCESS ;
}
2018-03-19 02:58:22 +08:00
// sanity check. Don't use proxmark if it is offline and you didn't specify useTraceBuffer
2018-08-13 03:54:31 +08:00
/*
2018-03-19 02:58:22 +08:00
static int SanityOfflineCheck ( bool useTraceBuffer ) {
2019-03-10 06:35:06 +08:00
if ( ! useTraceBuffer & & offline ) {
PrintAndLogEx ( NORMAL , " Your proxmark3 device is offline. Specify [1] to use TraceBuffer data instead " ) ;
return 0 ;
}
return 1 ;
2018-03-19 02:58:22 +08:00
}
2018-08-13 03:54:31 +08:00
*/
2018-03-19 02:58:22 +08:00
2019-04-12 06:38:54 +08:00
static int CmdTraceLoad ( const char * Cmd ) {
2020-10-10 01:45:29 +08:00
CLIParserContext * ctx ;
CLIParserInit ( & ctx , " trace load " ,
" Load protocol data from binary file to trace buffer \n "
2020-12-05 20:27:39 +08:00
" File extension is <.trace> " ,
" trace load -f mytracefile -> w/o file extension "
2020-10-10 01:45:29 +08:00
) ;
void * argtable [ ] = {
arg_param_begin ,
arg_strx0 ( " f " , " file " , " <filename> " , " trace file to load " ) ,
arg_param_end
} ;
CLIExecWithReturn ( ctx , Cmd , argtable , false ) ;
int fnlen = 0 ;
char filename [ FILE_PATH_SIZE ] = { 0 } ;
CLIParamStrToBuf ( arg_get_str ( ctx , 1 ) , ( uint8_t * ) filename , FILE_PATH_SIZE , & fnlen ) ;
CLIParserFree ( ctx ) ;
2019-04-12 06:38:54 +08:00
2020-05-04 03:43:03 +08:00
if ( g_trace )
free ( g_trace ) ;
2019-04-12 06:38:54 +08:00
2020-06-03 18:29:52 +08:00
size_t len = 0 ;
2020-06-08 09:15:10 +08:00
if ( loadFile_safe ( filename , " .trace " , ( void * * ) & g_trace , & len ) ! = PM3_SUCCESS ) {
2020-06-03 18:29:52 +08:00
PrintAndLogEx ( FAILED , " Could not open file " _YELLOW_ ( " %s " ) , filename ) ;
return PM3_EIO ;
2019-04-12 06:38:54 +08:00
}
2020-06-08 09:15:10 +08:00
2020-06-03 18:29:52 +08:00
g_traceLen = ( long ) len ;
2020-06-08 09:15:10 +08:00
2020-06-23 17:24:00 +08:00
PrintAndLogEx ( SUCCESS , " Recorded Activity (TraceLen = " _YELLOW_ ( " %lu " ) " bytes) " , g_traceLen ) ;
2019-11-25 04:14:27 +08:00
return PM3_SUCCESS ;
2019-04-12 06:38:54 +08:00
}
static int CmdTraceSave ( const char * Cmd ) {
2020-06-08 09:15:10 +08:00
2020-10-10 01:45:29 +08:00
CLIParserContext * ctx ;
CLIParserInit ( & ctx , " trace save " ,
" Save protocol data from trace buffer to binary file \n "
2020-12-05 20:27:39 +08:00
" File extension is <.trace> " ,
" trace save -f mytracefile -> w/o file extension "
2020-10-10 01:45:29 +08:00
) ;
void * argtable [ ] = {
arg_param_begin ,
2020-12-05 20:27:39 +08:00
arg_strx0 ( " f " , " file " , " <filename> " , " trace file to save " ) ,
2020-10-10 01:45:29 +08:00
arg_param_end
} ;
CLIExecWithReturn ( ctx , Cmd , argtable , false ) ;
int fnlen = 0 ;
char filename [ FILE_PATH_SIZE ] = { 0 } ;
CLIParamStrToBuf ( arg_get_str ( ctx , 1 ) , ( uint8_t * ) filename , FILE_PATH_SIZE , & fnlen ) ;
CLIParserFree ( ctx ) ;
2020-08-12 03:39:51 +08:00
2020-06-04 17:50:41 +08:00
if ( g_traceLen = = 0 ) {
download_trace ( ) ;
2021-01-29 03:31:39 +08:00
if ( g_traceLen = = 0 ) {
PrintAndLogEx ( WARNING , " trace is empty, nothing to save " ) ;
return PM3_SUCCESS ;
}
2019-04-12 06:38:54 +08:00
}
2020-06-04 17:52:58 +08:00
saveFile ( filename , " .trace " , g_trace , g_traceLen ) ;
2019-11-25 04:14:27 +08:00
return PM3_SUCCESS ;
2019-04-12 06:38:54 +08:00
}
2021-04-20 03:21:47 +08:00
int CmdTraceListAlias ( const char * Cmd , const char * alias , const char * protocol ) {
2021-04-19 20:35:09 +08:00
CLIParserContext * ctx ;
2021-04-20 03:21:47 +08:00
char desc [ 500 ] = { 0 } ;
snprintf ( desc , sizeof ( desc ) - 1 ,
2021-05-06 03:04:48 +08:00
" Alias of `trace list -t %s` with selected protocol data to annotate trace buffer \n "
" You can load a trace from file (see `trace load -h`) or it be downloaded from device by default \n "
" It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol " ,
protocol ) ;
2021-04-19 20:35:09 +08:00
char example [ 200 ] = { 0 } ;
2021-04-20 03:21:47 +08:00
snprintf ( example , sizeof ( example ) - 1 ,
2021-05-06 03:04:48 +08:00
" %s list -f -> show frame delay times \n "
" %s list -1 -> use trace buffer " ,
alias , alias ) ;
2021-04-20 03:21:47 +08:00
char fullalias [ 100 ] = { 0 } ;
snprintf ( fullalias , sizeof ( fullalias ) - 1 , " %s list " , alias ) ;
CLIParserInit ( & ctx , fullalias , desc , example ) ;
2021-04-19 20:35:09 +08:00
void * argtable [ ] = {
arg_param_begin ,
arg_lit0 ( " 1 " , " buffer " , " use data from trace buffer " ) ,
arg_lit0 ( " f " , NULL , " show frame delay times " ) ,
arg_lit0 ( " c " , NULL , " mark CRC bytes " ) ,
arg_lit0 ( " r " , NULL , " show relative times (gap and duration) " ) ,
arg_lit0 ( " u " , NULL , " display times in microseconds instead of clock cycles " ) ,
arg_lit0 ( " x " , NULL , " show hexdump to convert to pcap(ng) \n "
" or to import into Wireshark using encapsulation type \" ISO 14443 \" " ) ,
arg_strx0 ( NULL , " dict " , " <file> " , " use dictionary keys file " ) ,
arg_param_end
} ;
CLIExecWithReturn ( ctx , Cmd , argtable , true ) ;
2021-04-20 05:31:11 +08:00
CLIParserFree ( ctx ) ;
2021-04-20 03:21:47 +08:00
char args [ 128 ] = { 0 } ;
snprintf ( args , sizeof ( args ) , " -t %s " , protocol ) ;
2021-04-20 05:25:13 +08:00
strncat ( args , Cmd , sizeof ( args ) - strlen ( args ) - 1 ) ;
2021-04-20 03:21:47 +08:00
return CmdTraceList ( args ) ;
2021-04-19 20:35:09 +08:00
}
2019-03-10 18:20:22 +08:00
int CmdTraceList ( const char * Cmd ) {
2020-10-10 01:45:29 +08:00
CLIParserContext * ctx ;
CLIParserInit ( & ctx , " trace list " ,
2020-10-12 04:40:05 +08:00
" Annotate trace buffer with selected protocol data \n "
" You can load a trace from file (see `trace load -h`) or it be downloaded from device by default \n " ,
" trace list -t raw -> just show raw data without annotations \n "
" trace list -t 14a -> interpret as " _YELLOW_ ( " ISO14443-A " ) " communications \n "
" trace list -t thinfilm -> interpret as " _YELLOW_ ( " Thinfilm " ) " communications \n "
" trace list -t topaz -> interpret as " _YELLOW_ ( " Topaz " ) " communications \n "
" trace list -t mf -> interpret as " _YELLOW_ ( " MIFARE Classic " ) " communications and decrypt crypto1 stream \n "
" trace list -t des -> interpret as " _YELLOW_ ( " MIFARE DESFire " ) " communications \n "
" trace list -t 14b -> interpret as " _YELLOW_ ( " ISO14443-B " ) " communications \n "
" trace list -t 7816 -> interpret as " _YELLOW_ ( " ISO7816-4 " ) " communications \n "
" trace list -t 15 -> interpret as " _YELLOW_ ( " ISO15693 " ) " communications \n "
" trace list -t iclass -> interpret as " _YELLOW_ ( " iCLASS " ) " communications \n "
" trace list -t legic -> interpret as " _YELLOW_ ( " LEGIC " ) " communications \n "
" trace list -t felica -> interpret as " _YELLOW_ ( " ISO18092 / FeliCa " ) " communications \n "
" trace list -t hitag1 -> interpret as " _YELLOW_ ( " Hitag1 " ) " communications \n "
" trace list -t hitag2 -> interpret as " _YELLOW_ ( " Hitag2 " ) " communications \n "
" trace list -t hitags -> interpret as " _YELLOW_ ( " HitagS " ) " communications \n "
" trace list -t lto -> interpret as " _YELLOW_ ( " LTO-CM " ) " communications \n "
" trace list -t cryptorf -> interpret as " _YELLOW_ ( " CryptoRF " ) " communitcations \n "
2021-01-27 19:43:50 +08:00
" trace list -t mf --dict <mfc_default_keys> -> use dictionary keys file \n "
2021-01-27 06:14:20 +08:00
" trace list -t 14a -f -> show frame delay times \n "
" trace list -t 14a -1 -> use trace buffer "
2020-10-12 04:40:05 +08:00
) ;
2020-10-10 01:45:29 +08:00
void * argtable [ ] = {
arg_param_begin ,
arg_lit0 ( " 1 " , " buffer " , " use data from trace buffer " ) ,
arg_lit0 ( " f " , NULL , " show frame delay times " ) ,
arg_lit0 ( " c " , NULL , " mark CRC bytes " ) ,
arg_lit0 ( " r " , NULL , " show relative times (gap and duration) " ) ,
arg_lit0 ( " u " , NULL , " display times in microseconds instead of clock cycles " ) ,
arg_lit0 ( " x " , NULL , " show hexdump to convert to pcap(ng) \n "
2020-10-12 04:40:05 +08:00
" or to import into Wireshark using encapsulation type \" ISO 14443 \" " ) ,
2020-10-10 01:45:29 +08:00
arg_strx0 ( " t " , " type " , NULL , " protocol to annotate the trace " ) ,
2021-01-27 19:43:50 +08:00
arg_strx0 ( NULL , " dict " , " <file> " , " use dictionary keys file " ) ,
2020-10-10 01:45:29 +08:00
arg_param_end
} ;
CLIExecWithReturn ( ctx , Cmd , argtable , false ) ;
2020-10-12 04:40:05 +08:00
2020-10-10 01:45:29 +08:00
bool use_buffer = arg_get_lit ( ctx , 1 ) ;
bool show_wait_cycles = arg_get_lit ( ctx , 2 ) ;
bool mark_crc = arg_get_lit ( ctx , 3 ) ;
bool use_relative = arg_get_lit ( ctx , 4 ) ;
2020-10-12 04:40:05 +08:00
bool use_us = arg_get_lit ( ctx , 5 ) ;
2020-10-10 01:45:29 +08:00
bool show_hex = arg_get_lit ( ctx , 6 ) ;
int tlen = 0 ;
2019-03-10 06:35:06 +08:00
char type [ 10 ] = { 0 } ;
2020-10-10 01:45:29 +08:00
CLIParamStrToBuf ( arg_get_str ( ctx , 7 ) , ( uint8_t * ) type , sizeof ( type ) , & tlen ) ;
str_lower ( type ) ;
2020-10-12 04:40:05 +08:00
2021-01-27 06:14:20 +08:00
int diclen = 0 ;
2021-01-27 19:43:50 +08:00
char dictionary [ FILE_PATH_SIZE + 2 ] = { 0 } ;
if ( CLIParamStrToBuf ( arg_get_str ( ctx , 8 ) , ( uint8_t * ) dictionary , FILE_PATH_SIZE , & diclen ) ) {
PrintAndLogEx ( FAILED , " Dictionary file name too long or invalid. " ) ;
diclen = 0 ;
}
2021-01-27 06:14:20 +08:00
2020-10-10 01:45:29 +08:00
CLIParserFree ( ctx ) ;
2019-03-10 06:35:06 +08:00
2020-10-10 01:45:29 +08:00
clearCommandBuffer ( ) ;
2019-03-10 06:35:06 +08:00
2020-10-10 01:45:29 +08:00
// no crc, no annotations
uint8_t protocol = - 1 ;
// validate type of output
if ( strcmp ( type , " iclass " ) = = 0 ) protocol = ICLASS ;
else if ( strcmp ( type , " 14a " ) = = 0 ) protocol = ISO_14443A ;
else if ( strcmp ( type , " 14b " ) = = 0 ) protocol = ISO_14443B ;
else if ( strcmp ( type , " topaz " ) = = 0 ) protocol = TOPAZ ;
else if ( strcmp ( type , " 7816 " ) = = 0 ) protocol = ISO_7816_4 ;
else if ( strcmp ( type , " des " ) = = 0 ) protocol = MFDES ;
else if ( strcmp ( type , " legic " ) = = 0 ) protocol = LEGIC ;
else if ( strcmp ( type , " 15 " ) = = 0 ) protocol = ISO_15693 ;
else if ( strcmp ( type , " felica " ) = = 0 ) protocol = FELICA ;
else if ( strcmp ( type , " mf " ) = = 0 ) protocol = PROTO_MIFARE ;
else if ( strcmp ( type , " hitag1 " ) = = 0 ) protocol = PROTO_HITAG1 ;
else if ( strcmp ( type , " hitag2 " ) = = 0 ) protocol = PROTO_HITAG2 ;
else if ( strcmp ( type , " hitags " ) = = 0 ) protocol = PROTO_HITAGS ;
else if ( strcmp ( type , " thinfilm " ) = = 0 ) protocol = THINFILM ;
else if ( strcmp ( type , " lto " ) = = 0 ) protocol = LTO ;
else if ( strcmp ( type , " cryptorf " ) = = 0 ) protocol = PROTO_CRYPTORF ;
2020-10-12 04:40:05 +08:00
else if ( strcmp ( type , " raw " ) = = 0 ) protocol = - 1 ;
2020-10-10 01:45:29 +08:00
2021-04-19 20:22:15 +08:00
if ( use_buffer = = false ) {
2020-06-04 17:50:41 +08:00
download_trace ( ) ;
2021-04-19 20:22:15 +08:00
} else if ( g_traceLen = = 0 ) {
PrintAndLogEx ( FAILED , " You requested a trace list in offline mode but there is no trace, consider using 'trace load' or removing parameter '1' " ) ;
return PM3_EINVARG ;
2019-03-10 06:35:06 +08:00
}
2020-05-04 03:43:03 +08:00
PrintAndLogEx ( SUCCESS , " Recorded activity (trace len = " _YELLOW_ ( " %lu " ) " bytes) " , g_traceLen ) ;
2020-05-08 18:30:18 +08:00
if ( g_traceLen = = 0 ) {
return PM3_SUCCESS ;
}
uint16_t tracepos = 0 ;
2019-10-30 20:35:03 +08:00
/*
2019-03-10 06:35:06 +08:00
if ( protocol = = FELICA ) {
2020-05-04 03:43:03 +08:00
printFelica ( g_traceLen , g_trace ) ;
2019-10-30 20:35:03 +08:00
} */
2020-10-10 01:45:29 +08:00
if ( show_hex ) {
2020-05-04 03:43:03 +08:00
while ( tracepos < g_traceLen ) {
tracepos = printHexLine ( tracepos , g_traceLen , g_trace , protocol ) ;
2019-05-09 22:34:06 +08:00
}
2019-03-10 06:35:06 +08:00
} else {
2020-07-13 19:55:19 +08:00
2020-08-13 18:25:04 +08:00
if ( use_relative ) {
2020-07-13 19:55:19 +08:00
PrintAndLogEx ( INFO , _YELLOW_ ( " gap " ) " = time between transfers. " _YELLOW_ ( " duration " ) " = duration of data transfer. " _YELLOW_ ( " src " ) " = source of transfer " ) ;
2020-08-13 18:25:04 +08:00
} else {
2020-07-13 19:55:19 +08:00
PrintAndLogEx ( INFO , _YELLOW_ ( " start " ) " = start of start frame " _YELLOW_ ( " end " ) " = end of frame. " _YELLOW_ ( " src " ) " = source of transfer " ) ;
2020-08-13 18:25:04 +08:00
}
2020-07-13 19:55:19 +08:00
if ( protocol = = ISO_14443A | | protocol = = PROTO_MIFARE | | protocol = = MFDES | | protocol = = TOPAZ | | protocol = = LTO ) {
if ( use_us )
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO14443A " ) " - all times are in microseconds " ) ;
else
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO14443A " ) " - all times are in carrier periods (1/13.56MHz) " ) ;
}
if ( protocol = = THINFILM ) {
if ( use_us )
2020-08-12 03:39:51 +08:00
PrintAndLogEx ( INFO , _YELLOW_ ( " Thinfilm " ) " - all times are in microseconds " ) ;
2020-07-13 19:55:19 +08:00
else
PrintAndLogEx ( INFO , _YELLOW_ ( " Thinfilm " ) " - all times are in carrier periods (1/13.56MHz) " ) ;
}
if ( protocol = = ICLASS | | protocol = = ISO_15693 ) {
if ( use_us )
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO15693 / iCLASS " ) " - all times are in microseconds " ) ;
else
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO15693 / iCLASS " ) " - all times are in carrier periods (1/13.56MHz) " ) ;
}
2019-03-10 07:00:59 +08:00
if ( protocol = = LEGIC )
2020-07-13 19:55:19 +08:00
PrintAndLogEx ( INFO , _YELLOW_ ( " LEGIC " ) " - Reader Mode: Timings are in ticks (1us == 1.5ticks) \n "
2019-03-10 07:00:59 +08:00
" Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us) " ) ;
2020-07-13 19:55:19 +08:00
2020-08-16 15:59:41 +08:00
if ( protocol = = ISO_14443B | | protocol = = PROTO_CRYPTORF ) {
2020-07-13 19:55:19 +08:00
if ( use_us )
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO14443B " ) " - all times are in microseconds " ) ;
else
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO14443B " ) " - all times are in carrier periods (1/13.56MHz) " ) ;
}
2019-03-10 07:00:59 +08:00
if ( protocol = = ISO_7816_4 )
2020-07-13 19:55:19 +08:00
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO7816-4 / Smartcard " ) " - Timings N/A " ) ;
2020-01-20 18:37:10 +08:00
if ( protocol = = PROTO_HITAG1 | | protocol = = PROTO_HITAG2 | | protocol = = PROTO_HITAGS )
2020-07-13 19:55:19 +08:00
PrintAndLogEx ( INFO , _YELLOW_ ( " Hitag1 / Hitag2 / HitagS " ) " - Timings in ETU (8us) " ) ;
if ( protocol = = FELICA ) {
if ( use_us )
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO18092 / FeliCa " ) " - all times are in microseconds " ) ;
else
PrintAndLogEx ( INFO , _YELLOW_ ( " ISO18092 / FeliCa " ) " - all times are in carrier periods (1/13.56MHz) " ) ;
}
2020-04-16 15:01:14 +08:00
2021-01-27 06:14:20 +08:00
const uint64_t * dicKeys = NULL ;
uint32_t dicKeysCount = 0 ;
bool dictionaryLoad = false ;
if ( protocol = = PROTO_MIFARE ) {
if ( diclen > 0 ) {
uint8_t * keyBlock = NULL ;
int res = loadFileDICTIONARY_safe ( dictionary , ( void * * ) & keyBlock , 6 , & dicKeysCount ) ;
if ( res ! = PM3_SUCCESS | | dicKeysCount = = 0 | | keyBlock = = NULL ) {
PrintAndLogEx ( FAILED , " An error occurred while loading the dictionary! (we will use the default keys now) " ) ;
} else {
dicKeys = calloc ( dicKeysCount , sizeof ( uint64_t ) ) ;
for ( int i = 0 ; i < dicKeysCount ; i + + ) {
uint64_t key = bytes_to_num ( keyBlock + i * 6 , 6 ) ;
memcpy ( ( uint8_t * ) & dicKeys [ i ] , & key , sizeof ( uint64_t ) ) ;
}
dictionaryLoad = true ;
}
if ( keyBlock ! = NULL ) {
free ( keyBlock ) ;
}
}
if ( dicKeys = = NULL ) {
dicKeys = g_mifare_default_keys ;
dicKeysCount = ARRAYLEN ( g_mifare_default_keys ) ;
}
}
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2020-08-13 18:25:04 +08:00
if ( use_relative ) {
PrintAndLogEx ( NORMAL , " Gap | Duration | Src | Data (! denotes parity error, ' denotes short bytes) | CRC | Annotation " ) ;
} else {
2020-07-13 19:55:19 +08:00
PrintAndLogEx ( NORMAL , " Start | End | Src | Data (! denotes parity error) | CRC | Annotation " ) ;
}
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " ------------+------------+-----+-------------------------------------------------------------------------+-----+-------------------- " ) ;
2020-07-13 18:25:44 +08:00
// clean authentication data used with the mifare classic decrypt fct
if ( protocol = = ISO_14443A | | protocol = = PROTO_MIFARE )
ClearAuthData ( ) ;
2020-07-13 19:55:19 +08:00
uint32_t previous_EOT = 0 ;
uint32_t * prev_EOT = NULL ;
if ( use_relative ) {
prev_EOT = & previous_EOT ;
}
2020-08-12 03:39:51 +08:00
2020-05-04 03:43:03 +08:00
while ( tracepos < g_traceLen ) {
2021-01-27 06:14:20 +08:00
tracepos = printTraceLine ( tracepos , g_traceLen , g_trace , protocol , show_wait_cycles , mark_crc , prev_EOT , use_us , dicKeys , dicKeysCount ) ;
2019-08-07 18:12:44 +08:00
2019-08-05 01:13:54 +08:00
if ( kbd_enter_pressed ( ) )
break ;
2019-03-10 06:35:06 +08:00
}
2021-01-27 06:14:20 +08:00
if ( dictionaryLoad )
free ( ( void * ) dicKeys ) ;
2019-03-10 06:35:06 +08:00
}
2020-10-12 04:40:05 +08:00
2020-10-10 01:45:29 +08:00
if ( show_hex )
PrintAndLogEx ( HINT , " syntax to use: " _YELLOW_ ( " `text2pcap -t \" %%S. \" -l 264 -n <input-text-file> <output-pcapng-file>` " ) ) ;
2019-11-25 04:14:27 +08:00
return PM3_SUCCESS ;
2018-03-19 01:00:41 +08:00
}
2020-06-04 17:50:41 +08:00
static command_t CommandTable [ ] = {
{ " help " , CmdHelp , AlwaysAvailable , " This help " } ,
{ " list " , CmdTraceList , AlwaysAvailable , " List protocol data in trace buffer " } ,
{ " load " , CmdTraceLoad , AlwaysAvailable , " Load trace from file " } ,
{ " save " , CmdTraceSave , AlwaysAvailable , " Save trace buffer to file " } ,
{ NULL , NULL , NULL , NULL }
} ;
static int CmdHelp ( const char * Cmd ) {
( void ) Cmd ; // Cmd is not used so far
CmdsHelp ( CommandTable ) ;
return PM3_SUCCESS ;
}
int CmdTrace ( const char * Cmd ) {
clearCommandBuffer ( ) ;
return CmdsParse ( CommandTable , Cmd ) ;
}