]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhfmf.c 
   1  //-----------------------------------------------------------------------------    2  // Copyright (C) 2011,2012 Merlok    4  // This code is licensed to you under the terms of the GNU GPL, version 2 or,    5  // at your option, any later version. See the LICENSE.txt file for the text of    7  //-----------------------------------------------------------------------------    8  // High frequency MIFARE commands    9  //-----------------------------------------------------------------------------   12  #include  "./nonce2key/nonce2key.h"   14  static int  CmdHelp ( const char  * Cmd
);   16  int  CmdHF14AMifare ( const char  * Cmd
)   19          uint32_t  nt 
=  0 ,  nr 
=  0 ;   20          uint64_t  par_list 
=  0 ,  ks_list 
=  0 ,  r_key 
=  0 ;   23          UsbCommand c 
= { CMD_READER_MIFARE
, { true ,  0 ,  0 }};   26          printf ( "------------------------------------------------------------------------- \n " );   27          printf ( "Executing command. Expected execution time: 25sec on average  :-) \n " );   28          printf ( "Press button on the proxmark3 device to abort both proxmark3 and client. \n " );   29          printf ( "------------------------------------------------------------------------- \n " );   37          while  ( ukbhit ())         getchar ();   45                          printf ( " \n aborted via keyboard! \n " );   50                  if  ( WaitForResponseTimeout ( CMD_ACK
, & resp
,  1000 )) {   52                          uid 
= ( uint32_t ) bytes_to_num ( resp
. d
. asBytes 
+   0 ,  4 );   53                          nt 
=  ( uint32_t ) bytes_to_num ( resp
. d
. asBytes 
+   4 ,  4 );   54                          par_list 
=  bytes_to_num ( resp
. d
. asBytes 
+   8 ,  8 );   55                          ks_list 
=  bytes_to_num ( resp
. d
. asBytes 
+   16 ,  8 );   56                          nr 
=  bytes_to_num ( resp
. d
. asBytes 
+  24 ,  4 );   59                                  case  - 1  :  PrintAndLog ( "Button pressed. Aborted. \n " );  break ;   60                                  case  - 2  :  PrintAndLog ( "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). \n " );  break ;   61                                  case  - 3  :  PrintAndLog ( "Card is not vulnerable to Darkside attack (its random number generator is not predictable). \n " );  break ;   62                                  case  - 4  :  PrintAndLog ( "Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown" );   63                                                          PrintAndLog ( "generating polynomial with 16 effective bits only, but shows unexpected behaviour. \n " );  break ;   73          if  ( isOK 
!=  1 )  return  1 ;   75          // execute original function from util nonce2key   76          if  ( nonce2key ( uid
,  nt
,  nr
,  par_list
,  ks_list
, & r_key
)) {   78                  PrintAndLog ( "Key not found (lfsr_common_prefix list is null). Nt= %0 8x" ,  nt
);       79                  PrintAndLog ( "Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce..." );   84                  printf ( "------------------------------------------------------------------ \n " );   85                  PrintAndLog ( "Found valid key: %0 12" llx
"  \n " ,  r_key
);   92  int  CmdHF14AMfWrBl ( const char  * Cmd
)   96          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };   97          uint8_t  bldata
[ 16 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 };  102                  PrintAndLog ( "Usage:  hf mf wrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>" );  103                  PrintAndLog ( "        sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F" );  107          blockNo 
=  param_get8 ( Cmd
,  0 );  108          cmdp 
=  param_getchar ( Cmd
,  1 );  110                  PrintAndLog ( "Key type must be A or B" );  113          if  ( cmdp 
!=  'A'  &&  cmdp 
!=  'a' )  keyType 
=  1 ;  114          if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  115                  PrintAndLog ( "Key must include 12 HEX symbols" );  118          if  ( param_gethex ( Cmd
,  3 ,  bldata
,  32 )) {  119                  PrintAndLog ( "Block data must include 32 HEX symbols" );  122          PrintAndLog ( "--block no: %d , key type: %c , key: %s " ,  blockNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  123          PrintAndLog ( "--data:  %s " ,  sprint_hex ( bldata
,  16 ));  125    UsbCommand c 
= { CMD_MIFARE_WRITEBL
, { blockNo
,  keyType
,  0 }};  126          memcpy ( c
. d
. asBytes
,  key
,  6 );  127          memcpy ( c
. d
. asBytes 
+  10 ,  bldata
,  16 );  131          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  132                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  133                  PrintAndLog ( "isOk: %0 2x" ,  isOK
);  135                  PrintAndLog ( "Command execute timeout" );  141  int  CmdHF14AMfRdBl ( const char  * Cmd
)  145          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  151                  PrintAndLog ( "Usage:  hf mf rdbl    <block number> <key A/B> <key (12 hex symbols)>" );  152                  PrintAndLog ( "        sample: hf mf rdbl 0 A FFFFFFFFFFFF " );  156          blockNo 
=  param_get8 ( Cmd
,  0 );  157          cmdp 
=  param_getchar ( Cmd
,  1 );  159                  PrintAndLog ( "Key type must be A or B" );  162          if  ( cmdp 
!=  'A'  &&  cmdp 
!=  'a' )  keyType 
=  1 ;  163          if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  164                  PrintAndLog ( "Key must include 12 HEX symbols" );  167          PrintAndLog ( "--block no: %d , key type: %c , key: %s  " ,  blockNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  169    UsbCommand c 
= { CMD_MIFARE_READBL
, { blockNo
,  keyType
,  0 }};  170          memcpy ( c
. d
. asBytes
,  key
,  6 );  174          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  175                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  176                  uint8_t  * data 
=  resp
. d
. asBytes
;  179                          PrintAndLog ( "isOk: %0 2x data: %s " ,  isOK
,  sprint_hex ( data
,  16 ));  181                          PrintAndLog ( "isOk: %0 2x" ,  isOK
);  183                  PrintAndLog ( "Command execute timeout" );  189  int  CmdHF14AMfRdSc ( const char  * Cmd
)  192          uint8_t  sectorNo 
=  0 ;  194          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  196          uint8_t  * data  
=  NULL
;  200                  PrintAndLog ( "Usage:  hf mf rdsc    <sector number> <key A/B> <key (12 hex symbols)>" );  201                  PrintAndLog ( "        sample: hf mf rdsc 0 A FFFFFFFFFFFF " );  205          sectorNo 
=  param_get8 ( Cmd
,  0 );  207                  PrintAndLog ( "Sector number must be less than 40" );  210          cmdp 
=  param_getchar ( Cmd
,  1 );  211          if  ( cmdp 
!=  'a'  &&  cmdp 
!=  'A'  &&  cmdp 
!=  'b'  &&  cmdp 
!=  'B' ) {  212                  PrintAndLog ( "Key type must be A or B" );  215          if  ( cmdp 
!=  'A'  &&  cmdp 
!=  'a' )  keyType 
=  1 ;  216          if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  217                  PrintAndLog ( "Key must include 12 HEX symbols" );  220          PrintAndLog ( "--sector no: %d  key type: %c  key: %s  " ,  sectorNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  222          UsbCommand c 
= { CMD_MIFARE_READSC
, { sectorNo
,  keyType
,  0 }};  223          memcpy ( c
. d
. asBytes
,  key
,  6 );  228          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  229                  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  230                  data  
=  resp
. d
. asBytes
;  232                  PrintAndLog ( "isOk: %0 2x" ,  isOK
);  234                          for  ( i 
=  0 ;  i 
< ( sectorNo
< 32 ? 3 : 15 );  i
++) {  235                                  PrintAndLog ( "data   :  %s " ,  sprint_hex ( data 
+  i 
*  16 ,  16 ));  237                          PrintAndLog ( "trailer:  %s " ,  sprint_hex ( data 
+ ( sectorNo
< 32 ? 3 : 15 ) *  16 ,  16 ));  240                  PrintAndLog ( "Command execute timeout" );  246  uint8_t  FirstBlockOfSector ( uint8_t  sectorNo
)  251                  return  32  *  4  + ( sectorNo 
-  32 ) *  16 ;  255  uint8_t  NumBlocksPerSector ( uint8_t  sectorNo
)  264  int  CmdHF14AMfDump ( const char  * Cmd
)  266          uint8_t  sectorNo
,  blockNo
;  270          uint8_t  rights
[ 40 ][ 4 ];  271          uint8_t  carddata
[ 256 ][ 16 ];  272          uint8_t  numSectors 
=  16 ;  279          char  cmdp 
=  param_getchar ( Cmd
,  0 );  281                  case  '0'  :  numSectors 
=  5 ;  break ;  283                  case  '\0' :  numSectors 
=  16 ;  break ;  284                  case  '2'  :  numSectors 
=  32 ;  break ;  285                  case  '4'  :  numSectors 
=  40 ;  break ;  286                  default :    numSectors 
=  16 ;  289          if  ( strlen ( Cmd
) >  1  ||  cmdp 
==  'h'  ||  cmdp 
==  'H' ) {  290                  PrintAndLog ( "Usage:   hf mf dump [card memory]" );  291                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  293                  PrintAndLog ( "Samples: hf mf dump" );  294                  PrintAndLog ( "         hf mf dump 4" );  298          if  (( fin 
=  fopen ( "dumpkeys.bin" , "rb" )) ==  NULL
) {  299                  PrintAndLog ( "Could not find file dumpkeys.bin" );  303          // Read keys A from file  304          for  ( sectorNo
= 0 ;  sectorNo
< numSectors
;  sectorNo
++) {  305                  if  ( fread (  keyA
[ sectorNo
],  1 ,  6 ,  fin 
) ==  0 ) {  306                          PrintAndLog ( "File reading error." );  312          // Read keys B from file  313          for  ( sectorNo
= 0 ;  sectorNo
< numSectors
;  sectorNo
++) {  314                  if  ( fread (  keyB
[ sectorNo
],  1 ,  6 ,  fin 
) ==  0 ) {  315                          PrintAndLog ( "File reading error." );  323          PrintAndLog ( "|-----------------------------------------|" );  324          PrintAndLog ( "|------ Reading sector access bits...-----|" );  325          PrintAndLog ( "|-----------------------------------------|" );  327          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  328                  UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  NumBlocksPerSector ( sectorNo
) -  1 ,  0 ,  0 }};  329                  memcpy ( c
. d
. asBytes
,  keyA
[ sectorNo
],  6 );  332                  if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  333                          uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  334                          uint8_t  * data  
=  resp
. d
. asBytes
;  336                                  rights
[ sectorNo
][ 0 ] = (( data
[ 7 ] &  0x10 )>> 2 ) | (( data
[ 8 ] &  0x1 )<< 1 ) | (( data
[ 8 ] &  0x10 )>> 4 );  // C1C2C3 for data area 0  337                                  rights
[ sectorNo
][ 1 ] = (( data
[ 7 ] &  0x20 )>> 3 ) | (( data
[ 8 ] &  0x2 )<< 0 ) | (( data
[ 8 ] &  0x20 )>> 5 );  // C1C2C3 for data area 1  338                                  rights
[ sectorNo
][ 2 ] = (( data
[ 7 ] &  0x40 )>> 4 ) | (( data
[ 8 ] &  0x4 )>> 1 ) | (( data
[ 8 ] &  0x40 )>> 6 );  // C1C2C3 for data area 2  339                                  rights
[ sectorNo
][ 3 ] = (( data
[ 7 ] &  0x80 )>> 5 ) | (( data
[ 8 ] &  0x8 )>> 2 ) | (( data
[ 8 ] &  0x80 )>> 7 );  // C1C2C3 for sector trailer  341                                  PrintAndLog ( "Could not get access rights for sector  %2 d. Trying with defaults..." ,  sectorNo
);  342                                  rights
[ sectorNo
][ 0 ] =  rights
[ sectorNo
][ 1 ] =  rights
[ sectorNo
][ 2 ] =  0x00 ;  343                                  rights
[ sectorNo
][ 3 ] =  0x01 ;  346                          PrintAndLog ( "Command execute timeout when trying to read access rights for sector  %2 d. Trying with defaults..." ,  sectorNo
);  347                          rights
[ sectorNo
][ 0 ] =  rights
[ sectorNo
][ 1 ] =  rights
[ sectorNo
][ 2 ] =  0x00 ;  348                          rights
[ sectorNo
][ 3 ] =  0x01 ;  352          PrintAndLog ( "|-----------------------------------------|" );  353          PrintAndLog ( "|----- Dumping all blocks to file... -----|" );  354          PrintAndLog ( "|-----------------------------------------|" );  357          for  ( sectorNo 
=  0 ;  isOK 
&&  sectorNo 
<  numSectors
;  sectorNo
++) {  358                  for  ( blockNo 
=  0 ;  isOK 
&&  blockNo 
<  NumBlocksPerSector ( sectorNo
);  blockNo
++) {  359                          bool  received 
=  false ;  361                          if  ( blockNo 
==  NumBlocksPerSector ( sectorNo
) -  1 ) {               // sector trailer. At least the Access Conditions can always be read with key A.   362                                  UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  0 ,  0 }};  363                                  memcpy ( c
. d
. asBytes
,  keyA
[ sectorNo
],  6 );  365                                  received 
=  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 );  366                          }  else  {                                                                                                 // data block. Check if it can be read with key A or key B  367                                  uint8_t  data_area 
=  sectorNo
< 32 ? blockNo
: blockNo
/ 5 ;  368                                  if  (( rights
[ sectorNo
][ data_area
] ==  0x03 ) || ( rights
[ sectorNo
][ data_area
] ==  0x05 )) {    // only key B would work  369                                          UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  1 ,  0 }};  370                                          memcpy ( c
. d
. asBytes
,  keyB
[ sectorNo
],  6 );  372                                          received 
=  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 );  373                                  }  else if  ( rights
[ sectorNo
][ data_area
] ==  0x07 ) {                                                                                // no key would work  375                                          PrintAndLog ( "Access rights do not allow reading of sector  %2 d block  %3 d" ,  sectorNo
,  blockNo
);  376                                  }  else  {                                                                                                                                                                 // key A would work  377                                          UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  0 ,  0 }};  378                                          memcpy ( c
. d
. asBytes
,  keyA
[ sectorNo
],  6 );  380                                          received 
=  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 );  385                                  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  386                                  uint8_t  * data  
=  resp
. d
. asBytes
;  387                                  if  ( blockNo 
==  NumBlocksPerSector ( sectorNo
) -  1 ) {               // sector trailer. Fill in the keys.  388                                          data
[ 0 ]  = ( keyA
[ sectorNo
][ 0 ]);  389                                          data
[ 1 ]  = ( keyA
[ sectorNo
][ 1 ]);  390                                          data
[ 2 ]  = ( keyA
[ sectorNo
][ 2 ]);  391                                          data
[ 3 ]  = ( keyA
[ sectorNo
][ 3 ]);  392                                          data
[ 4 ]  = ( keyA
[ sectorNo
][ 4 ]);  393                                          data
[ 5 ]  = ( keyA
[ sectorNo
][ 5 ]);  394                                          data
[ 10 ] = ( keyB
[ sectorNo
][ 0 ]);  395                                          data
[ 11 ] = ( keyB
[ sectorNo
][ 1 ]);  396                                          data
[ 12 ] = ( keyB
[ sectorNo
][ 2 ]);  397                                          data
[ 13 ] = ( keyB
[ sectorNo
][ 3 ]);  398                                          data
[ 14 ] = ( keyB
[ sectorNo
][ 4 ]);  399                                          data
[ 15 ] = ( keyB
[ sectorNo
][ 5 ]);  402                                          memcpy ( carddata
[ FirstBlockOfSector ( sectorNo
) +  blockNo
],  data
,  16 );  403                      PrintAndLog ( "Successfully read block  %2 d of sector  %2 d." ,  blockNo
,  sectorNo
);  405                                          PrintAndLog ( "Could not read block  %2 d of sector  %2 d" ,  blockNo
,  sectorNo
);  411                                  PrintAndLog ( "Command execute timeout when trying to read block  %2 d of sector  %2 d." ,  blockNo
,  sectorNo
);  418                  if  (( fout 
=  fopen ( "dumpdata.bin" , "wb" )) ==  NULL
) {   419                          PrintAndLog ( "Could not create file name dumpdata.bin" );  422                  uint16_t  numblocks 
=  FirstBlockOfSector ( numSectors 
-  1 ) +  NumBlocksPerSector ( numSectors 
-  1 );  423                  fwrite ( carddata
,  1 ,  16 * numblocks
,  fout
);  425                  PrintAndLog ( "Dumped  %d  blocks ( %d  bytes) to file dumpdata.bin" ,  numblocks
,  16 * numblocks
);  431  int  CmdHF14AMfRestore ( const char  * Cmd
)  433          uint8_t  sectorNo
, blockNo
;  435          uint8_t  key
[ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF };  436          uint8_t  bldata
[ 16 ] = { 0x00 };  444          char  cmdp 
=  param_getchar ( Cmd
,  0 );  446                  case  '0'  :  numSectors 
=  5 ;  break ;  448                  case  '\0' :  numSectors 
=  16 ;  break ;  449                  case  '2'  :  numSectors 
=  32 ;  break ;  450                  case  '4'  :  numSectors 
=  40 ;  break ;  451                  default :    numSectors 
=  16 ;  454          if  ( strlen ( Cmd
) >  1  ||  cmdp 
==  'h'  ||  cmdp 
==  'H' ) {  455                  PrintAndLog ( "Usage:   hf mf restore [card memory]" );  456                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  458                  PrintAndLog ( "Samples: hf mf restore" );  459                  PrintAndLog ( "         hf mf restore 4" );  463          if  (( fkeys 
=  fopen ( "dumpkeys.bin" , "rb" )) ==  NULL
) {  464                  PrintAndLog ( "Could not find file dumpkeys.bin" );  468          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  469                  if  ( fread ( keyA
[ sectorNo
],  1 ,  6 ,  fkeys
) ==  0 ) {  470                          PrintAndLog ( "File reading error (dumpkeys.bin)." );  477          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  478                  if  ( fread ( keyB
[ sectorNo
],  1 ,  6 ,  fkeys
) ==  0 ) {  479                          PrintAndLog ( "File reading error (dumpkeys.bin)." );  487          if  (( fdump 
=  fopen ( "dumpdata.bin" , "rb" )) ==  NULL
) {  488                  PrintAndLog ( "Could not find file dumpdata.bin" );  491          PrintAndLog ( "Restoring dumpdata.bin to card" );  493          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  494                  for ( blockNo 
=  0 ;  blockNo 
<  NumBlocksPerSector ( sectorNo
);  blockNo
++) {  495                          UsbCommand c 
= { CMD_MIFARE_WRITEBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  keyType
,  0 }};  496                          memcpy ( c
. d
. asBytes
,  key
,  6 );  498                          if  ( fread ( bldata
,  1 ,  16 ,  fdump
) ==  0 ) {  499                                  PrintAndLog ( "File reading error (dumpdata.bin)." );  504                          if  ( blockNo 
==  NumBlocksPerSector ( sectorNo
) -  1 ) {       // sector trailer  505                                  bldata
[ 0 ]  = ( keyA
[ sectorNo
][ 0 ]);  506                                  bldata
[ 1 ]  = ( keyA
[ sectorNo
][ 1 ]);  507                                  bldata
[ 2 ]  = ( keyA
[ sectorNo
][ 2 ]);  508                                  bldata
[ 3 ]  = ( keyA
[ sectorNo
][ 3 ]);  509                                  bldata
[ 4 ]  = ( keyA
[ sectorNo
][ 4 ]);  510                                  bldata
[ 5 ]  = ( keyA
[ sectorNo
][ 5 ]);  511                                  bldata
[ 10 ] = ( keyB
[ sectorNo
][ 0 ]);  512                                  bldata
[ 11 ] = ( keyB
[ sectorNo
][ 1 ]);  513                                  bldata
[ 12 ] = ( keyB
[ sectorNo
][ 2 ]);  514                                  bldata
[ 13 ] = ( keyB
[ sectorNo
][ 3 ]);  515                                  bldata
[ 14 ] = ( keyB
[ sectorNo
][ 4 ]);  516                                  bldata
[ 15 ] = ( keyB
[ sectorNo
][ 5 ]);  519                          PrintAndLog ( "Writing to block  %3 d:  %s " ,  FirstBlockOfSector ( sectorNo
) +  blockNo
,  sprint_hex ( bldata
,  16 ));  521                          memcpy ( c
. d
. asBytes 
+  10 ,  bldata
,  16 );  525                          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  526                                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  527                                  PrintAndLog ( "isOk: %0 2x" ,  isOK
);  529                                  PrintAndLog ( "Command execute timeout" );  538  int  CmdHF14AMfNested ( const char  * Cmd
)  540          int  i
,  j
,  res
,  iterations
;  541          sector 
* e_sector 
=  NULL
;  544          uint8_t  trgBlockNo 
=  0 ;  545          uint8_t  trgKeyType 
=  0 ;  546          uint8_t  SectorsCnt 
=  0 ;  547          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  548          uint8_t  keyBlock
[ 14 * 6 ];  550          bool  transferToEml 
=  false ;  552          bool  createDumpFile 
=  false ;  554          uint8_t  standart
[ 6 ] = { 0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF };  555          uint8_t  tempkey
[ 6 ] = { 0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF };  560                  PrintAndLog ( "Usage:" );  561                  PrintAndLog ( " all sectors:  hf mf nested  <card memory> <block number> <key A/B> <key (12 hex symbols)> [t,d]" );  562                  PrintAndLog ( " one sector:   hf mf nested  o <block number> <key A/B> <key (12 hex symbols)>" );  563                  PrintAndLog ( "               <target block number> <target key A/B> [t]" );  564                  PrintAndLog ( "card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K" );  565                  PrintAndLog ( "t - transfer keys into emulator memory" );  566                  PrintAndLog ( "d - write keys to binary file" );  568                  PrintAndLog ( "      sample1: hf mf nested 1 0 A FFFFFFFFFFFF " );  569                  PrintAndLog ( "      sample2: hf mf nested 1 0 A FFFFFFFFFFFF t " );  570                  PrintAndLog ( "      sample3: hf mf nested 1 0 A FFFFFFFFFFFF d " );  571                  PrintAndLog ( "      sample4: hf mf nested o 0 A FFFFFFFFFFFF 4 A" );  575          cmdp 
=  param_getchar ( Cmd
,  0 );  576          blockNo 
=  param_get8 ( Cmd
,  1 );  577          ctmp 
=  param_getchar ( Cmd
,  2 );  579          if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  580                  PrintAndLog ( "Key type must be A or B" );  584          if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' )   587          if  ( param_gethex ( Cmd
,  3 ,  key
,  12 )) {  588                  PrintAndLog ( "Key must include 12 HEX symbols" );  592          if  ( cmdp 
==  'o'  ||  cmdp 
==  'O' ) {  594                  trgBlockNo 
=  param_get8 ( Cmd
,  4 );  595                  ctmp 
=  param_getchar ( Cmd
,  5 );  596                  if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  597                          PrintAndLog ( "Target key type must be A or B" );  600                  if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' )   605                          case  '0' :  SectorsCnt 
=  05 ;  break ;  606                          case  '1' :  SectorsCnt 
=  16 ;  break ;  607                          case  '2' :  SectorsCnt 
=  32 ;  break ;  608                          case  '4' :  SectorsCnt 
=  40 ;  break ;  609                          default :   SectorsCnt 
=  16 ;  613          ctmp 
=  param_getchar ( Cmd
,  4 );  614          if               ( ctmp 
==  't'  ||  ctmp 
==  'T' )  transferToEml 
=  true ;  615          else if  ( ctmp 
==  'd'  ||  ctmp 
==  'D' )  createDumpFile 
=  true ;  617          ctmp 
=  param_getchar ( Cmd
,  6 );  618          transferToEml 
|= ( ctmp 
==  't'  ||  ctmp 
==  'T' );  619          transferToEml 
|= ( ctmp 
==  'd'  ||  ctmp 
==  'D' );  622                  PrintAndLog ( "--target block no: %3 d, target key type: %c  " ,  trgBlockNo
,  trgKeyType
? 'B' : 'A' );  623                  int16_t  isOK 
=  mfnested ( blockNo
,  keyType
,  key
,  trgBlockNo
,  trgKeyType
,  keyBlock
,  true );  626                                  case  - 1  :  PrintAndLog ( "Error: No response from Proxmark. \n " );  break ;  627                                  case  - 2  :  PrintAndLog ( "Button pressed. Aborted. \n " );  break ;  628                                  case  - 3  :  PrintAndLog ( "Tag isn't vulnerable to Nested Attack (random numbers are not predictable). \n " );  break ;  629                                  default  :  PrintAndLog ( "Unknown Error. \n " );  633                  key64 
=  bytes_to_num ( keyBlock
,  6 );  635                          PrintAndLog ( "Found valid key: %0 12" llx
,  key64
);  637                          // transfer key to the emulator  639                                  uint8_t  sectortrailer
;  640                                  if  ( trgBlockNo 
<  32 * 4 ) {         // 4 block sector  641                                          sectortrailer 
= ( trgBlockNo 
&  0x03 ) +  3 ;  642                                  }  else  {                                         // 16 block sector  643                                          sectortrailer 
= ( trgBlockNo 
&  0x0f ) +  15 ;  645                                  mfEmlGetMem ( keyBlock
,  sectortrailer
,  1 );  648                                          num_to_bytes ( key64
,  6 ,  keyBlock
);  650                                          num_to_bytes ( key64
,  6 , & keyBlock
[ 10 ]);  651                                  mfEmlSetMem ( keyBlock
,  sectortrailer
,  1 );                  654                          PrintAndLog ( "No valid key found" );  657          else  {  // ------------------------------------  multiple sectors working  661                  e_sector 
=  calloc ( SectorsCnt
,  sizeof ( sector
));  662                  if  ( e_sector 
==  NULL
)  return  1 ;  664                  //test current key and additional standard keys first  665                  memcpy ( keyBlock
,  key
,  6 );  666                  num_to_bytes ( 0xffffffffffff ,  6 , ( uint8_t *)( keyBlock 
+  1  *  6 ));  667                  num_to_bytes ( 0x000000000000 ,  6 , ( uint8_t *)( keyBlock 
+  2  *  6 ));  668                  num_to_bytes ( 0xa0a1a2a3a4a5 ,  6 , ( uint8_t *)( keyBlock 
+  3  *  6 ));  669                  num_to_bytes ( 0xb0b1b2b3b4b5 ,  6 , ( uint8_t *)( keyBlock 
+  4  *  6 ));  670                  num_to_bytes ( 0xaabbccddeeff ,  6 , ( uint8_t *)( keyBlock 
+  5  *  6 ));  671                  num_to_bytes ( 0x4d3a99c351dd ,  6 , ( uint8_t *)( keyBlock 
+  6  *  6 ));  672                  num_to_bytes ( 0x1a982c7e459a ,  6 , ( uint8_t *)( keyBlock 
+  7  *  6 ));  673                  num_to_bytes ( 0xd3f7d3f7d3f7 ,  6 , ( uint8_t *)( keyBlock 
+  8  *  6 ));  674                  num_to_bytes ( 0x714c5c886e97 ,  6 , ( uint8_t *)( keyBlock 
+  9  *  6 ));  675                  num_to_bytes ( 0x587ee5f9350f ,  6 , ( uint8_t *)( keyBlock 
+  10  *  6 ));  676                  num_to_bytes ( 0xa0478cc39091 ,  6 , ( uint8_t *)( keyBlock 
+  11  *  6 ));  677                  num_to_bytes ( 0x533cb6c723f6 ,  6 , ( uint8_t *)( keyBlock 
+  12  *  6 ));  678                  num_to_bytes ( 0x8fd0a4f256e9 ,  6 , ( uint8_t *)( keyBlock 
+  13  *  6 ));  680                  PrintAndLog ( "Testing known keys. Sector count= %d " ,  SectorsCnt
);  681                  for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  682                          for  ( j 
=  0 ;  j 
<  2 ;  j
++) {  683                                  if  ( e_sector
[ i
]. foundKey
[ j
])  continue ;  685                                  res 
=  mfCheckKeys ( FirstBlockOfSector ( i
),  j
,  true ,  6 ,  keyBlock
, & key64
);  688                                          e_sector
[ i
]. Key
[ j
] =  key64
;  689                                          e_sector
[ i
]. foundKey
[ j
] =  1 ;  696                  PrintAndLog ( "nested..." );  697                  bool  calibrate 
=  true ;  698                  for  ( i 
=  0 ;  i 
<  NESTED_SECTOR_RETRY
;  i
++) {  699                          for  ( uint8_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  700                                  for  ( trgKeyType 
=  0 ;  trgKeyType 
<  2 ;  trgKeyType
++) {   701                                          if  ( e_sector
[ sectorNo
]. foundKey
[ trgKeyType
])  continue ;  702                                          PrintAndLog ( "-----------------------------------------------" );  703                                          int16_t  isOK 
=  mfnested ( blockNo
,  keyType
,  key
,  FirstBlockOfSector ( sectorNo
),  trgKeyType
,  keyBlock
,  calibrate
);  706                                                          case  - 1  :  PrintAndLog ( "Error: No response from Proxmark. \n " );  break ;  707                                                          case  - 2  :  PrintAndLog ( "Button pressed. Aborted. \n " );  break ;  708                                                          case  - 3  :  PrintAndLog ( "Tag isn't vulnerable to Nested Attack (random numbers are not predictable). \n " );  break ;  709                                                          default  :  PrintAndLog ( "Unknown Error. \n " );  719                                          key64 
=  bytes_to_num ( keyBlock
,  6 );  721                                                  PrintAndLog ( "Found valid key: %0 12" llx
,  key64
);  722                                                  e_sector
[ sectorNo
]. foundKey
[ trgKeyType
] =  1 ;  723                                                  e_sector
[ sectorNo
]. Key
[ trgKeyType
] =  key64
;  729                  printf ( "Time in nested:  %1 .3f ( %1 .3f sec per key) \n\n " , (( float ) clock () -  time1
)/ CLOCKS_PER_SEC
, (( float ) clock () -  time1
)/ iterations
/ CLOCKS_PER_SEC
);  731                  PrintAndLog ( "----------------------------------------------- \n Iterations count:  %d \n\n " ,  iterations
);  733                  PrintAndLog ( "|---|----------------|---|----------------|---|" );  734                  PrintAndLog ( "|sec|key A           |res|key B           |res|" );  735                  PrintAndLog ( "|---|----------------|---|----------------|---|" );  736                  for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  737                          PrintAndLog ( "| %0 3d|   %0 12" llx
"  |  %d  |   %0 12" llx
"  |  %d  |" ,  i
,  738                                  e_sector
[ i
]. Key
[ 0 ],  e_sector
[ i
]. foundKey
[ 0 ],  e_sector
[ i
]. Key
[ 1 ],  e_sector
[ i
]. foundKey
[ 1 ]);  740                  PrintAndLog ( "|---|----------------|---|----------------|---|" );  742                  // transfer them to the emulator  744                          for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  745                                  mfEmlGetMem ( keyBlock
,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ,  1 );  746                                  if  ( e_sector
[ i
]. foundKey
[ 0 ])  747                                          num_to_bytes ( e_sector
[ i
]. Key
[ 0 ],  6 ,  keyBlock
);  748                                  if  ( e_sector
[ i
]. foundKey
[ 1 ])  749                                          num_to_bytes ( e_sector
[ i
]. Key
[ 1 ],  6 , & keyBlock
[ 10 ]);  750                                  mfEmlSetMem ( keyBlock
,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ,  1 );  755                  if  ( createDumpFile
) {  756                          if  (( fkeys 
=  fopen ( "dumpkeys.bin" , "wb" )) ==  NULL
) {   757                                  PrintAndLog ( "Could not create file dumpkeys.bin" );  761                          PrintAndLog ( "Printing keys to binary file dumpkeys.bin..." );  762                          for ( i
= 0 ;  i
< SectorsCnt
;  i
++) {  763                                  if  ( e_sector
[ i
]. foundKey
[ 0 ]){  764                                          num_to_bytes ( e_sector
[ i
]. Key
[ 0 ],  6 ,  tempkey
);  765                                          fwrite  (  tempkey
,  1 ,  6 ,  fkeys 
);  768                                          fwrite  ( & standart
,  1 ,  6 ,  fkeys 
);  771                          for ( i
= 0 ;  i
< SectorsCnt
;  i
++) {  772                                  if  ( e_sector
[ i
]. foundKey
[ 1 ]){  773                                          num_to_bytes ( e_sector
[ i
]. Key
[ 1 ],  6 ,  tempkey
);  774                                          fwrite  (  tempkey
,  1 ,  6 ,  fkeys 
);  777                                          fwrite  ( & standart
,  1 ,  6 ,  fkeys 
);  788  int  CmdHF14AMfChk ( const char  * Cmd
)  791                  PrintAndLog ( "Usage:  hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]" );  792                  PrintAndLog ( "          * - all sectors" );  793                  PrintAndLog ( "card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K" );  794                  PrintAndLog ( "d - write keys to binary file \n " );  795                  PrintAndLog ( "t - write keys to emulator memory" );  796                  PrintAndLog ( "      sample: hf mf chk 0 A 1234567890ab keys.dic" );  797                  PrintAndLog ( "              hf mf chk *1 ? t" );  798                  PrintAndLog ( "              hf mf chk *1 ? d" );  803          char  filename
[ FILE_PATH_SIZE
]={ 0 };  805          uint8_t  * keyBlock 
=  NULL
, * p
;  806          uint8_t  stKeyBlock 
=  20 ;  812          uint8_t  SectorsCnt 
=  1 ;  816          int  transferToEml 
=  0 ;  817          int  createDumpFile 
=  0 ;  819          keyBlock 
=  calloc ( stKeyBlock
,  6 );  820          if  ( keyBlock 
==  NULL
)  return  1 ;  822          uint64_t  defaultKeys
[] =  824                  0xffffffffffff ,  // Default key (first key used by program if no user defined key)  825                  0x000000000000 ,  // Blank key  826                  0xa0a1a2a3a4a5 ,  // NFCForum MAD key  838          int  defaultKeysSize 
=  sizeof ( defaultKeys
) /  sizeof ( uint64_t );  840          for  ( int  defaultKeyCounter 
=  0 ;  defaultKeyCounter 
<  defaultKeysSize
;  defaultKeyCounter
++)  842                  num_to_bytes ( defaultKeys
[ defaultKeyCounter
],  6 , ( uint8_t *)( keyBlock 
+  defaultKeyCounter 
*  6 ));  845          if  ( param_getchar ( Cmd
,  0 )== '*' ) {  847                  switch ( param_getchar ( Cmd
+ 1 ,  0 )) {  848                          case  '0' :  SectorsCnt 
=   5 ;  break ;  849                          case  '1' :  SectorsCnt 
=  16 ;  break ;  850                          case  '2' :  SectorsCnt 
=  32 ;  break ;  851                          case  '4' :  SectorsCnt 
=  40 ;  break ;  852                          default :   SectorsCnt 
=  16 ;  856                  blockNo 
=  param_get8 ( Cmd
,  0 );  858          ctmp 
=  param_getchar ( Cmd
,  1 );  870                  PrintAndLog ( "Key type must be A , B or ?" );  874          ctmp 
=  param_getchar ( Cmd
,  2 );  875          if               ( ctmp 
==  't'  ||  ctmp 
==  'T' )  transferToEml 
=  1 ;  876          else if  ( ctmp 
==  'd'  ||  ctmp 
==  'D' )  createDumpFile 
=  1 ;  878          for  ( i 
=  transferToEml 
||  createDumpFile
;  param_getchar ( Cmd
,  2  +  i
);  i
++) {  879                  if  (! param_gethex ( Cmd
,  2  +  i
,  keyBlock 
+  6  *  keycnt
,  12 )) {  880                          if  (  stKeyBlock 
-  keycnt 
<  2 ) {  881                                  p 
=  realloc ( keyBlock
,  6 *( stKeyBlock
+= 10 ));  883                                          PrintAndLog ( "Cannot allocate memory for Keys" );  889                          PrintAndLog ( "chk key[ %2 d]  %0 2x %0 2x %0 2x %0 2x %0 2x %0 2x" ,  keycnt
,  890                          ( keyBlock 
+  6 * keycnt
)[ 0 ],( keyBlock 
+  6 * keycnt
)[ 1 ], ( keyBlock 
+  6 * keycnt
)[ 2 ],  891                          ( keyBlock 
+  6 * keycnt
)[ 3 ], ( keyBlock 
+  6 * keycnt
)[ 4 ],     ( keyBlock 
+  6 * keycnt
)[ 5 ],  6 );  895                          if  (  param_getstr ( Cmd
,  2  +  i
, filename
) >=  FILE_PATH_SIZE 
) {  896                                  PrintAndLog ( "File name too long" );  901                          if  ( ( f 
=  fopen (  filename 
,  "r" )) ) {  902                                  while (  fgets ( buf
,  sizeof ( buf
),  f
) ){  903                                          if  ( strlen ( buf
) <  12  ||  buf
[ 11 ] ==  ' \n ' )  906                                          while  ( fgetc ( f
) !=  ' \n '  && ! feof ( f
)) ;   //goto next line  908                                          if (  buf
[ 0 ]== '#'  )  continue ;      //The line start with # is comment, skip  910                                          if  (! isxdigit ( buf
[ 0 ])){  911                                                  PrintAndLog ( "File content error. ' %s ' must include 12 HEX symbols" , buf
);  917                                          if  (  stKeyBlock 
-  keycnt 
<  2 ) {  918                                                  p 
=  realloc ( keyBlock
,  6 *( stKeyBlock
+= 10 ));  920                                                          PrintAndLog ( "Cannot allocate memory for defKeys" );  926                                          memset ( keyBlock 
+  6  *  keycnt
,  0 ,  6 );  927                                          num_to_bytes ( strtoll ( buf
,  NULL
,  16 ),  6 ,  keyBlock 
+  6 * keycnt
);  928                                          PrintAndLog ( "chk custom key[ %2 d]  %0 12" llx
,  keycnt
,  bytes_to_num ( keyBlock 
+  6 * keycnt
,  6 ));  930                                          memset ( buf
,  0 ,  sizeof ( buf
));  934                                  PrintAndLog ( "File:  %s : not found or locked." ,  filename
);  943                  PrintAndLog ( "No key specified, trying default keys" );  944                  for  (; keycnt 
<  defaultKeysSize
;  keycnt
++)  945                          PrintAndLog ( "chk default key[ %2 d]  %0 2x %0 2x %0 2x %0 2x %0 2x %0 2x" ,  keycnt
,  946                                  ( keyBlock 
+  6 * keycnt
)[ 0 ],( keyBlock 
+  6 * keycnt
)[ 1 ], ( keyBlock 
+  6 * keycnt
)[ 2 ],  947                                  ( keyBlock 
+  6 * keycnt
)[ 3 ], ( keyBlock 
+  6 * keycnt
)[ 4 ],     ( keyBlock 
+  6 * keycnt
)[ 5 ],  6 );  950          // initialize storage for found keys  951          bool  validKey
[ 2 ][ 40 ];  952          uint8_t  foundKey
[ 2 ][ 40 ][ 6 ];  953          for  ( uint16_t  t 
=  0 ;  t 
<  2 ;  t
++) {  954                  for  ( uint16_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  955                          validKey
[ t
][ sectorNo
] =  false ;  956                          for  ( uint16_t  i 
=  0 ;  i 
<  6 ;  i
++) {  957                                  foundKey
[ t
][ sectorNo
][ i
] =  0xff ;  962          for  (  int  t 
= ! keyType
;  t 
<  2 ;  keyType
== 2 ?( t
++):( t
= 2 ) ) {  964                  for  ( int  i 
=  0 ;  i 
<  SectorsCnt
; ++ i
) {  965                          PrintAndLog ( "--sector: %2 d, block: %3 d, key type: %C , key count: %2 d " ,  i
,  b
,  t
? 'B' : 'A' ,  keycnt
);  966                          uint32_t  max_keys 
=  keycnt
> USB_CMD_DATA_SIZE
/ 6 ? USB_CMD_DATA_SIZE
/ 6 : keycnt
;  967                          for  ( uint32_t  c 
=  0 ;  c 
<  keycnt
;  c
+= max_keys
) {  968                                  uint32_t  size 
=  keycnt
- c
> max_keys
? max_keys
: keycnt
- c
;  969                                  res 
=  mfCheckKeys ( b
,  t
,  true ,  size
, & keyBlock
[ 6 * c
], & key64
);  972                                                  PrintAndLog ( "Found valid key:[ %0 12" llx
"]" , key64
);  973                                                  num_to_bytes ( key64
,  6 ,  foundKey
[ t
][ i
]);  974                                                  validKey
[ t
][ i
] =  true ;  977                                          PrintAndLog ( "Command execute timeout" );  980                          b
< 127 ?( b
+= 4 ):( b
+= 16 );     986                  for  ( uint16_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  987                          if  ( validKey
[ 0 ][ sectorNo
] ||  validKey
[ 1 ][ sectorNo
]) {  988                                  mfEmlGetMem ( block
,  FirstBlockOfSector ( sectorNo
) +  NumBlocksPerSector ( sectorNo
) -  1 ,  1 );  989                                  for  ( uint16_t  t 
=  0 ;  t 
<  2 ;  t
++) {  990                                          if  ( validKey
[ t
][ sectorNo
]) {  991                                                  memcpy ( block 
+  t
* 10 ,  foundKey
[ t
][ sectorNo
],  6 );  994                                  mfEmlSetMem ( block
,  FirstBlockOfSector ( sectorNo
) +  NumBlocksPerSector ( sectorNo
) -  1 ,  1 );  997                  PrintAndLog ( "Found keys have been transferred to the emulator memory" ); 1000          if  ( createDumpFile
) { 1001                  FILE  * fkeys 
=  fopen ( "dumpkeys.bin" , "wb" ); 1002                  if  ( fkeys 
==  NULL
) {  1003                          PrintAndLog ( "Could not create file dumpkeys.bin" ); 1007                  for  ( uint16_t  t 
=  0 ;  t 
<  2 ;  t
++) { 1008                          fwrite ( foundKey
[ t
],  1 ,  6 * SectorsCnt
,  fkeys
); 1011                  PrintAndLog ( "Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys." ); 1019  void  readerAttack ( nonces_t ar_resp
[],  bool  setEmulatorMem
) { 1020          #define ATTACK_KEY_COUNT 8 1027          st_t sector_trailer
[ ATTACK_KEY_COUNT
]; 1028          memset ( sector_trailer
,  0x00 ,  sizeof ( sector_trailer
)); 1030          uint8_t  stSector
[ ATTACK_KEY_COUNT
]; 1031          memset ( stSector
,  0x00 ,  sizeof ( stSector
)); 1032          uint8_t  key_cnt
[ ATTACK_KEY_COUNT
]; 1033          memset ( key_cnt
,  0x00 ,  sizeof ( key_cnt
)); 1035          for  ( uint8_t  i 
=  0 ;  i
< ATTACK_KEY_COUNT
;  i
++) { 1036                  if  ( ar_resp
[ i
]. ar2 
>  0 ) { 1037                          //PrintAndLog("Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2); 1038                          if  ( mfkey32 ( ar_resp
[ i
], & key
)) { 1039                                  PrintAndLog ( "Found Key %s  for sector  %0 2d: [ %0 4x %0 8x]" , ( ar_resp
[ i
]. keytype
) ?  "B"  :  "A" ,  ar_resp
[ i
]. sector
, ( uint32_t ) ( key
>> 32 ), ( uint32_t ) ( key 
& 0xFFFFFFFF )); 1041                                  for  ( uint8_t  ii 
=  0 ;  ii
< ATTACK_KEY_COUNT
;  ii
++) { 1042                                          if  ( key_cnt
[ ii
]== 0  ||  stSector
[ ii
]== ar_resp
[ i
]. sector
) { 1043                                                  if  ( ar_resp
[ i
]. keytype
== 0 ) { 1045                                                          sector_trailer
[ ii
]. keyA 
=  key
; 1046                                                          stSector
[ ii
] =  ar_resp
[ i
]. sector
; 1051                                                          sector_trailer
[ ii
]. keyB 
=  key
; 1052                                                          stSector
[ ii
] =  ar_resp
[ i
]. sector
; 1061          //set emulator memory for keys 1062          if  ( setEmulatorMem
) { 1063                  for  ( uint8_t  i 
=  0 ;  i
< ATTACK_KEY_COUNT
;  i
++) { 1065                                  //PrintAndLog   ("block %d, keyA:%04x%08x, keyb:%04x%08x",stSector[i]*4+3, (uint32_t) (sector_trailer[i].keyA>>32), (uint32_t) (sector_trailer[i].keyA &0xFFFFFFFF),(uint32_t) (sector_trailer[i].keyB>>32), (uint32_t) (sector_trailer[i].keyB &0xFFFFFFFF)); 1066                                  uint8_t  memBlock
[ 16 ]; 1067                                  memset ( memBlock
,  0x00 ,  sizeof ( memBlock
)); 1069                                  memset ( cmd1
, 0x00 , sizeof ( cmd1
)); 1070                                  snprintf ( cmd1
, sizeof ( cmd1
), " %0 4x %0 8xFF078069 %0 4x %0 8x" ,( uint32_t ) ( sector_trailer
[ i
]. keyA
>> 32 ), ( uint32_t ) ( sector_trailer
[ i
]. keyA 
& 0xFFFFFFFF ),( uint32_t ) ( sector_trailer
[ i
]. keyB
>> 32 ), ( uint32_t ) ( sector_trailer
[ i
]. keyB 
& 0xFFFFFFFF )); 1071                                  PrintAndLog ( "Setting Emulator Memory Block  %0 2d: [ %s ]" , stSector
[ i
]* 4 + 3 ,  cmd1
); 1072                                  if  ( param_gethex ( cmd1
,  0 ,  memBlock
,  32 )) { 1073                                          PrintAndLog ( "block data must include 32 HEX symbols" ); 1077                                  UsbCommand c 
= { CMD_MIFARE_EML_MEMSET
, {( stSector
[ i
]* 4 + 3 ),  1 ,  0 }}; 1078                                  memcpy ( c
. d
. asBytes
,  memBlock
,  16 ); 1079                                  clearCommandBuffer (); 1085          for  ( uint8_t  i 
=  ATTACK_KEY_COUNT
;  i
< ATTACK_KEY_COUNT
* 2 ;  i
++) { 1086                  if  ( ar_resp
[ i
]. ar2 
>  0 ) { 1087                          if  ( tryMfk32_moebius ( ar_resp
[ i
], & key
)) { 1088                                  PrintAndLog ( "M-Found Key %s  for sector  %0 2d: [ %0 4x %0 8x]" , ( ar_resp
[ i
]. keytype
) ?  "B"  :  "A" ,  ar_resp
[ i
]. sector
, ( uint32_t ) ( key
>> 32 ), ( uint32_t ) ( key 
& 0xFFFFFFFF )); 1094  int  usage_hf14_mf1ksim ( void ) { 1095          PrintAndLog ( "Usage:  hf mf sim  [h] u <uid (8,14 hex symbols)> n <numreads> i x" ); 1096          PrintAndLog ( "options:" ); 1097          PrintAndLog ( "      h    this help" ); 1098          PrintAndLog ( "      u    (Optional) UID 4,7 bytes. If not specified, the UID 4b from emulator memory will be used" ); 1099          PrintAndLog ( "      n    (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite" ); 1100          PrintAndLog ( "      i    (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted" ); 1101          PrintAndLog ( "      x    (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)" ); 1102          PrintAndLog ( "      e    (Optional) set keys found from 'reader attack' to emulator memory" ); 1103          PrintAndLog ( "      f    (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>'" ); 1104          PrintAndLog ( "samples:" ); 1105          PrintAndLog ( "           hf mf sim u 0a0a0a0a" ); 1106          PrintAndLog ( "           hf mf sim u 11223344556677" ); 1107          PrintAndLog ( "           hf mf sim u 112233445566778899AA" );      1111  int  CmdHF14AMf1kSim ( const char  * Cmd
) { 1112          uint8_t  uid
[ 10 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 }; 1113          uint8_t  exitAfterNReads 
=  0 ; 1117          bool  setEmulatorMem 
=  false ; 1118          bool  attackFromFile 
=  false ; 1120          char  filename
[ FILE_PATH_SIZE
]; 1121          memset ( filename
,  0x00 ,  sizeof ( filename
)); 1124          uint8_t  uidBuffer
[ 64 ]; 1127          bool  errors 
=  false ; 1129          while ( param_getchar ( Cmd
,  cmdp
) !=  0x00 ) { 1130                  switch ( param_getchar ( Cmd
,  cmdp
)) { 1133                          setEmulatorMem 
=  true ; 1138                          len 
=  param_getstr ( Cmd
,  cmdp
+ 1 ,  filename
); 1140                                  PrintAndLog ( "error no filename found" ); 1143                          attackFromFile 
=  true ; 1148                          return  usage_hf14_mf1ksim (); 1151                          flags 
|=  FLAG_INTERACTIVE
; 1156                          exitAfterNReads 
=  param_get8 ( Cmd
,  pnr
+ 1 ); 1161                          param_gethex_ex ( Cmd
,  cmdp
+ 1 ,  uid
, & uidlen
); 1163                                  case  20 :  flags 
=  FLAG_10B_UID_IN_DATA
;   break ;  //not complete 1164                                  case  14 :  flags 
=  FLAG_7B_UID_IN_DATA
;  break ; 1165                                  case   8 :  flags 
=  FLAG_4B_UID_IN_DATA
;  break ; 1166                                  default :  return  usage_hf14_mf1ksim (); 1172                          flags 
|=  FLAG_NR_AR_ATTACK
; 1176                          PrintAndLog ( "Unknown parameter ' %c '" ,  param_getchar ( Cmd
,  cmdp
)); 1183          if ( errors
)  return  usage_hf14_mf1ksim (); 1185          // attack from file implies nr ar attack... 1186          if  (!( flags 
&  FLAG_NR_AR_ATTACK
) &&  attackFromFile
)  flags 
|=  FLAG_NR_AR_ATTACK
; 1188          UsbCommand c 
= { CMD_SIMULATE_MIFARE_CARD
, { flags
,  exitAfterNReads
, 0 }}; 1192          if  ( attackFromFile
) { 1195                  f 
=  fopen ( filename
,  "r" ); 1197                          PrintAndLog ( "File  %s  not found or locked" ,  filename
); 1201                          memset ( buf
,  0 ,  sizeof ( buf
)); 1202                          memset ( uidBuffer
,  0 ,  sizeof ( uidBuffer
)); 1204                          if  ( fgets ( buf
,  sizeof ( buf
),  f
) ==  NULL
) {                        1205                                  if  ( count 
>  0 )  break ; 1207                                  PrintAndLog ( "File reading error." ); 1212                          if  ( strlen ( buf
) <  uidlen
) { 1213                                  if ( strlen ( buf
) &&  feof ( f
)) 1215                                  PrintAndLog ( "File content error. Block data must include  %d  HEX symbols" ,  uidlen
); 1220                          for  ( uint8_t  i 
=  0 ;  i 
<  uidlen
;  i 
+=  2 ) { 1221                                  sscanf (& buf
[ i
],  " %0 2x" , ( unsigned int  *)& uidBuffer
[ i 
/  2 ]); 1224                          PrintAndLog ( "mf 1k sim uid:  %s , numreads: %d , flags: %d  (0x %0 2x) " , 1225                                          flags 
&  FLAG_4B_UID_IN_DATA 
?  sprint_hex ( uid
, 4 ): 1226                                                  flags 
&  FLAG_7B_UID_IN_DATA     
?  sprint_hex ( uid
, 7 ):  1227                                                          flags 
&  FLAG_10B_UID_IN_DATA 
?  sprint_hex ( uid
, 10 ):  "N/A" 1228                                          ,  exitAfterNReads
,  flags
,  flags
); 1230                          memcpy ( c
. d
. asBytes
,  uid
,  sizeof ( uid
)); 1231                          clearCommandBuffer (); 1234                          if ( flags 
&  FLAG_INTERACTIVE
) { 1235                                  PrintAndLog ( "Press pm3-button to abort simulation" ); 1236                                  while (!  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) { 1237                                          //We're waiting only 1.5 s at a time, otherwise we get the 1238                                          // annoying message about "Waiting for a response... " 1241                                  if  ( flags 
&  FLAG_NR_AR_ATTACK
) { 1242                                          nonces_t ar_resp
[ ATTACK_KEY_COUNT
* 2 ]; 1243                                          memcpy ( ar_resp
,  resp
. d
. asBytes
,  sizeof ( ar_resp
)); 1244                                          readerAttack ( ar_resp
,  setEmulatorMem
); 1253                  PrintAndLog ( "mf 1k sim uid:  %s , numreads: %d , flags: %d  (0x %0 2x) " , 1254                                  flags 
&  FLAG_4B_UID_IN_DATA 
?  sprint_hex ( uid
, 4 ): 1255                                          flags 
&  FLAG_7B_UID_IN_DATA     
?  sprint_hex ( uid
, 7 ):  1256                                                  flags 
&  FLAG_10B_UID_IN_DATA 
?  sprint_hex ( uid
, 10 ):  "N/A" 1257                                  ,  exitAfterNReads
,  flags
,  flags
); 1259                  memcpy ( c
. d
. asBytes
,  uid
,  sizeof ( uid
)); 1260                  clearCommandBuffer (); 1263                  if ( flags 
&  FLAG_INTERACTIVE
) { 1264                          PrintAndLog ( "Press pm3-button to abort simulation" ); 1265                          while (!  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) { 1266                                  //We're waiting only 1.5 s at a time, otherwise we get the 1267                                  // annoying message about "Waiting for a response... " 1270                          if  ( flags 
&  FLAG_NR_AR_ATTACK
) { 1271                                  nonces_t ar_resp
[ ATTACK_KEY_COUNT
* 2 ]; 1272                                  memcpy ( ar_resp
,  resp
. d
. asBytes
,  sizeof ( ar_resp
)); 1273                                  readerAttack ( ar_resp
,  setEmulatorMem
); 1281  int  CmdHF14AMfDbg ( const char  * Cmd
) 1283          int  dbgMode 
=  param_get32ex ( Cmd
,  0 ,  0 ,  10 ); 1285                  PrintAndLog ( "Max debug mode parameter is 4  \n " ); 1288          if  ( strlen ( Cmd
) <  1  || ! param_getchar ( Cmd
,  0 ) ||  dbgMode 
>  4 ) { 1289                  PrintAndLog ( "Usage:  hf mf dbg  <debug level>" ); 1290                  PrintAndLog ( " 0 - no debug messages" ); 1291                  PrintAndLog ( " 1 - error messages" ); 1292                  PrintAndLog ( " 2 - plus information messages" ); 1293                  PrintAndLog ( " 3 - plus debug messages" ); 1294                  PrintAndLog ( " 4 - print even debug messages in timing critical functions" ); 1295                  PrintAndLog ( "     Note: this option therefore may cause malfunction itself" ); 1299    UsbCommand c 
= { CMD_MIFARE_SET_DBGMODE
, { dbgMode
,  0 ,  0 }}; 1305  int  CmdHF14AMfEGet ( const char  * Cmd
) 1307          uint8_t  blockNo 
=  0 ; 1308          uint8_t  data
[ 16 ] = { 0x00 }; 1310          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) { 1311                  PrintAndLog ( "Usage:  hf mf eget <block number>" ); 1312                  PrintAndLog ( " sample: hf mf eget 0 " ); 1316          blockNo 
=  param_get8 ( Cmd
,  0 ); 1319          if  (! mfEmlGetMem ( data
,  blockNo
,  1 )) { 1320                  PrintAndLog ( "data[ %3 d]: %s " ,  blockNo
,  sprint_hex ( data
,  16 )); 1322                  PrintAndLog ( "Command execute timeout" ); 1328  int  CmdHF14AMfEClear ( const char  * Cmd
) 1330          if  ( param_getchar ( Cmd
,  0 ) ==  'h' ) { 1331                  PrintAndLog ( "Usage:  hf mf eclr" ); 1332                  PrintAndLog ( "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF  \n " ); 1336    UsbCommand c 
= { CMD_MIFARE_EML_MEMCLR
, { 0 ,  0 ,  0 }}; 1342  int  CmdHF14AMfESet ( const char  * Cmd
) 1344          uint8_t  memBlock
[ 16 ]; 1345          uint8_t  blockNo 
=  0 ; 1347          memset ( memBlock
,  0x00 ,  sizeof ( memBlock
)); 1349          if  ( strlen ( Cmd
) <  3  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) { 1350                  PrintAndLog ( "Usage:  hf mf eset <block number> <block data (32 hex symbols)>" ); 1351                  PrintAndLog ( " sample: hf mf eset 1 000102030405060708090a0b0c0d0e0f " ); 1355          blockNo 
=  param_get8 ( Cmd
,  0 ); 1357          if  ( param_gethex ( Cmd
,  1 ,  memBlock
,  32 )) { 1358                  PrintAndLog ( "block data must include 32 HEX symbols" ); 1363          UsbCommand c 
= { CMD_MIFARE_EML_MEMSET
, { blockNo
,  1 ,  0 }}; 1364          memcpy ( c
. d
. asBytes
,  memBlock
,  16 ); 1370  int  CmdHF14AMfELoad ( const char  * Cmd
) 1373          char  filename
[ FILE_PATH_SIZE
]; 1374          char  * fnameptr 
=  filename
; 1375          char  buf
[ 64 ] = { 0x00 }; 1376          uint8_t  buf8
[ 64 ] = { 0x00 }; 1377          int  i
,  len
,  blockNum
,  numBlocks
; 1378          int  nameParamNo 
=  1 ; 1380          char  ctmp 
=  param_getchar ( Cmd
,  0 ); 1382          if  (  ctmp 
==  'h'  ||  ctmp 
==  0x00 ) { 1383                  PrintAndLog ( "It loads emul dump from the file `filename.eml`" ); 1384                  PrintAndLog ( "Usage:  hf mf eload [card memory] <file name w/o `.eml`>" ); 1385                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" ); 1387                  PrintAndLog ( " sample: hf mf eload filename" ); 1388                  PrintAndLog ( "         hf mf eload 4 filename" ); 1393                  case  '0'  :  numBlocks 
=  5 * 4 ;  break ; 1395                  case  '\0' :  numBlocks 
=  16 * 4 ;  break ; 1396                  case  '2'  :  numBlocks 
=  32 * 4 ;  break ; 1397                  case  '4'  :  numBlocks 
=  256 ;  break ; 1404          len 
=  param_getstr ( Cmd
, nameParamNo
, filename
); 1406          if  ( len 
>  FILE_PATH_SIZE 
-  4 )  len 
=  FILE_PATH_SIZE 
-  4 ; 1410          sprintf ( fnameptr
,  ".eml" );  1413          f 
=  fopen ( filename
,  "r" ); 1415                  PrintAndLog ( "File  %s  not found or locked" ,  filename
); 1421                  memset ( buf
,  0 ,  sizeof ( buf
)); 1423                  if  ( fgets ( buf
,  sizeof ( buf
),  f
) ==  NULL
) { 1425                          if  ( blockNum 
>=  numBlocks
)  break ; 1427                          PrintAndLog ( "File reading error." ); 1432                  if  ( strlen ( buf
) <  32 ){ 1433                          if ( strlen ( buf
) &&  feof ( f
)) 1435                          PrintAndLog ( "File content error. Block data must include 32 HEX symbols" ); 1440                  for  ( i 
=  0 ;  i 
<  32 ;  i 
+=  2 ) { 1441                          sscanf (& buf
[ i
],  " %0 2x" , ( unsigned int  *)& buf8
[ i 
/  2 ]); 1444                  if  ( mfEmlSetMem ( buf8
,  blockNum
,  1 )) { 1445                          PrintAndLog ( "Cant set emul block:  %3 d" ,  blockNum
); 1452                  if  ( blockNum 
>=  numBlocks
)  break ; 1457          if  (( blockNum 
!=  numBlocks
)) { 1458                  PrintAndLog ( "File content error. Got  %d  must be  %d  blocks." , blockNum
,  numBlocks
); 1461          PrintAndLog ( "Loaded  %d  blocks from file:  %s " ,  blockNum
,  filename
); 1466  int  CmdHF14AMfESave ( const char  * Cmd
) 1469          char  filename
[ FILE_PATH_SIZE
]; 1470          char  *  fnameptr 
=  filename
; 1472          int  i
,  j
,  len
,  numBlocks
; 1473          int  nameParamNo 
=  1 ; 1475          memset ( filename
,  0 ,  sizeof ( filename
)); 1476          memset ( buf
,  0 ,  sizeof ( buf
)); 1478          char  ctmp 
=  param_getchar ( Cmd
,  0 ); 1480          if  (  ctmp 
==  'h'  ||  ctmp 
==  'H' ) { 1481                  PrintAndLog ( "It saves emul dump into the file `filename.eml` or `cardID.eml`" ); 1482                  PrintAndLog ( " Usage:  hf mf esave [card memory] [file name w/o `.eml`]" ); 1483                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" ); 1485                  PrintAndLog ( " sample: hf mf esave " ); 1486                  PrintAndLog ( "         hf mf esave 4" ); 1487                  PrintAndLog ( "         hf mf esave 4 filename" ); 1492                  case  '0'  :  numBlocks 
=  5 * 4 ;  break ; 1494                  case  '\0' :  numBlocks 
=  16 * 4 ;  break ; 1495                  case  '2'  :  numBlocks 
=  32 * 4 ;  break ; 1496                  case  '4'  :  numBlocks 
=  256 ;  break ; 1503          len 
=  param_getstr ( Cmd
, nameParamNo
, filename
); 1505          if  ( len 
>  FILE_PATH_SIZE 
-  4 )  len 
=  FILE_PATH_SIZE 
-  4 ; 1507          // user supplied filename? 1509                  // get filename (UID from memory) 1510                  if  ( mfEmlGetMem ( buf
,  0 ,  1 )) { 1511                          PrintAndLog ( "Can \' t get UID from block:  %d " ,  0 ); 1512                          len 
=  sprintf ( fnameptr
,  "dump" ); 1516                          for  ( j 
=  0 ;  j 
<  7 ;  j
++,  fnameptr 
+=  2 ) 1517                                  sprintf ( fnameptr
,  " %0 2X" ,  buf
[ j
]); 1523          // add file extension 1524          sprintf ( fnameptr
,  ".eml" );  1527          f 
=  fopen ( filename
,  "w+" ); 1530                  PrintAndLog ( "Can't open file  %s  " ,  filename
); 1535          for  ( i 
=  0 ;  i 
<  numBlocks
;  i
++) { 1536                  if  ( mfEmlGetMem ( buf
,  i
,  1 )) { 1537                          PrintAndLog ( "Cant get block:  %d " ,  i
); 1540                  for  ( j 
=  0 ;  j 
<  16 ;  j
++) 1541                          fprintf ( f
,  " %0 2X" ,  buf
[ j
]);  1546          PrintAndLog ( "Saved  %d  blocks to file:  %s " ,  numBlocks
,  filename
); 1552  int  CmdHF14AMfECFill ( const char  * Cmd
) 1554          uint8_t  keyType 
=  0 ; 1555          uint8_t  numSectors 
=  16 ; 1557          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) { 1558                  PrintAndLog ( "Usage:  hf mf ecfill <key A/B> [card memory]" ); 1559                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" ); 1561                  PrintAndLog ( "samples:  hf mf ecfill A" ); 1562                  PrintAndLog ( "          hf mf ecfill A 4" ); 1563                  PrintAndLog ( "Read card and transfer its data to emulator memory." ); 1564                  PrintAndLog ( "Keys must be laid in the emulator memory.  \n " ); 1568          char  ctmp 
=  param_getchar ( Cmd
,  0 ); 1569          if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) { 1570                  PrintAndLog ( "Key type must be A or B" ); 1573          if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' )  keyType 
=  1 ; 1575          ctmp 
=  param_getchar ( Cmd
,  1 ); 1577                  case  '0'  :  numSectors 
=  5 ;  break ; 1579                  case  '\0' :  numSectors 
=  16 ;  break ; 1580                  case  '2'  :  numSectors 
=  32 ;  break ; 1581                  case  '4'  :  numSectors 
=  40 ;  break ; 1582                  default :    numSectors 
=  16 ; 1585          printf ( "--params: numSectors:  %d , keyType: %d " ,  numSectors
,  keyType
); 1586          UsbCommand c 
= { CMD_MIFARE_EML_CARDLOAD
, { numSectors
,  keyType
,  0 }}; 1592  int  CmdHF14AMfEKeyPrn ( const char  * Cmd
) 1597          uint64_t  keyA
,  keyB
; 1599          if  ( param_getchar ( Cmd
,  0 ) ==  'h' ) { 1600                  PrintAndLog ( "It prints the keys loaded in the emulator memory" ); 1601                  PrintAndLog ( "Usage:  hf mf ekeyprn [card memory]" ); 1602                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" ); 1604                  PrintAndLog ( " sample: hf mf ekeyprn 1" ); 1608          char  cmdp 
=  param_getchar ( Cmd
,  0 ); 1611                  case  '0'  :  numSectors 
=  5 ;  break ; 1613                  case  '\0' :  numSectors 
=  16 ;  break ; 1614                  case  '2'  :  numSectors 
=  32 ;  break ; 1615                  case  '4'  :  numSectors 
=  40 ;  break ; 1616                  default :    numSectors 
=  16 ; 1619          PrintAndLog ( "|---|----------------|----------------|" ); 1620          PrintAndLog ( "|sec|key A           |key B           |" ); 1621          PrintAndLog ( "|---|----------------|----------------|" ); 1622          for  ( i 
=  0 ;  i 
<  numSectors
;  i
++) { 1623                  if  ( mfEmlGetMem ( data
,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ,  1 )) { 1624                          PrintAndLog ( "error get block  %d " ,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ); 1627                  keyA 
=  bytes_to_num ( data
,  6 ); 1628                  keyB 
=  bytes_to_num ( data 
+  10 ,  6 ); 1629                  PrintAndLog ( "| %0 3d|   %0 12" llx
"  |   %0 12" llx
"  |" ,  i
,  keyA
,  keyB
); 1631          PrintAndLog ( "|---|----------------|----------------|" ); 1637  int  CmdHF14AMfCSetUID ( const char  * Cmd
) 1639          uint8_t  wipeCard 
=  0 ; 1640          uint8_t  uid
[ 8 ] = { 0x00 }; 1641          uint8_t  oldUid
[ 8 ] = { 0x00 }; 1642          uint8_t  atqa
[ 2 ] = { 0x00 }; 1643          uint8_t  sak
[ 1 ] = { 0x00 }; 1644          uint8_t  atqaPresent 
=  1 ; 1649          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  argi
) ==  'h' ) { 1650                  PrintAndLog ( "Usage:  hf mf csetuid <UID 8 hex symbols> [ATQA 4 hex symbols SAK 2 hex symbols] [w]" ); 1651                  PrintAndLog ( "sample:  hf mf csetuid 01020304" ); 1652                  PrintAndLog ( "sample:  hf mf csetuid 01020304 0004 08 w" ); 1653                  PrintAndLog ( "Set UID, ATQA, and SAK for magic Chinese card (only works with such cards)" ); 1654                  PrintAndLog ( "If you also want to wipe the card then add 'w' at the end of the command line." ); 1658          if  ( param_getchar ( Cmd
,  argi
) &&  param_gethex ( Cmd
,  argi
,  uid
,  8 )) { 1659                  PrintAndLog ( "UID must include 8 HEX symbols" ); 1664          ctmp 
=  param_getchar ( Cmd
,  argi
); 1665          if  ( ctmp 
==  'w'  ||  ctmp 
==  'W' ) { 1671                  if  ( param_getchar ( Cmd
,  argi
)) { 1672                          if  ( param_gethex ( Cmd
,  argi
,  atqa
,  4 )) { 1673                                  PrintAndLog ( "ATQA must include 4 HEX symbols" ); 1677                          if  (! param_getchar ( Cmd
,  argi
) ||  param_gethex ( Cmd
,  argi
,  sak
,  2 )) { 1678                                  PrintAndLog ( "SAK must include 2 HEX symbols" ); 1687                  ctmp 
=  param_getchar ( Cmd
,  argi
); 1688                  if  ( ctmp 
==  'w'  ||  ctmp 
==  'W' ) { 1693          PrintAndLog ( "--wipe card: %s   uid: %s " , ( wipeCard
)? "YES" : "NO" ,  sprint_hex ( uid
,  4 )); 1695          res 
=  mfCSetUID ( uid
, ( atqaPresent
)? atqa
: NULL
, ( atqaPresent
)? sak
: NULL
,  oldUid
,  wipeCard
); 1697                          PrintAndLog ( "Can't set UID. error= %d " ,  res
); 1701          PrintAndLog ( "old UID: %s " ,  sprint_hex ( oldUid
,  4 )); 1702          PrintAndLog ( "new UID: %s " ,  sprint_hex ( uid
,  4 )); 1706  int  CmdHF14AMfCSetBlk ( const char  * Cmd
) 1708          uint8_t  memBlock
[ 16 ] = { 0x00 }; 1709          uint8_t  blockNo 
=  0 ; 1710          bool  wipeCard 
=  FALSE
; 1713          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) { 1714                  PrintAndLog ( "Usage:  hf mf csetblk <block number> <block data (32 hex symbols)> [w]" ); 1715                  PrintAndLog ( "sample:  hf mf csetblk 1 01020304050607080910111213141516" ); 1716                  PrintAndLog ( "Set block data for magic Chinese card (only works with such cards)" ); 1717                  PrintAndLog ( "If you also want wipe the card then add 'w' at the end of the command line" ); 1721          blockNo 
=  param_get8 ( Cmd
,  0 ); 1723          if  ( param_gethex ( Cmd
,  1 ,  memBlock
,  32 )) { 1724                  PrintAndLog ( "block data must include 32 HEX symbols" ); 1728          char  ctmp 
=  param_getchar ( Cmd
,  2 ); 1729          wipeCard 
= ( ctmp 
==  'w'  ||  ctmp 
==  'W' ); 1730          PrintAndLog ( "--block number: %2 d data: %s " ,  blockNo
,  sprint_hex ( memBlock
,  16 )); 1732          res 
=  mfCSetBlock ( blockNo
,  memBlock
,  NULL
,  wipeCard
,  CSETBLOCK_SINGLE_OPER
); 1734                  PrintAndLog ( "Can't write block. error= %d " ,  res
); 1741  int  CmdHF14AMfCLoad ( const char  * Cmd
) 1744          char  filename
[ FILE_PATH_SIZE
] = { 0x00 }; 1745          char  *  fnameptr 
=  filename
; 1746          char  buf
[ 64 ] = { 0x00 }; 1747          uint8_t  buf8
[ 64 ] = { 0x00 }; 1748          uint8_t  fillFromEmulator 
=  0 ; 1749          int  i
,  len
,  blockNum
,  flags
= 0 ; 1751          if  ( param_getchar ( Cmd
,  0 ) ==  'h'  ||  param_getchar ( Cmd
,  0 )==  0x00 ) { 1752                  PrintAndLog ( "It loads magic Chinese card from the file `filename.eml`" ); 1753                  PrintAndLog ( "or from emulator memory (option `e`)" ); 1754                  PrintAndLog ( "Usage:  hf mf cload <file name w/o `.eml`>" ); 1755                  PrintAndLog ( "   or:  hf mf cload e " ); 1756                  PrintAndLog ( " sample: hf mf cload filename" ); 1760          char  ctmp 
=  param_getchar ( Cmd
,  0 ); 1761          if  ( ctmp 
==  'e'  ||  ctmp 
==  'E' )  fillFromEmulator 
=  1 ; 1763          if  ( fillFromEmulator
) { 1764                  for  ( blockNum 
=  0 ;  blockNum 
<  16  *  4 ;  blockNum 
+=  1 ) { 1765                          if  ( mfEmlGetMem ( buf8
,  blockNum
,  1 )) { 1766                                  PrintAndLog ( "Cant get block:  %d " ,  blockNum
); 1769                          if  ( blockNum 
==  0 )  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;                                // switch on field and send magic sequence 1770                          if  ( blockNum 
==  1 )  flags 
=  0 ;                                                                                                    // just write 1771                          if  ( blockNum 
==  16  *  4  -  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;              // Done. Magic Halt and switch off field. 1773                          if  ( mfCSetBlock ( blockNum
,  buf8
,  NULL
,  0 ,  flags
)) { 1774                                  PrintAndLog ( "Cant set magic card block:  %d " ,  blockNum
); 1781                  if  ( len 
>  FILE_PATH_SIZE 
-  4 )  len 
=  FILE_PATH_SIZE 
-  4 ; 1783                  memcpy ( filename
,  Cmd
,  len
); 1786                  sprintf ( fnameptr
,  ".eml" );  1789                  f 
=  fopen ( filename
,  "r" ); 1791                          PrintAndLog ( "File not found or locked." ); 1798                          memset ( buf
,  0 ,  sizeof ( buf
)); 1800                          if  ( fgets ( buf
,  sizeof ( buf
),  f
) ==  NULL
) { 1802                                  PrintAndLog ( "File reading error." ); 1806                          if  ( strlen ( buf
) <  32 ) { 1807                                  if ( strlen ( buf
) &&  feof ( f
)) 1809                                  PrintAndLog ( "File content error. Block data must include 32 HEX symbols" ); 1813                          for  ( i 
=  0 ;  i 
<  32 ;  i 
+=  2 ) 1814                                  sscanf (& buf
[ i
],  " %0 2x" , ( unsigned int  *)& buf8
[ i 
/  2 ]); 1816                          if  ( blockNum 
==  0 )  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;                                // switch on field and send magic sequence 1817                          if  ( blockNum 
==  1 )  flags 
=  0 ;                                                                                                    // just write 1818                          if  ( blockNum 
==  16  *  4  -  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;              // Done. Switch off field. 1820                          if  ( mfCSetBlock ( blockNum
,  buf8
,  NULL
,  0 ,  flags
)) { 1821                                  PrintAndLog ( "Can't set magic card block:  %d " ,  blockNum
); 1826                          if  ( blockNum 
>=  16  *  4 )  break ;   // magic card type - mifare 1K 1830                  if  ( blockNum 
!=  16  *  4  &&  blockNum 
!=  32  *  4  +  8  *  16 ){ 1831                          PrintAndLog ( "File content error. There must be 64 blocks" ); 1834                  PrintAndLog ( "Loaded from file:  %s " ,  filename
); 1840  int  CmdHF14AMfCGetBlk ( const char  * Cmd
) { 1841          uint8_t  memBlock
[ 16 ]; 1842          uint8_t  blockNo 
=  0 ; 1844          memset ( memBlock
,  0x00 ,  sizeof ( memBlock
)); 1846          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) { 1847                  PrintAndLog ( "Usage:  hf mf cgetblk <block number>" ); 1848                  PrintAndLog ( "sample:  hf mf cgetblk 1" ); 1849                  PrintAndLog ( "Get block data from magic Chinese card (only works with such cards) \n " ); 1853          blockNo 
=  param_get8 ( Cmd
,  0 ); 1855          PrintAndLog ( "--block number: %2 d " ,  blockNo
); 1857          res 
=  mfCGetBlock ( blockNo
,  memBlock
,  CSETBLOCK_SINGLE_OPER
); 1859                          PrintAndLog ( "Can't read block. error= %d " ,  res
); 1863          PrintAndLog ( "block data: %s " ,  sprint_hex ( memBlock
,  16 )); 1868  int  CmdHF14AMfCGetSc ( const char  * Cmd
) { 1869          uint8_t  memBlock
[ 16 ] = { 0x00 }; 1870          uint8_t  sectorNo 
=  0 ; 1873          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) { 1874                  PrintAndLog ( "Usage:  hf mf cgetsc <sector number>" ); 1875                  PrintAndLog ( "sample:  hf mf cgetsc 0" ); 1876                  PrintAndLog ( "Get sector data from magic Chinese card (only works with such cards) \n " ); 1880          sectorNo 
=  param_get8 ( Cmd
,  0 ); 1881          if  ( sectorNo 
>  15 ) { 1882                  PrintAndLog ( "Sector number must be in [0..15] as in MIFARE classic." ); 1886          PrintAndLog ( "--sector number: %d  " ,  sectorNo
); 1888          flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
; 1889          for  ( i 
=  0 ;  i 
<  4 ;  i
++) { 1890                  if  ( i 
==  1 )  flags 
=  0 ; 1891                  if  ( i 
==  3 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
; 1893                  res 
=  mfCGetBlock ( sectorNo 
*  4  +  i
,  memBlock
,  flags
); 1895                          PrintAndLog ( "Can't read block.  %d  error= %d " ,  sectorNo 
*  4  +  i
,  res
); 1899                  PrintAndLog ( "block  %3 d data: %s " ,  sectorNo 
*  4  +  i
,  sprint_hex ( memBlock
,  16 )); 1905  int  CmdHF14AMfCSave ( const char  * Cmd
) { 1908          char  filename
[ FILE_PATH_SIZE
] = { 0x00 }; 1909          char  *  fnameptr 
=  filename
; 1910          uint8_t  fillFromEmulator 
=  0 ; 1911          uint8_t  buf
[ 64 ] = { 0x00 }; 1912          int  i
,  j
,  len
,  flags
; 1914          // memset(filename, 0, sizeof(filename)); 1915          // memset(buf, 0, sizeof(buf)); 1917          if  ( param_getchar ( Cmd
,  0 ) ==  'h' ) { 1918                  PrintAndLog ( "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`" ); 1919                  PrintAndLog ( "or into emulator memory (option `e`)" ); 1920                  PrintAndLog ( "Usage:  hf mf esave [file name w/o `.eml`][e]" ); 1921                  PrintAndLog ( " sample: hf mf esave " ); 1922                  PrintAndLog ( "         hf mf esave filename" ); 1923                  PrintAndLog ( "         hf mf esave e  \n " ); 1927          char  ctmp 
=  param_getchar ( Cmd
,  0 ); 1928          if  ( ctmp 
==  'e'  ||  ctmp 
==  'E' )  fillFromEmulator 
=  1 ; 1930          if  ( fillFromEmulator
) { 1931                  // put into emulator 1932                  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
; 1933                  for  ( i 
=  0 ;  i 
<  16  *  4 ;  i
++) { 1934                          if  ( i 
==  1 )  flags 
=  0 ; 1935                          if  ( i 
==  16  *  4  -  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
; 1937                          if  ( mfCGetBlock ( i
,  buf
,  flags
)) { 1938                                  PrintAndLog ( "Cant get block:  %d " ,  i
); 1942                          if  ( mfEmlSetMem ( buf
,  i
,  1 )) { 1943                                  PrintAndLog ( "Cant set emul block:  %d " ,  i
); 1950                  if  ( len 
>  FILE_PATH_SIZE 
-  4 )  len 
=  FILE_PATH_SIZE 
-  4 ; 1954                          if  ( mfCGetBlock ( 0 ,  buf
,  CSETBLOCK_SINGLE_OPER
)) { 1955                                  PrintAndLog ( "Cant get block:  %d " ,  0 ); 1956                                  len 
=  sprintf ( fnameptr
,  "dump" ); 1960                                  for  ( j 
=  0 ;  j 
<  7 ;  j
++,  fnameptr 
+=  2 ) 1961                                          sprintf ( fnameptr
,  " %0 2x" ,  buf
[ j
]);  1964                          memcpy ( filename
,  Cmd
,  len
); 1968                  sprintf ( fnameptr
,  ".eml" );  1971                  f 
=  fopen ( filename
,  "w+" ); 1974                          PrintAndLog ( "File not found or locked." ); 1979                  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
; 1980                  for  ( i 
=  0 ;  i 
<  16  *  4 ;  i
++) { 1981                          if  ( i 
==  1 )  flags 
=  0 ; 1982                          if  ( i 
==  16  *  4  -  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
; 1984                          if  ( mfCGetBlock ( i
,  buf
,  flags
)) { 1985                                  PrintAndLog ( "Cant get block:  %d " ,  i
); 1988                          for  ( j 
=  0 ;  j 
<  16 ;  j
++) 1989                                  fprintf ( f
,  " %0 2x" ,  buf
[ j
]);  1994                  PrintAndLog ( "Saved to file:  %s " ,  filename
); 2001  int  CmdHF14AMfSniff ( const char  * Cmd
){ 2003          bool  wantLogToFile 
=  0 ; 2004          bool  wantDecrypt 
=  0 ; 2005          //bool wantSaveToEml = 0; TODO 2006          bool  wantSaveToEmlFile 
=  0 ; 2016          uint8_t  atqa
[ 2 ] = { 0x00 }; 2019          uint8_t  * buf 
=  NULL
; 2020          uint16_t  bufsize 
=  0 ; 2021          uint8_t  * bufPtr 
=  NULL
; 2023          char  ctmp 
=  param_getchar ( Cmd
,  0 ); 2024          if  (  ctmp 
==  'h'  ||  ctmp 
==  'H'  ) { 2025                  PrintAndLog ( "It continuously gets data from the field and saves it to: log, emulator, emulator file." ); 2026                  PrintAndLog ( "You can specify:" ); 2027                  PrintAndLog ( "    l - save encrypted sequence to logfile `uid.log`" ); 2028                  PrintAndLog ( "    d - decrypt sequence and put it to log file `uid.log`" ); 2029                  PrintAndLog ( " n/a   e - decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory" ); 2030                  PrintAndLog ( "    f - decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`" ); 2031                  PrintAndLog ( "Usage:  hf mf sniff [l][d][e][f]" ); 2032                  PrintAndLog ( "  sample: hf mf sniff l d e" ); 2036          for  ( int  i 
=  0 ;  i 
<  4 ;  i
++) { 2037                  ctmp 
=  param_getchar ( Cmd
,  i
); 2038                  if  ( ctmp 
==  'l'  ||  ctmp 
==  'L' )  wantLogToFile 
=  true ; 2039                  if  ( ctmp 
==  'd'  ||  ctmp 
==  'D' )  wantDecrypt 
=  true ; 2040                  //if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO 2041                  if  ( ctmp 
==  'f'  ||  ctmp 
==  'F' )  wantSaveToEmlFile 
=  true ; 2044          printf ( "------------------------------------------------------------------------- \n " ); 2045          printf ( "Executing command.  \n " ); 2046          printf ( "Press the key on the proxmark3 device to abort both proxmark3 and client. \n " ); 2047          printf ( "Press the key on pc keyboard to abort the client. \n " ); 2048          printf ( "------------------------------------------------------------------------- \n " ); 2050          UsbCommand c 
= { CMD_MIFARE_SNIFFER
, { 0 ,  0 ,  0 }}; 2051          clearCommandBuffer (); 2060                          printf ( " \n aborted via keyboard! \n " ); 2065                  if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 2000 )) { 2066                          res 
=  resp
. arg
[ 0 ] &  0xff ; 2067                          uint16_t  traceLen 
=  resp
. arg
[ 1 ]; 2070                          if  ( res 
==  0 )  return  0 ;                                          // we are done 2072                          if  ( res 
==  1 ) {                                                          // there is (more) data to be transferred 2073                                  if  ( pckNum 
==  0 ) {                                               // first packet, (re)allocate necessary buffer 2074                                          if  ( traceLen 
>  bufsize
) { 2076                                                  if  ( buf 
==  NULL
) {                               // not yet allocated 2077                                                          p 
=  malloc ( traceLen
); 2078                                                  }  else  {                                                 // need more memory 2079                                                          p 
=  realloc ( buf
,  traceLen
); 2082                                                          PrintAndLog ( "Cannot allocate memory for trace" ); 2090                                          memset ( buf
,  0x00 ,  traceLen
); 2092                                  memcpy ( bufPtr
,  resp
. d
. asBytes
,  len
); 2097                          if  ( res 
==  2 ) {                                                          // received all data, start displaying 2098                                  blockLen 
=  bufPtr 
-  buf
; 2101                                  PrintAndLog ( "received trace len:  %d  packages:  %d " ,  blockLen
,  pckNum
); 2102                                  while  ( bufPtr 
-  buf 
<  blockLen
) { 2103                                          bufPtr 
+=  6 ;                                             // skip (void) timing information 2104                                          len 
= *(( uint16_t  *) bufPtr
); 2112                                          if  (( len 
==  14 ) && ( bufPtr
[ 0 ] ==  0xff ) && ( bufPtr
[ 1 ] ==  0xff ) && ( bufPtr
[ 12 ] ==  0xff ) && ( bufPtr
[ 13 ] ==  0xff )) { 2113                                                  memcpy ( uid
,  bufPtr 
+  2 ,  7 ); 2114                                                  memcpy ( atqa
,  bufPtr 
+  2  +  7 ,  2 ); 2115                                                  uid_len 
= ( atqa
[ 0 ] &  0xC0 ) ==  0x40  ?  7  :  4 ; 2117                                                  PrintAndLog ( "tag select uid: %s  atqa:0x %0 2x %0 2x sak:0x %0 2x" ,  2118                                                          sprint_hex ( uid 
+ ( 7  -  uid_len
),  uid_len
), 2122                                                  if  ( wantLogToFile 
||  wantDecrypt
) { 2123                                                          FillFileNameByUID ( logHexFileName
,  uid 
+ ( 7  -  uid_len
),  ".log" ,  uid_len
); 2124                                                          AddLogCurrentDT ( logHexFileName
); 2127                                                          mfTraceInit ( uid
,  atqa
,  sak
,  wantSaveToEmlFile
); 2129                                                  PrintAndLog ( " %s ( %d ): %s " ,  isTag 
?  "TAG" : "RDR" ,  num
,  sprint_hex ( bufPtr
,  len
)); 2131                                                          AddLogHex ( logHexFileName
,  isTag 
?  "TAG: " : "RDR: " ,  bufPtr
,  len
); 2133                                                          mfTraceDecode ( bufPtr
,  len
,  wantSaveToEmlFile
); 2137                                          bufPtr 
+= (( len
- 1 )/ 8 + 1 );         // ignore parity 2148  //needs nt, ar, at, Data to decrypt 2149  int  CmdDecryptTraceCmds ( const char  * Cmd
){ 2152          param_gethex_ex ( Cmd
, 3 , data
,& len
); 2153          return  tryDecryptWord ( param_get32ex ( Cmd
, 0 , 0 , 16 ), param_get32ex ( Cmd
, 1 , 0 , 16 ), param_get32ex ( Cmd
, 2 , 0 , 16 ), data
, len
/ 2 ); 2156  static  command_t CommandTable
[] = 2158    { "help" ,               CmdHelp
,                                 1 ,  "This help" }, 2159    { "dbg" ,                CmdHF14AMfDbg
,                   0 ,  "Set default debug mode" }, 2160    { "rdbl" ,               CmdHF14AMfRdBl
,                  0 ,  "Read MIFARE classic block" }, 2161    { "rdsc" ,               CmdHF14AMfRdSc
,                  0 ,  "Read MIFARE classic sector" }, 2162    { "dump" ,               CmdHF14AMfDump
,                  0 ,  "Dump MIFARE classic tag to binary file" }, 2163    { "restore" ,    CmdHF14AMfRestore
,               0 ,  "Restore MIFARE classic binary file to BLANK tag" }, 2164    { "wrbl" ,               CmdHF14AMfWrBl
,                  0 ,  "Write MIFARE classic block" }, 2165    { "chk" ,                CmdHF14AMfChk
,                   0 ,  "Test block keys" }, 2166    { "mifare" ,     CmdHF14AMifare
,                  0 ,  "Read parity error messages." }, 2167    { "nested" ,     CmdHF14AMfNested
,                0 ,  "Test nested authentication" }, 2168    { "sniff" ,              CmdHF14AMfSniff
,                 0 ,  "Sniff card-reader communication" }, 2169    { "sim" ,                CmdHF14AMf1kSim
,                 0 ,  "Simulate MIFARE card" }, 2170    { "eclr" ,               CmdHF14AMfEClear
,                0 ,  "Clear simulator memory block" }, 2171    { "eget" ,               CmdHF14AMfEGet
,                  0 ,  "Get simulator memory block" }, 2172    { "eset" ,               CmdHF14AMfESet
,                  0 ,  "Set simulator memory block" }, 2173    { "eload" ,              CmdHF14AMfELoad
,                 0 ,  "Load from file emul dump" }, 2174    { "esave" ,              CmdHF14AMfESave
,                 0 ,  "Save to file emul dump" }, 2175    { "ecfill" ,     CmdHF14AMfECFill
,                0 ,  "Fill simulator memory with help of keys from simulator" }, 2176    { "ekeyprn" ,    CmdHF14AMfEKeyPrn
,               0 ,  "Print keys from simulator memory" }, 2177    { "csetuid" ,    CmdHF14AMfCSetUID
,               0 ,  "Set UID for magic Chinese card" }, 2178    { "csetblk" ,    CmdHF14AMfCSetBlk
,               0 ,  "Write block - Magic Chinese card" }, 2179    { "cgetblk" ,    CmdHF14AMfCGetBlk
,               0 ,  "Read block - Magic Chinese card" }, 2180    { "cgetsc" ,     CmdHF14AMfCGetSc
,                0 ,  "Read sector - Magic Chinese card" }, 2181    { "cload" ,              CmdHF14AMfCLoad
,                 0 ,  "Load dump into magic Chinese card" }, 2182    { "csave" ,              CmdHF14AMfCSave
,                 0 ,  "Save dump from magic Chinese card into file or emulator" }, 2183    { "decrypt" ,  CmdDecryptTraceCmds
, 1 ,  "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace" }, 2184    { NULL
,  NULL
,  0 ,  NULL
} 2187  int  CmdHFMF ( const char  * Cmd
) 2190          WaitForResponseTimeout ( CMD_ACK
, NULL
, 100 ); 2192    CmdsParse ( CommandTable
,  Cmd
); 2196  int  CmdHelp ( const char  * Cmd
) 2198    CmdsHelp ( CommandTable
);