style and text. unify some parameter names

This commit is contained in:
iceman1001 2025-06-08 20:56:01 +02:00
commit ec26b6d84f
5 changed files with 196 additions and 92 deletions

View file

@ -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", "<hex>", "Use specific AID (3 hex bytes, big endian)"),
arg_str0("k", "key", "<hex>", "Key for checking (HEX 16 bytes)"),
arg_str0("d", "dict", "<fn>", "Dictionary file with keys"),
arg_str0("f", "file", "<fn>", "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", "<pattern>", "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", "<d40|ev1|ev2|lrp>", "Secure channel"),
arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
arg_str0(NULL, "isoid", "<hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
arg_str0(NULL, "dict", "<fn>", "Dictionary file name with keys"),
arg_str0("f", "file", "<fn>", "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;
}

View file

@ -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", "<hex>", "Key number, 2 hex bytes"),
arg_str1(NULL, "key", "<hex>", "Key, 16 hex bytes"),
arg_str1("k", "key", "<hex>", "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", "<hex>", "Key for checking (HEX 16 bytes)"),
arg_str0("d", "dict", "<fn>", "Dictionary file with keys"),
arg_str0("f", "file", "<fn>", "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", "<pattern>", "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,

View file

@ -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];
}

View file

@ -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

View file

@ -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 <hex> Use specific AID (3 hex bytes, big endian)",
"-k, --key <hex> Key for checking (HEX 16 bytes)",
"-d, --dict <fn> Dictionary file with keys",
"-f, --file <fn> 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 <pattern> Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)",
@ -5775,7 +5775,7 @@
"-i, --kdfi <hex> KDF input (1-31 hex bytes)",
"-a, --apdu Show APDU requests and responses"
],
"usage": "hf mfdes chk [-hva] [--aid <hex>] [-k <hex>] [-d <fn>] [--pattern1b] [--pattern2b] [--startp2b <pattern>] [-j <fn>] [--kdf <0|1|2>] [-i <hex>]"
"usage": "hf mfdes chk [-hva] [--aid <hex>] [-k <hex>] [-f <fn>] [--pattern1b] [--pattern2b] [--startp2b <pattern>] [-j <fn>] [--kdf <0|1|2>] [-i <hex>]"
},
"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 <d40|ev1|ev2|lrp> Secure channel",
"--aid <hex> Application ID (3 hex bytes, big endian)",
"--isoid <hex> Application ISO ID (ISO DF ID) (2 hex bytes, big endian).",
"--dict <fn> Dictionary file name with keys",
"-f, --file <fn> Filename of dictionary",
"--save Save found key and parameters to defaults"
],
"usage": "hf mfdes detect [-hav] [-n <dec>] [-t <DES|2TDEA|3TDEA|AES>] [-k <hex>] [--kdf <none|AN10922|gallagher>] [-i <hex>] [-m <plain|mac|encrypt>] [-c <native|niso|iso>] [--schann <d40|ev1|ev2|lrp>] [--aid <hex>] [--isoid <hex>] [--dict <fn>] [--save]"
"usage": "hf mfdes detect [-hav] [-n <dec>] [-t <DES|2TDEA|3TDEA|AES>] [-k <hex>] [--kdf <none|AN10922|gallagher>] [-i <hex>] [-m <plain|mac|encrypt>] [-c <native|niso|iso>] [--schann <d40|ev1|ev2|lrp>] [--aid <hex>] [--isoid <hex>] [-f <fn>] [--save]"
},
"hf mfdes dump": {
"command": "hf mfdes dump",
@ -6770,9 +6770,9 @@
"-h, --help This help",
"-v, --verbose Verbose output",
"--ki <hex> Key number, 2 hex bytes",
"--key <hex> Key, 16 hex bytes"
"-k, --key <hex> Key, 16 hex bytes"
],
"usage": "hf mfp auth [-hv] --ki <hex> --key <hex>"
"usage": "hf mfp auth [-hv] --ki <hex> -k <hex>"
},
"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 <hex> Key for checking (HEX 16 bytes)",
"-d, --dict <fn> Dictionary file with keys",
"-f, --file <fn> 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 <pattern> 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 <hex>] [-d <fn>] [--pattern1b] [--pattern2b] [--startp2b <pattern>] [--dump]"
"usage": "hf mfp chk [-habv] [-s <0..255>] [-e <0..255>] [-k <hex>] [-f <fn>] [--pattern1b] [--pattern2b] [--startp2b <pattern>] [--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"
}
}