mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
style and text. unify some parameter names
This commit is contained in:
parent
add2eb8e9d
commit
ec26b6d84f
5 changed files with 196 additions and 92 deletions
|
@ -1187,8 +1187,8 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "hf mfdes chk",
|
CLIParserInit(&ctx, "hf mfdes chk",
|
||||||
"Checks keys with MIFARE DESFire card.",
|
"Checks keys with MIFARE DESFire card.",
|
||||||
"hf mfdes chk --aid 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
|
"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 -f 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 --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 --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");
|
"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_param_begin,
|
||||||
arg_str0(NULL, "aid", "<hex>", "Use specific AID (3 hex bytes, big endian)"),
|
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("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, "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_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`)"),
|
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);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 11);
|
|
||||||
|
|
||||||
int aidlength = 0;
|
int aidlength = 0;
|
||||||
uint8_t aid[3] = {0};
|
uint8_t aid[3] = {0};
|
||||||
CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
|
CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
|
||||||
|
|
||||||
swap24(aid);
|
swap24(aid);
|
||||||
|
|
||||||
uint8_t vkey[16] = {0};
|
uint8_t vkey[16] = {0};
|
||||||
int vkeylen = 0;
|
int vkeylen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen);
|
CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen);
|
||||||
|
@ -1293,17 +1293,26 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
int kdfInputLen = 0;
|
int kdfInputLen = 0;
|
||||||
CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen);
|
CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen);
|
||||||
|
|
||||||
|
bool APDULogging = arg_get_lit(ctx, 11);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
|
|
||||||
// 1-byte pattern search mode
|
// 1-byte pattern search mode
|
||||||
if (pattern1b) {
|
if (pattern1b) {
|
||||||
for (uint32_t i = 0; i < 0x100; i++)
|
|
||||||
|
for (uint32_t i = 0; i < 0x100; i++) {
|
||||||
memset(aeskeyList[i], i, 16);
|
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);
|
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);
|
memset(k3kkeyList[i], i, 24);
|
||||||
|
}
|
||||||
|
|
||||||
aeskeyListLen = 0x100;
|
aeskeyListLen = 0x100;
|
||||||
deskeyListLen = 0x100;
|
deskeyListLen = 0x100;
|
||||||
k3kkeyListLen = 0x100;
|
k3kkeyListLen = 0x100;
|
||||||
|
@ -1319,18 +1328,21 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
if (dict_filenamelen) {
|
if (dict_filenamelen) {
|
||||||
|
|
||||||
res = loadFileDICTIONARYEx((char *)dict_filename, deskeyList, sizeof(deskeyList), NULL, 8, &deskeyListLen, 0, &endFilePosition, true);
|
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.");
|
PrintAndLogEx(SUCCESS, "First part of des dictionary successfully loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
endFilePosition = 0;
|
endFilePosition = 0;
|
||||||
res = loadFileDICTIONARYEx((char *)dict_filename, aeskeyList, sizeof(aeskeyList), NULL, 16, &aeskeyListLen, 0, &endFilePosition, true);
|
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.");
|
PrintAndLogEx(SUCCESS, "First part of aes dictionary successfully loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
endFilePosition = 0;
|
endFilePosition = 0;
|
||||||
res = loadFileDICTIONARYEx((char *)dict_filename, k3kkeyList, sizeof(k3kkeyList), NULL, 24, &k3kkeyListLen, 0, &endFilePosition, true);
|
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.");
|
PrintAndLogEx(SUCCESS, "First part of k3kdes dictionary successfully loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
endFilePosition = 0;
|
endFilePosition = 0;
|
||||||
}
|
}
|
||||||
|
@ -1352,8 +1364,9 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen);
|
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose == false)
|
if (verbose == false) {
|
||||||
PrintAndLogEx(INFO, "Search keys:");
|
PrintAndLogEx(INFO, "Search keys:");
|
||||||
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
uint8_t app_ids[78] = {0};
|
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.",
|
"Detect key type and tries to find one from the list.",
|
||||||
"hf mfdes detect -> detect key 0 from PICC level\n"
|
"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 --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 --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");
|
"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, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
|
||||||
arg_str0(NULL, "aid", "<hex>", "Application ID (3 hex bytes, big endian)"),
|
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, "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_lit0(NULL, "save", "Save found key and parameters to defaults"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
|
@ -1571,28 +1584,38 @@ static int CmdHF14aDesDetect(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t data[250] = {0};
|
uint8_t data[250] = {0};
|
||||||
size_t datalen = 0;
|
size_t datalen = 0;
|
||||||
|
|
||||||
res = DesfireGetKeySettings(&dctx, data, &datalen);
|
res = DesfireGetKeySettings(&dctx, data, &datalen);
|
||||||
if (res == PM3_SUCCESS && datalen >= 2) {
|
if (res == PM3_SUCCESS && datalen >= 2) {
|
||||||
|
|
||||||
uint8_t num_keys = data[1];
|
uint8_t num_keys = data[1];
|
||||||
|
|
||||||
switch (num_keys >> 6) {
|
switch (num_keys >> 6) {
|
||||||
case 0:
|
case 0: {
|
||||||
keytypes[T_DES] = true;
|
keytypes[T_DES] = true;
|
||||||
keytypes[T_3DES] = true;
|
keytypes[T_3DES] = true;
|
||||||
break;
|
break;
|
||||||
case 1:
|
}
|
||||||
|
case 1: {
|
||||||
keytypes[T_3K3DES] = true;
|
keytypes[T_3K3DES] = true;
|
||||||
break;
|
break;
|
||||||
case 2:
|
}
|
||||||
|
case 2: {
|
||||||
keytypes[T_AES] = true;
|
keytypes[T_AES] = true;
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if fail - check auth commands
|
// if fail - check auth commands
|
||||||
AuthCommandsChk_t authCmdCheck = {0};
|
AuthCommandsChk_t authCmdCheck = {0};
|
||||||
DesfireCheckAuthCommands(selectway, id, NULL, 0, &authCmdCheck);
|
DesfireCheckAuthCommands(selectway, id, NULL, 0, &authCmdCheck);
|
||||||
|
|
||||||
if (authCmdCheck.checked) {
|
if (authCmdCheck.checked) {
|
||||||
|
|
||||||
if (authCmdCheck.auth) {
|
if (authCmdCheck.auth) {
|
||||||
keytypes[T_DES] = true;
|
keytypes[T_DES] = true;
|
||||||
keytypes[T_3DES] = true;
|
keytypes[T_3DES] = true;
|
||||||
|
@ -1601,14 +1624,17 @@ static int CmdHF14aDesDetect(const char *Cmd) {
|
||||||
keytypes[T_3K3DES] = true;
|
keytypes[T_3K3DES] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authCmdCheck.authAES || authCmdCheck.authEV2) {
|
if (authCmdCheck.authAES || authCmdCheck.authEV2) {
|
||||||
keytypes[T_AES] = true;
|
keytypes[T_AES] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authCmdCheck.authLRP) {
|
if (authCmdCheck.authLRP) {
|
||||||
keytypes[T_AES] = true;
|
keytypes[T_AES] = true;
|
||||||
uselrp = true;
|
uselrp = true;
|
||||||
securechann = DACLRP;
|
securechann = DACLRP;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// if nothing helps - we check DES only
|
// if nothing helps - we check DES only
|
||||||
keytypes[T_DES] = true;
|
keytypes[T_DES] = true;
|
||||||
|
@ -1623,10 +1649,13 @@ static int CmdHF14aDesDetect(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (DesfireMFSelected(selectway, id))
|
|
||||||
|
if (DesfireMFSelected(selectway, id)) {
|
||||||
PrintAndLogEx(INFO, "Check PICC key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum);
|
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, "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",
|
PrintAndLogEx(INFO, "keys: DES: %s 2TDEA: %s 3TDEA: %s AES: %s LRP: %s",
|
||||||
keytypes[T_DES] ? _GREEN_("YES") : _RED_("NO"),
|
keytypes[T_DES] ? _GREEN_("YES") : _RED_("NO"),
|
||||||
keytypes[T_3DES] ? _GREEN_("YES") : _RED_("NO"),
|
keytypes[T_3DES] ? _GREEN_("YES") : _RED_("NO"),
|
||||||
|
@ -1640,43 +1669,61 @@ static int CmdHF14aDesDetect(const char *Cmd) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
size_t errcount = 0;
|
size_t errcount = 0;
|
||||||
for (uint8_t ktype = T_DES; ktype <= T_AES; ktype++) {
|
for (uint8_t ktype = T_DES; ktype <= T_AES; ktype++) {
|
||||||
if (!keytypes[ktype])
|
|
||||||
|
if (keytypes[ktype] == false) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
dctx.keyType = ktype;
|
dctx.keyType = ktype;
|
||||||
if (verbose)
|
|
||||||
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "Scan key type: %s", CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType));
|
PrintAndLogEx(INFO, "Scan key type: %s", CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType));
|
||||||
|
}
|
||||||
|
|
||||||
if (dict_filenamelen == 0) {
|
if (dict_filenamelen == 0) {
|
||||||
// keys from mifaredefault.h
|
// keys from mifaredefault.h
|
||||||
for (int i = 0; i < g_mifare_plus_default_keys_len; i++) {
|
for (int i = 0; i < g_mifare_plus_default_keys_len; i++) {
|
||||||
|
|
||||||
uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0};
|
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;
|
continue;
|
||||||
if (ktype == T_3K3DES)
|
}
|
||||||
|
|
||||||
|
if (ktype == T_3K3DES) {
|
||||||
memcpy(&key[16], key, 8);
|
memcpy(&key[16], key, 8);
|
||||||
|
}
|
||||||
|
|
||||||
res = DesfireAuthCheck(&dctx, selectway, id, securechann, key);
|
res = DesfireAuthCheck(&dctx, selectway, id, securechann, key);
|
||||||
if (res == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
found = true;
|
found = true;
|
||||||
break; // all the params already in the dctx
|
break; // all the params already in the dctx
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == -10) {
|
if (res == -10) {
|
||||||
if (verbose)
|
|
||||||
|
if (verbose) {
|
||||||
PrintAndLogEx(ERR, "Can't select AID. There is no connection with card.");
|
PrintAndLogEx(ERR, "Can't select AID. There is no connection with card.");
|
||||||
|
}
|
||||||
|
|
||||||
found = false;
|
found = false;
|
||||||
break; // we can't select app after invalid 1st auth stages
|
break; // we can't select app after invalid 1st auth stages
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == -11) {
|
if (res == -11) {
|
||||||
|
|
||||||
if (errcount > 10) {
|
if (errcount > 10) {
|
||||||
if (verbose)
|
if (verbose) {
|
||||||
PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount);
|
PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
errcount++;
|
errcount++;
|
||||||
} else
|
|
||||||
|
} else {
|
||||||
errcount = 0;
|
errcount = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// keys from file
|
// keys from file
|
||||||
uint8_t keyList[MAX_KEYS_LIST_LEN * MAX_KEY_LEN] = {0};
|
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 keylen = desfire_get_key_length(dctx.keyType);
|
||||||
size_t endFilePosition = 0;
|
size_t endFilePosition = 0;
|
||||||
|
|
||||||
while (!found) {
|
while (found == false) {
|
||||||
|
|
||||||
res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, keylen, &keyListLen, endFilePosition, &endFilePosition, verbose);
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < keyListLen; i++) {
|
for (int i = 0; i < keyListLen; i++) {
|
||||||
|
|
||||||
res = DesfireAuthCheck(&dctx, selectway, id, securechann, &keyList[i * keylen]);
|
res = DesfireAuthCheck(&dctx, selectway, id, securechann, &keyList[i * keylen]);
|
||||||
if (res == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
found = true;
|
found = true;
|
||||||
break; // all the params already in the dctx
|
break; // all the params already in the dctx
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == -10) {
|
if (res == -10) {
|
||||||
if (verbose)
|
if (verbose) {
|
||||||
PrintAndLogEx(ERR, "Can't select AID. There is no connection with card.");
|
PrintAndLogEx(ERR, "Can't select AID. There is no connection with card.");
|
||||||
|
}
|
||||||
|
|
||||||
found = false;
|
found = false;
|
||||||
break; // we can't select app after invalid 1st auth stages
|
break; // we can't select app after invalid 1st auth stages
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == -11) {
|
if (res == -11) {
|
||||||
|
|
||||||
if (errcount > 10) {
|
if (errcount > 10) {
|
||||||
if (verbose)
|
if (verbose) {
|
||||||
PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount);
|
PrintAndLogEx(ERR, "Too much errors (%zu) from card", errcount);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
errcount++;
|
errcount++;
|
||||||
} else
|
|
||||||
|
} else {
|
||||||
errcount = 0;
|
errcount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endFilePosition == 0)
|
if (endFilePosition == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (found)
|
|
||||||
|
if (found) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
if (DesfireMFSelected(selectway, id))
|
|
||||||
|
if (DesfireMFSelected(selectway, id)) {
|
||||||
PrintAndLogEx(INFO, _GREEN_("Found") " key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum);
|
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, "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"),
|
PrintAndLogEx(INFO, "channel " _GREEN_("%s") " key " _GREEN_("%s") " [%d]: " _GREEN_("%s"),
|
||||||
CLIGetOptionListStr(DesfireSecureChannelOpts, securechann),
|
CLIGetOptionListStr(DesfireSecureChannelOpts, securechann),
|
||||||
|
@ -1741,6 +1804,7 @@ static int CmdHF14aDesDetect(const char *Cmd) {
|
||||||
DropField();
|
DropField();
|
||||||
|
|
||||||
if (found && save) {
|
if (found && save) {
|
||||||
|
|
||||||
defaultKeyNum = dctx.keyNum;
|
defaultKeyNum = dctx.keyNum;
|
||||||
defaultAlgoId = dctx.keyType;
|
defaultAlgoId = dctx.keyType;
|
||||||
memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE);
|
memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE);
|
||||||
|
@ -1751,17 +1815,16 @@ static int CmdHF14aDesDetect(const char *Cmd) {
|
||||||
defaultCommSet = dctx.cmdSet;
|
defaultCommSet = dctx.cmdSet;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------");
|
PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------");
|
||||||
|
PrintAndLogEx(INFO, "Key Num....... %d", defaultKeyNum);
|
||||||
PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum);
|
PrintAndLogEx(INFO, "Algo.......... %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId));
|
||||||
PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId));
|
PrintAndLogEx(INFO, "Key........... %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId)));
|
||||||
PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, desfire_get_key_length(defaultAlgoId)));
|
PrintAndLogEx(INFO, "KDF algo...... %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo));
|
||||||
PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo));
|
PrintAndLogEx(INFO, "KDF input..... [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen));
|
||||||
PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen));
|
PrintAndLogEx(INFO, "Secure chan... %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel));
|
||||||
PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel));
|
PrintAndLogEx(INFO, "Command set... %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet));
|
||||||
PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet));
|
PrintAndLogEx(INFO, "Parameters saved to in-memory ( %s )", _GREEN_("ok"));
|
||||||
PrintAndLogEx(INFO, _GREEN_("Saved"));
|
|
||||||
}
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -575,7 +575,8 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "hf mfp initp",
|
CLIParserInit(&ctx, "hf mfp initp",
|
||||||
"Executes Write Perso command for all card's keys. Can be used in SL0 mode only.",
|
"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 --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[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -700,13 +701,14 @@ static int CmdHFMFPAuth(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "hf mfp auth",
|
CLIParserInit(&ctx, "hf mfp auth",
|
||||||
"Executes AES authentication command for MIFARE Plus card",
|
"Executes AES authentication command for MIFARE Plus card",
|
||||||
"hf mfp auth --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
|
"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[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("v", "verbose", "Verbose output"),
|
arg_lit0("v", "verbose", "Verbose output"),
|
||||||
arg_str1(NULL, "ki", "<hex>", "Key number, 2 hex bytes"),
|
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
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
@ -756,7 +758,8 @@ static int CmdHFMFPRdbl(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "hf mfp rdbl",
|
CLIParserInit(&ctx, "hf mfp rdbl",
|
||||||
"Reads blocks from MIFARE Plus card",
|
"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 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[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -874,7 +877,8 @@ static int CmdHFMFPRdsc(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "hf mfp rdsc",
|
CLIParserInit(&ctx, "hf mfp rdsc",
|
||||||
"Reads one sector from MIFARE Plus card",
|
"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 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[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -1418,9 +1422,10 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
"Checks keys on MIFARE Plus card",
|
"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 -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 -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 --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[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -1429,7 +1434,7 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
arg_int0("s", "startsec", "<0..255>", "Start sector number"),
|
arg_int0("s", "startsec", "<0..255>", "Start sector number"),
|
||||||
arg_int0("e", "endsec", "<0..255>", "End sector number"),
|
arg_int0("e", "endsec", "<0..255>", "End sector number"),
|
||||||
arg_str0("k", "key", "<hex>", "Key for checking (HEX 16 bytes)"),
|
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, "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_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`)"),
|
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 startKeyAB = 0;
|
||||||
uint8_t endKeyAB = 1;
|
uint8_t endKeyAB = 1;
|
||||||
if (keyA && (keyB == false))
|
if (keyA && (keyB == false)) {
|
||||||
endKeyAB = 0;
|
endKeyAB = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((keyA == false) && keyB)
|
if ((keyA == false) && keyB) {
|
||||||
startKeyAB = 1;
|
startKeyAB = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (endSector < startSector)
|
if (endSector < startSector) {
|
||||||
endSector = startSector;
|
endSector = startSector;
|
||||||
|
}
|
||||||
|
|
||||||
// 1-byte pattern search mode
|
// 1-byte pattern search mode
|
||||||
if (pattern1b) {
|
if (pattern1b) {
|
||||||
|
|
||||||
for (int i = 0; i < 0x100; i++) {
|
for (int i = 0; i < 0x100; i++) {
|
||||||
memset(keyList[i], i, 16);
|
memset(keyList[i], i, 16);
|
||||||
}
|
}
|
||||||
|
@ -1535,9 +1544,10 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
// dictionary mode
|
// dictionary mode
|
||||||
size_t endFilePosition = 0;
|
size_t endFilePosition = 0;
|
||||||
if (dict_filenamelen) {
|
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) {
|
if (res == PM3_SUCCESS && endFilePosition) {
|
||||||
keyListLen = keycnt;
|
keyListLen = keycnt;
|
||||||
PrintAndLogEx(SUCCESS, "First part of dictionary successfully loaded.");
|
PrintAndLogEx(SUCCESS, "First part of dictionary successfully loaded.");
|
||||||
|
@ -1604,13 +1614,13 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
char strA[46 + 1] = {0};
|
char strA[46 + 1] = {0};
|
||||||
char strB[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 has_ndef_key = false;
|
||||||
bool printedHeader = false;
|
bool printedHeader = false;
|
||||||
for (uint8_t s = startSector; s <= endSector; s++) {
|
for (uint8_t s = startSector; s <= endSector; s++) {
|
||||||
|
|
||||||
if ((memcmp(&foundKeys[0][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], ndef_key, AES_KEY_LEN) == 0)) {
|
(memcmp(&foundKeys[1][s][1], g_mifarep_ndef_key, AES_KEY_LEN) == 0)) {
|
||||||
has_ndef_key = true;
|
has_ndef_key = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,10 +1647,12 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, " " _YELLOW_("%03d") " | %s | %s", s, strA, strB);
|
PrintAndLogEx(INFO, " " _YELLOW_("%03d") " | %s | %s", s, strA, strB);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printedHeader == false)
|
if (printedHeader == false) {
|
||||||
PrintAndLogEx(INFO, "No keys found(");
|
PrintAndLogEx(INFO, "No keys found");
|
||||||
else
|
} else {
|
||||||
PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------\n");
|
PrintAndLogEx(INFO, "-----+----------------------------------+----------------------------------");
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
// save keys to json
|
// save keys to json
|
||||||
if (create_dumpfile && printedHeader) {
|
if (create_dumpfile && printedHeader) {
|
||||||
|
@ -1691,7 +1703,7 @@ static int CmdHFMFPChk(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MAD detection
|
// 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");
|
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",
|
CLIParserInit(&ctx, "hf mfp mad",
|
||||||
"Checks and prints MIFARE Application Directory (MAD)",
|
"Checks and prints MIFARE Application Directory (MAD)",
|
||||||
"hf mfp mad\n"
|
"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[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
|
|
@ -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 RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
|
||||||
uint8_t RndB[17] = {0};
|
uint8_t RndB[17] = {0};
|
||||||
|
|
||||||
if (silentMode)
|
if (silentMode) {
|
||||||
verbose = false;
|
verbose = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mf4session)
|
if (mf4session) {
|
||||||
mf4session->Authenticated = false;
|
mf4session->Authenticated = false;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00};
|
uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00};
|
||||||
int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode);
|
int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
|
|
||||||
if (silentMode == false) {
|
if (silentMode == false) {
|
||||||
PrintAndLogEx(ERR, "Exchange raw error: %d", res);
|
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 (datalen < 1) {
|
||||||
if (!silentMode) PrintAndLogEx(ERR, "Card response wrong length: %d", datalen);
|
if (silentMode == false) {
|
||||||
if (dropFieldIfError) DropField();
|
PrintAndLogEx(ERR, "Card response wrong length: %d", datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropFieldIfError) {
|
||||||
|
DropField();
|
||||||
|
}
|
||||||
return PM3_EWRONGANSWER;
|
return PM3_EWRONGANSWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data[0] != 0x90) {
|
if (data[0] != 0x90) {
|
||||||
if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x %s", data[0], mfpGetErrorDescription(data[0]));
|
if (silentMode == false) {
|
||||||
if (dropFieldIfError) DropField();
|
PrintAndLogEx(ERR, "Card response error: %02x %s", data[0], mfpGetErrorDescription(data[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropFieldIfError) {
|
||||||
|
DropField();
|
||||||
|
}
|
||||||
return PM3_EWRONGANSWER;
|
return PM3_EWRONGANSWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datalen != 19) { // code 1b + 16b + crc 2b
|
if (datalen != 19) { // code 1b + 16b + crc 2b
|
||||||
if (!silentMode) PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen);
|
if (silentMode == false) {
|
||||||
if (dropFieldIfError) DropField();
|
PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropFieldIfError) {
|
||||||
|
DropField();
|
||||||
|
}
|
||||||
return PM3_EWRONGANSWER;
|
return PM3_EWRONGANSWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,11 +286,13 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33));
|
PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33));
|
||||||
}
|
}
|
||||||
|
|
||||||
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode);
|
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
if (silentMode == false) {
|
if (silentMode == false) {
|
||||||
PrintAndLogEx(ERR, "Exchange raw error: %d", res);
|
PrintAndLogEx(ERR, "Exchange raw error: %d", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dropFieldIfError) {
|
if (dropFieldIfError) {
|
||||||
DropField();
|
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 (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) {
|
if (verbose) {
|
||||||
PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16));
|
PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16));
|
||||||
PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16));
|
PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16));
|
||||||
}
|
}
|
||||||
if (dropFieldIfError) DropField();
|
|
||||||
|
if (dropFieldIfError) {
|
||||||
|
DropField();
|
||||||
|
}
|
||||||
return PM3_EWRONGANSWER;
|
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};
|
uint8_t kenc[16] = {0};
|
||||||
memcpy(&kenc[0], &RndA[11], 5);
|
memcpy(&kenc[0], &RndA[11], 5);
|
||||||
memcpy(&kenc[5], &RndB[11], 5);
|
memcpy(&kenc[5], &RndB[11], 5);
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
kenc[10 + i] = RndA[4 + i] ^ RndB[4 + 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};
|
uint8_t kmac[16] = {0};
|
||||||
memcpy(&kmac[0], &RndA[7], 5);
|
memcpy(&kmac[0], &RndA[7], 5);
|
||||||
memcpy(&kmac[5], &RndB[7], 5);
|
memcpy(&kmac[5], &RndB[7], 5);
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
kmac[10 + i] = RndA[0 + i] ^ RndB[0 + i];
|
kmac[10 + i] = RndA[0 + i] ^ RndB[0 + i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "mifaredefault.h" // consts
|
#include "mifaredefault.h" // consts
|
||||||
#include "protocol_vigik.h"
|
#include "protocol_vigik.h"
|
||||||
|
|
||||||
#define MIFARE_SECTOR_RETRY 10
|
#define MIFARE_SECTOR_RETRY 6
|
||||||
|
|
||||||
// mifare tracer flags
|
// mifare tracer flags
|
||||||
#define TRACE_IDLE 0x00
|
#define TRACE_IDLE 0x00
|
||||||
|
|
|
@ -5755,8 +5755,8 @@
|
||||||
"description": "Checks keys with MIFARE DESFire card.",
|
"description": "Checks keys with MIFARE DESFire card.",
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf mfdes chk --aid 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456",
|
"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 -f 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 --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 --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"
|
"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",
|
"-h, --help This help",
|
||||||
"--aid <hex> Use specific AID (3 hex bytes, big endian)",
|
"--aid <hex> Use specific AID (3 hex bytes, big endian)",
|
||||||
"-k, --key <hex> Key for checking (HEX 16 bytes)",
|
"-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, ...)",
|
"--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, ...)",
|
"--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`)",
|
"--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)",
|
"-i, --kdfi <hex> KDF input (1-31 hex bytes)",
|
||||||
"-a, --apdu Show APDU requests and responses"
|
"-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": {
|
"hf mfdes chkeysettings": {
|
||||||
"command": "hf mfdes chkeysettings",
|
"command": "hf mfdes chkeysettings",
|
||||||
|
@ -6130,7 +6130,7 @@
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf mfdes detect -> detect key 0 from PICC level",
|
"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 --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 --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"
|
"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",
|
"--schann <d40|ev1|ev2|lrp> Secure channel",
|
||||||
"--aid <hex> Application ID (3 hex bytes, big endian)",
|
"--aid <hex> Application ID (3 hex bytes, big endian)",
|
||||||
"--isoid <hex> Application ISO ID (ISO DF ID) (2 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"
|
"--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": {
|
"hf mfdes dump": {
|
||||||
"command": "hf mfdes dump",
|
"command": "hf mfdes dump",
|
||||||
|
@ -6770,9 +6770,9 @@
|
||||||
"-h, --help This help",
|
"-h, --help This help",
|
||||||
"-v, --verbose Verbose output",
|
"-v, --verbose Verbose output",
|
||||||
"--ki <hex> Key number, 2 hex bytes",
|
"--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": {
|
"hf mfp chconf": {
|
||||||
"command": "hf mfp chconf",
|
"command": "hf mfp chconf",
|
||||||
|
@ -6806,7 +6806,7 @@
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B",
|
"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 -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 --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"
|
"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",
|
"-s, --startsec <0..255> Start sector number",
|
||||||
"-e, --endsec <0..255> End sector number",
|
"-e, --endsec <0..255> End sector number",
|
||||||
"-k, --key <hex> Key for checking (HEX 16 bytes)",
|
"-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, ...)",
|
"--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, ...)",
|
"--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`)",
|
"--startp2b <pattern> Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)",
|
||||||
"--dump Dump found keys to JSON file",
|
"--dump Dump found keys to JSON file",
|
||||||
"-v, --verbose Verbose output"
|
"-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": {
|
"hf mfp chkey": {
|
||||||
"command": "hf mfp chkey",
|
"command": "hf mfp chkey",
|
||||||
|
@ -13376,6 +13376,6 @@
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"commands_extracted": 768,
|
"commands_extracted": 768,
|
||||||
"extracted_by": "PM3Help2JSON v1.00",
|
"extracted_by": "PM3Help2JSON v1.00",
|
||||||
"extracted_on": "2025-06-08T17:26:24"
|
"extracted_on": "2025-06-08T18:54:12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue