diff --git a/utils/nfc-mfclassic.1 b/utils/nfc-mfclassic.1 index 34083c6..0be3871 100644 --- a/utils/nfc-mfclassic.1 +++ b/utils/nfc-mfclassic.1 @@ -5,6 +5,7 @@ nfc-mfclassic \- MIFARE Classic command line tool .B nfc-mfclassic .RI \fR\fBf\fR|\fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR .RI \fR\fBa\fR|\fR\fBA\fR|\fBb\fR\fR|\fBB\fR +.RI \fR\fBu\fR\fR|\fBU\fR<\fBuid\fR>\fR .IR DUMP .RI [ .IR KEYS @@ -56,6 +57,15 @@ or .B B ). +When using multiple tags infront of a reader, the +.B U +option can be used to supply the UID of tag to be read or written. Append the +hexadecimal UID to the U option. For example U01ab23cd for the 4 byte UID +0x01 0xab 0x23 0xcd. Using the +.B u +parameter instead will use whatever libnfc decides which generally is the lowest +UID. + *** Note that .B W and @@ -90,6 +100,13 @@ Halt on errors ( B ). .TP +.BR u " | " U +Use the default UID ( +.B u +) or supply a valid 4 byte UID ( +.B U +). +.TP .IR DUMP MiFare Dump (MFD) used to write (card to MFD) or (MFD to card) .TP diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index f9a27b5..56d5717 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -491,26 +491,29 @@ static void print_usage(const char *pcProgramName) { printf("Usage: "); - printf("%s f|r|R|w|W a|b [ [f]]\n", pcProgramName); + printf("%s f|r|R|w|W a|b u|U<01ab23cd> [ [f]]\n", pcProgramName); 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"); 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(" 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"); printf(" - MiFare Dump (MFD) that contain the keys (optional)\n"); printf(" f - Force using the keyfile even if UID does not match (optional)\n"); printf("Examples: \n\n"); printf(" Read card to file, using key A:\n\n"); - printf(" %s r a mycard.mfd\n\n", pcProgramName); + printf(" %s r a u mycard.mfd\n\n", pcProgramName); printf(" Write file to blank card, using key A:\n\n"); - printf(" %s w a mycard.mfd\n\n", pcProgramName); + printf(" %s w a u mycard.mfd\n\n", pcProgramName); printf(" Write new data and/or keys to previously written card, using key A:\n\n"); - printf(" %s w a newdata.mfd mycard.mfd\n\n", pcProgramName); + printf(" %s w a u newdata.mfd mycard.mfd\n\n", pcProgramName); printf(" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n"); - printf(" %s f A dummy.mfd keyfile.mfd f\n", pcProgramName); - printf(" %s f B dummy.mfd keyfile.mfd f\n\n", pcProgramName); + printf(" %s f A u dummy.mfd keyfile.mfd f\n", pcProgramName); + printf(" %s f B u dummy.mfd keyfile.mfd f\n\n", pcProgramName); + printf(" Read card to file, using key A and uid 0x01 0xab 0x23 0xcd:\n\n"); + printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName); } int @@ -518,6 +521,9 @@ main(int argc, const char *argv[]) { action_t atAction = ACTION_USAGE; uint8_t *pbtUID; + uint8_t _tag_uid[4]; + uint8_t *tag_uid = _tag_uid; + int unlock = 0; if (argc < 2) { @@ -526,7 +532,7 @@ main(int argc, const char *argv[]) } const char *command = argv[1]; - if (argc < 4) { + if (argc < 5) { print_usage(argv[0]); exit(EXIT_FAILURE); } @@ -536,8 +542,8 @@ 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 > 4); - bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); + bUseKeyFile = (argc > 5); + 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; if (strcmp(command, "W") == 0) @@ -545,8 +551,26 @@ 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 > 4); - bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); + bUseKeyFile = (argc > 5); + bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0)); + } + if (argv[3][0] == 'U') { + unsigned long int _uid; + + if (strlen(argv[3]) != 9) { + printf("Error, illegal tag specification, use U01ab23cd for example.\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + _uid = strtoul(argv[3] + 1, NULL, 16); + tag_uid[0] = (_uid & 0xff000000UL) >> 24; + tag_uid[1] = (_uid & 0x00ff0000UL) >> 16; + tag_uid[2] = (_uid & 0x0000ff00UL) >> 8; + tag_uid[3] = (_uid & 0x000000ffUL); + printf("Attempting to use specific UID: 0x%2x 0x%2x 0x%2x 0x%2x\n", + tag_uid[0], tag_uid[1], tag_uid[2], tag_uid[3]); + } else { + tag_uid = NULL; } if (atAction == ACTION_USAGE) { @@ -555,13 +579,13 @@ main(int argc, const char *argv[]) } // We don't know yet the card size so let's read only the UID from the keyfile for the moment if (bUseKeyFile) { - FILE *pfKeys = fopen(argv[4], "rb"); + FILE *pfKeys = fopen(argv[5], "rb"); if (pfKeys == NULL) { - printf("Could not open keys file: %s\n", argv[4]); + printf("Could not open keys file: %s\n", argv[5]); exit(EXIT_FAILURE); } if (fread(&mtKeys, 1, 4, pfKeys) != 4) { - printf("Could not read UID from key file: %s\n", argv[4]); + printf("Could not read UID from key file: %s\n", argv[5]); fclose(pfKeys); exit(EXIT_FAILURE); } @@ -606,7 +630,10 @@ main(int argc, const char *argv[]) printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); // Try to find a MIFARE Classic tag - if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { + 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"); nfc_close(pnd); nfc_exit(context); @@ -668,13 +695,13 @@ main(int argc, const char *argv[]) printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16); if (bUseKeyFile) { - FILE *pfKeys = fopen(argv[4], "rb"); + FILE *pfKeys = fopen(argv[5], "rb"); if (pfKeys == NULL) { - printf("Could not open keys file: %s\n", argv[4]); + printf("Could not open keys file: %s\n", argv[5]); exit(EXIT_FAILURE); } if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) { - printf("Could not read keys file: %s\n", argv[4]); + printf("Could not read keys file: %s\n", argv[5]); fclose(pfKeys); exit(EXIT_FAILURE); } @@ -684,16 +711,16 @@ main(int argc, const char *argv[]) if (atAction == ACTION_READ) { memset(&mtDump, 0x00, sizeof(mtDump)); } else { - FILE *pfDump = fopen(argv[3], "rb"); + FILE *pfDump = fopen(argv[4], "rb"); if (pfDump == NULL) { - printf("Could not open dump file: %s\n", argv[3]); + printf("Could not open dump file: %s\n", argv[4]); exit(EXIT_FAILURE); } if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) { - printf("Could not read dump file: %s\n", argv[3]); + printf("Could not read dump file: %s\n", argv[4]); fclose(pfDump); exit(EXIT_FAILURE); } @@ -703,17 +730,17 @@ main(int argc, const char *argv[]) if (atAction == ACTION_READ) { if (read_card(unlock)) { - printf("Writing data to file: %s ...", argv[3]); + printf("Writing data to file: %s ...", argv[4]); fflush(stdout); - FILE *pfDump = fopen(argv[3], "wb"); + FILE *pfDump = fopen(argv[4], "wb"); if (pfDump == NULL) { - printf("Could not open dump file: %s\n", argv[3]); + printf("Could not open dump file: %s\n", argv[4]); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) { - printf("\nCould not write to file: %s\n", argv[3]); + printf("\nCould not write to file: %s\n", argv[4]); fclose(pfDump); nfc_close(pnd); nfc_exit(context);