Merge pull request #350 from oliv3r/master

Allow mfultralight and mfc tools to work also with specific UID's
This commit is contained in:
Romuald Conty 2016-05-15 11:48:39 +02:00
commit 403650a0fc
3 changed files with 162 additions and 52 deletions

View file

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

View file

@ -491,26 +491,29 @@ static void
print_usage(const char *pcProgramName)
{
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(" *** 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(" *** 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(" 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(" <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("Examples: \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(" %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(" %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(" %s f A dummy.mfd keyfile.mfd f\n", pcProgramName);
printf(" %s f B dummy.mfd keyfile.mfd f\n\n", pcProgramName);
printf(" %s f A u dummy.mfd keyfile.mfd f\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
@ -518,6 +521,9 @@ main(int argc, const char *argv[])
{
action_t atAction = ACTION_USAGE;
uint8_t *pbtUID;
uint8_t _tag_uid[4];
uint8_t *tag_uid = _tag_uid;
int unlock = 0;
if (argc < 2) {
@ -526,31 +532,45 @@ main(int argc, const char *argv[])
}
const char *command = argv[1];
if (argc < 5) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
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';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 4);
bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
bUseKeyFile = (argc > 5);
bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
if (argc < 4) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
atAction = ACTION_WRITE;
if (strcmp(command, "W") == 0)
unlock = 1;
bFormatCard = (strcmp(command, "f") == 0);
bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
bUseKeyFile = (argc > 4);
bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
bUseKeyFile = (argc > 5);
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) {
@ -559,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
if (bUseKeyFile) {
FILE *pfKeys = fopen(argv[4], "rb");
FILE *pfKeys = fopen(argv[5], "rb");
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);
}
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);
exit(EXIT_FAILURE);
}
@ -610,7 +630,10 @@ main(int argc, const char *argv[])
printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
// 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");
nfc_close(pnd);
nfc_exit(context);
@ -672,13 +695,13 @@ main(int argc, const char *argv[])
printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16);
if (bUseKeyFile) {
FILE *pfKeys = fopen(argv[4], "rb");
FILE *pfKeys = fopen(argv[5], "rb");
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);
}
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);
exit(EXIT_FAILURE);
}
@ -688,16 +711,16 @@ main(int argc, const char *argv[])
if (atAction == ACTION_READ) {
memset(&mtDump, 0x00, sizeof(mtDump));
} else {
FILE *pfDump = fopen(argv[3], "rb");
FILE *pfDump = fopen(argv[4], "rb");
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);
}
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);
exit(EXIT_FAILURE);
}
@ -707,17 +730,17 @@ main(int argc, const char *argv[])
if (atAction == ACTION_READ) {
if (read_card(unlock)) {
printf("Writing data to file: %s ...", argv[3]);
printf("Writing data to file: %s ...", argv[4]);
fflush(stdout);
FILE *pfDump = fopen(argv[3], "wb");
FILE *pfDump = fopen(argv[4], "wb");
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_exit(context);
exit(EXIT_FAILURE);
}
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);
nfc_close(pnd);
nfc_exit(context);

View file

@ -58,11 +58,15 @@
#include "nfc-utils.h"
#include "mifare.h"
#define MAX_TARGET_COUNT 16
#define MAX_UID_LEN 10
#define BLOCK_COUNT 0xf
static nfc_device *pnd;
static nfc_target nt;
static mifare_param mp;
static mifareul_tag mtDump;
static uint32_t uiBlocks = 0xF;
static const uint32_t uiBlocks = BLOCK_COUNT;
// special unlock command
uint8_t abtUnlock1[1] = { 0x40 };
@ -180,7 +184,7 @@ unlock_card(void)
static bool check_magic() {
bool bFailure = false;
int uid_data;
int uid_data;
for (uint32_t page = 0; page <= 1; page++) {
// Show if the readout went well
@ -194,27 +198,27 @@ static bool check_magic() {
}
uid_data = 0x00000000;
memcpy(mp.mpd.abtData, &uid_data, sizeof uid_data);
memset(mp.mpd.abtData + 4, 0, 12);
//Force the write without checking for errors - otherwise the writes to the sector 0 seem to complain
nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp);
}
//Check that the ID is now set to 0x000000000000
if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
//printf("%u", mp.mpd.abtData);
bool result = true;
for(int i = 0; i <= 7; i++) {
if (mp.mpd.abtData[i] != 0x00) result = false;
}
}
if (result) {
if (result) {
return true;
}
}
}
//Initially check if we can unlock via the MF method
if (unlock_card()) {
@ -235,7 +239,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
char buffer[BUFSIZ];
if (!write_otp) {
if (!write_otp) {
printf("Write OTP bytes ? [yN] ");
if (!fgets(buffer, BUFSIZ, stdin)) {
ERR("Unable to read standard input.");
@ -243,7 +247,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
}
if (!write_lock) {
if (!write_lock) {
printf("Write Lock bytes ? [yN] ");
if (!fgets(buffer, BUFSIZ, stdin)) {
ERR("Unable to read standard input.");
@ -251,7 +255,7 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
}
if (!write_uid) {
if (!write_uid) {
printf("Write UID bytes (only for special writeable UID cards) ? [yN] ");
if (!fgets(buffer, BUFSIZ, stdin)) {
ERR("Unable to read standard input.");
@ -267,12 +271,12 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
} else {
if (!check_magic()) {
printf("\nUnable to unlock card - are you sure the card is magic?\n");
return false;
bFailure = false;
return false;
}
}
for (int page = uiSkippedPages; page <= 0xF; page++) {
for (uint32_t page = uiSkippedPages; page <= ((uiBlocks / 4) * 4); page++) {
if ((page == 0x2) && (!write_lock)) {
printf("s");
uiSkippedPages++;
@ -310,6 +314,57 @@ write_card(bool write_otp, bool write_lock, bool write_uid)
return true;
}
static int list_passive_targets(nfc_device *_pnd)
{
int res = 0;
nfc_target ant[MAX_TARGET_COUNT];
if (nfc_initiator_init(_pnd) < 0) {
return -EXIT_FAILURE;
}
if ((res = nfc_initiator_list_passive_targets(_pnd, nmMifare, ant, MAX_TARGET_COUNT)) >= 0) {
int i;
if (res > 0)
printf("%d ISO14443A passive target(s) found:\n", res);
for (i = 0; i < res; i++) {
size_t szPos;
printf("\t");
for (szPos = 0; szPos < ant[i].nti.nai.szUidLen; szPos++) {
printf("%02x", ant[i].nti.nai.abtUid[szPos]);
}
printf("\n");
}
}
return 0;
}
static size_t str_to_uid(const char *str, uint8_t *uid)
{
uint8_t i;
memset(uid, 0x0, MAX_UID_LEN);
i = 0;
while ((*str != '\0') && ((i >> 1) < MAX_UID_LEN) ) {
char nibble[2] = { 0x00, '\n' }; /* for strtol */
nibble[0] = *str++;
if (isxdigit(nibble[0])) {
if (isupper(nibble[0]))
nibble[0] = tolower(nibble[0]);
uid[i >> 1] |= strtol(nibble, NULL, 16) << ((i % 2) ? 0 : 4) & ((i % 2) ? 0x0f : 0xf0);
i++;
}
}
return i >> 1;
}
static void
print_usage(const char *argv[])
{
@ -321,18 +376,21 @@ print_usage(const char *argv[])
printf("\t--lock\t\t - Don't prompt for Lockbit writing (Assume yes)\n");
printf("\t--uid\t\t - Don't prompt for UID writing (Assume yes)\n");
printf("\t--full\t\t - Assume full card write (UID + OTP + Lockbit)\n");
printf("\t--with-uid <UID>\t\t - Specify UID to read/write from\n");
}
int
main(int argc, const char *argv[])
{
int iAction = 0;
uint8_t iUID[MAX_UID_LEN] = { 0x0 };
size_t szUID = 0;
bool bOTP = false;
bool bLock = false;
bool bUID = false;
FILE *pfDump;
if (argc == 0) {
if (argc < 2) {
print_usage(argv);
exit(EXIT_FAILURE);
}
@ -345,6 +403,12 @@ main(int argc, const char *argv[])
iAction = 1;
} else if (0 == strcmp(argv[arg], "w")) {
iAction = 2;
} else if (0 == strcmp(argv[arg], "--with-uid")) {
if (argc < 5) {
ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4");
exit(EXIT_FAILURE);
}
szUID = str_to_uid(argv[4], iUID);
} else if (0 == strcmp(argv[arg], "--full")) {
bOTP = true;
bLock = true;
@ -359,7 +423,7 @@ main(int argc, const char *argv[])
iAction = 3;
} else {
//Skip validation of the filename
if (arg != 2) {
if ((arg != 2) && (arg != 4)) {
ERR("%s is not supported option.", argv[arg]);
print_usage(argv);
exit(EXIT_FAILURE);
@ -390,7 +454,7 @@ main(int argc, const char *argv[])
ERR("Unable to determine operating mode");
exit(EXIT_FAILURE);
}
nfc_context *context;
nfc_init(&context);
if (context == NULL) {
@ -405,6 +469,14 @@ main(int argc, const char *argv[])
nfc_exit(context);
exit(EXIT_FAILURE);
}
printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
if (list_passive_targets(pnd)) {
nfc_perror(pnd, "nfc_device_set_property_bool");
nfc_close(pnd);
nfc_exit(context);
exit(EXIT_FAILURE);
}
if (nfc_initiator_init(pnd) < 0) {
nfc_perror(pnd, "nfc_initiator_init");
@ -421,10 +493,8 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE);
}
printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
// Try to find a MIFARE Ultralight tag
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) {
ERR("no tag was found\n");
nfc_close(pnd);
nfc_exit(context);
@ -439,7 +509,7 @@ main(int argc, const char *argv[])
exit(EXIT_FAILURE);
}
// Get the info from the current tag
printf("Found MIFARE Ultralight card with UID: ");
printf("Using MIFARE Ultralight card with UID: ");
size_t szPos;
for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) {
printf("%02x", nt.nti.nai.abtUid[szPos]);