improved FUDAN identification and anti-collision select based on @lsylx issue #1599

This commit is contained in:
iceman1001 2022-04-30 18:39:14 +02:00
commit dd20083126
2 changed files with 80 additions and 6 deletions

View file

@ -2512,7 +2512,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
p_card->ats_len = 0; p_card->ats_len = 0;
} }
if (!GetATQA(resp, resp_par, use_ecp, use_magsafe)) { if (GetATQA(resp, resp_par, use_ecp, use_magsafe) == false) {
return 0; return 0;
} }
@ -2521,6 +2521,29 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
p_card->atqa[1] = resp[1]; p_card->atqa[1] = resp[1];
} }
// 11RF005SH or 11RF005M, Read UID again
if (p_card && p_card->atqa[1] == 0x00 ) {
if ((p_card->atqa[0]==0x03) || (p_card->atqa[0]==0x05)) {
// Read real UID
uint8_t fudan_read[] = { 0x30, 0x01, 0x02, 0xA8};
ReaderTransmit(fudan_read, sizeof(fudan_read), NULL);
ReaderReceive(resp, resp_par);
memcpy(p_card->uid, resp, 4);
// select again?
if (GetATQA(resp, resp_par, false, false) == false) {
return 0;
}
p_card->sak = 0x0A;
p_card->uidlen = 4;
return 1;
}
}
if (anticollision) { if (anticollision) {
// clear uid // clear uid
if (uid_ptr) if (uid_ptr)

View file

@ -1470,7 +1470,9 @@ typedef enum {
MTPLUS = 8, MTPLUS = 8,
MTULTRALIGHT = 16, MTULTRALIGHT = 16,
HID_SEOS = 32, HID_SEOS = 32,
MTOTHER = 64 MTOTHER = 64,
MTEMV = 128,
MTFUDAN = 256,
} nxp_mifare_type_t; } nxp_mifare_type_t;
// Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1 // Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
@ -1577,6 +1579,9 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status) {
if ((atqa & 0x0001) == 0x0001) { if ((atqa & 0x0001) == 0x0001) {
printTag("HID SEOS (smartmx / javacard)"); printTag("HID SEOS (smartmx / javacard)");
type |= HID_SEOS; type |= HID_SEOS;
} else if ((atqa & 0x0004) == 0x0004) {
printTag("EMV");
type |= MTEMV;
} else { } else {
printTag("MIFARE Plus EV1 2K/4K in SL3"); printTag("MIFARE Plus EV1 2K/4K in SL3");
printTag("MIFARE Plus S 2K/4K in SL3"); printTag("MIFARE Plus S 2K/4K in SL3");
@ -1592,6 +1597,20 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status) {
} else if ((sak & 0x04) == 0x04) { } else if ((sak & 0x04) == 0x04) {
printTag("Any MIFARE CL1"); printTag("Any MIFARE CL1");
type |= MTDESFIRE; type |= MTDESFIRE;
} else if ((sak & 0x0A) == 0x0A) {
if ((atqa & 0x0003) == 0x0003) {
// Uses Shanghai algo
printTag("FM11RF005SH (FUDAN Shanghai Metro)");
type |= MTFUDAN;
} else if ((atqa & 0x0005) == 0x0005) {
printTag("FM11RF005M (FUDAN MIFARE Classic clone)");
type |= MTFUDAN;
}
}
else if ((sak & 0x53) == 0x53) {
printTag("FM11RF08SH (FUDAN)");
type |= MTFUDAN;
} else { } else {
printTag("MIFARE Ultralight"); printTag("MIFARE Ultralight");
printTag("MIFARE Ultralight C"); printTag("MIFARE Ultralight C");
@ -1760,6 +1779,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
bool isMifareUltralight = false; bool isMifareUltralight = false;
bool isST = false; bool isST = false;
bool isEMV = false; bool isEMV = false;
bool isFUDAN = false;
int nxptype = MTNONE; int nxptype = MTNONE;
if (card.uidlen <= 4) { if (card.uidlen <= 4) {
@ -1773,6 +1793,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if ((nxptype & MTOTHER) == MTOTHER) if ((nxptype & MTOTHER) == MTOTHER)
isMifareClassic = true; isMifareClassic = true;
if ((nxptype & MTFUDAN) == MTFUDAN)
isFUDAN = true;
if ((nxptype & MTEMV) == MTEMV)
isEMV = true;
} else { } else {
// Double & triple sized UID, can be mapped to a manufacturer. // Double & triple sized UID, can be mapped to a manufacturer.
@ -1793,6 +1819,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if ((nxptype & MTOTHER) == MTOTHER) if ((nxptype & MTOTHER) == MTOTHER)
isMifareClassic = true; isMifareClassic = true;
if ((nxptype & MTFUDAN) == MTFUDAN)
isFUDAN = true;
if ((nxptype & MTEMV) == MTEMV)
isEMV = true;
break; break;
case 0x05: // Infineon case 0x05: // Infineon
if ((card.uid[1] & 0xF0) == 0x10) { if ((card.uid[1] & 0xF0) == 0x10) {
@ -1860,12 +1892,14 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
break; break;
} }
case 0x0A: { case 0x0A: {
if (card.atqa[0] == 0x03) if (card.atqa[0] == 0x03) {
// Uses MIFARE Crypto-1 algo
printTag("FM11RF005M (FUDAN MIFARE Classic clone)");
else if (card.atqa[0] == 0x05)
// Uses Shanghai algo // Uses Shanghai algo
printTag("FM11RF005SH (FUDAN Shanghai Metro)"); printTag("FM11RF005SH (FUDAN Shanghai Metro)");
} else if (card.atqa[0] == 0x05) {
// Uses MIFARE Crypto-1 algo
printTag("FM11RF005M (FUDAN MIFARE Classic clone)");
}
break; break;
} }
case 0x20: { case 0x20: {
@ -1880,6 +1914,10 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
printTag("Nokia 6212 or 6131"); printTag("Nokia 6212 or 6131");
break; break;
} }
case 0x53: {
printTag("FM11RF08SH (FUDAN)");
break;
}
case 0x98: { case 0x98: {
printTag("Gemplus MPCOS"); printTag("Gemplus MPCOS");
break; break;
@ -2259,6 +2297,19 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
if (isEMV) if (isEMV)
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`emv search -s`")); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`emv search -s`"));
if (isFUDAN) {
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf 14a raw`") " - since FUDAN is different");
PrintAndLogEx(HINT, " hf 14a raw -a -b 7 -p 26");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3000");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3001");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3002");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3003");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3004");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3005");
PrintAndLogEx(HINT, " hf 14a raw -p -c 3006");
PrintAndLogEx(HINT, " hf 14a raw -c 3007");
}
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
DropField(); DropField();
return select_status; return select_status;