This commit is contained in:
iceman1001 2024-11-15 14:28:14 +01:00
commit 3a3ea75d12
11 changed files with 124 additions and 126 deletions

View file

@ -2168,7 +2168,7 @@ static void generate_single_key_block_inverted_opt(const uint8_t *startingKey, u
0x95, 0x96, 0x99, 0x9A, 0x9C, 0xA3, 0xA5, 0xA6, 0xA9, 0xAA, 0x95, 0x96, 0x99, 0x9A, 0x9C, 0xA3, 0xA5, 0xA6, 0xA9, 0xAA,
0xAC, 0xB1, 0xB2, 0xB4, 0xB8, 0xC3, 0xC5, 0xC6, 0xC9, 0xCA, 0xAC, 0xB1, 0xB2, 0xB4, 0xB8, 0xC3, 0xC5, 0xC6, 0xC9, 0xCA,
0xCC, 0xD1, 0xD2, 0xD4, 0xD8, 0xE1, 0xE2, 0xE4, 0xE8, 0xF0 0xCC, 0xD1, 0xD2, 0xD4, 0xD8, 0xE1, 0xE2, 0xE4, 0xE8, 0xF0
}; };
uint8_t binary_endings[8]; // Array to store binary values for each ending bit uint8_t binary_endings[8]; // Array to store binary values for each ending bit
// Extract each bit from the ending_bits[k] and store it in binary_endings // Extract each bit from the ending_bits[k] and store it in binary_endings

View file

@ -3128,82 +3128,82 @@ void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *
}; };
first_nt_counter++; first_nt_counter++;
} else for (uint8_t i = 0; i < nr_nested; i++) { } else for (uint8_t i = 0; i < nr_nested; i++) {
if (need_first_auth) { if (need_first_auth) {
cuid = 0; cuid = 0;
if (hardreset) { if (hardreset) {
if (g_dbglevel >= DBG_EXTENDED) { if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("RF reset"); Dbprintf("RF reset");
}
// some cards need longer than mf_reset_card() to see effect on nT
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(150);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
} }
// some cards need longer than mf_reset_card() to see effect on nT if (g_dbglevel >= DBG_EXTENDED) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); Dbprintf("select");
SpinDelay(150); }
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if (iso14443a_select_card(NULL, NULL, &cuid, true, 0, true) == false) {
} retval = PM3_ESOFT;
if (g_dbglevel >= DBG_EXTENDED) { goto OUT;
Dbprintf("select"); }
} if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, &nt_first, NULL, NULL, NULL, corruptnrar, corruptnrarparity)) {
if (iso14443a_select_card(NULL, NULL, &cuid, true, 0, true) == false) {
retval = PM3_ESOFT;
goto OUT;
}
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, &nt_first, NULL, NULL, NULL, corruptnrar, corruptnrarparity)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT;
goto OUT;
};
is_last_auth_first_auth = true;
first_nt_counter++;
if ((first_nt_counter > 1) && (old_nt_first == nt_first)) {
first_nt_repetition_counter++;
}
old_nt_first = nt_first;
if (!reset && !hardreset) {
need_first_auth = false;
}
if (addread) {
uint8_t dataread[16] = {0x00};
mifare_classic_readblock(pcs, block_no, dataread);
}
if (addauth) {
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, NULL, NULL, NULL, false, false)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT; retval = PM3_ESOFT;
goto OUT; goto OUT;
} else if (g_dbglevel >= DBG_EXTENDED) { };
Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt)); is_last_auth_first_auth = true;
first_nt_counter++;
if ((first_nt_counter > 1) && (old_nt_first == nt_first)) {
first_nt_repetition_counter++;
} }
is_last_auth_first_auth = false; old_nt_first = nt_first;
if (nt == nt_first) { if (!reset && !hardreset) {
first_and_nested_nt_repetition_counter++; need_first_auth = false;
}
if (addread) {
uint8_t dataread[16] = {0x00};
mifare_classic_readblock(pcs, block_no, dataread);
}
if (addauth) {
if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, NULL, NULL, NULL, false, false)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error");
retval = PM3_ESOFT;
goto OUT;
} else if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt));
}
is_last_auth_first_auth = false;
if (nt == nt_first) {
first_and_nested_nt_repetition_counter++;
}
old_nt = nt;
} }
old_nt = nt;
} }
}
nt = 0; nt = 0;
ntenc = 0; ntenc = 0;
if (mifare_classic_authex_cmd(pcs, cuid, incblk2 ? block_no_nested + (i * 4) : block_no_nested, key_auth_cmd_nested, ui64key_nested, AUTH_NESTED, &nt, &ntenc, &ntencpar, NULL, false, false)) { if (mifare_classic_authex_cmd(pcs, cuid, incblk2 ? block_no_nested + (i * 4) : block_no_nested, key_auth_cmd_nested, ui64key_nested, AUTH_NESTED, &nt, &ntenc, &ntencpar, NULL, false, false)) {
if (g_dbglevel >= DBG_ERROR) Dbprintf("Nested auth error"); if (g_dbglevel >= DBG_ERROR) Dbprintf("Nested auth error");
need_first_auth = true; need_first_auth = true;
} else if (g_dbglevel >= DBG_EXTENDED) { } else if (g_dbglevel >= DBG_EXTENDED) {
if (is_last_auth_first_auth) { if (is_last_auth_first_auth) {
Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt)); Dbprintf("Nonce distance: %5i (first nonce <> nested nonce)", nonce_distance(nt_first, nt));
} else { } else {
Dbprintf("Nonce distance: %5i", nonce_distance(old_nt, nt)); Dbprintf("Nonce distance: %5i", nonce_distance(old_nt, nt));
}
} }
nested_nt_session_counter++;
is_last_auth_first_auth = false;
old_nt = nt;
if (nt == nt_first) {
first_and_nested_nt_repetition_counter++;
}
if ((nested_nt_session_counter > 1) && (oldntenc == ntenc)) {
nested_nt_repetition_counter++;
}
oldntenc = ntenc;
} }
nested_nt_session_counter++;
is_last_auth_first_auth = false;
old_nt = nt;
if (nt == nt_first) {
first_and_nested_nt_repetition_counter++;
}
if ((nested_nt_session_counter > 1) && (oldntenc == ntenc)) {
nested_nt_repetition_counter++;
}
oldntenc = ntenc;
}
data[1] = (cuid >> 24) & 0xFF; data[1] = (cuid >> 24) & 0xFF;
data[2] = (cuid >> 16) & 0xFF; data[2] = (cuid >> 16) & 0xFF;

View file

@ -483,7 +483,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )"); PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )");
//Block 13 (This is needed for Rev.C readers!) //Block 13 (This is needed for Rev.C readers!)
uint8_t block_0x13[PICOPASS_BLOCK_SIZE] = {0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x1C}; uint8_t block_0x13[PICOPASS_BLOCK_SIZE] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C};
memcpy(data + (0x13 * 8), block_0x13, sizeof(block_0x13)); memcpy(data + (0x13 * 8), block_0x13, sizeof(block_0x13));
// encrypted partial keyroll key 14 // encrypted partial keyroll key 14
@ -536,7 +536,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
} else { } else {
memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data, cc, sizeof(picopass_hdr_t));
memcpy(data + (6 * 8), o->data, sizeof(o->data)); memcpy(data + (6 * 8), o->data, sizeof(o->data));
if (strstr(o->desc, "Custom") != NULL){ if (strstr(o->desc, "Custom") != NULL) {
if (got_mk == false) { if (got_mk == false) {
PrintAndLogEx(ERR, "please specify New Master Key!"); PrintAndLogEx(ERR, "please specify New Master Key!");
free(data); free(data);
@ -5066,16 +5066,16 @@ static int CmdHFiClassConfigCard(const char *Cmd) {
if (ccidx > -1 && ccidx < ARRAYLEN(iclass_config_options)) { if (ccidx > -1 && ccidx < ARRAYLEN(iclass_config_options)) {
const iclass_config_card_item_t *item = get_config_card_item(ccidx); const iclass_config_card_item_t *item = get_config_card_item(ccidx);
if (strstr(item->desc, "ELITE") != NULL && got_kr == false) { if (strstr(item->desc, "ELITE") != NULL && got_kr == false) {
PrintAndLogEx(ERR, "please specify ELITE Key (--eki) !"); PrintAndLogEx(ERR, "please specify ELITE Key (--eki) !");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (strstr(item->desc, "Custom") != NULL && got_mk == false) { if (strstr(item->desc, "Custom") != NULL && got_mk == false) {
PrintAndLogEx(ERR, "please specify New Standard Master Key (--mrki) !"); PrintAndLogEx(ERR, "please specify New Standard Master Key (--mrki) !");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (strstr(item->desc, "Restore") != NULL && card_kidx == -1) { if (strstr(item->desc, "Restore") != NULL && card_kidx == -1) {
PrintAndLogEx(ERR, "please specify the Current Reader's Key (--ki) !"); PrintAndLogEx(ERR, "please specify the Current Reader's Key (--ki) !");
return PM3_EINVARG; return PM3_EINVARG;
} }
generate_config_card(item, keyroll_key, got_kr, card_key, got_eki, elite, got_mk, master_key); generate_config_card(item, keyroll_key, got_kr, card_key, got_eki, elite, got_mk, master_key);
} }

View file

@ -250,9 +250,9 @@ bool mfc_value(const uint8_t *d, int32_t *val) {
uint32_t b = MemLeToUint4byte(d + 8); uint32_t b = MemLeToUint4byte(d + 8);
int val_checks = ( int val_checks = (
(a == b) && (a == ~a_inv) && (a == b) && (a == ~a_inv) &&
(d[12] == (~d[13] & 0xFF)) && (d[12] == (~d[13] & 0xFF)) &&
(d[14] == (~d[15] & 0xFF)) (d[14] == (~d[15] & 0xFF))
); );
if (val) { if (val) {
@ -1602,7 +1602,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
PrintAndLogEx(INFO, " %3d | %s| ( " _RED_("fail") " ) key " _YELLOW_("%c"), PrintAndLogEx(INFO, " %3d | %s| ( " _RED_("fail") " ) key " _YELLOW_("%c"),
blockno, blockno,
sprint_hex(bldata, sizeof(bldata)), sprint_hex(bldata, sizeof(bldata)),
(kt == MF_KEY_A) ? 'A' : 'B' (kt == MF_KEY_A) ? 'A' : 'B'
); );
} // end loop key types } // end loop key types
} // end loop B } // end loop B
@ -2963,7 +2963,7 @@ noValidKeyFound:
PrintAndLogEx(INFO, "======================= " _YELLOW_("START READ B KEY ATTACK") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("START READ B KEY ATTACK") " =======================");
PrintAndLogEx(INFO, "reading B key of sector %3d with key type %c", PrintAndLogEx(INFO, "reading B key of sector %3d with key type %c",
current_sector_i, current_sector_i,
(current_key_type_i == MF_KEY_B) ? 'B' : 'A'); (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
} }
uint8_t sectrail = (mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1); uint8_t sectrail = (mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1);
@ -2995,7 +2995,7 @@ noValidKeyFound:
if (verbose) { if (verbose) {
PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c", PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c",
current_sector_i, current_sector_i,
(current_key_type_i == MF_KEY_B) ? 'B' : 'A' (current_key_type_i == MF_KEY_B) ? 'B' : 'A'
); );
PrintAndLogEx(INFO, " -- reading the B key was not possible, maybe due to access rights?"); PrintAndLogEx(INFO, " -- reading the B key was not possible, maybe due to access rights?");
@ -3018,7 +3018,7 @@ skipReadBKey:
PrintAndLogEx(INFO, "======================= " _YELLOW_("START NESTED ATTACK") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("START NESTED ATTACK") " =======================");
PrintAndLogEx(INFO, "sector no %3d, target key type %c", PrintAndLogEx(INFO, "sector no %3d, target key type %c",
current_sector_i, current_sector_i,
(current_key_type_i == MF_KEY_B) ? 'B' : 'A'); (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
} }
tryNested: tryNested:
isOK = mf_nested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate); isOK = mf_nested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate);
@ -3144,7 +3144,7 @@ tryStaticnested:
PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " ======================="); PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " =======================");
PrintAndLogEx(INFO, "sector no %3d, target key type %c", PrintAndLogEx(INFO, "sector no %3d, target key type %c",
current_sector_i, current_sector_i,
(current_key_type_i == MF_KEY_B) ? 'B' : 'A'); (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
} }
isOK = mf_static_nested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key); isOK = mf_static_nested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key);
@ -4424,7 +4424,7 @@ void printKeyTableEx(size_t sectorscnt, sector_t *e_sector, uint8_t start_sector
_YELLOW_("H") ":Hardnested / " _YELLOW_("H") ":Hardnested / "
_YELLOW_("C") ":statiCnested / " _YELLOW_("C") ":statiCnested / "
_YELLOW_("A") ":keyA " _YELLOW_("A") ":keyA "
" )" " )"
); );
if (sectorscnt == 18) { if (sectorscnt == 18) {
PrintAndLogEx(INFO, "( " _MAGENTA_("*") " ) These sectors used for signature. Lays outside of user memory"); PrintAndLogEx(INFO, "( " _MAGENTA_("*") " ) These sectors used for signature. Lays outside of user memory");
@ -5212,7 +5212,7 @@ static int CmdHF14AMfCSetUID(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen)); PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen));
PrintAndLogEx(SUCCESS, "New UID... %s ( %s )", PrintAndLogEx(SUCCESS, "New UID... %s ( %s )",
sprint_hex(verify_uid, uidlen), sprint_hex(verify_uid, uidlen),
(res == 0) ? _GREEN_("verified") : _RED_("fail") (res == 0) ? _GREEN_("verified") : _RED_("fail")
); );
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -6603,10 +6603,10 @@ int CmdHFMFNDEFFormat(const char *Cmd) {
"If not, it will try finding a key file based on your UID. ie, if you ran autopwn before", "If not, it will try finding a key file based on your UID. ie, if you ran autopwn before",
"hf mf ndefformat\n" "hf mf ndefformat\n"
// "hf mf ndefformat --mini --> MIFARE Mini\n" // "hf mf ndefformat --mini --> MIFARE Mini\n"
"hf mf ndefformat --1k --> MIFARE Classic 1k\n" "hf mf ndefformat --1k --> MIFARE Classic 1k\n"
// "hf mf ndefformat --2k --> MIFARE 2k\n" // "hf mf ndefformat --2k --> MIFARE 2k\n"
// "hf mf ndefformat --4k --> MIFARE 4k\n" // "hf mf ndefformat --4k --> MIFARE 4k\n"
"hf mf ndefformat --keys hf-mf-01020304-key.bin --> MIFARE 1k with keys from specified file\n" "hf mf ndefformat --keys hf-mf-01020304-key.bin --> MIFARE 1k with keys from specified file\n"
); );
void *argtable[] = { void *argtable[] = {
@ -9258,7 +9258,7 @@ static int CmdHF14AMfValue(const char *Cmd) {
// don't want to write value data and break something // don't want to write value data and break something
if ((blockno == 0) || if ((blockno == 0) ||
(mfIsSectorTrailer(blockno)) || (mfIsSectorTrailer(blockno)) ||
(trnval == 0) || (trnval == 0) ||
(trnval != -1 && mfIsSectorTrailer(trnval))) { (trnval != -1 && mfIsSectorTrailer(trnval))) {
PrintAndLogEx(WARNING, "invalid block number, should be a data block"); PrintAndLogEx(WARNING, "invalid block number, should be a data block");
return PM3_EINVARG; return PM3_EINVARG;
@ -9695,47 +9695,47 @@ static int CmdHF14AMfInfo(const char *Cmd) {
// backdoor might be present, or just a clone reusing Fudan MF data... // backdoor might be present, or just a clone reusing Fudan MF data...
PrintAndLogEx(SUCCESS, "Fudan based card"); PrintAndLogEx(SUCCESS, "Fudan based card");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0
&& card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
&& (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x90) { && (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x90) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08S"); PrintAndLogEx(SUCCESS, "Fudan FM11RF08S");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0
&& card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x03\x00\x10", 4) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x03\x00\x10", 4) == 0
&& blockdata[15] == 0x90) { && blockdata[15] == 0x90) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B"); PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
&& blockdata[15] == 0x98) { && blockdata[15] == 0x98) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08S **98"); PrintAndLogEx(SUCCESS, "Fudan FM11RF08S **98");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
&& (blockdata[8] >= 0x01 && blockdata[8] <= 0x03) && blockdata[15] == 0x1D) { && (blockdata[8] >= 0x01 && blockdata[8] <= 0x03) && blockdata[15] == 0x1D) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08"); PrintAndLogEx(SUCCESS, "Fudan FM11RF08");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k32, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k32, sizeof(fkey)) == 0
&& card.sak == 0x18 && memcmp(blockdata + 5, "\x18\x02\x00\x46\x44\x53\x37\x30\x56\x30\x31", 11) == 0) { && card.sak == 0x18 && memcmp(blockdata + 5, "\x18\x02\x00\x46\x44\x53\x37\x30\x56\x30\x31", 11) == 0) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF32"); PrintAndLogEx(SUCCESS, "Fudan FM11RF32");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) { && card.sak == 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF32 (SAK=20)"); PrintAndLogEx(SUCCESS, "Fudan FM11RF32 (SAK=20)");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x28 && ( && card.sak == 0x28 && (
(memcmp(blockdata + 5, "\x28\x04\x00\x90\x10\x15\x01\x00\x00\x00\x00", 11) == 0) || (memcmp(blockdata + 5, "\x28\x04\x00\x90\x10\x15\x01\x00\x00\x00\x00", 11) == 0) ||
(memcmp(blockdata + 5, "\x28\x04\x00\x90\x11\x15\x01\x00\x00\x00\x00", 11) == 0))) { (memcmp(blockdata + 5, "\x28\x04\x00\x90\x11\x15\x01\x00\x00\x00\x00", 11) == 0))) {
// Note: it also has ATS = // Note: it also has ATS =
// 10 78 80 90 02 20 90 00 00 00 00 00 + UID + CRC // 10 78 80 90 02 20 90 00 00 00 00 00 + UID + CRC
PrintAndLogEx(SUCCESS, "Fudan FM1208-10"); PrintAndLogEx(SUCCESS, "Fudan FM1208-10");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x28 && memcmp(blockdata + 5, "\x28\x04\x00\x90\x53\xB7\x0C\x00\x00\x00\x00", 11) == 0) { && card.sak == 0x28 && memcmp(blockdata + 5, "\x28\x04\x00\x90\x53\xB7\x0C\x00\x00\x00\x00", 11) == 0) {
// Note: it also has ATS = // Note: it also has ATS =
// 10 78 80 B0 02 20 90 00 00 00 00 00 + UID + CRC // 10 78 80 B0 02 20 90 00 00 00 00 00 + UID + CRC
PrintAndLogEx(SUCCESS, "Fudan FM1216-137"); PrintAndLogEx(SUCCESS, "Fudan FM1216-137");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x88 && memcmp(blockdata + 5, "\x88\x04\x00\x43", 4) == 0) { && card.sak == 0x88 && memcmp(blockdata + 5, "\x88\x04\x00\x43", 4) == 0) {
PrintAndLogEx(SUCCESS, "Infineon SLE66R35"); PrintAndLogEx(SUCCESS, "Infineon SLE66R35");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x44", 4) == 0) { && card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x44", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5003"); PrintAndLogEx(SUCCESS, "NXP MF1ICS5003");
} else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
&& card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x45", 4) == 0) { && card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x45", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5004"); PrintAndLogEx(SUCCESS, "NXP MF1ICS5004");
} else if (fKeyType == MF_KEY_BD) { } else if (fKeyType == MF_KEY_BD) {
PrintAndLogEx(SUCCESS, _RED_("Unknown card with backdoor, please report details!")); PrintAndLogEx(SUCCESS, _RED_("Unknown card with backdoor, please report details!"));

View file

@ -466,7 +466,7 @@ static void piv_print_fascn(const uint8_t *buf, const size_t len, int level) {
PrintAndLogEx(NORMAL, "%s" NOLF, encoded[tmp & 0x1f]); PrintAndLogEx(NORMAL, "%s" NOLF, encoded[tmp & 0x1f]);
} }
uint8_t lrc = buf[24] & 0x1f; uint8_t lrc = buf[24] & 0x1f;
PrintAndLogEx(NORMAL, " LRC=[" _YELLOW_("%02" PRIx8 ) "]", lrc); PrintAndLogEx(NORMAL, " LRC=[" _YELLOW_("%02" PRIx8) "]", lrc);
} }
static bool piv_tag_dump(const struct tlv *tlv, int level) { static bool piv_tag_dump(const struct tlv *tlv, int level) {

View file

@ -3242,23 +3242,20 @@
"command": "hf iclass configcard", "command": "hf iclass configcard",
"description": "Manage reader configuration card via Cardhelper or internal database, The generated config card will be uploaded to device emulator memory. You can start simulating `hf iclass sim -t 3` or use the emul commands", "description": "Manage reader configuration card via Cardhelper or internal database, The generated config card will be uploaded to device emulator memory. You can start simulating `hf iclass sim -t 3` or use the emul commands",
"notes": [ "notes": [
"hf iclass configcard -l -> download config card settings from cardhelper",
"hf iclass configcard -p -> print all config cards in the database", "hf iclass configcard -p -> print all config cards in the database",
"hf iclass configcard --ci 1 -> view config card setting in slot 1", "hf iclass configcard --g 0 -> generate config file with option 0"
"hf iclass configcard -g --ci 0 -> generate config file from slot 0"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help This help", "-h, --help This help",
"--ci <dec> use config slot at index", "--g <dec> use config option",
"--ki <dec> Card Key - index to select key from memory 'hf iclass managekeys'", "--ki <dec> Card Key - index to select key from memory 'hf iclass managekeys'",
"--krki <dec> Elite Keyroll Key - index to select key from memory 'hf iclass managekeys'", "--eki <dec> Elite Key - index to select key from memory 'hf iclass managekeys'",
"--mrki <dec> Standard Master Key - index to select key from memory 'hf iclass managekeys'",
"--elite Use elite key for the the Card Key ki", "--elite Use elite key for the the Card Key ki",
"-g generate card dump file",
"-l load available cards",
"-p print available cards" "-p print available cards"
], ],
"usage": "hf iclass configcard [-hglp] [--ci <dec>] [--ki <dec>] [--krki <dec>] [--elite]" "usage": "hf iclass configcard [-hp] [--g <dec>] [--ki <dec>] [--eki <dec>] [--mrki <dec>] [--elite]"
}, },
"hf iclass creditepurse": { "hf iclass creditepurse": {
"command": "hf iclass creditepurse", "command": "hf iclass creditepurse",
@ -5175,9 +5172,10 @@
"-b, --keyb use key B for access printing sectors (by default: key A)", "-b, --keyb use key B for access printing sectors (by default: key A)",
"--be (optional, BigEndian)", "--be (optional, BigEndian)",
"--dch decode Card Holder information", "--dch decode Card Holder information",
"-f, --file <fn> load dump file and decode MAD" "-f, --file <fn> load dump file and decode MAD",
"--force force decode (skip key check)"
], ],
"usage": "hf mf mad [-hvb] [--aid <hex>] [-k <hex>] [--be] [--dch] [-f <fn>]" "usage": "hf mf mad [-hvb] [--aid <hex>] [-k <hex>] [--be] [--dch] [-f <fn>] [--force]"
}, },
"hf mf nack": { "hf mf nack": {
"command": "hf mf nack", "command": "hf mf nack",
@ -12244,7 +12242,7 @@
"--aid <hex> Applet ID to select. By default A0000003080000100 will be used", "--aid <hex> Applet ID to select. By default A0000003080000100 will be used",
"--nonce <hex> Nonce to sign.", "--nonce <hex> Nonce to sign.",
"--slot <dec id> Slot number. Default will be 0x9E (card auth cert).", "--slot <dec id> Slot number. Default will be 0x9E (card auth cert).",
"--alg <dec> Algorithm to use to sign. Example values: 06=RSA-1024, 07=RSA-2048, 11=ECC-P256 (default), 14=ECC-P384" "--alg <dec> Algorithm to use to sign. Example values: 06=RSA-1024, 07=RSA-2048, 17=ECC-P256 (default), 20=ECC-P384"
], ],
"usage": "piv sign [-hskatw] [--aid <hex>] --nonce <hex> [--slot <dec id>] [--alg <dec>]" "usage": "piv sign [-hskatw] [--aid <hex>] --nonce <hex> [--slot <dec id>] [--alg <dec>]"
}, },
@ -13005,6 +13003,6 @@
"metadata": { "metadata": {
"commands_extracted": 749, "commands_extracted": 749,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2024-11-02T14:09:48" "extracted_on": "2024-11-15T13:26:34"
} }
} }

View file

@ -413,7 +413,7 @@ Check column "offline" for their availability.
|`hf iclass esave `|N |`Save emulator memory to file` |`hf iclass esave `|N |`Save emulator memory to file`
|`hf iclass esetblk `|N |`Set emulator memory block data` |`hf iclass esetblk `|N |`Set emulator memory block data`
|`hf iclass eview `|N |`View emulator memory` |`hf iclass eview `|N |`View emulator memory`
|`hf iclass configcard `|N |`Reader configuration card` |`hf iclass configcard `|N |`Reader configuration card generator`
|`hf iclass calcnewkey `|Y |`Calc diversified keys (blocks 3 & 4) to write new keys` |`hf iclass calcnewkey `|Y |`Calc diversified keys (blocks 3 & 4) to write new keys`
|`hf iclass encode `|Y |`Encode binary wiegand to block 7` |`hf iclass encode `|Y |`Encode binary wiegand to block 7`
|`hf iclass encrypt `|Y |`Encrypt given block data` |`hf iclass encrypt `|Y |`Encrypt given block data`