read_card(int read_unlocked) { uint iBlock; bool bFailure = false; uint uiReadBlocks = 0; if (read_unlocked != 0) { if (!unlock_card()) { return(false); } } //printf("Reading out %d blocks |", uiBlocks + 1); // Read the card from end to begin for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { // Authenticate everytime we reach a trailer block if (is_trailer_block(iBlock)) { if (bFailure) { // When a failure occured we need to redo the anti-collision if (NFC.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 (0 == read_unlocked && !authenticate(iBlock)) { //printf("!\nError: authentication failed for block 0x%02x\n", iBlock); return(false); } // Try to read out the trailer if (Mifare.nfc_initiator_mifare_cmd(pnd, Mifare.mifare_cmd.MC_READ, (byte)iBlock, mp)) { if (0 != read_unlocked) { MiscTool.memcpy(mtDump.amb[iBlock].mbd.abtData, 0, mp.mpd.abtData, 0, 16); } else { // Copy the keys over from our key dump and store the retrieved access bits MiscTool.memcpy(mtDump.amb[iBlock].mbt.abtKeyA, 0, mtKeys.amb[iBlock].mbt.abtKeyA, 0, 6); MiscTool.memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, 0, mp.mpd.abtData, 6, 4); MiscTool.memcpy(mtDump.amb[iBlock].mbt.abtKeyB, 0, mtKeys.amb[iBlock].mbt.abtKeyB, 0, 6); } } else { //printf("!\nfailed to read trailer block 0x%02x\n", iBlock); bFailure = true; } } else { // Make sure a earlier readout did not fail if (!bFailure) { // Try to read out the data block if (Mifare.nfc_initiator_mifare_cmd(pnd, Mifare.mifare_cmd.MC_READ, (byte)iBlock, mp)) { MiscTool.memcpy(mtDump.amb[iBlock].mbd.abtData, 0, mp.mpd.abtData, 0, 16); } else { //printf("!\nError: unable to read block 0x%02x\n", iBlock); bFailure = true; } } } // Show if the readout went well for each block print_success_or_failure(bFailure, ref uiReadBlocks); if ((!bTolerateFailures) && bFailure) { return(false); } } //printf("|\n"); //printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1); //fflush(stdout); return(true); }
write_card(int write_block_zero) { uint uiBlock; bool bFailure = false; uint uiWriteBlocks = 0; if (write_block_zero != 0) { if (!unlock_card()) { return(false); } } //printf("Writing %d blocks |", uiBlocks + 1); // Write the card from begin to end; for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { // Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { if (bFailure) { // When a failure occured we need to redo the anti-collision if (NFC.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 (0 == write_block_zero && !authenticate(uiBlock)) { //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 MiscTool.memcpy(mp.mpd.abtData, 0, default_key, 0, 6); MiscTool.memcpy(mp.mpd.abtData, 6, default_acl, 0, 4); MiscTool.memcpy(mp.mpd.abtData, 10, default_key, 0, 6); } else { // Copy the keys over from our key dump and store the retrieved access bits MiscTool.memcpy(mp.mpd.abtData, 0, mtDump.amb[uiBlock].mbt.abtKeyA, 0, 6); MiscTool.memcpy(mp.mpd.abtData, 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 0, 4); MiscTool.memcpy(mp.mpd.abtData, 10, mtDump.amb[uiBlock].mbt.abtKeyB, 0, 6); } // Try to write the trailer if (Mifare.nfc_initiator_mifare_cmd(pnd, Mifare.mifare_cmd.MC_WRITE, (byte)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 && 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 != 0) { MiscTool.memset(mp.mpd.abtData, 0x00, 16); } else { MiscTool.memcpy(mp.mpd.abtData, 0, mtDump.amb[uiBlock].mbd.abtData, 0, 16); } // 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 (!Mifare.nfc_initiator_mifare_cmd(pnd, Mifare.mifare_cmd.MC_WRITE, (byte)uiBlock, mp)) { bFailure = true; } } } // Show if the write went well for each block print_success_or_failure(bFailure, ref uiWriteBlocks); if ((!bTolerateFailures) && bFailure) { return(false); } } //printf("|\n"); //printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); //fflush(stdout); return(true); }
authenticate(uint uiBlock) { Mifare.mifare_cmd mc; uint uiTrailerBlock; // Set the authentication information (uid) MiscTool.memcpy(mp.mpa.abtAuthUid, 0, nt.nti.nai.abtUid, nt.nti.nai.szUidLen - 4, 4); // Should we use key A or B? mc = (bUseKeyA) ? Mifare.mifare_cmd.MC_AUTH_A : Mifare.mifare_cmd.MC_AUTH_B; // Key file authentication. if (bUseKeyFile) { // Locate the trailer (with the keys) used for this sector uiTrailerBlock = get_trailer_block(uiBlock); // Extract the right key from dump file if (bUseKeyA) { MiscTool.memcpy(mp.mpa.abtKey, 0, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 0, 6); } else { MiscTool.memcpy(mp.mpa.abtKey, 0, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 0, 6); } // Try to authenticate for the current sector if (Mifare.nfc_initiator_mifare_cmd(pnd, mc, (byte)uiBlock, mp)) { return(true); } } // If formatting or not using key file, try to guess the right key if (bFormatCard || !bUseKeyFile) { for (int key_index = 0; key_index < num_keys; key_index++) { MiscTool.memcpy(mp.mpa.abtKey, 0, keys, (key_index * 6), 6); if (Mifare.nfc_initiator_mifare_cmd(pnd, mc, (byte)uiBlock, mp)) { if (bUseKeyA) { MiscTool.memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, 0, mp.mpa.abtKey, 0, 6); } else { MiscTool.memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, 0, mp.mpa.abtKey, 0, 6); } return(true); } if (NFC.nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, null) <= 0) { //ERR("tag was removed"); return(false); } } } return(false); }