diff --git a/utils/nfc-mfclassic.c b/utils/nfc-mfclassic.c index bc3fe6c..ba07b6f 100644 --- a/utils/nfc-mfclassic.c +++ b/utils/nfc-mfclassic.c @@ -10,6 +10,7 @@ * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: * Copyright (C) 2011-2013 Adam Laurie + * Copyright (C) 2018-2019 Danielle Bruneo * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -70,7 +71,9 @@ static bool bForceKeyFile; static bool bTolerateFailures; static bool bFormatCard; static bool magic2 = false; +static bool magic3 = false; static bool unlocked = false; +static bool bForceSizeMismatch; static uint8_t uiBlocks; static uint8_t keys[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -208,10 +211,18 @@ authenticate(uint32_t uiBlock) // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) return true; - } + } else if (magic3) { + //If it's a One Time Write card, we're gonna authenticate with the default keys + memcpy(mp.mpa.abtKey, default_key, sizeof(default_key)); + + + // Try to authenticate for the current sector + if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { + return true; + } // If formatting or not using key file, try to guess the right key - if (bFormatCard || !bUseKeyFile) { + } else if (bFormatCard || !bUseKeyFile) { for (size_t key_index = 0; key_index < num_keys; key_index++) { memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6); if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { @@ -352,10 +363,17 @@ read_card(int read_unlocked) if (read_unlocked) { memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData)); } else { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA)); - memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); - memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB)); + //If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL + if (magic3) { + memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key)); + memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); + memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key)); + } else { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA)); + memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits)); + memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB)); + } } } else { printf("!\nfailed to read trailer block 0x%02x\n", iBlock); @@ -392,6 +410,7 @@ write_card(int write_block_zero) bool bFailure = false; uint32_t uiWriteBlocks = 0; + //Determine if we have to unlock the card if (write_block_zero) { //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. @@ -407,8 +426,8 @@ write_card(int write_block_zero) } printf("Writing %d blocks |", uiBlocks + 1); - // Write the card from begin to end; - for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { + // Completely write the card, end to start, but skipping block 0 + for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { if (bFailure) { @@ -423,44 +442,116 @@ write_card(int write_block_zero) fflush(stdout); // Try to authenticate for the current sector - if (!write_block_zero && !authenticate(uiBlock) && !bTolerateFailures) { - printf("!\nError: authentication failed for block %02x\n", uiBlock); - return false; + // 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 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; + } + } + + if (is_trailer_block(uiBlock)) { + if (bFormatCard) { + // Copy the default key and reset the access bits + memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA)); + memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits)); + memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB)); + } else { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA)); + memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits)); + memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB)); + } + + // Try to write the trailer + if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { + printf("failed to write trailer block %d \n", uiBlock); + bFailure = true; + } + } 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 + 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; + } - if (is_trailer_block(uiBlock)) { - if (bFormatCard) { - // Copy the default key and reset the access bits - memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA)); - memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits)); - memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB)); - } else { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA)); - memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits)); - memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB)); + //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; + } + } } - // Try to write the trailer - if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { - printf("failed to write trailer block %d \n", uiBlock); - bFailure = true; - } - } 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) { - // Try to write the data block + // 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! + // 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"); @@ -468,15 +559,24 @@ write_card(int write_block_zero) return false; } } - if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) + 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; + } - // Show if the write went well for each block - print_success_or_failure(bFailure, &uiWriteBlocks); - if ((!bTolerateFailures) && bFailure) - return false; + } + printf("|\n"); printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); fflush(stdout); @@ -505,6 +605,7 @@ print_usage(const char *pcProgramName) printf(" - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); printf(" - 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 u mycard.mfd\n\n", pcProgramName); @@ -519,6 +620,54 @@ print_usage(const char *pcProgramName) printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName); } + +bool is_directwrite(){ + printf("Checking if Badge is DirectWrite...\n"); + + // Set default keys + memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key)); + memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits)); + memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key)); + + // Temporarly override bUseKeyFile + bool orig_bUseKeyFile=bUseKeyFile; + bUseKeyFile=false; + // Try to authenticate for the current sector + if (!authenticate(0)) { + printf("!\nError: authentication failed for block 0x%02x\n", 0); + bUseKeyFile=orig_bUseKeyFile; + return false; + } + // restore bUseKeyFile + bUseKeyFile=orig_bUseKeyFile; + + // Try to read block 0 + uint8_t original_b0[16]; + if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { + memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData)); + printf(" Original Block 0: "); + for(int i=0;i<16;i++){ + printf("%02x", original_b0[i]); + } + printf("\n"); + printf(" Original UID: %02x%02x%02x%02x\n", + original_b0[0], original_b0[1], original_b0[2], original_b0[3]); + } else { + printf("!\nError: unable to read block 0x%02x\n", 0); + return false; + } + + printf(" Attempt to write Block 0 ...\n"); + memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0)); + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) { + printf("Failure to write to data block %i\n", 0); + return false; + } + printf(" Block 0 written successfully\n"); + + return true; +} + int main(int argc, const char *argv[]) { @@ -697,6 +846,26 @@ main(int argc, const char *argv[]) } printf("Guessing size: seems to be a %lu-byte card\n", (uiBlocks + 1) * sizeof(mifare_classic_block)); + //If size is 4k check for direct-write card + if (uiBlocks == 0xff) { + if (is_directwrite()){ + printf("Card is DirectWrite\n"); + magic3=true; + unlock=0; + } else { + printf("Card is not DirectWrite\n"); + } + } + + //Check to see if we have a One Time Write badge (magic3) + if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 && + pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) { + printf("Card appears to be a One Time Write Card..\n"); + magic3 = true; + unlock = 0; + } + + if (bUseKeyFile) { FILE *pfKeys = fopen(argv[5], "rb"); if (pfKeys == NULL) { diff --git a/utils/nfc-mfultralight.c b/utils/nfc-mfultralight.c index 3fe2100..8ae641f 100644 --- a/utils/nfc-mfultralight.c +++ b/utils/nfc-mfultralight.c @@ -10,6 +10,7 @@ * See AUTHORS file for a more comprehensive list of contributors. * Additional contributors of this file: * Copyright (C) 2013-2018 Adam Laurie + * Copyright (C) 2018-2019 Daniele Bruneo * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -290,50 +291,48 @@ unlock_card(void) return true; } -static bool check_magic() -{ - bool bFailure = false; - int uid_data; +static bool check_magic() { + // Firstly try to directly read and re-write the first three pages + // if this fail try to unlock with chinese magic backdoor - for (uint32_t page = 0; page <= 1; page++) { - // Show if the readout went well - 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) { - ERR("tag was removed"); - return false; - } - bFailure = false; - } - - 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 + bool directWrite = true; + // Try to read pages 0, 1, 2 + uint8_t original_b0[12]; + printf("Checking if UL badge is DirectWrite...\n"); 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; + memcpy(original_b0, mp.mpd.abtData, 12); + printf(" Original Block 0 (Pages 0-2): "); + for(int i=0;i<12;i++){ + printf("%02x", original_b0[i]); } - - if (result) { - return true; - } - + printf("\n"); + printf(" Original UID: %02x%02x%02x%02x%02x%02x%02x\n", + original_b0[0], original_b0[1], original_b0[2], original_b0[4], original_b0[5], original_b0[6], original_b0[7]); + } else { + printf("!\nError: unable to read block 0x%02x\n", 0); + directWrite = false; } - - //Initially check if we can unlock via the MF method - if (unlock_card()) { + printf(" Attempt to write Block 0 (pages 0-2) ...\n"); + for (uint32_t page = 0; page <= 2; page++) { + printf(" Writing Page %i:", page); + memcpy(mp.mpd.abtData, original_b0 + page*4, 4); + for(int i=0;i<4;i++){ + printf(" %02x", mp.mpd.abtData[i]); + } + printf("\n"); + if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) { + printf(" Failure writing Page %i\n", page); + directWrite = false; + break; + } + } + if(directWrite){ + printf(" Block 0 written successfully\n"); + printf("Card is DirectWrite\n"); return true; } else { - return false; + printf("Card is not DirectWrite\n"); + return unlock_card(); } } @@ -383,9 +382,9 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } - printf("Writing %d pages |", uiBlocks); /* We may need to skip 2 first pages. */ if (!write_uid) { + printf("Writing %d pages |", uiBlocks); printf("ss"); uiSkippedPages = 2; } else { @@ -393,6 +392,7 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid) printf("\nUnable to unlock card - are you sure the card is magic?\n"); return false; } + printf("Writing %d pages |", uiBlocks); } for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) { @@ -527,7 +527,7 @@ main(int argc, const char *argv[]) bool bFilename = false; FILE *pfDump; - if (argc < 3) { + if (argc == 0) { print_usage(argv); exit(EXIT_FAILURE); } @@ -580,7 +580,7 @@ main(int argc, const char *argv[]) } } } - if (! bFilename) { + if (iAction != 3 && !bFilename) { ERR("Please supply a Mifare Dump filename"); exit(EXIT_FAILURE); } @@ -650,7 +650,7 @@ main(int argc, const char *argv[]) if (get_ev1_version()) { if (!bPWD) printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n"); - if (abtRx[6] == 0x0b) { + if (abtRx[6] == 0x0b || abtRx[6] == 0x00) { printf("EV1 type: MF0UL11 (48 bytes)\n"); uiBlocks = 20; // total number of 4 byte 'pages' iDumpSize = uiBlocks * 4;