Merge pull request #608 from gelotus/nfc-mfclassic
Improve support for gen2 and gen3 tags thanks @gelotus
This commit is contained in:
commit
0de55961c4
1 changed files with 114 additions and 110 deletions
|
@ -54,6 +54,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
@ -242,7 +248,7 @@ authenticate(uint32_t uiBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
unlock_card(void)
|
unlock_card(bool write)
|
||||||
{
|
{
|
||||||
// Configure the CRC
|
// Configure the CRC
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
|
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
|
||||||
|
@ -260,6 +266,10 @@ unlock_card(void)
|
||||||
// now send unlock
|
// now send unlock
|
||||||
if (!transmit_bits(abtUnlock1, 7)) {
|
if (!transmit_bits(abtUnlock1, 7)) {
|
||||||
printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
|
printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
|
||||||
|
if (write) {
|
||||||
|
printf("Trying to rewrite block 0 on a gen2 tag.\n");
|
||||||
|
magic2 = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (transmit_bytes(abtUnlock2, 1)) {
|
if (transmit_bytes(abtUnlock2, 1)) {
|
||||||
printf("Card unlocked\n");
|
printf("Card unlocked\n");
|
||||||
|
@ -270,6 +280,15 @@ unlock_card(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset reader
|
// reset reader
|
||||||
|
if (!unlocked) {
|
||||||
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
|
||||||
|
printf("Error: tag was removed\n");
|
||||||
|
nfc_close(pnd);
|
||||||
|
nfc_exit(context);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Configure the CRC
|
// Configure the CRC
|
||||||
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
|
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror(pnd, "nfc_device_set_property_bool");
|
||||||
|
@ -316,7 +335,7 @@ get_rats(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
read_card(int read_unlocked)
|
read_card(bool read_unlocked)
|
||||||
{
|
{
|
||||||
int32_t iBlock;
|
int32_t iBlock;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
|
@ -325,12 +344,12 @@ read_card(int read_unlocked)
|
||||||
if (read_unlocked) {
|
if (read_unlocked) {
|
||||||
//If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
|
//If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
|
||||||
//need to use the R mode. We'll trigger a warning and let them proceed.
|
//need to use the R mode. We'll trigger a warning and let them proceed.
|
||||||
if (magic2) {
|
if (magic2 || magic3) {
|
||||||
printf("Note: This card does not require an unlocked read (R) \n");
|
printf("Note: This card does not require an unlocked read (R) \n");
|
||||||
read_unlocked = 0;
|
read_unlocked = 0;
|
||||||
} else {
|
} else {
|
||||||
//If User has requested an unlocked read, but we're unable to unlock the card, we'll error out.
|
//If User has requested an unlocked read, but we're unable to unlock the card, we'll error out.
|
||||||
if (!unlock_card()) {
|
if (!unlock_card(false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,7 +422,7 @@ read_card(int read_unlocked)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
write_card(int write_block_zero)
|
write_card(bool write_block_zero)
|
||||||
{
|
{
|
||||||
uint32_t uiBlock;
|
uint32_t uiBlock;
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
|
@ -411,24 +430,22 @@ write_card(int write_block_zero)
|
||||||
|
|
||||||
//Determine if we have to unlock the card
|
//Determine if we have to unlock the card
|
||||||
if (write_block_zero) {
|
if (write_block_zero) {
|
||||||
//If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
|
if (!magic2 && !magic3) {
|
||||||
//need to use the W mode. We'll trigger a warning and let them proceed.
|
if (!unlock_card(true)) {
|
||||||
if (magic2) {
|
|
||||||
printf("Note: This card does not require an unlocked write (W) \n");
|
|
||||||
write_block_zero = 0;
|
|
||||||
} else {
|
|
||||||
//If User has requested an unlocked write, but we're unable to unlock the card, we'll error out.
|
|
||||||
if (!unlock_card()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Writing %d blocks |", uiBlocks + 1);
|
printf("Writing %d blocks |", uiBlocks + write_block_zero);
|
||||||
// Completely write the card, end to start, but skipping block 0
|
// Completely write the card, but skipping block 0 if we don't need to write on it
|
||||||
for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
|
for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
|
||||||
|
//Determine if we have to write block 0
|
||||||
|
if (!write_block_zero && uiBlock == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Authenticate everytime we reach the first sector of a new block
|
// Authenticate everytime we reach the first sector of a new block
|
||||||
if (is_first_block(uiBlock)) {
|
if (uiBlock == 1 || is_first_block(uiBlock)) {
|
||||||
if (bFailure) {
|
if (bFailure) {
|
||||||
// When a failure occured we need to redo the anti-collision
|
// When a failure occured we need to redo the anti-collision
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
||||||
|
@ -444,12 +461,13 @@ write_card(int write_block_zero)
|
||||||
// If we are are writing to a chinese magic card, we've already unlocked
|
// If we are are writing to a chinese magic card, we've already unlocked
|
||||||
// If we're writing to a One Time Write card, we need to authenticate
|
// If we're writing to a One Time Write card, we need to authenticate
|
||||||
// If we're writing something else, we'll need to authenticate
|
// If we're writing something else, we'll need to authenticate
|
||||||
if ((write_block_zero && magic3) || !write_block_zero) {
|
if ((write_block_zero && (magic2 || magic3)) || !write_block_zero) {
|
||||||
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
||||||
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (is_trailer_block(uiBlock)) {
|
if (is_trailer_block(uiBlock)) {
|
||||||
if (bFormatCard) {
|
if (bFormatCard) {
|
||||||
|
@ -470,10 +488,6 @@ write_card(int write_block_zero)
|
||||||
bFailure = true;
|
bFailure = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The first block 0x00 is read only, skip this
|
|
||||||
if (uiBlock == 0 && !write_block_zero && !magic2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Make sure a earlier write did not fail
|
// Make sure a earlier write did not fail
|
||||||
if (!bFailure) {
|
if (!bFailure) {
|
||||||
// Try to write the data block
|
// Try to write the data block
|
||||||
|
@ -484,7 +498,7 @@ write_card(int write_block_zero)
|
||||||
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
||||||
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
||||||
if (uiBlock == 0) {
|
if (uiBlock == 0) {
|
||||||
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
|
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) {
|
||||||
printf("!\nError: incorrect BCC in MFD file!\n");
|
printf("!\nError: incorrect BCC in MFD file!\n");
|
||||||
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
||||||
return false;
|
return false;
|
||||||
|
@ -494,88 +508,29 @@ write_card(int write_block_zero)
|
||||||
bFailure = true;
|
bFailure = true;
|
||||||
printf("Failure to write to data block %i\n", uiBlock);
|
printf("Failure to write to data block %i\n", uiBlock);
|
||||||
}
|
}
|
||||||
|
if (uiBlock == 0 && (magic2 || magic3)) {
|
||||||
|
if (nfc_initiator_init(pnd) < 0) {
|
||||||
|
nfc_perror(pnd, "nfc_initiator_init");
|
||||||
|
nfc_close(pnd);
|
||||||
|
nfc_exit(context);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
};
|
||||||
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
||||||
|
printf("!\nError: tag was removed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("Failure during write process.\n");
|
printf("Failure during write process.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
// Show if the write went well for each block
|
// Show if the write went well for each block
|
||||||
print_success_or_failure(bFailure, &uiWriteBlocks);
|
print_success_or_failure(bFailure, &uiWriteBlocks);
|
||||||
if ((! bTolerateFailures) && bFailure)
|
if ((! bTolerateFailures) && bFailure)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Write Block 0 if necessary
|
|
||||||
if (write_block_zero || magic2 || magic3) {
|
|
||||||
for (uiBlock = 0; uiBlock < 4; uiBlock++) {
|
|
||||||
|
|
||||||
// The first block 0x00 is read only, skip this
|
|
||||||
if (uiBlock == 0) {
|
|
||||||
//If the card is not magic, we're gonna skip over
|
|
||||||
if (write_block_zero || magic2 || magic3) {
|
|
||||||
//NOP
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_first_block(uiBlock)) {
|
|
||||||
if (bFailure) {
|
|
||||||
// When a failure occured we need to redo the anti-collision
|
|
||||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
|
||||||
printf("!\nError: tag was removed\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bFailure = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
// Try to authenticate for the current sector
|
|
||||||
// If we are are writing to a chinese magic card, we've already unlocked
|
|
||||||
// If we're writing to a One Time Write, we need to authenticate
|
|
||||||
// If we're writing something else, we'll need to authenticate
|
|
||||||
if ((write_block_zero && magic3) || !write_block_zero) {
|
|
||||||
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
|
||||||
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure a earlier write did not fail
|
|
||||||
if (!bFailure) {
|
|
||||||
// Try to write the data block
|
|
||||||
if (bFormatCard && uiBlock)
|
|
||||||
memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
|
|
||||||
else
|
|
||||||
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
|
||||||
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
|
||||||
if (uiBlock == 0) {
|
|
||||||
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
|
|
||||||
printf("!\nError: incorrect BCC in MFD file!\n");
|
|
||||||
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
|
|
||||||
bFailure = true;
|
|
||||||
printf("Failure to write to data block %i\n", uiBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
printf("Failure during write process.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show if the write went well for each block
|
|
||||||
print_success_or_failure(bFailure, &uiWriteBlocks);
|
|
||||||
if ((! bTolerateFailures) && bFailure)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("|\n");
|
printf("|\n");
|
||||||
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -593,18 +548,25 @@ static void
|
||||||
print_usage(const char *pcProgramName)
|
print_usage(const char *pcProgramName)
|
||||||
{
|
{
|
||||||
printf("Usage: ");
|
printf("Usage: ");
|
||||||
|
#ifndef _WIN32
|
||||||
|
printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f] [v]]\n", pcProgramName);
|
||||||
|
#else
|
||||||
printf("%s f|r|R|w|W a|b u|U<01ab23cd> <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);
|
||||||
|
#endif
|
||||||
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(" *** unlocking (W) also works for rewriting block 0 in gen2 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(" 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");
|
||||||
|
#ifndef _WIN32
|
||||||
|
printf(" v - Sends libnfc log output to console (optional)\n");
|
||||||
|
#endif
|
||||||
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 u mycard.mfd\n\n", pcProgramName);
|
printf(" %s r a u mycard.mfd\n\n", pcProgramName);
|
||||||
|
@ -620,7 +582,7 @@ print_usage(const char *pcProgramName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool is_directwrite(void)
|
static bool is_directwrite(bool test_write)
|
||||||
{
|
{
|
||||||
printf("Checking if Badge is DirectWrite...\n");
|
printf("Checking if Badge is DirectWrite...\n");
|
||||||
|
|
||||||
|
@ -634,7 +596,7 @@ static bool is_directwrite(void)
|
||||||
bUseKeyFile = false;
|
bUseKeyFile = false;
|
||||||
// Try to authenticate for the current sector
|
// Try to authenticate for the current sector
|
||||||
if (!authenticate(0)) {
|
if (!authenticate(0)) {
|
||||||
printf("!\nError: authentication failed for block 0x%02x\n", 0);
|
printf("!\nError: authentication failed for block 0x00\n");
|
||||||
bUseKeyFile = orig_bUseKeyFile;
|
bUseKeyFile = orig_bUseKeyFile;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -653,14 +615,17 @@ static bool is_directwrite(void)
|
||||||
printf(" Original UID: %02x%02x%02x%02x\n",
|
printf(" Original UID: %02x%02x%02x%02x\n",
|
||||||
original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
|
original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
|
||||||
} else {
|
} else {
|
||||||
printf("!\nError: unable to read block 0x%02x\n", 0);
|
printf("!\nError: unable to read block 0x00\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!test_write)
|
||||||
|
return true;
|
||||||
|
|
||||||
printf(" Attempt to write Block 0 ...\n");
|
printf(" Attempt to write Block 0 ...\n");
|
||||||
memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
|
memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
|
||||||
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
|
||||||
printf("Failure to write to data block %i\n", 0);
|
printf("Failure to write to data block 0\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printf(" Block 0 written successfully\n");
|
printf(" Block 0 written successfully\n");
|
||||||
|
@ -676,7 +641,7 @@ main(int argc, const char *argv[])
|
||||||
uint8_t _tag_uid[4];
|
uint8_t _tag_uid[4];
|
||||||
uint8_t *tag_uid = _tag_uid;
|
uint8_t *tag_uid = _tag_uid;
|
||||||
|
|
||||||
int unlock = 0;
|
bool unlock = false;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
|
@ -691,19 +656,19 @@ main(int argc, const char *argv[])
|
||||||
if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
|
if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
|
||||||
atAction = ACTION_READ;
|
atAction = ACTION_READ;
|
||||||
if (strcmp(command, "R") == 0)
|
if (strcmp(command, "R") == 0)
|
||||||
unlock = 1;
|
unlock = true;
|
||||||
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 > 5);
|
bUseKeyFile = (argc > 5) && strcmp(argv[5], "v");
|
||||||
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "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)
|
||||||
unlock = 1;
|
unlock = true;
|
||||||
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 > 5);
|
bUseKeyFile = (argc > 5) && strcmp(argv[5], "v");
|
||||||
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
|
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
|
||||||
}
|
}
|
||||||
if (argv[3][0] == 'U') {
|
if (argv[3][0] == 'U') {
|
||||||
|
@ -725,6 +690,21 @@ main(int argc, const char *argv[])
|
||||||
tag_uid = NULL;
|
tag_uid = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Send noise from lib to /dev/null
|
||||||
|
bool verbose = false;
|
||||||
|
if (argv[7]) {
|
||||||
|
if (strcmp(argv[7], "v") == 0) verbose = true;
|
||||||
|
} else {
|
||||||
|
if ((strcmp(argv[6], "v")) || (strcmp(argv[5], "v")) == 0) verbose = true;
|
||||||
|
}
|
||||||
|
if (!verbose) {
|
||||||
|
int fd = open("/dev/null", O_WRONLY);
|
||||||
|
dup2(fd, 2);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (atAction == ACTION_USAGE) {
|
if (atAction == ACTION_USAGE) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -764,6 +744,14 @@ main(int argc, const char *argv[])
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Drop the field for a while, so can be reset
|
||||||
|
if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, true) < 0) {
|
||||||
|
nfc_perror(pnd, "nfc_device_set_property_bool activate field");
|
||||||
|
nfc_close(pnd);
|
||||||
|
nfc_exit(context);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
// Let the reader only try once to find a tag
|
// Let the reader only try once to find a tag
|
||||||
if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
|
if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
|
||||||
nfc_perror(pnd, "nfc_device_set_property_bool");
|
nfc_perror(pnd, "nfc_device_set_property_bool");
|
||||||
|
@ -779,11 +767,24 @@ main(int argc, const char *argv[])
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure the CRC and Parity settings
|
||||||
|
if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
|
||||||
|
nfc_perror(pnd, "nfc_device_set_property_bool crc");
|
||||||
|
nfc_close(pnd);
|
||||||
|
nfc_exit(context);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, true) < 0) {
|
||||||
|
nfc_perror(pnd, "nfc_device_set_property_bool parity");
|
||||||
|
nfc_close(pnd);
|
||||||
|
nfc_exit(context);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
int tags;
|
int tags;
|
||||||
|
|
||||||
tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
|
tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
|
||||||
if (tags <= 0) {
|
if (tags <= 0) {
|
||||||
printf("Error: no tag was found\n");
|
printf("Error: no tag was found\n");
|
||||||
|
@ -792,7 +793,8 @@ main(int argc, const char *argv[])
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
// Test if we are dealing with a MIFARE compatible tag
|
// Test if we are dealing with a MIFARE compatible tag
|
||||||
if ((nt.nti.nai.btSak & 0x08) == 0) {
|
if (((nt.nti.nai.btSak & 0x08) == 0) && (nt.nti.nai.btSak != 0x01)) {
|
||||||
|
// if ((nt.nti.nai.btSak & 0x08) == 0) {
|
||||||
printf("Warning: tag is probably not a MFC!\n");
|
printf("Warning: tag is probably not a MFC!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,12 +852,15 @@ main(int argc, const char *argv[])
|
||||||
|
|
||||||
//If size is 4k check for direct-write card
|
//If size is 4k check for direct-write card
|
||||||
if (uiBlocks == 0xff) {
|
if (uiBlocks == 0xff) {
|
||||||
if (is_directwrite()) {
|
if (is_directwrite(atAction == ACTION_WRITE)) {
|
||||||
printf("Card is DirectWrite\n");
|
printf("Card is DirectWrite\n");
|
||||||
magic3 = true;
|
magic3 = true;
|
||||||
unlock = 0;
|
|
||||||
} else {
|
} else {
|
||||||
printf("Card is not DirectWrite\n");
|
printf("Card is not DirectWrite\n");
|
||||||
|
// reset after error
|
||||||
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
|
||||||
|
ERR("tag was removed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -864,7 +869,6 @@ main(int argc, const char *argv[])
|
||||||
pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
|
pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
|
||||||
printf("Card appears to be a One Time Write Card..\n");
|
printf("Card appears to be a One Time Write Card..\n");
|
||||||
magic3 = true;
|
magic3 = true;
|
||||||
unlock = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue