2011-06-10 21:35:10 +08:00
//-----------------------------------------------------------------------------
2012-07-07 00:19:05 +08:00
// Copyright (C) 2011,2012 Merlok
2011-06-10 21:35:10 +08:00
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency MIFARE commands
//-----------------------------------------------------------------------------
2017-05-29 16:56:37 +08:00
# include "cmdhfmf.h"
2017-02-23 05:45:00 +08:00
# include <inttypes.h>
2017-03-12 22:06:27 +08:00
# include <string.h>
2017-03-07 03:07:02 +08:00
# include <stdio.h>
# include <stdlib.h>
2017-03-12 22:06:27 +08:00
# include <ctype.h>
2018-06-03 20:25:20 +08:00
# include "comms.h"
2017-03-07 03:07:02 +08:00
# include "cmdmain.h"
2017-05-29 16:56:37 +08:00
# include "cmdhfmfhard.h"
2018-02-09 22:50:55 +08:00
# include "parity.h"
2017-03-07 03:07:02 +08:00
# include "util.h"
2017-06-08 04:35:20 +08:00
# include "util_posix.h"
2017-05-29 16:56:37 +08:00
# include "usb_cmd.h"
2017-03-07 03:07:02 +08:00
# include "ui.h"
# include "mifarehost.h"
# include "mifare.h"
2017-03-24 01:06:14 +08:00
# include "mfkey.h"
2018-01-03 04:28:13 +08:00
# include "hardnested/hardnested_bf_core.h"
2018-10-11 04:34:04 +08:00
# include "cliparser/cliparser.h"
# include "cmdhf14a.h"
# include <polarssl/aes.h>
2017-03-07 03:07:02 +08:00
# define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
2011-06-10 21:35:10 +08:00
static int CmdHelp ( const char * Cmd ) ;
int CmdHF14AMifare ( const char * Cmd )
{
2017-03-12 01:32:53 +08:00
int isOK = 0 ;
uint64_t key = 0 ;
isOK = mfDarkside ( & key ) ;
switch ( isOK ) {
case - 1 : PrintAndLog ( " Button pressed. Aborted. " ) ; return 1 ;
case - 2 : PrintAndLog ( " Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). " ) ; return 1 ;
case - 3 : PrintAndLog ( " Card is not vulnerable to Darkside attack (its random number generator is not predictable). " ) ; return 1 ;
case - 4 : PrintAndLog ( " Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown " ) ;
2017-05-29 16:56:37 +08:00
PrintAndLog ( " generating polynomial with 16 effective bits only, but shows unexpected behaviour. " ) ; return 1 ;
2017-03-12 01:32:53 +08:00
case - 5 : PrintAndLog ( " Aborted via keyboard. " ) ; return 1 ;
default : PrintAndLog ( " Found valid key:%012 " PRIx64 " \n " , key ) ;
2012-05-30 11:45:55 +08:00
}
2017-07-12 21:58:32 +08:00
2015-01-05 22:51:27 +08:00
PrintAndLog ( " " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
2017-03-12 01:32:53 +08:00
2011-06-10 21:35:10 +08:00
int CmdHF14AMfWrBl ( const char * Cmd )
{
uint8_t blockNo = 0 ;
uint8_t keyType = 0 ;
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t bldata [ 16 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
char cmdp = 0x00 ;
if ( strlen ( Cmd ) < 3 ) {
PrintAndLog ( " Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)> " ) ;
PrintAndLog ( " sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-10 21:35:10 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
cmdp = param_getchar ( Cmd , 1 ) ;
if ( cmdp = = 0x00 ) {
PrintAndLog ( " Key type must be A or B " ) ;
return 1 ;
}
if ( cmdp ! = ' A ' & & cmdp ! = ' a ' ) keyType = 1 ;
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
PrintAndLog ( " Key must include 12 HEX symbols " ) ;
return 1 ;
}
if ( param_gethex ( Cmd , 3 , bldata , 32 ) ) {
PrintAndLog ( " Block data must include 32 HEX symbols " ) ;
return 1 ;
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --block no:%d, key type:%c, key:%s " , blockNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
2011-06-10 21:35:10 +08:00
PrintAndLog ( " --data: %s " , sprint_hex ( bldata , 16 ) ) ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
UsbCommand c = { CMD_MIFARE_WRITEBL , { blockNo , keyType , 0 } } ;
memcpy ( c . d . asBytes , key , 6 ) ;
memcpy ( c . d . asBytes + 10 , bldata , 16 ) ;
SendCommand ( & c ) ;
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
2011-06-10 21:35:10 +08:00
PrintAndLog ( " isOk:%02x " , isOK ) ;
} else {
PrintAndLog ( " Command execute timeout " ) ;
}
2014-02-01 05:17:34 +08:00
return 0 ;
}
int CmdHF14AMfRdBl ( const char * Cmd )
{
uint8_t blockNo = 0 ;
2011-06-10 21:35:10 +08:00
uint8_t keyType = 0 ;
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
char cmdp = 0x00 ;
if ( strlen ( Cmd ) < 3 ) {
PrintAndLog ( " Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)> " ) ;
PrintAndLog ( " sample: hf mf rdbl 0 A FFFFFFFFFFFF " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-10 21:35:10 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
cmdp = param_getchar ( Cmd , 1 ) ;
if ( cmdp = = 0x00 ) {
PrintAndLog ( " Key type must be A or B " ) ;
return 1 ;
}
if ( cmdp ! = ' A ' & & cmdp ! = ' a ' ) keyType = 1 ;
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
PrintAndLog ( " Key must include 12 HEX symbols " ) ;
return 1 ;
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --block no:%d, key type:%c, key:%s " , blockNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
UsbCommand c = { CMD_MIFARE_READBL , { blockNo , keyType , 0 } } ;
memcpy ( c . d . asBytes , key , 6 ) ;
SendCommand ( & c ) ;
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2014-09-11 01:04:50 +08:00
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
uint8_t * data = resp . d . asBytes ;
2011-06-10 21:35:10 +08:00
if ( isOK )
PrintAndLog ( " isOk:%02x data:%s " , isOK , sprint_hex ( data , 16 ) ) ;
else
PrintAndLog ( " isOk:%02x " , isOK ) ;
} else {
PrintAndLog ( " Command execute timeout " ) ;
}
2014-02-01 05:17:34 +08:00
return 0 ;
}
int CmdHF14AMfRdSc ( const char * Cmd )
{
int i ;
2011-06-10 21:35:10 +08:00
uint8_t sectorNo = 0 ;
uint8_t keyType = 0 ;
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t isOK = 0 ;
2014-09-11 01:04:50 +08:00
uint8_t * data = NULL ;
2011-06-10 21:35:10 +08:00
char cmdp = 0x00 ;
if ( strlen ( Cmd ) < 3 ) {
PrintAndLog ( " Usage: hf mf rdsc <sector number> <key A/B> <key (12 hex symbols)> " ) ;
PrintAndLog ( " sample: hf mf rdsc 0 A FFFFFFFFFFFF " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-10 21:35:10 +08:00
sectorNo = param_get8 ( Cmd , 0 ) ;
2014-09-11 01:04:50 +08:00
if ( sectorNo > 39 ) {
PrintAndLog ( " Sector number must be less than 40 " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
cmdp = param_getchar ( Cmd , 1 ) ;
2014-09-11 01:04:50 +08:00
if ( cmdp ! = ' a ' & & cmdp ! = ' A ' & & cmdp ! = ' b ' & & cmdp ! = ' B ' ) {
2011-06-10 21:35:10 +08:00
PrintAndLog ( " Key type must be A or B " ) ;
return 1 ;
}
if ( cmdp ! = ' A ' & & cmdp ! = ' a ' ) keyType = 1 ;
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
PrintAndLog ( " Key must include 12 HEX symbols " ) ;
return 1 ;
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --sector no:%d key type:%c key:%s " , sectorNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
UsbCommand c = { CMD_MIFARE_READSC , { sectorNo , keyType , 0 } } ;
2011-06-10 21:35:10 +08:00
memcpy ( c . d . asBytes , key , 6 ) ;
2014-09-11 01:04:50 +08:00
SendCommand ( & c ) ;
2011-06-10 21:35:10 +08:00
PrintAndLog ( " " ) ;
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
isOK = resp . arg [ 0 ] & 0xff ;
data = resp . d . asBytes ;
2011-06-10 21:35:10 +08:00
PrintAndLog ( " isOk:%02x " , isOK ) ;
2014-09-11 01:04:50 +08:00
if ( isOK ) {
for ( i = 0 ; i < ( sectorNo < 32 ? 3 : 15 ) ; i + + ) {
PrintAndLog ( " data : %s " , sprint_hex ( data + i * 16 , 16 ) ) ;
2011-06-10 21:35:10 +08:00
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " trailer: %s " , sprint_hex ( data + ( sectorNo < 32 ? 3 : 15 ) * 16 , 16 ) ) ;
}
2011-06-10 21:35:10 +08:00
} else {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Command execute timeout " ) ;
2011-06-10 21:35:10 +08:00
}
2014-09-11 01:04:50 +08:00
return 0 ;
}
2011-06-10 21:35:10 +08:00
2014-09-11 01:04:50 +08:00
uint8_t FirstBlockOfSector ( uint8_t sectorNo )
{
if ( sectorNo < 32 ) {
return sectorNo * 4 ;
2011-06-10 21:35:10 +08:00
} else {
2014-09-11 01:04:50 +08:00
return 32 * 4 + ( sectorNo - 32 ) * 16 ;
2011-06-10 21:35:10 +08:00
}
}
2014-09-11 01:04:50 +08:00
uint8_t NumBlocksPerSector ( uint8_t sectorNo )
{
if ( sectorNo < 32 ) {
return 4 ;
} else {
return 16 ;
}
}
2017-10-05 19:37:51 +08:00
static int ParamCardSizeSectors ( const char c ) {
int numBlocks = 16 ;
switch ( c ) {
case ' 0 ' : numBlocks = 5 ; break ;
case ' 2 ' : numBlocks = 32 ; break ;
case ' 4 ' : numBlocks = 40 ; break ;
default : numBlocks = 16 ;
}
return numBlocks ;
}
static int ParamCardSizeBlocks ( const char c ) {
int numBlocks = 16 * 4 ;
switch ( c ) {
case ' 0 ' : numBlocks = 5 * 4 ; break ;
case ' 2 ' : numBlocks = 32 * 4 ; break ;
case ' 4 ' : numBlocks = 32 * 4 + 8 * 16 ; break ;
default : numBlocks = 16 * 4 ;
}
return numBlocks ;
}
2012-05-30 11:45:55 +08:00
int CmdHF14AMfDump ( const char * Cmd )
2011-08-30 17:52:18 +08:00
{
2014-09-11 01:04:50 +08:00
uint8_t sectorNo , blockNo ;
2017-07-12 21:58:32 +08:00
2012-05-30 11:45:55 +08:00
uint8_t keyA [ 40 ] [ 6 ] ;
uint8_t keyB [ 40 ] [ 6 ] ;
uint8_t rights [ 40 ] [ 4 ] ;
2014-09-12 02:58:34 +08:00
uint8_t carddata [ 256 ] [ 16 ] ;
2014-09-11 01:04:50 +08:00
uint8_t numSectors = 16 ;
2017-07-12 21:58:32 +08:00
2011-08-30 17:52:18 +08:00
FILE * fin ;
FILE * fout ;
2017-07-12 21:58:32 +08:00
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
2014-09-11 01:04:50 +08:00
char cmdp = param_getchar ( Cmd , 0 ) ;
2017-10-05 19:37:51 +08:00
numSectors = ParamCardSizeSectors ( cmdp ) ;
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
if ( strlen ( Cmd ) > 1 | | cmdp = = ' h ' | | cmdp = = ' H ' ) {
PrintAndLog ( " Usage: hf mf dump [card memory] " ) ;
PrintAndLog ( " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " " ) ;
PrintAndLog ( " Samples: hf mf dump " ) ;
PrintAndLog ( " hf mf dump 4 " ) ;
return 0 ;
}
2017-07-12 21:58:32 +08:00
2011-08-30 17:52:18 +08:00
if ( ( fin = fopen ( " dumpkeys.bin " , " rb " ) ) = = NULL ) {
2012-05-30 11:45:55 +08:00
PrintAndLog ( " Could not find file dumpkeys.bin " ) ;
2011-08-30 17:52:18 +08:00
return 1 ;
}
2017-07-12 21:58:32 +08:00
2015-01-05 22:51:27 +08:00
// Read keys A from file
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2017-02-23 16:40:12 +08:00
size_t bytes_read = fread ( keyA [ sectorNo ] , 1 , 6 , fin ) ;
if ( bytes_read ! = 6 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " File reading error. " ) ;
2014-10-28 05:33:37 +08:00
fclose ( fin ) ;
2013-03-14 23:03:04 +08:00
return 2 ;
2014-09-11 01:04:50 +08:00
}
2011-08-30 17:52:18 +08:00
}
2017-07-12 21:58:32 +08:00
2015-01-05 22:51:27 +08:00
// Read keys B from file
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2017-02-23 16:40:12 +08:00
size_t bytes_read = fread ( keyB [ sectorNo ] , 1 , 6 , fin ) ;
if ( bytes_read ! = 6 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " File reading error. " ) ;
2014-10-28 05:33:37 +08:00
fclose ( fin ) ;
2013-03-14 23:03:04 +08:00
return 2 ;
2014-09-11 01:04:50 +08:00
}
2011-08-30 17:52:18 +08:00
}
2017-07-12 21:58:32 +08:00
2014-10-28 05:33:37 +08:00
fclose ( fin ) ;
2014-09-11 01:04:50 +08:00
2011-08-30 17:52:18 +08:00
PrintAndLog ( " |-----------------------------------------| " ) ;
PrintAndLog ( " |------ Reading sector access bits...-----| " ) ;
PrintAndLog ( " |-----------------------------------------| " ) ;
2017-03-01 00:09:42 +08:00
uint8_t tries = 0 ;
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2017-07-12 21:58:32 +08:00
for ( tries = 0 ; tries < 3 ; tries + + ) {
2017-03-01 00:09:42 +08:00
UsbCommand c = { CMD_MIFARE_READBL , { FirstBlockOfSector ( sectorNo ) + NumBlocksPerSector ( sectorNo ) - 1 , 0 , 0 } } ;
memcpy ( c . d . asBytes , keyA [ sectorNo ] , 6 ) ;
SendCommand ( & c ) ;
2011-08-30 17:52:18 +08:00
2017-03-01 00:09:42 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
uint8_t * data = resp . d . asBytes ;
if ( isOK ) {
rights [ sectorNo ] [ 0 ] = ( ( data [ 7 ] & 0x10 ) > > 2 ) | ( ( data [ 8 ] & 0x1 ) < < 1 ) | ( ( data [ 8 ] & 0x10 ) > > 4 ) ; // C1C2C3 for data area 0
rights [ sectorNo ] [ 1 ] = ( ( data [ 7 ] & 0x20 ) > > 3 ) | ( ( data [ 8 ] & 0x2 ) < < 0 ) | ( ( data [ 8 ] & 0x20 ) > > 5 ) ; // C1C2C3 for data area 1
rights [ sectorNo ] [ 2 ] = ( ( data [ 7 ] & 0x40 ) > > 4 ) | ( ( data [ 8 ] & 0x4 ) > > 1 ) | ( ( data [ 8 ] & 0x40 ) > > 6 ) ; // C1C2C3 for data area 2
rights [ sectorNo ] [ 3 ] = ( ( data [ 7 ] & 0x80 ) > > 5 ) | ( ( data [ 8 ] & 0x8 ) > > 2 ) | ( ( data [ 8 ] & 0x80 ) > > 7 ) ; // C1C2C3 for sector trailer
break ;
} else if ( tries = = 2 ) { // on last try set defaults
PrintAndLog ( " Could not get access rights for sector %2d. Trying with defaults... " , sectorNo ) ;
rights [ sectorNo ] [ 0 ] = rights [ sectorNo ] [ 1 ] = rights [ sectorNo ] [ 2 ] = 0x00 ;
rights [ sectorNo ] [ 3 ] = 0x01 ;
}
2014-09-11 01:04:50 +08:00
} else {
2017-03-01 00:09:42 +08:00
PrintAndLog ( " Command execute timeout when trying to read access rights for sector %2d. Trying with defaults... " , sectorNo ) ;
2014-09-12 13:45:04 +08:00
rights [ sectorNo ] [ 0 ] = rights [ sectorNo ] [ 1 ] = rights [ sectorNo ] [ 2 ] = 0x00 ;
rights [ sectorNo ] [ 3 ] = 0x01 ;
2011-08-30 17:52:18 +08:00
}
}
}
2017-07-12 21:58:32 +08:00
2011-08-30 17:52:18 +08:00
PrintAndLog ( " |-----------------------------------------| " ) ;
PrintAndLog ( " |----- Dumping all blocks to file... -----| " ) ;
PrintAndLog ( " |-----------------------------------------| " ) ;
2017-07-12 21:58:32 +08:00
2014-09-12 02:58:34 +08:00
bool isOK = true ;
for ( sectorNo = 0 ; isOK & & sectorNo < numSectors ; sectorNo + + ) {
for ( blockNo = 0 ; isOK & & blockNo < NumBlocksPerSector ( sectorNo ) ; blockNo + + ) {
2014-09-11 01:04:50 +08:00
bool received = false ;
2017-07-12 21:58:32 +08:00
for ( tries = 0 ; tries < 3 ; tries + + ) {
if ( blockNo = = NumBlocksPerSector ( sectorNo ) - 1 ) { // sector trailer. At least the Access Conditions can always be read with key A.
2014-09-12 02:58:34 +08:00
UsbCommand c = { CMD_MIFARE_READBL , { FirstBlockOfSector ( sectorNo ) + blockNo , 0 , 0 } } ;
memcpy ( c . d . asBytes , keyA [ sectorNo ] , 6 ) ;
SendCommand ( & c ) ;
received = WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ;
2017-03-01 00:09:42 +08:00
} else { // data block. Check if it can be read with key A or key B
uint8_t data_area = sectorNo < 32 ? blockNo : blockNo / 5 ;
if ( ( rights [ sectorNo ] [ data_area ] = = 0x03 ) | | ( rights [ sectorNo ] [ data_area ] = = 0x05 ) ) { // only key B would work
UsbCommand c = { CMD_MIFARE_READBL , { FirstBlockOfSector ( sectorNo ) + blockNo , 1 , 0 } } ;
memcpy ( c . d . asBytes , keyB [ sectorNo ] , 6 ) ;
SendCommand ( & c ) ;
received = WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ;
} else if ( rights [ sectorNo ] [ data_area ] = = 0x07 ) { // no key would work
isOK = false ;
PrintAndLog ( " Access rights do not allow reading of sector %2d block %3d " , sectorNo , blockNo ) ;
tries = 2 ;
} else { // key A would work
UsbCommand c = { CMD_MIFARE_READBL , { FirstBlockOfSector ( sectorNo ) + blockNo , 0 , 0 } } ;
memcpy ( c . d . asBytes , keyA [ sectorNo ] , 6 ) ;
SendCommand ( & c ) ;
received = WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ;
}
}
if ( received ) {
isOK = resp . arg [ 0 ] & 0xff ;
if ( isOK ) break ;
2011-08-30 17:52:18 +08:00
}
}
2012-12-05 07:39:18 +08:00
if ( received ) {
2014-09-12 02:58:34 +08:00
isOK = resp . arg [ 0 ] & 0xff ;
2012-12-05 07:39:18 +08:00
uint8_t * data = resp . d . asBytes ;
2014-09-11 01:04:50 +08:00
if ( blockNo = = NumBlocksPerSector ( sectorNo ) - 1 ) { // sector trailer. Fill in the keys.
data [ 0 ] = ( keyA [ sectorNo ] [ 0 ] ) ;
data [ 1 ] = ( keyA [ sectorNo ] [ 1 ] ) ;
data [ 2 ] = ( keyA [ sectorNo ] [ 2 ] ) ;
data [ 3 ] = ( keyA [ sectorNo ] [ 3 ] ) ;
data [ 4 ] = ( keyA [ sectorNo ] [ 4 ] ) ;
data [ 5 ] = ( keyA [ sectorNo ] [ 5 ] ) ;
data [ 10 ] = ( keyB [ sectorNo ] [ 0 ] ) ;
data [ 11 ] = ( keyB [ sectorNo ] [ 1 ] ) ;
data [ 12 ] = ( keyB [ sectorNo ] [ 2 ] ) ;
data [ 13 ] = ( keyB [ sectorNo ] [ 3 ] ) ;
data [ 14 ] = ( keyB [ sectorNo ] [ 4 ] ) ;
data [ 15 ] = ( keyB [ sectorNo ] [ 5 ] ) ;
2011-09-02 16:33:45 +08:00
}
2011-08-30 17:52:18 +08:00
if ( isOK ) {
2014-09-12 02:58:34 +08:00
memcpy ( carddata [ FirstBlockOfSector ( sectorNo ) + blockNo ] , data , 16 ) ;
PrintAndLog ( " Successfully read block %2d of sector %2d. " , blockNo , sectorNo ) ;
2014-09-11 01:04:50 +08:00
} else {
PrintAndLog ( " Could not read block %2d of sector %2d " , blockNo , sectorNo ) ;
2014-09-12 02:58:34 +08:00
break ;
2011-08-30 17:52:18 +08:00
}
}
else {
2014-09-12 02:58:34 +08:00
isOK = false ;
PrintAndLog ( " Command execute timeout when trying to read block %2d of sector %2d. " , blockNo , sectorNo ) ;
break ;
2011-08-30 17:52:18 +08:00
}
}
}
2014-09-12 02:58:34 +08:00
if ( isOK ) {
2017-07-12 21:58:32 +08:00
if ( ( fout = fopen ( " dumpdata.bin " , " wb " ) ) = = NULL ) {
2014-09-12 02:58:34 +08:00
PrintAndLog ( " Could not create file name dumpdata.bin " ) ;
return 1 ;
}
uint16_t numblocks = FirstBlockOfSector ( numSectors - 1 ) + NumBlocksPerSector ( numSectors - 1 ) ;
fwrite ( carddata , 1 , 16 * numblocks , fout ) ;
fclose ( fout ) ;
PrintAndLog ( " Dumped %d blocks (%d bytes) to file dumpdata.bin " , numblocks , 16 * numblocks ) ;
}
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
return 0 ;
2011-08-30 17:52:18 +08:00
}
2012-05-30 11:45:55 +08:00
int CmdHF14AMfRestore ( const char * Cmd )
2011-08-30 17:52:18 +08:00
{
2014-09-11 01:04:50 +08:00
uint8_t sectorNo , blockNo ;
2011-08-30 17:52:18 +08:00
uint8_t keyType = 0 ;
2015-04-08 19:31:04 +08:00
uint8_t key [ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
2015-01-08 05:00:29 +08:00
uint8_t bldata [ 16 ] = { 0x00 } ;
2014-09-11 01:04:50 +08:00
uint8_t keyA [ 40 ] [ 6 ] ;
uint8_t keyB [ 40 ] [ 6 ] ;
uint8_t numSectors ;
2017-07-12 21:58:32 +08:00
2011-08-30 17:52:18 +08:00
FILE * fdump ;
FILE * fkeys ;
2014-09-11 01:04:50 +08:00
char cmdp = param_getchar ( Cmd , 0 ) ;
switch ( cmdp ) {
case ' 0 ' : numSectors = 5 ; break ;
2017-07-12 21:58:32 +08:00
case ' 1 ' :
2014-09-11 01:04:50 +08:00
case ' \0 ' : numSectors = 16 ; break ;
case ' 2 ' : numSectors = 32 ; break ;
case ' 4 ' : numSectors = 40 ; break ;
default : numSectors = 16 ;
2017-07-12 21:58:32 +08:00
}
2014-09-11 01:04:50 +08:00
if ( strlen ( Cmd ) > 1 | | cmdp = = ' h ' | | cmdp = = ' H ' ) {
PrintAndLog ( " Usage: hf mf restore [card memory] " ) ;
PrintAndLog ( " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " " ) ;
PrintAndLog ( " Samples: hf mf restore " ) ;
PrintAndLog ( " hf mf restore 4 " ) ;
return 0 ;
}
2011-08-30 17:52:18 +08:00
if ( ( fkeys = fopen ( " dumpkeys.bin " , " rb " ) ) = = NULL ) {
2012-05-30 11:45:55 +08:00
PrintAndLog ( " Could not find file dumpkeys.bin " ) ;
2011-08-30 17:52:18 +08:00
return 1 ;
}
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2017-02-23 16:40:12 +08:00
size_t bytes_read = fread ( keyA [ sectorNo ] , 1 , 6 , fkeys ) ;
if ( bytes_read ! = 6 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " File reading error (dumpkeys.bin). " ) ;
2015-01-09 00:51:52 +08:00
fclose ( fkeys ) ;
2013-03-14 23:03:04 +08:00
return 2 ;
2014-09-11 01:04:50 +08:00
}
2011-08-30 17:52:18 +08:00
}
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2017-02-23 16:40:12 +08:00
size_t bytes_read = fread ( keyB [ sectorNo ] , 1 , 6 , fkeys ) ;
if ( bytes_read ! = 6 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " File reading error (dumpkeys.bin). " ) ;
2015-01-09 00:51:52 +08:00
fclose ( fkeys ) ;
2013-03-14 23:03:04 +08:00
return 2 ;
2014-09-11 01:04:50 +08:00
}
2011-08-30 17:52:18 +08:00
}
2015-01-08 05:00:29 +08:00
2014-10-31 04:49:18 +08:00
fclose ( fkeys ) ;
2014-09-12 02:58:34 +08:00
2015-01-08 05:00:29 +08:00
if ( ( fdump = fopen ( " dumpdata.bin " , " rb " ) ) = = NULL ) {
PrintAndLog ( " Could not find file dumpdata.bin " ) ;
return 1 ;
2017-07-12 21:58:32 +08:00
}
2011-09-06 17:16:32 +08:00
PrintAndLog ( " Restoring dumpdata.bin to card " ) ;
2011-08-30 17:52:18 +08:00
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
for ( blockNo = 0 ; blockNo < NumBlocksPerSector ( sectorNo ) ; blockNo + + ) {
UsbCommand c = { CMD_MIFARE_WRITEBL , { FirstBlockOfSector ( sectorNo ) + blockNo , keyType , 0 } } ;
2011-08-30 17:52:18 +08:00
memcpy ( c . d . asBytes , key , 6 ) ;
2017-07-12 21:58:32 +08:00
2017-02-23 16:40:12 +08:00
size_t bytes_read = fread ( bldata , 1 , 16 , fdump ) ;
if ( bytes_read ! = 16 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " File reading error (dumpdata.bin). " ) ;
2014-10-31 04:49:18 +08:00
fclose ( fdump ) ;
2014-09-11 01:04:50 +08:00
return 2 ;
}
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
if ( blockNo = = NumBlocksPerSector ( sectorNo ) - 1 ) { // sector trailer
bldata [ 0 ] = ( keyA [ sectorNo ] [ 0 ] ) ;
bldata [ 1 ] = ( keyA [ sectorNo ] [ 1 ] ) ;
bldata [ 2 ] = ( keyA [ sectorNo ] [ 2 ] ) ;
bldata [ 3 ] = ( keyA [ sectorNo ] [ 3 ] ) ;
bldata [ 4 ] = ( keyA [ sectorNo ] [ 4 ] ) ;
bldata [ 5 ] = ( keyA [ sectorNo ] [ 5 ] ) ;
bldata [ 10 ] = ( keyB [ sectorNo ] [ 0 ] ) ;
bldata [ 11 ] = ( keyB [ sectorNo ] [ 1 ] ) ;
bldata [ 12 ] = ( keyB [ sectorNo ] [ 2 ] ) ;
bldata [ 13 ] = ( keyB [ sectorNo ] [ 3 ] ) ;
bldata [ 14 ] = ( keyB [ sectorNo ] [ 4 ] ) ;
bldata [ 15 ] = ( keyB [ sectorNo ] [ 5 ] ) ;
2017-07-12 21:58:32 +08:00
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Writing to block %3d: %s " , FirstBlockOfSector ( sectorNo ) + blockNo , sprint_hex ( bldata , 16 ) ) ;
2017-07-12 21:58:32 +08:00
2011-08-30 17:52:18 +08:00
memcpy ( c . d . asBytes + 10 , bldata , 16 ) ;
SendCommand ( & c ) ;
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
2014-09-11 01:04:50 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2012-12-05 07:39:18 +08:00
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
2011-08-30 17:52:18 +08:00
PrintAndLog ( " isOk:%02x " , isOK ) ;
} else {
PrintAndLog ( " Command execute timeout " ) ;
}
}
}
2017-07-12 21:58:32 +08:00
2011-08-30 17:52:18 +08:00
fclose ( fdump ) ;
return 0 ;
}
2017-10-19 03:44:59 +08:00
//----------------------------------------------
// Nested
//----------------------------------------------
static void parseParamTDS ( const char * Cmd , const uint8_t indx , bool * paramT , bool * paramD , uint8_t * timeout ) {
char ctmp3 [ 3 ] = { 0 } ;
int len = param_getlength ( Cmd , indx ) ;
if ( len > 0 & & len < 4 ) {
2017-11-12 05:08:57 +08:00
param_getstr ( Cmd , indx , ctmp3 , sizeof ( ctmp3 ) ) ;
2017-10-19 03:44:59 +08:00
* paramT | = ( ctmp3 [ 0 ] = = ' t ' | | ctmp3 [ 0 ] = = ' T ' ) ;
* paramD | = ( ctmp3 [ 0 ] = = ' d ' | | ctmp3 [ 0 ] = = ' D ' ) ;
bool paramS1 = * paramT | | * paramD ;
// slow and very slow
if ( ctmp3 [ 0 ] = = ' s ' | | ctmp3 [ 0 ] = = ' S ' | | ctmp3 [ 1 ] = = ' s ' | | ctmp3 [ 1 ] = = ' S ' ) {
* timeout = 11 ; // slow
if ( ! paramS1 & & ( ctmp3 [ 1 ] = = ' s ' | | ctmp3 [ 1 ] = = ' S ' ) ) {
* timeout = 53 ; // very slow
}
if ( paramS1 & & ( ctmp3 [ 2 ] = = ' s ' | | ctmp3 [ 2 ] = = ' S ' ) ) {
* timeout = 53 ; // very slow
}
}
}
}
2011-06-10 21:35:10 +08:00
int CmdHF14AMfNested ( const char * Cmd )
{
int i , j , res , iterations ;
2017-03-07 03:07:02 +08:00
sector_t * e_sector = NULL ;
2011-06-10 21:35:10 +08:00
uint8_t blockNo = 0 ;
uint8_t keyType = 0 ;
uint8_t trgBlockNo = 0 ;
uint8_t trgKeyType = 0 ;
2014-09-11 01:04:50 +08:00
uint8_t SectorsCnt = 0 ;
2011-06-10 21:35:10 +08:00
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2017-11-13 01:08:57 +08:00
uint8_t keyBlock [ MifareDefaultKeysSize * 6 ] ;
2011-06-10 21:35:10 +08:00
uint64_t key64 = 0 ;
2017-10-19 03:44:59 +08:00
// timeout in units. (ms * 106)/10 or us*0.0106
uint8_t btimeout14a = MF_CHKKEYS_DEFTIMEOUT ; // fast by default
2017-10-05 19:37:51 +08:00
bool autosearchKey = false ;
2017-07-12 21:58:32 +08:00
2017-10-05 19:37:51 +08:00
bool transferToEml = false ;
2014-09-11 01:04:50 +08:00
bool createDumpFile = false ;
2011-08-30 17:52:18 +08:00
FILE * fkeys ;
2011-09-01 16:13:18 +08:00
uint8_t standart [ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
uint8_t tempkey [ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
char cmdp , ctmp ;
if ( strlen ( Cmd ) < 3 ) {
PrintAndLog ( " Usage: " ) ;
2017-10-19 03:44:59 +08:00
PrintAndLog ( " all sectors: hf mf nested <card memory> <block number> <key A/B> <key (12 hex symbols)> [t|d|s|ss] " ) ;
PrintAndLog ( " all sectors autosearch key: hf mf nested <card memory> * [t|d|s|ss] " ) ;
2011-06-25 21:03:01 +08:00
PrintAndLog ( " one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)> " ) ;
PrintAndLog ( " <target block number> <target key A/B> [t] " ) ;
2017-10-05 19:37:51 +08:00
PrintAndLog ( " " ) ;
2011-06-10 21:35:10 +08:00
PrintAndLog ( " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K " ) ;
2017-10-05 19:37:51 +08:00
PrintAndLog ( " t - transfer keys to emulator memory " ) ;
PrintAndLog ( " d - write keys to binary file dumpkeys.bin " ) ;
2017-10-19 03:44:59 +08:00
PrintAndLog ( " s - Slow (1ms) check keys (required by some non standard cards) " ) ;
PrintAndLog ( " ss - Very slow (5ms) check keys " ) ;
2011-06-10 21:35:10 +08:00
PrintAndLog ( " " ) ;
PrintAndLog ( " sample1: hf mf nested 1 0 A FFFFFFFFFFFF " ) ;
2014-09-12 02:58:34 +08:00
PrintAndLog ( " sample2: hf mf nested 1 0 A FFFFFFFFFFFF t " ) ;
PrintAndLog ( " sample3: hf mf nested 1 0 A FFFFFFFFFFFF d " ) ;
PrintAndLog ( " sample4: hf mf nested o 0 A FFFFFFFFFFFF 4 A " ) ;
2017-10-05 19:37:51 +08:00
PrintAndLog ( " sample5: hf mf nested 1 * t " ) ;
2017-10-19 03:44:59 +08:00
PrintAndLog ( " sample6: hf mf nested 1 * ss " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2017-10-05 19:37:51 +08:00
// <card memory>
2011-06-10 21:35:10 +08:00
cmdp = param_getchar ( Cmd , 0 ) ;
2017-10-05 19:37:51 +08:00
if ( cmdp = = ' o ' | | cmdp = = ' O ' ) {
cmdp = ' o ' ;
SectorsCnt = 1 ;
} else {
SectorsCnt = ParamCardSizeSectors ( cmdp ) ;
2011-06-10 21:35:10 +08:00
}
2017-10-05 19:37:51 +08:00
// <block number>. number or autosearch key (*)
if ( param_getchar ( Cmd , 1 ) = = ' * ' ) {
autosearchKey = true ;
2017-07-12 21:58:32 +08:00
2017-10-19 03:44:59 +08:00
parseParamTDS ( Cmd , 2 , & transferToEml , & createDumpFile , & btimeout14a ) ;
2017-07-12 21:58:32 +08:00
2017-10-19 03:44:59 +08:00
PrintAndLog ( " --nested. sectors:%2d, block no:*, eml:%c, dmp=%c checktimeout=%d us " ,
SectorsCnt , transferToEml ? ' y ' : ' n ' , createDumpFile ? ' y ' : ' n ' , ( ( int ) btimeout14a * 10000 ) / 106 ) ;
2017-10-05 19:37:51 +08:00
} else {
blockNo = param_get8 ( Cmd , 1 ) ;
2017-07-12 21:58:32 +08:00
2017-10-05 19:37:51 +08:00
ctmp = param_getchar ( Cmd , 2 ) ;
2014-09-11 01:04:50 +08:00
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
2017-10-05 19:37:51 +08:00
PrintAndLog ( " Key type must be A or B " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2017-10-05 19:37:51 +08:00
2017-07-12 21:58:32 +08:00
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' )
2017-10-05 19:37:51 +08:00
keyType = 1 ;
if ( param_gethex ( Cmd , 3 , key , 12 ) ) {
PrintAndLog ( " Key must include 12 HEX symbols " ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
2017-10-05 19:37:51 +08:00
// check if we can authenticate to sector
res = mfCheckKeys ( blockNo , keyType , true , 1 , key , & key64 ) ;
if ( res ) {
PrintAndLog ( " Can't authenticate to block:%3d key type:%c key:%s " , blockNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
return 3 ;
2011-06-10 21:35:10 +08:00
}
2011-06-18 02:39:54 +08:00
2017-10-05 19:37:51 +08:00
// one sector nested
if ( cmdp = = ' o ' ) {
trgBlockNo = param_get8 ( Cmd , 4 ) ;
2017-07-12 21:58:32 +08:00
2017-10-05 19:37:51 +08:00
ctmp = param_getchar ( Cmd , 5 ) ;
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
PrintAndLog ( " Target key type must be A or B " ) ;
return 1 ;
}
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' )
trgKeyType = 1 ;
2017-07-12 21:58:32 +08:00
2017-10-19 03:44:59 +08:00
parseParamTDS ( Cmd , 6 , & transferToEml , & createDumpFile , & btimeout14a ) ;
2017-10-05 19:37:51 +08:00
} else {
2017-10-19 03:44:59 +08:00
parseParamTDS ( Cmd , 4 , & transferToEml , & createDumpFile , & btimeout14a ) ;
2017-10-05 19:37:51 +08:00
}
2017-10-19 03:44:59 +08:00
PrintAndLog ( " --nested. sectors:%2d, block no:%3d, key type:%c, eml:%c, dmp=%c checktimeout=%d us " ,
SectorsCnt , blockNo , keyType ? ' B ' : ' A ' , transferToEml ? ' y ' : ' n ' , createDumpFile ? ' y ' : ' n ' , ( ( int ) btimeout14a * 10000 ) / 106 ) ;
2017-10-05 19:37:51 +08:00
}
// one-sector nested
if ( cmdp = = ' o ' ) { // ------------------------------------ one sector working
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --target block no:%3d, target key type:%c " , trgBlockNo , trgKeyType ? ' B ' : ' A ' ) ;
2015-06-24 13:48:36 +08:00
int16_t isOK = mfnested ( blockNo , keyType , key , trgBlockNo , trgKeyType , keyBlock , true ) ;
if ( isOK ) {
switch ( isOK ) {
case - 1 : PrintAndLog ( " Error: No response from Proxmark. \n " ) ; break ;
case - 2 : PrintAndLog ( " Button pressed. Aborted. \n " ) ; break ;
case - 3 : PrintAndLog ( " Tag isn't vulnerable to Nested Attack (random numbers are not predictable). \n " ) ; break ;
default : PrintAndLog ( " Unknown Error. \n " ) ;
}
2011-06-10 21:35:10 +08:00
return 2 ;
}
2013-09-15 17:33:17 +08:00
key64 = bytes_to_num ( keyBlock , 6 ) ;
if ( key64 ) {
2017-02-23 05:45:00 +08:00
PrintAndLog ( " Found valid key:%012 " PRIx64 , key64 ) ;
2011-06-18 02:39:54 +08:00
// transfer key to the emulator
if ( transferToEml ) {
2014-09-11 01:04:50 +08:00
uint8_t sectortrailer ;
if ( trgBlockNo < 32 * 4 ) { // 4 block sector
2018-02-01 15:09:14 +08:00
sectortrailer = trgBlockNo | 0x03 ;
2014-09-11 01:04:50 +08:00
} else { // 16 block sector
2018-02-01 15:09:14 +08:00
sectortrailer = trgBlockNo | 0x0f ;
2014-09-11 01:04:50 +08:00
}
mfEmlGetMem ( keyBlock , sectortrailer , 1 ) ;
2017-07-12 21:58:32 +08:00
2011-06-18 02:39:54 +08:00
if ( ! trgKeyType )
num_to_bytes ( key64 , 6 , keyBlock ) ;
else
num_to_bytes ( key64 , 6 , & keyBlock [ 10 ] ) ;
2017-07-12 21:58:32 +08:00
mfEmlSetMem ( keyBlock , sectortrailer , 1 ) ;
2017-10-05 19:37:51 +08:00
PrintAndLog ( " Key transferred to emulator memory. " ) ;
2011-06-18 02:39:54 +08:00
}
} else {
2011-06-10 21:35:10 +08:00
PrintAndLog ( " No valid key found " ) ;
2011-06-18 02:39:54 +08:00
}
2011-09-01 16:13:18 +08:00
}
else { // ------------------------------------ multiple sectors working
2017-03-12 22:06:27 +08:00
uint64_t msclock1 ;
msclock1 = msclock ( ) ;
2013-09-15 17:33:17 +08:00
2017-03-07 03:07:02 +08:00
e_sector = calloc ( SectorsCnt , sizeof ( sector_t ) ) ;
2011-06-10 21:35:10 +08:00
if ( e_sector = = NULL ) return 1 ;
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
//test current key and additional standard keys first
2017-10-16 03:19:34 +08:00
for ( int defaultKeyCounter = 0 ; defaultKeyCounter < MifareDefaultKeysSize ; defaultKeyCounter + + ) {
num_to_bytes ( MifareDefaultKeys [ defaultKeyCounter ] , 6 , ( uint8_t * ) ( keyBlock + defaultKeyCounter * 6 ) ) ;
}
2011-06-10 21:35:10 +08:00
PrintAndLog ( " Testing known keys. Sector count=%d " , SectorsCnt ) ;
2017-11-13 01:08:57 +08:00
mfCheckKeysSec ( SectorsCnt , 2 , btimeout14a , true , MifareDefaultKeysSize , keyBlock , e_sector ) ;
2017-10-05 19:37:51 +08:00
// get known key from array
bool keyFound = false ;
if ( autosearchKey ) {
for ( i = 0 ; i < SectorsCnt ; i + + ) {
for ( j = 0 ; j < 2 ; j + + ) {
if ( e_sector [ i ] . foundKey [ j ] ) {
// get known key
blockNo = i * 4 ;
keyType = j ;
num_to_bytes ( e_sector [ i ] . Key [ j ] , 6 , key ) ;
keyFound = true ;
break ;
}
}
if ( keyFound ) break ;
}
// Can't found a key....
if ( ! keyFound ) {
PrintAndLog ( " Can't found any of the known keys. " ) ;
2018-06-13 14:13:20 +08:00
free ( e_sector ) ;
2017-10-05 19:37:51 +08:00
return 4 ;
}
PrintAndLog ( " --auto key. block no:%3d, key type:%c key:%s " , blockNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
}
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
// nested sectors
iterations = 0 ;
PrintAndLog ( " nested... " ) ;
2013-09-15 17:33:17 +08:00
bool calibrate = true ;
2011-06-10 21:35:10 +08:00
for ( i = 0 ; i < NESTED_SECTOR_RETRY ; i + + ) {
2014-09-11 01:04:50 +08:00
for ( uint8_t sectorNo = 0 ; sectorNo < SectorsCnt ; sectorNo + + ) {
2017-07-12 21:58:32 +08:00
for ( trgKeyType = 0 ; trgKeyType < 2 ; trgKeyType + + ) {
2014-09-11 01:04:50 +08:00
if ( e_sector [ sectorNo ] . foundKey [ trgKeyType ] ) continue ;
2013-09-15 17:33:17 +08:00
PrintAndLog ( " ----------------------------------------------- " ) ;
2015-06-24 13:48:36 +08:00
int16_t isOK = mfnested ( blockNo , keyType , key , FirstBlockOfSector ( sectorNo ) , trgKeyType , keyBlock , calibrate ) ;
if ( isOK ) {
switch ( isOK ) {
case - 1 : PrintAndLog ( " Error: No response from Proxmark. \n " ) ; break ;
case - 2 : PrintAndLog ( " Button pressed. Aborted. \n " ) ; break ;
case - 3 : PrintAndLog ( " Tag isn't vulnerable to Nested Attack (random numbers are not predictable). \n " ) ; break ;
default : PrintAndLog ( " Unknown Error. \n " ) ;
}
2015-01-05 22:51:27 +08:00
free ( e_sector ) ;
2015-06-24 13:48:36 +08:00
return 2 ;
} else {
2013-09-15 17:33:17 +08:00
calibrate = false ;
}
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
iterations + + ;
2013-09-15 17:33:17 +08:00
key64 = bytes_to_num ( keyBlock , 6 ) ;
if ( key64 ) {
2017-02-23 05:45:00 +08:00
PrintAndLog ( " Found valid key:%012 " PRIx64 , key64 ) ;
2014-09-11 01:04:50 +08:00
e_sector [ sectorNo ] . foundKey [ trgKeyType ] = 1 ;
e_sector [ sectorNo ] . Key [ trgKeyType ] = key64 ;
2017-10-16 03:19:34 +08:00
// try to check this key as a key to the other sectors
2017-10-19 03:44:59 +08:00
mfCheckKeysSec ( SectorsCnt , 2 , btimeout14a , true , 1 , keyBlock , e_sector ) ;
2011-06-10 21:35:10 +08:00
}
}
2013-09-15 17:33:17 +08:00
}
2011-06-10 21:35:10 +08:00
}
2017-10-05 19:37:51 +08:00
// print nested statistic
PrintAndLog ( " \n \n ----------------------------------------------- \n Nested statistic: \n Iterations count: %d " , iterations ) ;
PrintAndLog ( " Time in nested: %1.3f (%1.3f sec per key) " , ( ( float ) ( msclock ( ) - msclock1 ) ) / 1000.0 , ( ( float ) ( msclock ( ) - msclock1 ) ) / iterations / 1000.0 ) ;
// print result
2011-06-10 21:35:10 +08:00
PrintAndLog ( " |---|----------------|---|----------------|---| " ) ;
PrintAndLog ( " |sec|key A |res|key B |res| " ) ;
PrintAndLog ( " |---|----------------|---|----------------|---| " ) ;
for ( i = 0 ; i < SectorsCnt ; i + + ) {
2017-02-23 05:45:00 +08:00
PrintAndLog ( " |%03d| %012 " PRIx64 " | %d | %012 " PRIx64 " | %d | " , i ,
2011-06-10 21:35:10 +08:00
e_sector [ i ] . Key [ 0 ] , e_sector [ i ] . foundKey [ 0 ] , e_sector [ i ] . Key [ 1 ] , e_sector [ i ] . foundKey [ 1 ] ) ;
}
PrintAndLog ( " |---|----------------|---|----------------|---| " ) ;
2017-07-12 21:58:32 +08:00
2017-10-05 19:37:51 +08:00
// transfer keys to the emulator memory
2011-06-18 02:39:54 +08:00
if ( transferToEml ) {
for ( i = 0 ; i < SectorsCnt ; i + + ) {
2014-09-11 01:04:50 +08:00
mfEmlGetMem ( keyBlock , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ;
2011-06-18 02:39:54 +08:00
if ( e_sector [ i ] . foundKey [ 0 ] )
2011-06-22 09:25:16 +08:00
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , keyBlock ) ;
2011-06-18 02:39:54 +08:00
if ( e_sector [ i ] . foundKey [ 1 ] )
num_to_bytes ( e_sector [ i ] . Key [ 1 ] , 6 , & keyBlock [ 10 ] ) ;
2014-09-11 01:04:50 +08:00
mfEmlSetMem ( keyBlock , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ;
2017-07-12 21:58:32 +08:00
}
2017-10-05 19:37:51 +08:00
PrintAndLog ( " Keys transferred to emulator memory. " ) ;
2011-06-18 02:39:54 +08:00
}
2017-07-12 21:58:32 +08:00
2011-09-01 16:13:18 +08:00
// Create dump file
2011-08-30 17:52:18 +08:00
if ( createDumpFile ) {
2017-07-12 21:58:32 +08:00
if ( ( fkeys = fopen ( " dumpkeys.bin " , " wb " ) ) = = NULL ) {
2012-05-30 11:45:55 +08:00
PrintAndLog ( " Could not create file dumpkeys.bin " ) ;
2011-08-30 17:52:18 +08:00
free ( e_sector ) ;
return 1 ;
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Printing keys to binary file dumpkeys.bin... " ) ;
for ( i = 0 ; i < SectorsCnt ; i + + ) {
2011-09-01 16:13:18 +08:00
if ( e_sector [ i ] . foundKey [ 0 ] ) {
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , tempkey ) ;
fwrite ( tempkey , 1 , 6 , fkeys ) ;
}
else {
fwrite ( & standart , 1 , 6 , fkeys ) ;
}
2011-08-30 17:52:18 +08:00
}
2014-09-11 01:04:50 +08:00
for ( i = 0 ; i < SectorsCnt ; i + + ) {
2011-09-01 16:13:18 +08:00
if ( e_sector [ i ] . foundKey [ 1 ] ) {
num_to_bytes ( e_sector [ i ] . Key [ 1 ] , 6 , tempkey ) ;
fwrite ( tempkey , 1 , 6 , fkeys ) ;
}
else {
fwrite ( & standart , 1 , 6 , fkeys ) ;
}
2011-08-30 17:52:18 +08:00
}
fclose ( fkeys ) ;
}
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
free ( e_sector ) ;
}
return 0 ;
}
2017-05-29 16:56:37 +08:00
int CmdHF14AMfNestedHard ( const char * Cmd )
{
uint8_t blockNo = 0 ;
uint8_t keyType = 0 ;
uint8_t trgBlockNo = 0 ;
uint8_t trgKeyType = 0 ;
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t trgkey [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2017-07-12 21:58:32 +08:00
2017-05-29 16:56:37 +08:00
char ctmp ;
ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp ! = ' R ' & & ctmp ! = ' r ' & & ctmp ! = ' T ' & & ctmp ! = ' t ' & & strlen ( Cmd ) < 20 ) {
PrintAndLog ( " Usage: " ) ;
PrintAndLog ( " hf mf hardnested <block number> <key A|B> <key (12 hex symbols)> " ) ;
PrintAndLog ( " <target block number> <target key A|B> [known target key (12 hex symbols)] [w] [s] " ) ;
PrintAndLog ( " or hf mf hardnested r [known target key] " ) ;
PrintAndLog ( " " ) ;
PrintAndLog ( " Options: " ) ;
PrintAndLog ( " w: Acquire nonces and write them to binary file nonces.bin " ) ;
PrintAndLog ( " s: Slower acquisition (required by some non standard cards) " ) ;
PrintAndLog ( " r: Read nonces.bin and start attack " ) ;
2018-01-03 04:28:13 +08:00
PrintAndLog ( " iX: set type of SIMD instructions. Without this flag programs autodetect it. " ) ;
PrintAndLog ( " i5: AVX512 " ) ;
PrintAndLog ( " i2: AVX2 " ) ;
PrintAndLog ( " ia: AVX " ) ;
PrintAndLog ( " is: SSE2 " ) ;
PrintAndLog ( " im: MMX " ) ;
PrintAndLog ( " in: none (use CPU regular instruction set) " ) ;
2017-05-29 16:56:37 +08:00
PrintAndLog ( " " ) ;
PrintAndLog ( " sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A " ) ;
PrintAndLog ( " sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w " ) ;
PrintAndLog ( " sample3: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w s " ) ;
PrintAndLog ( " sample4: hf mf hardnested r " ) ;
PrintAndLog ( " " ) ;
PrintAndLog ( " Add the known target key to check if it is present in the remaining key space: " ) ;
PrintAndLog ( " sample5: hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2017-05-29 16:56:37 +08:00
bool know_target_key = false ;
bool nonce_file_read = false ;
bool nonce_file_write = false ;
bool slow = false ;
int tests = 0 ;
2017-07-12 21:58:32 +08:00
2018-01-03 04:28:13 +08:00
uint16_t iindx = 0 ;
2017-05-29 16:56:37 +08:00
if ( ctmp = = ' R ' | | ctmp = = ' r ' ) {
nonce_file_read = true ;
2018-01-03 04:28:13 +08:00
iindx = 1 ;
2017-05-29 16:56:37 +08:00
if ( ! param_gethex ( Cmd , 1 , trgkey , 12 ) ) {
know_target_key = true ;
2018-01-03 04:28:13 +08:00
iindx = 2 ;
2017-05-29 16:56:37 +08:00
}
} else if ( ctmp = = ' T ' | | ctmp = = ' t ' ) {
tests = param_get32ex ( Cmd , 1 , 100 , 10 ) ;
2018-01-03 04:28:13 +08:00
iindx = 2 ;
2017-05-29 16:56:37 +08:00
if ( ! param_gethex ( Cmd , 2 , trgkey , 12 ) ) {
know_target_key = true ;
2018-01-03 04:28:13 +08:00
iindx = 3 ;
2017-05-29 16:56:37 +08:00
}
} else {
blockNo = param_get8 ( Cmd , 0 ) ;
ctmp = param_getchar ( Cmd , 1 ) ;
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
PrintAndLog ( " Key type must be A or B " ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' ) {
2017-05-29 16:56:37 +08:00
keyType = 1 ;
}
2017-07-12 21:58:32 +08:00
2017-05-29 16:56:37 +08:00
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
PrintAndLog ( " Key must include 12 HEX symbols " ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
2017-05-29 16:56:37 +08:00
trgBlockNo = param_get8 ( Cmd , 3 ) ;
ctmp = param_getchar ( Cmd , 4 ) ;
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
PrintAndLog ( " Target key type must be A or B " ) ;
return 1 ;
}
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' ) {
trgKeyType = 1 ;
}
uint16_t i = 5 ;
if ( ! param_gethex ( Cmd , 5 , trgkey , 12 ) ) {
know_target_key = true ;
i + + ;
}
2018-01-03 04:28:13 +08:00
iindx = i ;
2017-05-29 16:56:37 +08:00
while ( ( ctmp = param_getchar ( Cmd , i ) ) ) {
if ( ctmp = = ' s ' | | ctmp = = ' S ' ) {
slow = true ;
} else if ( ctmp = = ' w ' | | ctmp = = ' W ' ) {
nonce_file_write = true ;
2018-01-03 04:28:13 +08:00
} else if ( param_getlength ( Cmd , i ) = = 2 & & ctmp = = ' i ' ) {
iindx = i ;
2017-05-29 16:56:37 +08:00
} else {
2018-01-03 04:28:13 +08:00
PrintAndLog ( " Possible options are w , s and/or iX " ) ;
2017-05-29 16:56:37 +08:00
return 1 ;
}
i + + ;
}
}
2018-01-03 04:28:13 +08:00
SetSIMDInstr ( SIMD_AUTO ) ;
if ( iindx > 0 ) {
while ( ( ctmp = param_getchar ( Cmd , iindx ) ) ) {
if ( param_getlength ( Cmd , iindx ) = = 2 & & ctmp = = ' i ' ) {
switch ( param_getchar_indx ( Cmd , 1 , iindx ) ) {
case ' 5 ' :
SetSIMDInstr ( SIMD_AVX512 ) ;
break ;
case ' 2 ' :
SetSIMDInstr ( SIMD_AVX2 ) ;
break ;
case ' a ' :
SetSIMDInstr ( SIMD_AVX ) ;
break ;
case ' s ' :
SetSIMDInstr ( SIMD_SSE2 ) ;
break ;
case ' m ' :
SetSIMDInstr ( SIMD_MMX ) ;
break ;
case ' n ' :
SetSIMDInstr ( SIMD_NONE ) ;
break ;
default :
PrintAndLog ( " Unknown SIMD type. %c " , param_getchar_indx ( Cmd , 1 , iindx ) ) ;
return 1 ;
}
}
iindx + + ;
}
}
2017-05-29 16:56:37 +08:00
2017-07-12 21:58:32 +08:00
PrintAndLog ( " --target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d " ,
trgBlockNo ,
2017-05-29 16:56:37 +08:00
trgKeyType ? ' B ' : ' A ' ,
trgkey [ 0 ] , trgkey [ 1 ] , trgkey [ 2 ] , trgkey [ 3 ] , trgkey [ 4 ] , trgkey [ 5 ] ,
know_target_key ? " " : " (not set) " ,
nonce_file_write ? " write " : nonce_file_read ? " read " : " none " ,
slow ? " Yes " : " No " ,
tests ) ;
int16_t isOK = mfnestedhard ( blockNo , keyType , key , trgBlockNo , trgKeyType , know_target_key ? trgkey : NULL , nonce_file_read , nonce_file_write , slow , tests ) ;
if ( isOK ) {
switch ( isOK ) {
case 1 : PrintAndLog ( " Error: No response from Proxmark. \n " ) ; break ;
case 2 : PrintAndLog ( " Button pressed. Aborted. \n " ) ; break ;
default : break ;
}
return 2 ;
}
return 0 ;
}
2011-06-10 21:35:10 +08:00
int CmdHF14AMfChk ( const char * Cmd )
{
2014-10-28 04:46:04 +08:00
if ( strlen ( Cmd ) < 3 ) {
2017-10-16 03:19:34 +08:00
PrintAndLog ( " Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d|s|ss] [<key (12 hex symbols)>] [<dic (*.dic)>] " ) ;
2014-10-28 04:46:04 +08:00
PrintAndLog ( " * - all sectors " ) ;
PrintAndLog ( " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K " ) ;
PrintAndLog ( " d - write keys to binary file \n " ) ;
2015-01-21 04:48:39 +08:00
PrintAndLog ( " t - write keys to emulator memory " ) ;
2017-10-16 03:19:34 +08:00
PrintAndLog ( " s - slow execute. timeout 1ms " ) ;
PrintAndLog ( " ss- very slow execute. timeout 5ms " ) ;
2014-10-28 04:46:04 +08:00
PrintAndLog ( " sample: hf mf chk 0 A 1234567890ab keys.dic " ) ;
PrintAndLog ( " hf mf chk *1 ? t " ) ;
2015-01-21 04:48:39 +08:00
PrintAndLog ( " hf mf chk *1 ? d " ) ;
2017-10-16 03:19:34 +08:00
PrintAndLog ( " hf mf chk *1 ? s " ) ;
PrintAndLog ( " hf mf chk *1 ? dss " ) ;
2014-10-28 04:46:04 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2014-10-28 04:46:04 +08:00
2012-05-30 11:45:55 +08:00
FILE * f ;
2015-01-08 05:00:29 +08:00
char filename [ FILE_PATH_SIZE ] = { 0 } ;
2012-06-07 17:24:49 +08:00
char buf [ 13 ] ;
2012-05-30 11:45:55 +08:00
uint8_t * keyBlock = NULL , * p ;
2017-06-12 21:07:00 +08:00
uint16_t stKeyBlock = 20 ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
int i , res ;
int keycnt = 0 ;
char ctmp = 0x00 ;
2017-12-28 19:29:30 +08:00
int clen = 0 ;
2017-10-16 03:19:34 +08:00
char ctmp3 [ 3 ] = { 0x00 } ;
2011-06-10 21:35:10 +08:00
uint8_t blockNo = 0 ;
2017-10-16 03:19:34 +08:00
uint8_t SectorsCnt = 0 ;
2011-06-10 21:35:10 +08:00
uint8_t keyType = 0 ;
uint64_t key64 = 0 ;
2017-10-16 03:19:34 +08:00
uint32_t timeout14a = 0 ; // timeout in us
bool param3InUse = false ;
2017-07-12 21:58:32 +08:00
2012-05-30 11:45:55 +08:00
int transferToEml = 0 ;
int createDumpFile = 0 ;
2017-10-16 03:19:34 +08:00
sector_t * e_sector = NULL ;
2011-06-10 21:35:10 +08:00
2012-05-30 11:45:55 +08:00
keyBlock = calloc ( stKeyBlock , 6 ) ;
if ( keyBlock = = NULL ) return 1 ;
2017-10-16 03:19:34 +08:00
int defaultKeysSize = MifareDefaultKeysSize ;
for ( int defaultKeyCounter = 0 ; defaultKeyCounter < defaultKeysSize ; defaultKeyCounter + + ) {
num_to_bytes ( MifareDefaultKeys [ defaultKeyCounter ] , 6 , ( uint8_t * ) ( keyBlock + defaultKeyCounter * 6 ) ) ;
2014-02-28 02:10:12 +08:00
}
2017-07-12 21:58:32 +08:00
2012-05-30 11:45:55 +08:00
if ( param_getchar ( Cmd , 0 ) = = ' * ' ) {
2017-10-05 19:37:51 +08:00
SectorsCnt = ParamCardSizeSectors ( param_getchar ( Cmd + 1 , 0 ) ) ;
2012-05-30 11:45:55 +08:00
}
else
blockNo = param_get8 ( Cmd , 0 ) ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
ctmp = param_getchar ( Cmd , 1 ) ;
2017-12-28 19:29:30 +08:00
clen = param_getlength ( Cmd , 1 ) ;
if ( clen = = 1 ) {
switch ( ctmp ) {
case ' a ' : case ' A ' :
keyType = 0 ;
break ;
case ' b ' : case ' B ' :
keyType = 1 ;
break ;
case ' ? ' :
keyType = 2 ;
break ;
default :
PrintAndLog ( " Key type must be A , B or ? " ) ;
free ( keyBlock ) ;
return 1 ;
} ;
}
2017-07-12 21:58:32 +08:00
2017-10-16 03:19:34 +08:00
// transfer to emulator & create dump file
2012-05-30 11:45:55 +08:00
ctmp = param_getchar ( Cmd , 2 ) ;
2017-12-28 19:29:30 +08:00
clen = param_getlength ( Cmd , 2 ) ;
if ( clen = = 1 & & ( ctmp = = ' t ' | | ctmp = = ' T ' ) ) transferToEml = 1 ;
if ( clen = = 1 & & ( ctmp = = ' d ' | | ctmp = = ' D ' ) ) createDumpFile = 1 ;
2017-10-16 03:19:34 +08:00
param3InUse = transferToEml | createDumpFile ;
timeout14a = 500 ; // fast by default
// double parameters - ts, ds
2017-12-28 19:29:30 +08:00
clen = param_getlength ( Cmd , 2 ) ;
2017-10-16 03:19:34 +08:00
if ( clen = = 2 | | clen = = 3 ) {
2017-11-12 05:08:57 +08:00
param_getstr ( Cmd , 2 , ctmp3 , sizeof ( ctmp3 ) ) ;
2017-10-16 03:19:34 +08:00
ctmp = ctmp3 [ 1 ] ;
}
//parse
if ( ctmp = = ' s ' | | ctmp = = ' S ' ) {
timeout14a = 1000 ; // slow
if ( ! param3InUse & & clen = = 2 & & ( ctmp3 [ 1 ] = = ' s ' | | ctmp3 [ 1 ] = = ' S ' ) ) {
timeout14a = 5000 ; // very slow
}
if ( param3InUse & & clen = = 3 & & ( ctmp3 [ 2 ] = = ' s ' | | ctmp3 [ 2 ] = = ' S ' ) ) {
timeout14a = 5000 ; // very slow
}
param3InUse = true ;
}
2017-07-12 21:58:32 +08:00
2017-10-16 03:19:34 +08:00
for ( i = param3InUse ; param_getchar ( Cmd , 2 + i ) ; i + + ) {
2012-05-30 11:45:55 +08:00
if ( ! param_gethex ( Cmd , 2 + i , keyBlock + 6 * keycnt , 12 ) ) {
if ( stKeyBlock - keycnt < 2 ) {
p = realloc ( keyBlock , 6 * ( stKeyBlock + = 10 ) ) ;
if ( ! p ) {
PrintAndLog ( " Cannot allocate memory for Keys " ) ;
free ( keyBlock ) ;
return 2 ;
}
keyBlock = p ;
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " chk key[%2d] %02x%02x%02x%02x%02x%02x " , keycnt ,
2012-05-30 11:45:55 +08:00
( keyBlock + 6 * keycnt ) [ 0 ] , ( keyBlock + 6 * keycnt ) [ 1 ] , ( keyBlock + 6 * keycnt ) [ 2 ] ,
( keyBlock + 6 * keycnt ) [ 3 ] , ( keyBlock + 6 * keycnt ) [ 4 ] , ( keyBlock + 6 * keycnt ) [ 5 ] , 6 ) ;
keycnt + + ;
} else {
// May be a dic file
2017-11-12 05:08:57 +08:00
if ( param_getstr ( Cmd , 2 + i , filename , sizeof ( filename ) ) > = FILE_PATH_SIZE ) {
2012-05-30 11:45:55 +08:00
PrintAndLog ( " File name too long " ) ;
free ( keyBlock ) ;
return 2 ;
}
2017-07-12 21:58:32 +08:00
2012-05-30 11:45:55 +08:00
if ( ( f = fopen ( filename , " r " ) ) ) {
2014-02-28 02:10:12 +08:00
while ( fgets ( buf , sizeof ( buf ) , f ) ) {
2012-05-31 17:46:02 +08:00
if ( strlen ( buf ) < 12 | | buf [ 11 ] = = ' \n ' )
continue ;
2017-07-12 21:58:32 +08:00
2012-05-31 17:46:02 +08:00
while ( fgetc ( f ) ! = ' \n ' & & ! feof ( f ) ) ; //goto next line
2017-07-12 21:58:32 +08:00
2013-09-15 17:33:17 +08:00
if ( buf [ 0 ] = = ' # ' ) continue ; //The line start with # is comment, skip
2011-06-10 21:35:10 +08:00
2017-12-29 00:56:18 +08:00
if ( ! isxdigit ( ( unsigned char ) buf [ 0 ] ) ) {
2012-05-31 17:46:02 +08:00
PrintAndLog ( " File content error. '%s' must include 12 HEX symbols " , buf ) ;
2012-05-30 11:45:55 +08:00
continue ;
}
2017-07-12 21:58:32 +08:00
2012-05-31 17:46:02 +08:00
buf [ 12 ] = 0 ;
2012-05-30 11:45:55 +08:00
if ( stKeyBlock - keycnt < 2 ) {
p = realloc ( keyBlock , 6 * ( stKeyBlock + = 10 ) ) ;
if ( ! p ) {
PrintAndLog ( " Cannot allocate memory for defKeys " ) ;
free ( keyBlock ) ;
2017-02-23 16:40:12 +08:00
fclose ( f ) ;
2012-05-30 11:45:55 +08:00
return 2 ;
}
keyBlock = p ;
}
memset ( keyBlock + 6 * keycnt , 0 , 6 ) ;
2012-05-31 17:46:02 +08:00
num_to_bytes ( strtoll ( buf , NULL , 16 ) , 6 , keyBlock + 6 * keycnt ) ;
2017-02-23 05:45:00 +08:00
PrintAndLog ( " chk custom key[%2d] %012 " PRIx64 , keycnt , bytes_to_num ( keyBlock + 6 * keycnt , 6 ) ) ;
2012-05-30 11:45:55 +08:00
keycnt + + ;
2014-02-28 02:10:12 +08:00
memset ( buf , 0 , sizeof ( buf ) ) ;
2012-05-30 11:45:55 +08:00
}
2014-10-28 04:46:04 +08:00
fclose ( f ) ;
2012-05-30 11:45:55 +08:00
} else {
PrintAndLog ( " File: %s: not found or locked. " , filename ) ;
free ( keyBlock ) ;
return 1 ;
2017-07-12 21:58:32 +08:00
2012-05-30 11:45:55 +08:00
}
2011-06-10 21:35:10 +08:00
}
}
2017-07-12 21:58:32 +08:00
2017-10-16 03:19:34 +08:00
// fill with default keys
2011-06-10 21:35:10 +08:00
if ( keycnt = = 0 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " No key specified, trying default keys " ) ;
2014-02-28 02:10:12 +08:00
for ( ; keycnt < defaultKeysSize ; keycnt + + )
2014-09-11 01:04:50 +08:00
PrintAndLog ( " chk default key[%2d] %02x%02x%02x%02x%02x%02x " , keycnt ,
2014-09-12 02:58:34 +08:00
( keyBlock + 6 * keycnt ) [ 0 ] , ( keyBlock + 6 * keycnt ) [ 1 ] , ( keyBlock + 6 * keycnt ) [ 2 ] ,
( keyBlock + 6 * keycnt ) [ 3 ] , ( keyBlock + 6 * keycnt ) [ 4 ] , ( keyBlock + 6 * keycnt ) [ 5 ] , 6 ) ;
}
2017-07-12 21:58:32 +08:00
2014-09-12 02:58:34 +08:00
// initialize storage for found keys
2017-10-16 03:19:34 +08:00
e_sector = calloc ( SectorsCnt , sizeof ( sector_t ) ) ;
2018-06-13 14:13:20 +08:00
if ( e_sector = = NULL ) {
free ( keyBlock ) ;
return 1 ;
}
2017-10-16 03:19:34 +08:00
for ( uint8_t keyAB = 0 ; keyAB < 2 ; keyAB + + ) {
2014-09-12 02:58:34 +08:00
for ( uint16_t sectorNo = 0 ; sectorNo < SectorsCnt ; sectorNo + + ) {
2017-10-16 03:19:34 +08:00
e_sector [ sectorNo ] . Key [ keyAB ] = 0xffffffffffff ;
e_sector [ sectorNo ] . foundKey [ keyAB ] = 0 ;
2014-09-12 02:58:34 +08:00
}
2011-06-10 21:35:10 +08:00
}
2017-10-16 03:19:34 +08:00
printf ( " \n " ) ;
bool foundAKey = false ;
uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt ;
if ( SectorsCnt ) {
PrintAndLog ( " To cancel this operation press the button on the proxmark... " ) ;
printf ( " -- " ) ;
for ( uint32_t c = 0 ; c < keycnt ; c + = max_keys ) {
uint32_t size = keycnt - c > max_keys ? max_keys : keycnt - c ;
res = mfCheckKeysSec ( SectorsCnt , keyType , timeout14a * 1.06 / 100 , true , size , & keyBlock [ 6 * c ] , e_sector ) ; // timeout is (ms * 106)/10 or us*0.0106
2017-07-12 21:58:32 +08:00
2017-10-16 03:19:34 +08:00
if ( res ! = 1 ) {
if ( ! res ) {
printf ( " o " ) ;
foundAKey = true ;
} else {
printf ( " . " ) ;
}
} else {
printf ( " \n " ) ;
PrintAndLog ( " Command execute timeout " ) ;
}
}
} else {
int keyAB = keyType ;
do {
2013-09-15 17:33:17 +08:00
for ( uint32_t c = 0 ; c < keycnt ; c + = max_keys ) {
2017-10-16 03:19:34 +08:00
uint32_t size = keycnt - c > max_keys ? max_keys : keycnt - c ;
res = mfCheckKeys ( blockNo , keyAB & 0x01 , true , size , & keyBlock [ 6 * c ] , & key64 ) ;
2014-09-11 01:04:50 +08:00
if ( res ! = 1 ) {
2012-05-30 11:45:55 +08:00
if ( ! res ) {
2017-10-16 03:19:34 +08:00
PrintAndLog ( " Found valid key:[%d:%c]%012 " PRIx64 , blockNo , ( keyAB & 0x01 ) ? ' B ' : ' A ' , key64 ) ;
foundAKey = true ;
2017-07-12 21:58:32 +08:00
}
2012-05-30 11:45:55 +08:00
} else {
PrintAndLog ( " Command execute timeout " ) ;
}
}
2017-10-16 03:19:34 +08:00
} while ( - - keyAB > 0 ) ;
2011-06-10 21:35:10 +08:00
}
2017-10-16 03:19:34 +08:00
// print result
if ( foundAKey ) {
if ( SectorsCnt ) {
PrintAndLog ( " " ) ;
PrintAndLog ( " |---|----------------|---|----------------|---| " ) ;
PrintAndLog ( " |sec|key A |res|key B |res| " ) ;
PrintAndLog ( " |---|----------------|---|----------------|---| " ) ;
for ( i = 0 ; i < SectorsCnt ; i + + ) {
PrintAndLog ( " |%03d| %012 " PRIx64 " | %d | %012 " PRIx64 " | %d | " , i ,
e_sector [ i ] . Key [ 0 ] , e_sector [ i ] . foundKey [ 0 ] , e_sector [ i ] . Key [ 1 ] , e_sector [ i ] . foundKey [ 1 ] ) ;
}
PrintAndLog ( " |---|----------------|---|----------------|---| " ) ;
}
} else {
PrintAndLog ( " " ) ;
PrintAndLog ( " No valid keys found. " ) ;
}
2014-09-12 02:58:34 +08:00
if ( transferToEml ) {
uint8_t block [ 16 ] ;
for ( uint16_t sectorNo = 0 ; sectorNo < SectorsCnt ; sectorNo + + ) {
2017-10-16 03:19:34 +08:00
if ( e_sector [ sectorNo ] . foundKey [ 0 ] | | e_sector [ sectorNo ] . foundKey [ 1 ] ) {
2014-09-12 02:58:34 +08:00
mfEmlGetMem ( block , FirstBlockOfSector ( sectorNo ) + NumBlocksPerSector ( sectorNo ) - 1 , 1 ) ;
for ( uint16_t t = 0 ; t < 2 ; t + + ) {
2017-10-16 03:19:34 +08:00
if ( e_sector [ sectorNo ] . foundKey [ t ] ) {
num_to_bytes ( e_sector [ sectorNo ] . Key [ t ] , 6 , block + t * 10 ) ;
2014-09-12 02:58:34 +08:00
}
}
mfEmlSetMem ( block , FirstBlockOfSector ( sectorNo ) + NumBlocksPerSector ( sectorNo ) - 1 , 1 ) ;
}
}
PrintAndLog ( " Found keys have been transferred to the emulator memory " ) ;
}
2012-05-30 11:45:55 +08:00
if ( createDumpFile ) {
2014-09-12 02:58:34 +08:00
FILE * fkeys = fopen ( " dumpkeys.bin " , " wb " ) ;
2017-07-12 21:58:32 +08:00
if ( fkeys = = NULL ) {
2012-05-30 11:45:55 +08:00
PrintAndLog ( " Could not create file dumpkeys.bin " ) ;
2017-10-16 03:19:34 +08:00
free ( e_sector ) ;
2014-09-12 02:58:34 +08:00
free ( keyBlock ) ;
2012-05-30 11:45:55 +08:00
return 1 ;
}
2017-10-16 03:19:34 +08:00
uint8_t mkey [ 6 ] ;
for ( uint8_t t = 0 ; t < 2 ; t + + ) {
for ( uint8_t sectorNo = 0 ; sectorNo < SectorsCnt ; sectorNo + + ) {
num_to_bytes ( e_sector [ sectorNo ] . Key [ t ] , 6 , mkey ) ;
fwrite ( mkey , 1 , 6 , fkeys ) ;
}
2012-05-30 11:45:55 +08:00
}
fclose ( fkeys ) ;
2014-09-12 02:58:34 +08:00
PrintAndLog ( " Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys. " ) ;
2012-05-30 11:45:55 +08:00
}
2014-09-12 02:58:34 +08:00
2017-10-16 03:19:34 +08:00
free ( e_sector ) ;
2014-09-12 02:58:34 +08:00
free ( keyBlock ) ;
2015-01-05 22:51:27 +08:00
PrintAndLog ( " " ) ;
2014-09-12 02:58:34 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
2017-01-26 17:27:08 +08:00
void readerAttack ( nonces_t ar_resp [ ] , bool setEmulatorMem , bool doStandardAttack ) {
2017-06-07 00:12:18 +08:00
# define ATTACK_KEY_COUNT 7 // keep same as define in iso14443a.c -> Mifare1ksim()
// cannot be more than 7 or it will overrun c.d.asBytes(512)
2016-06-25 11:43:53 +08:00
uint64_t key = 0 ;
typedef struct {
uint64_t keyA ;
uint64_t keyB ;
} st_t ;
st_t sector_trailer [ ATTACK_KEY_COUNT ] ;
memset ( sector_trailer , 0x00 , sizeof ( sector_trailer ) ) ;
uint8_t stSector [ ATTACK_KEY_COUNT ] ;
memset ( stSector , 0x00 , sizeof ( stSector ) ) ;
uint8_t key_cnt [ ATTACK_KEY_COUNT ] ;
memset ( key_cnt , 0x00 , sizeof ( key_cnt ) ) ;
for ( uint8_t i = 0 ; i < ATTACK_KEY_COUNT ; i + + ) {
if ( ar_resp [ i ] . ar2 > 0 ) {
2016-06-27 12:09:40 +08:00
//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);
2017-01-26 17:27:08 +08:00
if ( doStandardAttack & & mfkey32 ( ar_resp [ i ] , & key ) ) {
2016-06-27 12:09:40 +08:00
PrintAndLog ( " 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 ) ) ;
2016-06-25 11:43:53 +08:00
for ( uint8_t ii = 0 ; ii < ATTACK_KEY_COUNT ; ii + + ) {
if ( key_cnt [ ii ] = = 0 | | stSector [ ii ] = = ar_resp [ i ] . sector ) {
if ( ar_resp [ i ] . keytype = = 0 ) {
//keyA
sector_trailer [ ii ] . keyA = key ;
stSector [ ii ] = ar_resp [ i ] . sector ;
key_cnt [ ii ] + + ;
break ;
} else {
//keyB
sector_trailer [ ii ] . keyB = key ;
stSector [ ii ] = ar_resp [ i ] . sector ;
key_cnt [ ii ] + + ;
break ;
}
}
}
2017-03-12 01:32:53 +08:00
} else if ( mfkey32_moebius ( ar_resp [ i + ATTACK_KEY_COUNT ] , & key ) ) {
2017-01-26 17:27:08 +08:00
uint8_t sectorNum = ar_resp [ i + ATTACK_KEY_COUNT ] . sector ;
uint8_t keyType = ar_resp [ i + ATTACK_KEY_COUNT ] . keytype ;
2017-02-23 05:45:00 +08:00
PrintAndLog ( " M-Found Key%s for sector %02d: [%012 " PRIx64 " ] "
2017-01-26 17:27:08 +08:00
, keyType ? " B " : " A "
, sectorNum
, key
) ;
for ( uint8_t ii = 0 ; ii < ATTACK_KEY_COUNT ; ii + + ) {
if ( key_cnt [ ii ] = = 0 | | stSector [ ii ] = = sectorNum ) {
if ( keyType = = 0 ) {
//keyA
sector_trailer [ ii ] . keyA = key ;
stSector [ ii ] = sectorNum ;
key_cnt [ ii ] + + ;
break ;
} else {
//keyB
sector_trailer [ ii ] . keyB = key ;
stSector [ ii ] = sectorNum ;
key_cnt [ ii ] + + ;
break ;
}
}
}
continue ;
2016-06-25 11:43:53 +08:00
}
}
}
//set emulator memory for keys
if ( setEmulatorMem ) {
for ( uint8_t i = 0 ; i < ATTACK_KEY_COUNT ; i + + ) {
if ( key_cnt [ i ] > 0 ) {
uint8_t memBlock [ 16 ] ;
memset ( memBlock , 0x00 , sizeof ( memBlock ) ) ;
char cmd1 [ 36 ] ;
memset ( cmd1 , 0x00 , sizeof ( cmd1 ) ) ;
snprintf ( cmd1 , sizeof ( cmd1 ) , " %04x%08xFF078069%04x%08x " , ( 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 ) ) ;
PrintAndLog ( " Setting Emulator Memory Block %02d: [%s] " , stSector [ i ] * 4 + 3 , cmd1 ) ;
if ( param_gethex ( cmd1 , 0 , memBlock , 32 ) ) {
PrintAndLog ( " block data must include 32 HEX symbols " ) ;
return ;
}
2017-07-12 21:58:32 +08:00
2016-06-25 11:43:53 +08:00
UsbCommand c = { CMD_MIFARE_EML_MEMSET , { ( stSector [ i ] * 4 + 3 ) , 1 , 0 } } ;
memcpy ( c . d . asBytes , memBlock , 16 ) ;
clearCommandBuffer ( ) ;
2017-07-12 21:58:32 +08:00
SendCommand ( & c ) ;
2016-06-25 11:43:53 +08:00
}
}
}
2016-07-29 00:52:18 +08:00
/*
//un-comment to use as well moebius attack
2016-06-25 11:43:53 +08:00
for ( uint8_t i = ATTACK_KEY_COUNT ; i < ATTACK_KEY_COUNT * 2 ; i + + ) {
if ( ar_resp [ i ] . ar2 > 0 ) {
if ( tryMfk32_moebius ( ar_resp [ i ] , & key ) ) {
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 ) ) ;
}
}
2016-07-29 00:52:18 +08:00
} */
2016-06-25 11:43:53 +08:00
}
int usage_hf14_mf1ksim ( void ) {
2016-06-27 12:09:40 +08:00
PrintAndLog ( " Usage: hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x " ) ;
2016-06-24 13:31:27 +08:00
PrintAndLog ( " options: " ) ;
PrintAndLog ( " h this help " ) ;
2016-06-27 12:09:40 +08:00
PrintAndLog ( " u (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used " ) ;
2016-06-24 13:31:27 +08:00
PrintAndLog ( " n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite " ) ;
PrintAndLog ( " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted " ) ;
PrintAndLog ( " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s) " ) ;
2016-06-27 12:09:40 +08:00
PrintAndLog ( " e (Optional) set keys found from 'reader attack' to emulator memory (implies x and i) " ) ;
2016-06-25 12:53:53 +08:00
PrintAndLog ( " f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i) " ) ;
2017-01-26 17:27:08 +08:00
PrintAndLog ( " r (Optional) Generate random nonces instead of sequential nonces. Standard reader attack won't work with this option, only moebius attack works. " ) ;
2016-06-24 13:31:27 +08:00
PrintAndLog ( " samples: " ) ;
PrintAndLog ( " hf mf sim u 0a0a0a0a " ) ;
PrintAndLog ( " hf mf sim u 11223344556677 " ) ;
2016-06-27 12:09:40 +08:00
PrintAndLog ( " hf mf sim u 112233445566778899AA " ) ;
PrintAndLog ( " hf mf sim f uids.txt " ) ;
PrintAndLog ( " hf mf sim u 0a0a0a0a e " ) ;
2017-07-12 21:58:32 +08:00
2016-06-24 13:31:27 +08:00
return 0 ;
}
2016-06-25 11:43:53 +08:00
int CmdHF14AMf1kSim ( const char * Cmd ) {
2016-06-25 12:53:53 +08:00
UsbCommand resp ;
2016-06-24 13:31:27 +08:00
uint8_t uid [ 10 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2014-02-01 05:17:34 +08:00
uint8_t exitAfterNReads = 0 ;
uint8_t flags = 0 ;
2016-06-24 13:31:27 +08:00
int uidlen = 0 ;
uint8_t pnr = 0 ;
bool setEmulatorMem = false ;
2016-06-25 11:43:53 +08:00
bool attackFromFile = false ;
FILE * f ;
char filename [ FILE_PATH_SIZE ] ;
memset ( filename , 0x00 , sizeof ( filename ) ) ;
int len = 0 ;
char buf [ 64 ] ;
uint8_t cmdp = 0 ;
bool errors = false ;
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 ) {
switch ( param_getchar ( Cmd , cmdp ) ) {
case ' e ' :
case ' E ' :
setEmulatorMem = true ;
2016-06-27 12:09:40 +08:00
//implies x and i
flags | = FLAG_INTERACTIVE ;
flags | = FLAG_NR_AR_ATTACK ;
2016-06-25 11:43:53 +08:00
cmdp + + ;
break ;
case ' f ' :
case ' F ' :
2017-11-12 05:08:57 +08:00
len = param_getstr ( Cmd , cmdp + 1 , filename , sizeof ( filename ) ) ;
2016-06-25 11:43:53 +08:00
if ( len < 1 ) {
PrintAndLog ( " error no filename found " ) ;
return 0 ;
}
attackFromFile = true ;
2016-06-27 12:09:40 +08:00
//implies x and i
flags | = FLAG_INTERACTIVE ;
flags | = FLAG_NR_AR_ATTACK ;
cmdp + = 2 ;
2016-06-25 11:43:53 +08:00
break ;
case ' h ' :
case ' H ' :
return usage_hf14_mf1ksim ( ) ;
case ' i ' :
case ' I ' :
flags | = FLAG_INTERACTIVE ;
cmdp + + ;
break ;
case ' n ' :
case ' N ' :
exitAfterNReads = param_get8 ( Cmd , pnr + 1 ) ;
cmdp + = 2 ;
break ;
2017-01-26 15:16:10 +08:00
case ' r ' :
case ' R ' :
flags | = FLAG_RANDOM_NONCE ;
cmdp + + ;
break ;
2016-06-25 11:43:53 +08:00
case ' u ' :
case ' U ' :
param_gethex_ex ( Cmd , cmdp + 1 , uid , & uidlen ) ;
switch ( uidlen ) {
case 20 : flags = FLAG_10B_UID_IN_DATA ; break ; //not complete
case 14 : flags = FLAG_7B_UID_IN_DATA ; break ;
case 8 : flags = FLAG_4B_UID_IN_DATA ; break ;
default : return usage_hf14_mf1ksim ( ) ;
}
2016-06-27 12:09:40 +08:00
cmdp + = 2 ;
2016-06-25 11:43:53 +08:00
break ;
case ' x ' :
case ' X ' :
flags | = FLAG_NR_AR_ATTACK ;
cmdp + + ;
break ;
default :
PrintAndLog ( " Unknown parameter '%c' " , param_getchar ( Cmd , cmdp ) ) ;
errors = true ;
break ;
2014-02-01 05:17:34 +08:00
}
2016-06-25 11:43:53 +08:00
if ( errors ) break ;
2014-02-01 05:17:34 +08:00
}
2016-06-25 11:43:53 +08:00
//Validations
if ( errors ) return usage_hf14_mf1ksim ( ) ;
2016-06-24 13:31:27 +08:00
2016-06-25 11:43:53 +08:00
//get uid from file
if ( attackFromFile ) {
int count = 0 ;
// open file
f = fopen ( filename , " r " ) ;
if ( f = = NULL ) {
PrintAndLog ( " File %s not found or locked " , filename ) ;
return 1 ;
}
2016-06-25 12:53:53 +08:00
PrintAndLog ( " Loading file and simulating. Press keyboard to abort " ) ;
while ( ! feof ( f ) & & ! ukbhit ( ) ) {
2016-06-25 11:43:53 +08:00
memset ( buf , 0 , sizeof ( buf ) ) ;
2016-06-29 09:02:26 +08:00
memset ( uid , 0 , sizeof ( uid ) ) ;
2014-02-01 05:17:34 +08:00
2017-07-12 21:58:32 +08:00
if ( fgets ( buf , sizeof ( buf ) , f ) = = NULL ) {
2016-06-25 11:43:53 +08:00
if ( count > 0 ) break ;
2017-07-12 21:58:32 +08:00
2016-06-25 11:43:53 +08:00
PrintAndLog ( " File reading error. " ) ;
fclose ( f ) ;
return 2 ;
}
2016-06-29 09:02:26 +08:00
if ( ! strlen ( buf ) & & feof ( f ) ) break ;
2016-06-25 12:53:53 +08:00
2016-06-29 09:02:26 +08:00
uidlen = strlen ( buf ) - 1 ;
2016-06-25 12:53:53 +08:00
switch ( uidlen ) {
2016-06-29 09:02:26 +08:00
case 20 : flags | = FLAG_10B_UID_IN_DATA ; break ; //not complete
case 14 : flags | = FLAG_7B_UID_IN_DATA ; break ;
case 8 : flags | = FLAG_4B_UID_IN_DATA ; break ;
2017-07-12 21:58:32 +08:00
default :
2016-06-29 09:02:26 +08:00
PrintAndLog ( " uid in file wrong length at %d (length: %d) [%s] " , count , uidlen , buf ) ;
2016-06-25 12:53:53 +08:00
fclose ( f ) ;
return 2 ;
2016-06-25 11:43:53 +08:00
}
2016-06-25 12:53:53 +08:00
2016-06-25 11:43:53 +08:00
for ( uint8_t i = 0 ; i < uidlen ; i + = 2 ) {
2016-06-29 09:02:26 +08:00
sscanf ( & buf [ i ] , " %02x " , ( unsigned int * ) & uid [ i / 2 ] ) ;
2016-06-25 11:43:53 +08:00
}
2017-07-12 21:58:32 +08:00
2016-06-25 12:53:53 +08:00
PrintAndLog ( " mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) - press button to abort " ,
2016-06-25 11:43:53 +08:00
flags & FLAG_4B_UID_IN_DATA ? sprint_hex ( uid , 4 ) :
2017-07-12 21:58:32 +08:00
flags & FLAG_7B_UID_IN_DATA ? sprint_hex ( uid , 7 ) :
2016-06-25 11:43:53 +08:00
flags & FLAG_10B_UID_IN_DATA ? sprint_hex ( uid , 10 ) : " N/A "
, exitAfterNReads , flags , flags ) ;
2016-06-25 12:53:53 +08:00
UsbCommand c = { CMD_SIMULATE_MIFARE_CARD , { flags , exitAfterNReads , 0 } } ;
2016-06-25 11:43:53 +08:00
memcpy ( c . d . asBytes , uid , sizeof ( uid ) ) ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2016-06-24 13:31:27 +08:00
2016-06-25 12:53:53 +08:00
while ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
}
//got a response
nonces_t ar_resp [ ATTACK_KEY_COUNT * 2 ] ;
memcpy ( ar_resp , resp . d . asBytes , sizeof ( ar_resp ) ) ;
2017-01-26 17:27:08 +08:00
// We can skip the standard attack if we have RANDOM_NONCE set.
readerAttack ( ar_resp , setEmulatorMem , ! ( flags & FLAG_RANDOM_NONCE ) ) ;
2016-06-27 12:09:40 +08:00
if ( ( bool ) resp . arg [ 1 ] ) {
2016-06-25 12:53:53 +08:00
PrintAndLog ( " Device button pressed - quitting " ) ;
fclose ( f ) ;
return 4 ;
2016-06-25 11:43:53 +08:00
}
count + + ;
}
fclose ( f ) ;
2016-06-27 12:09:40 +08:00
} else { //not from file
2014-02-01 05:17:34 +08:00
2016-06-25 11:43:53 +08:00
PrintAndLog ( " mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) " ,
flags & FLAG_4B_UID_IN_DATA ? sprint_hex ( uid , 4 ) :
2017-07-12 21:58:32 +08:00
flags & FLAG_7B_UID_IN_DATA ? sprint_hex ( uid , 7 ) :
2016-06-25 11:43:53 +08:00
flags & FLAG_10B_UID_IN_DATA ? sprint_hex ( uid , 10 ) : " N/A "
, exitAfterNReads , flags , flags ) ;
2014-02-01 05:17:34 +08:00
2016-06-25 12:53:53 +08:00
UsbCommand c = { CMD_SIMULATE_MIFARE_CARD , { flags , exitAfterNReads , 0 } } ;
2016-06-25 11:43:53 +08:00
memcpy ( c . d . asBytes , uid , sizeof ( uid ) ) ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2014-02-01 05:17:34 +08:00
2016-06-25 11:43:53 +08:00
if ( flags & FLAG_INTERACTIVE ) {
PrintAndLog ( " Press pm3-button to abort simulation " ) ;
while ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
2016-06-22 23:03:37 +08:00
}
2016-06-25 11:43:53 +08:00
//got a response
if ( flags & FLAG_NR_AR_ATTACK ) {
nonces_t ar_resp [ ATTACK_KEY_COUNT * 2 ] ;
memcpy ( ar_resp , resp . d . asBytes , sizeof ( ar_resp ) ) ;
2017-01-26 17:27:08 +08:00
// We can skip the standard attack if we have RANDOM_NONCE set.
readerAttack ( ar_resp , setEmulatorMem , ! ( flags & FLAG_RANDOM_NONCE ) ) ;
2016-06-22 23:03:37 +08:00
}
}
2014-09-11 01:04:50 +08:00
}
2016-06-25 11:43:53 +08:00
2014-09-11 01:04:50 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
int CmdHF14AMfDbg ( const char * Cmd )
{
2011-06-18 02:39:54 +08:00
int dbgMode = param_get32ex ( Cmd , 0 , 0 , 10 ) ;
if ( dbgMode > 4 ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Max debug mode parameter is 4 \n " ) ;
2011-06-18 02:39:54 +08:00
}
if ( strlen ( Cmd ) < 1 | | ! param_getchar ( Cmd , 0 ) | | dbgMode > 4 ) {
2011-06-10 21:35:10 +08:00
PrintAndLog ( " Usage: hf mf dbg <debug level> " ) ;
PrintAndLog ( " 0 - no debug messages " ) ;
PrintAndLog ( " 1 - error messages " ) ;
2014-07-31 03:23:02 +08:00
PrintAndLog ( " 2 - plus information messages " ) ;
PrintAndLog ( " 3 - plus debug messages " ) ;
PrintAndLog ( " 4 - print even debug messages in timing critical functions " ) ;
PrintAndLog ( " Note: this option therefore may cause malfunction itself " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-10 21:35:10 +08:00
2011-06-18 02:39:54 +08:00
UsbCommand c = { CMD_MIFARE_SET_DBGMODE , { dbgMode , 0 , 0 } } ;
SendCommand ( & c ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
int CmdHF14AMfEGet ( const char * Cmd )
{
2011-06-18 02:39:54 +08:00
uint8_t blockNo = 0 ;
2015-01-21 04:23:04 +08:00
uint8_t data [ 16 ] = { 0x00 } ;
2011-06-18 02:39:54 +08:00
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " Usage: hf mf eget <block number> " ) ;
PrintAndLog ( " sample: hf mf eget 0 " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-18 02:39:54 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
PrintAndLog ( " " ) ;
2014-09-11 01:04:50 +08:00
if ( ! mfEmlGetMem ( data , blockNo , 1 ) ) {
PrintAndLog ( " data[%3d]:%s " , blockNo , sprint_hex ( data , 16 ) ) ;
2011-06-18 02:39:54 +08:00
} else {
PrintAndLog ( " Command execute timeout " ) ;
}
return 0 ;
}
int CmdHF14AMfEClear ( const char * Cmd )
{
if ( param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " Usage: hf mf eclr " ) ;
PrintAndLog ( " It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-18 02:39:54 +08:00
UsbCommand c = { CMD_MIFARE_EML_MEMCLR , { 0 , 0 , 0 } } ;
SendCommand ( & c ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
2014-09-11 01:04:50 +08:00
2011-06-10 21:35:10 +08:00
int CmdHF14AMfESet ( const char * Cmd )
{
2011-06-18 02:39:54 +08:00
uint8_t memBlock [ 16 ] ;
uint8_t blockNo = 0 ;
memset ( memBlock , 0x00 , sizeof ( memBlock ) ) ;
if ( strlen ( Cmd ) < 3 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " Usage: hf mf eset <block number> <block data (32 hex symbols)> " ) ;
PrintAndLog ( " sample: hf mf eset 1 000102030405060708090a0b0c0d0e0f " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-18 02:39:54 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
2017-07-12 21:58:32 +08:00
2011-06-18 02:39:54 +08:00
if ( param_gethex ( Cmd , 1 , memBlock , 32 ) ) {
PrintAndLog ( " block data must include 32 HEX symbols " ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
2011-06-18 02:39:54 +08:00
// 1 - blocks count
2018-01-27 01:09:56 +08:00
return mfEmlSetMem ( memBlock , blockNo , 1 ) ;
2011-06-10 21:35:10 +08:00
}
2014-09-11 01:04:50 +08:00
2011-06-10 21:35:10 +08:00
int CmdHF14AMfELoad ( const char * Cmd )
{
2011-06-22 09:25:16 +08:00
FILE * f ;
2015-01-08 05:00:29 +08:00
char filename [ FILE_PATH_SIZE ] ;
2014-09-11 01:04:50 +08:00
char * fnameptr = filename ;
2015-01-21 04:23:04 +08:00
char buf [ 64 ] = { 0x00 } ;
uint8_t buf8 [ 64 ] = { 0x00 } ;
2015-01-08 05:00:29 +08:00
int i , len , blockNum , numBlocks ;
int nameParamNo = 1 ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
if ( ctmp = = ' h ' | | ctmp = = 0x00 ) {
2011-06-22 09:25:16 +08:00
PrintAndLog ( " It loads emul dump from the file `filename.eml` " ) ;
2015-01-08 05:00:29 +08:00
PrintAndLog ( " Usage: hf mf eload [card memory] <file name w/o `.eml`> " ) ;
PrintAndLog ( " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " " ) ;
2011-06-22 09:25:16 +08:00
PrintAndLog ( " sample: hf mf eload filename " ) ;
2015-01-08 05:00:29 +08:00
PrintAndLog ( " hf mf eload 4 filename " ) ;
2011-06-22 09:25:16 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-22 09:25:16 +08:00
2015-01-08 05:00:29 +08:00
switch ( ctmp ) {
case ' 0 ' : numBlocks = 5 * 4 ; break ;
2017-07-12 21:58:32 +08:00
case ' 1 ' :
2015-01-08 05:00:29 +08:00
case ' \0 ' : numBlocks = 16 * 4 ; break ;
case ' 2 ' : numBlocks = 32 * 4 ; break ;
case ' 4 ' : numBlocks = 256 ; break ;
default : {
numBlocks = 16 * 4 ;
nameParamNo = 0 ;
}
}
2017-11-12 05:08:57 +08:00
len = param_getstr ( Cmd , nameParamNo , filename , sizeof ( filename ) ) ;
2017-07-12 21:58:32 +08:00
2017-02-23 16:40:12 +08:00
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2011-06-22 09:25:16 +08:00
2015-05-25 02:14:22 +08:00
fnameptr + = len ;
2011-06-22 09:25:16 +08:00
2017-07-12 21:58:32 +08:00
sprintf ( fnameptr , " .eml " ) ;
2011-06-22 09:25:16 +08:00
// open file
f = fopen ( filename , " r " ) ;
if ( f = = NULL ) {
2015-01-05 22:51:27 +08:00
PrintAndLog ( " File %s not found or locked " , filename ) ;
2011-06-22 09:25:16 +08:00
return 1 ;
}
2017-07-12 21:58:32 +08:00
2011-06-22 09:25:16 +08:00
blockNum = 0 ;
while ( ! feof ( f ) ) {
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-07-12 21:58:32 +08:00
2013-03-14 23:03:04 +08:00
if ( fgets ( buf , sizeof ( buf ) , f ) = = NULL ) {
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
if ( blockNum > = numBlocks ) break ;
2017-07-12 21:58:32 +08:00
2014-02-01 05:17:34 +08:00
PrintAndLog ( " File reading error. " ) ;
2014-10-28 05:33:37 +08:00
fclose ( f ) ;
2013-03-14 23:03:04 +08:00
return 2 ;
2014-09-11 01:04:50 +08:00
}
2017-07-12 21:58:32 +08:00
2011-06-22 09:25:16 +08:00
if ( strlen ( buf ) < 32 ) {
2012-05-30 11:45:55 +08:00
if ( strlen ( buf ) & & feof ( f ) )
break ;
2011-06-22 09:25:16 +08:00
PrintAndLog ( " File content error. Block data must include 32 HEX symbols " ) ;
2014-10-28 05:33:37 +08:00
fclose ( f ) ;
2011-06-22 09:25:16 +08:00
return 2 ;
}
2017-07-12 21:58:32 +08:00
2014-09-11 01:04:50 +08:00
for ( i = 0 ; i < 32 ; i + = 2 ) {
sscanf ( & buf [ i ] , " %02x " , ( unsigned int * ) & buf8 [ i / 2 ] ) ;
}
2017-07-12 21:58:32 +08:00
2011-06-22 09:25:16 +08:00
if ( mfEmlSetMem ( buf8 , blockNum , 1 ) ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Cant set emul block: %3d " , blockNum ) ;
2014-10-28 05:33:37 +08:00
fclose ( f ) ;
2011-06-22 09:25:16 +08:00
return 3 ;
}
2015-01-21 04:23:04 +08:00
printf ( " . " ) ;
2011-06-22 09:25:16 +08:00
blockNum + + ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
if ( blockNum > = numBlocks ) break ;
2011-06-22 09:25:16 +08:00
}
fclose ( f ) ;
2015-01-21 04:23:04 +08:00
printf ( " \n " ) ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
if ( ( blockNum ! = numBlocks ) ) {
PrintAndLog ( " File content error. Got %d must be %d blocks. " , blockNum , numBlocks ) ;
2011-06-22 09:25:16 +08:00
return 4 ;
}
2014-02-01 05:17:34 +08:00
PrintAndLog ( " Loaded %d blocks from file: %s " , blockNum , filename ) ;
2014-09-11 01:04:50 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
2014-09-11 01:04:50 +08:00
2011-06-10 21:35:10 +08:00
int CmdHF14AMfESave ( const char * Cmd )
{
2011-06-22 09:25:16 +08:00
FILE * f ;
2015-01-08 05:00:29 +08:00
char filename [ FILE_PATH_SIZE ] ;
2011-06-22 09:25:16 +08:00
char * fnameptr = filename ;
uint8_t buf [ 64 ] ;
2015-01-08 05:00:29 +08:00
int i , j , len , numBlocks ;
int nameParamNo = 1 ;
2017-07-12 21:58:32 +08:00
2011-06-22 09:25:16 +08:00
memset ( filename , 0 , sizeof ( filename ) ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
2015-01-08 05:00:29 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
if ( ctmp = = ' h ' | | ctmp = = ' H ' ) {
2011-06-22 09:25:16 +08:00
PrintAndLog ( " It saves emul dump into the file `filename.eml` or `cardID.eml` " ) ;
2015-01-08 05:00:29 +08:00
PrintAndLog ( " Usage: hf mf esave [card memory] [file name w/o `.eml`] " ) ;
PrintAndLog ( " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " " ) ;
2011-06-22 09:25:16 +08:00
PrintAndLog ( " sample: hf mf esave " ) ;
2015-01-08 05:00:29 +08:00
PrintAndLog ( " hf mf esave 4 " ) ;
PrintAndLog ( " hf mf esave 4 filename " ) ;
2011-06-22 09:25:16 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-22 09:25:16 +08:00
2015-01-08 05:00:29 +08:00
switch ( ctmp ) {
case ' 0 ' : numBlocks = 5 * 4 ; break ;
2017-07-12 21:58:32 +08:00
case ' 1 ' :
2015-01-08 05:00:29 +08:00
case ' \0 ' : numBlocks = 16 * 4 ; break ;
case ' 2 ' : numBlocks = 32 * 4 ; break ;
case ' 4 ' : numBlocks = 256 ; break ;
default : {
numBlocks = 16 * 4 ;
nameParamNo = 0 ;
}
}
2017-11-12 05:08:57 +08:00
len = param_getstr ( Cmd , nameParamNo , filename , sizeof ( filename ) ) ;
2017-07-12 21:58:32 +08:00
2017-02-23 16:40:12 +08:00
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
// user supplied filename?
2011-06-22 09:25:16 +08:00
if ( len < 1 ) {
2015-01-08 05:00:29 +08:00
// get filename (UID from memory)
2011-06-22 09:25:16 +08:00
if ( mfEmlGetMem ( buf , 0 , 1 ) ) {
2015-01-08 05:00:29 +08:00
PrintAndLog ( " Can \' t get UID from block: %d " , 0 ) ;
2015-05-25 02:14:22 +08:00
len = sprintf ( fnameptr , " dump " ) ;
fnameptr + = len ;
}
else {
for ( j = 0 ; j < 7 ; j + + , fnameptr + = 2 )
sprintf ( fnameptr , " %02X " , buf [ j ] ) ;
2011-06-22 09:25:16 +08:00
}
} else {
2015-05-25 02:14:22 +08:00
fnameptr + = len ;
2011-06-22 09:25:16 +08:00
}
2015-01-08 05:00:29 +08:00
// add file extension
2017-07-12 21:58:32 +08:00
sprintf ( fnameptr , " .eml " ) ;
2011-06-22 09:25:16 +08:00
// open file
f = fopen ( filename , " w+ " ) ;
2015-01-08 05:00:29 +08:00
if ( ! f ) {
PrintAndLog ( " Can't open file %s " , filename ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
2011-06-22 09:25:16 +08:00
// put hex
2015-01-08 05:00:29 +08:00
for ( i = 0 ; i < numBlocks ; i + + ) {
2011-06-22 09:25:16 +08:00
if ( mfEmlGetMem ( buf , i , 1 ) ) {
PrintAndLog ( " Cant get block: %d " , i ) ;
break ;
}
for ( j = 0 ; j < 16 ; j + + )
2017-07-12 21:58:32 +08:00
fprintf ( f , " %02X " , buf [ j ] ) ;
2011-06-22 09:25:16 +08:00
fprintf ( f , " \n " ) ;
}
fclose ( f ) ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
PrintAndLog ( " Saved %d blocks to file: %s " , numBlocks , filename ) ;
2017-07-12 21:58:32 +08:00
2011-06-10 21:35:10 +08:00
return 0 ;
}
2014-09-11 01:04:50 +08:00
2011-08-30 17:52:18 +08:00
int CmdHF14AMfECFill ( const char * Cmd )
{
2011-06-18 02:39:54 +08:00
uint8_t keyType = 0 ;
2014-09-11 01:04:50 +08:00
uint8_t numSectors = 16 ;
2017-07-12 21:58:32 +08:00
2011-06-18 02:39:54 +08:00
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Usage: hf mf ecfill <key A/B> [card memory] " ) ;
PrintAndLog ( " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " " ) ;
PrintAndLog ( " samples: hf mf ecfill A " ) ;
PrintAndLog ( " hf mf ecfill A 4 " ) ;
PrintAndLog ( " Read card and transfer its data to emulator memory. " ) ;
PrintAndLog ( " Keys must be laid in the emulator memory. \n " ) ;
2011-06-18 02:39:54 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2011-06-18 02:39:54 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2014-09-11 01:04:50 +08:00
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
2011-06-18 02:39:54 +08:00
PrintAndLog ( " Key type must be A or B " ) ;
return 1 ;
}
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' ) keyType = 1 ;
2014-09-11 01:04:50 +08:00
ctmp = param_getchar ( Cmd , 1 ) ;
switch ( ctmp ) {
case ' 0 ' : numSectors = 5 ; break ;
2017-07-12 21:58:32 +08:00
case ' 1 ' :
2014-09-11 01:04:50 +08:00
case ' \0 ' : numSectors = 16 ; break ;
case ' 2 ' : numSectors = 32 ; break ;
case ' 4 ' : numSectors = 40 ; break ;
default : numSectors = 16 ;
2017-07-12 21:58:32 +08:00
}
2014-09-11 01:04:50 +08:00
2018-01-25 13:49:40 +08:00
printf ( " --params: numSectors: %d, keyType:%d \n " , numSectors , keyType ) ;
2014-09-11 01:04:50 +08:00
UsbCommand c = { CMD_MIFARE_EML_CARDLOAD , { numSectors , keyType , 0 } } ;
SendCommand ( & c ) ;
return 0 ;
2011-06-18 02:39:54 +08:00
}
2011-08-30 17:52:18 +08:00
int CmdHF14AMfEKeyPrn ( const char * Cmd )
{
2014-09-11 01:04:50 +08:00
int i ;
2015-01-08 05:00:29 +08:00
uint8_t numSectors ;
2011-06-18 02:39:54 +08:00
uint8_t data [ 16 ] ;
uint64_t keyA , keyB ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
if ( param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " It prints the keys loaded in the emulator memory " ) ;
PrintAndLog ( " Usage: hf mf ekeyprn [card memory] " ) ;
PrintAndLog ( " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " " ) ;
PrintAndLog ( " sample: hf mf ekeyprn 1 " ) ;
return 0 ;
2017-07-12 21:58:32 +08:00
}
2015-01-08 05:00:29 +08:00
char cmdp = param_getchar ( Cmd , 0 ) ;
2017-07-12 21:58:32 +08:00
2015-01-08 05:00:29 +08:00
switch ( cmdp ) {
case ' 0 ' : numSectors = 5 ; break ;
2017-07-12 21:58:32 +08:00
case ' 1 ' :
2015-01-08 05:00:29 +08:00
case ' \0 ' : numSectors = 16 ; break ;
case ' 2 ' : numSectors = 32 ; break ;
case ' 4 ' : numSectors = 40 ; break ;
default : numSectors = 16 ;
2017-07-12 21:58:32 +08:00
}
2011-06-18 02:39:54 +08:00
PrintAndLog ( " |---|----------------|----------------| " ) ;
PrintAndLog ( " |sec|key A |key B | " ) ;
PrintAndLog ( " |---|----------------|----------------| " ) ;
2015-01-08 05:00:29 +08:00
for ( i = 0 ; i < numSectors ; i + + ) {
2014-09-11 01:04:50 +08:00
if ( mfEmlGetMem ( data , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ) {
PrintAndLog ( " error get block %d " , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 ) ;
2011-06-18 02:39:54 +08:00
break ;
}
keyA = bytes_to_num ( data , 6 ) ;
keyB = bytes_to_num ( data + 10 , 6 ) ;
2017-02-23 05:45:00 +08:00
PrintAndLog ( " |%03d| %012 " PRIx64 " | %012 " PRIx64 " | " , i , keyA , keyB ) ;
2011-06-18 02:39:54 +08:00
}
PrintAndLog ( " |---|----------------|----------------| " ) ;
2017-07-12 21:58:32 +08:00
2011-06-18 02:39:54 +08:00
return 0 ;
}
2012-07-05 15:31:56 +08:00
int CmdHF14AMfCSetUID ( const char * Cmd )
{
2015-01-05 22:51:27 +08:00
uint8_t uid [ 8 ] = { 0x00 } ;
uint8_t oldUid [ 8 ] = { 0x00 } ;
2015-02-10 10:31:53 +08:00
uint8_t atqa [ 2 ] = { 0x00 } ;
uint8_t sak [ 1 ] = { 0x00 } ;
2017-09-23 01:40:42 +08:00
uint8_t atqaPresent = 0 ;
2012-07-05 15:31:56 +08:00
int res ;
2015-02-10 10:31:53 +08:00
2017-09-23 01:40:42 +08:00
uint8_t needHelp = 0 ;
char cmdp = 1 ;
if ( param_getchar ( Cmd , 0 ) & & param_gethex ( Cmd , 0 , uid , 8 ) ) {
PrintAndLog ( " UID must include 8 HEX symbols " ) ;
return 1 ;
}
if ( param_getlength ( Cmd , 1 ) > 1 & & param_getlength ( Cmd , 2 ) > 1 ) {
atqaPresent = 1 ;
cmdp = 3 ;
if ( param_gethex ( Cmd , 1 , atqa , 4 ) ) {
PrintAndLog ( " ATQA must include 4 HEX symbols " ) ;
return 1 ;
}
if ( param_gethex ( Cmd , 2 , sak , 2 ) ) {
PrintAndLog ( " SAK must include 2 HEX symbols " ) ;
return 1 ;
}
}
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 )
{
switch ( param_getchar ( Cmd , cmdp ) )
{
case ' h ' :
case ' H ' :
needHelp = 1 ;
break ;
default :
PrintAndLog ( " ERROR: Unknown parameter '%c' " , param_getchar ( Cmd , cmdp ) ) ;
needHelp = 1 ;
break ;
}
cmdp + + ;
}
if ( strlen ( Cmd ) < 1 | | needHelp ) {
PrintAndLog ( " " ) ;
PrintAndLog ( " Usage: hf mf csetuid <UID 8 hex symbols> [ATQA 4 hex symbols SAK 2 hex symbols] " ) ;
2015-02-10 10:31:53 +08:00
PrintAndLog ( " sample: hf mf csetuid 01020304 " ) ;
2017-09-23 01:40:42 +08:00
PrintAndLog ( " sample: hf mf csetuid 01020304 0004 08 " ) ;
2015-02-10 10:31:53 +08:00
PrintAndLog ( " Set UID, ATQA, and SAK for magic Chinese card (only works with such cards) " ) ;
2012-07-05 15:31:56 +08:00
return 0 ;
2015-02-10 10:31:53 +08:00
}
2012-07-05 15:31:56 +08:00
2017-09-23 01:40:42 +08:00
PrintAndLog ( " uid:%s " , sprint_hex ( uid , 4 ) ) ;
if ( atqaPresent ) {
PrintAndLog ( " --atqa:%s sak:%02x " , sprint_hex ( atqa , 2 ) , sak [ 0 ] ) ;
2012-07-05 15:31:56 +08:00
}
2015-02-10 10:31:53 +08:00
2017-09-23 01:40:42 +08:00
res = mfCSetUID ( uid , ( atqaPresent ) ? atqa : NULL , ( atqaPresent ) ? sak : NULL , oldUid ) ;
if ( res ) {
PrintAndLog ( " Can't set UID. Error=%d " , res ) ;
return 1 ;
}
PrintAndLog ( " old UID:%s " , sprint_hex ( oldUid , 4 ) ) ;
PrintAndLog ( " new UID:%s " , sprint_hex ( uid , 4 ) ) ;
return 0 ;
}
int CmdHF14AMfCWipe ( const char * Cmd )
{
int res , gen = 0 ;
int numBlocks = 16 * 4 ;
bool wipeCard = false ;
bool fillCard = false ;
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
2017-12-07 06:30:27 +08:00
PrintAndLog ( " Usage: hf mf cwipe [card size] [w] [f] " ) ;
PrintAndLog ( " sample: hf mf cwipe 1 w f " ) ;
2017-09-23 01:40:42 +08:00
PrintAndLog ( " [card size]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLog ( " w - Wipe magic Chinese card (only works with gen:1a cards) " ) ;
PrintAndLog ( " f - Fill the card with default data and keys (works with gen:1a and gen:1b cards only) " ) ;
return 0 ;
2015-02-10 10:31:53 +08:00
}
2017-09-23 01:40:42 +08:00
gen = mfCIdentify ( ) ;
if ( ( gen ! = 1 ) & & ( gen ! = 2 ) )
return 1 ;
2017-10-05 19:37:51 +08:00
numBlocks = ParamCardSizeBlocks ( param_getchar ( Cmd , 0 ) ) ;
2017-09-23 01:40:42 +08:00
char cmdp = 0 ;
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 ) {
switch ( param_getchar ( Cmd , cmdp ) ) {
case ' w ' :
case ' W ' :
2015-02-10 10:31:53 +08:00
wipeCard = 1 ;
2017-09-23 01:40:42 +08:00
break ;
case ' f ' :
case ' F ' :
fillCard = 1 ;
break ;
default :
break ;
2015-02-10 10:31:53 +08:00
}
2017-09-23 01:40:42 +08:00
cmdp + + ;
2015-02-10 10:31:53 +08:00
}
2012-07-05 15:31:56 +08:00
2017-09-23 01:40:42 +08:00
if ( ! wipeCard & & ! fillCard )
2017-09-26 19:29:08 +08:00
wipeCard = true ;
2012-07-05 15:31:56 +08:00
2017-09-23 01:40:42 +08:00
PrintAndLog ( " --blocks count:%2d wipe:%c fill:%c " , numBlocks , ( wipeCard ) ? ' y ' : ' n ' , ( fillCard ) ? ' y ' : ' n ' ) ;
if ( gen = = 2 ) {
/* generation 1b magic card */
if ( wipeCard ) {
PrintAndLog ( " WARNING: can't wipe magic card 1b generation " ) ;
2012-07-05 15:31:56 +08:00
}
2017-09-23 01:40:42 +08:00
res = mfCWipe ( numBlocks , true , false , fillCard ) ;
} else {
/* generation 1a magic card by default */
res = mfCWipe ( numBlocks , false , wipeCard , fillCard ) ;
}
2017-07-12 21:58:32 +08:00
2017-09-23 01:40:42 +08:00
if ( res ) {
PrintAndLog ( " Can't wipe. error=%d " , res ) ;
return 1 ;
}
PrintAndLog ( " OK " ) ;
2012-07-05 15:31:56 +08:00
return 0 ;
}
int CmdHF14AMfCSetBlk ( const char * Cmd )
{
2015-01-21 04:23:04 +08:00
uint8_t memBlock [ 16 ] = { 0x00 } ;
2012-07-05 16:09:41 +08:00
uint8_t blockNo = 0 ;
2017-03-07 03:07:02 +08:00
bool wipeCard = false ;
2017-07-12 21:58:32 +08:00
int res , gen = 0 ;
2012-07-05 16:09:41 +08:00
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
2015-04-09 03:08:05 +08:00
PrintAndLog ( " Usage: hf mf csetblk <block number> <block data (32 hex symbols)> [w] " ) ;
2012-07-05 16:09:41 +08:00
PrintAndLog ( " sample: hf mf csetblk 1 01020304050607080910111213141516 " ) ;
2015-04-09 03:08:05 +08:00
PrintAndLog ( " Set block data for magic Chinese card (only works with such cards) " ) ;
PrintAndLog ( " If you also want wipe the card then add 'w' at the end of the command line " ) ;
2012-07-05 16:09:41 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
gen = mfCIdentify ( ) ;
2017-09-23 01:40:42 +08:00
if ( ( gen ! = 1 ) & & ( gen ! = 2 ) )
return 1 ;
2012-07-05 16:09:41 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
if ( param_gethex ( Cmd , 1 , memBlock , 32 ) ) {
PrintAndLog ( " block data must include 32 HEX symbols " ) ;
return 1 ;
}
2015-04-09 03:08:05 +08:00
char ctmp = param_getchar ( Cmd , 2 ) ;
wipeCard = ( ctmp = = ' w ' | | ctmp = = ' W ' ) ;
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --block number:%2d data:%s " , blockNo , sprint_hex ( memBlock , 16 ) ) ;
2012-07-05 16:09:41 +08:00
2017-07-12 21:58:32 +08:00
if ( gen = = 2 ) {
/* generation 1b magic card */
res = mfCSetBlock ( blockNo , memBlock , NULL , wipeCard , CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B ) ;
} else {
/* generation 1a magic card by default */
res = mfCSetBlock ( blockNo , memBlock , NULL , wipeCard , CSETBLOCK_SINGLE_OPER ) ;
}
2012-07-05 16:09:41 +08:00
if ( res ) {
2015-04-09 03:08:05 +08:00
PrintAndLog ( " Can't write block. error=%d " , res ) ;
return 1 ;
}
2012-07-05 15:31:56 +08:00
return 0 ;
}
2014-09-11 01:04:50 +08:00
2012-07-05 15:31:56 +08:00
int CmdHF14AMfCLoad ( const char * Cmd )
{
2012-07-05 18:59:15 +08:00
FILE * f ;
2015-01-08 05:00:29 +08:00
char filename [ FILE_PATH_SIZE ] = { 0x00 } ;
2012-07-05 18:59:15 +08:00
char * fnameptr = filename ;
2017-07-12 21:58:32 +08:00
char buf [ 256 ] = { 0x00 } ;
uint8_t buf8 [ 256 ] = { 0x00 } ;
2012-07-05 18:59:15 +08:00
uint8_t fillFromEmulator = 0 ;
2017-07-12 21:58:32 +08:00
int i , len , blockNum , flags = 0 , gen = 0 , numblock = 64 ;
2012-07-05 18:59:15 +08:00
if ( param_getchar ( Cmd , 0 ) = = ' h ' | | param_getchar ( Cmd , 0 ) = = 0x00 ) {
2015-01-21 04:48:39 +08:00
PrintAndLog ( " It loads magic Chinese card from the file `filename.eml` " ) ;
2017-07-12 21:58:32 +08:00
PrintAndLog ( " or from emulator memory (option `e`). 4K card: (option `4`) " ) ;
PrintAndLog ( " Usage: hf mf cload [file name w/o `.eml`][e][4] " ) ;
PrintAndLog ( " or: hf mf cload e [4] " ) ;
PrintAndLog ( " Sample: hf mf cload filename " ) ;
PrintAndLog ( " hf mf cload filname 4 " ) ;
PrintAndLog ( " hf mf cload e " ) ;
PrintAndLog ( " hf mf cload e 4 " ) ;
2012-07-05 18:59:15 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2012-07-05 18:59:15 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp = = ' e ' | | ctmp = = ' E ' ) fillFromEmulator = 1 ;
2017-07-12 21:58:32 +08:00
ctmp = param_getchar ( Cmd , 1 ) ;
if ( ctmp = = ' 4 ' ) numblock = 256 ;
gen = mfCIdentify ( ) ;
PrintAndLog ( " Loading magic mifare %dK " , numblock = = 256 ? 4 : 1 ) ;
2012-07-05 18:59:15 +08:00
if ( fillFromEmulator ) {
2017-07-12 21:58:32 +08:00
for ( blockNum = 0 ; blockNum < numblock ; blockNum + = 1 ) {
2012-07-05 18:59:15 +08:00
if ( mfEmlGetMem ( buf8 , blockNum , 1 ) ) {
PrintAndLog ( " Cant get block: %d " , blockNum ) ;
return 2 ;
}
2015-03-10 04:36:27 +08:00
if ( blockNum = = 0 ) flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC ; // switch on field and send magic sequence
if ( blockNum = = 1 ) flags = 0 ; // just write
2017-07-12 21:58:32 +08:00
if ( blockNum = = numblock - 1 ) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD ; // Done. Magic Halt and switch off field.
2012-07-05 18:59:15 +08:00
2017-07-12 21:58:32 +08:00
if ( gen = = 2 )
/* generation 1b magic card */
flags | = CSETBLOCK_MAGIC_1B ;
2012-07-05 18:59:15 +08:00
if ( mfCSetBlock ( blockNum , buf8 , NULL , 0 , flags ) ) {
PrintAndLog ( " Cant set magic card block: %d " , blockNum ) ;
return 3 ;
}
}
return 0 ;
} else {
2017-11-12 05:08:57 +08:00
param_getstr ( Cmd , 0 , filename , sizeof ( filename ) ) ;
2017-07-12 21:58:32 +08:00
len = strlen ( filename ) ;
2017-02-23 16:40:12 +08:00
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2012-07-05 18:59:15 +08:00
2017-07-12 21:58:32 +08:00
//memcpy(filename, Cmd, len);
2015-05-25 04:43:08 +08:00
fnameptr + = len ;
2012-07-05 18:59:15 +08:00
2017-07-12 21:58:32 +08:00
sprintf ( fnameptr , " .eml " ) ;
2012-07-05 18:59:15 +08:00
// open file
f = fopen ( filename , " r " ) ;
if ( f = = NULL ) {
PrintAndLog ( " File not found or locked. " ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
2012-07-05 18:59:15 +08:00
blockNum = 0 ;
while ( ! feof ( f ) ) {
2017-07-12 21:58:32 +08:00
2012-07-05 18:59:15 +08:00
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-07-12 21:58:32 +08:00
2013-03-14 23:03:04 +08:00
if ( fgets ( buf , sizeof ( buf ) , f ) = = NULL ) {
2015-05-13 23:14:17 +08:00
fclose ( f ) ;
2014-09-11 01:04:50 +08:00
PrintAndLog ( " File reading error. " ) ;
return 2 ;
}
2012-07-05 18:59:15 +08:00
2015-03-10 04:36:27 +08:00
if ( strlen ( buf ) < 32 ) {
2012-07-05 18:59:15 +08:00
if ( strlen ( buf ) & & feof ( f ) )
break ;
PrintAndLog ( " File content error. Block data must include 32 HEX symbols " ) ;
2015-05-13 23:14:17 +08:00
fclose ( f ) ;
2012-07-05 18:59:15 +08:00
return 2 ;
}
for ( i = 0 ; i < 32 ; i + = 2 )
sscanf ( & buf [ i ] , " %02x " , ( unsigned int * ) & buf8 [ i / 2 ] ) ;
2015-03-10 04:36:27 +08:00
if ( blockNum = = 0 ) flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC ; // switch on field and send magic sequence
if ( blockNum = = 1 ) flags = 0 ; // just write
2017-07-12 21:58:32 +08:00
if ( blockNum = = numblock - 1 ) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD ; // Done. Switch off field.
2012-07-05 18:59:15 +08:00
2017-07-12 21:58:32 +08:00
if ( gen = = 2 )
/* generation 1b magic card */
flags | = CSETBLOCK_MAGIC_1B ;
2012-07-05 18:59:15 +08:00
if ( mfCSetBlock ( blockNum , buf8 , NULL , 0 , flags ) ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " Can't set magic card block: %d " , blockNum ) ;
2017-02-23 16:40:12 +08:00
fclose ( f ) ;
2012-07-05 18:59:15 +08:00
return 3 ;
}
blockNum + + ;
2017-07-12 21:58:32 +08:00
if ( blockNum > = numblock ) break ; // magic card type - mifare 1K 64 blocks, mifare 4k 256 blocks
2012-07-05 18:59:15 +08:00
}
fclose ( f ) ;
2017-07-12 21:58:32 +08:00
//if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){
if ( blockNum ! = numblock ) {
PrintAndLog ( " File content error. There must be %d blocks " , numblock ) ;
2012-07-05 18:59:15 +08:00
return 4 ;
}
PrintAndLog ( " Loaded from file: %s " , filename ) ;
return 0 ;
}
2015-01-21 04:48:39 +08:00
return 0 ;
2012-07-05 15:31:56 +08:00
}
2012-07-05 22:05:01 +08:00
int CmdHF14AMfCGetBlk ( const char * Cmd ) {
uint8_t memBlock [ 16 ] ;
uint8_t blockNo = 0 ;
2017-07-12 21:58:32 +08:00
int res , gen = 0 ;
2012-07-05 22:05:01 +08:00
memset ( memBlock , 0x00 , sizeof ( memBlock ) ) ;
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " Usage: hf mf cgetblk <block number> " ) ;
PrintAndLog ( " sample: hf mf cgetblk 1 " ) ;
2015-04-09 03:08:05 +08:00
PrintAndLog ( " Get block data from magic Chinese card (only works with such cards) \n " ) ;
2012-07-05 22:05:01 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
gen = mfCIdentify ( ) ;
2012-07-05 22:05:01 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --block number:%2d " , blockNo ) ;
2012-07-05 22:05:01 +08:00
2017-07-12 21:58:32 +08:00
if ( gen = = 2 ) {
/* generation 1b magic card */
res = mfCGetBlock ( blockNo , memBlock , CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B ) ;
} else {
/* generation 1a magic card by default */
res = mfCGetBlock ( blockNo , memBlock , CSETBLOCK_SINGLE_OPER ) ;
}
2012-07-05 22:05:01 +08:00
if ( res ) {
PrintAndLog ( " Can't read block. error=%d " , res ) ;
return 1 ;
}
2017-07-12 21:58:32 +08:00
2012-07-05 22:05:01 +08:00
PrintAndLog ( " block data:%s " , sprint_hex ( memBlock , 16 ) ) ;
return 0 ;
}
int CmdHF14AMfCGetSc ( const char * Cmd ) {
2015-01-21 04:23:04 +08:00
uint8_t memBlock [ 16 ] = { 0x00 } ;
2012-07-05 22:05:01 +08:00
uint8_t sectorNo = 0 ;
2017-07-12 21:58:32 +08:00
int i , res , flags , gen = 0 , baseblock = 0 , sect_size = 4 ;
2012-07-05 22:05:01 +08:00
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " Usage: hf mf cgetsc <sector number> " ) ;
PrintAndLog ( " sample: hf mf cgetsc 0 " ) ;
2015-04-09 03:08:05 +08:00
PrintAndLog ( " Get sector data from magic Chinese card (only works with such cards) \n " ) ;
2012-07-05 22:05:01 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2012-07-05 22:05:01 +08:00
sectorNo = param_get8 ( Cmd , 0 ) ;
2017-07-12 21:58:32 +08:00
if ( sectorNo > 39 ) {
PrintAndLog ( " Sector number must be in [0..15] in MIFARE classic 1k and [0..39] in MIFARE classic 4k. " ) ;
2012-07-05 22:05:01 +08:00
return 1 ;
}
2014-09-11 01:04:50 +08:00
PrintAndLog ( " --sector number:%d " , sectorNo ) ;
2012-07-05 22:05:01 +08:00
2017-07-12 21:58:32 +08:00
gen = mfCIdentify ( ) ;
2012-07-05 22:05:01 +08:00
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC ;
2017-07-12 21:58:32 +08:00
if ( sectorNo < 32 ) {
baseblock = sectorNo * 4 ;
} else {
baseblock = 128 + 16 * ( sectorNo - 32 ) ;
}
if ( sectorNo > 31 ) sect_size = 16 ;
for ( i = 0 ; i < sect_size ; i + + ) {
2012-07-05 22:05:01 +08:00
if ( i = = 1 ) flags = 0 ;
2017-07-12 21:58:32 +08:00
if ( i = = sect_size - 1 ) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD ;
2012-07-05 22:05:01 +08:00
2017-07-12 21:58:32 +08:00
if ( gen = = 2 )
/* generation 1b magic card */
flags | = CSETBLOCK_MAGIC_1B ;
res = mfCGetBlock ( baseblock + i , memBlock , flags ) ;
2012-07-05 22:05:01 +08:00
if ( res ) {
2017-07-12 21:58:32 +08:00
PrintAndLog ( " Can't read block. %d error=%d " , baseblock + i , res ) ;
2012-07-05 22:05:01 +08:00
return 1 ;
}
2017-07-12 21:58:32 +08:00
PrintAndLog ( " block %3d data:%s " , baseblock + i , sprint_hex ( memBlock , 16 ) ) ;
2012-07-05 22:05:01 +08:00
}
return 0 ;
}
2014-09-11 01:04:50 +08:00
2012-07-05 22:05:01 +08:00
int CmdHF14AMfCSave ( const char * Cmd ) {
FILE * f ;
2015-01-08 05:00:29 +08:00
char filename [ FILE_PATH_SIZE ] = { 0x00 } ;
2012-07-05 22:05:01 +08:00
char * fnameptr = filename ;
uint8_t fillFromEmulator = 0 ;
2017-07-12 21:58:32 +08:00
uint8_t buf [ 256 ] = { 0x00 } ;
int i , j , len , flags , gen = 0 , numblock = 64 ;
2015-01-08 05:00:29 +08:00
// memset(filename, 0, sizeof(filename));
// memset(buf, 0, sizeof(buf));
2012-07-05 22:05:01 +08:00
if ( param_getchar ( Cmd , 0 ) = = ' h ' ) {
PrintAndLog ( " It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml` " ) ;
2017-07-12 21:58:32 +08:00
PrintAndLog ( " or into emulator memory (option `e`). 4K card: (option `4`) " ) ;
2017-09-26 22:36:05 +08:00
PrintAndLog ( " Usage: hf mf csave [file name w/o `.eml`][e][4] " ) ;
PrintAndLog ( " Sample: hf mf csave " ) ;
PrintAndLog ( " hf mf csave filename " ) ;
PrintAndLog ( " hf mf csave e " ) ;
PrintAndLog ( " hf mf csave 4 " ) ;
PrintAndLog ( " hf mf csave filename 4 " ) ;
PrintAndLog ( " hf mf csave e 4 " ) ;
2012-07-05 22:05:01 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2012-07-05 22:05:01 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp = = ' e ' | | ctmp = = ' E ' ) fillFromEmulator = 1 ;
2017-07-12 21:58:32 +08:00
if ( ctmp = = ' 4 ' ) numblock = 256 ;
ctmp = param_getchar ( Cmd , 1 ) ;
if ( ctmp = = ' 4 ' ) numblock = 256 ;
gen = mfCIdentify ( ) ;
PrintAndLog ( " Saving magic mifare %dK " , numblock = = 256 ? 4 : 1 ) ;
2012-07-05 22:05:01 +08:00
if ( fillFromEmulator ) {
// put into emulator
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC ;
2017-07-12 21:58:32 +08:00
for ( i = 0 ; i < numblock ; i + + ) {
2012-07-05 22:05:01 +08:00
if ( i = = 1 ) flags = 0 ;
2017-07-12 21:58:32 +08:00
if ( i = = numblock - 1 ) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD ;
if ( gen = = 2 )
/* generation 1b magic card */
flags | = CSETBLOCK_MAGIC_1B ;
2012-07-05 22:05:01 +08:00
if ( mfCGetBlock ( i , buf , flags ) ) {
PrintAndLog ( " Cant get block: %d " , i ) ;
break ;
}
2017-07-12 21:58:32 +08:00
2012-07-05 22:05:01 +08:00
if ( mfEmlSetMem ( buf , i , 1 ) ) {
PrintAndLog ( " Cant set emul block: %d " , i ) ;
return 3 ;
}
}
return 0 ;
} else {
2017-11-12 05:08:57 +08:00
param_getstr ( Cmd , 0 , filename , sizeof ( filename ) ) ;
2017-07-12 21:58:32 +08:00
len = strlen ( filename ) ;
2017-02-23 16:40:12 +08:00
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2017-07-12 21:58:32 +08:00
ctmp = param_getchar ( Cmd , 0 ) ;
if ( len < 1 | | ( ctmp = = ' 4 ' ) ) {
2012-07-05 22:05:01 +08:00
// get filename
2017-07-12 21:58:32 +08:00
flags = CSETBLOCK_SINGLE_OPER ;
if ( gen = = 2 )
/* generation 1b magic card */
flags | = CSETBLOCK_MAGIC_1B ;
if ( mfCGetBlock ( 0 , buf , flags ) ) {
2012-07-05 22:05:01 +08:00
PrintAndLog ( " Cant get block: %d " , 0 ) ;
2015-05-25 17:47:27 +08:00
len = sprintf ( fnameptr , " dump " ) ;
fnameptr + = len ;
}
else {
for ( j = 0 ; j < 7 ; j + + , fnameptr + = 2 )
2017-07-12 21:58:32 +08:00
sprintf ( fnameptr , " %02x " , buf [ j ] ) ;
2012-07-05 22:05:01 +08:00
}
} else {
2017-07-12 21:58:32 +08:00
//memcpy(filename, Cmd, len);
2012-07-05 22:05:01 +08:00
fnameptr + = len ;
}
2017-07-12 21:58:32 +08:00
sprintf ( fnameptr , " .eml " ) ;
2012-07-05 22:05:01 +08:00
// open file
f = fopen ( filename , " w+ " ) ;
2015-01-08 05:00:29 +08:00
if ( f = = NULL ) {
PrintAndLog ( " File not found or locked. " ) ;
return 1 ;
}
2012-07-05 22:05:01 +08:00
// put hex
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC ;
2017-07-12 21:58:32 +08:00
for ( i = 0 ; i < numblock ; i + + ) {
2012-07-05 22:05:01 +08:00
if ( i = = 1 ) flags = 0 ;
2017-07-12 21:58:32 +08:00
if ( i = = numblock - 1 ) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD ;
if ( gen = = 2 )
/* generation 1b magic card */
flags | = CSETBLOCK_MAGIC_1B ;
2012-07-05 22:05:01 +08:00
if ( mfCGetBlock ( i , buf , flags ) ) {
PrintAndLog ( " Cant get block: %d " , i ) ;
break ;
}
for ( j = 0 ; j < 16 ; j + + )
2017-07-12 21:58:32 +08:00
fprintf ( f , " %02x " , buf [ j ] ) ;
2012-07-05 22:05:01 +08:00
fprintf ( f , " \n " ) ;
}
fclose ( f ) ;
2017-07-12 21:58:32 +08:00
2012-07-05 22:05:01 +08:00
PrintAndLog ( " Saved to file: %s " , filename ) ;
2017-07-12 21:58:32 +08:00
2012-07-05 22:05:01 +08:00
return 0 ;
}
}
2014-09-11 01:04:50 +08:00
2012-07-07 00:19:05 +08:00
int CmdHF14AMfSniff ( const char * Cmd ) {
2015-01-05 22:51:27 +08:00
2012-07-17 19:29:34 +08:00
bool wantLogToFile = 0 ;
bool wantDecrypt = 0 ;
2012-07-20 17:04:23 +08:00
//bool wantSaveToEml = 0; TODO
2012-07-16 22:49:51 +08:00
bool wantSaveToEmlFile = 0 ;
2017-07-12 21:58:32 +08:00
//var
2012-07-11 23:52:33 +08:00
int res = 0 ;
int len = 0 ;
2018-02-09 22:50:55 +08:00
int parlen = 0 ;
2012-07-11 23:52:33 +08:00
int blockLen = 0 ;
int pckNum = 0 ;
2015-01-27 15:34:48 +08:00
int num = 0 ;
uint8_t uid [ 7 ] ;
2014-07-15 14:39:56 +08:00
uint8_t uid_len ;
2015-01-21 04:23:04 +08:00
uint8_t atqa [ 2 ] = { 0x00 } ;
2012-07-11 23:52:33 +08:00
uint8_t sak ;
bool isTag ;
2015-01-27 15:34:48 +08:00
uint8_t * buf = NULL ;
uint16_t bufsize = 0 ;
uint8_t * bufPtr = NULL ;
2018-02-09 22:50:55 +08:00
uint8_t parity [ 16 ] ;
2017-07-12 21:58:32 +08:00
2015-01-21 04:48:39 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp = = ' h ' | | ctmp = = ' H ' ) {
2014-09-11 01:04:50 +08:00
PrintAndLog ( " It continuously gets data from the field and saves it to: log, emulator, emulator file. " ) ;
2012-07-16 22:49:51 +08:00
PrintAndLog ( " You can specify: " ) ;
PrintAndLog ( " l - save encrypted sequence to logfile `uid.log` " ) ;
PrintAndLog ( " d - decrypt sequence and put it to log file `uid.log` " ) ;
PrintAndLog ( " n/a e - decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory " ) ;
2015-01-05 22:51:27 +08:00
PrintAndLog ( " f - decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml` " ) ;
PrintAndLog ( " Usage: hf mf sniff [l][d][e][f] " ) ;
2012-07-16 22:49:51 +08:00
PrintAndLog ( " sample: hf mf sniff l d e " ) ;
2012-07-07 00:19:05 +08:00
return 0 ;
2017-07-12 21:58:32 +08:00
}
2012-07-16 22:49:51 +08:00
for ( int i = 0 ; i < 4 ; i + + ) {
2015-01-21 04:48:39 +08:00
ctmp = param_getchar ( Cmd , i ) ;
2012-07-16 22:49:51 +08:00
if ( ctmp = = ' l ' | | ctmp = = ' L ' ) wantLogToFile = true ;
if ( ctmp = = ' d ' | | ctmp = = ' D ' ) wantDecrypt = true ;
2012-07-20 17:04:23 +08:00
//if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO
2012-07-16 22:49:51 +08:00
if ( ctmp = = ' f ' | | ctmp = = ' F ' ) wantSaveToEmlFile = true ;
}
2017-07-12 21:58:32 +08:00
2012-07-11 23:52:33 +08:00
printf ( " ------------------------------------------------------------------------- \n " ) ;
printf ( " Executing command. \n " ) ;
printf ( " Press the key on the proxmark3 device to abort both proxmark3 and client. \n " ) ;
printf ( " Press the key on pc keyboard to abort the client. \n " ) ;
printf ( " ------------------------------------------------------------------------- \n " ) ;
2014-03-26 04:38:24 +08:00
UsbCommand c = { CMD_MIFARE_SNIFFER , { 0 , 0 , 0 } } ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2012-07-07 00:19:05 +08:00
2012-07-11 23:52:33 +08:00
// wait cycle
while ( true ) {
printf ( " . " ) ;
fflush ( stdout ) ;
if ( ukbhit ( ) ) {
getchar ( ) ;
printf ( " \n aborted via keyboard! \n " ) ;
break ;
}
2017-07-12 21:58:32 +08:00
2015-01-27 15:34:48 +08:00
UsbCommand resp ;
2018-01-13 05:37:55 +08:00
if ( WaitForResponseTimeoutW ( CMD_ACK , & resp , 2000 , false ) ) {
2012-12-05 07:39:18 +08:00
res = resp . arg [ 0 ] & 0xff ;
2015-01-27 15:34:48 +08:00
uint16_t traceLen = resp . arg [ 1 ] ;
len = resp . arg [ 2 ] ;
2017-02-23 16:40:12 +08:00
if ( res = = 0 ) { // we are done
2018-01-13 05:37:55 +08:00
break ;
2017-02-23 16:40:12 +08:00
}
2015-01-27 15:34:48 +08:00
if ( res = = 1 ) { // there is (more) data to be transferred
if ( pckNum = = 0 ) { // first packet, (re)allocate necessary buffer
2017-02-23 16:40:12 +08:00
if ( traceLen > bufsize | | buf = = NULL ) {
2015-01-27 15:34:48 +08:00
uint8_t * p ;
if ( buf = = NULL ) { // not yet allocated
p = malloc ( traceLen ) ;
} else { // need more memory
p = realloc ( buf , traceLen ) ;
}
if ( p = = NULL ) {
PrintAndLog ( " Cannot allocate memory for trace " ) ;
free ( buf ) ;
return 2 ;
}
buf = p ;
}
2012-07-11 23:52:33 +08:00
bufPtr = buf ;
2015-01-27 15:34:48 +08:00
bufsize = traceLen ;
memset ( buf , 0x00 , traceLen ) ;
2012-07-11 23:52:33 +08:00
}
2012-12-05 07:39:18 +08:00
memcpy ( bufPtr , resp . d . asBytes , len ) ;
2012-07-11 23:52:33 +08:00
bufPtr + = len ;
pckNum + + ;
}
2015-01-27 15:34:48 +08:00
if ( res = = 2 ) { // received all data, start displaying
2012-07-11 23:52:33 +08:00
blockLen = bufPtr - buf ;
bufPtr = buf ;
printf ( " > \n " ) ;
PrintAndLog ( " received trace len: %d packages: %d " , blockLen , pckNum ) ;
2014-12-16 14:41:07 +08:00
while ( bufPtr - buf < blockLen ) {
2015-01-27 15:34:48 +08:00
bufPtr + = 6 ; // skip (void) timing information
2014-12-16 14:41:07 +08:00
len = * ( ( uint16_t * ) bufPtr ) ;
if ( len & 0x8000 ) {
isTag = true ;
len & = 0x7fff ;
} else {
isTag = false ;
}
2018-02-09 22:50:55 +08:00
parlen = ( len - 1 ) / 8 + 1 ;
2014-12-16 14:41:07 +08:00
bufPtr + = 2 ;
if ( ( len = = 14 ) & & ( bufPtr [ 0 ] = = 0xff ) & & ( bufPtr [ 1 ] = = 0xff ) & & ( bufPtr [ 12 ] = = 0xff ) & & ( bufPtr [ 13 ] = = 0xff ) ) {
2012-07-11 23:52:33 +08:00
memcpy ( uid , bufPtr + 2 , 7 ) ;
memcpy ( atqa , bufPtr + 2 + 7 , 2 ) ;
2014-07-15 14:39:56 +08:00
uid_len = ( atqa [ 0 ] & 0xC0 ) = = 0x40 ? 7 : 4 ;
2012-07-11 23:52:33 +08:00
sak = bufPtr [ 11 ] ;
2017-07-12 21:58:32 +08:00
PrintAndLog ( " tag select uid:%s atqa:0x%02x%02x sak:0x%02x " ,
2014-07-15 14:39:56 +08:00
sprint_hex ( uid + ( 7 - uid_len ) , uid_len ) ,
2017-07-12 21:58:32 +08:00
atqa [ 1 ] ,
atqa [ 0 ] ,
2014-07-15 14:39:56 +08:00
sak ) ;
2014-03-26 04:38:24 +08:00
if ( wantLogToFile | | wantDecrypt ) {
2014-07-15 14:39:56 +08:00
FillFileNameByUID ( logHexFileName , uid + ( 7 - uid_len ) , " .log " , uid_len ) ;
2012-07-16 22:49:51 +08:00
AddLogCurrentDT ( logHexFileName ) ;
2017-07-12 21:58:32 +08:00
}
if ( wantDecrypt )
2015-01-05 22:51:27 +08:00
mfTraceInit ( uid , atqa , sak , wantSaveToEmlFile ) ;
2012-07-11 23:52:33 +08:00
} else {
2018-02-09 22:50:55 +08:00
oddparitybuf ( bufPtr , len , parity ) ;
PrintAndLog ( " %s(%d):%s [%s] c[%s]%c " ,
isTag ? " TAG " : " RDR " ,
num ,
sprint_hex ( bufPtr , len ) ,
printBitsPar ( bufPtr + len , len ) ,
printBitsPar ( parity , len ) ,
memcmp ( bufPtr + len , parity , len / 8 + 1 ) ? ' ! ' : ' ' ) ;
2017-07-12 21:58:32 +08:00
if ( wantLogToFile )
2015-01-05 22:51:27 +08:00
AddLogHex ( logHexFileName , isTag ? " TAG: " : " RDR: " , bufPtr , len ) ;
2017-07-12 21:58:32 +08:00
if ( wantDecrypt )
2018-02-09 22:50:55 +08:00
mfTraceDecode ( bufPtr , len , bufPtr [ len ] , wantSaveToEmlFile ) ;
2017-07-12 21:58:32 +08:00
num + + ;
2012-07-11 23:52:33 +08:00
}
bufPtr + = len ;
2018-02-09 22:50:55 +08:00
bufPtr + = parlen ; // ignore parity
2012-07-11 23:52:33 +08:00
}
2015-01-27 15:34:48 +08:00
pckNum = 0 ;
2012-07-11 23:52:33 +08:00
}
2015-01-05 22:51:27 +08:00
} // resp not NULL
2012-07-11 23:52:33 +08:00
} // while (true)
2015-01-27 15:34:48 +08:00
free ( buf ) ;
2018-01-13 05:37:55 +08:00
msleep ( 300 ) ; // wait for exiting arm side.
PrintAndLog ( " Done. " ) ;
2014-03-26 04:38:24 +08:00
return 0 ;
2012-07-07 00:19:05 +08:00
}
2015-10-07 12:24:55 +08:00
//needs nt, ar, at, Data to decrypt
int CmdDecryptTraceCmds ( const char * Cmd ) {
uint8_t data [ 50 ] ;
int len = 0 ;
param_gethex_ex ( Cmd , 3 , data , & len ) ;
return tryDecryptWord ( param_get32ex ( Cmd , 0 , 0 , 16 ) , param_get32ex ( Cmd , 1 , 0 , 16 ) , param_get32ex ( Cmd , 2 , 0 , 16 ) , data , len / 2 ) ;
}
2015-01-27 15:34:48 +08:00
2018-10-11 04:34:04 +08:00
int aes_encode ( uint8_t * iv , uint8_t * key , uint8_t * input , uint8_t * output , int length ) {
uint8_t iiv [ 16 ] = { 0 } ;
if ( iv )
memcpy ( iiv , iv , 16 ) ;
aes_context aes ;
aes_init ( & aes ) ;
if ( aes_setkey_enc ( & aes , key , 128 ) )
return 1 ;
if ( aes_crypt_cbc ( & aes , AES_ENCRYPT , length , iiv , input , output ) )
return 2 ;
aes_free ( & aes ) ;
return 0 ;
}
int aes_decode ( uint8_t * iv , uint8_t * key , uint8_t * input , uint8_t * output , int length ) {
uint8_t iiv [ 16 ] = { 0 } ;
if ( iv )
memcpy ( iiv , iv , 16 ) ;
aes_context aes ;
aes_init ( & aes ) ;
if ( aes_setkey_dec ( & aes , key , 128 ) )
return 1 ;
if ( aes_crypt_cbc ( & aes , AES_DECRYPT , length , iiv , input , output ) )
return 2 ;
aes_free ( & aes ) ;
return 0 ;
}
int CmdHF14AMfAuth4 ( const char * cmd ) {
uint8_t keyn [ 20 ] = { 0 } ;
int keynlen = 0 ;
uint8_t key [ 16 ] = { 0 } ;
int keylen = 0 ;
uint8_t data [ 257 ] = { 0 } ;
int datalen = 0 ;
uint8_t Rnd1 [ 17 ] = { 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f , 0x00 } ;
uint8_t Rnd2 [ 17 ] = { 0 } ;
CLIParserInit ( " hf mf auth4 " ,
" Executes AES authentication command in ISO14443-4 " ,
" Usage: \n \t hf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication \n "
" \t hf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication \n " ) ;
void * argtable [ ] = {
arg_param_begin ,
arg_str1 ( NULL , NULL , " <Key Num (HEX 2 bytes)> " , NULL ) ,
arg_str1 ( NULL , NULL , " <Key Value (HEX 16 bytes)> " , NULL ) ,
arg_param_end
} ;
CLIExecWithReturn ( cmd , argtable , true ) ;
CLIGetStrWithReturn ( 1 , keyn , & keynlen ) ;
CLIGetStrWithReturn ( 2 , key , & keylen ) ;
CLIParserFree ( ) ;
if ( keynlen ! = 2 ) {
PrintAndLog ( " ERROR: <Key Num> must be 2 bytes long instead of: %d " , keynlen ) ;
return 1 ;
}
if ( keylen ! = 16 ) {
PrintAndLog ( " ERROR: <Key Value> must be 16 bytes long instead of: %d " , keylen ) ;
return 1 ;
}
uint8_t cmd1 [ ] = { 0x0a , 0x00 , 0x70 , keyn [ 1 ] , keyn [ 0 ] , 0x00 } ;
int res = ExchangeRAW14a ( cmd1 , sizeof ( cmd1 ) , true , true , data , sizeof ( data ) , & datalen ) ;
if ( res ) {
PrintAndLog ( " ERROR exchande raw error: %d " , res ) ;
2018-10-12 01:28:29 +08:00
DropField ( ) ;
2018-10-11 04:34:04 +08:00
return 2 ;
}
PrintAndLog ( " <phase1: %s " , sprint_hex ( data , datalen ) ) ;
if ( datalen < 3 ) {
PrintAndLog ( " ERROR: card response length: %d " , datalen ) ;
2018-10-12 01:28:29 +08:00
DropField ( ) ;
2018-10-11 04:34:04 +08:00
return 3 ;
}
if ( data [ 0 ] ! = 0x0a | | data [ 1 ] ! = 0x00 ) {
PrintAndLog ( " ERROR: card response. Framing error. :%s " , sprint_hex ( data , 2 ) ) ;
2018-10-12 01:28:29 +08:00
DropField ( ) ;
2018-10-11 04:34:04 +08:00
return 3 ;
}
if ( data [ 2 ] ! = 0x90 ) {
PrintAndLog ( " ERROR: card response error: %02x " , data [ 2 ] ) ;
2018-10-12 01:28:29 +08:00
DropField ( ) ;
2018-10-11 04:34:04 +08:00
return 3 ;
}
if ( datalen ! = 19 ) {
PrintAndLog ( " ERROR: card response must be 16 bytes long instead of: %d " , datalen ) ;
2018-10-12 01:28:29 +08:00
DropField ( ) ;
2018-10-11 04:34:04 +08:00
return 3 ;
}
aes_decode ( NULL , key , & data [ 3 ] , Rnd2 , 16 ) ;
Rnd2 [ 16 ] = Rnd2 [ 0 ] ;
PrintAndLog ( " Rnd2: %s " , sprint_hex ( Rnd2 , 16 ) ) ;
uint8_t cmd2 [ 35 ] = { 0 } ;
cmd2 [ 0 ] = 0x0b ;
cmd2 [ 1 ] = 0x00 ;
cmd2 [ 2 ] = 0x72 ;
uint8_t raw [ 32 ] = { 0 } ;
memmove ( raw , Rnd1 , 16 ) ;
memmove ( & raw [ 16 ] , & Rnd2 [ 1 ] , 16 ) ;
aes_encode ( NULL , key , raw , & cmd2 [ 3 ] , 32 ) ;
PrintAndLog ( " >phase2: %s " , sprint_hex ( cmd2 , 35 ) ) ;
res = ExchangeRAW14a ( cmd2 , sizeof ( cmd2 ) , false , false , data , sizeof ( data ) , & datalen ) ;
if ( res ) {
PrintAndLog ( " ERROR exchande raw error: %d " , res ) ;
DropField ( ) ;
return 4 ;
}
PrintAndLog ( " <phase2: %s " , sprint_hex ( data , datalen ) ) ;
aes_decode ( NULL , key , & data [ 3 ] , raw , 32 ) ;
PrintAndLog ( " res: %s " , sprint_hex ( raw , 32 ) ) ;
PrintAndLog ( " Rnd1`: %s " , sprint_hex ( & raw [ 4 ] , 16 ) ) ;
if ( memcmp ( & raw [ 4 ] , & Rnd1 [ 1 ] , 16 ) ) {
PrintAndLog ( " \n ERROR: Authentication FAILED. rnd not equal " ) ;
PrintAndLog ( " rnd1 reader: %s " , sprint_hex ( & Rnd1 [ 1 ] , 16 ) ) ;
PrintAndLog ( " rnd1 card: %s " , sprint_hex ( & raw [ 4 ] , 16 ) ) ;
DropField ( ) ;
return 5 ;
}
DropField ( ) ;
PrintAndLog ( " \n Authentication OK " ) ;
return 0 ;
}
2011-08-30 17:52:18 +08:00
static command_t CommandTable [ ] =
2011-06-10 21:35:10 +08:00
{
2017-05-29 16:56:37 +08:00
{ " help " , CmdHelp , 1 , " This help " } ,
{ " dbg " , CmdHF14AMfDbg , 0 , " Set default debug mode " } ,
{ " rdbl " , CmdHF14AMfRdBl , 0 , " Read MIFARE classic block " } ,
{ " rdsc " , CmdHF14AMfRdSc , 0 , " Read MIFARE classic sector " } ,
{ " dump " , CmdHF14AMfDump , 0 , " Dump MIFARE classic tag to binary file " } ,
{ " restore " , CmdHF14AMfRestore , 0 , " Restore MIFARE classic binary file to BLANK tag " } ,
{ " wrbl " , CmdHF14AMfWrBl , 0 , " Write MIFARE classic block " } ,
2018-10-11 04:34:04 +08:00
{ " auth4 " , CmdHF14AMfAuth4 , 0 , " ISO14443-4 AES authentication " } ,
2017-05-29 16:56:37 +08:00
{ " chk " , CmdHF14AMfChk , 0 , " Test block keys " } ,
{ " mifare " , CmdHF14AMifare , 0 , " Read parity error messages. " } ,
{ " hardnested " , CmdHF14AMfNestedHard , 0 , " Nested attack for hardened Mifare cards " } ,
{ " nested " , CmdHF14AMfNested , 0 , " Test nested authentication " } ,
{ " sniff " , CmdHF14AMfSniff , 0 , " Sniff card-reader communication " } ,
{ " sim " , CmdHF14AMf1kSim , 0 , " Simulate MIFARE card " } ,
{ " eclr " , CmdHF14AMfEClear , 0 , " Clear simulator memory block " } ,
{ " eget " , CmdHF14AMfEGet , 0 , " Get simulator memory block " } ,
{ " eset " , CmdHF14AMfESet , 0 , " Set simulator memory block " } ,
{ " eload " , CmdHF14AMfELoad , 0 , " Load from file emul dump " } ,
{ " esave " , CmdHF14AMfESave , 0 , " Save to file emul dump " } ,
{ " ecfill " , CmdHF14AMfECFill , 0 , " Fill simulator memory with help of keys from simulator " } ,
{ " ekeyprn " , CmdHF14AMfEKeyPrn , 0 , " Print keys from simulator memory " } ,
2017-09-23 01:40:42 +08:00
{ " cwipe " , CmdHF14AMfCWipe , 0 , " Wipe magic Chinese card " } ,
2017-05-29 16:56:37 +08:00
{ " csetuid " , CmdHF14AMfCSetUID , 0 , " Set UID for magic Chinese card " } ,
{ " csetblk " , CmdHF14AMfCSetBlk , 0 , " Write block - Magic Chinese card " } ,
{ " cgetblk " , CmdHF14AMfCGetBlk , 0 , " Read block - Magic Chinese card " } ,
{ " cgetsc " , CmdHF14AMfCGetSc , 0 , " Read sector - Magic Chinese card " } ,
{ " cload " , CmdHF14AMfCLoad , 0 , " Load dump into magic Chinese card " } ,
{ " csave " , CmdHF14AMfCSave , 0 , " Save dump from magic Chinese card into file or emulator " } ,
{ " decrypt " , CmdDecryptTraceCmds , 1 , " [nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace " } ,
{ NULL , NULL , 0 , NULL }
2011-06-10 21:35:10 +08:00
} ;
int CmdHFMF ( const char * Cmd )
{
2018-06-13 14:13:20 +08:00
( void ) WaitForResponseTimeout ( CMD_ACK , NULL , 100 ) ;
CmdsParse ( CommandTable , Cmd ) ;
return 0 ;
2011-06-10 21:35:10 +08:00
}
int CmdHelp ( const char * Cmd )
{
CmdsHelp ( CommandTable ) ;
return 0 ;
}