mfclassic 防止控制位误写 指定读写的块 补丁

昨天悲剧了,把一个不完整的dump写到了饭卡里,控制位全是0,直接导致饭卡的大部分区锁死,万幸的是,关键数据区没损坏,消费,门禁还都好用……

为了防止悲剧的再次发生,给 nfc-mfclassic 添加了 防止控制位误写 功能,以下是 指定读写的块+防止控制位误写 补丁:

Index: nfc-mfclassic.c===================================================================— nfc-mfclassic.c(版本 1416)+++ nfc-mfclassic.c(工作副本)@@ -38,6 +38,13 @@ # include "config.h" #endif // HAVE_CONFIG_H +#define BYTE_HIGH(X) ( 0XF & (X>>4) )+#define BYTE_LOW(X) ( 0XF & X)+#define BYTE_HIGH_NOT(X) ( 0XF & ~BYTE_HIGH(X) )+#define BYTE_LOW_NOT(X) ( 0XF & ~BYTE_LOW(X) )++#define GET_CX_BIT(half_byte,block) ( 0x1 & (half_byte >> block))+ #include <stdio.h> #include <stdlib.h> #include <stdint.h>@@ -71,6 +78,9 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56 };+//Operate block+static bool blocks[0xFF];+static bool bSkip = false; static const nfc_modulation nmMifare = { .nmt = NMT_ISO14443A,@@ -127,11 +137,11 @@ } static void-print_success_or_failure (bool bFailure, uint32_t *uiBlockCounter)+print_success_or_failure (char bFailure) {- printf ("%c", (bFailure) ? ‘x’ : ‘.’);- if (uiBlockCounter && !bFailure)- *uiBlockCounter += (*uiBlockCounter < 128) ? 4 : 16;+ printf ("%c", (bFailure) ? (bFailure==true?’x’:’-‘): ‘.’);+// if (uiBlockCounter && !bFailure)+// *uiBlockCounter += (*uiBlockCounter < 128) ? 4 : 16; } static bool@@ -191,10 +201,10 @@memcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6);elsememcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);-// Try to authenticate for the current sectorif (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp))return true;+ nfc_initiator_select_passive_target (pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL); } else {// Try to guess the right keyfor (key_index = 0; key_index < num_keys; key_index++) {@@ -259,7 +269,7 @@ read_card (int read_unlocked) { int32_t iBlock;- bool bFailure = false;+ char bFailure = false; uint32_t uiReadBlocks = 0;if(read_unlocked)@@ -275,8 +285,17 @@if (is_trailer_block (iBlock)) {// Skip this the first time, bFailure it means nothing (yet)if (iBlock != uiBlocks)-print_success_or_failure (bFailure, &uiReadBlocks);+print_success_or_failure (bFailure); +if (bSkip)+{+for (int i=iBlock;get_trailer_block(i)==iBlock;–i)+if (blocks[i])+goto next;+bFailure = -1;+continue ;+}+next:// Show if the readout went wellif (bFailure) {// When a failure occured we need to redo the anti-collision@@ -291,9 +310,14 @@// Try to authenticate for the current sectorif (!read_unlocked && !authenticate (iBlock)) {-printf ("!\nError: authentication failed for block 0x%02x\n", iBlock);-return false;+//printf ("!\nError: authentication failed for block 0x%02x\n", iBlock);+bFailure = true;+continue ;+//return false;}++if (bSkip && !blocks[iBlock])+continue ;// Try to read out the trailerif (nfc_initiator_mifare_cmd (pnd, MC_READ, iBlock, &mp)) {if(read_unlocked) {@@ -304,15 +328,20 @@memcpy (mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);memcpy (mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);}+uiReadBlocks++;} else {printf ("!\nError: unable to read trailer block 0x%02x\n", iBlock);}} else {++if (bSkip && !blocks[iBlock])+continue ;// Make sure a earlier readout did not failif (!bFailure) {// Try to read out the data blockif (nfc_initiator_mifare_cmd (pnd, MC_READ, iBlock, &mp)) {memcpy (mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);+uiReadBlocks++;} else {bFailure = true;printf ("!\nError: unable to read block 0x%02x\n", iBlock);@@ -321,7 +350,7 @@}} }- print_success_or_failure (bFailure, &uiReadBlocks);+ print_success_or_failure (bFailure); printf ("|\n"); printf ("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1); fflush (stdout);@@ -333,7 +362,7 @@ write_card (int write_block_zero) { uint32_t uiBlock;- bool bFailure = false;+ char bFailure = false; uint32_t uiWriteBlocks = 0;@@ -348,8 +377,18 @@if (is_first_block (uiBlock)) {// Skip this the first time, bFailure it means nothing (yet)if (uiBlock != 0)-print_success_or_failure (bFailure, &uiWriteBlocks);+print_success_or_failure (bFailure); +if (bSkip)+{+for (int i=get_trailer_block(uiBlock);i>uiBlock;–i)+if (blocks[i])+goto next;+bFailure = -1;+continue ;+}+next:+// Show if the readout went wellif (bFailure) {// When a failure occured we need to redo the anti-collision@@ -364,28 +403,69 @@// Try to authenticate for the current sectorif (!write_block_zero && !authenticate (uiBlock)) {-printf ("!\nError: authentication failed for block %02x\n", uiBlock);-return false;+//printf ("!\nError: authentication failed for block %02x\n", uiBlock);+bFailure = true;+continue ;+//return false;}} + if (bSkip && !blocks[uiBlock])+continue ;if (is_trailer_block (uiBlock)) {// Copy the keys over from our key dump and store the retrieved access bitsmemcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6);+// VERY INPORTENT! Verify the AccessBits+if ( BYTE_HIGH_NOT(mtDump.amb[uiBlock].mbt.abtAccessBits[0]) != BYTE_LOW(mtDump.amb[uiBlock].mbt.abtAccessBits[2])+|| BYTE_LOW_NOT(mtDump.amb[uiBlock].mbt.abtAccessBits[0]) != BYTE_HIGH(mtDump.amb[uiBlock].mbt.abtAccessBits[1])+|| BYTE_LOW_NOT(mtDump.amb[uiBlock].mbt.abtAccessBits[1]) != BYTE_HIGH(mtDump.amb[uiBlock].mbt.abtAccessBits[2])++)+{+printf ("\nNOT valid AccessBits! block:%d AccessBits:%02X %02X %02X %02X\n",uiBlock,mtDump.amb[uiBlock].mbt.abtAccessBits[0],+mtDump.amb[uiBlock].mbt.abtAccessBits[1],+mtDump.amb[uiBlock].mbt.abtAccessBits[2],+mtDump.amb[uiBlock].mbt.abtAccessBits[3]);+return false;+}++if ( +GET_CX_BIT/*C3*/(BYTE_HIGH(mtDump.amb[uiBlock].mbt.abtAccessBits[2]),3)==0 ||++GET_CX_BIT(/*C1*/BYTE_HIGH(mtDump.amb[uiBlock].mbt.abtAccessBits[1]),3)==1 &&+GET_CX_BIT(/*C2*/BYTE_LOW(mtDump.amb[uiBlock].mbt.abtAccessBits[2]),3)==1+)+{+printf ("\nThe AccessBits for ‘access bits writable’ didn’t set,This means that you will never be able to change AccessBits again\+,if you really want to do this,use f option(haven’t implement now) AccessBits:%02X %02X %02X %02X C1C2C3:%1X %1X %1X\n",mtDump.amb[uiBlock].mbt.abtAccessBits[0],+mtDump.amb[uiBlock].mbt.abtAccessBits[1],+mtDump.amb[uiBlock].mbt.abtAccessBits[2],+mtDump.amb[uiBlock].mbt.abtAccessBits[3],+BYTE_HIGH(mtDump.amb[uiBlock].mbt.abtAccessBits[1]),+BYTE_LOW(mtDump.amb[uiBlock].mbt.abtAccessBits[2]),+BYTE_HIGH(mtDump.amb[uiBlock].mbt.abtAccessBits[2])+);+return false;+}+memcpy (mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4);memcpy (mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6);// Try to write the trailerif (nfc_initiator_mifare_cmd (pnd, MC_WRITE, uiBlock, &mp) == false) {-printf ("failed to write trailer block %d \n", uiBlock);+//printf ("failed to write trailer block %d \n", uiBlock);bFailure = true;}+else+uiWriteBlocks++;} else {++if (bSkip && !blocks[uiBlock])+continue ;// The first block 0x00 is read only, skip thisif (uiBlock == 0 && ! write_block_zero)continue; -// Make sure a earlier write did not failif (!bFailure) {// Try to write the data block@@ -399,10 +479,12 @@}if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, uiBlock, &mp))bFailure = true;+else+uiWriteBlocks++;}} }- print_success_or_failure (bFailure, &uiWriteBlocks);+ print_success_or_failure (bFailure); printf ("|\n"); printf ("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); fflush (stdout);@@ -420,14 +502,16 @@ print_usage (const char *pcProgramName) { printf ("Usage: ");- printf ("%s r|R|w|W a|b <dump.mfd> [<keys.mfd>]\n", pcProgramName);- printf (" r|R|w|W- Perform read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");- printf ("*** note that unlocked write will attempt to overwrite block 0 including UID\n");- printf ("*** unlocked read does not require authentication and will reveal A and B keys\n");- printf ("*** unlocking only works with special Mifare 1K cards (Chinese clones)\n");- printf (" a|b- Use A or B keys for action\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 ("%s r|R|w|W[<,sector[t]>[…]] a|b <dump.mfd> [<keys.mfd>]\n", pcProgramName);+ printf (" <r|R|w|W>[<,sector[t|f]]>[…]] – Perform read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");+ printf ("the sector to be read or write ,include or exclude trailer block ,can be specified,omit means all sectors include trailer block\n");+ printf ("example: r,0,15t means only read sector 0 and sector 15 include trailer block\n");+ printf ("*** note that unlocked write will attempt to overwrite block 0 including UID\n");+ printf ("*** unlocked read does not require authentication and will reveal A and B keys\n");+ printf ("*** unlocking only works with special Mifare 1K cards (Chinese clones)\n");+ printf (" a|b- Use A or B keys for action\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"); } int@@ -443,10 +527,10 @@print_usage (argv[0]);exit (EXIT_FAILURE); }- const char *command = argv[1];+ const char *command = strtok(argv[1], ",");if (strcmp (command, "r") == 0 || strcmp (command, "R") == 0) {- if (argc < 4) {+ if (argc < 4) {print_usage (argv[0]);exit (EXIT_FAILURE);}@@ -467,6 +551,23 @@bUseKeyFile = (argc > 4); } + char *sector = NULL;+ int isector;+ while ( (sector=strtok(NULL, ",")) != NULL )+ {+ if ( (isector=atoi(sector))==0 && sector[0]!=’0′ || isector<0 || isector>39)+ {+printf("invalid sector argument: %s\n",sector);+exit (EXIT_FAILURE);+ }+ bSkip=true;++ for(int i=get_trailer_block(isector<32?isector*4:256-(40-isector)*16) – !(sector[strlen(sector)-1]==’t’) ;+ i>=(isector<32?isector*4:256-(40-isector)*16) ;+ –i)+blocks[i] = true;+ }+ switch (atAction) { case ACTION_USAGE:print_usage (argv[0]);

,一遍一遍的……你突然明白自己还活着,

mfclassic 防止控制位误写 指定读写的块 补丁

相关文章:

你感兴趣的文章:

标签云: