MFULC trace: detect when known key is used during auth

This commit is contained in:
Philippe Teuwen 2021-10-15 01:31:16 +02:00
commit e5d7ce61e6
5 changed files with 298 additions and 199 deletions

View file

@ -47,6 +47,9 @@ void ClearAuthData(void) {
static int gs_ntag_i2c_state = 0; static int gs_ntag_i2c_state = 0;
static int gs_mfuc_state = 0;
static uint8_t gs_mfuc_authdata[3][16] = {0};
static uint8_t *gs_mfuc_key = NULL;
/** /**
* @brief iso14443A_CRC_check Checks CRC in command or response * @brief iso14443A_CRC_check Checks CRC in command or response
@ -162,202 +165,240 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n) {
} }
int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response) {
if (! is_response) {
if ((gs_ntag_i2c_state == 1) && (cmdsize == 6) && (memcmp(cmd + 1, "\x00\x00\x00", 3) == 0)) {
snprintf(exp, size, "SECTOR(%d)", cmd[0]);
gs_ntag_i2c_state = 0;
return 1;
}
if ((gs_ntag_i2c_state == 1) && (cmdsize == 6) && (memcmp(cmd + 1, "\x00\x00\x00", 3) == 0)) {
snprintf(exp, size, "SECTOR(%d)", cmd[0]);
gs_ntag_i2c_state = 0; gs_ntag_i2c_state = 0;
return 1; switch (cmd[0]) {
} case ISO14443A_CMD_WUPA:
snprintf(exp, size, "WUPA");
gs_ntag_i2c_state = 0; break;
case ISO14443A_CMD_ANTICOLL_OR_SELECT: {
switch (cmd[0]) { // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
case ISO14443A_CMD_WUPA: // 93 50 = Bit oriented anti-collision (usage: 9350+ up to 5bytes, 9350 answer - up to 5bytes UID+BCC)
snprintf(exp, size, "WUPA"); // 93 70 = Select (usage: 9370+5bytes 9370 answer - answer: 1byte SAK)
break; if (cmd[1] == 0x70)
case ISO14443A_CMD_ANTICOLL_OR_SELECT: { snprintf(exp, size, "SELECT_UID");
// 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) else if (cmd[1] == 0x20 || cmd[1] == 0x50)
// 93 50 = Bit oriented anti-collision (usage: 9350+ up to 5bytes, 9350 answer - up to 5bytes UID+BCC) snprintf(exp, size, "ANTICOLL");
// 93 70 = Select (usage: 9370+5bytes 9370 answer - answer: 1byte SAK) else
if (cmd[1] == 0x70) snprintf(exp, size, "SELECT_XXX");
snprintf(exp, size, "SELECT_UID"); break;
else if (cmd[1] == 0x20 || cmd[1] == 0x50)
snprintf(exp, size, "ANTICOLL");
else
snprintf(exp, size, "SELECT_XXX");
break;
}
case ISO14443A_CMD_ANTICOLL_OR_SELECT_2: {
//95 20 = Anticollision of cascade level2
//95 50 = Bit oriented anti-collision level2
//95 70 = Select of cascade level2
if (cmd[1] == 0x70)
snprintf(exp, size, "SELECT_UID-2");
else if (cmd[1] == 0x20 || cmd[1] == 0x50)
snprintf(exp, size, "ANTICOLL-2");
else
snprintf(exp, size, "SELECT_XXX-2");
break;
}
case ISO14443A_CMD_ANTICOLL_OR_SELECT_3: {
//97 20 = Anticollision of cascade level3
//97 50 = Bit oriented anti-collision level3
//97 70 = Select of cascade level3
if (cmd[1] == 0x70)
snprintf(exp, size, "SELECT_UID-3");
else if (cmd[1] == 0x20 || cmd[1] == 0x50)
snprintf(exp, size, "ANTICOLL-3");
else
snprintf(exp, size, "SELECT_XXX-3");
break;
}
case ISO14443A_CMD_REQA:
snprintf(exp, size, "REQA");
break;
case ISO14443A_CMD_READBLOCK:
snprintf(exp, size, "READBLOCK(%d)", cmd[1]);
break;
case ISO14443A_CMD_WRITEBLOCK:
snprintf(exp, size, "WRITEBLOCK(%d)", cmd[1]);
break;
case ISO14443A_CMD_HALT:
snprintf(exp, size, "HALT");
MifareAuthState = masNone;
break;
case ISO14443A_CMD_RATS:
snprintf(exp, size, "RATS");
break;
case ISO14443A_CMD_PPS:
snprintf(exp, size, "PPS");
break;
case ISO14443A_CMD_OPTS:
snprintf(exp, size, "OPTIONAL TIMESLOT");
break;
case MIFARE_CMD_INC:
snprintf(exp, size, "INC(%d)", cmd[1]);
break;
case MIFARE_CMD_DEC:
snprintf(exp, size, "DEC(%d)", cmd[1]);
break;
case MIFARE_CMD_RESTORE:
if (cmdsize == 4)
// cmd0 == 0xC2 and cmd1 == 0xFF
// high probability its SELECT SECTOR COMMAND:
if (cmd[1] == 0xFF) {
snprintf(exp, size, "SELECT SECTOR");
gs_ntag_i2c_state = 1;
} else {
snprintf(exp, size, "RESTORE(%d)", cmd[1]);
} else
return 0;
break;
case MIFARE_CMD_TRANSFER:
snprintf(exp, size, "TRANSFER(%d)", cmd[1]);
break;
case MIFARE_AUTH_KEYA: {
if (cmdsize > 3) {
snprintf(exp, size, "AUTH-A(%d)", cmd[1]);
MifareAuthState = masNt;
} else {
// case MIFARE_ULEV1_VERSION : both 0x60.
snprintf(exp, size, "EV1 VERSION");
} }
break; case ISO14443A_CMD_ANTICOLL_OR_SELECT_2: {
} //95 20 = Anticollision of cascade level2
case MIFARE_AUTH_KEYB: { //95 50 = Bit oriented anti-collision level2
MifareAuthState = masNt; //95 70 = Select of cascade level2
snprintf(exp, size, "AUTH-B(%d)", cmd[1]); if (cmd[1] == 0x70)
break; snprintf(exp, size, "SELECT_UID-2");
} else if (cmd[1] == 0x20 || cmd[1] == 0x50)
case MIFARE_MAGICWUPC1: snprintf(exp, size, "ANTICOLL-2");
snprintf(exp, size, "MAGIC WUPC1"); else
break; snprintf(exp, size, "SELECT_XXX-2");
case MIFARE_MAGICWUPC2: break;
snprintf(exp, size, "MAGIC WUPC2"); }
break; case ISO14443A_CMD_ANTICOLL_OR_SELECT_3: {
case MIFARE_MAGICWIPEC: //97 20 = Anticollision of cascade level3
snprintf(exp, size, "MAGIC WIPEC"); //97 50 = Bit oriented anti-collision level3
break; //97 70 = Select of cascade level3
case MIFARE_ULC_AUTH_1: if (cmd[1] == 0x70)
snprintf(exp, size, "AUTH "); snprintf(exp, size, "SELECT_UID-3");
break; else if (cmd[1] == 0x20 || cmd[1] == 0x50)
case MIFARE_ULC_AUTH_2: snprintf(exp, size, "ANTICOLL-3");
snprintf(exp, size, "AUTH_ANSW"); else
break; snprintf(exp, size, "SELECT_XXX-3");
case MIFARE_ULEV1_AUTH: break;
if (cmdsize == 7) }
snprintf(exp, size, "PWD-AUTH KEY: " _YELLOW_("0x%02x%02x%02x%02x"), cmd[1], cmd[2], cmd[3], cmd[4]); case ISO14443A_CMD_REQA:
else snprintf(exp, size, "REQA");
snprintf(exp, size, "PWD-AUTH"); break;
break; case ISO14443A_CMD_READBLOCK:
case MIFARE_ULEV1_FASTREAD : { snprintf(exp, size, "READBLOCK(%d)", cmd[1]);
if (cmdsize >= 3 && cmd[2] <= 0xE6) break;
snprintf(exp, size, "READ RANGE (%d-%d)", cmd[1], cmd[2]); case ISO14443A_CMD_WRITEBLOCK:
else
// outside limits, useful for some tags...
snprintf(exp, size, "READ RANGE (%d-%d) (?)", cmd[1], cmd[2]);
break;
}
case MIFARE_ULC_WRITE : {
if (cmd[1] < 0x21)
snprintf(exp, size, "WRITEBLOCK(%d)", cmd[1]); snprintf(exp, size, "WRITEBLOCK(%d)", cmd[1]);
else break;
// outside limits, useful for some tags... case ISO14443A_CMD_HALT:
snprintf(exp, size, "WRITEBLOCK(%d) (?)", cmd[1]); snprintf(exp, size, "HALT");
break; MifareAuthState = masNone;
} break;
case MIFARE_ULEV1_READ_CNT : { case ISO14443A_CMD_RATS:
if (cmd[1] < 5) snprintf(exp, size, "RATS");
snprintf(exp, size, "READ CNT(%d)", cmd[1]); break;
else case ISO14443A_CMD_PPS:
snprintf(exp, size, "?"); snprintf(exp, size, "PPS");
break; break;
} case ISO14443A_CMD_OPTS:
case MIFARE_ULEV1_INCR_CNT : { snprintf(exp, size, "OPTIONAL TIMESLOT");
if (cmd[1] < 5) break;
snprintf(exp, size, "INCR(%d)", cmd[1]); case MIFARE_CMD_INC:
else snprintf(exp, size, "INC(%d)", cmd[1]);
snprintf(exp, size, "?"); break;
break; case MIFARE_CMD_DEC:
} snprintf(exp, size, "DEC(%d)", cmd[1]);
case MIFARE_ULEV1_READSIG: break;
snprintf(exp, size, "READ SIG"); case MIFARE_CMD_RESTORE:
break;
case MIFARE_ULEV1_CHECKTEAR:
snprintf(exp, size, "CHK TEARING(%d)", cmd[1]);
break;
case MIFARE_ULEV1_VCSL:
snprintf(exp, size, "VCSL");
break;
case MIFARE_ULNANO_WRITESIG:
snprintf(exp, size, "WRITE SIG");
break;
case MIFARE_ULNANO_LOCKSIG: {
if (cmd[1] == 0)
snprintf(exp, size, "UNLOCK SIG");
else if (cmd[1] == 2)
snprintf(exp, size, "LOCK SIG");
else
snprintf(exp, size, "?");
break;
}
case NTAG_I2C_FASTWRITE:
if (cmdsize == 69)
snprintf(exp, size, "FAST WRITE (%d - %d)", cmd[1], cmd[2]);
else
snprintf(exp, size, "?");
break; if (cmdsize == 4)
default: // cmd0 == 0xC2 and cmd1 == 0xFF
return 0; // high probability its SELECT SECTOR COMMAND:
if (cmd[1] == 0xFF) {
snprintf(exp, size, "SELECT SECTOR");
gs_ntag_i2c_state = 1;
} else {
snprintf(exp, size, "RESTORE(%d)", cmd[1]);
} else
return 0;
break;
case MIFARE_CMD_TRANSFER:
snprintf(exp, size, "TRANSFER(%d)", cmd[1]);
break;
case MIFARE_AUTH_KEYA: {
if (cmdsize > 3) {
snprintf(exp, size, "AUTH-A(%d)", cmd[1]);
MifareAuthState = masNt;
} else {
// case MIFARE_ULEV1_VERSION : both 0x60.
snprintf(exp, size, "EV1 VERSION");
}
break;
}
case MIFARE_AUTH_KEYB: {
MifareAuthState = masNt;
snprintf(exp, size, "AUTH-B(%d)", cmd[1]);
break;
}
case MIFARE_MAGICWUPC1:
snprintf(exp, size, "MAGIC WUPC1");
break;
case MIFARE_MAGICWUPC2:
snprintf(exp, size, "MAGIC WUPC2");
break;
case MIFARE_MAGICWIPEC:
snprintf(exp, size, "MAGIC WIPEC");
break;
case MIFARE_ULC_AUTH_1:
gs_mfuc_state = 1;
snprintf(exp, size, "AUTH-1 ");
break;
case MIFARE_ULC_AUTH_2:
if ((gs_mfuc_state == 2) && (cmdsize==19)){
memcpy(gs_mfuc_authdata[1], &cmd[1], 16);
if (trace_mfuc_try_default_3des_keys(&gs_mfuc_key, gs_mfuc_state, gs_mfuc_authdata) == PM3_SUCCESS) {
// buffer too small to print the full key,
// so we give just a hint that one of the default keys was used
// snprintf(exp, size, "AUTH-2 KEY: " _YELLOW_("%s"), sprint_hex(gs_mfuc_key, 16));
snprintf(exp, size, "AUTH-2 KEY: " _YELLOW_("%02x%02x%02x%02x..."), gs_mfuc_key[0], gs_mfuc_key[1], gs_mfuc_key[2], gs_mfuc_key[3]);
} else {
snprintf(exp, size, "AUTH-2");
}
gs_mfuc_state = 3;
} else {
return 0;
}
break;
case MIFARE_ULEV1_AUTH:
if (cmdsize == 7)
snprintf(exp, size, "PWD-AUTH KEY: " _YELLOW_("0x%02x%02x%02x%02x"), cmd[1], cmd[2], cmd[3], cmd[4]);
else
snprintf(exp, size, "PWD-AUTH");
break;
case MIFARE_ULEV1_FASTREAD : {
if (cmdsize >= 3 && cmd[2] <= 0xE6)
snprintf(exp, size, "READ RANGE (%d-%d)", cmd[1], cmd[2]);
else
// outside limits, useful for some tags...
snprintf(exp, size, "READ RANGE (%d-%d) (?)", cmd[1], cmd[2]);
break;
}
case MIFARE_ULC_WRITE : {
if (cmd[1] < 0x21)
snprintf(exp, size, "WRITEBLOCK(%d)", cmd[1]);
else
// outside limits, useful for some tags...
snprintf(exp, size, "WRITEBLOCK(%d) (?)", cmd[1]);
break;
}
case MIFARE_ULEV1_READ_CNT : {
if (cmd[1] < 5)
snprintf(exp, size, "READ CNT(%d)", cmd[1]);
else
snprintf(exp, size, "?");
break;
}
case MIFARE_ULEV1_INCR_CNT : {
if (cmd[1] < 5)
snprintf(exp, size, "INCR(%d)", cmd[1]);
else
snprintf(exp, size, "?");
break;
}
case MIFARE_ULEV1_READSIG:
snprintf(exp, size, "READ SIG");
break;
case MIFARE_ULEV1_CHECKTEAR:
snprintf(exp, size, "CHK TEARING(%d)", cmd[1]);
break;
case MIFARE_ULEV1_VCSL:
snprintf(exp, size, "VCSL");
break;
case MIFARE_ULNANO_WRITESIG:
snprintf(exp, size, "WRITE SIG");
break;
case MIFARE_ULNANO_LOCKSIG: {
if (cmd[1] == 0)
snprintf(exp, size, "UNLOCK SIG");
else if (cmd[1] == 2)
snprintf(exp, size, "LOCK SIG");
else
snprintf(exp, size, "?");
break;
}
case NTAG_I2C_FASTWRITE:
if (cmdsize == 69)
snprintf(exp, size, "FAST WRITE (%d - %d)", cmd[1], cmd[2]);
else
snprintf(exp, size, "?");
break;
default:
return 0;
}
} else {
if (gs_mfuc_state==1) {
if ((cmd[0]==0xAF) && (cmdsize==11)) {
// register RndB
memcpy(gs_mfuc_authdata[0], &cmd[1], 8);
gs_mfuc_state=2;
} else {
gs_mfuc_state=0;
}
}
if (gs_mfuc_state==3) {
if ((cmd[0]==0x00) && (cmdsize==11)) {
// register RndA'
memcpy(gs_mfuc_authdata[2], &cmd[1], 8);
if (trace_mfuc_try_default_3des_keys(&gs_mfuc_key, gs_mfuc_state, gs_mfuc_authdata) == PM3_SUCCESS) {
snprintf(exp, size, "AUTH-2 ANSW OK");
gs_mfuc_state=0;
return 1;
}
}
gs_mfuc_state=0;
}
return 0;
} }
return 1; return 1;
} }
void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response) {
applyIso14443a(exp, size, cmd, cmdsize); applyIso14443a(exp, size, cmd, cmdsize, is_response);
} }
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool isResponse) { void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool isResponse) {
@ -770,7 +811,7 @@ void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
// it's basically a ISO14443a tag, so try annotation from there // it's basically a ISO14443a tag, so try annotation from there
if (applyIso14443a(exp, size, cmd, cmdsize) == 0) { if (applyIso14443a(exp, size, cmd, cmdsize, false) == 0) {
// S-block 11xxx010 // S-block 11xxx010
if ((cmd[0] & 0xC0) && (cmdsize == 3)) { if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
@ -1428,8 +1469,8 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8
break; break;
} }
if (!isResponse && ((MifareAuthState == masNone) || (MifareAuthState == masError))) if ((MifareAuthState == masNone) || (MifareAuthState == masError))
annotateIso14443a(exp, size, cmd, cmdsize); annotateIso14443a(exp, size, cmd, cmdsize, isResponse);
} }

View file

@ -37,7 +37,7 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len);
uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n); uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n);
uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n); uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response);
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool isResponse); void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool isResponse);
void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
@ -46,7 +46,7 @@ void annotateLegic(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response);
void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse); void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse);
void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);

View file

@ -255,6 +255,65 @@ static int ulc_authentication(uint8_t *key, bool switch_off_field) {
return 0; return 0;
} }
static int trace_mfuc_try_key(uint8_t *key, int state, uint8_t (*authdata)[16]) {
uint8_t iv[8] = {0};
uint8_t RndB[8] = {0};
uint8_t RndARndB[16] = {0};
uint8_t RndA[8] = {0};
mbedtls_des3_context ctx_des3;
switch (state) {
case 2:
mbedtls_des3_set2key_dec(&ctx_des3, key);
mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
8, iv, authdata[0], RndB);
mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
16, iv, authdata[1], RndARndB);
if ((memcmp(&RndB[1], &RndARndB[8], 7) == 0) &&
(RndB[0] == RndARndB[15])) {
return PM3_SUCCESS;
}
break;
case 3:
if (key == NULL) {// if no key was found
return PM3_ESOFT;
}
memcpy(iv, authdata[0], 8);
mbedtls_des3_set2key_dec(&ctx_des3, key);
mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
16, iv, authdata[1], RndARndB);
mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
8, iv, authdata[2], RndA);
if ((memcmp(&RndARndB[1], RndA, 7) == 0) &&
(RndARndB[0] == RndA[7])) {
return PM3_SUCCESS;
}
break;
default:
return PM3_EINVARG;
}
return PM3_ESOFT;
}
int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (*authdata)[16]) {
switch (state) {
case 2:
for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
uint8_t *key = default_3des_keys[i];
if (trace_mfuc_try_key(key, state, authdata) == PM3_SUCCESS) {
*correct_key = key;
return PM3_SUCCESS;
}
}
break;
case 3:
return trace_mfuc_try_key(*correct_key, state, authdata);
break;
default:
return PM3_EINVARG;
}
return PM3_ESOFT;
}
static int try_default_3des_keys(uint8_t **correct_key) { static int try_default_3des_keys(uint8_t **correct_key) {
PrintAndLogEx(INFO, "Trying some default 3des keys"); PrintAndLogEx(INFO, "Trying some default 3des keys");
for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) { for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {

View file

@ -24,6 +24,7 @@ uint32_t GetHF14AMfU_Type(void);
int ul_print_type(uint32_t tagtype, uint8_t spaces); int ul_print_type(uint32_t tagtype, uint8_t spaces);
void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage); void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage);
int ul_read_uid(uint8_t *uid); int ul_read_uid(uint8_t *uid);
int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (*authdata)[16]);
int CmdHFMFUltra(const char *Cmd); int CmdHFMFUltra(const char *Cmd);
int CmdHF14MfuNDEFRead(const char *Cmd); int CmdHF14MfuNDEFRead(const char *Cmd);

View file

@ -334,6 +334,10 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
// Always annotate these protocols both reader/tag messages // Always annotate these protocols both reader/tag messages
switch (protocol) { switch (protocol) {
case ISO_14443A:
case ISO_7816_4:
annotateIso14443a(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
break;
case PROTO_MIFARE: case PROTO_MIFARE:
annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, TRACELOG_PARITY_LEN(hdr), hdr->isResponse); annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, TRACELOG_PARITY_LEN(hdr), hdr->isResponse);
break; break;
@ -359,9 +363,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
case LEGIC: case LEGIC:
annotateLegic(explanation, sizeof(explanation), frame, data_len); annotateLegic(explanation, sizeof(explanation), frame, data_len);
break; break;
case ISO_14443A:
annotateIso14443a(explanation, sizeof(explanation), frame, data_len);
break;
case MFDES: case MFDES:
annotateMfDesfire(explanation, sizeof(explanation), frame, data_len); annotateMfDesfire(explanation, sizeof(explanation), frame, data_len);
break; break;
@ -372,7 +373,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
annotateTopaz(explanation, sizeof(explanation), frame, data_len); annotateTopaz(explanation, sizeof(explanation), frame, data_len);
break; break;
case ISO_7816_4: case ISO_7816_4:
annotateIso14443a(explanation, sizeof(explanation), frame, data_len);
annotateIso7816(explanation, sizeof(explanation), frame, data_len); annotateIso7816(explanation, sizeof(explanation), frame, data_len);
break; break;
case ISO_15693: case ISO_15693:
@ -466,9 +466,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
if (protocol == PROTO_MIFARE) { if (protocol == PROTO_MIFARE) {
if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen, mfDicKeys, mfDicKeysCount)) { if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen, mfDicKeys, mfDicKeysCount)) {
memset(explanation, 0x00, sizeof(explanation)); memset(explanation, 0x00, sizeof(explanation));
if (hdr->isResponse == false) { annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen, hdr->isResponse);
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen);
}
uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen); uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
PrintAndLogEx(NORMAL, " | | * |%-72s | %-4s| %s", PrintAndLogEx(NORMAL, " | | * |%-72s | %-4s| %s",
sprint_hex_inrow_spaces(mfData, mfDataLen, 2), sprint_hex_inrow_spaces(mfData, mfDataLen, 2),