From a28a53761079e8d29d326dad03007497981c1737 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Tue, 23 Jun 2020 14:08:04 +0100 Subject: [PATCH 01/17] partial fix of nfc-mfclassic which only writes first sector of each block and not sector 1,2,3 unles 'unlocked' write - debuggers still in! --- utils/nfc-mfclassic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 6530224..a3837c9 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -426,7 +426,8 @@ write_card(int write_block_zero) printf("Writing %d blocks |", uiBlocks + 1); // Completely write the card, end to start, but skipping block 0 - for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) { + for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { + printf("{%d}",uiBlock); // Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { if (bFailure) { @@ -438,6 +439,7 @@ write_card(int write_block_zero) bFailure = false; } + printf("[%d]",uiBlock); fflush(stdout); // Try to authenticate for the current sector @@ -450,8 +452,10 @@ write_card(int write_block_zero) return false; } } + } if (is_trailer_block(uiBlock)) { + printf("t"); if (bFormatCard) { // Copy the default key and reset the access bits memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA)); @@ -471,7 +475,7 @@ write_card(int write_block_zero) } } else { // The first block 0x00 is read only, skip this - if (uiBlock == 0 && !write_block_zero && !magic2) + if (uiBlock == 0 && !write_block_zero && !magic2) continue; // Make sure a earlier write did not fail @@ -482,6 +486,7 @@ write_card(int write_block_zero) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); + printf("(%d)%d",uiBlock,sizeof(mp.mpd.abtData)); // do not write a block 0 with incorrect BCC - card will be made invalid! if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { @@ -499,7 +504,7 @@ write_card(int write_block_zero) printf("Failure during write process.\n"); } } - } + //} // Show if the write went well for each block print_success_or_failure(bFailure, &uiWriteBlocks); if ((! bTolerateFailures) && bFailure) From e560689f60a057963e1b359078ed092c71350a52 Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Wed, 24 Jun 2020 11:11:21 +0100 Subject: [PATCH 02/17] restore original block count logic and add debuggers for block0 --- utils/nfc-mfclassic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index a3837c9..9af6a91 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -426,7 +426,7 @@ write_card(int write_block_zero) printf("Writing %d blocks |", uiBlocks + 1); // Completely write the card, end to start, but skipping block 0 - for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { + for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) { printf("{%d}",uiBlock); // Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { @@ -515,6 +515,7 @@ write_card(int write_block_zero) if (write_block_zero || magic2 || magic3) { for (uiBlock = 0; uiBlock < 4; uiBlock++) { + printf("-%d-",uiBlock); // The first block 0x00 is read only, skip this if (uiBlock == 0) { //If the card is not magic, we're gonna skip over @@ -555,6 +556,7 @@ write_card(int write_block_zero) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); + printf("<%d>",uiBlock); // do not write a block 0 with incorrect BCC - card will be made invalid! if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { From 7b6ff73c4b969965dd8a8e221e150d51308953be Mon Sep 17 00:00:00 2001 From: Adam Laurie Date: Wed, 24 Jun 2020 20:38:01 +0100 Subject: [PATCH 03/17] only test DirectWrite write if we need to. only write block 0 if specifically requested to. --- utils/nfc-mfclassic.c | 88 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 9af6a91..02dbb6d 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -325,7 +325,7 @@ read_card(int read_unlocked) if (read_unlocked) { //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't //need to use the R mode. We'll trigger a warning and let them proceed. - if (magic2) { + if (magic2 || magic3) { printf("Note: This card does not require an unlocked read (R) \n"); read_unlocked = 0; } else { @@ -411,25 +411,18 @@ write_card(int write_block_zero) //Determine if we have to unlock the card if (write_block_zero) { - //If the user is attempting an unlocked write, but has a direct-write type magic card, they don't - //need to use the W mode. We'll trigger a warning and let them proceed. - if (magic2) { - printf("Note: This card does not require an unlocked write (W) \n"); - write_block_zero = 0; - } else { - //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out. + if (!magic2 && !magic3) { if (!unlock_card()) { return false; } } } - printf("Writing %d blocks |", uiBlocks + 1); - // Completely write the card, end to start, but skipping block 0 - for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) { - printf("{%d}",uiBlock); + printf("Writing %d blocks |", uiBlocks + write_block_zero); + // Completely write the card, but skipping block 0 + for (uiBlock = 1; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block - if (is_first_block(uiBlock)) { + if (uiBlock == 1 || is_first_block(uiBlock)) { if (bFailure) { // When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { @@ -439,7 +432,6 @@ write_card(int write_block_zero) bFailure = false; } - printf("[%d]",uiBlock); fflush(stdout); // Try to authenticate for the current sector @@ -455,7 +447,6 @@ write_card(int write_block_zero) } if (is_trailer_block(uiBlock)) { - printf("t"); if (bFormatCard) { // Copy the default key and reset the access bits memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA)); @@ -474,10 +465,6 @@ write_card(int write_block_zero) bFailure = true; } } else { - // The first block 0x00 is read only, skip this - if (uiBlock == 0 && !write_block_zero && !magic2) - continue; - // Make sure a earlier write did not fail if (!bFailure) { // Try to write the data block @@ -486,7 +473,6 @@ write_card(int write_block_zero) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); - printf("(%d)%d",uiBlock,sizeof(mp.mpd.abtData)); // do not write a block 0 with incorrect BCC - card will be made invalid! if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { @@ -511,20 +497,9 @@ write_card(int write_block_zero) return false; } - //Write Block 0 if necessary - if (write_block_zero || magic2 || magic3) { - for (uiBlock = 0; uiBlock < 4; uiBlock++) { - - printf("-%d-",uiBlock); - // The first block 0x00 is read only, skip this - if (uiBlock == 0) { - //If the card is not magic, we're gonna skip over - if (write_block_zero || magic2 || magic3) { - //NOP - } else { - continue; - } - } + //Write Block 0 if requested to do so + if (write_block_zero) { + for (uiBlock = 0; uiBlock < 1; uiBlock++) { if (is_first_block(uiBlock)) { if (bFailure) { @@ -556,15 +531,12 @@ write_card(int write_block_zero) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); - printf("<%d>",uiBlock); // do not write a block 0 with incorrect BCC - card will be made invalid! - if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { printf("!\nError: incorrect BCC in MFD file!\n"); printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); return false; } - } if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; printf("Failure to write to data block %i\n", uiBlock); @@ -574,13 +546,12 @@ write_card(int write_block_zero) printf("Failure during write process.\n"); } - // Show if the write went well for each block + // Show if the write went well for block 0 print_success_or_failure(bFailure, &uiWriteBlocks); if ((! bTolerateFailures) && bFailure) return false; } - } printf("|\n"); @@ -627,7 +598,7 @@ print_usage(const char *pcProgramName) } -static bool is_directwrite(void) +static bool is_directwrite(bool test_write) { printf("Checking if Badge is DirectWrite...\n"); @@ -664,6 +635,9 @@ static bool is_directwrite(void) return false; } + if(!test_write) + return true; + printf(" Attempt to write Block 0 ...\n"); memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0)); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) { @@ -771,6 +745,14 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); }; + // Drop the field for a while, so can be reset + if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, true) < 0) { + nfc_perror(pnd, "nfc_device_set_property_bool activate field"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + // Let the reader only try once to find a tag if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) { nfc_perror(pnd, "nfc_device_set_property_bool"); @@ -786,11 +768,24 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } + // Configure the CRC and Parity settings + if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) { + nfc_perror(pnd, "nfc_device_set_property_bool crc"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + if (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true) < 0) { + nfc_perror(pnd, "nfc_device_set_property_bool parity"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); // Try to find a MIFARE Classic tag int tags; - tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt); if (tags <= 0) { printf("Error: no tag was found\n"); @@ -799,7 +794,8 @@ main(int argc, const char *argv[]) exit(EXIT_FAILURE); } // Test if we are dealing with a MIFARE compatible tag - if ((nt.nti.nai.btSak & 0x08) == 0) { + if (((nt.nti.nai.btSak & 0x08) == 0) && (nt.nti.nai.btSak != 0x01)) { +// if ((nt.nti.nai.btSak & 0x08) == 0) { printf("Warning: tag is probably not a MFC!\n"); } @@ -857,12 +853,15 @@ main(int argc, const char *argv[]) //If size is 4k check for direct-write card if (uiBlocks == 0xff) { - if (is_directwrite()) { + if (is_directwrite(atAction == ACTION_WRITE)) { printf("Card is DirectWrite\n"); magic3 = true; - unlock = 0; } else { printf("Card is not DirectWrite\n"); + // reset after error + if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) { + ERR("tag was removed"); + } } } @@ -871,7 +870,6 @@ main(int argc, const char *argv[]) pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) { printf("Card appears to be a One Time Write Card..\n"); magic3 = true; - unlock = 0; } From 5a87f1f3db2a30a25ec74fccf2d3f42952c474ef Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 25 Jun 2020 19:29:38 +0200 Subject: [PATCH 04/17] Splitting block 0 writing and other block writing, not needed anymore --- utils/nfc-mfclassic.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 02dbb6d..6c90458 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -473,14 +473,6 @@ write_card(int write_block_zero) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); - // do not write a block 0 with incorrect BCC - card will be made invalid! - if (uiBlock == 0) { - if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { - printf("!\nError: incorrect BCC in MFD file!\n"); - printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); - return false; - } - } if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; printf("Failure to write to data block %i\n", uiBlock); From dd96571f8895139e7fdbcb29b62ac542eaeec79e Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 25 Jun 2020 19:49:04 +0200 Subject: [PATCH 05/17] no need to loop, only one block --- utils/nfc-mfclassic.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 6c90458..3c3638c 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -491,17 +491,16 @@ write_card(int write_block_zero) //Write Block 0 if requested to do so if (write_block_zero) { - for (uiBlock = 0; uiBlock < 1; uiBlock++) { - - if (is_first_block(uiBlock)) { - if (bFailure) { - // When a failure occured we need to redo the anti-collision - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + uiBlock = 0; + is_first_block(0); + if (bFailure) { + // When a failure occured we need to redo the anti-collision + if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { printf("!\nError: tag was removed\n"); return false; - } - bFailure = false; } + bFailure = false; + } fflush(stdout); // Try to authenticate for the current sector @@ -509,12 +508,11 @@ write_card(int write_block_zero) // If we're writing to a One Time Write, we need to authenticate // If we're writing something else, we'll need to authenticate if ((write_block_zero && magic3) || !write_block_zero) { - if (!authenticate(uiBlock) && !bTolerateFailures) { - printf("!\nError: authentication failed for block %02x\n", uiBlock); + if (!authenticate(0) && !bTolerateFailures) { + printf("!\nError: authentication failed for block 00\n"); return false; } } - } // Make sure a earlier write did not fail if (!bFailure) { @@ -531,7 +529,7 @@ write_card(int write_block_zero) } if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; - printf("Failure to write to data block %i\n", uiBlock); + printf("Failure to write to data block 0\n"); } } else { @@ -544,7 +542,6 @@ write_card(int write_block_zero) return false; } - } printf("|\n"); printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); From 3f4b7a037a56c734ec30dde366cfa17cbb36ee43 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 25 Jun 2020 23:10:06 +0200 Subject: [PATCH 06/17] add rewrite support for gen2 tags with W command add rewrite support for gen2 tags with W command --- utils/nfc-mfclassic.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 3c3638c..a159990 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -260,6 +260,8 @@ unlock_card(void) // now send unlock if (!transmit_bits(abtUnlock1, 7)) { printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); + printf("Trying to rewrite block 0 on a gen2 tag.\n"); + magic2 = true; } else { if (transmit_bytes(abtUnlock2, 1)) { printf("Card unlocked\n"); @@ -270,6 +272,15 @@ unlock_card(void) } // reset reader + if (!unlocked) { + if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) { + printf("Error: tag was removed\n"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + } + return true; + } // Configure the CRC if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) { nfc_perror(pnd, "nfc_device_set_property_bool"); @@ -438,7 +449,7 @@ write_card(int write_block_zero) // If we are are writing to a chinese magic card, we've already unlocked // If we're writing to a One Time Write card, we need to authenticate // If we're writing something else, we'll need to authenticate - if ((write_block_zero && magic3) || !write_block_zero) { + if ((write_block_zero && (magic2 || magic3)) || !write_block_zero) { if (!authenticate(uiBlock) && !bTolerateFailures) { printf("!\nError: authentication failed for block %02x\n", uiBlock); return false; @@ -507,7 +518,7 @@ write_card(int write_block_zero) // If we are are writing to a chinese magic card, we've already unlocked // If we're writing to a One Time Write, we need to authenticate // If we're writing something else, we'll need to authenticate - if ((write_block_zero && magic3) || !write_block_zero) { + if ((write_block_zero && (magic2 || magic3)) || !write_block_zero) { if (!authenticate(0) && !bTolerateFailures) { printf("!\nError: authentication failed for block 00\n"); return false; From 4e922e81942c4f339d5b014c769f4591620add44 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 25 Jun 2020 23:32:03 +0200 Subject: [PATCH 07/17] sends lib log to /dev/null in posix and added option (v) to reactivate There in an error handling and messaging inside --- utils/nfc-mfclassic.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index a159990..28444c5 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -54,6 +54,12 @@ #include #include +#ifndef _WIN32 +#include +#include +#include +#endif + #include #include "mifare.h" @@ -571,7 +577,11 @@ static void print_usage(const char *pcProgramName) { printf("Usage: "); + #ifndef _WIN32 + printf("%s f|r|R|w|W a|b u|U<01ab23cd> [ [f] [v]]\n", pcProgramName); + #else printf("%s f|r|R|w|W a|b u|U<01ab23cd> [ [f]]\n", pcProgramName); + #endif printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n"); printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n"); printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); @@ -582,7 +592,9 @@ print_usage(const char *pcProgramName) printf(" - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf(" - MiFare Dump (MFD) that contain the keys (optional)\n"); printf(" f - Force using the keyfile even if UID does not match (optional)\n"); - + #ifndef _WIN32 + printf(" v - Sends libnfc log output to console (optional)\n"); + #endif printf("Examples: \n\n"); printf(" Read card to file, using key A:\n\n"); printf(" %s r a u mycard.mfd\n\n", pcProgramName); @@ -706,6 +718,21 @@ main(int argc, const char *argv[]) tag_uid = NULL; } + #ifndef _WIN32 + // Send noise from lib to /dev/null + bool verbose = false; + if (argv[7]) { + if (strcmp(argv[7], "v") == 0) verbose = true; + } else { + if (strcmp(argv[6], "v") == 0) verbose = true; + } + if (!verbose) { + int fd = open("/dev/null", O_WRONLY); + dup2(fd, 2); + close(fd); + } + #endif + if (atAction == ACTION_USAGE) { print_usage(argv[0]); exit(EXIT_FAILURE); From 2b21d87e8efd77d912c794c78f5acc794ad03d46 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 25 Jun 2020 23:45:17 +0200 Subject: [PATCH 08/17] add gen2 desc to help add gen2 desc to help --- utils/nfc-mfclassic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 28444c5..28e4a1b 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -587,6 +587,7 @@ print_usage(const char *pcProgramName) printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n"); + printf(" *** unlocking (w) also works for rewriting block 0 in gen2 clones\n"); printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n"); printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n"); printf(" - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); From 7a5e654309b0f993338c3c9739dc8515394f632a Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 25 Jun 2020 23:56:38 +0200 Subject: [PATCH 09/17] hardcoded values --- utils/nfc-mfclassic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 28e4a1b..6b9366f 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -644,7 +644,7 @@ static bool is_directwrite(bool test_write) printf(" Original UID: %02x%02x%02x%02x\n", original_b0[0], original_b0[1], original_b0[2], original_b0[3]); } else { - printf("!\nError: unable to read block 0x%02x\n", 0); + printf("!\nError: unable to read block 0x00\n"); return false; } @@ -654,7 +654,7 @@ static bool is_directwrite(bool test_write) printf(" Attempt to write Block 0 ...\n"); memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0)); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) { - printf("Failure to write to data block %i\n", 0); + printf("Failure to write to data block 0\n"); return false; } printf(" Block 0 written successfully\n"); From 02f0f6b29033b3e6ef3cd498d8a400c2bb0f6ecb Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 26 Jun 2020 01:28:57 +0200 Subject: [PATCH 10/17] add verbose case add verbose case --- utils/nfc-mfclassic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 6b9366f..b3e1b1f 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -688,7 +688,7 @@ main(int argc, const char *argv[]) unlock = 1; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); - bUseKeyFile = (argc > 5); + bUseKeyFile = (argc > 5) && strcmp(argv[5], "v"); bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { atAction = ACTION_WRITE; @@ -697,7 +697,7 @@ main(int argc, const char *argv[]) bFormatCard = (strcmp(command, "f") == 0); bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); - bUseKeyFile = (argc > 5); + bUseKeyFile = (argc > 5) && strcmp(argv[5], "v"); bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); } if (argv[3][0] == 'U') { @@ -725,7 +725,7 @@ main(int argc, const char *argv[]) if (argv[7]) { if (strcmp(argv[7], "v") == 0) verbose = true; } else { - if (strcmp(argv[6], "v") == 0) verbose = true; + if ((strcmp(argv[6], "v")) || (strcmp(argv[5], "v")) == 0) verbose = true; } if (!verbose) { int fd = open("/dev/null", O_WRONLY); From 3c55b8746b4f5a899642757608c914ae0ae0c4ec Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 26 Jun 2020 01:50:11 +0200 Subject: [PATCH 11/17] swap 0 block write and other blocks write when writing to gen2 and possible on gen3, it writes first block 3 wich is the trailing sector before writing to block 0, so the last write to block 0 fails because authenticate to old keyset --- utils/nfc-mfclassic.c | 109 +++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index b3e1b1f..f39dbe2 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -436,6 +436,61 @@ write_card(int write_block_zero) } printf("Writing %d blocks |", uiBlocks + write_block_zero); + //Write Block 0 if requested to do so + if (write_block_zero) { + uiBlock = 0; + is_first_block(0); + if (bFailure) { + // When a failure occured we need to redo the anti-collision + if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + printf("!\nError: tag was removed\n"); + return false; + } + bFailure = false; + } + + fflush(stdout); + // Try to authenticate for the current sector + // If we are are writing to a chinese magic card, we've already unlocked + // If we're writing to a One Time Write, we need to authenticate + // If we're writing something else, we'll need to authenticate + if ((write_block_zero && (magic2 || magic3)) || !write_block_zero) { + if (!authenticate(0) && !bTolerateFailures) { + printf("!\nError: authentication failed for block 00\n"); + return false; + } + } + + // Make sure a earlier write did not fail + if (!bFailure) { + // Try to write the data block + if (bFormatCard && uiBlock) + memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); + else + memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); + // do not write a block 0 with incorrect BCC - card will be made invalid! + if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { + printf("!\nError: incorrect BCC in MFD file!\n"); + printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); + return false; + } + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { + bFailure = true; + printf("Failure to write to data block 0\n"); + } + + } + else { + printf("Failure during write process.\n"); + } + + // Show if the write went well for block 0 + print_success_or_failure(bFailure, &uiWriteBlocks); + if ((!bTolerateFailures) && bFailure) + return false; + + } + // Completely write the card, but skipping block 0 for (uiBlock = 1; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block @@ -506,60 +561,6 @@ write_card(int write_block_zero) return false; } - //Write Block 0 if requested to do so - if (write_block_zero) { - uiBlock = 0; - is_first_block(0); - if (bFailure) { - // When a failure occured we need to redo the anti-collision - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { - printf("!\nError: tag was removed\n"); - return false; - } - bFailure = false; - } - - fflush(stdout); - // Try to authenticate for the current sector - // If we are are writing to a chinese magic card, we've already unlocked - // If we're writing to a One Time Write, we need to authenticate - // If we're writing something else, we'll need to authenticate - if ((write_block_zero && (magic2 || magic3)) || !write_block_zero) { - if (!authenticate(0) && !bTolerateFailures) { - printf("!\nError: authentication failed for block 00\n"); - return false; - } - } - - // Make sure a earlier write did not fail - if (!bFailure) { - // Try to write the data block - if (bFormatCard && uiBlock) - memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); - else - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); - // do not write a block 0 with incorrect BCC - card will be made invalid! - if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { - printf("!\nError: incorrect BCC in MFD file!\n"); - printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); - return false; - } - if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { - bFailure = true; - printf("Failure to write to data block 0\n"); - } - - } else { - printf("Failure during write process.\n"); - } - - // Show if the write went well for block 0 - print_success_or_failure(bFailure, &uiWriteBlocks); - if ((! bTolerateFailures) && bFailure) - return false; - - } - printf("|\n"); printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); fflush(stdout); From 709ef8381f16588de94d08592670772364f18ffb Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 26 Jun 2020 13:34:50 +0200 Subject: [PATCH 12/17] reinit for retrieving new uid after block 0 write --- utils/nfc-mfclassic.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index f39dbe2..5278a37 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -490,7 +490,18 @@ write_card(int write_block_zero) return false; } - + if (magic2 || magic3) { + if (nfc_initiator_init(pnd) < 0) { + nfc_perror(pnd, "nfc_initiator_init"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + }; + if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + printf("!\nError: tag was removed\n"); + return false; + } + } // Completely write the card, but skipping block 0 for (uiBlock = 1; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block From f7b9b0eafa44f97f817387689d09b998e7c49686 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 26 Jun 2020 13:36:18 +0200 Subject: [PATCH 13/17] remove unused stuff for block 0 writing --- utils/nfc-mfclassic.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 5278a37..bb127ff 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -440,14 +440,6 @@ write_card(int write_block_zero) if (write_block_zero) { uiBlock = 0; is_first_block(0); - if (bFailure) { - // When a failure occured we need to redo the anti-collision - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { - printf("!\nError: tag was removed\n"); - return false; - } - bFailure = false; - } fflush(stdout); // Try to authenticate for the current sector @@ -461,12 +453,7 @@ write_card(int write_block_zero) } } - // Make sure a earlier write did not fail - if (!bFailure) { // Try to write the data block - if (bFormatCard && uiBlock) - memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); - else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); // do not write a block 0 with incorrect BCC - card will be made invalid! if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { @@ -478,12 +465,6 @@ write_card(int write_block_zero) bFailure = true; printf("Failure to write to data block 0\n"); } - - } - else { - printf("Failure during write process.\n"); - } - // Show if the write went well for block 0 print_success_or_failure(bFailure, &uiWriteBlocks); if ((!bTolerateFailures) && bFailure) From db957aabdff2123f2a3e32dc650f0dcfa90e49d4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 26 Jun 2020 18:29:01 +0200 Subject: [PATCH 14/17] adds write condition check in unlock_card() --- utils/nfc-mfclassic.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index bb127ff..233ad8a 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -248,7 +248,7 @@ authenticate(uint32_t uiBlock) } static bool -unlock_card(void) +unlock_card(bool write) { // Configure the CRC if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) { @@ -266,8 +266,10 @@ unlock_card(void) // now send unlock if (!transmit_bits(abtUnlock1, 7)) { printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n"); - printf("Trying to rewrite block 0 on a gen2 tag.\n"); - magic2 = true; + if (write) { + printf("Trying to rewrite block 0 on a gen2 tag.\n"); + magic2 = true; + } } else { if (transmit_bytes(abtUnlock2, 1)) { printf("Card unlocked\n"); @@ -333,7 +335,7 @@ get_rats(void) } static bool -read_card(int read_unlocked) +read_card(bool read_unlocked) { int32_t iBlock; bool bFailure = false; @@ -347,7 +349,7 @@ read_card(int read_unlocked) read_unlocked = 0; } else { //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out. - if (!unlock_card()) { + if (!unlock_card(false)) { return false; } } @@ -420,7 +422,7 @@ read_card(int read_unlocked) } static bool -write_card(int write_block_zero) +write_card(bool write_block_zero) { uint32_t uiBlock; bool bFailure = false; @@ -429,7 +431,7 @@ write_card(int write_block_zero) //Determine if we have to unlock the card if (write_block_zero) { if (!magic2 && !magic3) { - if (!unlock_card()) { + if (!unlock_card(true)) { return false; } } @@ -663,7 +665,7 @@ main(int argc, const char *argv[]) uint8_t _tag_uid[4]; uint8_t *tag_uid = _tag_uid; - int unlock = 0; + bool unlock = false; if (argc < 2) { print_usage(argv[0]); @@ -678,7 +680,7 @@ main(int argc, const char *argv[]) if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) { atAction = ACTION_READ; if (strcmp(command, "R") == 0) - unlock = 1; + unlock = true; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bUseKeyFile = (argc > 5) && strcmp(argv[5], "v"); @@ -686,7 +688,7 @@ main(int argc, const char *argv[]) } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { atAction = ACTION_WRITE; if (strcmp(command, "W") == 0) - unlock = 1; + unlock = true; bFormatCard = (strcmp(command, "f") == 0); bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); From 01bc5693d9f8e24b9de908a92d0f1d3bfbddac77 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 26 Jun 2020 19:08:04 +0200 Subject: [PATCH 15/17] another hardcode value --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 233ad8a..952339b 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -620,7 +620,7 @@ static bool is_directwrite(bool test_write) bUseKeyFile = false; // Try to authenticate for the current sector if (!authenticate(0)) { - printf("!\nError: authentication failed for block 0x%02x\n", 0); + printf("!\nError: authentication failed for block 0x00\n"); bUseKeyFile = orig_bUseKeyFile; return false; } From 6921e57fb8da1d859c349282297e0eaf70953258 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 27 Jun 2020 13:33:04 +0200 Subject: [PATCH 16/17] correct typo --- utils/nfc-mfclassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 952339b..65c8375 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -582,7 +582,7 @@ print_usage(const char *pcProgramName) printf(" *** unlocked read does not require authentication and will reveal A and B keys\n"); printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n"); - printf(" *** unlocking (w) also works for rewriting block 0 in gen2 clones\n"); + printf(" *** unlocking (W) also works for rewriting block 0 in gen2 clones\n"); printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n"); printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n"); printf(" - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); From c8fcaea8ab2515086882fad37c3f5ab8ed3cd80a Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 27 Jun 2020 16:17:15 +0200 Subject: [PATCH 17/17] no need to differentiate routines --- utils/nfc-mfclassic.c | 74 +++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index 65c8375..fb39633 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -438,55 +438,12 @@ write_card(bool write_block_zero) } printf("Writing %d blocks |", uiBlocks + write_block_zero); - //Write Block 0 if requested to do so - if (write_block_zero) { - uiBlock = 0; - is_first_block(0); - - fflush(stdout); - // Try to authenticate for the current sector - // If we are are writing to a chinese magic card, we've already unlocked - // If we're writing to a One Time Write, we need to authenticate - // If we're writing something else, we'll need to authenticate - if ((write_block_zero && (magic2 || magic3)) || !write_block_zero) { - if (!authenticate(0) && !bTolerateFailures) { - printf("!\nError: authentication failed for block 00\n"); - return false; - } + // Completely write the card, but skipping block 0 if we don't need to write on it + for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { + //Determine if we have to write block 0 + if (!write_block_zero && uiBlock == 0) { + continue; } - - // Try to write the data block - memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); - // do not write a block 0 with incorrect BCC - card will be made invalid! - if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { - printf("!\nError: incorrect BCC in MFD file!\n"); - printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); - return false; - } - if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { - bFailure = true; - printf("Failure to write to data block 0\n"); - } - // Show if the write went well for block 0 - print_success_or_failure(bFailure, &uiWriteBlocks); - if ((!bTolerateFailures) && bFailure) - return false; - - } - if (magic2 || magic3) { - if (nfc_initiator_init(pnd) < 0) { - nfc_perror(pnd, "nfc_initiator_init"); - nfc_close(pnd); - nfc_exit(context); - exit(EXIT_FAILURE); - }; - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { - printf("!\nError: tag was removed\n"); - return false; - } - } - // Completely write the card, but skipping block 0 - for (uiBlock = 1; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block if (uiBlock == 1 || is_first_block(uiBlock)) { if (bFailure) { @@ -539,11 +496,30 @@ write_card(bool write_block_zero) memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData)); else memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData)); + // do not write a block 0 with incorrect BCC - card will be made invalid! + if (uiBlock == 0) { + if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) { + printf("!\nError: incorrect BCC in MFD file!\n"); + printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); + return false; + } + } if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; printf("Failure to write to data block %i\n", uiBlock); } - + if (uiBlock == 0 && (magic2 || magic3)) { + if (nfc_initiator_init(pnd) < 0) { + nfc_perror(pnd, "nfc_initiator_init"); + nfc_close(pnd); + nfc_exit(context); + exit(EXIT_FAILURE); + }; + if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + printf("!\nError: tag was removed\n"); + return false; + } + } } else { printf("Failure during write process.\n"); }