mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
only print uid types in 14a info, and skip decoding of bad ATS
This commit is contained in:
parent
3efe3d9f85
commit
ed60d26808
2 changed files with 206 additions and 190 deletions
|
@ -419,30 +419,38 @@ static int CmdHf14AConfig(const char *Cmd) {
|
||||||
return hf14a_setconfig(&config, verbose);
|
return hf14a_setconfig(&config, verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintUidType(iso14a_card_select_t *card) {
|
static const char* get_uid_type(iso14a_card_select_t *card) {
|
||||||
|
|
||||||
|
static char s[60] = {0};
|
||||||
|
memset(s, 0, sizeof(s));
|
||||||
|
|
||||||
switch (card->uidlen) {
|
switch (card->uidlen) {
|
||||||
case 4:
|
case 4: {
|
||||||
if (card->uid[0] == 0x08) {
|
if (card->uid[0] == 0x08) {
|
||||||
PrintAndLogEx(SUCCESS, " UID type: " _GREEN_("RID") " (random ID)");
|
sprintf(s, " ( RID - random ID )");
|
||||||
} else if ((card->uid[0] & 0xF) == 0xF) {
|
} else if ((card->uid[0] & 0xF) == 0xF) {
|
||||||
PrintAndLogEx(SUCCESS, " UID type: " _GREEN_("FNUID") " (fixed but non-unique ID)");
|
sprintf(s, " ( FNUID, fixed, non-unique ID )");
|
||||||
} else if (card->uid[0] == 0x88) {
|
} else if (card->uid[0] == 0x88) {
|
||||||
PrintAndLogEx(WARNING, " UID type: " _YELLOW_("Cascade tag") " (not final UID)");
|
sprintf(s, " ( Cascade tag - not final )");
|
||||||
} else if (card->uid[0] == 0xF8) {
|
} else if (card->uid[0] == 0xF8) {
|
||||||
PrintAndLogEx(WARNING, " UID type: " _YELLOW_("RFU"));
|
sprintf(s, " ( RFU )");
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, " UID type: " _GREEN_("ONUID") " (re-used UID)");
|
sprintf(s, " ( ONUID, re-used )");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
}
|
||||||
PrintAndLogEx(SUCCESS, " UID type: " _GREEN_("Double Size UID"));
|
case 7: {
|
||||||
|
sprintf(s, " ( double )");
|
||||||
break;
|
break;
|
||||||
case 10:
|
}
|
||||||
PrintAndLogEx(SUCCESS, " UID type: " _GREEN_("Triple Size UID"));
|
case 10: {
|
||||||
|
sprintf(s, " ( triple )");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(ERR, " UID type: " _RED_("wrong UID length"));
|
break;
|
||||||
}
|
}
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
||||||
|
@ -476,7 +484,6 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card->uid, card->uidlen));
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card->uid, card->uidlen));
|
||||||
PrintUidType(card);
|
|
||||||
PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card->atqa[1], card->atqa[0]);
|
PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card->atqa[1], card->atqa[0]);
|
||||||
PrintAndLogEx(SUCCESS, " SAK: %02X [%" PRIu64 "]", card->sak, resp.oldarg[0]);
|
PrintAndLogEx(SUCCESS, " SAK: %02X [%" PRIu64 "]", card->sak, resp.oldarg[0]);
|
||||||
|
|
||||||
|
@ -643,7 +650,6 @@ static int CmdHF14AReader(const char *Cmd) {
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||||
|
|
||||||
if (!(silent && continuous)) {
|
if (!(silent && continuous)) {
|
||||||
PrintUidType(&card);
|
|
||||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
||||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||||
|
|
||||||
|
@ -2081,8 +2087,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " %s", sprint_hex(card.uid, card.uidlen), get_uid_type(&card));
|
||||||
PrintUidType(&card);
|
|
||||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
||||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||||
|
|
||||||
|
@ -2272,211 +2277,217 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--");
|
PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bad_ats = false;
|
||||||
if (card.ats[0] != card.ats_len - 2) {
|
if (card.ats[0] != card.ats_len - 2) {
|
||||||
PrintAndLogEx(WARNING, _RED_("ATS may be corrupted."));
|
PrintAndLogEx(WARNING, _RED_("ATS may be corrupted."));
|
||||||
PrintAndLogEx(INFO, "Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
|
PrintAndLogEx(INFO, "Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
|
||||||
|
bad_ats = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "ATS: " _YELLOW_("%s")"[ %02X %02X ]", sprint_hex(card.ats, card.ats_len - 2), card.ats[card.ats_len - 2], card.ats[card.ats_len - 1]);
|
PrintAndLogEx(SUCCESS, "ATS: " _YELLOW_("%s")"[ %02X %02X ]", sprint_hex(card.ats, card.ats_len - 2), card.ats[card.ats_len - 2], card.ats[card.ats_len - 1]);
|
||||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]);
|
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]);
|
||||||
|
|
||||||
if ((card.ats[0] > 1) && (card.ats_len > 3)) { // there is a format byte (T0)
|
if (bad_ats == false) {
|
||||||
ta1 = (card.ats[1] & 0x10) == 0x10;
|
|
||||||
tb1 = (card.ats[1] & 0x20) == 0x20;
|
|
||||||
tc1 = (card.ats[1] & 0x40) == 0x40;
|
|
||||||
int16_t fsci = card.ats[1] & 0x0f;
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
|
if ((card.ats[0] > 1) && (card.ats_len > 3)) { // there is a format byte (T0)
|
||||||
"TC1 is%s present, FSCI is %d (FSC = %d)",
|
ta1 = (card.ats[1] & 0x10) == 0x10;
|
||||||
card.ats[1],
|
tb1 = (card.ats[1] & 0x20) == 0x20;
|
||||||
(ta1 ? "" : _RED_(" NOT")),
|
tc1 = (card.ats[1] & 0x40) == 0x40;
|
||||||
(tb1 ? "" : _RED_(" NOT")),
|
int16_t fsci = card.ats[1] & 0x0f;
|
||||||
(tc1 ? "" : _RED_(" NOT")),
|
|
||||||
fsci,
|
|
||||||
fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
int pos = 2;
|
|
||||||
if (ta1 && (card.ats_len > pos + 2)) {
|
|
||||||
char dr[16], ds[16];
|
|
||||||
dr[0] = ds[0] = '\0';
|
|
||||||
if (card.ats[pos] & 0x10) strcat(ds, "2, ");
|
|
||||||
if (card.ats[pos] & 0x20) strcat(ds, "4, ");
|
|
||||||
if (card.ats[pos] & 0x40) strcat(ds, "8, ");
|
|
||||||
if (card.ats[pos] & 0x01) strcat(dr, "2, ");
|
|
||||||
if (card.ats[pos] & 0x02) strcat(dr, "4, ");
|
|
||||||
if (card.ats[pos] & 0x04) strcat(dr, "8, ");
|
|
||||||
if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
|
|
||||||
if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
|
|
||||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
|
|
||||||
"DR: [%s], DS: [%s]",
|
|
||||||
card.ats[pos],
|
|
||||||
((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""),
|
|
||||||
dr,
|
|
||||||
ds
|
|
||||||
);
|
|
||||||
|
|
||||||
pos++;
|
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
|
||||||
}
|
"TC1 is%s present, FSCI is %d (FSC = %d)",
|
||||||
|
card.ats[1],
|
||||||
|
(ta1 ? "" : _RED_(" NOT")),
|
||||||
|
(tb1 ? "" : _RED_(" NOT")),
|
||||||
|
(tc1 ? "" : _RED_(" NOT")),
|
||||||
|
fsci,
|
||||||
|
fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int pos = 2;
|
||||||
|
if (ta1 && (card.ats_len > pos + 2)) {
|
||||||
|
char dr[16], ds[16];
|
||||||
|
dr[0] = ds[0] = '\0';
|
||||||
|
if (card.ats[pos] & 0x10) strcat(ds, "2, ");
|
||||||
|
if (card.ats[pos] & 0x20) strcat(ds, "4, ");
|
||||||
|
if (card.ats[pos] & 0x40) strcat(ds, "8, ");
|
||||||
|
if (card.ats[pos] & 0x01) strcat(dr, "2, ");
|
||||||
|
if (card.ats[pos] & 0x02) strcat(dr, "4, ");
|
||||||
|
if (card.ats[pos] & 0x04) strcat(dr, "8, ");
|
||||||
|
if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
|
||||||
|
if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
|
||||||
|
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
|
||||||
|
"DR: [%s], DS: [%s]",
|
||||||
|
card.ats[pos],
|
||||||
|
((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""),
|
||||||
|
dr,
|
||||||
|
ds
|
||||||
|
);
|
||||||
|
|
||||||
if (tb1 && (card.ats_len > pos + 2)) {
|
pos++;
|
||||||
uint32_t sfgi = card.ats[pos] & 0x0F;
|
}
|
||||||
uint32_t fwi = card.ats[pos] >> 4;
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
|
if (tb1 && (card.ats_len > pos + 2)) {
|
||||||
card.ats[pos],
|
uint32_t sfgi = card.ats[pos] & 0x0F;
|
||||||
(sfgi),
|
uint32_t fwi = card.ats[pos] >> 4;
|
||||||
sfgi ? "" : "(not needed) ",
|
|
||||||
sfgi ? (1 << 12) << sfgi : 0,
|
|
||||||
fwi,
|
|
||||||
(1 << 12) << fwi
|
|
||||||
);
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tc1 && (card.ats_len > pos + 2)) {
|
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
|
||||||
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
|
card.ats[pos],
|
||||||
card.ats[pos],
|
(sfgi),
|
||||||
(card.ats[pos] & 0x01) ? "" : _RED_(" NOT"),
|
sfgi ? "" : "(not needed) ",
|
||||||
(card.ats[pos] & 0x02) ? "" : _RED_(" NOT")
|
sfgi ? (1 << 12) << sfgi : 0,
|
||||||
);
|
fwi,
|
||||||
pos++;
|
(1 << 12) << fwi
|
||||||
}
|
);
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
// ATS - Historial bytes and identify based on it
|
if (tc1 && (card.ats_len > pos + 2)) {
|
||||||
if ((card.ats[0] > pos) && (card.ats_len >= card.ats[0] + 2)) {
|
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
|
||||||
char tip[60];
|
card.ats[pos],
|
||||||
tip[0] = '\0';
|
(card.ats[pos] & 0x01) ? "" : _RED_(" NOT"),
|
||||||
if (card.ats[0] - pos >= 7) {
|
(card.ats[pos] & 0x02) ? "" : _RED_(" NOT")
|
||||||
|
);
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tip, sizeof(tip), " ");
|
// ATS - Historial bytes and identify based on it
|
||||||
|
if ((card.ats[0] > pos) && (card.ats_len >= card.ats[0] + 2)) {
|
||||||
|
char tip[60];
|
||||||
|
tip[0] = '\0';
|
||||||
|
if (card.ats[0] - pos >= 7) {
|
||||||
|
|
||||||
if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
|
snprintf(tip, sizeof(tip), " ");
|
||||||
|
|
||||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
|
|
||||||
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
|
||||||
|
|
||||||
if ((card.atqa[0] & 0x02) == 0x02) {
|
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
|
|
||||||
} else if ((card.atqa[0] & 0x04) == 0x04) {
|
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
|
|
||||||
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { //SAK B4,5,6
|
|
||||||
|
|
||||||
if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
|
|
||||||
|
|
||||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
|
||||||
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
|
|
||||||
|
if ((card.atqa[0] & 0x02) == 0x02) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
|
||||||
|
} else if ((card.atqa[0] & 0x04) == 0x04) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
|
||||||
|
}
|
||||||
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
|
||||||
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
} else { //SAK B4,5,6
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
|
|
||||||
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
|
||||||
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
|
|
||||||
|
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
|
||||||
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
|
||||||
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
|
||||||
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
|
||||||
|
} else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
|
||||||
|
snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t calen = card.ats[0] - pos;
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------");
|
|
||||||
|
|
||||||
if (card.ats[pos] == 0xC1) {
|
|
||||||
PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip);
|
|
||||||
PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type");
|
|
||||||
PrintAndLogEx(SUCCESS, " %02X.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]);
|
|
||||||
switch (card.ats[pos + 2] & 0xf0) {
|
|
||||||
case 0x10:
|
|
||||||
PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire");
|
|
||||||
isMifareDESFire = true;
|
|
||||||
isMifareClassic = false;
|
|
||||||
isMifarePlus = false;
|
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus");
|
|
||||||
isMifarePlus = true;
|
|
||||||
isMifareDESFire = false;
|
|
||||||
isMifareClassic = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (card.ats[pos + 2] & 0x0f) {
|
|
||||||
case 0x00:
|
|
||||||
PrintAndLogEx(SUCCESS, " x0............... < 1 kByte");
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
PrintAndLogEx(SUCCESS, " x1............... 1 kByte");
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
PrintAndLogEx(SUCCESS, " x2............... 2 kByte");
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
PrintAndLogEx(SUCCESS, " x3............... 4 kByte");
|
|
||||||
break;
|
|
||||||
case 0x04:
|
|
||||||
PrintAndLogEx(SUCCESS, " x4............... 8 kByte");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (card.ats[pos + 3] & 0xf0) {
|
|
||||||
case 0x00:
|
|
||||||
PrintAndLogEx(SUCCESS, " 0x............ Engineering sample");
|
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
PrintAndLogEx(SUCCESS, " 2x............ Released");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (card.ats[pos + 3] & 0x0f) {
|
|
||||||
case 0x00:
|
|
||||||
PrintAndLogEx(SUCCESS, " x0............ Generation 1");
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
PrintAndLogEx(SUCCESS, " x1............ Generation 2");
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
PrintAndLogEx(SUCCESS, " x2............ Generation 3");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (card.ats[pos + 4] & 0x0f) {
|
|
||||||
case 0x00:
|
|
||||||
PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported");
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported");
|
|
||||||
break;
|
|
||||||
case 0x0E:
|
|
||||||
PrintAndLogEx(SUCCESS, " xE......... no VCS command supported");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (card.ats[pos] == 0x80 || card.ats[pos] == 0x00) {
|
|
||||||
PrintAndLogEx(SUCCESS, "%s (compact TLV data object)", sprint_hex_inrow(&card.ats[pos], calen));
|
|
||||||
get_compact_tlv(card.ats + pos, calen);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(SUCCESS, "%s - %s"
|
|
||||||
, sprint_hex_inrow(card.ats + pos, calen)
|
|
||||||
, sprint_ascii(card.ats + pos, calen)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
uint8_t calen = card.ats[0] - pos;
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------");
|
||||||
|
|
||||||
|
if (card.ats[pos] == 0xC1) {
|
||||||
|
PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip);
|
||||||
|
PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type");
|
||||||
|
PrintAndLogEx(SUCCESS, " %02X.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]);
|
||||||
|
switch (card.ats[pos + 2] & 0xf0) {
|
||||||
|
case 0x10:
|
||||||
|
PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire");
|
||||||
|
isMifareDESFire = true;
|
||||||
|
isMifareClassic = false;
|
||||||
|
isMifarePlus = false;
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus");
|
||||||
|
isMifarePlus = true;
|
||||||
|
isMifareDESFire = false;
|
||||||
|
isMifareClassic = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (card.ats[pos + 2] & 0x0f) {
|
||||||
|
case 0x00:
|
||||||
|
PrintAndLogEx(SUCCESS, " x0............... < 1 kByte");
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
PrintAndLogEx(SUCCESS, " x1............... 1 kByte");
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
PrintAndLogEx(SUCCESS, " x2............... 2 kByte");
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
PrintAndLogEx(SUCCESS, " x3............... 4 kByte");
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
PrintAndLogEx(SUCCESS, " x4............... 8 kByte");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (card.ats[pos + 3] & 0xf0) {
|
||||||
|
case 0x00:
|
||||||
|
PrintAndLogEx(SUCCESS, " 0x............ Engineering sample");
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
PrintAndLogEx(SUCCESS, " 2x............ Released");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (card.ats[pos + 3] & 0x0f) {
|
||||||
|
case 0x00:
|
||||||
|
PrintAndLogEx(SUCCESS, " x0............ Generation 1");
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
PrintAndLogEx(SUCCESS, " x1............ Generation 2");
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
PrintAndLogEx(SUCCESS, " x2............ Generation 3");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (card.ats[pos + 4] & 0x0f) {
|
||||||
|
case 0x00:
|
||||||
|
PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported");
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported");
|
||||||
|
break;
|
||||||
|
case 0x0E:
|
||||||
|
PrintAndLogEx(SUCCESS, " xE......... no VCS command supported");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (card.ats[pos] == 0x80 || card.ats[pos] == 0x00) {
|
||||||
|
PrintAndLogEx(SUCCESS, "%s (compact TLV data object)", sprint_hex_inrow(&card.ats[pos], calen));
|
||||||
|
get_compact_tlv(card.ats + pos, calen);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(SUCCESS, "%s - %s"
|
||||||
|
, sprint_hex_inrow(card.ats + pos, calen)
|
||||||
|
, sprint_ascii(card.ats + pos, calen)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_aid_search) {
|
if (do_aid_search) {
|
||||||
|
@ -2558,6 +2569,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
PrintAndLogEx(INFO, "----------------------------------------------------");
|
PrintAndLogEx(INFO, "----------------------------------------------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (isISO18092) {
|
if (isISO18092) {
|
||||||
|
|
|
@ -1507,6 +1507,10 @@ uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) {
|
||||||
isMagic = MemLeToUint2byte(resp.data.asBytes);
|
isMagic = MemLeToUint2byte(resp.data.asBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isMagic) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
}
|
||||||
|
|
||||||
if ((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) {
|
if ((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) {
|
||||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1a"));
|
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1a"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue