diff --git a/examples/nfc-mfclassic.1 b/examples/nfc-mfclassic.1 index e39c78d..b508cea 100644 --- a/examples/nfc-mfclassic.1 +++ b/examples/nfc-mfclassic.1 @@ -3,7 +3,7 @@ nfc-mfclassic \- MIFARE Classic command line tool .SH SYNOPSIS .B nfc-mfclassic -.RI \fR\fBr\fR|\fBw\fR\fR|\fBu\fR +.RI \fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR .RI \fR\fBa\fR|\fBb\fR .IR DUMP .IR [KEYS] @@ -27,18 +27,25 @@ to store the keys and data for all sectors. Be cautious that some parts of a Mifare Classic memory are used for r/w access of the rest of the memory, so please read the tag documentation before experimenting too much! -The 'u' option allows writing of special Mifare cards that can be 'unlocked' to allow block 0 +The 'W' option allows writing of special Mifare cards that can be 'unlocked' to allow block 0 to be overwritten. This includes UID and manufacturer data. Take care when amending UIDs to set the correct BCC (UID checksum). Currently only 4 byte UIDs are supported. +Similarly, the 'R' option allows an 'unlocked' read. This bypasses authentication and allows +reading of the Key A and Key B data regardless of ACLs. + +*** Note that 'W' and 'R' options only work on special versions of Mifare 1K cards (Chinese clones). + .SH OPTIONS -.BR r " | " w " | " u +.BR r " | " R " | " w " | " W Perform read from ( .B r +) or unlocked read from ( +.B R ) or write to ( .B w ) or unlocked write to ( -.B u +.B W ) card. .TP .BR a " | " b @@ -65,6 +72,7 @@ are covered by the GNU Lesser General Public License (LGPL), version 3. Roel Verdult Romuald Conty Romain Tartière +Adam Laurie .PP This manual page was written by Romuald Conty . It is licensed under the terms of the GNU GPL (version 2 or later). diff --git a/examples/nfc-mfclassic.c b/examples/nfc-mfclassic.c index e129199..6818437 100644 --- a/examples/nfc-mfclassic.c +++ b/examples/nfc-mfclassic.c @@ -213,13 +213,60 @@ authenticate (uint32_t uiBlock) return false; } +static bool +unlock_card() +{ + printf ("Unlocking card\n"); + + // Configure the CRC + if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + // Use raw send/receive methods + if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + + iso14443a_crc_append(abtHalt, 2); + transmit_bytes (abtHalt, 4); + // now send unlock + if (!transmit_bits (abtUnlock1, 7)) { + printf("unlock failure!\n"); + return false; + } + if (!transmit_bytes (abtUnlock2, 1)) { + printf("unlock failure!\n"); + return false; + } + + // reset reader + // Configure the CRC + if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + // Switch off raw send/receive methods + if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) { + nfc_perror (pnd, "nfc_configure"); + exit (EXIT_FAILURE); + } + return true; +} + static bool -read_card (void) +read_card (int read_unlocked) { int32_t iBlock; bool bFailure = false; uint32_t uiReadBlocks = 0; + if(read_unlocked) + if (!unlock_card()) + return false; + + printf ("Reading out %d blocks |", uiBlocks + 1); // Read the card from end to begin @@ -243,7 +290,7 @@ read_card (void) fflush (stdout); // Try to authenticate for the current sector - if (!authenticate (iBlock)) { + if (!read_unlocked && !authenticate (iBlock)) { printf ("!\nError: authentication failed for block 0x%02x\n", iBlock); return false; } @@ -286,46 +333,9 @@ write_card (int write_block_zero) uint32_t uiWriteBlocks = 0; - if(write_block_zero) { - printf ("Unlocking card\n"); - - // Configure the CRC - if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) { - nfc_perror (pnd, "nfc_configure"); - exit (EXIT_FAILURE); - } - // Use raw send/receive methods - if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) { - nfc_perror (pnd, "nfc_configure"); - exit (EXIT_FAILURE); - } - - iso14443a_crc_append(abtHalt, 2); - transmit_bytes (abtHalt, 4); - // now send unlock - if (!transmit_bits (abtUnlock1, 7)) { - printf("unlock failure!\n"); + if(write_block_zero) + if (!unlock_card()) return false; - } - if (!transmit_bytes (abtUnlock2, 1)) { - printf("unlock failure!\n"); - return false; - } - - // reset reader - // Configure the CRC - if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) { - nfc_perror (pnd, "nfc_configure"); - exit (EXIT_FAILURE); - } - // Switch off raw send/receive methods - if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) { - nfc_perror (pnd, "nfc_configure"); - exit (EXIT_FAILURE); - } - } - - printf ("Writing %d blocks |", uiBlocks + 1); // Write the card from begin to end; @@ -418,18 +428,18 @@ typedef enum { ACTION_READ, ACTION_WRITE, ACTION_EXTRACT, - ACTION_USAGE, - ACTION_WRITE_UNLOCKED + ACTION_USAGE } action_t; static void print_usage (const char *pcProgramName) { printf ("Usage: "); - printf ("%s r|w|u a|b []\n", pcProgramName); - printf (" r|w|u - Perform read from (r) or write to (w) or unlocked write to (u) card\n"); + printf ("%s r|R|w|W a|b []\n", pcProgramName); + printf (" r|R|w|W - Perform read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n"); printf (" *** note that unlocked write will attempt to overwrite block 0 including UID\n"); - printf (" *** and only works with special Mifare 1K cards (Chinese clones)\n"); + printf (" *** unlocked read does not require authentication and will reveal A and B keys\n"); + printf (" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n"); printf (" a|b - Use A or B keys for action\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"); @@ -447,6 +457,7 @@ main (int argc, const char *argv[]) byte_t *pbtUID; FILE *pfKeys = NULL; FILE *pfDump = NULL; + int unlock= 0; if (argc < 2) { print_usage (argv[0]); @@ -454,22 +465,24 @@ main (int argc, const char *argv[]) } const char *command = argv[1]; - if (strcmp (command, "r") == 0) { + if (strcmp (command, "r") == 0 || strcmp (command, "R") == 0) { if (argc < 4) { print_usage (argv[0]); exit (EXIT_FAILURE); } atAction = ACTION_READ; + if (strcmp (command, "R") == 0) + unlock= 1; bUseKeyA = tolower ((int) ((unsigned char) *(argv[2]))) == 'a'; bUseKeyFile = (argc > 4); - } else if (strcmp (command, "w") == 0 || strcmp (command, "u") == 0) { + } else if (strcmp (command, "w") == 0 || strcmp (command, "W") == 0) { if (argc < 4) { print_usage (argv[0]); exit (EXIT_FAILURE); } atAction = ACTION_WRITE; - if (strcmp (command, "u") == 0) - atAction = ACTION_WRITE_UNLOCKED; + if (strcmp (command, "W") == 0) + unlock= 1; bUseKeyA = tolower ((int) ((unsigned char) *(argv[2]))) == 'a'; bUseKeyFile = (argc > 4); } else if (strcmp (command, "x") == 0) { @@ -487,7 +500,6 @@ main (int argc, const char *argv[]) break; case ACTION_READ: case ACTION_WRITE: - case ACTION_WRITE_UNLOCKED: if (bUseKeyFile) { pfKeys = fopen (argv[4], "rb"); if (pfKeys == NULL) { @@ -580,7 +592,7 @@ main (int argc, const char *argv[]) printf ("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16); if (atAction == ACTION_READ) { - if (read_card ()) { + if (read_card (unlock)) { printf ("Writing data to file: %s ...", argv[3]); fflush (stdout); pfDump = fopen (argv[3], "wb"); @@ -596,10 +608,7 @@ main (int argc, const char *argv[]) fclose (pfDump); } } else if (atAction == ACTION_WRITE) { - write_card (0); - } - else if (atAction == ACTION_WRITE_UNLOCKED) { - write_card (1); + write_card (unlock); } nfc_disconnect (pnd); diff --git a/examples/nfc-mfsetuid.1 b/examples/nfc-mfsetuid.1 index b395847..a51d68d 100644 --- a/examples/nfc-mfsetuid.1 +++ b/examples/nfc-mfsetuid.1 @@ -3,12 +3,20 @@ nfc-mfsetuid \- MIFARE 1K special card UID setting and recovery tool .SH SYNOPSIS .B nfc-mfsetuid +[UID] .SH DESCRIPTION .B nfc-mfsetuid is a MIFARE tool that allows setting of UID on special versions (Chinese clones) of Mifare 1K cards. It will also recover damaged cards that have had invalid data written to block 0 (e.g. wrong BCC). Currently only 4 Byte UID is supported. +Specify an eight hex character UID or leave blank for the default '01234567'. +.SH OPTIONS +.B -f +Format. Wipe all data (set to 0xFF) and reset ACLs to defaults. + +.B -q +Quiet. Suppress output of commands and responses. .SH BUGS Please report any bugs on the .B libnfc diff --git a/examples/nfc-mfsetuid.c b/examples/nfc-mfsetuid.c index 52176cc..0c65bd1 100644 --- a/examples/nfc-mfsetuid.c +++ b/examples/nfc-mfsetuid.c @@ -81,8 +81,10 @@ byte_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 }; // special unlock command byte_t abtUnlock1[1] = { 0x40 }; byte_t abtUnlock2[1] = { 0x43 }; +byte_t abtWipe[1] = { 0x41 }; byte_t abtWrite[4] = { 0xa0, 0x00, 0x5f, 0xb1 }; byte_t abtData[18] = { 0x01, 0x23, 0x45, 0x67, 0x00, 0x08, 0x04, 0x00, 0x46, 0x59, 0x25, 0x58, 0x49, 0x10, 0x23, 0x02, 0x23, 0xeb }; +byte_t abtBlank[18] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0xCC }; static bool @@ -134,7 +136,8 @@ print_usage (char *argv[]) printf ("Usage: %s [OPTIONS] [UID]\n", argv[0]); printf ("Options:\n"); printf ("\t-h\tHelp. Print this message.\n"); - printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n"); + printf ("\t-f\tFormat. Delete all data (set to 0xFF) and reset ACLs to default.\n"); + printf ("\t-q\tQuiet mode. Suppress output of READER and CARD data (improves timing).\n"); printf ("\n\tSpecify UID (4 HEX bytes) to set UID, or leave blank for default '01234567'.\n"); printf ("\tThis utility can be used to recover cards that have been damaged by writing bad\n"); printf ("\tdata (e.g. wrong BCC), thus making them non-selectable by most tools/readers.\n"); @@ -144,15 +147,19 @@ print_usage (char *argv[]) int main (int argc, char *argv[]) { - int arg, i; + int arg, i; + bool format= false; unsigned int c; - char tmp[3]= { 0x00, 0x00, 0x00 }; + char tmp[3]= { 0x00, 0x00, 0x00 }; + // Get commandline options for (arg = 1; arg < argc; arg++) { if (0 == strcmp (argv[arg], "-h")) { print_usage (argv); exit(EXIT_SUCCESS); + } else if (0 == strcmp (argv[arg], "-f")) { + format= true; } else if (0 == strcmp (argv[arg], "-q")) { quiet_output = true; } else if (strlen(argv[arg]) == 8) { @@ -322,9 +329,22 @@ main (int argc, char *argv[]) iso14443a_crc_append(abtHalt, 2); transmit_bytes (abtHalt, 4); transmit_bits (abtUnlock1,7); + if(format) { + transmit_bytes (abtWipe,1); + transmit_bytes (abtHalt, 4); + transmit_bits (abtUnlock1,7); + } transmit_bytes (abtUnlock2,1); transmit_bytes (abtWrite,4); transmit_bytes (abtData,18); + if(format) { + for(i= 3 ; i < 64 ; i += 4) { + abtWrite[1]= (char) i; + iso14443a_crc_append (abtWrite, 2); + transmit_bytes (abtWrite,4); + transmit_bytes (abtBlank,18); + } + } nfc_disconnect (pnd);