Add CUID card support
This commit is contained in:
parent
b7dbacf5cf
commit
e21e9c6410
@ -37,15 +37,33 @@ option to format the card will reset all keys to FFFFFFFFFFFF, all data to 00 an
|
||||
|
||||
The
|
||||
.B 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
|
||||
option performs a write operation on special MIFARE Classic cards, that can
|
||||
be 'unlocked' to allow block 0 to be modified ('generation 1 Chinese magic
|
||||
cards'). Similarly, the
|
||||
.B R
|
||||
option allows an 'unlocked' read. This bypasses authentication and allows
|
||||
reading of the Key A and Key B data regardless of ACLs.
|
||||
|
||||
The
|
||||
.B C
|
||||
option performs a write operation on special MIFARE Classic cards, that allow
|
||||
block 0 to be modified by the regular write command ('generation 2 Chinese
|
||||
magic cards'/'CUID direct-write cards'). This type of card does not reply to
|
||||
the backdoor/unlock command of generation 1 cards and is therefore harder to
|
||||
detect.
|
||||
|
||||
*** Note that
|
||||
.B W
|
||||
,
|
||||
.B R
|
||||
and
|
||||
.B C
|
||||
options only work on Chinese magic cards (clones of MIFARE Classic cards, that
|
||||
have a modifiable block 0). Rewriting block 0 allows for modification of
|
||||
manufacturer data such as the UID. Writing bad manufacturer data into block 0
|
||||
(e.g. bad BCC) may permanantly brick a Chinese magic card. Currently, only
|
||||
4-byte UIDs are supported.
|
||||
|
||||
R/W errors on some blocks can be either considered as critical or ignored.
|
||||
To halt on first error, specify keys with lowercase (
|
||||
.B a
|
||||
@ -66,25 +84,21 @@ hexadecimal UID to the U option. For example U01ab23cd for the 4 byte UID
|
||||
parameter instead will use whatever libnfc decides which generally is the lowest
|
||||
UID.
|
||||
|
||||
*** Note that
|
||||
.B W
|
||||
and
|
||||
.B R
|
||||
options only work on special versions of MIFARE 1K cards (Chinese clones).
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR f " | " r " | " R " | " w " | " W
|
||||
.BR f " | " r " | " R " | " w " | " W " | " C
|
||||
Perform format (
|
||||
.B f
|
||||
) or read from (
|
||||
.B r
|
||||
) or unlocked read from (
|
||||
) or unlocked/gen1 read from (
|
||||
.B R
|
||||
) or write to (
|
||||
.B w
|
||||
) or unlocked write to (
|
||||
) or unlocked/gen1 write to (
|
||||
.B W
|
||||
) or direct/CUID/gen2 write to (
|
||||
C
|
||||
) card.
|
||||
.TP
|
||||
.BR a " | " A " | " b " | " B
|
||||
|
||||
@ -70,6 +70,7 @@ static bool bForceKeyFile;
|
||||
static bool bTolerateFailures;
|
||||
static bool bFormatCard;
|
||||
static bool magic_type2a = false;
|
||||
static bool magic_type2b = false;
|
||||
static bool unlocked = false;
|
||||
static uint8_t uiBlocks;
|
||||
static uint8_t keys[] = {
|
||||
@ -315,7 +316,7 @@ read_card(int read_unlocked)
|
||||
if (read_unlocked) {
|
||||
//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.
|
||||
if (magic_type2a) {
|
||||
if (magic_type2a || magic_type2b) {
|
||||
printf("Note: This card does not require an unlocked read (R) \n");
|
||||
read_unlocked = false;
|
||||
} else {
|
||||
@ -395,7 +396,7 @@ write_card(bool write_unlocked)
|
||||
if (write_unlocked) {
|
||||
//If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
|
||||
//need to use the W mode. We'll trigger a warning and let them proceed.
|
||||
if (magic_type2a) {
|
||||
if (magic_type2a || magic_type2b) {
|
||||
printf("Note: This card does not require an unlocked write (W) \n");
|
||||
write_unlocked = false;
|
||||
} else {
|
||||
@ -449,7 +450,7 @@ write_card(bool write_unlocked)
|
||||
}
|
||||
} else {
|
||||
// The first block 0x00 is read only, skip this
|
||||
if (uiBlock == 0 && !write_unlocked && !magic_type2a)
|
||||
if (uiBlock == 0 && !(write_unlocked || magic_type2a || magic_type2b))
|
||||
continue;
|
||||
|
||||
|
||||
@ -476,6 +477,21 @@ write_card(bool write_unlocked)
|
||||
print_success_or_failure(bFailure, &uiWriteBlocks);
|
||||
if ((!bTolerateFailures) && bFailure)
|
||||
return false;
|
||||
if (uiBlock == 0 && magic_type2b)
|
||||
{
|
||||
// CUID card must be selected again after writing of block0
|
||||
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
||||
printf("Error: tag disappeared after writing block 0\n");
|
||||
nfc_close(pnd);
|
||||
nfc_exit(context);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Re-authenticate to sector 0 for writing of remaining blocks
|
||||
if (!authenticate(uiBlock)) {
|
||||
printf("!\nError: re-authentication failed for block %02x\n", uiBlock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("|\n");
|
||||
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
||||
@ -495,11 +511,10 @@ print_usage(const char *pcProgramName)
|
||||
{
|
||||
printf("Usage: ");
|
||||
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(" f|r|R|w|W|C - Perform format (f) or read from (r) or unlocked/gen1 read from (R) or write to (w) or unlocked/gen1\n");
|
||||
printf(" write to (W) or direct/CUID/gen2 write to (C) card\n");
|
||||
printf(" *** Options (R), (W) and (C) only work on Chinese magic cards (read manpage to prevent bricking them!)\n");
|
||||
printf(" *** Format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\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");
|
||||
@ -547,10 +562,12 @@ main(int argc, const char *argv[])
|
||||
bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
|
||||
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) {
|
||||
} else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "C") == 0 || strcmp(command, "f") == 0) {
|
||||
atAction = ACTION_WRITE;
|
||||
if (strcmp(command, "W") == 0)
|
||||
unlock = true;
|
||||
if (strcmp(command, "C") == 0)
|
||||
magic_type2b = true;
|
||||
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]));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user