diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a962108..89033d969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Changed the magic card detection. It now acts as flags (@iceman1001) - Added `hf ict` - skeleton commands in preperation (@iceman1001) - Added `lf hitag eview` - now supports viewing of emulator memory (@iceman1001) - Added `lf hitag view` - now supports viewing of dump files (@iceman1001) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index c3738ec2e..1fb89404a 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2457,8 +2457,8 @@ static void mf_reset_card(void) { void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { // variables - uint8_t rec[MAX_MIFARE_PARITY_SIZE] = {0x00}; - uint8_t recpar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t rec[1] = {0x00}; + uint8_t recpar[1] = {0x00}; uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73}; uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f}; uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8}; @@ -2467,39 +2467,36 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0}; uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D}; bool isGen2 = false; - bool isGen1AGdm = false; uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE); uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE); uint8_t *uid = BigBuf_calloc(10); - uint8_t *data = BigBuf_calloc(16); - + uint16_t flag = MAGIC_FLAG_NONE; uint32_t cuid = 0; - size_t data_off = 0; + int res = 0; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); // Generation 1 test ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) { - uint8_t isGen = MAGIC_GEN_1A; + if (ReaderReceive(rec, recpar) && (rec[0] == 0x0A)) { + flag = MAGIC_FLAG_GEN_1A; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if (!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { - isGen = MAGIC_GEN_1B; - }; - data[data_off++] = isGen; + if (ReaderReceive(rec, recpar) && (rec[0] != 0x0A)) { + flag = MAGIC_FLAG_GEN_1B; + } // check for GDM config ReaderTransmit(gen4gdmGetConf, sizeof(gen4gdmGetConf), NULL); - int res = ReaderReceive(buf, par); + res = ReaderReceive(buf, par); if (res > 1) { - isGen1AGdm = true; + flag |= MAGIC_FLAG_GDM_WUP_40; } } mf_reset_card(); - int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); + res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if (res) { // Check for Magic Gen4 GTU with default password: // Get config should return 30 or 32 bytes @@ -2507,7 +2504,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { ReaderTransmit(gen4GetConf, sizeof(gen4GetConf), NULL); res = ReaderReceive(buf, par); if (res == 32 || res == 34) { - data[data_off++] = MAGIC_GEN_4GTU; + flag |= MAGIC_FLAG_GEN_4GTU; } } @@ -2517,7 +2514,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { res = iso14443a_select_card(uid, NULL, &cuid, true, 0, false); if (res) { if (cuid == 0xAA55C396) { - data[data_off++] = MAGIC_GEN_UNFUSED; + flag |= MAGIC_FLAG_GEN_UNFUSED; } ReaderTransmit(rats, sizeof(rats), NULL); @@ -2527,38 +2524,38 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) { // test for some MFC gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } else if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) { // test for some MFC 7b gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } else if (memcmp(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) { // test for Ultralight magic gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) { // test for Ultralight EV1 magic gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) { // test for some other Ultralight EV1 magic gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) { // test for some other Ultralight magic gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) { // test for NTAG213 magic gen2 isGen2 = true; - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; } // test for super card ReaderTransmit(superGen1, sizeof(superGen1), NULL); res = ReaderReceive(buf, par); if (res == 22) { - uint8_t isGen = MAGIC_SUPER_GEN1; + uint8_t isGen = MAGIC_FLAG_SUPER_GEN1; // check for super card gen2 // not available after RATS, reset card before executing @@ -2568,10 +2565,10 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { ReaderTransmit(rdbl00, sizeof(rdbl00), NULL); res = ReaderReceive(buf, par); if (res == 18) { - isGen = MAGIC_SUPER_GEN2; + isGen = MAGIC_FLAG_SUPER_GEN2; } - data[data_off++] = isGen; + flag |= isGen; } } @@ -2584,7 +2581,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { ReaderTransmit(rdblf0, sizeof(rdblf0), NULL); res = ReaderReceive(buf, par); if (res == 18) { - data[data_off++] = MAGIC_NTAG21X; + flag |= MAGIC_FLAG_NTAG21X; } } } else { @@ -2597,7 +2594,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { // regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it // if we do get an ACK, we immediately abort to ensure nothing is ever actually written // only perform test if we haven't already identified Gen2. No need test if we have a positive identification already - if (!isGen2) { + if (isGen2 == false) { mf_reset_card(); res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); @@ -2607,7 +2604,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) { if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, par, NULL) == 1) && (buf[0] == 0x0A)) { - data[data_off++] = MAGIC_GEN_2; + flag |= MAGIC_FLAG_GEN_2; // turn off immediately to ensure nothing ever accidentally writes to the block FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } @@ -2624,7 +2621,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { ReaderTransmit(rdbl00, sizeof(rdbl00), NULL); res = ReaderReceive(buf, par); if (res == 18) { - data[data_off++] = MAGIC_GEN_3; + flag |= MAGIC_FLAG_GEN_3; } } @@ -2636,7 +2633,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { ReaderTransmit(gen4gdmAuth, sizeof(gen4gdmAuth), NULL); res = ReaderReceive(buf, par); if (res == 4) { - data[data_off++] = MAGIC_GDM_AUTH; + flag |= MAGIC_FLAG_GDM_AUTH; } } @@ -2646,24 +2643,20 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) { res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if (res) { if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) { - data[data_off++] = MAGIC_QL88; + flag |= MAGIC_FLAG_QL88; } crypto1_deinit(pcs); } } }; - if (isGen1AGdm == true) { - data[data_off++] = MAGIC_GDM_WUP_40; - } - // GDM alt magic wakeup (20) ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL); if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) { - data[data_off++] = MAGIC_GDM_WUP_20; + flag |= MAGIC_FLAG_GDM_WUP_20; } - reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, data, data_off); + reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, (uint8_t *)&flag, sizeof(uint16_t)); // turns off OnSuccessMagic(); BigBuf_free(); diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index a6a42eb2e..63c0cbcff 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2487,34 +2487,40 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return PM3_EFAILED; } - int isMagic = 0; + uint16_t isMagic = 0; if (isMifareClassic) { isMagic = detect_mf_magic(true, MF_KEY_B, 0xFFFFFFFFFFFF); } + if (isMifareUltralight) { - isMagic = (detect_mf_magic(false, MF_KEY_A, 0) == MAGIC_NTAG21X); + isMagic = ((detect_mf_magic(false, MF_KEY_A, 0) & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X); } + if (isMifareClassic) { int res = detect_classic_static_nonce(); - if (res == NONCE_STATIC) + if (res == NONCE_STATIC) { PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes")); + } - if (res == NONCE_FAIL && verbose) + if (res == NONCE_FAIL && verbose) { PrintAndLogEx(SUCCESS, "Static nonce......... " _RED_("read failed")); + } if (res == NONCE_NORMAL) { // not static res = detect_classic_prng(); - if (res == 1) + if (res == 1) { PrintAndLogEx(SUCCESS, "Prng detection....... " _GREEN_("weak")); - else if (res == 0) + } else if (res == 0) { PrintAndLogEx(SUCCESS, "Prng detection....... " _YELLOW_("hard")); - else + } else { PrintAndLogEx(FAILED, "Prng detection........ " _RED_("fail")); + } - if (do_nack_test) + if (do_nack_test) { detect_classic_nackbug(false); + } } uint8_t signature[32] = {0}; @@ -2522,7 +2528,6 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (res == PM3_SUCCESS) { mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature)); } - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands"); } @@ -2530,20 +2535,25 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return PM3_EFAILED; } - if (isMifareUltralight) + if (isMifareUltralight) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`"); + } - if (isMifarePlus && isMagic == 0 && isEMV == false) + if (isMifarePlus && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfp info") "`"); + } - if (isMifareDESFire && isMagic == 0 && isEMV == false) + if (isMifareDESFire && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfdes info") "`"); + } - if (isST) + if (isST) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st info") "`"); + } - if (isEMV) + if (isEMV) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv reader") "`"); + } if (isFUDAN) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`"); @@ -2564,6 +2574,35 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf ntag424 info") "`"); } + if (isMifareClassic && + (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) + ) { + PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf c*") "` commands when interacting"); + } + + if (isMifareClassic && + ((isMagic & MAGIC_FLAG_GEN_2) == MAGIC_FLAG_GEN_2) + ) { + PrintAndLogEx(HINT, "Hint: Use normal `" _YELLOW_("hf mf") "` commands when interacting"); + } + + if (isMifareClassic && + ((isMagic & MAGIC_FLAG_GEN_3) == MAGIC_FLAG_GEN_3) + ) { + PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mf gen3*") "` commands when interacting"); + } + + if (isMifareClassic && + ((isMagic & MAGIC_FLAG_GEN_4GTU) == MAGIC_FLAG_GEN_4GTU) + ) { + PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mf g*") "` commands when interacting"); + } + + if (isMifareClassic && + ((isMagic & MAGIC_FLAG_GDM_AUTH) == MAGIC_FLAG_GDM_AUTH) + ) { + PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mf gdm*") "` commands when interacting"); + } PrintAndLogEx(NORMAL, ""); DropField(); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 3891033bc..cbfcb6b11 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -9341,13 +9341,12 @@ static int CmdHF14AMfInfo(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Magic Tag Information")); - if (detect_mf_magic(true, MF_KEY_B, e_sector[0].Key[MF_KEY_B]) == 0) { - if (detect_mf_magic(true, MF_KEY_A, e_sector[0].Key[MF_KEY_A]) == 0) { + if (detect_mf_magic(true, MF_KEY_B, e_sector[0].Key[MF_KEY_B]) == MAGIC_FLAG_NONE) { + if (detect_mf_magic(true, MF_KEY_A, e_sector[0].Key[MF_KEY_A]) == MAGIC_FLAG_NONE) { PrintAndLogEx(INFO, ""); } } - free(keyBlock); free(e_sector); diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 3e7e1cf57..535b9d9db 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -381,7 +381,6 @@ static int CmdHFMFPInfo(const char *Cmd) { // https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161 uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false); - if (res != PM3_SUCCESS) { PrintAndLogEx(INFO, "identification failed"); PrintAndLogEx(NORMAL, ""); diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index ac3e0d18b..4e97a2aa9 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -467,17 +467,23 @@ static int ulev1_readSignature(uint8_t *response, uint16_t responseLength) { // make sure field is off before calling this function static int ul_fudan_check(void) { iso14a_card_select_t card; - if (!ul_select(&card)) + if (ul_select(&card) == false) { return MFU_TT_UL_ERROR; + } uint8_t cmd[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa7}; //wrong crc on purpose should be 0xa8 clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return MFU_TT_UL_ERROR; - if (resp.oldarg[0] != 1) return MFU_TT_UL_ERROR; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { + return MFU_TT_UL_ERROR; + } + if (resp.oldarg[0] != 1) { + return MFU_TT_UL_ERROR; + } - return (!resp.data.asBytes[0]) ? MFU_TT_FUDAN_UL : MFU_TT_UL; //if response == 0x00 then Fudan, else Genuine NXP + return (resp.data.asBytes[0] == 0) + ? MFU_TT_FUDAN_UL : MFU_TT_UL; //if response == 0x00 then Fudan, else Genuine NXP } static int ul_print_default(uint8_t *data, uint8_t *real_uid) { @@ -776,7 +782,8 @@ static int ulc_print_configuration(uint8_t *data) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("UL-C Configuration") " --------------------------"); - PrintAndLogEx(INFO, "Available memory... " _YELLOW_("%u") " bytes", 0x2F * 4); + PrintAndLogEx(INFO, "Total memory....... " _YELLOW_("%u") " bytes", MAX_ULC_BLOCKS * 4); + PrintAndLogEx(INFO, "Available memory... " _YELLOW_("%u") " bytes", (MAX_ULC_BLOCKS - 4) * 4); PrintAndLogEx(INFO, "40 / 0x28 | %s - %s Higher lockbits", sprint_hex(data, 4), sprint_bin(data, 2)); PrintAndLogEx(INFO, "41 / 0x29 | %s - %s Counter", sprint_hex(data + 4, 4), sprint_bin(data + 4, 2)); @@ -1271,35 +1278,41 @@ static int ul_magic_test(void) { // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: iso14a_card_select_t card; - if (ul_select(&card) == false) + if (ul_select(&card) == false) { return MFU_TT_UL_ERROR; + } int status = ul_comp_write(0, NULL, 0); DropField(); - if (status == 0) + if (status == 0) { return MFU_TT_MAGIC; + } // check for GEN1A, GEN1B and NTAG21x - uint8_t is_generation = 0; PacketResponseNG resp; clearCommandBuffer(); uint8_t payload[] = { 0 }; SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload)); + + uint16_t is_generation = MAGIC_FLAG_NONE; if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) { - if (resp.status == PM3_SUCCESS) - is_generation = resp.data.asBytes[0]; + if ((resp.status == PM3_SUCCESS) && resp.length == sizeof(uint16_t)) { + is_generation = resp.data.asDwords[0] & 0xFFFF; + } } - switch (is_generation) { - case MAGIC_GEN_1A: - return MFU_TT_MAGIC_1A; - case MAGIC_GEN_1B: - return MFU_TT_MAGIC_1B; - case MAGIC_NTAG21X: - return MFU_TT_MAGIC_NTAG; - default: - break; + + if ((is_generation & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) { + return MFU_TT_MAGIC_1A; } - return 0; + + if ((is_generation & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B) { + return MFU_TT_MAGIC_1B; + } + if ((is_generation & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) { + return MFU_TT_MAGIC_NTAG; + } + + return MFU_TT_UNKNOWN; } static char *GenerateFilename(const char *prefix, const char *suffix) { diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 040de321d..8ba467a94 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1389,10 +1389,10 @@ int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, ui return NONCE_FAIL; } -/* try to see if card responses to "Chinese magic backdoor" commands. */ -int detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) { +// try to see if card responses to "Chinese magic backdoor" commands. +// returns flag +uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) { - uint8_t isMagic = 0; PacketResponseNG resp; clearCommandBuffer(); uint8_t payload[1 + 1 + MIFARE_KEY_SIZE] = { is_mfc, key_type }; @@ -1401,54 +1401,67 @@ int detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) { SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload)); if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) { if (resp.status != PM3_SUCCESS) { - return 0; + return MAGIC_FLAG_NONE; } } - for (size_t i = 0; i < resp.length; i++) { - isMagic = 1; - switch (resp.data.asBytes[i]) { - case MAGIC_GEN_1A: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1a")); - break; - case MAGIC_GEN_1B: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1b")); - break; - case MAGIC_GEN_2: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 2 / CUID")); - break; - case MAGIC_GEN_3: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 3 / APDU") " ( possibly )"); - break; - case MAGIC_GEN_4GTU: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GTU")); - break; - case MAGIC_GDM_AUTH: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Magic Auth )"); - break; - case MAGIC_GDM_WUP_20: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Alt Magic Wakeup )"); - break; - case MAGIC_GDM_WUP_40: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Gen1 Magic Wakeup )"); - break; - case MAGIC_GEN_UNFUSED: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Write Once / FUID")); - break; - case MAGIC_SUPER_GEN1: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 1") _GREEN_(" )")); - break; - case MAGIC_SUPER_GEN2: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 2") _GREEN_(" )")); - break; - case MAGIC_NTAG21X: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("NTAG21x")); - break; - case MAGIC_QL88: - PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("QL88")); - default: - break; - } + uint16_t isMagic = MAGIC_FLAG_NONE; + if ((resp.status == PM3_SUCCESS) && resp.length == sizeof(uint16_t)) { + isMagic = resp.data.asDwords[0] & 0xFFFF; + } + + PrintAndLogEx(INFO, "...%04x", isMagic); + + if ((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1a")); + } + + if ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1b")); + } + + if ((isMagic & MAGIC_FLAG_GEN_2) == MAGIC_FLAG_GEN_2) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 2 / CUID")); + } + + if ((isMagic & MAGIC_FLAG_GEN_3) == MAGIC_FLAG_GEN_3) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 3 / APDU") " ( possibly )"); + } + + if ((isMagic & MAGIC_FLAG_GEN_4GTU) == MAGIC_FLAG_GEN_4GTU) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GTU")); + } + + if ((isMagic & MAGIC_FLAG_GDM_AUTH) == MAGIC_FLAG_GDM_AUTH) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Magic Auth )"); + } + + if ((isMagic & MAGIC_FLAG_GDM_WUP_20) == MAGIC_FLAG_GDM_WUP_20) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Alt Magic Wakeup )"); + } + + if ((isMagic & MAGIC_FLAG_GDM_WUP_40) == MAGIC_FLAG_GDM_WUP_40) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Gen1 Magic Wakeup )"); + } + + if ((isMagic & MAGIC_FLAG_GEN_UNFUSED) == MAGIC_FLAG_GEN_UNFUSED) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Write Once / FUID")); + } + + if ((isMagic & MAGIC_FLAG_SUPER_GEN1) == MAGIC_FLAG_SUPER_GEN1) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 1") _GREEN_(" )")); + } + + if ((isMagic & MAGIC_FLAG_SUPER_GEN2) == MAGIC_FLAG_SUPER_GEN2) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 2") _GREEN_(" )")); + } + + if ((isMagic & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("NTAG21x")); + } + + if ((isMagic & MAGIC_FLAG_QL88) == MAGIC_FLAG_QL88) { + PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("QL88")); } return isMagic; } diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index f71a9436d..83a280d77 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -101,7 +101,7 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int detect_classic_prng(void); int detect_classic_nackbug(bool verbose); -int detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key); +uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key); int detect_classic_static_nonce(void); int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key); bool detect_mfc_ev1_signature(void); diff --git a/include/protocols.h b/include/protocols.h index d2934002c..7b15b235c 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -256,20 +256,21 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MAGIC_WIPE 0x40 #define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E -// by CMD_HF_MIFARE_CIDENT -#define MAGIC_GEN_1A 1 -#define MAGIC_GEN_1B 2 -#define MAGIC_GEN_2 4 -#define MAGIC_GEN_UNFUSED 5 -#define MAGIC_SUPER_GEN1 6 -#define MAGIC_SUPER_GEN2 7 -#define MAGIC_NTAG21X 8 -#define MAGIC_GEN_3 9 -#define MAGIC_GEN_4GTU 10 -#define MAGIC_GDM_AUTH 11 -#define MAGIC_QL88 12 -#define MAGIC_GDM_WUP_20 13 -#define MAGIC_GDM_WUP_40 14 +// by CMD_HF_MIFARE_CIDENT / Flags +#define MAGIC_FLAG_NONE 0x0000 +#define MAGIC_FLAG_GEN_1A 0x0001 +#define MAGIC_FLAG_GEN_1B 0x0002 +#define MAGIC_FLAG_GEN_2 0x0004 +#define MAGIC_FLAG_GEN_UNFUSED 0x0008 +#define MAGIC_FLAG_SUPER_GEN1 0x0010 +#define MAGIC_FLAG_SUPER_GEN2 0x0020 +#define MAGIC_FLAG_NTAG21X 0x0040 +#define MAGIC_FLAG_GEN_3 0x0080 +#define MAGIC_FLAG_GEN_4GTU 0x0100 +#define MAGIC_FLAG_GDM_AUTH 0x0200 +#define MAGIC_FLAG_QL88 0x0400 +#define MAGIC_FLAG_GDM_WUP_20 0x0800 +#define MAGIC_FLAG_GDM_WUP_40 0x1000 // Commands for configuration of Gen4 GTU cards.