nfc-mfclassic: Add option to specify key

The nfc-mfclassic utility will pick a seemingly random (the libnfc
default which seems to be the lowest UID). With the new (u|U) options
it is now possible to force a UID and thus write a specific tag, which
can be very useful if there are more then one tag visible.

Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
This commit is contained in:
Olliver Schinagl 2016-02-18 18:28:08 +01:00
parent 898f3a4d2f
commit e1a25a8203
2 changed files with 69 additions and 25 deletions

View file

@ -5,6 +5,7 @@ nfc-mfclassic \- MIFARE Classic command line tool
.B nfc-mfclassic .B nfc-mfclassic
.RI \fR\fBf\fR|\fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR .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\fBa\fR|\fR\fBA\fR|\fBb\fR\fR|\fBB\fR
.RI \fR\fBu\fR\fR|\fBU\fR<\fBuid\fR>\fR
.IR DUMP .IR DUMP
.RI [ .RI [
.IR KEYS .IR KEYS
@ -56,6 +57,15 @@ or
.B B .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 *** Note that
.B W .B W
and and
@ -90,6 +100,13 @@ Halt on errors (
B B
). ).
.TP .TP
.BR u " | " U
Use the default UID (
.B u
) or supply a valid 4 byte UID (
.B U<uid>
).
.TP
.IR DUMP .IR DUMP
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card) MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
.TP .TP

View file

@ -491,26 +491,29 @@ static void
print_usage(const char *pcProgramName) print_usage(const char *pcProgramName)
{ {
printf("Usage: "); printf("Usage: ");
printf("%s f|r|R|w|W a|b <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName); printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [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(" 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(" *** 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(" *** 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(" *** 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 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(" 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(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n"); printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
printf(" f - Force using the keyfile even if UID does not match (optional)\n"); printf(" f - Force using the keyfile even if UID does not match (optional)\n");
printf("Examples: \n\n"); printf("Examples: \n\n");
printf(" Read card to file, using key A:\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(" 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(" 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(" 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 A u dummy.mfd keyfile.mfd f\n", pcProgramName);
printf(" %s f B dummy.mfd keyfile.mfd f\n\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 int
@ -518,6 +521,9 @@ main(int argc, const char *argv[])
{ {
action_t atAction = ACTION_USAGE; action_t atAction = ACTION_USAGE;
uint8_t *pbtUID; uint8_t *pbtUID;
uint8_t _tag_uid[4];
uint8_t *tag_uid = _tag_uid;
int unlock = 0; int unlock = 0;
if (argc < 2) { if (argc < 2) {
@ -526,7 +532,7 @@ main(int argc, const char *argv[])
} }
const char *command = argv[1]; const char *command = argv[1];
if (argc < 4) { if (argc < 5) {
print_usage(argv[0]); print_usage(argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -536,8 +542,8 @@ main(int argc, const char *argv[])
unlock = 1; unlock = 1;
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 4); bUseKeyFile = (argc > 5);
bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) { } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
atAction = ACTION_WRITE; atAction = ACTION_WRITE;
if (strcmp(command, "W") == 0) if (strcmp(command, "W") == 0)
@ -545,8 +551,26 @@ main(int argc, const char *argv[])
bFormatCard = (strcmp(command, "f") == 0); bFormatCard = (strcmp(command, "f") == 0);
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a'; bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2])); bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 4); bUseKeyFile = (argc > 5);
bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0)); 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) { 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 // We don't know yet the card size so let's read only the UID from the keyfile for the moment
if (bUseKeyFile) { if (bUseKeyFile) {
FILE *pfKeys = fopen(argv[4], "rb"); FILE *pfKeys = fopen(argv[5], "rb");
if (pfKeys == NULL) { 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); exit(EXIT_FAILURE);
} }
if (fread(&mtKeys, 1, 4, pfKeys) != 4) { 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); fclose(pfKeys);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -606,7 +630,10 @@ main(int argc, const char *argv[])
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
// Try to find a MIFARE Classic tag // 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"); printf("Error: no tag was found\n");
nfc_close(pnd); nfc_close(pnd);
nfc_exit(context); 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); printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16);
if (bUseKeyFile) { if (bUseKeyFile) {
FILE *pfKeys = fopen(argv[4], "rb"); FILE *pfKeys = fopen(argv[5], "rb");
if (pfKeys == NULL) { 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); exit(EXIT_FAILURE);
} }
if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) { 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); fclose(pfKeys);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -684,16 +711,16 @@ main(int argc, const char *argv[])
if (atAction == ACTION_READ) { if (atAction == ACTION_READ) {
memset(&mtDump, 0x00, sizeof(mtDump)); memset(&mtDump, 0x00, sizeof(mtDump));
} else { } else {
FILE *pfDump = fopen(argv[3], "rb"); FILE *pfDump = fopen(argv[4], "rb");
if (pfDump == NULL) { 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); exit(EXIT_FAILURE);
} }
if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) { 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); fclose(pfDump);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -703,17 +730,17 @@ main(int argc, const char *argv[])
if (atAction == ACTION_READ) { if (atAction == ACTION_READ) {
if (read_card(unlock)) { if (read_card(unlock)) {
printf("Writing data to file: %s ...", argv[3]); printf("Writing data to file: %s ...", argv[4]);
fflush(stdout); fflush(stdout);
FILE *pfDump = fopen(argv[3], "wb"); FILE *pfDump = fopen(argv[4], "wb");
if (pfDump == NULL) { 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_close(pnd);
nfc_exit(context); nfc_exit(context);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) { 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); fclose(pfDump);
nfc_close(pnd); nfc_close(pnd);
nfc_exit(context); nfc_exit(context);