65 static mifare_param mp;
66 static mifare_classic_tag mtKeys;
67 static mifare_classic_tag mtDump;
69 static bool bUseKeyFile;
70 static bool bForceKeyFile;
71 static bool bTolerateFailures;
72 static bool bFormatCard;
73 static bool magic2 =
false;
74 static bool magic3 =
false;
75 static bool unlocked =
false;
76 static uint8_t uiBlocks;
77 static uint8_t keys[] = {
78 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7,
80 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
81 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
82 0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd,
83 0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a,
84 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
88 static uint8_t default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
89 static uint8_t default_acl[] = {0xff, 0x07, 0x80, 0x69};
96 static size_t num_keys =
sizeof(keys) / 6;
98 #define MAX_FRAME_LEN 264
100 static uint8_t abtRx[MAX_FRAME_LEN];
103 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
106 uint8_t abtUnlock1[1] = { 0x40 };
107 uint8_t abtUnlock2[1] = { 0x43 };
110 transmit_bits(
const uint8_t *pbtTx,
const size_t szTxBits)
113 printf(
"Sent bits: ");
114 print_hex_bits(pbtTx, szTxBits);
120 printf(
"Received bits: ");
121 print_hex_bits(abtRx, szRxBits);
128 transmit_bytes(
const uint8_t *pbtTx,
const size_t szTx)
131 printf(
"Sent bits: ");
132 print_hex(pbtTx, szTx);
139 printf(
"Received bits: ");
140 print_hex(abtRx, res);
146 print_success_or_failure(
bool bFailure, uint32_t *uiBlockCounter)
148 printf(
"%c", (bFailure) ?
'x' :
'.');
149 if (uiBlockCounter && !bFailure)
150 *uiBlockCounter += 1;
154 is_first_block(uint32_t uiBlock)
158 return ((uiBlock) % 4 == 0);
160 return ((uiBlock) % 16 == 0);
164 is_trailer_block(uint32_t uiBlock)
168 return ((uiBlock + 1) % 4 == 0);
170 return ((uiBlock + 1) % 16 == 0);
174 get_trailer_block(uint32_t uiFirstBlock)
177 uint32_t trailer_block = 0;
178 if (uiFirstBlock < 128) {
179 trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
181 trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
183 return trailer_block;
187 authenticate(uint32_t uiBlock)
192 memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
195 mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
201 uint32_t uiTrailerBlock;
202 uiTrailerBlock = get_trailer_block(uiBlock);
206 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA,
sizeof(mp.mpa.abtKey));
208 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB,
sizeof(mp.mpa.abtKey));
216 memcpy(mp.mpa.abtKey, default_key,
sizeof(default_key));
224 }
else if (bFormatCard || !bUseKeyFile) {
225 for (
size_t key_index = 0; key_index < num_keys; key_index++) {
226 memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
229 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey,
sizeof(mtKeys.amb[uiBlock].mbt.abtKeyA));
231 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey,
sizeof(mtKeys.amb[uiBlock].mbt.abtKeyB));
235 ERR(
"tag was removed");
258 iso14443a_crc_append(abtHalt, 2);
259 transmit_bytes(abtHalt, 4);
261 if (!transmit_bits(abtUnlock1, 7)) {
262 printf(
"Warning: Unlock command [1/2]: failed / not acknowledged.\n");
264 if (transmit_bytes(abtUnlock2, 1)) {
265 printf(
"Card unlocked\n");
268 printf(
"Warning: Unlock command [2/2]: failed / not acknowledged.\n");
275 nfc_perror(pnd,
"nfc_device_set_property_bool");
280 nfc_perror(pnd,
"nfc_device_set_property_bool");
290 uint8_t abtRats[2] = { 0xe0, 0x50};
310 printf(
"Error: tag disappeared\n");
319 read_card(
int read_unlocked)
322 bool bFailure =
false;
323 uint32_t uiReadBlocks = 0;
329 printf(
"Note: This card does not require an unlocked read (R) \n");
333 if (!unlock_card()) {
339 printf(
"Reading out %d blocks |", uiBlocks + 1);
341 for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
343 if (is_trailer_block(iBlock)) {
347 printf(
"!\nError: tag was removed\n");
356 if (!read_unlocked && !authenticate(iBlock)) {
357 printf(
"!\nError: authentication failed for block 0x%02x\n", iBlock);
363 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData,
sizeof(mtDump.amb[iBlock].mbd.abtData));
367 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key,
sizeof(default_key));
368 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits,
sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
369 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key,
sizeof(default_key));
372 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA,
sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
373 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits,
sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
374 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB,
sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
378 printf(
"!\nfailed to read trailer block 0x%02x\n", iBlock);
386 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData,
sizeof(mtDump.amb[iBlock].mbd.abtData));
388 printf(
"!\nError: unable to read block 0x%02x\n", iBlock);
394 print_success_or_failure(bFailure, &uiReadBlocks);
395 if ((!bTolerateFailures) && bFailure)
399 printf(
"Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
406 write_card(
int write_block_zero)
409 bool bFailure =
false;
410 uint32_t uiWriteBlocks = 0;
413 if (write_block_zero) {
417 printf(
"Note: This card does not require an unlocked write (W) \n");
418 write_block_zero = 0;
421 if (!unlock_card()) {
427 printf(
"Writing %d blocks |", uiBlocks + 1);
429 for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
431 if (is_first_block(uiBlock)) {
435 printf(
"!\nError: tag was removed\n");
447 if ((write_block_zero && magic3) || !write_block_zero) {
448 if (!authenticate(uiBlock) && !bTolerateFailures) {
449 printf(
"!\nError: authentication failed for block %02x\n", uiBlock);
454 if (is_trailer_block(uiBlock)) {
457 memcpy(mp.mpt.abtKeyA, default_key,
sizeof(mp.mpt.abtKeyA));
458 memcpy(mp.mpt.abtAccessBits, default_acl,
sizeof(mp.mpt.abtAccessBits));
459 memcpy(mp.mpt.abtKeyB, default_key,
sizeof(mp.mpt.abtKeyB));
462 memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA,
sizeof(mp.mpt.abtKeyA));
463 memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits,
sizeof(mp.mpt.abtAccessBits));
464 memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB,
sizeof(mp.mpt.abtKeyB));
469 printf(
"failed to write trailer block %d \n", uiBlock);
474 if (uiBlock == 0 && !write_block_zero && !magic2)
480 if (bFormatCard && uiBlock)
482 memset(mp.mpd.abtData, 0x00,
sizeof(mp.mpd.abtData));
484 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData,
sizeof(mp.mpd.abtData));
487 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
488 printf(
"!\nError: incorrect BCC in MFD file!\n");
489 printf(
"Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
495 printf(
"Failure to write to data block %i\n", uiBlock);
499 printf(
"Failure during write process.\n");
504 print_success_or_failure(bFailure, &uiWriteBlocks);
505 if ((! bTolerateFailures) && bFailure)
510 if (write_block_zero || magic2 || magic3) {
511 for (uiBlock = 0; uiBlock < 4; uiBlock++) {
516 if (write_block_zero || magic2 || magic3) {
523 if (is_first_block(uiBlock)) {
527 printf(
"!\nError: tag was removed\n");
538 if ((write_block_zero && magic3) || !write_block_zero) {
539 if (!authenticate(uiBlock) && !bTolerateFailures) {
540 printf(
"!\nError: authentication failed for block %02x\n", uiBlock);
549 if (bFormatCard && uiBlock)
550 memset(mp.mpd.abtData, 0x00,
sizeof(mp.mpd.abtData));
552 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData,
sizeof(mp.mpd.abtData));
555 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
556 printf(
"!\nError: incorrect BCC in MFD file!\n");
557 printf(
"Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
563 printf(
"Failure to write to data block %i\n", uiBlock);
567 printf(
"Failure during write process.\n");
571 print_success_or_failure(bFailure, &uiWriteBlocks);
572 if ((! bTolerateFailures) && bFailure)
580 printf(
"Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
593 print_usage(
const char *pcProgramName)
596 printf(
"%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
597 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");
598 printf(
" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
599 printf(
" *** unlocked read does not require authentication and will reveal A and B keys\n");
600 printf(
" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
601 printf(
" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
602 printf(
" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
603 printf(
" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
604 printf(
" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
605 printf(
" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
606 printf(
" f - Force using the keyfile even if UID does not match (optional)\n");
608 printf(
"Examples: \n\n");
609 printf(
" Read card to file, using key A:\n\n");
610 printf(
" %s r a u mycard.mfd\n\n", pcProgramName);
611 printf(
" Write file to blank card, using key A:\n\n");
612 printf(
" %s w a u mycard.mfd\n\n", pcProgramName);
613 printf(
" Write new data and/or keys to previously written card, using key A:\n\n");
614 printf(
" %s w a u newdata.mfd mycard.mfd\n\n", pcProgramName);
615 printf(
" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n");
616 printf(
" %s f A u dummy.mfd keyfile.mfd f\n", pcProgramName);
617 printf(
" %s f B u dummy.mfd keyfile.mfd f\n\n", pcProgramName);
618 printf(
" Read card to file, using key A and uid 0x01 0xab 0x23 0xcd:\n\n");
619 printf(
" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName);
623 static bool is_directwrite(
void)
625 printf(
"Checking if Badge is DirectWrite...\n");
628 memcpy(mtDump.amb[0].mbt.abtKeyA, default_key,
sizeof(default_key));
629 memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl,
sizeof(mp.mpt.abtAccessBits));
630 memcpy(mtDump.amb[0].mbt.abtKeyB, default_key,
sizeof(default_key));
633 bool orig_bUseKeyFile = bUseKeyFile;
636 if (!authenticate(0)) {
637 printf(
"!\nError: authentication failed for block 0x%02x\n", 0);
638 bUseKeyFile = orig_bUseKeyFile;
642 bUseKeyFile = orig_bUseKeyFile;
645 uint8_t original_b0[16];
647 memcpy(original_b0, mp.mpd.abtData,
sizeof(mp.mpd.abtData));
648 printf(
" Original Block 0: ");
649 for (
int i = 0; i < 16; i++) {
650 printf(
"%02x", original_b0[i]);
653 printf(
" Original UID: %02x%02x%02x%02x\n",
654 original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
656 printf(
"!\nError: unable to read block 0x%02x\n", 0);
660 printf(
" Attempt to write Block 0 ...\n");
661 memcpy(mp.mpd.abtData, original_b0,
sizeof(original_b0));
663 printf(
"Failure to write to data block %i\n", 0);
666 printf(
" Block 0 written successfully\n");
672 main(
int argc,
const char *argv[])
674 action_t atAction = ACTION_USAGE;
677 uint8_t *tag_uid = _tag_uid;
682 print_usage(argv[0]);
685 const char *command = argv[1];
688 print_usage(argv[0]);
691 if (strcmp(command,
"r") == 0 || strcmp(command,
"R") == 0) {
692 atAction = ACTION_READ;
693 if (strcmp(command,
"R") == 0)
695 bUseKeyA = tolower((
int)((
unsigned char) * (argv[2]))) ==
'a';
696 bTolerateFailures = tolower((
int)((
unsigned char) * (argv[2]))) != (int)((
unsigned char) * (argv[2]));
697 bUseKeyFile = (argc > 5);
698 bForceKeyFile = ((argc > 6) && (strcmp((
char *)argv[6],
"f") == 0));
699 }
else if (strcmp(command,
"w") == 0 || strcmp(command,
"W") == 0 || strcmp(command,
"f") == 0) {
700 atAction = ACTION_WRITE;
701 if (strcmp(command,
"W") == 0)
703 bFormatCard = (strcmp(command,
"f") == 0);
704 bUseKeyA = tolower((
int)((
unsigned char) * (argv[2]))) ==
'a';
705 bTolerateFailures = tolower((
int)((
unsigned char) * (argv[2]))) != (int)((
unsigned char) * (argv[2]));
706 bUseKeyFile = (argc > 5);
707 bForceKeyFile = ((argc > 6) && (strcmp((
char *)argv[6],
"f") == 0));
709 if (argv[3][0] ==
'U') {
710 unsigned long int _uid;
712 if (strlen(argv[3]) != 9) {
713 printf(
"Error, illegal tag specification, use U01ab23cd for example.\n");
714 print_usage(argv[0]);
717 _uid = strtoul(argv[3] + 1, NULL, 16);
718 tag_uid[0] = (_uid & 0xff000000UL) >> 24;
719 tag_uid[1] = (_uid & 0x00ff0000UL) >> 16;
720 tag_uid[2] = (_uid & 0x0000ff00UL) >> 8;
721 tag_uid[3] = (_uid & 0x000000ffUL);
722 printf(
"Attempting to use specific UID: 0x%2x 0x%2x 0x%2x 0x%2x\n",
723 tag_uid[0], tag_uid[1], tag_uid[2], tag_uid[3]);
728 if (atAction == ACTION_USAGE) {
729 print_usage(argv[0]);
734 FILE *pfKeys = fopen(argv[5],
"rb");
735 if (pfKeys == NULL) {
736 printf(
"Could not open keys file: %s\n", argv[5]);
739 if (fread(&mtKeys, 1, 4, pfKeys) != 4) {
740 printf(
"Could not read UID from key file: %s\n", argv[5]);
747 if (context == NULL) {
748 ERR(
"Unable to init libnfc (malloc)");
755 ERR(
"Error opening NFC reader");
769 nfc_perror(pnd,
"nfc_device_set_property_bool");
776 nfc_perror(pnd,
"nfc_device_set_property_bool");
789 printf(
"Error: no tag was found\n");
795 if ((nt.nti.nai.btSak & 0x08) == 0) {
796 printf(
"Warning: tag is probably not a MFC!\n");
800 pbtUID = nt.nti.nai.abtUid;
804 memcpy(fileUid, mtKeys.amb[0].mbm.abtUID, 4);
806 if (memcmp(pbtUID, fileUid, 4) != 0) {
807 printf(
"Expected MIFARE Classic card with UID starting as: %02x%02x%02x%02x\n",
808 fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
809 printf(
"Got card with UID starting as: %02x%02x%02x%02x\n",
810 pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]);
811 if (!bForceKeyFile) {
812 printf(
"Aborting!\n");
819 printf(
"Found MIFARE Classic card:\n");
820 print_nfc_target(&nt,
false);
823 if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02 || nt.nti.nai.btSak == 0x18)
826 else if (nt.nti.nai.btSak == 0x09)
834 if ((res = get_rats()) > 0) {
835 printf(
"RATS support: yes\n");
836 if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
837 && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
838 && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
843 if ((res == 9) && (abtRx[5] == 0xda) && (abtRx[6] == 0xbc)
844 && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
848 printf(
"RATS support: no\n");
849 printf(
"Guessing size: seems to be a %lu-byte card\n", (
unsigned long)((uiBlocks + 1) *
sizeof(mifare_classic_block)));
852 if (uiBlocks == 0xff) {
853 if (is_directwrite()) {
854 printf(
"Card is DirectWrite\n");
858 printf(
"Card is not DirectWrite\n");
863 if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 &&
864 pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
865 printf(
"Card appears to be a One Time Write Card..\n");
872 FILE *pfKeys = fopen(argv[5],
"rb");
873 if (pfKeys == NULL) {
874 printf(
"Could not open keys file: %s\n", argv[5]);
877 if (fread(&mtKeys, 1, (uiBlocks + 1) *
sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) *
sizeof(mifare_classic_block)) {
878 printf(
"Could not read keys file: %s\n", argv[5]);
885 if (atAction == ACTION_READ) {
886 memset(&mtDump, 0x00,
sizeof(mtDump));
888 FILE *pfDump = fopen(argv[4],
"rb");
890 if (pfDump == NULL) {
891 printf(
"Could not open dump file: %s\n", argv[4]);
896 if (fread(&mtDump, 1, (uiBlocks + 1) *
sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) *
sizeof(mifare_classic_block)) {
897 printf(
"Could not read dump file: %s\n", argv[4]);
905 if (atAction == ACTION_READ) {
906 if (read_card(unlock)) {
907 printf(
"Writing data to file: %s ...", argv[4]);
909 FILE *pfDump = fopen(argv[4],
"wb");
910 if (pfDump == NULL) {
911 printf(
"Could not open dump file: %s\n", argv[4]);
916 if (fwrite(&mtDump, 1, (uiBlocks + 1) *
sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) *
sizeof(mifare_classic_block))) {
917 printf(
"\nCould not write to file: %s\n", argv[4]);
926 }
else if (atAction == ACTION_WRITE) {
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.