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

博主分享了一次因操作失误导致饭卡部分区域被锁定的经历,为避免类似问题,他们为nfc-mfclassic工具添加了新的功能,即指定读写块和防止控制位误写的功能。通过这个补丁,可以更好地保护卡片数据的安全,确保关键区域不受影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   昨天悲剧了,把一个不完整的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);
     else
       memcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);
-
     // Try to authenticate for the current sector
     if (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 key
     for (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 well
       if (bFailure) {
         // When a failure occured we need to redo the anti-collision
@@ -291,9 +310,14 @@
 
       // Try to authenticate for the current sector
       if (!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 trailer
       if (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 fail
       if (!bFailure) {
         // Try to read out the data block
         if (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 well
       if (bFailure) {
         // When a failure occured we need to redo the anti-collision
@@ -364,28 +403,69 @@
 
       // Try to authenticate for the current sector
       if (!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 bits
       memcpy (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 trailer
       if (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 this
       if (uiBlock == 0 && ! write_block_zero)
         continue;
 
-
       // Make sure a earlier write did not fail
       if (!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]);


 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值