diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 5ecc3a545..1315869db 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1187,8 +1187,8 @@ static int CmdHF14aDesChk(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes chk", "Checks keys with MIFARE DESFire card.", "hf mfdes chk --aid 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n" - "hf mfdes chk -d mfdes_default_keys -> check keys against all existing aid on card\n" - "hf mfdes chk -d mfdes_default_keys --aid 123456 -> check keys against aid 0x123456\n" + "hf mfdes chk -f mfdes_default_keys -> check keys against all existing aid on card\n" + "hf mfdes chk -f mfdes_default_keys --aid 123456 -> check keys against aid 0x123456\n" "hf mfdes chk --aid 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to `keys.json`\n" "hf mfdes chk --aid 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00"); @@ -1196,7 +1196,7 @@ static int CmdHF14aDesChk(const char *Cmd) { arg_param_begin, arg_str0(NULL, "aid", "", "Use specific AID (3 hex bytes, big endian)"), arg_str0("k", "key", "", "Key for checking (HEX 16 bytes)"), - arg_str0("d", "dict", "", "Dictionary file with keys"), + arg_str0("f", "file", "", "Filename of dictionary"), arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), arg_str0(NULL, "startp2b", "", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), @@ -1209,12 +1209,12 @@ static int CmdHF14aDesChk(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); - bool APDULogging = arg_get_lit(ctx, 11); - int aidlength = 0; uint8_t aid[3] = {0}; CLIGetHexWithReturn(ctx, 1, aid, &aidlength); + swap24(aid); + uint8_t vkey[16] = {0}; int vkeylen = 0; CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen); @@ -1293,17 +1293,26 @@ static int CmdHF14aDesChk(const char *Cmd) { int kdfInputLen = 0; CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen); + bool APDULogging = arg_get_lit(ctx, 11); + CLIParserFree(ctx); SetAPDULogging(APDULogging); // 1-byte pattern search mode if (pattern1b) { - for (uint32_t i = 0; i < 0x100; i++) + + for (uint32_t i = 0; i < 0x100; i++) { memset(aeskeyList[i], i, 16); - for (uint32_t i = 0; i < 0x100; i++) + } + + for (uint32_t i = 0; i < 0x100; i++) { memset(deskeyList[i], i, 8); - for (uint32_t i = 0; i < 0x100; i++) + } + + for (uint32_t i = 0; i < 0x100; i++) { memset(k3kkeyList[i], i, 24); + } + aeskeyListLen = 0x100; deskeyListLen = 0x100; k3kkeyListLen = 0x100; @@ -1319,18 +1328,21 @@ static int CmdHF14aDesChk(const char *Cmd) { if (dict_filenamelen) { res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 8, &deskeyListLen, 0, &endFilePosition, true); - if (res == PM3_SUCCESS && endFilePosition) + if (res == PM3_SUCCESS && endFilePosition) { PrintAndLogEx(SUCCESS, "First part of des dictionary successfully loaded."); + } endFilePosition = 0; res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &aeskeyListLen, 0, &endFilePosition, true); - if (res == PM3_SUCCESS && endFilePosition) + if (res == PM3_SUCCESS && endFilePosition) { PrintAndLogEx(SUCCESS, "First part of aes dictionary successfully loaded."); + } endFilePosition = 0; res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 24, &k3kkeyListLen, 0, &endFilePosition, true); - if (res == PM3_SUCCESS && endFilePosition) + if (res == PM3_SUCCESS && endFilePosition) { PrintAndLogEx(SUCCESS, "First part of k3kdes dictionary successfully loaded."); + } endFilePosition = 0; } @@ -1352,8 +1364,9 @@ static int CmdHF14aDesChk(const char *Cmd) { PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen); } - if (verbose == false) + if (verbose == false) { PrintAndLogEx(INFO, "Search keys:"); + } bool result = false; uint8_t app_ids[78] = {0}; @@ -1508,7 +1521,7 @@ static int CmdHF14aDesDetect(const char *Cmd) { "Detect key type and tries to find one from the list.", "hf mfdes detect -> detect key 0 from PICC level\n" "hf mfdes detect --schann d40 -> detect key 0 from PICC level via secure channel D40\n" - "hf mfdes detect --dict mfdes_default_keys -> detect key 0 from PICC level with help of the standard dictionary\n" + "hf mfdes detect -f mfdes_default_keys -> detect key 0 from PICC level with help of the standard dictionary\n" "hf mfdes detect --aid 123456 -n 2 --save -> detect key 2 from app 123456 and if succeed - save params to defaults (`default` command)\n" "hf mfdes detect --isoid df01 --save -> detect key 0 and save to defaults with card in the LRP mode"); @@ -1526,7 +1539,7 @@ static int CmdHF14aDesDetect(const char *Cmd) { arg_str0(NULL, "schann", "", "Secure channel"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), arg_str0(NULL, "isoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), - arg_str0(NULL, "dict", "", "Dictionary file name with keys"), + arg_str0("f", "file", "", "Filename of dictionary"), arg_lit0(NULL, "save", "Save found key and parameters to defaults"), arg_param_end }; @@ -1571,28 +1584,38 @@ static int CmdHF14aDesDetect(const char *Cmd) { uint8_t data[250] = {0}; size_t datalen = 0; + res = DesfireGetKeySettings(&dctx, data, &datalen); if (res == PM3_SUCCESS && datalen >= 2) { + uint8_t num_keys = data[1]; + switch (num_keys >> 6) { - case 0: + case 0: { keytypes[T_DES] = true; keytypes[T_3DES] = true; break; - case 1: + } + case 1: { keytypes[T_3K3DES] = true; break; - case 2: + } + case 2: { keytypes[T_AES] = true; break; - default: + } + default: { break; + } } + } else { // if fail - check auth commands AuthCommandsChk_t authCmdCheck = {0}; DesfireCheckAuthCommands(selectway, id, NULL, 0, &authCmdCheck); + if (authCmdCheck.checked) { + if (authCmdCheck.auth) { keytypes[T_DES] = true; keytypes[T_3DES] = true; @@ -1601,14 +1624,17 @@ static int CmdHF14aDesDetect(const char *Cmd) { keytypes[T_3K3DES] = true; } } + if (authCmdCheck.authAES || authCmdCheck.authEV2) { keytypes[T_AES] = true; } + if (authCmdCheck.authLRP) { keytypes[T_AES] = true; uselrp = true; securechann = DACLRP; } + } else { // if nothing helps - we check DES only keytypes[T_DES] = true; @@ -1623,10 +1649,13 @@ static int CmdHF14aDesDetect(const char *Cmd) { } if (verbose) { - if (DesfireMFSelected(selectway, id)) + + if (DesfireMFSelected(selectway, id)) { PrintAndLogEx(INFO, "Check PICC key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum); - else + } else { PrintAndLogEx(INFO, "Check: %s key num: %d (0x%02x)", DesfireWayIDStr(selectway, id), dctx.keyNum, dctx.keyNum); + } + PrintAndLogEx(INFO, "keys: DES: %s 2TDEA: %s 3TDEA: %s AES: %s LRP: %s", keytypes[T_DES] ? _GREEN_("YES") : _RED_("NO"), keytypes[T_3DES] ? _GREEN_("YES") : _RED_("NO"), @@ -1640,43 +1669,61 @@ static int CmdHF14aDesDetect(const char *Cmd) { bool found = false; size_t errcount = 0; for (uint8_t ktype = T_DES; ktype <= T_AES; ktype++) { - if (!keytypes[ktype]) + + if (keytypes[ktype] == false) { continue; + } + dctx.keyType = ktype; - if (verbose) + + if (verbose) { PrintAndLogEx(INFO, "Scan key type: %s", CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType)); + } if (dict_filenamelen == 0) { // keys from mifaredefault.h for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { + uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0}; - if (hex_to_bytes(g_mifare_plus_default_keys[i], key, 16) != 16) + if (hex_to_bytes(g_mifare_plus_default_keys[i], key, 16) != 16) { continue; - if (ktype == T_3K3DES) + } + + if (ktype == T_3K3DES) { memcpy(&key[16], key, 8); + } res = DesfireAuthCheck(&dctx, selectway, id, securechann, key); if (res == PM3_SUCCESS) { found = true; break; // all the params already in the dctx } + if (res == -10) { - if (verbose) + + if (verbose) { PrintAndLogEx(ERR, "Can't select AID. There is no connection with card."); + } found = false; break; // we can't select app after invalid 1st auth stages } + if (res == -11) { + if (errcount > 10) { - if (verbose) + if (verbose) { PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount); + } break; } errcount++; - } else + + } else { errcount = 0; + } } + } else { // keys from file uint8_t keyList[MAX_KEYS_LIST_LEN * MAX_KEY_LEN] = {0}; @@ -1684,49 +1731,65 @@ static int CmdHF14aDesDetect(const char *Cmd) { size_t keylen = desfire_get_key_length(dctx.keyType); size_t endFilePosition = 0; - while (!found) { + while (found == false) { + res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, keylen, &keyListLen, endFilePosition, &endFilePosition, verbose); - if (res != 1 && res != PM3_SUCCESS) + if (res != 1 && res != PM3_SUCCESS) { break; + } for (int i = 0; i < keyListLen; i++) { + res = DesfireAuthCheck(&dctx, selectway, id, securechann, &keyList[i * keylen]); if (res == PM3_SUCCESS) { found = true; break; // all the params already in the dctx } + if (res == -10) { - if (verbose) + if (verbose) { PrintAndLogEx(ERR, "Can't select AID. There is no connection with card."); + } found = false; break; // we can't select app after invalid 1st auth stages } + if (res == -11) { + if (errcount > 10) { - if (verbose) + if (verbose) { PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount); + } break; } errcount++; - } else + + } else { errcount = 0; + } + } - if (endFilePosition == 0) + if (endFilePosition == 0) { break; + } } } - if (found) + + if (found) { break; + } } if (found) { - if (DesfireMFSelected(selectway, id)) + + if (DesfireMFSelected(selectway, id)) { PrintAndLogEx(INFO, _GREEN_("Found") " key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum); - else + } else { PrintAndLogEx(INFO, "Found key for: %s key num: %d (0x%02x)", DesfireWayIDStr(selectway, id), dctx.keyNum, dctx.keyNum); + } PrintAndLogEx(INFO, "channel " _GREEN_("%s") " key " _GREEN_("%s") " [%d]: " _GREEN_("%s"), CLIGetOptionListStr(DesfireSecureChannelOpts, securechann), @@ -1741,6 +1804,7 @@ static int CmdHF14aDesDetect(const char *Cmd) { DropField(); if (found && save) { + defaultKeyNum = dctx.keyNum; defaultAlgoId = dctx.keyType; memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE); @@ -1751,17 +1815,16 @@ static int CmdHF14aDesDetect(const char *Cmd) { defaultCommSet = dctx.cmdSet; PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); - - PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum); - PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId)); - PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId))); - PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo)); - PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen)); - PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); - PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet)); - PrintAndLogEx(INFO, _GREEN_("Saved")); + PrintAndLogEx(INFO, "Key Num....... %d", defaultKeyNum); + PrintAndLogEx(INFO, "Algo.......... %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId)); + PrintAndLogEx(INFO, "Key........... %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId))); + PrintAndLogEx(INFO, "KDF algo...... %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo)); + PrintAndLogEx(INFO, "KDF input..... [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen)); + PrintAndLogEx(INFO, "Secure chan... %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); + PrintAndLogEx(INFO, "Command set... %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet)); + PrintAndLogEx(INFO, "Parameters saved to in-memory ( %s )", _GREEN_("ok")); } - + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 8437d72da..a1af9d780 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -575,7 +575,8 @@ static int CmdHFMFPInitPerso(const char *Cmd) { CLIParserInit(&ctx, "hf mfp initp", "Executes Write Perso command for all card's keys. Can be used in SL0 mode only.", "hf mfp initp --key 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n" - "hf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange"); + "hf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange" + ); void *argtable[] = { arg_param_begin, @@ -700,13 +701,14 @@ static int CmdHFMFPAuth(const char *Cmd) { CLIParserInit(&ctx, "hf mfp auth", "Executes AES authentication command for MIFARE Plus card", "hf mfp auth --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> executes authentication\n" - "hf mfp auth --ki 9003 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data"); + "hf mfp auth --ki 9003 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data" + ); void *argtable[] = { arg_param_begin, arg_lit0("v", "verbose", "Verbose output"), arg_str1(NULL, "ki", "", "Key number, 2 hex bytes"), - arg_str1(NULL, "key", "", "Key, 16 hex bytes"), + arg_str1("k", "key", "", "Key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -756,7 +758,8 @@ static int CmdHFMFPRdbl(const char *Cmd) { CLIParserInit(&ctx, "hf mfp rdbl", "Reads blocks from MIFARE Plus card", "hf mfp rdbl --blk 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" - "hf mfp rdbl --blk 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF"); + "hf mfp rdbl --blk 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF" + ); void *argtable[] = { arg_param_begin, @@ -874,7 +877,8 @@ static int CmdHFMFPRdsc(const char *Cmd) { CLIParserInit(&ctx, "hf mfp rdsc", "Reads one sector from MIFARE Plus card", "hf mfp rdsc -s 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" - "hf mfp rdsc -s 1 -v -> executes authentication and shows sector 1 data with default key"); + "hf mfp rdsc -s 1 -v -> executes authentication and shows sector 1 data with default key" + ); void *argtable[] = { arg_param_begin, @@ -1418,9 +1422,10 @@ static int CmdHFMFPChk(const char *Cmd) { "Checks keys on MIFARE Plus card", "hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" "hf mfp chk -s 2 -a -> check default key list on sector 2, only key A\n" - "hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n" + "hf mfp chk -f mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n" "hf mfp chk --pattern1b --dump -> check all 1-byte keys pattern and save found keys to file\n" - "hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00"); + "hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00" + ); void *argtable[] = { arg_param_begin, @@ -1429,7 +1434,7 @@ static int CmdHFMFPChk(const char *Cmd) { arg_int0("s", "startsec", "<0..255>", "Start sector number"), arg_int0("e", "endsec", "<0..255>", "End sector number"), arg_str0("k", "key", "", "Key for checking (HEX 16 bytes)"), - arg_str0("d", "dict", "", "Dictionary file with keys"), + arg_str0("f", "file", "", "Dictionary file with default keys"), arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), arg_str0(NULL, "startp2b", "", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), @@ -1507,17 +1512,21 @@ static int CmdHFMFPChk(const char *Cmd) { uint8_t startKeyAB = 0; uint8_t endKeyAB = 1; - if (keyA && (keyB == false)) + if (keyA && (keyB == false)) { endKeyAB = 0; + } - if ((keyA == false) && keyB) + if ((keyA == false) && keyB) { startKeyAB = 1; + } - if (endSector < startSector) + if (endSector < startSector) { endSector = startSector; + } // 1-byte pattern search mode if (pattern1b) { + for (int i = 0; i < 0x100; i++) { memset(keyList[i], i, 16); } @@ -1535,9 +1544,10 @@ static int CmdHFMFPChk(const char *Cmd) { // dictionary mode size_t endFilePosition = 0; if (dict_filenamelen) { - uint32_t keycnt = 0; - res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, 0, &endFilePosition, true); + uint32_t keycnt = 0; + + res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, 0, &endFilePosition, true); if (res == PM3_SUCCESS && endFilePosition) { keyListLen = keycnt; PrintAndLogEx(SUCCESS, "First part of dictionary successfully loaded."); @@ -1604,13 +1614,13 @@ static int CmdHFMFPChk(const char *Cmd) { char strA[46 + 1] = {0}; char strB[46 + 1] = {0}; - uint8_t ndef_key[] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; + bool has_ndef_key = false; bool printedHeader = false; for (uint8_t s = startSector; s <= endSector; s++) { - if ((memcmp(&foundKeys[0][s][1], ndef_key, AES_KEY_LEN) == 0) || - (memcmp(&foundKeys[1][s][1], ndef_key, AES_KEY_LEN) == 0)) { + if ((memcmp(&foundKeys[0][s][1], g_mifarep_ndef_key, AES_KEY_LEN) == 0) || + (memcmp(&foundKeys[1][s][1], g_mifarep_ndef_key, AES_KEY_LEN) == 0)) { has_ndef_key = true; } @@ -1637,10 +1647,12 @@ static int CmdHFMFPChk(const char *Cmd) { PrintAndLogEx(INFO, " " _YELLOW_("%03d") " | %s | %s", s, strA, strB); } - if (printedHeader == false) - PrintAndLogEx(INFO, "No keys found("); - else - PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------\n"); + if (printedHeader == false) { + PrintAndLogEx(INFO, "No keys found"); + } else { + PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------"); + } + PrintAndLogEx(NORMAL, ""); // save keys to json if (create_dumpfile && printedHeader) { @@ -1691,7 +1703,7 @@ static int CmdHFMFPChk(const char *Cmd) { } // MAD detection - if ((memcmp(&foundKeys[0][0][1], "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7", AES_KEY_LEN) == 0)) { + if ((memcmp(&foundKeys[0][0][1], g_mifarep_mad_key, AES_KEY_LEN) == 0)) { PrintAndLogEx(HINT, "Hint: MAD key detected. Try " _YELLOW_("`hf mfp mad`") " for more details"); } @@ -1784,7 +1796,8 @@ static int CmdHFMFPMAD(const char *Cmd) { CLIParserInit(&ctx, "hf mfp mad", "Checks and prints MIFARE Application Directory (MAD)", "hf mfp mad\n" - "hf mfp mad --aid e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> read and print NDEF data from MAD aid"); + "hf mfp mad --aid e103 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> read and print NDEF data from MAD aid" + ); void *argtable[] = { arg_param_begin, diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index 3716f7470..ea7986441 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -210,15 +210,18 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; uint8_t RndB[17] = {0}; - if (silentMode) + if (silentMode) { verbose = false; + } - if (mf4session) + if (mf4session) { mf4session->Authenticated = false; + } uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode); if (res != PM3_SUCCESS) { + if (silentMode == false) { PrintAndLogEx(ERR, "Exchange raw error: %d", res); } @@ -234,20 +237,35 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo } if (datalen < 1) { - if (!silentMode) PrintAndLogEx(ERR, "Card response wrong length: %d", datalen); - if (dropFieldIfError) DropField(); + if (silentMode == false) { + PrintAndLogEx(ERR, "Card response wrong length: %d", datalen); + } + + if (dropFieldIfError) { + DropField(); + } return PM3_EWRONGANSWER; } if (data[0] != 0x90) { - if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x %s", data[0], mfpGetErrorDescription(data[0])); - if (dropFieldIfError) DropField(); + if (silentMode == false) { + PrintAndLogEx(ERR, "Card response error: %02x %s", data[0], mfpGetErrorDescription(data[0])); + } + + if (dropFieldIfError) { + DropField(); + } return PM3_EWRONGANSWER; } if (datalen != 19) { // code 1b + 16b + crc 2b - if (!silentMode) PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen); - if (dropFieldIfError) DropField(); + if (silentMode == false) { + PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen); + } + + if (dropFieldIfError) { + DropField(); + } return PM3_EWRONGANSWER; } @@ -268,11 +286,13 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo if (verbose) { PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33)); } + res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode); if (res != PM3_SUCCESS) { if (silentMode == false) { PrintAndLogEx(ERR, "Exchange raw error: %d", res); } + if (dropFieldIfError) { DropField(); } @@ -291,12 +311,18 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo } if (memcmp(&raw[4], &RndA[1], 16)) { - if (!silentMode) PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd is not equal"); + if (silentMode == false) { + PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd is not equal"); + } + if (verbose) { PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16)); PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16)); } - if (dropFieldIfError) DropField(); + + if (dropFieldIfError) { + DropField(); + } return PM3_EWRONGANSWER; } @@ -309,6 +335,7 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo uint8_t kenc[16] = {0}; memcpy(&kenc[0], &RndA[11], 5); memcpy(&kenc[5], &RndB[11], 5); + for (int i = 0; i < 5; i++) { kenc[10 + i] = RndA[4 + i] ^ RndB[4 + i]; } @@ -322,6 +349,7 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo uint8_t kmac[16] = {0}; memcpy(&kmac[0], &RndA[7], 5); memcpy(&kmac[5], &RndB[7], 5); + for (int i = 0; i < 5; i++) { kmac[10 + i] = RndA[0 + i] ^ RndB[0 + i]; } diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 66a2ad780..9e6ba67c3 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -26,7 +26,7 @@ #include "mifaredefault.h" // consts #include "protocol_vigik.h" -#define MIFARE_SECTOR_RETRY 10 +#define MIFARE_SECTOR_RETRY 6 // mifare tracer flags #define TRACE_IDLE 0x00 diff --git a/doc/commands.json b/doc/commands.json index 08a61cc39..e18cb9743 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -5755,8 +5755,8 @@ "description": "Checks keys with MIFARE DESFire card.", "notes": [ "hf mfdes chk --aid 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456", - "hf mfdes chk -d mfdes_default_keys -> check keys against all existing aid on card", - "hf mfdes chk -d mfdes_default_keys --aid 123456 -> check keys against aid 0x123456", + "hf mfdes chk -f mfdes_default_keys -> check keys against all existing aid on card", + "hf mfdes chk -f mfdes_default_keys --aid 123456 -> check keys against aid 0x123456", "hf mfdes chk --aid 123456 --pattern1b -j keys -> check all 1-byte keys pattern on aid 0x123456 and save found keys to `keys.json`", "hf mfdes chk --aid 123456 --pattern2b --startp2b FA00 -> check all 2-byte keys pattern on aid 0x123456. Start from key FA00FA00...FA00" ], @@ -5765,7 +5765,7 @@ "-h, --help This help", "--aid Use specific AID (3 hex bytes, big endian)", "-k, --key Key for checking (HEX 16 bytes)", - "-d, --dict Dictionary file with keys", + "-f, --file Filename of dictionary", "--pattern1b Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)", "--pattern2b Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)", "--startp2b Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)", @@ -5775,7 +5775,7 @@ "-i, --kdfi KDF input (1-31 hex bytes)", "-a, --apdu Show APDU requests and responses" ], - "usage": "hf mfdes chk [-hva] [--aid ] [-k ] [-d ] [--pattern1b] [--pattern2b] [--startp2b ] [-j ] [--kdf <0|1|2>] [-i ]" + "usage": "hf mfdes chk [-hva] [--aid ] [-k ] [-f ] [--pattern1b] [--pattern2b] [--startp2b ] [-j ] [--kdf <0|1|2>] [-i ]" }, "hf mfdes chkeysettings": { "command": "hf mfdes chkeysettings", @@ -6130,7 +6130,7 @@ "notes": [ "hf mfdes detect -> detect key 0 from PICC level", "hf mfdes detect --schann d40 -> detect key 0 from PICC level via secure channel D40", - "hf mfdes detect --dict mfdes_default_keys -> detect key 0 from PICC level with help of the standard dictionary", + "hf mfdes detect -f mfdes_default_keys -> detect key 0 from PICC level with help of the standard dictionary", "hf mfdes detect --aid 123456 -n 2 --save -> detect key 2 from app 123456 and if succeed - save params to defaults (`default` command)", "hf mfdes detect --isoid df01 --save -> detect key 0 and save to defaults with card in the LRP mode" ], @@ -6149,10 +6149,10 @@ "--schann Secure channel", "--aid Application ID (3 hex bytes, big endian)", "--isoid Application ISO ID (ISO DF ID) (2 hex bytes, big endian).", - "--dict Dictionary file name with keys", + "-f, --file Filename of dictionary", "--save Save found key and parameters to defaults" ], - "usage": "hf mfdes detect [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [--dict ] [--save]" + "usage": "hf mfdes detect [-hav] [-n ] [-t ] [-k ] [--kdf ] [-i ] [-m ] [-c ] [--schann ] [--aid ] [--isoid ] [-f ] [--save]" }, "hf mfdes dump": { "command": "hf mfdes dump", @@ -6770,9 +6770,9 @@ "-h, --help This help", "-v, --verbose Verbose output", "--ki Key number, 2 hex bytes", - "--key Key, 16 hex bytes" + "-k, --key Key, 16 hex bytes" ], - "usage": "hf mfp auth [-hv] --ki --key " + "usage": "hf mfp auth [-hv] --ki -k " }, "hf mfp chconf": { "command": "hf mfp chconf", @@ -6806,7 +6806,7 @@ "notes": [ "hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B", "hf mfp chk -s 2 -a -> check default key list on sector 2, only key A", - "hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6", + "hf mfp chk -f mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6", "hf mfp chk --pattern1b --dump -> check all 1-byte keys pattern and save found keys to file", "hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00" ], @@ -6818,14 +6818,14 @@ "-s, --startsec <0..255> Start sector number", "-e, --endsec <0..255> End sector number", "-k, --key Key for checking (HEX 16 bytes)", - "-d, --dict Dictionary file with keys", + "-f, --file Dictionary file with default keys", "--pattern1b Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)", "--pattern2b Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)", "--startp2b Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)", "--dump Dump found keys to JSON file", "-v, --verbose Verbose output" ], - "usage": "hf mfp chk [-habv] [-s <0..255>] [-e <0..255>] [-k ] [-d ] [--pattern1b] [--pattern2b] [--startp2b ] [--dump]" + "usage": "hf mfp chk [-habv] [-s <0..255>] [-e <0..255>] [-k ] [-f ] [--pattern1b] [--pattern2b] [--startp2b ] [--dump]" }, "hf mfp chkey": { "command": "hf mfp chkey", @@ -13376,6 +13376,6 @@ "metadata": { "commands_extracted": 768, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2025-06-08T17:26:24" + "extracted_on": "2025-06-08T18:54:12" } }