]>
 
 
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhfmf.c 
 
 
 
 
 
 
 
a2da01c97fc474c3e1b636e9ad46643d4076e500
   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  //-----------------------------------------------------------------------------  
  18  #include  "proxmark3.h"  
  20  #include  "cmdhfmfhard.h"  
  23  #include  "util_posix.h"  
  26  #include  "mifarehost.h"  
  29  #include  "hardnested/hardnested_bf_core.h"  
  31  #define NESTED_SECTOR_RETRY     10                       // how often we try mfested() until we give up  
  33  static int  CmdHelp ( const char  * Cmd
);  
  35  int  CmdHF14AMifare ( const char  * Cmd
)  
  39          isOK 
=  mfDarkside (& key
);  
  41                  case  - 1  :  PrintAndLog ( "Button pressed. Aborted." );  return  1 ;  
  42                  case  - 2  :  PrintAndLog ( "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests)." );  return  1 ;  
  43                  case  - 3  :  PrintAndLog ( "Card is not vulnerable to Darkside attack (its random number generator is not predictable)." );  return  1 ;  
  44                  case  - 4  :  PrintAndLog ( "Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown" );  
  45                                    PrintAndLog ( "generating polynomial with 16 effective bits only, but shows unexpected behaviour." );  return  1 ;  
  46                  case  - 5  :  PrintAndLog ( "Aborted via keyboard." );   return  1 ;  
  47                  default  :  PrintAndLog ( "Found valid key: %0 12"  PRIx64 
" \n " ,  key
);  
  55  int  CmdHF14AMfWrBl ( const char  * Cmd
)  
  59          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
  60          uint8_t  bldata
[ 16 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
  65                  PrintAndLog ( "Usage:  hf mf wrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>" );  
  66                  PrintAndLog ( "        sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F" );  
  70          blockNo 
=  param_get8 ( Cmd
,  0 );  
  71          cmdp 
=  param_getchar ( Cmd
,  1 );  
  73                  PrintAndLog ( "Key type must be A or B" );  
  76          if  ( cmdp 
!=  'A'  &&  cmdp 
!=  'a' )  keyType 
=  1 ;  
  77          if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  
  78                  PrintAndLog ( "Key must include 12 HEX symbols" );  
  81          if  ( param_gethex ( Cmd
,  3 ,  bldata
,  32 )) {  
  82                  PrintAndLog ( "Block data must include 32 HEX symbols" );  
  85          PrintAndLog ( "--block no: %d , key type: %c , key: %s " ,  blockNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  
  86          PrintAndLog ( "--data:  %s " ,  sprint_hex ( bldata
,  16 ));  
  88    UsbCommand c 
= { CMD_MIFARE_WRITEBL
, { blockNo
,  keyType
,  0 }};  
  89          memcpy ( c
. d
. asBytes
,  key
,  6 );  
  90          memcpy ( c
. d
. asBytes 
+  10 ,  bldata
,  16 );  
  94          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
  95                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
  96                  PrintAndLog ( "isOk: %0 2x" ,  isOK
);  
  98                  PrintAndLog ( "Command execute timeout" );  
 104  int  CmdHF14AMfRdBl ( const char  * Cmd
)  
 108          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
 114                  PrintAndLog ( "Usage:  hf mf rdbl    <block number> <key A/B> <key (12 hex symbols)>" );  
 115                  PrintAndLog ( "        sample: hf mf rdbl 0 A FFFFFFFFFFFF " );  
 119          blockNo 
=  param_get8 ( Cmd
,  0 );  
 120          cmdp 
=  param_getchar ( Cmd
,  1 );  
 122                  PrintAndLog ( "Key type must be A or B" );  
 125          if  ( cmdp 
!=  'A'  &&  cmdp 
!=  'a' )  keyType 
=  1 ;  
 126          if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  
 127                  PrintAndLog ( "Key must include 12 HEX symbols" );  
 130          PrintAndLog ( "--block no: %d , key type: %c , key: %s  " ,  blockNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  
 132    UsbCommand c 
= { CMD_MIFARE_READBL
, { blockNo
,  keyType
,  0 }};  
 133          memcpy ( c
. d
. asBytes
,  key
,  6 );  
 137          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
 138                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
 139                  uint8_t  * data 
=  resp
. d
. asBytes
;  
 142                          PrintAndLog ( "isOk: %0 2x data: %s " ,  isOK
,  sprint_hex ( data
,  16 ));  
 144                          PrintAndLog ( "isOk: %0 2x" ,  isOK
);  
 146                  PrintAndLog ( "Command execute timeout" );  
 152  int  CmdHF14AMfRdSc ( const char  * Cmd
)  
 155          uint8_t  sectorNo 
=  0 ;  
 157          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
 159          uint8_t  * data  
=  NULL
;  
 163                  PrintAndLog ( "Usage:  hf mf rdsc    <sector number> <key A/B> <key (12 hex symbols)>" );  
 164                  PrintAndLog ( "        sample: hf mf rdsc 0 A FFFFFFFFFFFF " );  
 168          sectorNo 
=  param_get8 ( Cmd
,  0 );  
 170                  PrintAndLog ( "Sector number must be less than 40" );  
 173          cmdp 
=  param_getchar ( Cmd
,  1 );  
 174          if  ( cmdp 
!=  'a'  &&  cmdp 
!=  'A'  &&  cmdp 
!=  'b'  &&  cmdp 
!=  'B' ) {  
 175                  PrintAndLog ( "Key type must be A or B" );  
 178          if  ( cmdp 
!=  'A'  &&  cmdp 
!=  'a' )  keyType 
=  1 ;  
 179          if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  
 180                  PrintAndLog ( "Key must include 12 HEX symbols" );  
 183          PrintAndLog ( "--sector no: %d  key type: %c  key: %s  " ,  sectorNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  
 185          UsbCommand c 
= { CMD_MIFARE_READSC
, { sectorNo
,  keyType
,  0 }};  
 186          memcpy ( c
. d
. asBytes
,  key
,  6 );  
 191          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
 192                  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
 193                  data  
=  resp
. d
. asBytes
;  
 195                  PrintAndLog ( "isOk: %0 2x" ,  isOK
);  
 197                          for  ( i 
=  0 ;  i 
< ( sectorNo
< 32 ? 3 : 15 );  i
++) {  
 198                                  PrintAndLog ( "data   :  %s " ,  sprint_hex ( data 
+  i 
*  16 ,  16 ));  
 200                          PrintAndLog ( "trailer:  %s " ,  sprint_hex ( data 
+ ( sectorNo
< 32 ? 3 : 15 ) *  16 ,  16 ));  
 203                  PrintAndLog ( "Command execute timeout" );  
 209  uint8_t  FirstBlockOfSector ( uint8_t  sectorNo
)  
 214                  return  32  *  4  + ( sectorNo 
-  32 ) *  16 ;  
 218  uint8_t  NumBlocksPerSector ( uint8_t  sectorNo
)  
 227  static int  ParamCardSizeSectors ( const char  c
) {  
 230                  case  '0'  :  numBlocks 
=  5 ;  break ;  
 231                  case  '2'  :  numBlocks 
=  32 ;  break ;  
 232                  case  '4'  :  numBlocks 
=  40 ;  break ;  
 233                  default :    numBlocks 
=  16 ;  
 238  static int  ParamCardSizeBlocks ( const char  c
) {  
 239          int  numBlocks 
=  16  *  4 ;  
 241                  case  '0'  :  numBlocks 
=  5  *  4 ;  break ;  
 242                  case  '2'  :  numBlocks 
=  32  *  4 ;  break ;  
 243                  case  '4'  :  numBlocks 
=  32  *  4  +  8  *  16 ;  break ;  
 244                  default :    numBlocks 
=  16  *  4 ;  
 249  int  CmdHF14AMfDump ( const char  * Cmd
)  
 251          uint8_t  sectorNo
,  blockNo
;  
 255          uint8_t  rights
[ 40 ][ 4 ];  
 256          uint8_t  carddata
[ 256 ][ 16 ];  
 257          uint8_t  numSectors 
=  16 ;  
 264          char  cmdp 
=  param_getchar ( Cmd
,  0 );  
 265          numSectors 
=  ParamCardSizeSectors ( cmdp
);  
 267          if  ( strlen ( Cmd
) >  1  ||  cmdp 
==  'h'  ||  cmdp 
==  'H' ) {  
 268                  PrintAndLog ( "Usage:   hf mf dump [card memory]" );  
 269                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
 271                  PrintAndLog ( "Samples: hf mf dump" );  
 272                  PrintAndLog ( "         hf mf dump 4" );  
 276          if  (( fin 
=  fopen ( "dumpkeys.bin" , "rb" )) ==  NULL
) {  
 277                  PrintAndLog ( "Could not find file dumpkeys.bin" );  
 281          // Read keys A from file  
 282          for  ( sectorNo
= 0 ;  sectorNo
< numSectors
;  sectorNo
++) {  
 283                  size_t  bytes_read 
=  fread ( keyA
[ sectorNo
],  1 ,  6 ,  fin
);  
 284                  if  ( bytes_read 
!=  6 ) {  
 285                          PrintAndLog ( "File reading error." );  
 291          // Read keys B from file  
 292          for  ( sectorNo
= 0 ;  sectorNo
< numSectors
;  sectorNo
++) {  
 293                  size_t  bytes_read 
=  fread ( keyB
[ sectorNo
],  1 ,  6 ,  fin
);  
 294                  if  ( bytes_read 
!=  6 ) {  
 295                          PrintAndLog ( "File reading error." );  
 303          PrintAndLog ( "|-----------------------------------------|" );  
 304          PrintAndLog ( "|------ Reading sector access bits...-----|" );  
 305          PrintAndLog ( "|-----------------------------------------|" );  
 307          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  
 308                  for  ( tries 
=  0 ;  tries 
<  3 ;  tries
++) {  
 309                          UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  NumBlocksPerSector ( sectorNo
) -  1 ,  0 ,  0 }};  
 310                          memcpy ( c
. d
. asBytes
,  keyA
[ sectorNo
],  6 );  
 313                          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
 314                                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
 315                                  uint8_t  * data  
=  resp
. d
. asBytes
;  
 317                                          rights
[ sectorNo
][ 0 ] = (( data
[ 7 ] &  0x10 )>> 2 ) | (( data
[ 8 ] &  0x1 )<< 1 ) | (( data
[ 8 ] &  0x10 )>> 4 );  // C1C2C3 for data area 0  
 318                                          rights
[ sectorNo
][ 1 ] = (( data
[ 7 ] &  0x20 )>> 3 ) | (( data
[ 8 ] &  0x2 )<< 0 ) | (( data
[ 8 ] &  0x20 )>> 5 );  // C1C2C3 for data area 1  
 319                                          rights
[ sectorNo
][ 2 ] = (( data
[ 7 ] &  0x40 )>> 4 ) | (( data
[ 8 ] &  0x4 )>> 1 ) | (( data
[ 8 ] &  0x40 )>> 6 );  // C1C2C3 for data area 2  
 320                                          rights
[ sectorNo
][ 3 ] = (( data
[ 7 ] &  0x80 )>> 5 ) | (( data
[ 8 ] &  0x8 )>> 2 ) | (( data
[ 8 ] &  0x80 )>> 7 );  // C1C2C3 for sector trailer  
 322                                  }  else if  ( tries 
==  2 ) {  // on last try set defaults  
 323                                          PrintAndLog ( "Could not get access rights for sector  %2 d. Trying with defaults..." ,  sectorNo
);  
 324                                          rights
[ sectorNo
][ 0 ] =  rights
[ sectorNo
][ 1 ] =  rights
[ sectorNo
][ 2 ] =  0x00 ;  
 325                                          rights
[ sectorNo
][ 3 ] =  0x01 ;  
 328                                  PrintAndLog ( "Command execute timeout when trying to read access rights for sector  %2 d. Trying with defaults..." ,  sectorNo
);  
 329                                  rights
[ sectorNo
][ 0 ] =  rights
[ sectorNo
][ 1 ] =  rights
[ sectorNo
][ 2 ] =  0x00 ;  
 330                                  rights
[ sectorNo
][ 3 ] =  0x01 ;  
 335          PrintAndLog ( "|-----------------------------------------|" );  
 336          PrintAndLog ( "|----- Dumping all blocks to file... -----|" );  
 337          PrintAndLog ( "|-----------------------------------------|" );  
 340          for  ( sectorNo 
=  0 ;  isOK 
&&  sectorNo 
<  numSectors
;  sectorNo
++) {  
 341                  for  ( blockNo 
=  0 ;  isOK 
&&  blockNo 
<  NumBlocksPerSector ( sectorNo
);  blockNo
++) {  
 342                          bool  received 
=  false ;  
 343                          for  ( tries 
=  0 ;  tries 
<  3 ;  tries
++) {  
 344                                  if  ( blockNo 
==  NumBlocksPerSector ( sectorNo
) -  1 ) {               // sector trailer. At least the Access Conditions can always be read with key A.  
 345                                          UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  0 ,  0 }};  
 346                                          memcpy ( c
. d
. asBytes
,  keyA
[ sectorNo
],  6 );  
 348                                          received 
=  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 );  
 349                                  }  else  {                                                                                                 // data block. Check if it can be read with key A or key B  
 350                                          uint8_t  data_area 
=  sectorNo
< 32 ? blockNo
: blockNo
/ 5 ;  
 351                                          if  (( rights
[ sectorNo
][ data_area
] ==  0x03 ) || ( rights
[ sectorNo
][ data_area
] ==  0x05 )) {    // only key B would work  
 352                                                  UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  1 ,  0 }};  
 353                                                  memcpy ( c
. d
. asBytes
,  keyB
[ sectorNo
],  6 );  
 355                                                  received 
=  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 );  
 356                                          }  else if  ( rights
[ sectorNo
][ data_area
] ==  0x07 ) {                                                                                // no key would work  
 358                                                  PrintAndLog ( "Access rights do not allow reading of sector  %2 d block  %3 d" ,  sectorNo
,  blockNo
);  
 360                                          }  else  {                                                                                                                                                                 // key A would work  
 361                                                  UsbCommand c 
= { CMD_MIFARE_READBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  0 ,  0 }};  
 362                                                  memcpy ( c
. d
. asBytes
,  keyA
[ sectorNo
],  6 );  
 364                                                  received 
=  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 );  
 368                                          isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
 374                                  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
 375                                  uint8_t  * data  
=  resp
. d
. asBytes
;  
 376                                  if  ( blockNo 
==  NumBlocksPerSector ( sectorNo
) -  1 ) {               // sector trailer. Fill in the keys.  
 377                                          data
[ 0 ]  = ( keyA
[ sectorNo
][ 0 ]);  
 378                                          data
[ 1 ]  = ( keyA
[ sectorNo
][ 1 ]);  
 379                                          data
[ 2 ]  = ( keyA
[ sectorNo
][ 2 ]);  
 380                                          data
[ 3 ]  = ( keyA
[ sectorNo
][ 3 ]);  
 381                                          data
[ 4 ]  = ( keyA
[ sectorNo
][ 4 ]);  
 382                                          data
[ 5 ]  = ( keyA
[ sectorNo
][ 5 ]);  
 383                                          data
[ 10 ] = ( keyB
[ sectorNo
][ 0 ]);  
 384                                          data
[ 11 ] = ( keyB
[ sectorNo
][ 1 ]);  
 385                                          data
[ 12 ] = ( keyB
[ sectorNo
][ 2 ]);  
 386                                          data
[ 13 ] = ( keyB
[ sectorNo
][ 3 ]);  
 387                                          data
[ 14 ] = ( keyB
[ sectorNo
][ 4 ]);  
 388                                          data
[ 15 ] = ( keyB
[ sectorNo
][ 5 ]);  
 391                                          memcpy ( carddata
[ FirstBlockOfSector ( sectorNo
) +  blockNo
],  data
,  16 );  
 392                      PrintAndLog ( "Successfully read block  %2 d of sector  %2 d." ,  blockNo
,  sectorNo
);  
 394                                          PrintAndLog ( "Could not read block  %2 d of sector  %2 d" ,  blockNo
,  sectorNo
);  
 400                                  PrintAndLog ( "Command execute timeout when trying to read block  %2 d of sector  %2 d." ,  blockNo
,  sectorNo
);  
 407                  if  (( fout 
=  fopen ( "dumpdata.bin" , "wb" )) ==  NULL
) {  
 408                          PrintAndLog ( "Could not create file name dumpdata.bin" );  
 411                  uint16_t  numblocks 
=  FirstBlockOfSector ( numSectors 
-  1 ) +  NumBlocksPerSector ( numSectors 
-  1 );  
 412                  fwrite ( carddata
,  1 ,  16 * numblocks
,  fout
);  
 414                  PrintAndLog ( "Dumped  %d  blocks ( %d  bytes) to file dumpdata.bin" ,  numblocks
,  16 * numblocks
);  
 420  int  CmdHF14AMfRestore ( const char  * Cmd
)  
 422          uint8_t  sectorNo
, blockNo
;  
 424          uint8_t  key
[ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF };  
 425          uint8_t  bldata
[ 16 ] = { 0x00 };  
 433          char  cmdp 
=  param_getchar ( Cmd
,  0 );  
 435                  case  '0'  :  numSectors 
=  5 ;  break ;  
 437                  case  '\0' :  numSectors 
=  16 ;  break ;  
 438                  case  '2'  :  numSectors 
=  32 ;  break ;  
 439                  case  '4'  :  numSectors 
=  40 ;  break ;  
 440                  default :    numSectors 
=  16 ;  
 443          if  ( strlen ( Cmd
) >  1  ||  cmdp 
==  'h'  ||  cmdp 
==  'H' ) {  
 444                  PrintAndLog ( "Usage:   hf mf restore [card memory]" );  
 445                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
 447                  PrintAndLog ( "Samples: hf mf restore" );  
 448                  PrintAndLog ( "         hf mf restore 4" );  
 452          if  (( fkeys 
=  fopen ( "dumpkeys.bin" , "rb" )) ==  NULL
) {  
 453                  PrintAndLog ( "Could not find file dumpkeys.bin" );  
 457          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  
 458                  size_t  bytes_read 
=  fread ( keyA
[ sectorNo
],  1 ,  6 ,  fkeys
);  
 459                  if  ( bytes_read 
!=  6 ) {  
 460                          PrintAndLog ( "File reading error (dumpkeys.bin)." );  
 466          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  
 467                  size_t  bytes_read 
=  fread ( keyB
[ sectorNo
],  1 ,  6 ,  fkeys
);  
 468                  if  ( bytes_read 
!=  6 ) {  
 469                          PrintAndLog ( "File reading error (dumpkeys.bin)." );  
 477          if  (( fdump 
=  fopen ( "dumpdata.bin" , "rb" )) ==  NULL
) {  
 478                  PrintAndLog ( "Could not find file dumpdata.bin" );  
 481          PrintAndLog ( "Restoring dumpdata.bin to card" );  
 483          for  ( sectorNo 
=  0 ;  sectorNo 
<  numSectors
;  sectorNo
++) {  
 484                  for ( blockNo 
=  0 ;  blockNo 
<  NumBlocksPerSector ( sectorNo
);  blockNo
++) {  
 485                          UsbCommand c 
= { CMD_MIFARE_WRITEBL
, { FirstBlockOfSector ( sectorNo
) +  blockNo
,  keyType
,  0 }};  
 486                          memcpy ( c
. d
. asBytes
,  key
,  6 );  
 488                          size_t  bytes_read 
=  fread ( bldata
,  1 ,  16 ,  fdump
);  
 489                          if  ( bytes_read 
!=  16 ) {  
 490                                  PrintAndLog ( "File reading error (dumpdata.bin)." );  
 495                          if  ( blockNo 
==  NumBlocksPerSector ( sectorNo
) -  1 ) {       // sector trailer  
 496                                  bldata
[ 0 ]  = ( keyA
[ sectorNo
][ 0 ]);  
 497                                  bldata
[ 1 ]  = ( keyA
[ sectorNo
][ 1 ]);  
 498                                  bldata
[ 2 ]  = ( keyA
[ sectorNo
][ 2 ]);  
 499                                  bldata
[ 3 ]  = ( keyA
[ sectorNo
][ 3 ]);  
 500                                  bldata
[ 4 ]  = ( keyA
[ sectorNo
][ 4 ]);  
 501                                  bldata
[ 5 ]  = ( keyA
[ sectorNo
][ 5 ]);  
 502                                  bldata
[ 10 ] = ( keyB
[ sectorNo
][ 0 ]);  
 503                                  bldata
[ 11 ] = ( keyB
[ sectorNo
][ 1 ]);  
 504                                  bldata
[ 12 ] = ( keyB
[ sectorNo
][ 2 ]);  
 505                                  bldata
[ 13 ] = ( keyB
[ sectorNo
][ 3 ]);  
 506                                  bldata
[ 14 ] = ( keyB
[ sectorNo
][ 4 ]);  
 507                                  bldata
[ 15 ] = ( keyB
[ sectorNo
][ 5 ]);  
 510                          PrintAndLog ( "Writing to block  %3 d:  %s " ,  FirstBlockOfSector ( sectorNo
) +  blockNo
,  sprint_hex ( bldata
,  16 ));  
 512                          memcpy ( c
. d
. asBytes 
+  10 ,  bldata
,  16 );  
 516                          if  ( WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
 517                                  uint8_t  isOK  
=  resp
. arg
[ 0 ] &  0xff ;  
 518                                  PrintAndLog ( "isOk: %0 2x" ,  isOK
);  
 520                                  PrintAndLog ( "Command execute timeout" );  
 529  //----------------------------------------------  
 531  //----------------------------------------------  
 533  static void  parseParamTDS ( const char  * Cmd
,  const uint8_t  indx
,  bool  * paramT
,  bool  * paramD
,  uint8_t  * timeout
) {  
 535          int  len 
=  param_getlength ( Cmd
,  indx
);  
 536          if  ( len 
>  0  &&  len 
<  4 ){  
 537                  param_getstr ( Cmd
,  indx
,  ctmp3
,  sizeof ( ctmp3
));  
 539                  * paramT 
|= ( ctmp3
[ 0 ] ==  't'  ||  ctmp3
[ 0 ] ==  'T' );  
 540                  * paramD 
|= ( ctmp3
[ 0 ] ==  'd'  ||  ctmp3
[ 0 ] ==  'D' );  
 541                  bool  paramS1 
= * paramT 
|| * paramD
;  
 543                  // slow and very slow  
 544                  if  ( ctmp3
[ 0 ] ==  's'  ||  ctmp3
[ 0 ] ==  'S'  ||  ctmp3
[ 1 ] ==  's'  ||  ctmp3
[ 1 ] ==  'S' ) {  
 545                          * timeout 
=  11 ;  // slow  
 547                          if  (! paramS1 
&& ( ctmp3
[ 1 ] ==  's'  ||  ctmp3
[ 1 ] ==  'S' )) {  
 548                                  * timeout 
=  53 ;  // very slow  
 550                          if  ( paramS1 
&& ( ctmp3
[ 2 ] ==  's'  ||  ctmp3
[ 2 ] ==  'S' )) {  
 551                                  * timeout 
=  53 ;  // very slow  
 557  int  CmdHF14AMfNested ( const char  * Cmd
)  
 559          int  i
,  j
,  res
,  iterations
;  
 560          sector_t 
* e_sector 
=  NULL
;  
 563          uint8_t  trgBlockNo 
=  0 ;  
 564          uint8_t  trgKeyType 
=  0 ;  
 565          uint8_t  SectorsCnt 
=  0 ;  
 566          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
 567          uint8_t  keyBlock
[ MifareDefaultKeysSize 
*  6 ];  
 569          // timeout in units. (ms * 106)/10 or us*0.0106  
 570          uint8_t  btimeout14a 
=  MF_CHKKEYS_DEFTIMEOUT
;  // fast by default  
 572          bool  autosearchKey 
=  false ;  
 574          bool  transferToEml 
=  false ;  
 575          bool  createDumpFile 
=  false ;  
 577          uint8_t  standart
[ 6 ] = { 0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF };  
 578          uint8_t  tempkey
[ 6 ] = { 0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF ,  0xFF };  
 583                  PrintAndLog ( "Usage:" );  
 584                  PrintAndLog ( " all sectors:  hf mf nested  <card memory> <block number> <key A/B> <key (12 hex symbols)> [t|d|s|ss]" );  
 585                  PrintAndLog ( " all sectors autosearch key:  hf mf nested  <card memory> * [t|d|s|ss]" );  
 586                  PrintAndLog ( " one sector:   hf mf nested  o <block number> <key A/B> <key (12 hex symbols)>" );  
 587                  PrintAndLog ( "               <target block number> <target key A/B> [t]" );  
 589                  PrintAndLog ( "card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K" );  
 590                  PrintAndLog ( "t - transfer keys to emulator memory" );  
 591                  PrintAndLog ( "d - write keys to binary file dumpkeys.bin" );  
 592                  PrintAndLog ( "s - Slow (1ms) check keys (required by some non standard cards)" );  
 593                  PrintAndLog ( "ss - Very slow (5ms) check keys" );  
 595                  PrintAndLog ( "      sample1: hf mf nested 1 0 A FFFFFFFFFFFF " );  
 596                  PrintAndLog ( "      sample2: hf mf nested 1 0 A FFFFFFFFFFFF t " );  
 597                  PrintAndLog ( "      sample3: hf mf nested 1 0 A FFFFFFFFFFFF d " );  
 598                  PrintAndLog ( "      sample4: hf mf nested o 0 A FFFFFFFFFFFF 4 A" );  
 599                  PrintAndLog ( "      sample5: hf mf nested 1 * t" );  
 600                  PrintAndLog ( "      sample6: hf mf nested 1 * ss" );  
 605          cmdp 
=  param_getchar ( Cmd
,  0 );  
 606          if  ( cmdp 
==  'o'  ||  cmdp 
==  'O' ) {  
 610                  SectorsCnt 
=  ParamCardSizeSectors ( cmdp
);  
 613          // <block number>. number or autosearch key (*)  
 614          if  ( param_getchar ( Cmd
,  1 ) ==  '*' ) {  
 615                  autosearchKey 
=  true ;  
 617                  parseParamTDS ( Cmd
,  2 , & transferToEml
, & createDumpFile
, & btimeout14a
);  
 619                  PrintAndLog ( "--nested. sectors: %2 d, block no:*, eml: %c , dmp= %c  checktimeout= %d  us" ,   
 620                          SectorsCnt
,  transferToEml
? 'y' : 'n' ,  createDumpFile
? 'y' : 'n' , (( int ) btimeout14a 
*  10000 ) /  106 );  
 622                  blockNo 
=  param_get8 ( Cmd
,  1 );  
 624                  ctmp 
=  param_getchar ( Cmd
,  2 );  
 625                  if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  
 626                          PrintAndLog ( "Key type must be A or B" );  
 630                  if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' )  
 633                  if  ( param_gethex ( Cmd
,  3 ,  key
,  12 )) {  
 634                          PrintAndLog ( "Key must include 12 HEX symbols" );  
 638                  // check if we can authenticate to sector  
 639                  res 
=  mfCheckKeys ( blockNo
,  keyType
,  true ,  1 ,  key
, & key64
);  
 641                          PrintAndLog ( "Can't authenticate to block: %3 d key type: %c  key: %s " ,  blockNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  
 647                          trgBlockNo 
=  param_get8 ( Cmd
,  4 );  
 649                          ctmp 
=  param_getchar ( Cmd
,  5 );  
 650                          if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  
 651                                  PrintAndLog ( "Target key type must be A or B" );  
 654                          if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' )  
 657                          parseParamTDS ( Cmd
,  6 , & transferToEml
, & createDumpFile
, & btimeout14a
);  
 659                          parseParamTDS ( Cmd
,  4 , & transferToEml
, & createDumpFile
, & btimeout14a
);  
 662                  PrintAndLog ( "--nested. sectors: %2 d, block no: %3 d, key type: %c , eml: %c , dmp= %c  checktimeout= %d  us" ,   
 663                          SectorsCnt
,  blockNo
,  keyType
? 'B' : 'A' ,  transferToEml
? 'y' : 'n' ,  createDumpFile
? 'y' : 'n' , (( int ) btimeout14a 
*  10000 ) /  106 );  
 667          if  ( cmdp 
==  'o' ) {  // ------------------------------------  one sector working  
 668                  PrintAndLog ( "--target block no: %3 d, target key type: %c  " ,  trgBlockNo
,  trgKeyType
? 'B' : 'A' );  
 669                  int16_t  isOK 
=  mfnested ( blockNo
,  keyType
,  key
,  trgBlockNo
,  trgKeyType
,  keyBlock
,  true );  
 672                                  case  - 1  :  PrintAndLog ( "Error: No response from Proxmark. \n " );  break ;  
 673                                  case  - 2  :  PrintAndLog ( "Button pressed. Aborted. \n " );  break ;  
 674                                  case  - 3  :  PrintAndLog ( "Tag isn't vulnerable to Nested Attack (random numbers are not predictable). \n " );  break ;  
 675                                  default  :  PrintAndLog ( "Unknown Error. \n " );  
 679                  key64 
=  bytes_to_num ( keyBlock
,  6 );  
 681                          PrintAndLog ( "Found valid key: %0 12"  PRIx64
,  key64
);  
 683                          // transfer key to the emulator  
 685                                  uint8_t  sectortrailer
;  
 686                                  if  ( trgBlockNo 
<  32 * 4 ) {         // 4 block sector  
 687                                          sectortrailer 
=  trgBlockNo 
|  0x03 ;  
 688                                  }  else  {                                         // 16 block sector  
 689                                          sectortrailer 
=  trgBlockNo 
|  0x0f ;  
 691                                  mfEmlGetMem ( keyBlock
,  sectortrailer
,  1 );  
 694                                          num_to_bytes ( key64
,  6 ,  keyBlock
);  
 696                                          num_to_bytes ( key64
,  6 , & keyBlock
[ 10 ]);  
 697                                  mfEmlSetMem ( keyBlock
,  sectortrailer
,  1 );  
 698                                  PrintAndLog ( "Key transferred to emulator memory." );  
 701                          PrintAndLog ( "No valid key found" );  
 704          else  {  // ------------------------------------  multiple sectors working  
 706                  msclock1 
=  msclock ();  
 708                  e_sector 
=  calloc ( SectorsCnt
,  sizeof ( sector_t
));  
 709                  if  ( e_sector 
==  NULL
)  return  1 ;  
 711                  //test current key and additional standard keys first  
 712                  for  ( int  defaultKeyCounter 
=  0 ;  defaultKeyCounter 
<  MifareDefaultKeysSize
;  defaultKeyCounter
++){  
 713                          num_to_bytes ( MifareDefaultKeys
[ defaultKeyCounter
],  6 , ( uint8_t *)( keyBlock 
+  defaultKeyCounter 
*  6 ));  
 716                  PrintAndLog ( "Testing known keys. Sector count= %d " ,  SectorsCnt
);  
 717                  mfCheckKeysSec ( SectorsCnt
,  2 ,  btimeout14a
,  true ,  MifareDefaultKeysSize
,  keyBlock
,  e_sector
);  
 719                  // get known key from array  
 720                  bool  keyFound 
=  false ;  
 722                          for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  
 723                                  for  ( j 
=  0 ;  j 
<  2 ;  j
++) {  
 724                                          if  ( e_sector
[ i
]. foundKey
[ j
]) {  
 728                                                  num_to_bytes ( e_sector
[ i
]. Key
[ j
],  6 ,  key
);  
 737                          // Can't found a key....  
 739                                  PrintAndLog ( "Can't found any of the known keys." );  
 742                          PrintAndLog ( "--auto key. block no: %3 d, key type: %c  key: %s " ,  blockNo
,  keyType
? 'B' : 'A' ,  sprint_hex ( key
,  6 ));  
 747                  PrintAndLog ( "nested..." );  
 748                  bool  calibrate 
=  true ;  
 749                  for  ( i 
=  0 ;  i 
<  NESTED_SECTOR_RETRY
;  i
++) {  
 750                          for  ( uint8_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  
 751                                  for  ( trgKeyType 
=  0 ;  trgKeyType 
<  2 ;  trgKeyType
++) {  
 752                                          if  ( e_sector
[ sectorNo
]. foundKey
[ trgKeyType
])  continue ;  
 753                                          PrintAndLog ( "-----------------------------------------------" );  
 754                                          int16_t  isOK 
=  mfnested ( blockNo
,  keyType
,  key
,  FirstBlockOfSector ( sectorNo
),  trgKeyType
,  keyBlock
,  calibrate
);  
 757                                                          case  - 1  :  PrintAndLog ( "Error: No response from Proxmark. \n " );  break ;  
 758                                                          case  - 2  :  PrintAndLog ( "Button pressed. Aborted. \n " );  break ;  
 759                                                          case  - 3  :  PrintAndLog ( "Tag isn't vulnerable to Nested Attack (random numbers are not predictable). \n " );  break ;  
 760                                                          default  :  PrintAndLog ( "Unknown Error. \n " );  
 770                                          key64 
=  bytes_to_num ( keyBlock
,  6 );  
 772                                                  PrintAndLog ( "Found valid key: %0 12"  PRIx64
,  key64
);  
 773                                                  e_sector
[ sectorNo
]. foundKey
[ trgKeyType
] =  1 ;  
 774                                                  e_sector
[ sectorNo
]. Key
[ trgKeyType
] =  key64
;  
 776                                                  // try to check this key as a key to the other sectors  
 777                                                  mfCheckKeysSec ( SectorsCnt
,  2 ,  btimeout14a
,  true ,  1 ,  keyBlock
,  e_sector
);  
 783                  // print nested statistic  
 784                  PrintAndLog ( " \n\n ----------------------------------------------- \n Nested statistic: \n Iterations count:  %d " ,  iterations
);  
 785                  PrintAndLog ( "Time in nested:  %1 .3f ( %1 .3f sec per key)" , (( float )( msclock () -  msclock1
))/ 1000.0 , (( float )( msclock () -  msclock1
))/ iterations
/ 1000.0 );  
 788                  PrintAndLog ( "|---|----------------|---|----------------|---|" );  
 789                  PrintAndLog ( "|sec|key A           |res|key B           |res|" );  
 790                  PrintAndLog ( "|---|----------------|---|----------------|---|" );  
 791                  for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  
 792                          PrintAndLog ( "| %0 3d|   %0 12"  PRIx64 
"  |  %d  |   %0 12"  PRIx64 
"  |  %d  |" ,  i
,  
 793                                  e_sector
[ i
]. Key
[ 0 ],  e_sector
[ i
]. foundKey
[ 0 ],  e_sector
[ i
]. Key
[ 1 ],  e_sector
[ i
]. foundKey
[ 1 ]);  
 795                  PrintAndLog ( "|---|----------------|---|----------------|---|" );  
 797                  // transfer keys to the emulator memory  
 799                          for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  
 800                                  mfEmlGetMem ( keyBlock
,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ,  1 );  
 801                                  if  ( e_sector
[ i
]. foundKey
[ 0 ])  
 802                                          num_to_bytes ( e_sector
[ i
]. Key
[ 0 ],  6 ,  keyBlock
);  
 803                                  if  ( e_sector
[ i
]. foundKey
[ 1 ])  
 804                                          num_to_bytes ( e_sector
[ i
]. Key
[ 1 ],  6 , & keyBlock
[ 10 ]);  
 805                                  mfEmlSetMem ( keyBlock
,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ,  1 );  
 807                          PrintAndLog ( "Keys transferred to emulator memory." );  
 811                  if  ( createDumpFile
) {  
 812                          if  (( fkeys 
=  fopen ( "dumpkeys.bin" , "wb" )) ==  NULL
) {  
 813                                  PrintAndLog ( "Could not create file dumpkeys.bin" );  
 817                          PrintAndLog ( "Printing keys to binary file dumpkeys.bin..." );  
 818                          for ( i
= 0 ;  i
< SectorsCnt
;  i
++) {  
 819                                  if  ( e_sector
[ i
]. foundKey
[ 0 ]){  
 820                                          num_to_bytes ( e_sector
[ i
]. Key
[ 0 ],  6 ,  tempkey
);  
 821                                          fwrite  (  tempkey
,  1 ,  6 ,  fkeys 
);  
 824                                          fwrite  ( & standart
,  1 ,  6 ,  fkeys 
);  
 827                          for ( i
= 0 ;  i
< SectorsCnt
;  i
++) {  
 828                                  if  ( e_sector
[ i
]. foundKey
[ 1 ]){  
 829                                          num_to_bytes ( e_sector
[ i
]. Key
[ 1 ],  6 ,  tempkey
);  
 830                                          fwrite  (  tempkey
,  1 ,  6 ,  fkeys 
);  
 833                                          fwrite  ( & standart
,  1 ,  6 ,  fkeys 
);  
 845  int  CmdHF14AMfNestedHard ( const char  * Cmd
)  
 849          uint8_t  trgBlockNo 
=  0 ;  
 850          uint8_t  trgKeyType 
=  0 ;  
 851          uint8_t  key
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
 852          uint8_t  trgkey
[ 6 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
 855          ctmp 
=  param_getchar ( Cmd
,  0 );  
 857          if  ( ctmp 
!=  'R'  &&  ctmp 
!=  'r'  &&  ctmp 
!=  'T'  &&  ctmp 
!=  't'  &&  strlen ( Cmd
) <  20 ) {  
 858                  PrintAndLog ( "Usage:" );  
 859                  PrintAndLog ( "      hf mf hardnested <block number> <key A|B> <key (12 hex symbols)>" );  
 860                  PrintAndLog ( "                       <target block number> <target key A|B> [known target key (12 hex symbols)] [w] [s]" );  
 861                  PrintAndLog ( "  or  hf mf hardnested r [known target key]" );  
 863                  PrintAndLog ( "Options: " );  
 864                  PrintAndLog ( "      w: Acquire nonces and write them to binary file nonces.bin" );  
 865                  PrintAndLog ( "      s: Slower acquisition (required by some non standard cards)" );  
 866                  PrintAndLog ( "      r: Read nonces.bin and start attack" );  
 867                  PrintAndLog ( "      iX: set type of SIMD instructions. Without this flag programs autodetect it." );  
 868                  PrintAndLog ( "        i5: AVX512" );  
 869                  PrintAndLog ( "        i2: AVX2" );  
 870                  PrintAndLog ( "        ia: AVX" );  
 871                  PrintAndLog ( "        is: SSE2" );  
 872                  PrintAndLog ( "        im: MMX" );  
 873                  PrintAndLog ( "        in: none (use CPU regular instruction set)" );  
 875                  PrintAndLog ( "      sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A" );  
 876                  PrintAndLog ( "      sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w" );  
 877                  PrintAndLog ( "      sample3: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w s" );  
 878                  PrintAndLog ( "      sample4: hf mf hardnested r" );  
 880                  PrintAndLog ( "Add the known target key to check if it is present in the remaining key space:" );  
 881                  PrintAndLog ( "      sample5: hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF" );  
 885          bool  know_target_key 
=  false ;  
 886          bool  nonce_file_read 
=  false ;  
 887          bool  nonce_file_write 
=  false ;  
 893          if  ( ctmp 
==  'R'  ||  ctmp 
==  'r' ) {  
 894                  nonce_file_read 
=  true ;  
 896                  if  (! param_gethex ( Cmd
,  1 ,  trgkey
,  12 )) {  
 897                          know_target_key 
=  true ;  
 900          }  else if  ( ctmp 
==  'T'  ||  ctmp 
==  't' ) {  
 901                  tests 
=  param_get32ex ( Cmd
,  1 ,  100 ,  10 );  
 903                  if  (! param_gethex ( Cmd
,  2 ,  trgkey
,  12 )) {  
 904                          know_target_key 
=  true ;  
 908                  blockNo 
=  param_get8 ( Cmd
,  0 );  
 909                  ctmp 
=  param_getchar ( Cmd
,  1 );  
 910                  if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  
 911                          PrintAndLog ( "Key type must be A or B" );  
 914                  if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' ) {  
 918                  if  ( param_gethex ( Cmd
,  2 ,  key
,  12 )) {  
 919                          PrintAndLog ( "Key must include 12 HEX symbols" );  
 923                  trgBlockNo 
=  param_get8 ( Cmd
,  3 );  
 924                  ctmp 
=  param_getchar ( Cmd
,  4 );  
 925                  if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  
 926                          PrintAndLog ( "Target key type must be A or B" );  
 929                  if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' ) {  
 935                  if  (! param_gethex ( Cmd
,  5 ,  trgkey
,  12 )) {  
 936                          know_target_key 
=  true ;  
 941                  while  (( ctmp 
=  param_getchar ( Cmd
,  i
))) {  
 942                          if  ( ctmp 
==  's'  ||  ctmp 
==  'S' ) {  
 944                          }  else if  ( ctmp 
==  'w'  ||  ctmp 
==  'W' ) {  
 945                                  nonce_file_write 
=  true ;  
 946                          }  else if  ( param_getlength ( Cmd
,  i
) ==  2  &&  ctmp 
==  'i' ) {  
 949                                  PrintAndLog ( "Possible options are w , s and/or iX" );  
 956          SetSIMDInstr ( SIMD_AUTO
);  
 958                  while  (( ctmp 
=  param_getchar ( Cmd
,  iindx
))) {  
 959                          if  ( param_getlength ( Cmd
,  iindx
) ==  2  &&  ctmp 
==  'i' ) {  
 960                                  switch ( param_getchar_indx ( Cmd
,  1 ,  iindx
)) {  
 962                                                  SetSIMDInstr ( SIMD_AVX512
);  
 965                                                  SetSIMDInstr ( SIMD_AVX2
);  
 968                                                  SetSIMDInstr ( SIMD_AVX
);  
 971                                                  SetSIMDInstr ( SIMD_SSE2
);  
 974                                                  SetSIMDInstr ( SIMD_MMX
);  
 977                                                  SetSIMDInstr ( SIMD_NONE
);  
 980                                                  PrintAndLog ( "Unknown SIMD type.  %c " ,  param_getchar_indx ( Cmd
,  1 ,  iindx
));  
 988          PrintAndLog ( "--target block no: %3 d, target key type: %c , known target key: 0x %0 2x %0 2x %0 2x %0 2x %0 2x %0 2x %s , file action:  %s , Slow:  %s , Tests:  %d  " ,  
 991                          trgkey
[ 0 ],  trgkey
[ 1 ],  trgkey
[ 2 ],  trgkey
[ 3 ],  trgkey
[ 4 ],  trgkey
[ 5 ],  
 992                          know_target_key
? "" : " (not set)" ,  
 993                          nonce_file_write
? "write" : nonce_file_read
? "read" : "none" ,  
 997          int16_t  isOK 
=  mfnestedhard ( blockNo
,  keyType
,  key
,  trgBlockNo
,  trgKeyType
,  know_target_key
? trgkey
: NULL
,  nonce_file_read
,  nonce_file_write
,  slow
,  tests
);  
1001                          case  1  :  PrintAndLog ( "Error: No response from Proxmark. \n " );  break ;  
1002                          case  2  :  PrintAndLog ( "Button pressed. Aborted. \n " );  break ;  
1012  int  CmdHF14AMfChk ( const char  * Cmd
)  
1014          if  ( strlen ( Cmd
)< 3 ) {  
1015                  PrintAndLog ( "Usage:  hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d|s|ss] [<key (12 hex symbols)>] [<dic (*.dic)>]" );  
1016                  PrintAndLog ( "          * - all sectors" );  
1017                  PrintAndLog ( "card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K" );  
1018                  PrintAndLog ( "d - write keys to binary file \n " );  
1019                  PrintAndLog ( "t - write keys to emulator memory" );  
1020                  PrintAndLog ( "s - slow execute. timeout 1ms" );  
1021                  PrintAndLog ( "ss- very slow execute. timeout 5ms" );  
1022                  PrintAndLog ( "      sample: hf mf chk 0 A 1234567890ab keys.dic" );  
1023                  PrintAndLog ( "              hf mf chk *1 ? t" );  
1024                  PrintAndLog ( "              hf mf chk *1 ? d" );  
1025                  PrintAndLog ( "              hf mf chk *1 ? s" );  
1026                  PrintAndLog ( "              hf mf chk *1 ? dss" );  
1031          char  filename
[ FILE_PATH_SIZE
]={ 0 };  
1033          uint8_t  * keyBlock 
=  NULL
, * p
;  
1034          uint16_t  stKeyBlock 
=  20 ;  
1040          char  ctmp3
[ 3 ]   = { 0x00 };  
1041          uint8_t  blockNo 
=  0 ;  
1042          uint8_t  SectorsCnt 
=  0 ;  
1043          uint8_t  keyType 
=  0 ;  
1045          uint32_t  timeout14a 
=  0 ;  // timeout in us  
1046          bool  param3InUse 
=  false ;  
1048          int  transferToEml 
=  0 ;  
1049          int  createDumpFile 
=  0 ;  
1051          sector_t 
* e_sector 
=  NULL
;  
1053          keyBlock 
=  calloc ( stKeyBlock
,  6 );  
1054          if  ( keyBlock 
==  NULL
)  return  1 ;  
1056          int  defaultKeysSize 
=  MifareDefaultKeysSize
;  
1057          for  ( int  defaultKeyCounter 
=  0 ;  defaultKeyCounter 
<  defaultKeysSize
;  defaultKeyCounter
++){  
1058                  num_to_bytes ( MifareDefaultKeys
[ defaultKeyCounter
],  6 , ( uint8_t *)( keyBlock 
+  defaultKeyCounter 
*  6 ));  
1061          if  ( param_getchar ( Cmd
,  0 )== '*' ) {  
1062                  SectorsCnt 
=  ParamCardSizeSectors ( param_getchar ( Cmd 
+  1 ,  0 ));  
1065                  blockNo 
=  param_get8 ( Cmd
,  0 );  
1067          ctmp 
=  param_getchar ( Cmd
,  1 );  
1068          clen 
=  param_getlength ( Cmd
,  1 );  
1081                          PrintAndLog ( "Key type must be A , B or ?" );  
1087          // transfer to emulator & create dump file  
1088          ctmp 
=  param_getchar ( Cmd
,  2 );  
1089          clen 
=  param_getlength ( Cmd
,  2 );  
1090          if  ( clen 
==  1  && ( ctmp 
==  't'  ||  ctmp 
==  'T' ))  transferToEml 
=  1 ;  
1091          if  ( clen 
==  1  && ( ctmp 
==  'd'  ||  ctmp 
==  'D' ))  createDumpFile 
=  1 ;  
1093          param3InUse 
=  transferToEml 
|  createDumpFile
;  
1095          timeout14a 
=  500 ;  // fast by default  
1096          // double parameters - ts, ds  
1097          clen 
=  param_getlength ( Cmd
,  2 );  
1098          if  ( clen 
==  2  ||  clen 
==  3 ){  
1099                  param_getstr ( Cmd
,  2 ,  ctmp3
,  sizeof ( ctmp3
));  
1103          if  ( ctmp 
==  's'  ||  ctmp 
==  'S' ) {  
1104                  timeout14a 
=  1000 ;  // slow  
1105                  if  (! param3InUse 
&&  clen 
==  2  && ( ctmp3
[ 1 ] ==  's'  ||  ctmp3
[ 1 ] ==  'S' )) {  
1106                          timeout14a 
=  5000 ;  // very slow  
1108                  if  ( param3InUse 
&&  clen 
==  3  && ( ctmp3
[ 2 ] ==  's'  ||  ctmp3
[ 2 ] ==  'S' )) {  
1109                          timeout14a 
=  5000 ;  // very slow  
1114          for  ( i 
=  param3InUse
;  param_getchar ( Cmd
,  2  +  i
);  i
++) {  
1115                  if  (! param_gethex ( Cmd
,  2  +  i
,  keyBlock 
+  6  *  keycnt
,  12 )) {  
1116                          if  (  stKeyBlock 
-  keycnt 
<  2 ) {  
1117                                  p 
=  realloc ( keyBlock
,  6 *( stKeyBlock
+= 10 ));  
1119                                          PrintAndLog ( "Cannot allocate memory for Keys" );  
1125                          PrintAndLog ( "chk key[ %2 d]  %0 2x %0 2x %0 2x %0 2x %0 2x %0 2x" ,  keycnt
,  
1126                          ( keyBlock 
+  6 * keycnt
)[ 0 ],( keyBlock 
+  6 * keycnt
)[ 1 ], ( keyBlock 
+  6 * keycnt
)[ 2 ],  
1127                          ( keyBlock 
+  6 * keycnt
)[ 3 ], ( keyBlock 
+  6 * keycnt
)[ 4 ],     ( keyBlock 
+  6 * keycnt
)[ 5 ],  6 );  
1130                          // May be a dic file  
1131                          if  (  param_getstr ( Cmd
,  2  +  i
,  filename
,  sizeof ( filename
)) >=  FILE_PATH_SIZE 
) {  
1132                                  PrintAndLog ( "File name too long" );  
1137                          if  ( ( f 
=  fopen (  filename 
,  "r" )) ) {  
1138                                  while (  fgets ( buf
,  sizeof ( buf
),  f
) ){  
1139                                          if  ( strlen ( buf
) <  12  ||  buf
[ 11 ] ==  ' \n ' )  
1142                                          while  ( fgetc ( f
) !=  ' \n '  && ! feof ( f
)) ;   //goto next line  
1144                                          if (  buf
[ 0 ]== '#'  )  continue ;      //The line start with # is comment, skip  
1146                                          if  (! isxdigit (( unsigned char ) buf
[ 0 ])){  
1147                                                  PrintAndLog ( "File content error. ' %s ' must include 12 HEX symbols" , buf
);  
1153                                          if  (  stKeyBlock 
-  keycnt 
<  2 ) {  
1154                                                  p 
=  realloc ( keyBlock
,  6 *( stKeyBlock
+= 10 ));  
1156                                                          PrintAndLog ( "Cannot allocate memory for defKeys" );  
1163                                          memset ( keyBlock 
+  6  *  keycnt
,  0 ,  6 );  
1164                                          num_to_bytes ( strtoll ( buf
,  NULL
,  16 ),  6 ,  keyBlock 
+  6 * keycnt
);  
1165                                          PrintAndLog ( "chk custom key[ %2 d]  %0 12"  PRIx64 
,  keycnt
,  bytes_to_num ( keyBlock 
+  6 * keycnt
,  6 ));  
1167                                          memset ( buf
,  0 ,  sizeof ( buf
));  
1171                                  PrintAndLog ( "File:  %s : not found or locked." ,  filename
);  
1179          // fill with default keys  
1181                  PrintAndLog ( "No key specified, trying default keys" );  
1182                  for  (; keycnt 
<  defaultKeysSize
;  keycnt
++)  
1183                          PrintAndLog ( "chk default key[ %2 d]  %0 2x %0 2x %0 2x %0 2x %0 2x %0 2x" ,  keycnt
,  
1184                                  ( keyBlock 
+  6 * keycnt
)[ 0 ],( keyBlock 
+  6 * keycnt
)[ 1 ], ( keyBlock 
+  6 * keycnt
)[ 2 ],  
1185                                  ( keyBlock 
+  6 * keycnt
)[ 3 ], ( keyBlock 
+  6 * keycnt
)[ 4 ],     ( keyBlock 
+  6 * keycnt
)[ 5 ],  6 );  
1188          // initialize storage for found keys  
1189          e_sector 
=  calloc ( SectorsCnt
,  sizeof ( sector_t
));  
1190          if  ( e_sector 
==  NULL
)  return  1 ;  
1191          for  ( uint8_t  keyAB 
=  0 ;  keyAB 
<  2 ;  keyAB
++) {  
1192                  for  ( uint16_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  
1193                          e_sector
[ sectorNo
]. Key
[ keyAB
] =  0xffffffffffff ;  
1194                          e_sector
[ sectorNo
]. foundKey
[ keyAB
] =  0 ;  
1199          bool  foundAKey 
=  false ;  
1200          uint32_t  max_keys 
=  keycnt 
>  USB_CMD_DATA_SIZE 
/  6  ?  USB_CMD_DATA_SIZE 
/  6  :  keycnt
;  
1202                  PrintAndLog ( "To cancel this operation press the button on the proxmark..." );  
1204                  for  ( uint32_t  c 
=  0 ;  c 
<  keycnt
;  c 
+=  max_keys
) {  
1206                          uint32_t  size 
=  keycnt
- c 
>  max_keys 
?  max_keys 
:  keycnt
- c
;  
1207                          res 
=  mfCheckKeysSec ( SectorsCnt
,  keyType
,  timeout14a 
*  1.06  /  100 ,  true ,  size
, & keyBlock
[ 6  *  c
],  e_sector
);  // timeout is (ms * 106)/10 or us*0.0106  
1218                                  PrintAndLog ( "Command execute timeout" );  
1222                  int  keyAB 
=  keyType
;  
1224                          for  ( uint32_t  c 
=  0 ;  c 
<  keycnt
;  c
+= max_keys
) {  
1226                                  uint32_t  size 
=  keycnt
- c 
>  max_keys 
?  max_keys 
:  keycnt
- c
;  
1227                                  res 
=  mfCheckKeys ( blockNo
,  keyAB 
&  0x01 ,  true ,  size
, & keyBlock
[ 6  *  c
], & key64
);   
1231                                                  PrintAndLog ( "Found valid key:[ %d : %c ] %0 12"  PRIx64
,  blockNo
, ( keyAB 
&  0x01 )? 'B' : 'A' ,  key64
);  
1235                                          PrintAndLog ( "Command execute timeout" );  
1238                  }  while (-- keyAB 
>  0 );  
1245                          PrintAndLog ( "|---|----------------|---|----------------|---|" );  
1246                          PrintAndLog ( "|sec|key A           |res|key B           |res|" );  
1247                          PrintAndLog ( "|---|----------------|---|----------------|---|" );  
1248                          for  ( i 
=  0 ;  i 
<  SectorsCnt
;  i
++) {  
1249                                  PrintAndLog ( "| %0 3d|   %0 12"  PRIx64 
"  |  %d  |   %0 12"  PRIx64 
"  |  %d  |" ,  i
,  
1250                                          e_sector
[ i
]. Key
[ 0 ],  e_sector
[ i
]. foundKey
[ 0 ],  e_sector
[ i
]. Key
[ 1 ],  e_sector
[ i
]. foundKey
[ 1 ]);  
1252                          PrintAndLog ( "|---|----------------|---|----------------|---|" );  
1256                  PrintAndLog ( "No valid keys found." );  
1259          if  ( transferToEml
) {  
1261                  for  ( uint16_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  
1262                          if  ( e_sector
[ sectorNo
]. foundKey
[ 0 ] ||  e_sector
[ sectorNo
]. foundKey
[ 1 ]) {  
1263                                  mfEmlGetMem ( block
,  FirstBlockOfSector ( sectorNo
) +  NumBlocksPerSector ( sectorNo
) -  1 ,  1 );  
1264                                  for  ( uint16_t  t 
=  0 ;  t 
<  2 ;  t
++) {  
1265                                          if  ( e_sector
[ sectorNo
]. foundKey
[ t
]) {  
1266                                                  num_to_bytes ( e_sector
[ sectorNo
]. Key
[ t
],  6 ,  block 
+  t 
*  10 );  
1269                                  mfEmlSetMem ( block
,  FirstBlockOfSector ( sectorNo
) +  NumBlocksPerSector ( sectorNo
) -  1 ,  1 );  
1272                  PrintAndLog ( "Found keys have been transferred to the emulator memory" );  
1275          if  ( createDumpFile
) {  
1276                  FILE  * fkeys 
=  fopen ( "dumpkeys.bin" , "wb" );  
1277                  if  ( fkeys 
==  NULL
) {  
1278                          PrintAndLog ( "Could not create file dumpkeys.bin" );  
1284                  for  ( uint8_t  t 
=  0 ;  t 
<  2 ;  t
++) {  
1285                          for  ( uint8_t  sectorNo 
=  0 ;  sectorNo 
<  SectorsCnt
;  sectorNo
++) {  
1286                                  num_to_bytes ( e_sector
[ sectorNo
]. Key
[ t
],  6 ,  mkey
);  
1287                                  fwrite ( mkey
,  1 ,  6 ,  fkeys
);  
1291                  PrintAndLog ( "Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys." );  
1300  void  readerAttack ( nonces_t ar_resp
[],  bool  setEmulatorMem
,  bool  doStandardAttack
) {  
1301          #define ATTACK_KEY_COUNT 7  // keep same as define in iso14443a.c -> Mifare1ksim()  
1302                                      // cannot be more than 7 or it will overrun c.d.asBytes(512)  
1308          st_t sector_trailer
[ ATTACK_KEY_COUNT
];  
1309          memset ( sector_trailer
,  0x00 ,  sizeof ( sector_trailer
));  
1311          uint8_t  stSector
[ ATTACK_KEY_COUNT
];  
1312          memset ( stSector
,  0x00 ,  sizeof ( stSector
));  
1313          uint8_t  key_cnt
[ ATTACK_KEY_COUNT
];  
1314          memset ( key_cnt
,  0x00 ,  sizeof ( key_cnt
));  
1316          for  ( uint8_t  i 
=  0 ;  i
< ATTACK_KEY_COUNT
;  i
++) {  
1317                  if  ( ar_resp
[ i
]. ar2 
>  0 ) {  
1318                          //PrintAndLog("DEBUG: 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);  
1319                          if  ( doStandardAttack 
&&  mfkey32 ( ar_resp
[ i
], & key
)) {  
1320                                  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 ));  
1322                                  for  ( uint8_t  ii 
=  0 ;  ii
< ATTACK_KEY_COUNT
;  ii
++) {  
1323                                          if  ( key_cnt
[ ii
]== 0  ||  stSector
[ ii
]== ar_resp
[ i
]. sector
) {  
1324                                                  if  ( ar_resp
[ i
]. keytype
== 0 ) {  
1326                                                          sector_trailer
[ ii
]. keyA 
=  key
;  
1327                                                          stSector
[ ii
] =  ar_resp
[ i
]. sector
;  
1332                                                          sector_trailer
[ ii
]. keyB 
=  key
;  
1333                                                          stSector
[ ii
] =  ar_resp
[ i
]. sector
;  
1339                          }  else if  ( mfkey32_moebius ( ar_resp
[ i
+ ATTACK_KEY_COUNT
], & key
)) {  
1340                                  uint8_t  sectorNum 
=  ar_resp
[ i
+ ATTACK_KEY_COUNT
]. sector
;  
1341                                  uint8_t  keyType 
=  ar_resp
[ i
+ ATTACK_KEY_COUNT
]. keytype
;  
1343                                  PrintAndLog ( "M-Found Key %s  for sector  %0 2d: [ %0 12"  PRIx64 
"]"  
1344                                          ,  keyType 
?  "B"  :  "A"  
1349                                  for  ( uint8_t  ii 
=  0 ;  ii
< ATTACK_KEY_COUNT
;  ii
++) {  
1350                                          if  ( key_cnt
[ ii
]== 0  ||  stSector
[ ii
]== sectorNum
) {  
1353                                                          sector_trailer
[ ii
]. keyA 
=  key
;  
1354                                                          stSector
[ ii
] =  sectorNum
;  
1359                                                          sector_trailer
[ ii
]. keyB 
=  key
;  
1360                                                          stSector
[ ii
] =  sectorNum
;  
1370          //set emulator memory for keys  
1371          if  ( setEmulatorMem
) {  
1372                  for  ( uint8_t  i 
=  0 ;  i
< ATTACK_KEY_COUNT
;  i
++) {  
1374                                  uint8_t  memBlock
[ 16 ];  
1375                                  memset ( memBlock
,  0x00 ,  sizeof ( memBlock
));  
1377                                  memset ( cmd1
, 0x00 , sizeof ( cmd1
));  
1378                                  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 ));  
1379                                  PrintAndLog ( "Setting Emulator Memory Block  %0 2d: [ %s ]" , stSector
[ i
]* 4 + 3 ,  cmd1
);  
1380                                  if  ( param_gethex ( cmd1
,  0 ,  memBlock
,  32 )) {  
1381                                          PrintAndLog ( "block data must include 32 HEX symbols" );  
1385                                  UsbCommand c 
= { CMD_MIFARE_EML_MEMSET
, {( stSector
[ i
]* 4 + 3 ),  1 ,  0 }};  
1386                                  memcpy ( c
. d
. asBytes
,  memBlock
,  16 );  
1387                                  clearCommandBuffer ();  
1393          //un-comment to use as well moebius attack  
1394          for (uint8_t i = ATTACK_KEY_COUNT; i<ATTACK_KEY_COUNT*2; i++) {  
1395                  if (ar_resp[i].ar2 > 0) {  
1396                          if (tryMfk32_moebius(ar_resp[i], &key)) {  
1397                                  PrintAndLog("M-Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));  
1403  int  usage_hf14_mf1ksim ( void ) {  
1404          PrintAndLog ( "Usage:  hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x" );  
1405          PrintAndLog ( "options:" );  
1406          PrintAndLog ( "      h    this help" );  
1407          PrintAndLog ( "      u    (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used" );  
1408          PrintAndLog ( "      n    (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite" );  
1409          PrintAndLog ( "      i    (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted" );  
1410          PrintAndLog ( "      x    (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)" );  
1411          PrintAndLog ( "      e    (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)" );  
1412          PrintAndLog ( "      f    (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)" );  
1413          PrintAndLog ( "      r    (Optional) Generate random nonces instead of sequential nonces. Standard reader attack won't work with this option, only moebius attack works." );  
1414          PrintAndLog ( "samples:" );  
1415          PrintAndLog ( "           hf mf sim u 0a0a0a0a" );  
1416          PrintAndLog ( "           hf mf sim u 11223344556677" );  
1417          PrintAndLog ( "           hf mf sim u 112233445566778899AA" );  
1418          PrintAndLog ( "           hf mf sim f uids.txt" );  
1419          PrintAndLog ( "           hf mf sim u 0a0a0a0a e" );  
1424  int  CmdHF14AMf1kSim ( const char  * Cmd
) {  
1426          uint8_t  uid
[ 10 ] = { 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 };  
1427          uint8_t  exitAfterNReads 
=  0 ;  
1431          bool  setEmulatorMem 
=  false ;  
1432          bool  attackFromFile 
=  false ;  
1434          char  filename
[ FILE_PATH_SIZE
];  
1435          memset ( filename
,  0x00 ,  sizeof ( filename
));  
1440          bool  errors 
=  false ;  
1442          while ( param_getchar ( Cmd
,  cmdp
) !=  0x00 ) {  
1443                  switch ( param_getchar ( Cmd
,  cmdp
)) {  
1446                          setEmulatorMem 
=  true ;  
1448                          flags 
|=  FLAG_INTERACTIVE
;  
1449                          flags 
|=  FLAG_NR_AR_ATTACK
;  
1454                          len 
=  param_getstr ( Cmd
,  cmdp
+ 1 ,  filename
,  sizeof ( filename
));  
1456                                  PrintAndLog ( "error no filename found" );  
1459                          attackFromFile 
=  true ;  
1461                          flags 
|=  FLAG_INTERACTIVE
;  
1462                          flags 
|=  FLAG_NR_AR_ATTACK
;  
1467                          return  usage_hf14_mf1ksim ();  
1470                          flags 
|=  FLAG_INTERACTIVE
;  
1475                          exitAfterNReads 
=  param_get8 ( Cmd
,  pnr
+ 1 );  
1480                          flags 
|=  FLAG_RANDOM_NONCE
;  
1485                          param_gethex_ex ( Cmd
,  cmdp
+ 1 ,  uid
, & uidlen
);  
1487                                  case  20 :  flags 
=  FLAG_10B_UID_IN_DATA
;   break ;  //not complete  
1488                                  case  14 :  flags 
=  FLAG_7B_UID_IN_DATA
;  break ;  
1489                                  case   8 :  flags 
=  FLAG_4B_UID_IN_DATA
;  break ;  
1490                                  default :  return  usage_hf14_mf1ksim ();  
1496                          flags 
|=  FLAG_NR_AR_ATTACK
;  
1500                          PrintAndLog ( "Unknown parameter ' %c '" ,  param_getchar ( Cmd
,  cmdp
));  
1507          if ( errors
)  return  usage_hf14_mf1ksim ();  
1510          if  ( attackFromFile
) {  
1513                  f 
=  fopen ( filename
,  "r" );  
1515                          PrintAndLog ( "File  %s  not found or locked" ,  filename
);  
1518                  PrintAndLog ( "Loading file and simulating. Press keyboard to abort" );  
1519                  while (! feof ( f
) && ! ukbhit ()){  
1520                          memset ( buf
,  0 ,  sizeof ( buf
));  
1521                          memset ( uid
,  0 ,  sizeof ( uid
));  
1523                          if  ( fgets ( buf
,  sizeof ( buf
),  f
) ==  NULL
) {  
1524                                  if  ( count 
>  0 )  break ;  
1526                                  PrintAndLog ( "File reading error." );  
1530                          if (! strlen ( buf
) &&  feof ( f
))  break ;  
1532                          uidlen 
=  strlen ( buf
)- 1 ;  
1534                                  case  20 :  flags 
|=  FLAG_10B_UID_IN_DATA
;  break ;  //not complete  
1535                                  case  14 :  flags 
|=  FLAG_7B_UID_IN_DATA
;  break ;  
1536                                  case   8 :  flags 
|=  FLAG_4B_UID_IN_DATA
;  break ;  
1538                                          PrintAndLog ( "uid in file wrong length at  %d  (length:  %d ) [ %s ]" , count
,  uidlen
,  buf
);  
1543                          for  ( uint8_t  i 
=  0 ;  i 
<  uidlen
;  i 
+=  2 ) {  
1544                                  sscanf (& buf
[ i
],  " %0 2x" , ( unsigned int  *)& uid
[ i 
/  2 ]);  
1547                          PrintAndLog ( "mf 1k sim uid:  %s , numreads: %d , flags: %d  (0x %0 2x) - press button to abort" ,  
1548                                          flags 
&  FLAG_4B_UID_IN_DATA 
?  sprint_hex ( uid
, 4 ):  
1549                                                  flags 
&  FLAG_7B_UID_IN_DATA     
?  sprint_hex ( uid
, 7 ):  
1550                                                          flags 
&  FLAG_10B_UID_IN_DATA 
?  sprint_hex ( uid
, 10 ):  "N/A"  
1551                                          ,  exitAfterNReads
,  flags
,  flags
);  
1553                          UsbCommand c 
= { CMD_SIMULATE_MIFARE_CARD
, { flags
,  exitAfterNReads
, 0 }};  
1554                          memcpy ( c
. d
. asBytes
,  uid
,  sizeof ( uid
));  
1555                          clearCommandBuffer ();  
1558                          while (!  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
1559                                  //We're waiting only 1.5 s at a time, otherwise we get the  
1560                                  // annoying message about "Waiting for a response... "  
1563                          nonces_t ar_resp
[ ATTACK_KEY_COUNT
* 2 ];  
1564                          memcpy ( ar_resp
,  resp
. d
. asBytes
,  sizeof ( ar_resp
));  
1565                          // We can skip the standard attack if we have RANDOM_NONCE set.  
1566                          readerAttack ( ar_resp
,  setEmulatorMem
, !( flags 
&  FLAG_RANDOM_NONCE
));  
1567                          if  (( bool ) resp
. arg
[ 1 ]) {  
1568                                  PrintAndLog ( "Device button pressed - quitting" );  
1575          }  else  {  //not from file  
1577                  PrintAndLog ( "mf 1k sim uid:  %s , numreads: %d , flags: %d  (0x %0 2x) " ,  
1578                                  flags 
&  FLAG_4B_UID_IN_DATA 
?  sprint_hex ( uid
, 4 ):  
1579                                          flags 
&  FLAG_7B_UID_IN_DATA     
?  sprint_hex ( uid
, 7 ):  
1580                                                  flags 
&  FLAG_10B_UID_IN_DATA 
?  sprint_hex ( uid
, 10 ):  "N/A"  
1581                                  ,  exitAfterNReads
,  flags
,  flags
);  
1583                  UsbCommand c 
= { CMD_SIMULATE_MIFARE_CARD
, { flags
,  exitAfterNReads
, 0 }};  
1584                  memcpy ( c
. d
. asBytes
,  uid
,  sizeof ( uid
));  
1585                  clearCommandBuffer ();  
1588                  if ( flags 
&  FLAG_INTERACTIVE
) {  
1589                          PrintAndLog ( "Press pm3-button to abort simulation" );  
1590                          while (!  WaitForResponseTimeout ( CMD_ACK
,& resp
, 1500 )) {  
1591                                  //We're waiting only 1.5 s at a time, otherwise we get the  
1592                                  // annoying message about "Waiting for a response... "  
1595                          if  ( flags 
&  FLAG_NR_AR_ATTACK
) {  
1596                                  nonces_t ar_resp
[ ATTACK_KEY_COUNT
* 2 ];  
1597                                  memcpy ( ar_resp
,  resp
. d
. asBytes
,  sizeof ( ar_resp
));  
1598                                  // We can skip the standard attack if we have RANDOM_NONCE set.  
1599                                  readerAttack ( ar_resp
,  setEmulatorMem
, !( flags 
&  FLAG_RANDOM_NONCE
));  
1607  int  CmdHF14AMfDbg ( const char  * Cmd
)  
1609          int  dbgMode 
=  param_get32ex ( Cmd
,  0 ,  0 ,  10 );  
1611                  PrintAndLog ( "Max debug mode parameter is 4  \n " );  
1614          if  ( strlen ( Cmd
) <  1  || ! param_getchar ( Cmd
,  0 ) ||  dbgMode 
>  4 ) {  
1615                  PrintAndLog ( "Usage:  hf mf dbg  <debug level>" );  
1616                  PrintAndLog ( " 0 - no debug messages" );  
1617                  PrintAndLog ( " 1 - error messages" );  
1618                  PrintAndLog ( " 2 - plus information messages" );  
1619                  PrintAndLog ( " 3 - plus debug messages" );  
1620                  PrintAndLog ( " 4 - print even debug messages in timing critical functions" );  
1621                  PrintAndLog ( "     Note: this option therefore may cause malfunction itself" );  
1625    UsbCommand c 
= { CMD_MIFARE_SET_DBGMODE
, { dbgMode
,  0 ,  0 }};  
1631  int  CmdHF14AMfEGet ( const char  * Cmd
)  
1633          uint8_t  blockNo 
=  0 ;  
1634          uint8_t  data
[ 16 ] = { 0x00 };  
1636          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
1637                  PrintAndLog ( "Usage:  hf mf eget <block number>" );  
1638                  PrintAndLog ( " sample: hf mf eget 0 " );  
1642          blockNo 
=  param_get8 ( Cmd
,  0 );  
1645          if  (! mfEmlGetMem ( data
,  blockNo
,  1 )) {  
1646                  PrintAndLog ( "data[ %3 d]: %s " ,  blockNo
,  sprint_hex ( data
,  16 ));  
1648                  PrintAndLog ( "Command execute timeout" );  
1654  int  CmdHF14AMfEClear ( const char  * Cmd
)  
1656          if  ( param_getchar ( Cmd
,  0 ) ==  'h' ) {  
1657                  PrintAndLog ( "Usage:  hf mf eclr" );  
1658                  PrintAndLog ( "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF  \n " );  
1662    UsbCommand c 
= { CMD_MIFARE_EML_MEMCLR
, { 0 ,  0 ,  0 }};  
1668  int  CmdHF14AMfESet ( const char  * Cmd
)  
1670          uint8_t  memBlock
[ 16 ];  
1671          uint8_t  blockNo 
=  0 ;  
1673          memset ( memBlock
,  0x00 ,  sizeof ( memBlock
));  
1675          if  ( strlen ( Cmd
) <  3  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
1676                  PrintAndLog ( "Usage:  hf mf eset <block number> <block data (32 hex symbols)>" );  
1677                  PrintAndLog ( " sample: hf mf eset 1 000102030405060708090a0b0c0d0e0f " );  
1681          blockNo 
=  param_get8 ( Cmd
,  0 );  
1683          if  ( param_gethex ( Cmd
,  1 ,  memBlock
,  32 )) {  
1684                  PrintAndLog ( "block data must include 32 HEX symbols" );  
1689          return  mfEmlSetMem ( memBlock
,  blockNo
,  1 );  
1693  int  CmdHF14AMfELoad ( const char  * Cmd
)  
1696          char  filename
[ FILE_PATH_SIZE
];  
1697          char  * fnameptr 
=  filename
;  
1698          char  buf
[ 64 ] = { 0x00 };  
1699          uint8_t  buf8
[ 64 ] = { 0x00 };  
1700          int  i
,  len
,  blockNum
,  numBlocks
;  
1701          int  nameParamNo 
=  1 ;  
1703          char  ctmp 
=  param_getchar ( Cmd
,  0 );  
1705          if  (  ctmp 
==  'h'  ||  ctmp 
==  0x00 ) {  
1706                  PrintAndLog ( "It loads emul dump from the file `filename.eml`" );  
1707                  PrintAndLog ( "Usage:  hf mf eload [card memory] <file name w/o `.eml`>" );  
1708                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
1710                  PrintAndLog ( " sample: hf mf eload filename" );  
1711                  PrintAndLog ( "         hf mf eload 4 filename" );  
1716                  case  '0'  :  numBlocks 
=  5 * 4 ;  break ;  
1718                  case  '\0' :  numBlocks 
=  16 * 4 ;  break ;  
1719                  case  '2'  :  numBlocks 
=  32 * 4 ;  break ;  
1720                  case  '4'  :  numBlocks 
=  256 ;  break ;  
1727          len 
=  param_getstr ( Cmd
, nameParamNo
, filename
, sizeof ( filename
));  
1729          if  ( len 
>  FILE_PATH_SIZE 
-  5 )  len 
=  FILE_PATH_SIZE 
-  5 ;  
1733          sprintf ( fnameptr
,  ".eml" );  
1736          f 
=  fopen ( filename
,  "r" );  
1738                  PrintAndLog ( "File  %s  not found or locked" ,  filename
);  
1744                  memset ( buf
,  0 ,  sizeof ( buf
));  
1746                  if  ( fgets ( buf
,  sizeof ( buf
),  f
) ==  NULL
) {  
1748                          if  ( blockNum 
>=  numBlocks
)  break ;  
1750                          PrintAndLog ( "File reading error." );  
1755                  if  ( strlen ( buf
) <  32 ){  
1756                          if ( strlen ( buf
) &&  feof ( f
))  
1758                          PrintAndLog ( "File content error. Block data must include 32 HEX symbols" );  
1763                  for  ( i 
=  0 ;  i 
<  32 ;  i 
+=  2 ) {  
1764                          sscanf (& buf
[ i
],  " %0 2x" , ( unsigned int  *)& buf8
[ i 
/  2 ]);  
1767                  if  ( mfEmlSetMem ( buf8
,  blockNum
,  1 )) {  
1768                          PrintAndLog ( "Cant set emul block:  %3 d" ,  blockNum
);  
1775                  if  ( blockNum 
>=  numBlocks
)  break ;  
1780          if  (( blockNum 
!=  numBlocks
)) {  
1781                  PrintAndLog ( "File content error. Got  %d  must be  %d  blocks." , blockNum
,  numBlocks
);  
1784          PrintAndLog ( "Loaded  %d  blocks from file:  %s " ,  blockNum
,  filename
);  
1789  int  CmdHF14AMfESave ( const char  * Cmd
)  
1792          char  filename
[ FILE_PATH_SIZE
];  
1793          char  *  fnameptr 
=  filename
;  
1795          int  i
,  j
,  len
,  numBlocks
;  
1796          int  nameParamNo 
=  1 ;  
1798          memset ( filename
,  0 ,  sizeof ( filename
));  
1799          memset ( buf
,  0 ,  sizeof ( buf
));  
1801          char  ctmp 
=  param_getchar ( Cmd
,  0 );  
1803          if  (  ctmp 
==  'h'  ||  ctmp 
==  'H' ) {  
1804                  PrintAndLog ( "It saves emul dump into the file `filename.eml` or `cardID.eml`" );  
1805                  PrintAndLog ( " Usage:  hf mf esave [card memory] [file name w/o `.eml`]" );  
1806                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
1808                  PrintAndLog ( " sample: hf mf esave " );  
1809                  PrintAndLog ( "         hf mf esave 4" );  
1810                  PrintAndLog ( "         hf mf esave 4 filename" );  
1815                  case  '0'  :  numBlocks 
=  5 * 4 ;  break ;  
1817                  case  '\0' :  numBlocks 
=  16 * 4 ;  break ;  
1818                  case  '2'  :  numBlocks 
=  32 * 4 ;  break ;  
1819                  case  '4'  :  numBlocks 
=  256 ;  break ;  
1826          len 
=  param_getstr ( Cmd
, nameParamNo
, filename
, sizeof ( filename
));  
1828          if  ( len 
>  FILE_PATH_SIZE 
-  5 )  len 
=  FILE_PATH_SIZE 
-  5 ;  
1830          // user supplied filename?  
1832                  // get filename (UID from memory)  
1833                  if  ( mfEmlGetMem ( buf
,  0 ,  1 )) {  
1834                          PrintAndLog ( "Can \' t get UID from block:  %d " ,  0 );  
1835                          len 
=  sprintf ( fnameptr
,  "dump" );  
1839                          for  ( j 
=  0 ;  j 
<  7 ;  j
++,  fnameptr 
+=  2 )  
1840                                  sprintf ( fnameptr
,  " %0 2X" ,  buf
[ j
]);  
1846          // add file extension  
1847          sprintf ( fnameptr
,  ".eml" );  
1850          f 
=  fopen ( filename
,  "w+" );  
1853                  PrintAndLog ( "Can't open file  %s  " ,  filename
);  
1858          for  ( i 
=  0 ;  i 
<  numBlocks
;  i
++) {  
1859                  if  ( mfEmlGetMem ( buf
,  i
,  1 )) {  
1860                          PrintAndLog ( "Cant get block:  %d " ,  i
);  
1863                  for  ( j 
=  0 ;  j 
<  16 ;  j
++)  
1864                          fprintf ( f
,  " %0 2X" ,  buf
[ j
]);  
1869          PrintAndLog ( "Saved  %d  blocks to file:  %s " ,  numBlocks
,  filename
);  
1875  int  CmdHF14AMfECFill ( const char  * Cmd
)  
1877          uint8_t  keyType 
=  0 ;  
1878          uint8_t  numSectors 
=  16 ;  
1880          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
1881                  PrintAndLog ( "Usage:  hf mf ecfill <key A/B> [card memory]" );  
1882                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
1884                  PrintAndLog ( "samples:  hf mf ecfill A" );  
1885                  PrintAndLog ( "          hf mf ecfill A 4" );  
1886                  PrintAndLog ( "Read card and transfer its data to emulator memory." );  
1887                  PrintAndLog ( "Keys must be laid in the emulator memory.  \n " );  
1891          char  ctmp 
=  param_getchar ( Cmd
,  0 );  
1892          if  ( ctmp 
!=  'a'  &&  ctmp 
!=  'A'  &&  ctmp 
!=  'b'  &&  ctmp 
!=  'B' ) {  
1893                  PrintAndLog ( "Key type must be A or B" );  
1896          if  ( ctmp 
!=  'A'  &&  ctmp 
!=  'a' )  keyType 
=  1 ;  
1898          ctmp 
=  param_getchar ( Cmd
,  1 );  
1900                  case  '0'  :  numSectors 
=  5 ;  break ;  
1902                  case  '\0' :  numSectors 
=  16 ;  break ;  
1903                  case  '2'  :  numSectors 
=  32 ;  break ;  
1904                  case  '4'  :  numSectors 
=  40 ;  break ;  
1905                  default :    numSectors 
=  16 ;  
1908          printf ( "--params: numSectors:  %d , keyType: %d \n " ,  numSectors
,  keyType
);  
1909          UsbCommand c 
= { CMD_MIFARE_EML_CARDLOAD
, { numSectors
,  keyType
,  0 }};  
1914  int  CmdHF14AMfEKeyPrn ( const char  * Cmd
)  
1919          uint64_t  keyA
,  keyB
;  
1921          if  ( param_getchar ( Cmd
,  0 ) ==  'h' ) {  
1922                  PrintAndLog ( "It prints the keys loaded in the emulator memory" );  
1923                  PrintAndLog ( "Usage:  hf mf ekeyprn [card memory]" );  
1924                  PrintAndLog ( "  [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
1926                  PrintAndLog ( " sample: hf mf ekeyprn 1" );  
1930          char  cmdp 
=  param_getchar ( Cmd
,  0 );  
1933                  case  '0'  :  numSectors 
=  5 ;  break ;  
1935                  case  '\0' :  numSectors 
=  16 ;  break ;  
1936                  case  '2'  :  numSectors 
=  32 ;  break ;  
1937                  case  '4'  :  numSectors 
=  40 ;  break ;  
1938                  default :    numSectors 
=  16 ;  
1941          PrintAndLog ( "|---|----------------|----------------|" );  
1942          PrintAndLog ( "|sec|key A           |key B           |" );  
1943          PrintAndLog ( "|---|----------------|----------------|" );  
1944          for  ( i 
=  0 ;  i 
<  numSectors
;  i
++) {  
1945                  if  ( mfEmlGetMem ( data
,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 ,  1 )) {  
1946                          PrintAndLog ( "error get block  %d " ,  FirstBlockOfSector ( i
) +  NumBlocksPerSector ( i
) -  1 );  
1949                  keyA 
=  bytes_to_num ( data
,  6 );  
1950                  keyB 
=  bytes_to_num ( data 
+  10 ,  6 );  
1951                  PrintAndLog ( "| %0 3d|   %0 12"  PRIx64 
"  |   %0 12"  PRIx64 
"  |" ,  i
,  keyA
,  keyB
);  
1953          PrintAndLog ( "|---|----------------|----------------|" );  
1958  int  CmdHF14AMfCSetUID ( const char  * Cmd
)  
1960          uint8_t  uid
[ 8 ] = { 0x00 };  
1961          uint8_t  oldUid
[ 8 ] = { 0x00 };  
1962          uint8_t  atqa
[ 2 ] = { 0x00 };  
1963          uint8_t  sak
[ 1 ] = { 0x00 };  
1964          uint8_t  atqaPresent 
=  0 ;  
1967          uint8_t  needHelp 
=  0 ;  
1970          if  ( param_getchar ( Cmd
,  0 ) &&  param_gethex ( Cmd
,  0 ,  uid
,  8 )) {  
1971                  PrintAndLog ( "UID must include 8 HEX symbols" );  
1975          if  ( param_getlength ( Cmd
,  1 ) >  1  &&  param_getlength ( Cmd
,  2 ) >   1 ) {  
1979                  if  ( param_gethex ( Cmd
,  1 ,  atqa
,  4 )) {  
1980                          PrintAndLog ( "ATQA must include 4 HEX symbols" );  
1984                  if  ( param_gethex ( Cmd
,  2 ,  sak
,  2 )) {  
1985                          PrintAndLog ( "SAK must include 2 HEX symbols" );  
1990          while ( param_getchar ( Cmd
,  cmdp
) !=  0x00 )  
1992                  switch ( param_getchar ( Cmd
,  cmdp
))  
1999                          PrintAndLog ( "ERROR: Unknown parameter ' %c '" ,  param_getchar ( Cmd
,  cmdp
));  
2006          if  ( strlen ( Cmd
) <  1  ||  needHelp
) {  
2008                  PrintAndLog ( "Usage:  hf mf csetuid <UID 8 hex symbols> [ATQA 4 hex symbols SAK 2 hex symbols]" );  
2009                  PrintAndLog ( "sample:  hf mf csetuid 01020304" );  
2010                  PrintAndLog ( "sample:  hf mf csetuid 01020304 0004 08" );  
2011                  PrintAndLog ( "Set UID, ATQA, and SAK for magic Chinese card (only works with such cards)" );  
2015          PrintAndLog ( "uid: %s " ,  sprint_hex ( uid
,  4 ));  
2017                  PrintAndLog ( "--atqa: %s  sak: %0 2x" ,  sprint_hex ( atqa
,  2 ),  sak
[ 0 ]);  
2020          res 
=  mfCSetUID ( uid
, ( atqaPresent
)? atqa
: NULL
, ( atqaPresent
)? sak
: NULL
,  oldUid
);  
2022                          PrintAndLog ( "Can't set UID. Error= %d " ,  res
);  
2026          PrintAndLog ( "old UID: %s " ,  sprint_hex ( oldUid
,  4 ));  
2027          PrintAndLog ( "new UID: %s " ,  sprint_hex ( uid
,  4 ));  
2031  int  CmdHF14AMfCWipe ( const char  * Cmd
)  
2034          int  numBlocks 
=  16  *  4 ;  
2035          bool  wipeCard 
=  false ;  
2036          bool  fillCard 
=  false ;  
2038          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
2039                  PrintAndLog ( "Usage:  hf mf cwipe [card size] [w] [f]" );  
2040                  PrintAndLog ( "sample:  hf mf cwipe 1 w f" );  
2041                  PrintAndLog ( "[card size]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K" );  
2042                  PrintAndLog ( "w - Wipe magic Chinese card (only works with gen:1a cards)" );  
2043                  PrintAndLog ( "f - Fill the card with default data and keys (works with gen:1a and gen:1b cards only)" );  
2047          gen 
=  mfCIdentify ();  
2048          if  (( gen 
!=  1 ) && ( gen 
!=  2 ))   
2051          numBlocks 
=  ParamCardSizeBlocks ( param_getchar ( Cmd
,  0 ));  
2054          while ( param_getchar ( Cmd
,  cmdp
) !=  0x00 ){  
2055                  switch ( param_getchar ( Cmd
,  cmdp
)) {  
2070          if  (! wipeCard 
&& ! fillCard
)   
2073          PrintAndLog ( "--blocks count: %2 d wipe: %c  fill: %c " ,  numBlocks
, ( wipeCard
)? 'y' : 'n' , ( fillCard
)? 'y' : 'n' );  
2076                  /* generation 1b magic card */  
2078                          PrintAndLog ( "WARNING: can't wipe magic card 1b generation" );  
2080                  res 
=  mfCWipe ( numBlocks
,  true ,  false ,  fillCard
);   
2082                  /* generation 1a magic card by default */  
2083                  res 
=  mfCWipe ( numBlocks
,  false ,  wipeCard
,  fillCard
);   
2087                  PrintAndLog ( "Can't wipe. error= %d " ,  res
);  
2094  int  CmdHF14AMfCSetBlk ( const char  * Cmd
)  
2096          uint8_t  memBlock
[ 16 ] = { 0x00 };  
2097          uint8_t  blockNo 
=  0 ;  
2098          bool  wipeCard 
=  false ;  
2101          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
2102                  PrintAndLog ( "Usage:  hf mf csetblk <block number> <block data (32 hex symbols)> [w]" );  
2103                  PrintAndLog ( "sample:  hf mf csetblk 1 01020304050607080910111213141516" );  
2104                  PrintAndLog ( "Set block data for magic Chinese card (only works with such cards)" );  
2105                  PrintAndLog ( "If you also want wipe the card then add 'w' at the end of the command line" );  
2109          gen 
=  mfCIdentify ();  
2110          if  (( gen 
!=  1 ) && ( gen 
!=  2 ))   
2113          blockNo 
=  param_get8 ( Cmd
,  0 );  
2115          if  ( param_gethex ( Cmd
,  1 ,  memBlock
,  32 )) {  
2116                  PrintAndLog ( "block data must include 32 HEX symbols" );  
2120          char  ctmp 
=  param_getchar ( Cmd
,  2 );  
2121          wipeCard 
= ( ctmp 
==  'w'  ||  ctmp 
==  'W' );  
2122          PrintAndLog ( "--block number: %2 d data: %s " ,  blockNo
,  sprint_hex ( memBlock
,  16 ));  
2125                  /* generation 1b magic card */  
2126                  res 
=  mfCSetBlock ( blockNo
,  memBlock
,  NULL
,  wipeCard
,  CSETBLOCK_SINGLE_OPER 
|  CSETBLOCK_MAGIC_1B
);  
2128                  /* generation 1a magic card by default */  
2129                  res 
=  mfCSetBlock ( blockNo
,  memBlock
,  NULL
,  wipeCard
,  CSETBLOCK_SINGLE_OPER
);  
2133                  PrintAndLog ( "Can't write block. error= %d " ,  res
);  
2140  int  CmdHF14AMfCLoad ( const char  * Cmd
)  
2143          char  filename
[ FILE_PATH_SIZE
] = { 0x00 };  
2144          char  *  fnameptr 
=  filename
;  
2145          char  buf
[ 256 ] = { 0x00 };  
2146          uint8_t  buf8
[ 256 ] = { 0x00 };  
2147          uint8_t  fillFromEmulator 
=  0 ;  
2148          int  i
,  len
,  blockNum
,  flags 
=  0 ,  gen 
=  0 ,  numblock 
=  64 ;  
2150          if  ( param_getchar ( Cmd
,  0 ) ==  'h'  ||  param_getchar ( Cmd
,  0 )==  0x00 ) {  
2151                  PrintAndLog ( "It loads magic Chinese card from the file `filename.eml`" );  
2152                  PrintAndLog ( "or from emulator memory (option `e`). 4K card: (option `4`)" );  
2153                  PrintAndLog ( "Usage:  hf mf cload [file name w/o `.eml`][e][4]" );  
2154                  PrintAndLog ( "   or:  hf mf cload e [4]" );  
2155                  PrintAndLog ( "Sample: hf mf cload filename" );  
2156                  PrintAndLog ( "        hf mf cload filname 4" );  
2157                  PrintAndLog ( "        hf mf cload e" );  
2158                  PrintAndLog ( "        hf mf cload e 4" );  
2162          char  ctmp 
=  param_getchar ( Cmd
,  0 );  
2163          if  ( ctmp 
==  'e'  ||  ctmp 
==  'E' )  fillFromEmulator 
=  1 ;  
2164          ctmp 
=  param_getchar ( Cmd
,  1 );  
2165          if  ( ctmp 
==  '4' )  numblock 
=  256 ;  
2167          gen 
=  mfCIdentify ();  
2168          PrintAndLog ( "Loading magic mifare  %d K" ,  numblock 
==  256  ?  4 : 1 );  
2170          if  ( fillFromEmulator
) {  
2171                  for  ( blockNum 
=  0 ;  blockNum 
<  numblock
;  blockNum 
+=  1 ) {  
2172                          if  ( mfEmlGetMem ( buf8
,  blockNum
,  1 )) {  
2173                                  PrintAndLog ( "Cant get block:  %d " ,  blockNum
);  
2176                          if  ( blockNum 
==  0 )  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;                                // switch on field and send magic sequence  
2177                          if  ( blockNum 
==  1 )  flags 
=  0 ;                                                                                                    // just write  
2178                          if  ( blockNum 
==  numblock 
-  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;            // Done. Magic Halt and switch off field.  
2181                                  /* generation 1b magic card */  
2182                                  flags 
|=  CSETBLOCK_MAGIC_1B
;  
2183                          if  ( mfCSetBlock ( blockNum
,  buf8
,  NULL
,  0 ,  flags
)) {  
2184                                  PrintAndLog ( "Cant set magic card block:  %d " ,  blockNum
);  
2190                  param_getstr ( Cmd
,  0 ,  filename
,  sizeof ( filename
));  
2192                  len 
=  strlen ( filename
);  
2193                  if  ( len 
>  FILE_PATH_SIZE 
-  5 )  len 
=  FILE_PATH_SIZE 
-  5 ;  
2195                  //memcpy(filename, Cmd, len);  
2198                  sprintf ( fnameptr
,  ".eml" );  
2201                  f 
=  fopen ( filename
,  "r" );  
2203                          PrintAndLog ( "File not found or locked." );  
2210                          memset ( buf
,  0 ,  sizeof ( buf
));  
2212                          if  ( fgets ( buf
,  sizeof ( buf
),  f
) ==  NULL
) {  
2214                                  PrintAndLog ( "File reading error." );  
2218                          if  ( strlen ( buf
) <  32 ) {  
2219                                  if ( strlen ( buf
) &&  feof ( f
))  
2221                                  PrintAndLog ( "File content error. Block data must include 32 HEX symbols" );  
2225                          for  ( i 
=  0 ;  i 
<  32 ;  i 
+=  2 )  
2226                                  sscanf (& buf
[ i
],  " %0 2x" , ( unsigned int  *)& buf8
[ i 
/  2 ]);  
2228                          if  ( blockNum 
==  0 )  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;                                // switch on field and send magic sequence  
2229                          if  ( blockNum 
==  1 )  flags 
=  0 ;                                                                                                    // just write  
2230                          if  ( blockNum 
==  numblock 
-  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;            // Done. Switch off field.  
2233                                  /* generation 1b magic card */  
2234                                  flags 
|=  CSETBLOCK_MAGIC_1B
;  
2235                          if  ( mfCSetBlock ( blockNum
,  buf8
,  NULL
,  0 ,  flags
)) {  
2236                                  PrintAndLog ( "Can't set magic card block:  %d " ,  blockNum
);  
2242                          if  ( blockNum 
>=  numblock
)  break ;   // magic card type - mifare 1K 64 blocks, mifare 4k 256 blocks  
2246                  //if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){  
2247                  if  ( blockNum 
!=  numblock
){  
2248                          PrintAndLog ( "File content error. There must be  %d  blocks" ,  numblock
);  
2251                  PrintAndLog ( "Loaded from file:  %s " ,  filename
);  
2257  int  CmdHF14AMfCGetBlk ( const char  * Cmd
) {  
2258          uint8_t  memBlock
[ 16 ];  
2259          uint8_t  blockNo 
=  0 ;  
2261          memset ( memBlock
,  0x00 ,  sizeof ( memBlock
));  
2263          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
2264                  PrintAndLog ( "Usage:  hf mf cgetblk <block number>" );  
2265                  PrintAndLog ( "sample:  hf mf cgetblk 1" );  
2266                  PrintAndLog ( "Get block data from magic Chinese card (only works with such cards) \n " );  
2270          gen 
=  mfCIdentify ();  
2272          blockNo 
=  param_get8 ( Cmd
,  0 );  
2274          PrintAndLog ( "--block number: %2 d " ,  blockNo
);  
2277                  /* generation 1b magic card */  
2278                  res 
=  mfCGetBlock ( blockNo
,  memBlock
,  CSETBLOCK_SINGLE_OPER 
|  CSETBLOCK_MAGIC_1B
);  
2280                  /* generation 1a magic card by default */  
2281                  res 
=  mfCGetBlock ( blockNo
,  memBlock
,  CSETBLOCK_SINGLE_OPER
);  
2284                          PrintAndLog ( "Can't read block. error= %d " ,  res
);  
2288          PrintAndLog ( "block data: %s " ,  sprint_hex ( memBlock
,  16 ));  
2292  int  CmdHF14AMfCGetSc ( const char  * Cmd
) {  
2293          uint8_t  memBlock
[ 16 ] = { 0x00 };  
2294          uint8_t  sectorNo 
=  0 ;  
2295          int  i
,  res
,  flags
,  gen 
=  0 ,  baseblock 
=  0 ,  sect_size 
=  4 ;  
2297          if  ( strlen ( Cmd
) <  1  ||  param_getchar ( Cmd
,  0 ) ==  'h' ) {  
2298                  PrintAndLog ( "Usage:  hf mf cgetsc <sector number>" );  
2299                  PrintAndLog ( "sample:  hf mf cgetsc 0" );  
2300                  PrintAndLog ( "Get sector data from magic Chinese card (only works with such cards) \n " );  
2304          sectorNo 
=  param_get8 ( Cmd
,  0 );  
2306          if  ( sectorNo 
>  39 ) {  
2307                  PrintAndLog ( "Sector number must be in [0..15] in MIFARE classic 1k and [0..39] in MIFARE classic 4k." );  
2311          PrintAndLog ( "--sector number: %d  " ,  sectorNo
);  
2313          gen 
=  mfCIdentify ();  
2315          flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;  
2316          if  ( sectorNo 
<  32  ) {  
2317                  baseblock 
=  sectorNo 
*  4 ;  
2319                  baseblock 
=  128  +  16  * ( sectorNo 
-  32 );  
2322          if  ( sectorNo 
>  31 )  sect_size 
=  16 ;  
2324          for  ( i 
=  0 ;  i 
<  sect_size
;  i
++) {  
2325                  if  ( i 
==  1 )  flags 
=  0 ;  
2326                  if  ( i 
==  sect_size 
-  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;  
2329                          /* generation 1b magic card */  
2330                          flags 
|=  CSETBLOCK_MAGIC_1B
;  
2332                  res 
=  mfCGetBlock ( baseblock 
+  i
,  memBlock
,  flags
);  
2334                          PrintAndLog ( "Can't read block.  %d  error= %d " ,  baseblock 
+  i
,  res
);  
2338                  PrintAndLog ( "block  %3 d data: %s " ,  baseblock 
+  i
,  sprint_hex ( memBlock
,  16 ));  
2344  int  CmdHF14AMfCSave ( const char  * Cmd
) {  
2347          char  filename
[ FILE_PATH_SIZE
] = { 0x00 };  
2348          char  *  fnameptr 
=  filename
;  
2349          uint8_t  fillFromEmulator 
=  0 ;  
2350          uint8_t  buf
[ 256 ] = { 0x00 };  
2351          int  i
,  j
,  len
,  flags
,  gen 
=  0 ,  numblock 
=  64 ;  
2353          // memset(filename, 0, sizeof(filename));  
2354          // memset(buf, 0, sizeof(buf));  
2356          if  ( param_getchar ( Cmd
,  0 ) ==  'h' ) {  
2357                  PrintAndLog ( "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`" );  
2358                  PrintAndLog ( "or into emulator memory (option `e`). 4K card: (option `4`)" );  
2359                  PrintAndLog ( "Usage:  hf mf csave [file name w/o `.eml`][e][4]" );  
2360                  PrintAndLog ( "Sample: hf mf csave " );  
2361                  PrintAndLog ( "        hf mf csave filename" );  
2362                  PrintAndLog ( "        hf mf csave e" );  
2363                  PrintAndLog ( "        hf mf csave 4" );  
2364                  PrintAndLog ( "        hf mf csave filename 4" );  
2365                  PrintAndLog ( "        hf mf csave e 4" );  
2369          char  ctmp 
=  param_getchar ( Cmd
,  0 );  
2370          if  ( ctmp 
==  'e'  ||  ctmp 
==  'E' )  fillFromEmulator 
=  1 ;  
2371          if  ( ctmp 
==  '4' )  numblock 
=  256 ;  
2372          ctmp 
=  param_getchar ( Cmd
,  1 );  
2373          if  ( ctmp 
==  '4' )  numblock 
=  256 ;  
2375          gen 
=  mfCIdentify ();  
2376          PrintAndLog ( "Saving magic mifare  %d K" ,  numblock 
==  256  ?  4 : 1 );  
2378          if  ( fillFromEmulator
) {  
2379                  // put into emulator  
2380                  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;  
2381                  for  ( i 
=  0 ;  i 
<  numblock
;  i
++) {  
2382                          if  ( i 
==  1 )  flags 
=  0 ;  
2383                          if  ( i 
==  numblock 
-  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;  
2386                                  /* generation 1b magic card */  
2387                                  flags 
|=  CSETBLOCK_MAGIC_1B
;  
2389                          if  ( mfCGetBlock ( i
,  buf
,  flags
)) {  
2390                                  PrintAndLog ( "Cant get block:  %d " ,  i
);  
2394                          if  ( mfEmlSetMem ( buf
,  i
,  1 )) {  
2395                                  PrintAndLog ( "Cant set emul block:  %d " ,  i
);  
2401                  param_getstr ( Cmd
,  0 ,  filename
,  sizeof ( filename
));  
2403                  len 
=  strlen ( filename
);  
2404                  if  ( len 
>  FILE_PATH_SIZE 
-  5 )  len 
=  FILE_PATH_SIZE 
-  5 ;  
2406                  ctmp 
=  param_getchar ( Cmd
,  0 );  
2407                  if  ( len 
<  1  || ( ctmp 
==  '4' )) {  
2410                          flags 
=  CSETBLOCK_SINGLE_OPER
;  
2412                                  /* generation 1b magic card */  
2413                                  flags 
|=  CSETBLOCK_MAGIC_1B
;  
2414                          if  ( mfCGetBlock ( 0 ,  buf
,  flags
)) {  
2415                                  PrintAndLog ( "Cant get block:  %d " ,  0 );  
2416                                  len 
=  sprintf ( fnameptr
,  "dump" );  
2420                                  for  ( j 
=  0 ;  j 
<  7 ;  j
++,  fnameptr 
+=  2 )  
2421                                          sprintf ( fnameptr
,  " %0 2x" ,  buf
[ j
]);  
2424                          //memcpy(filename, Cmd, len);  
2428                  sprintf ( fnameptr
,  ".eml" );  
2431                  f 
=  fopen ( filename
,  "w+" );  
2434                          PrintAndLog ( "File not found or locked." );  
2439                  flags 
=  CSETBLOCK_INIT_FIELD 
+  CSETBLOCK_WUPC
;  
2440                  for  ( i 
=  0 ;  i 
<  numblock
;  i
++) {  
2441                          if  ( i 
==  1 )  flags 
=  0 ;  
2442                          if  ( i 
==  numblock 
-  1 )  flags 
=  CSETBLOCK_HALT 
+  CSETBLOCK_RESET_FIELD
;  
2445                                  /* generation 1b magic card */  
2446                                  flags 
|=  CSETBLOCK_MAGIC_1B
;  
2447                          if  ( mfCGetBlock ( i
,  buf
,  flags
)) {  
2448                                  PrintAndLog ( "Cant get block:  %d " ,  i
);  
2451                          for  ( j 
=  0 ;  j 
<  16 ;  j
++)  
2452                                  fprintf ( f
,  " %0 2x" ,  buf
[ j
]);  
2457                  PrintAndLog ( "Saved to file:  %s " ,  filename
);  
2464  int  CmdHF14AMfSniff ( const char  * Cmd
){  
2466          bool  wantLogToFile 
=  0 ;  
2467          bool  wantDecrypt 
=  0 ;  
2468          //bool wantSaveToEml = 0; TODO  
2469          bool  wantSaveToEmlFile 
=  0 ;  
2480          uint8_t  atqa
[ 2 ] = { 0x00 };  
2483          uint8_t  * buf 
=  NULL
;  
2484          uint16_t  bufsize 
=  0 ;  
2485          uint8_t  * bufPtr 
=  NULL
;  
2488          char  ctmp 
=  param_getchar ( Cmd
,  0 );  
2489          if  (  ctmp 
==  'h'  ||  ctmp 
==  'H'  ) {  
2490                  PrintAndLog ( "It continuously gets data from the field and saves it to: log, emulator, emulator file." );  
2491                  PrintAndLog ( "You can specify:" );  
2492                  PrintAndLog ( "    l - save encrypted sequence to logfile `uid.log`" );  
2493                  PrintAndLog ( "    d - decrypt sequence and put it to log file `uid.log`" );  
2494                  PrintAndLog ( " n/a   e - decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory" );  
2495                  PrintAndLog ( "    f - decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`" );  
2496                  PrintAndLog ( "Usage:  hf mf sniff [l][d][e][f]" );  
2497                  PrintAndLog ( "  sample: hf mf sniff l d e" );  
2501          for  ( int  i 
=  0 ;  i 
<  4 ;  i
++) {  
2502                  ctmp 
=  param_getchar ( Cmd
,  i
);  
2503                  if  ( ctmp 
==  'l'  ||  ctmp 
==  'L' )  wantLogToFile 
=  true ;  
2504                  if  ( ctmp 
==  'd'  ||  ctmp 
==  'D' )  wantDecrypt 
=  true ;  
2505                  //if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO  
2506                  if  ( ctmp 
==  'f'  ||  ctmp 
==  'F' )  wantSaveToEmlFile 
=  true ;  
2509          printf ( "------------------------------------------------------------------------- \n " );  
2510          printf ( "Executing command.  \n " );  
2511          printf ( "Press the key on the proxmark3 device to abort both proxmark3 and client. \n " );  
2512          printf ( "Press the key on pc keyboard to abort the client. \n " );  
2513          printf ( "------------------------------------------------------------------------- \n " );  
2515          UsbCommand c 
= { CMD_MIFARE_SNIFFER
, { 0 ,  0 ,  0 }};  
2516          clearCommandBuffer ();  
2525                          printf ( " \n aborted via keyboard! \n " );  
2530                  if  ( WaitForResponseTimeoutW ( CMD_ACK
, & resp
,  2000 ,  false )) {  
2531                          res 
=  resp
. arg
[ 0 ] &  0xff ;  
2532                          uint16_t  traceLen 
=  resp
. arg
[ 1 ];  
2535                          if  ( res 
==  0 ) {                                                          // we are done  
2539                          if  ( res 
==  1 ) {                                                          // there is (more) data to be transferred  
2540                                  if  ( pckNum 
==  0 ) {                                               // first packet, (re)allocate necessary buffer  
2541                                          if  ( traceLen 
>  bufsize 
||  buf 
==  NULL
) {  
2543                                                  if  ( buf 
==  NULL
) {                               // not yet allocated  
2544                                                          p 
=  malloc ( traceLen
);  
2545                                                  }  else  {                                                 // need more memory  
2546                                                          p 
=  realloc ( buf
,  traceLen
);  
2549                                                          PrintAndLog ( "Cannot allocate memory for trace" );  
2557                                          memset ( buf
,  0x00 ,  traceLen
);  
2559                                  memcpy ( bufPtr
,  resp
. d
. asBytes
,  len
);  
2564                          if  ( res 
==  2 ) {                                                          // received all data, start displaying  
2565                                  blockLen 
=  bufPtr 
-  buf
;  
2568                                  PrintAndLog ( "received trace len:  %d  packages:  %d " ,  blockLen
,  pckNum
);  
2569                                  while  ( bufPtr 
-  buf 
<  blockLen
) {  
2570                                          bufPtr 
+=  6 ;                                             // skip (void) timing information  
2571                                          len 
= *(( uint16_t  *) bufPtr
);  
2578                                          parlen 
= ( len 
-  1 ) /  8  +  1 ;  
2580                                          if  (( len 
==  14 ) && ( bufPtr
[ 0 ] ==  0xff ) && ( bufPtr
[ 1 ] ==  0xff ) && ( bufPtr
[ 12 ] ==  0xff ) && ( bufPtr
[ 13 ] ==  0xff )) {  
2581                                                  memcpy ( uid
,  bufPtr 
+  2 ,  7 );  
2582                                                  memcpy ( atqa
,  bufPtr 
+  2  +  7 ,  2 );  
2583                                                  uid_len 
= ( atqa
[ 0 ] &  0xC0 ) ==  0x40  ?  7  :  4 ;  
2585                                                  PrintAndLog ( "tag select uid: %s  atqa:0x %0 2x %0 2x sak:0x %0 2x" ,  
2586                                                          sprint_hex ( uid 
+ ( 7  -  uid_len
),  uid_len
),  
2590                                                  if  ( wantLogToFile 
||  wantDecrypt
) {  
2591                                                          FillFileNameByUID ( logHexFileName
,  uid 
+ ( 7  -  uid_len
),  ".log" ,  uid_len
);  
2592                                                          AddLogCurrentDT ( logHexFileName
);  
2595                                                          mfTraceInit ( uid
,  atqa
,  sak
,  wantSaveToEmlFile
);  
2597                                                  oddparitybuf ( bufPtr
,  len
,  parity
);  
2598                                                  PrintAndLog ( " %s ( %d ): %s  [ %s ] c[ %s ] %c " ,   
2599                                                          isTag 
?  "TAG" : "RDR" ,   
2601                                                          sprint_hex ( bufPtr
,  len
),   
2602                                                          printBitsPar ( bufPtr 
+  len
,  len
),   
2603                                                          printBitsPar ( parity
,  len
),  
2604                                                          memcmp ( bufPtr 
+  len
,  parity
,  len 
/  8  +  1 ) ?  '!'  :  ' ' );  
2606                                                          AddLogHex ( logHexFileName
,  isTag 
?  "TAG: " : "RDR: " ,  bufPtr
,  len
);  
2608                                                          mfTraceDecode ( bufPtr
,  len
,  bufPtr
[ len
],  wantSaveToEmlFile
);  
2612                                          bufPtr 
+=  parlen
;        // ignore parity  
2621          msleep ( 300 );  // wait for exiting arm side.  
2622          PrintAndLog ( "Done." );  
2626  //needs nt, ar, at, Data to decrypt  
2627  int  CmdDecryptTraceCmds ( const char  * Cmd
){  
2630          param_gethex_ex ( Cmd
, 3 , data
,& len
);  
2631          return  tryDecryptWord ( param_get32ex ( Cmd
, 0 , 0 , 16 ), param_get32ex ( Cmd
, 1 , 0 , 16 ), param_get32ex ( Cmd
, 2 , 0 , 16 ), data
, len
/ 2 );  
2634  static  command_t CommandTable
[] =  
2636    { "help" ,              CmdHelp
,                  1 ,  "This help" },  
2637    { "dbg" ,               CmdHF14AMfDbg
,            0 ,  "Set default debug mode" },  
2638    { "rdbl" ,              CmdHF14AMfRdBl
,           0 ,  "Read MIFARE classic block" },  
2639    { "rdsc" ,              CmdHF14AMfRdSc
,           0 ,  "Read MIFARE classic sector" },  
2640    { "dump" ,              CmdHF14AMfDump
,           0 ,  "Dump MIFARE classic tag to binary file" },  
2641    { "restore" ,           CmdHF14AMfRestore
,        0 ,  "Restore MIFARE classic binary file to BLANK tag" },  
2642    { "wrbl" ,              CmdHF14AMfWrBl
,           0 ,  "Write MIFARE classic block" },  
2643    { "chk" ,               CmdHF14AMfChk
,            0 ,  "Test block keys" },  
2644    { "mifare" ,            CmdHF14AMifare
,           0 ,  "Read parity error messages." },  
2645    { "hardnested" ,        CmdHF14AMfNestedHard
,     0 ,  "Nested attack for hardened Mifare cards" },  
2646    { "nested" ,            CmdHF14AMfNested
,         0 ,  "Test nested authentication" },  
2647    { "sniff" ,             CmdHF14AMfSniff
,          0 ,  "Sniff card-reader communication" },  
2648    { "sim" ,               CmdHF14AMf1kSim
,          0 ,  "Simulate MIFARE card" },  
2649    { "eclr" ,              CmdHF14AMfEClear
,         0 ,  "Clear simulator memory block" },  
2650    { "eget" ,              CmdHF14AMfEGet
,           0 ,  "Get simulator memory block" },  
2651    { "eset" ,              CmdHF14AMfESet
,           0 ,  "Set simulator memory block" },  
2652    { "eload" ,             CmdHF14AMfELoad
,          0 ,  "Load from file emul dump" },  
2653    { "esave" ,             CmdHF14AMfESave
,          0 ,  "Save to file emul dump" },  
2654    { "ecfill" ,            CmdHF14AMfECFill
,         0 ,  "Fill simulator memory with help of keys from simulator" },  
2655    { "ekeyprn" ,           CmdHF14AMfEKeyPrn
,        0 ,  "Print keys from simulator memory" },  
2656    { "cwipe" ,             CmdHF14AMfCWipe
,          0 ,  "Wipe magic Chinese card" },  
2657    { "csetuid" ,           CmdHF14AMfCSetUID
,        0 ,  "Set UID for magic Chinese card" },  
2658    { "csetblk" ,           CmdHF14AMfCSetBlk
,        0 ,  "Write block - Magic Chinese card" },  
2659    { "cgetblk" ,           CmdHF14AMfCGetBlk
,        0 ,  "Read block - Magic Chinese card" },  
2660    { "cgetsc" ,            CmdHF14AMfCGetSc
,         0 ,  "Read sector - Magic Chinese card" },  
2661    { "cload" ,             CmdHF14AMfCLoad
,          0 ,  "Load dump into magic Chinese card" },  
2662    { "csave" ,             CmdHF14AMfCSave
,          0 ,  "Save dump from magic Chinese card into file or emulator" },  
2663    { "decrypt" ,           CmdDecryptTraceCmds
,      1 ,  "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace" },  
2664    { NULL
,                NULL
,                     0 ,  NULL
}  
2667  int  CmdHFMF ( const char  * Cmd
)  
2670          WaitForResponseTimeout ( CMD_ACK
, NULL
, 100 );  
2672    CmdsParse ( CommandTable
,  Cmd
);  
2676  int  CmdHelp ( const char  * Cmd
)  
2678    CmdsHelp ( CommandTable
);