71static mifare_param mp;
72static mifare_classic_tag mtKeys;
73static mifare_classic_tag mtDump;
75static bool bUseKeyFile;
76static bool bForceKeyFile;
77static bool bTolerateFailures;
78static bool bFormatCard;
79static bool dWrite =
false;
80static bool unlocked =
false;
81static uint8_t uiBlocks;
82static uint8_t keys[] = {
83 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7,
85 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
86 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
87 0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd,
88 0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a,
89 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
93static uint8_t default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
94static uint8_t default_acl[] = {0xff, 0x07, 0x80, 0x69};
101static size_t num_keys =
sizeof(keys) / 6;
103#define MAX_FRAME_LEN 264
105static uint8_t abtRx[MAX_FRAME_LEN];
108uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
111uint8_t abtUnlock1[1] = { 0x40 };
112uint8_t abtUnlock2[1] = { 0x43 };
115transmit_bits(
const uint8_t *pbtTx,
const size_t szTxBits)
118 printf(
"Sent bits: ");
119 print_hex_bits(pbtTx, szTxBits);
125 printf(
"Received bits: ");
126 print_hex_bits(abtRx, szRxBits);
133transmit_bytes(
const uint8_t *pbtTx,
const size_t szTx)
136 printf(
"Sent bits: ");
137 print_hex(pbtTx, szTx);
144 printf(
"Received bits: ");
145 print_hex(abtRx, res);
151print_success_or_failure(
bool bFailure, uint32_t *uiBlockCounter)
153 printf(
"%c", (bFailure) ?
'x' :
'.');
154 if (uiBlockCounter && !bFailure)
155 *uiBlockCounter += 1;
159is_first_block(uint32_t uiBlock)
163 return ((uiBlock) % 4 == 0);
165 return ((uiBlock) % 16 == 0);
169is_trailer_block(uint32_t uiBlock)
173 return ((uiBlock + 1) % 4 == 0);
175 return ((uiBlock + 1) % 16 == 0);
179get_trailer_block(uint32_t uiFirstBlock)
182 uint32_t trailer_block = 0;
183 if (uiFirstBlock < 128) {
184 trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
186 trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
188 return trailer_block;
192authenticate(uint32_t uiBlock)
197 memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
200 mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
206 uint32_t uiTrailerBlock;
207 uiTrailerBlock = get_trailer_block(uiBlock);
211 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA,
sizeof(mp.mpa.abtKey));
213 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB,
sizeof(mp.mpa.abtKey));
220 }
else if (bFormatCard || !bUseKeyFile) {
221 for (
size_t key_index = 0; key_index < num_keys; key_index++) {
222 memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
225 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey,
sizeof(mtKeys.amb[uiBlock].mbt.abtKeyA));
227 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey,
sizeof(mtKeys.amb[uiBlock].mbt.abtKeyB));
231 ERR(
"tag was removed");
241unlock_card(
bool write)
254 iso14443a_crc_append(abtHalt, 2);
255 transmit_bytes(abtHalt, 4);
257 if (!transmit_bits(abtUnlock1, 7)) {
258 printf(
"Warning: Unlock command [1/2]: failed / not acknowledged.\n");
261 printf(
"Trying to rewrite block 0 on a direct write tag.\n");
264 if (transmit_bytes(abtUnlock2, 1)) {
265 printf(
"Card unlocked\n");
268 printf(
"Warning: Unlock command [2/2]: failed / not acknowledged.\n");
275 printf(
"Error: tag was removed\n");
284 nfc_perror(pnd,
"nfc_device_set_property_bool");
289 nfc_perror(pnd,
"nfc_device_set_property_bool");
299 uint8_t abtRats[2] = { 0xe0, 0x50};
319 printf(
"Error: tag disappeared\n");
328read_card(
bool read_unlocked)
331 bool bFailure =
false;
332 uint32_t uiReadBlocks = 0;
339 printf(
"Note: This card can't do an unlocked read (R) \n");
344 printf(
"Reading out %d blocks |", uiBlocks + 1);
346 for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
348 if (is_trailer_block(iBlock)) {
352 printf(
"!\nError: tag was removed\n");
361 if (!read_unlocked && !authenticate(iBlock)) {
362 printf(
"!\nError: authentication failed for block 0x%02x\n", iBlock);
368 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData,
sizeof(mtDump.amb[iBlock].mbd.abtData));
371 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA,
sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
372 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits,
sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
373 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB,
sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
376 printf(
"!\nfailed to read trailer block 0x%02x\n", iBlock);
384 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData,
sizeof(mtDump.amb[iBlock].mbd.abtData));
386 printf(
"!\nError: unable to read block 0x%02x\n", iBlock);
392 print_success_or_failure(bFailure, &uiReadBlocks);
393 if ((!bTolerateFailures) && bFailure)
397 printf(
"Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
404write_card(
bool write_block_zero)
407 bool bFailure =
false;
408 uint32_t uiWriteBlocks = 0;
411 if (write_block_zero) {
415 printf(
"Writing %d blocks |", uiBlocks + write_block_zero);
417 for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
419 if (!write_block_zero && uiBlock == 0) {
423 if (uiBlock == 1 || is_first_block(uiBlock)) {
427 printf(
"!\nError: tag was removed\n");
439 if ((write_block_zero && dWrite) || !write_block_zero) {
440 if (!authenticate(uiBlock) && !bTolerateFailures) {
441 printf(
"!\nError: authentication failed for block %02x\n", uiBlock);
447 if (is_trailer_block(uiBlock)) {
450 memcpy(mp.mpt.abtKeyA, default_key,
sizeof(mp.mpt.abtKeyA));
451 memcpy(mp.mpt.abtAccessBits, default_acl,
sizeof(mp.mpt.abtAccessBits));
452 memcpy(mp.mpt.abtKeyB, default_key,
sizeof(mp.mpt.abtKeyB));
455 memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA,
sizeof(mp.mpt.abtKeyA));
456 memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits,
sizeof(mp.mpt.abtAccessBits));
457 memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB,
sizeof(mp.mpt.abtKeyB));
462 printf(
"failed to write trailer block %d \n", uiBlock);
469 if (bFormatCard && uiBlock)
471 memset(mp.mpd.abtData, 0x00,
sizeof(mp.mpd.abtData));
473 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData,
sizeof(mp.mpd.abtData));
476 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) {
477 printf(
"!\nError: incorrect BCC in MFD file!\n");
478 printf(
"Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
484 printf(
"Failure to write to data block %i\n", uiBlock);
486 if (uiBlock == 0 && dWrite) {
494 printf(
"!\nError: tag was removed\n");
499 printf(
"Failure during write process.\n");
504 print_success_or_failure(bFailure, &uiWriteBlocks);
505 if ((! bTolerateFailures) && bFailure)
510 printf(
"Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
523print_usage(
const char *pcProgramName)
527 printf(
"%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f] [v]]\n", pcProgramName);
529 printf(
"%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
531 printf(
" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or block 0 write to (W) card\n");
532 printf(
" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
533 printf(
" *** unlocked read does not require authentication and will reveal A and B keys\n");
534 printf(
" *** note that block 0 write will attempt to overwrite block 0 including UID\n");
535 printf(
" *** block 0 write only works with special Mifare cards (Chinese clones)\n");
536 printf(
" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
537 printf(
" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
538 printf(
" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
539 printf(
" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
540 printf(
" f - Force using the keyfile even if UID does not match (optional)\n");
542 printf(
" v - Sends libnfc log output to console (optional)\n");
544 printf(
"Examples: \n\n");
545 printf(
" Read card to file, using key A:\n\n");
546 printf(
" %s r a u mycard.mfd\n\n", pcProgramName);
547 printf(
" Write file to blank card, using key A:\n\n");
548 printf(
" %s w a u mycard.mfd\n\n", pcProgramName);
549 printf(
" Write new data and/or keys to previously written card, using key A:\n\n");
550 printf(
" %s w a u newdata.mfd mycard.mfd\n\n", pcProgramName);
551 printf(
" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n");
552 printf(
" %s f A u dummy.mfd keyfile.mfd f\n", pcProgramName);
553 printf(
" %s f B u dummy.mfd keyfile.mfd f\n\n", pcProgramName);
554 printf(
" Read card to file, using key A and uid 0x01 0xab 0x23 0xcd:\n\n");
555 printf(
" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName);
560main(
int argc,
const char *argv[])
562 action_t atAction = ACTION_USAGE;
565 uint8_t *tag_uid = _tag_uid;
570 print_usage(argv[0]);
573 const char *command = argv[1];
576 print_usage(argv[0]);
579 if (strcmp(command,
"r") == 0 || strcmp(command,
"R") == 0) {
580 atAction = ACTION_READ;
581 if (strcmp(command,
"R") == 0)
583 bUseKeyA = tolower((
int)((
unsigned char) * (argv[2]))) ==
'a';
584 bTolerateFailures = tolower((
int)((
unsigned char) * (argv[2]))) != (int)((
unsigned char) * (argv[2]));
585 bUseKeyFile = (argc > 5) && strcmp(argv[5],
"v");
586 bForceKeyFile = ((argc > 6) && (strcmp((
char *)argv[6],
"f") == 0));
587 }
else if (strcmp(command,
"w") == 0 || strcmp(command,
"W") == 0 || strcmp(command,
"f") == 0) {
588 atAction = ACTION_WRITE;
589 if (strcmp(command,
"W") == 0)
591 bFormatCard = (strcmp(command,
"f") == 0);
592 bUseKeyA = tolower((
int)((
unsigned char) * (argv[2]))) ==
'a';
593 bTolerateFailures = tolower((
int)((
unsigned char) * (argv[2]))) != (int)((
unsigned char) * (argv[2]));
594 bUseKeyFile = (argc > 5) && strcmp(argv[5],
"v");
595 bForceKeyFile = ((argc > 6) && (strcmp((
char *)argv[6],
"f") == 0));
597 if (argv[3][0] ==
'U') {
598 unsigned long int _uid;
600 if (strlen(argv[3]) != 9) {
601 printf(
"Error, illegal tag specification, use U01ab23cd for example.\n");
602 print_usage(argv[0]);
605 _uid = strtoul(argv[3] + 1, NULL, 16);
606 tag_uid[0] = (_uid & 0xff000000UL) >> 24;
607 tag_uid[1] = (_uid & 0x00ff0000UL) >> 16;
608 tag_uid[2] = (_uid & 0x0000ff00UL) >> 8;
609 tag_uid[3] = (_uid & 0x000000ffUL);
610 printf(
"Attempting to use specific UID: 0x%2x 0x%2x 0x%2x 0x%2x\n",
611 tag_uid[0], tag_uid[1], tag_uid[2], tag_uid[3]);
618 bool verbose =
false;
620 if (strcmp(argv[7],
"v") == 0) verbose =
true;
622 if ((strcmp(argv[6],
"v")) || (strcmp(argv[5],
"v")) == 0) verbose =
true;
625 int fd = open(
"/dev/null", O_WRONLY);
631 if (atAction == ACTION_USAGE) {
632 print_usage(argv[0]);
637 FILE *pfKeys = fopen(argv[5],
"rb");
638 if (pfKeys == NULL) {
639 printf(
"Could not open keys file: %s\n", argv[5]);
642 if (fread(&mtKeys, 1, 4, pfKeys) != 4) {
643 printf(
"Could not read UID from key file: %s\n", argv[5]);
650 if (context == NULL) {
651 ERR(
"Unable to init libnfc (malloc)");
658 ERR(
"Error opening NFC reader");
672 nfc_perror(pnd,
"nfc_device_set_property_bool activate field");
680 nfc_perror(pnd,
"nfc_device_set_property_bool");
687 nfc_perror(pnd,
"nfc_device_set_property_bool");
695 nfc_perror(pnd,
"nfc_device_set_property_bool crc");
701 nfc_perror(pnd,
"nfc_device_set_property_bool parity");
713 printf(
"Error: no tag was found\n");
719 if (((nt.nti.nai.btSak & 0x08) == 0) && (nt.nti.nai.btSak != 0x01)) {
721 printf(
"Warning: tag is probably not a MFC!\n");
725 pbtUID = nt.nti.nai.abtUid;
729 memcpy(fileUid, mtKeys.amb[0].mbm.abtUID, 4);
731 if (memcmp(pbtUID, fileUid, 4) != 0) {
732 printf(
"Expected MIFARE Classic card with UID starting as: %02x%02x%02x%02x\n",
733 fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
734 printf(
"Got card with UID starting as: %02x%02x%02x%02x\n",
735 pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]);
736 if (!bForceKeyFile) {
737 printf(
"Aborting!\n");
744 printf(
"Found MIFARE Classic card:\n");
745 print_nfc_target(&nt,
false);
748 if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02 || nt.nti.nai.btSak == 0x18)
751 else if (nt.nti.nai.btSak == 0x09)
759 if ((res = get_rats()) > 0) {
760 printf(
"RATS support: yes\n");
761 if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
762 && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
763 && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
768 printf(
"RATS support: no\n");
769 printf(
"Guessing size: seems to be a %lu-byte card\n", (
unsigned long)((uiBlocks + 1) *
sizeof(mifare_classic_block)));
772 FILE *pfKeys = fopen(argv[5],
"rb");
773 if (pfKeys == NULL) {
774 printf(
"Could not open keys file: %s\n", argv[5]);
777 if (fread(&mtKeys, 1, (uiBlocks + 1) *
sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) *
sizeof(mifare_classic_block)) {
778 printf(
"Could not read keys file: %s\n", argv[5]);
785 if (atAction == ACTION_READ) {
786 memset(&mtDump, 0x00,
sizeof(mtDump));
788 FILE *pfDump = fopen(argv[4],
"rb");
790 if (pfDump == NULL) {
791 printf(
"Could not open dump file: %s\n", argv[4]);
796 if (fread(&mtDump, 1, (uiBlocks + 1) *
sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) *
sizeof(mifare_classic_block)) {
797 printf(
"Could not read dump file: %s\n", argv[4]);
805 if (atAction == ACTION_READ) {
806 if (read_card(unlock)) {
807 printf(
"Writing data to file: %s ...", argv[4]);
809 FILE *pfDump = fopen(argv[4],
"wb");
810 if (pfDump == NULL) {
811 printf(
"Could not open dump file: %s\n", argv[4]);
816 if (fwrite(&mtDump, 1, (uiBlocks + 1) *
sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) *
sizeof(mifare_classic_block))) {
817 printf(
"\nCould not write to file: %s\n", argv[4]);
830 }
else if (atAction == ACTION_WRITE) {
831 if (!write_card(unlock)) {
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
void nfc_close(nfc_device *pnd)
Close from a NFC device.
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
int nfc_initiator_transceive_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout)
Send data to target then retrieve data from target.
int nfc_initiator_transceive_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar)
Transceive raw bit-frames to a target.
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt)
Select a passive or emulated tag.
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
Set a device's boolean-property value.
bool nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
Execute a MIFARE Classic Command.
provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
Provide some examples shared functions like print, parity calculation, options parsing.
#define ERR(...)
Print a error message.
NFC library context Struct which contains internal options, references, pointers, etc....
NFC modulation structure.