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
//-----------------------------------------------------------------------------
# include "cmdhfmf.h"
2018-02-07 03:08:42 +08:00
# define MIFARE_4K_MAXBLOCK 255
# define MIFARE_2K_MAXBLOCK 128
# define MIFARE_1K_MAXBLOCK 64
# define MIFARE_MINI_MAXBLOCK 20
2011-06-10 21:35:10 +08:00
static int CmdHelp ( const char * Cmd ) ;
2018-02-07 22:33:32 +08:00
2018-02-08 22:52:53 +08:00
int usage_hf14_ice ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf ice [l] <limit> [f] <name> " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " l <limit> nonces to be collected " ) ;
PrintAndLogEx ( NORMAL , " f <name> save nonces to <name> instead of hf-mf-<UID>-nonces.bin " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf ice " ) ;
PrintAndLogEx ( NORMAL , " hf mf ice f nonces.bin " ) ;
2018-02-08 22:52:53 +08:00
return 0 ;
}
2018-02-07 22:33:32 +08:00
int usage_hf14_dump ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf dump [card memory] k <name> f <name> " ) ;
PrintAndLogEx ( NORMAL , " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLogEx ( NORMAL , " k <name> : key filename, if no <name> given, UID will be used as filename " ) ;
PrintAndLogEx ( NORMAL , " f <name> : data filename, if no <name> given, UID will be used as filename " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf dump " ) ;
PrintAndLogEx ( NORMAL , " hf mf dump 4 " ) ;
2018-02-07 22:33:32 +08:00
return 0 ;
}
2016-04-18 19:18:02 +08:00
int usage_hf14_mifare ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf darkside [h] <block number> <A|B> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <block number> (Optional) target other block " ) ;
PrintAndLogEx ( NORMAL , " <A|B> (optional) target key type " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf darkside " ) ;
PrintAndLogEx ( NORMAL , " hf mf darkside 16 " ) ;
PrintAndLogEx ( NORMAL , " hf mf darkside 16 B " ) ;
2016-04-18 19:18:02 +08:00
return 0 ;
}
int usage_hf14_mf1ksim ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf sim [h] u <uid> n <numreads> [i] [x] [e] [v] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used " ) ;
PrintAndLogEx ( NORMAL , " n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite " ) ;
PrintAndLogEx ( NORMAL , " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted " ) ;
PrintAndLogEx ( NORMAL , " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader " ) ;
PrintAndLogEx ( NORMAL , " e (Optional) Fill simulator keys from found keys " ) ;
PrintAndLogEx ( NORMAL , " v (Optional) Verbose " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf sim u 0a0a0a0a " ) ;
PrintAndLogEx ( NORMAL , " hf mf sim u 11223344556677 " ) ;
PrintAndLogEx ( NORMAL , " hf mf sim u 112233445566778899AA " ) ;
PrintAndLogEx ( NORMAL , " hf mf sim u 11223344 i x " ) ;
2016-04-18 19:18:02 +08:00
return 0 ;
}
int usage_hf14_dbg ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf dbg [h] <debug level> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <debug level> (Optional) see list for valid levels " ) ;
PrintAndLogEx ( NORMAL , " 0 - no debug messages " ) ;
PrintAndLogEx ( NORMAL , " 1 - error messages " ) ;
PrintAndLogEx ( NORMAL , " 2 - plus information messages " ) ;
PrintAndLogEx ( NORMAL , " 3 - plus debug messages " ) ;
PrintAndLogEx ( NORMAL , " 4 - print even debug messages in timing critical functions " ) ;
PrintAndLogEx ( NORMAL , " Note: this option therefore may cause malfunction itself " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf dbg 3 " ) ;
2016-04-18 19:18:02 +08:00
return 0 ;
}
int usage_hf14_sniff ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It continuously gets data from the field and saves it to: log, emulator, emulator file. " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf sniff [h] [l] [d] [f] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " l save encrypted sequence to logfile `uid.log` " ) ;
PrintAndLogEx ( NORMAL , " d decrypt sequence and put it to log file `uid.log` " ) ;
// PrintAndLogEx(NORMAL, " n/a e decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory");
PrintAndLogEx ( NORMAL , " f decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml` " ) ;
PrintAndLogEx ( NORMAL , " Example: " ) ;
PrintAndLogEx ( NORMAL , " hf mf sniff l d f " ) ;
2016-04-18 19:18:02 +08:00
return 0 ;
}
2016-04-23 18:18:34 +08:00
int usage_hf14_nested ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: " ) ;
PrintAndLogEx ( NORMAL , " all sectors: hf mf nested <card memory> <block number> <key A/B> <key (12 hex symbols)> [t,d] " ) ;
PrintAndLogEx ( NORMAL , " one sector: hf mf nested o <block number> <key A/B> <key (12 hex symbols)> " ) ;
PrintAndLogEx ( NORMAL , " <target block number> <target key A/B> [t] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K " ) ;
PrintAndLogEx ( NORMAL , " t transfer keys into emulator memory " ) ;
PrintAndLogEx ( NORMAL , " d write keys to binary file `hf-mf-<UID>-key.bin` " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf nested 1 0 A FFFFFFFFFFFF " ) ;
PrintAndLogEx ( NORMAL , " hf mf nested 1 0 A FFFFFFFFFFFF t " ) ;
PrintAndLogEx ( NORMAL , " hf mf nested 1 0 A FFFFFFFFFFFF d " ) ;
PrintAndLogEx ( NORMAL , " hf mf nested o 0 A FFFFFFFFFFFF 4 A " ) ;
2016-04-23 18:18:34 +08:00
return 0 ;
}
int usage_hf14_hardnested ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested <block number> <key A|B> <key (12 hex symbols)> " ) ;
PrintAndLogEx ( NORMAL , " <target block number> <target key A|B> [known target key (12 hex symbols)] [w] [s] " ) ;
PrintAndLogEx ( NORMAL , " or hf mf hardnested r [known target key] " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " w acquire nonces and UID, and write them to binary file with default name hf-mf-<UID>-nonces.bin " ) ;
PrintAndLogEx ( NORMAL , " s slower acquisition (required by some non standard cards) " ) ;
PrintAndLogEx ( NORMAL , " r read hf-mf-<UID>-nonces.bin if tag present, otherwise read nonces.bin, then start attack " ) ;
PrintAndLogEx ( NORMAL , " u <UID> read/write hf-mf-<UID>-nonces.bin instead of default name " ) ;
PrintAndLogEx ( NORMAL , " f <name> read/write <name> instead of default name " ) ;
PrintAndLogEx ( NORMAL , " t tests? " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested 0 A FFFFFFFFFFFF 4 A " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested 0 A FFFFFFFFFFFF 4 A w " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested 0 A FFFFFFFFFFFF 4 A f nonces.bin w s " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested r " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested r a0a1a2a3a4a5 " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Add the known target key to check if it is present in the remaining key space: " ) ;
PrintAndLogEx ( NORMAL , " hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF " ) ;
2016-04-23 18:18:34 +08:00
return 0 ;
}
int usage_hf14_chk ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf chk [h] <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " * all sectors based on card memory, other values then below defaults to 1k " ) ;
PrintAndLogEx ( NORMAL , " 0 - MINI(320 bytes) " ) ;
PrintAndLogEx ( NORMAL , " 1 - 1K " ) ;
PrintAndLogEx ( NORMAL , " 2 - 2K " ) ;
PrintAndLogEx ( NORMAL , " 4 - 4K " ) ;
PrintAndLogEx ( NORMAL , " d write keys to binary file " ) ;
PrintAndLogEx ( NORMAL , " t write keys to emulator memory \n " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf chk 0 A 1234567890ab keys.dic -- target block 0, Key A " ) ;
PrintAndLogEx ( NORMAL , " hf mf chk *1 ? t -- target all blocks, all keys, 1K, write to emul " ) ;
PrintAndLogEx ( NORMAL , " hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file " ) ;
2016-04-23 18:18:34 +08:00
return 0 ;
}
2017-10-05 22:00:56 +08:00
int usage_hf14_chk_fast ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf fchk [h] <card memory> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <cardmem> all sectors based on card memory, other values than below defaults to 1k " ) ;
PrintAndLogEx ( NORMAL , " 0 - MINI(320 bytes) " ) ;
PrintAndLogEx ( NORMAL , " 1 - 1K <default> " ) ;
PrintAndLogEx ( NORMAL , " 2 - 2K " ) ;
PrintAndLogEx ( NORMAL , " 4 - 4K " ) ;
PrintAndLogEx ( NORMAL , " d write keys to binary file " ) ;
PrintAndLogEx ( NORMAL , " t write keys to emulator memory \n " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf fchk 1 1234567890ab keys.dic -- target 1K using key 1234567890ab, using dictionary file " ) ;
PrintAndLogEx ( NORMAL , " hf mf fchk 1 t -- target 1K, write to emulator memory " ) ;
PrintAndLogEx ( NORMAL , " hf mf fchk 1 d -- target 1K, write to file " ) ;
2017-10-05 22:00:56 +08:00
return 0 ;
}
2016-08-08 23:49:30 +08:00
int usage_hf14_keybrute ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " J_Run's 2nd phase of multiple sector nested authentication key recovery " ) ;
PrintAndLogEx ( NORMAL , " You have a known 4 last bytes of a key recovered with mf_nonce_brute tool. " ) ;
PrintAndLogEx ( NORMAL , " First 2 bytes of key will be bruteforced " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " ---[ This attack is obsolete, try hardnested instead ]--- " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf keybrute [h] <block number> <A|B> <key> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <block number> target block number " ) ;
PrintAndLogEx ( NORMAL , " <A|B> target key type " ) ;
PrintAndLogEx ( NORMAL , " <key> candidate key from mf_nonce_brute tool " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf keybrute 1 A 000011223344 " ) ;
2016-08-08 23:49:30 +08:00
return 0 ;
}
2017-07-13 19:10:46 +08:00
int usage_hf14_restore ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf restore [card memory] u <UID> k <name> f <name> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLogEx ( NORMAL , " u <UID> : uid, try to restore from hf-mf-<UID>-key.bin and hf-mf-<UID>-data.bin " ) ;
PrintAndLogEx ( NORMAL , " k <name> : key filename, specific the full filename of key file " ) ;
PrintAndLogEx ( NORMAL , " f <name> : data filename, specific the full filename of data file " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf restore -- read the UID from tag first, then restore from hf-mf-<UID>-key.bin and and hf-mf-<UID>-data.bin " ) ;
PrintAndLogEx ( NORMAL , " hf mf restore 1 u 12345678 -- restore from hf-mf-12345678-key.bin and hf-mf-12345678-data.bin " ) ;
PrintAndLogEx ( NORMAL , " hf mf restore 1 u 12345678 k dumpkey.bin -- restore from dumpkey.bin and hf-mf-12345678-data.bin " ) ;
PrintAndLogEx ( NORMAL , " hf mf restore 4 -- read the UID from tag with 4K memory first, then restore from hf-mf-<UID>-key.bin and and hf-mf-<UID>-data.bin " ) ;
2017-07-13 19:10:46 +08:00
return 0 ;
}
2017-08-31 01:13:49 +08:00
int usage_hf14_decryptbytes ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values \n " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf decrypt [h] <nt> <ar_enc> <at_enc> <data> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <nt> reader nonce " ) ;
PrintAndLogEx ( NORMAL , " <ar_enc> encrypted reader response " ) ;
PrintAndLogEx ( NORMAL , " <at_enc> encrypted tag response " ) ;
PrintAndLogEx ( NORMAL , " <data> encrypted data, taken directly after at_enc and forward " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf decrypt b830049b 9248314a 9280e203 41e586f9 \n " ) ;
PrintAndLogEx ( NORMAL , " this sample decrypts 41e586f9 -> 3003999a Annotated: 30 03 [99 9a] auth block 3 [crc] " ) ;
2017-08-31 01:13:49 +08:00
return 0 ;
}
2011-06-10 21:35:10 +08:00
2017-07-11 23:45:23 +08:00
int usage_hf14_eget ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf eget <block number> " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf eget 0 " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_eclr ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf eclr " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_eset ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf eset <block number> <block data (32 hex symbols)> " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf eset 1 000102030405060708090a0b0c0d0e0f " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_eload ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It loads emul dump from the file `filename.eml` " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf eload [card memory] <file name w/o `.eml`> [numblocks] " ) ;
PrintAndLogEx ( NORMAL , " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf eload filename " ) ;
PrintAndLogEx ( NORMAL , " hf mf eload 4 filename " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_esave ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It saves emul dump into the file `filename.eml` or `cardID.eml` " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf esave [card memory] [file name w/o `.eml`] " ) ;
PrintAndLogEx ( NORMAL , " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf esave " ) ;
PrintAndLogEx ( NORMAL , " hf mf esave 4 " ) ;
PrintAndLogEx ( NORMAL , " hf mf esave 4 filename " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_ecfill ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Read card and transfer its data to emulator memory. " ) ;
PrintAndLogEx ( NORMAL , " Keys must be laid in the emulator memory. \n " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf ecfill <key A/B> [card memory] " ) ;
PrintAndLogEx ( NORMAL , " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf ecfill A " ) ;
PrintAndLogEx ( NORMAL , " hf mf ecfill A 4 " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
2017-07-13 19:10:46 +08:00
int usage_hf14_ekeyprn ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It prints the keys loaded in the emulator memory " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf ekeyprn [card memory] " ) ;
PrintAndLogEx ( NORMAL , " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf ekeyprn 1 " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_csetuid ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf csetuid [h] <UID 8 hex symbols> [ATQA 4 hex symbols] [SAK 2 hex symbols] [w] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " w wipe card before writing " ) ;
PrintAndLogEx ( NORMAL , " <uid> UID 8 hex symbols " ) ;
PrintAndLogEx ( NORMAL , " <atqa> ATQA 4 hex symbols " ) ;
PrintAndLogEx ( NORMAL , " <sak> SAK 2 hex symbols " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf csetuid 01020304 " ) ;
PrintAndLogEx ( NORMAL , " hf mf csetuid 01020304 0004 08 w " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_csetblk ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Set block data for magic Chinese card. Only works with magic cards " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf csetblk [h] <block number> <block data (32 hex symbols)> [w] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " w wipe card before writing " ) ;
PrintAndLogEx ( NORMAL , " <block> block number " ) ;
PrintAndLogEx ( NORMAL , " <data> block data to write (32 hex symbols) " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf csetblk 1 01020304050607080910111213141516 " ) ;
PrintAndLogEx ( NORMAL , " hf mf csetblk 1 01020304050607080910111213141516 w " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_cload ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It loads magic Chinese card from the file `filename.eml` " ) ;
PrintAndLogEx ( NORMAL , " or from emulator memory " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf cload [h] [e] <file name w/o `.eml`> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " e load card with data from emulator memory " ) ;
PrintAndLogEx ( NORMAL , " <filename> load card with data from file " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf cload mydump " ) ;
PrintAndLogEx ( NORMAL , " hf mf cload e " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_cgetblk ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Get block data from magic Chinese card. Only works with magic cards \n " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf cgetblk [h] <block number> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <block> block number " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf cgetblk 1 " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_cgetsc ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Get sector data from magic Chinese card. Only works with magic cards \n " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf cgetsc [h] <sector number> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " <sector> sector number " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf cgetsc 0 " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
int usage_hf14_csave ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml` " ) ;
PrintAndLogEx ( NORMAL , " or into emulator memory " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf csave [h] [e] [u] [card memory] i <file name w/o `.eml`> " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " e save data to emulator memory " ) ;
PrintAndLogEx ( NORMAL , " u save data to file, use carduid as filename " ) ;
PrintAndLogEx ( NORMAL , " card memory 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K " ) ;
PrintAndLogEx ( NORMAL , " o <filename> save data to file " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf csave u 1 " ) ;
PrintAndLogEx ( NORMAL , " hf mf csave e 1 " ) ;
PrintAndLogEx ( NORMAL , " hf mf csave 4 o filename " ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
}
2017-12-06 06:34:52 +08:00
int usage_hf14_nack ( void ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Test a mifare classic based card for the NACK bug. " ) ;
PrintAndLogEx ( NORMAL , " " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf nack [h] [v] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h this help " ) ;
PrintAndLogEx ( NORMAL , " v verbose " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf nack " ) ;
2017-12-06 06:34:52 +08:00
return 0 ;
}
2017-07-11 23:45:23 +08:00
2018-02-05 18:59:24 +08:00
int GetHFMF14AUID ( uint8_t * uid , int * uidlen ) {
2018-02-10 00:01:50 +08:00
UsbCommand c = { CMD_READER_ISO_14443a , { ISO14A_CONNECT , 0 , 0 } } ;
2018-02-05 00:30:40 +08:00
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
UsbCommand resp ;
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 2500 ) ) {
//if (!silent)
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " iso14443a card select failed " ) ;
2018-02-05 00:30:40 +08:00
DropField ( ) ;
return 0 ;
}
iso14a_card_select_t card ;
memcpy ( & card , ( iso14a_card_select_t * ) resp . d . asBytes , sizeof ( iso14a_card_select_t ) ) ;
memcpy ( uid , card . uid , card . uidlen * sizeof ( uint8_t ) ) ;
2018-02-05 18:59:24 +08:00
* uidlen = card . uidlen ;
2018-02-05 00:30:40 +08:00
return 1 ;
}
char * GenerateFilename ( const char * prefix , const char * suffix ) {
2018-02-05 22:36:30 +08:00
uint8_t uid [ 10 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2018-02-05 18:59:24 +08:00
int uidlen = 0 ;
2018-02-05 00:30:40 +08:00
char * fptr = malloc ( sizeof ( char ) * ( strlen ( prefix ) + strlen ( suffix ) ) + sizeof ( uid ) * 2 + 1 ) ;
2018-02-07 22:00:25 +08:00
GetHFMF14AUID ( uid , & uidlen ) ;
if ( ! uidlen ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " No tag found. " ) ;
2018-02-05 00:30:40 +08:00
return NULL ;
}
2018-02-05 18:59:24 +08:00
strcpy ( fptr , prefix ) ;
FillFileNameByUID ( fptr , uid , suffix , uidlen ) ;
2018-02-05 00:30:40 +08:00
return fptr ;
}
2018-02-05 23:50:06 +08:00
int CmdHF14ADarkside ( const char * Cmd ) {
2017-07-28 02:58:59 +08:00
uint8_t blockno = 0 , key_type = MIFARE_AUTH_KEYA ;
uint64_t key = 0 ;
2016-01-21 05:26:01 +08:00
char cmdp = param_getchar ( Cmd , 0 ) ;
2016-04-18 19:18:02 +08:00
if ( cmdp = = ' H ' | | cmdp = = ' h ' ) return usage_hf14_mifare ( ) ;
2016-01-19 23:58:07 +08:00
2017-07-28 02:58:59 +08:00
blockno = param_get8 ( Cmd , 0 ) ;
2016-08-05 03:51:26 +08:00
cmdp = param_getchar ( Cmd , 1 ) ;
if ( cmdp = = ' B ' | | cmdp = = ' b ' )
2017-07-28 02:58:59 +08:00
key_type = MIFARE_AUTH_KEYB ;
int isOK = mfDarkside ( blockno , key_type , & key ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2017-07-28 02:58:59 +08:00
switch ( isOK ) {
2018-02-21 14:52:22 +08:00
case - 1 : PrintAndLogEx ( WARNING , " button pressed. Aborted. " ) ; return 1 ;
case - 2 : PrintAndLogEx ( FAILED , " card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). " ) ; return 1 ;
case - 3 : PrintAndLogEx ( FAILED , " card is not vulnerable to Darkside attack (its random number generator is not predictable). " ) ; return 1 ;
case - 4 : PrintAndLogEx ( FAILED , " card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown " ) ;
PrintAndLogEx ( FAILED , " generating polynomial with 16 effective bits only, but shows unexpected behaviour. " ) ; return 1 ;
case - 5 : PrintAndLogEx ( WARNING , " aborted via keyboard. " ) ; return 1 ;
default : PrintAndLogEx ( SUCCESS , " found valid key: %012 " PRIx64 " \n " , key ) ; break ;
}
PrintAndLogEx ( NORMAL , " " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
2016-04-23 18:26:29 +08:00
int CmdHF14AMfWrBl ( const char * Cmd ) {
2011-06-10 21:35:10 +08:00
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 } ;
char cmdp = 0x00 ;
if ( strlen ( Cmd ) < 3 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)> " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
blockNo = param_get8 ( Cmd , 0 ) ;
cmdp = param_getchar ( Cmd , 1 ) ;
if ( cmdp = = 0x00 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key type must be A or B " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
if ( cmdp ! = ' A ' & & cmdp ! = ' a ' ) keyType = 1 ;
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key must include 12 HEX symbols " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
if ( param_gethex ( Cmd , 3 , bldata , 32 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Block data must include 32 HEX symbols " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --block no:%d, key type:%c, key:%s " , blockNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
PrintAndLogEx ( NORMAL , " --data: %s " , sprint_hex ( bldata , 16 ) ) ;
2011-06-10 21:35:10 +08:00
2015-10-13 03:30:54 +08:00
UsbCommand c = { CMD_MIFARE_WRITEBL , { blockNo , keyType , 0 } } ;
2011-06-10 21:35:10 +08:00
memcpy ( c . d . asBytes , key , 6 ) ;
memcpy ( c . d . asBytes + 10 , bldata , 16 ) ;
2015-10-13 03:30:54 +08:00
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2011-06-10 21:35:10 +08:00
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
2017-08-29 21:47:26 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2012-12-05 07:39:18 +08:00
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " isOk:%02x " , isOK ) ;
2011-06-10 21:35:10 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Command execute timeout " ) ;
2011-06-10 21:35:10 +08:00
}
2014-02-01 05:17:34 +08:00
return 0 ;
}
2016-04-23 18:26:29 +08:00
int CmdHF14AMfRdBl ( const char * Cmd ) {
2014-02-01 05:17:34 +08:00
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-02-23 07:03:10 +08:00
char cmdp = 0x00 ;
2011-06-10 21:35:10 +08:00
if ( strlen ( Cmd ) < 3 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)> " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf rdbl 0 A FFFFFFFFFFFF " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
blockNo = param_get8 ( Cmd , 0 ) ;
cmdp = param_getchar ( Cmd , 1 ) ;
if ( cmdp = = 0x00 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key type must be A or B " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
if ( cmdp ! = ' A ' & & cmdp ! = ' a ' ) keyType = 1 ;
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key must include 12 HEX symbols " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --block no:%d, key type:%c, key:%s " , blockNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
2011-06-10 21:35:10 +08:00
2015-10-13 03:30:54 +08:00
UsbCommand c = { CMD_MIFARE_READBL , { blockNo , keyType , 0 } } ;
2011-06-10 21:35:10 +08:00
memcpy ( c . d . asBytes , key , 6 ) ;
2015-10-13 03:30:54 +08:00
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2011-06-10 21:35:10 +08:00
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
2017-03-09 18:19:30 +08:00
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 )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " isOk:%02x data:%s " , isOK , sprint_hex ( data , 16 ) ) ;
2011-06-10 21:35:10 +08:00
else
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " isOk:%02x " , isOK ) ;
2011-06-10 21:35:10 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Command execute timeout " ) ;
2011-06-10 21:35:10 +08:00
}
2014-02-01 05:17:34 +08:00
return 0 ;
}
2016-04-23 18:26:29 +08:00
int CmdHF14AMfRdSc ( const char * Cmd ) {
2014-02-01 05:17:34 +08:00
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 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf mf rdsc <sector number> <key A/B> <key (12 hex symbols)> " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf mf rdsc 0 A FFFFFFFFFFFF " ) ;
2011-06-10 21:35:10 +08:00
return 0 ;
}
sectorNo = param_get8 ( Cmd , 0 ) ;
2014-09-11 01:04:50 +08:00
if ( sectorNo > 39 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " 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 ' ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key type must be A or B " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
if ( cmdp ! = ' A ' & & cmdp ! = ' a ' ) keyType = 1 ;
if ( param_gethex ( Cmd , 2 , key , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key must include 12 HEX symbols " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --sector no:%d key type:%c key:%s " , sectorNo , keyType ? ' B ' : ' A ' , sprint_hex ( key , 6 ) ) ;
2011-06-10 21:35:10 +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 ) ;
2015-10-13 03:30:54 +08:00
clearCommandBuffer ( ) ;
2014-09-11 01:04:50 +08:00
SendCommand ( & c ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2011-06-10 21:35:10 +08:00
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
2017-08-29 21:47:26 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2012-12-05 07:39:18 +08:00
isOK = resp . arg [ 0 ] & 0xff ;
data = resp . d . asBytes ;
2011-06-10 21:35:10 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " isOk:%02x " , isOK ) ;
2014-09-11 01:04:50 +08:00
if ( isOK ) {
for ( i = 0 ; i < ( sectorNo < 32 ? 3 : 15 ) ; i + + ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " data : %s " , sprint_hex ( data + i * 16 , 16 ) ) ;
2011-06-10 21:35:10 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " trailer: %s " , sprint_hex ( data + ( sectorNo < 32 ? 3 : 15 ) * 16 , 16 ) ) ;
2014-09-11 01:04:50 +08:00
}
2011-06-10 21:35:10 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " 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
2017-07-11 23:45:23 +08:00
uint8_t NumOfBlocks ( char card ) {
switch ( card ) {
case ' 0 ' : return MIFARE_MINI_MAXBLOCK ;
case ' 1 ' : return MIFARE_1K_MAXBLOCK ;
case ' 2 ' : return MIFARE_2K_MAXBLOCK ;
case ' 4 ' : return MIFARE_4K_MAXBLOCK ;
default : return MIFARE_1K_MAXBLOCK ;
}
}
uint8_t NumOfSectors ( char card ) {
switch ( card ) {
case ' 0 ' : return 5 ;
case ' 1 ' : return 16 ;
case ' 2 ' : return 32 ;
case ' 4 ' : return 40 ;
default : return 16 ;
}
}
2016-04-23 18:26:29 +08:00
uint8_t FirstBlockOfSector ( uint8_t sectorNo ) {
2014-09-11 01:04:50 +08:00
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
}
}
2016-04-23 18:26:29 +08:00
uint8_t NumBlocksPerSector ( uint8_t sectorNo ) {
2014-09-11 01:04:50 +08:00
if ( sectorNo < 32 ) {
return 4 ;
} else {
return 16 ;
}
}
2016-04-18 19:18:02 +08:00
int CmdHF14AMfDump ( const char * Cmd ) {
2018-02-07 03:08:42 +08:00
2014-09-11 01:04:50 +08:00
uint8_t sectorNo , blockNo ;
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 ;
2018-02-07 22:33:32 +08:00
uint8_t cmdp = 0 ;
char keyFilename [ FILE_PATH_SIZE ] = { 0 } ;
char dataFilename [ FILE_PATH_SIZE ] = { 0 } ;
char * fptr ;
2018-02-05 00:30:40 +08:00
2017-07-11 23:45:23 +08:00
FILE * fin , * fout ;
2012-12-05 07:39:18 +08:00
UsbCommand resp ;
2014-09-11 01:04:50 +08:00
2018-02-07 22:33:32 +08:00
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 ) {
switch ( param_getchar ( Cmd , cmdp ) ) {
case ' h ' :
case ' H ' :
return usage_hf14_dump ( ) ;
case ' k ' :
case ' K ' :
param_getstr ( Cmd , cmdp + 1 , keyFilename , FILE_PATH_SIZE ) ;
cmdp + = 2 ;
break ;
case ' f ' :
case ' F ' :
param_getstr ( Cmd , cmdp + 1 , dataFilename , FILE_PATH_SIZE ) ;
cmdp + = 2 ;
break ;
default :
if ( cmdp = = 0 )
{
numSectors = NumOfSectors ( param_getchar ( Cmd , cmdp ) ) ;
cmdp + + ;
}
else
{
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Unknown parameter '%c' \n " , param_getchar ( Cmd , cmdp ) ) ;
2018-02-07 22:33:32 +08:00
return usage_hf14_dump ( ) ;
}
}
2014-09-11 01:04:50 +08:00
}
2018-02-07 22:33:32 +08:00
if ( keyFilename [ 0 ] = = 0x00 )
{
fptr = GenerateFilename ( " hf-mf- " , " -key.bin " ) ;
if ( fptr = = NULL )
return 1 ;
strcpy ( keyFilename , fptr ) ;
}
if ( ( fin = fopen ( keyFilename , " rb " ) ) = = NULL ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " Could not find file %s " , keyFilename ) ;
2011-08-30 17:52:18 +08:00
return 1 ;
}
2015-01-05 22:51:27 +08:00
// Read keys A from file
2016-01-20 02:52:01 +08:00
size_t bytes_read ;
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2016-01-20 02:52:01 +08:00
bytes_read = fread ( keyA [ sectorNo ] , 1 , 6 , fin ) ;
2017-02-24 08:14:47 +08:00
if ( bytes_read ! = 6 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " 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
}
2014-09-11 01:04:50 +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 + + ) {
2016-01-20 02:52:01 +08:00
bytes_read = fread ( keyB [ sectorNo ] , 1 , 6 , fin ) ;
2017-02-24 08:14:47 +08:00
if ( bytes_read ! = 6 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " 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
}
2015-01-08 05:00:29 +08:00
2014-10-28 05:33:37 +08:00
fclose ( fin ) ;
2016-10-21 22:06:53 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |-----------------------------------------| " ) ;
PrintAndLogEx ( NORMAL , " |------ Reading sector access bits...-----| " ) ;
PrintAndLogEx ( NORMAL , " |-----------------------------------------| " ) ;
2017-03-02 03:14:46 +08:00
uint8_t tries = 0 ;
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2018-02-07 03:08:42 +08:00
for ( tries = 0 ; tries < MIFARE_SECTOR_RETRY ; tries + + ) {
UsbCommand c = { CMD_MIFARE_READBL , { FirstBlockOfSector ( sectorNo ) + NumBlocksPerSector ( sectorNo ) - 1 , 0 , 0 } } ;
memcpy ( c . d . asBytes , keyA [ sectorNo ] , 6 ) ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2011-08-30 17:52:18 +08:00
2018-02-07 03:08: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
2017-03-02 03:14:46 +08:00
break ;
} else if ( tries = = 2 ) { // on last try set defaults
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " could not get access rights for sector %2d. Trying with defaults... " , sectorNo ) ;
2018-02-07 03:08:42 +08:00
rights [ sectorNo ] [ 0 ] = rights [ sectorNo ] [ 1 ] = rights [ sectorNo ] [ 2 ] = 0x00 ;
rights [ sectorNo ] [ 3 ] = 0x01 ;
}
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " 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
}
}
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |-----------------------------------------| " ) ;
PrintAndLogEx ( NORMAL , " |----- Dumping all blocks to file... -----| " ) ;
PrintAndLogEx ( NORMAL , " |-----------------------------------------| " ) ;
2011-08-30 17:52:18 +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 ;
2018-02-07 03:08:42 +08:00
for ( tries = 0 ; tries < MIFARE_SECTOR_RETRY ; 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 ) ;
2015-10-13 03:30:54 +08:00
clearCommandBuffer ( ) ;
2014-09-12 02:58:34 +08:00
SendCommand ( & c ) ;
2018-02-07 03:08:42 +08:00
received = WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ;
} 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 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " access rights do not allow reading of sector %2d block %3d " , sectorNo , blockNo ) ;
2018-02-07 03:08:42 +08:00
tries = MIFARE_SECTOR_RETRY ;
} else { // key A would work
UsbCommand c = { CMD_MIFARE_READBL , { FirstBlockOfSector ( sectorNo ) + blockNo , 0 , 0 } } ;
memcpy ( c . d . asBytes , keyA [ sectorNo ] , 6 ) ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
received = WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ;
2017-03-02 03:14:46 +08:00
}
}
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 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " successfully read block %2d of sector %2d. " , blockNo , sectorNo ) ;
2014-09-11 01:04:50 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " 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 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " command execute timeout when trying to 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
}
}
}
2014-09-12 02:58:34 +08:00
if ( isOK ) {
2018-02-07 22:33:32 +08:00
if ( dataFilename [ 0 ] = = 0x00 ) {
fptr = GenerateFilename ( " hf-mf- " , " -data.bin " ) ;
if ( fptr = = NULL )
return 1 ;
strcpy ( dataFilename , fptr ) ;
}
if ( ( fout = fopen ( dataFilename , " wb " ) ) = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " could not create file name %s " , dataFilename ) ;
2014-09-12 02:58:34 +08:00
return 1 ;
}
uint16_t numblocks = FirstBlockOfSector ( numSectors - 1 ) + NumBlocksPerSector ( numSectors - 1 ) ;
fwrite ( carddata , 1 , 16 * numblocks , fout ) ;
fclose ( fout ) ;
2018-02-22 09:36:11 +08:00
PrintAndLogEx ( SUCCESS , " dumped %d blocks (%d bytes) to file %s " , numblocks , 16 * numblocks , dataFilename ) ;
2014-09-12 02:58:34 +08:00
}
2014-09-11 01:04:50 +08:00
return 0 ;
2011-08-30 17:52:18 +08:00
}
2016-04-18 19:18:02 +08:00
int CmdHF14AMfRestore ( const char * Cmd ) {
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 ] ;
2018-02-08 00:17:19 +08:00
uint8_t numSectors = 16 ;
uint8_t cmdp = 0 ;
char keyFilename [ FILE_PATH_SIZE ] = " " ;
char dataFilename [ FILE_PATH_SIZE ] = " " ;
char szTemp [ FILE_PATH_SIZE ] = " " ;
char * fptr ;
2017-07-11 23:45:23 +08:00
FILE * fdump , * fkeys ;
2014-09-11 01:04:50 +08:00
2018-02-08 00:17:19 +08:00
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 ) {
switch ( param_getchar ( Cmd , cmdp ) ) {
case ' h ' :
case ' H ' :
return usage_hf14_restore ( ) ;
case ' u ' :
case ' U ' :
param_getstr ( Cmd , cmdp + 1 , szTemp , FILE_PATH_SIZE ) ;
if ( keyFilename [ 0 ] = = 0x00 )
snprintf ( keyFilename , FILE_PATH_SIZE , " hf-mf-%s-key.bin " , szTemp ) ;
if ( dataFilename [ 0 ] = = 0x00 )
snprintf ( dataFilename , FILE_PATH_SIZE , " hf-mf-%s-data.bin " , szTemp ) ;
cmdp + = 2 ;
break ;
case ' k ' :
case ' K ' :
param_getstr ( Cmd , cmdp + 1 , keyFilename , FILE_PATH_SIZE ) ;
cmdp + = 2 ;
break ;
case ' f ' :
case ' F ' :
param_getstr ( Cmd , cmdp + 1 , dataFilename , FILE_PATH_SIZE ) ;
cmdp + = 2 ;
break ;
default :
if ( cmdp = = 0 )
{
numSectors = NumOfSectors ( param_getchar ( Cmd , cmdp ) ) ;
cmdp + + ;
}
else
{
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Unknown parameter '%c' \n " , param_getchar ( Cmd , cmdp ) ) ;
2018-02-08 00:17:19 +08:00
return usage_hf14_restore ( ) ;
}
}
}
if ( keyFilename [ 0 ] = = 0x00 )
{
fptr = GenerateFilename ( " hf-mf- " , " -key.bin " ) ;
if ( fptr = = NULL )
return 1 ;
strcpy ( keyFilename , fptr ) ;
}
2014-09-11 01:04:50 +08:00
2018-02-08 00:17:19 +08:00
if ( ( fkeys = fopen ( keyFilename , " rb " ) ) = = NULL ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " Could not find file %s " , keyFilename ) ;
2011-08-30 17:52:18 +08:00
return 1 ;
}
2016-01-20 02:52:01 +08:00
size_t bytes_read ;
2014-09-11 01:04:50 +08:00
for ( sectorNo = 0 ; sectorNo < numSectors ; sectorNo + + ) {
2016-01-20 02:52:01 +08:00
bytes_read = fread ( keyA [ sectorNo ] , 1 , 6 , fkeys ) ;
2017-02-24 08:14:47 +08:00
if ( bytes_read ! = 6 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " File reading error (%s). " , keyFilename ) ;
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 + + ) {
2016-01-20 02:52:01 +08:00
bytes_read = fread ( keyB [ sectorNo ] , 1 , 6 , fkeys ) ;
2017-02-24 08:14:47 +08:00
if ( bytes_read ! = 6 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " File reading error (%s). " , keyFilename ) ;
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
2018-02-08 00:17:19 +08:00
if ( dataFilename [ 0 ] = = 0x00 )
{
fptr = GenerateFilename ( " hf-mf- " , " -data.bin " ) ;
if ( fptr = = NULL )
return 1 ;
strcpy ( dataFilename , fptr ) ;
}
if ( ( fdump = fopen ( dataFilename , " rb " ) ) = = NULL ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " Could not find file %s " , dataFilename ) ;
2015-01-08 05:00:29 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Restoring %s to card " , dataFilename ) ;
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 } } ;
2016-01-20 05:25:34 +08:00
memcpy ( c . d . asBytes , key , 6 ) ;
bytes_read = fread ( bldata , 1 , 16 , fdump ) ;
2017-02-24 08:14:47 +08:00
if ( bytes_read ! = 16 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " File reading error (%s). " , dataFilename ) ;
2014-10-31 04:49:18 +08:00
fclose ( fdump ) ;
2016-10-21 22:06:53 +08:00
fdump = NULL ;
2014-09-11 01:04:50 +08:00
return 2 ;
}
2011-08-30 17:52:18 +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 ] ) ;
2011-08-30 17:52:18 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Writing to block %3d: %s " , FirstBlockOfSector ( sectorNo ) + blockNo , sprint_hex ( bldata , 16 ) ) ;
2011-08-30 17:52:18 +08:00
memcpy ( c . d . asBytes + 10 , bldata , 16 ) ;
2015-10-13 03:30:54 +08:00
clearCommandBuffer ( ) ;
2011-08-30 17:52:18 +08:00
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 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " isOk:%02x " , isOK ) ;
2011-08-30 17:52:18 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Command execute timeout " ) ;
2011-08-30 17:52:18 +08:00
}
}
}
fclose ( fdump ) ;
return 0 ;
}
2016-04-18 19:18:02 +08:00
int CmdHF14AMfNested ( const char * Cmd ) {
2017-12-13 03:05:36 +08:00
int i , res , iterations ;
2017-03-07 02:11:08 +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-12-13 03:05:36 +08:00
uint8_t keyBlock [ ( MIFARE_DEFAULTKEYS_SIZE + 1 ) * 6 ] ;
2011-06-10 21:35:10 +08:00
uint64_t key64 = 0 ;
2014-09-11 01:04:50 +08:00
bool transferToEml = false ;
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 } ;
2018-02-05 00:30:40 +08:00
char * fptr ;
2016-04-23 18:18:34 +08:00
if ( strlen ( Cmd ) < 3 ) return usage_hf14_nested ( ) ;
2011-06-10 21:35:10 +08:00
2016-04-23 18:18:34 +08:00
char cmdp , ctmp ;
2011-06-10 21:35:10 +08:00
cmdp = param_getchar ( Cmd , 0 ) ;
blockNo = param_get8 ( Cmd , 1 ) ;
ctmp = param_getchar ( Cmd , 2 ) ;
2016-04-23 18:18:34 +08:00
2014-09-11 01:04:50 +08:00
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " key type must be A or B " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2015-01-08 05:00:29 +08:00
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' )
keyType = 1 ;
2011-06-10 21:35:10 +08:00
if ( param_gethex ( Cmd , 3 , key , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " key must include 12 HEX symbols " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2011-06-18 02:39:54 +08:00
if ( cmdp = = ' o ' | | cmdp = = ' O ' ) {
2011-06-10 21:35:10 +08:00
cmdp = ' o ' ;
trgBlockNo = param_get8 ( Cmd , 4 ) ;
ctmp = param_getchar ( Cmd , 5 ) ;
2014-09-11 01:04:50 +08:00
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " target key type must be A or B " ) ;
2011-06-10 21:35:10 +08:00
return 1 ;
}
2015-01-08 05:00:29 +08:00
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' )
trgKeyType = 1 ;
2011-06-10 21:35:10 +08:00
} else {
2017-07-11 23:45:23 +08:00
SectorsCnt = NumOfSectors ( cmdp ) ;
2011-06-10 21:35:10 +08:00
}
2011-06-18 02:39:54 +08:00
ctmp = param_getchar ( Cmd , 4 ) ;
2017-07-31 19:37:41 +08:00
transferToEml | = ( ctmp = = ' t ' | | ctmp = = ' T ' ) ;
createDumpFile | = ( ctmp = = ' d ' | | ctmp = = ' D ' ) ;
2011-09-01 16:13:18 +08:00
2011-06-18 02:39:54 +08:00
ctmp = param_getchar ( Cmd , 6 ) ;
transferToEml | = ( ctmp = = ' t ' | | ctmp = = ' T ' ) ;
2017-07-31 19:37:41 +08:00
createDumpFile | = ( ctmp = = ' d ' | | ctmp = = ' D ' ) ;
// check if we can authenticate to sector
res = mfCheckKeys ( blockNo , keyType , true , 1 , key , & key64 ) ;
if ( res ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " key is wrong. Can't authenticate to block:%3d key type:%c " , blockNo , keyType ? ' B ' : ' A ' ) ;
2017-07-31 19:37:41 +08:00
return 3 ;
}
2011-06-10 21:35:10 +08:00
if ( cmdp = = ' o ' ) {
2015-06-25 18:41:39 +08:00
int16_t isOK = mfnested ( blockNo , keyType , key , trgBlockNo , trgKeyType , keyBlock , true ) ;
2016-01-26 03:28:34 +08:00
switch ( isOK ) {
2018-02-21 14:52:22 +08:00
case - 1 : PrintAndLogEx ( WARNING , " Error: No response from Proxmark. \n " ) ; break ;
case - 2 : PrintAndLogEx ( WARNING , " Button pressed. Aborted. \n " ) ; break ;
case - 3 : PrintAndLogEx ( FAILED , " Tag isn't vulnerable to Nested Attack (PRNG is not predictable). \n " ) ; break ;
case - 4 : PrintAndLogEx ( FAILED , " No valid key found " ) ; break ;
2016-01-26 03:28:34 +08:00
case - 5 :
key64 = bytes_to_num ( keyBlock , 6 ) ;
// transfer key to the emulator
if ( transferToEml ) {
uint8_t sectortrailer ;
if ( trgBlockNo < 32 * 4 ) { // 4 block sector
2018-01-27 02:31:13 +08:00
sectortrailer = ( trgBlockNo & ~ 0x03 ) + 3 ;
2016-01-26 03:28:34 +08:00
} else { // 16 block sector
2018-01-27 02:31:13 +08:00
sectortrailer = ( trgBlockNo & ~ 0x0f ) + 15 ;
2016-01-26 03:28:34 +08:00
}
mfEmlGetMem ( keyBlock , sectortrailer , 1 ) ;
if ( ! trgKeyType )
num_to_bytes ( key64 , 6 , keyBlock ) ;
else
num_to_bytes ( key64 , 6 , & keyBlock [ 10 ] ) ;
2017-07-31 19:50:55 +08:00
mfEmlSetMem ( keyBlock , sectortrailer , 1 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Key transferred to emulator memory. " ) ;
2014-09-11 01:04:50 +08:00
}
2016-01-26 03:28:34 +08:00
return 0 ;
2018-02-21 14:52:22 +08:00
default : PrintAndLogEx ( WARNING , " Unknown Error. \n " ) ;
2011-06-18 02:39:54 +08:00
}
2016-01-26 03:28:34 +08:00
return 2 ;
2011-09-01 16:13:18 +08:00
}
else { // ------------------------------------ multiple sectors working
2017-07-28 07:35:49 +08:00
uint64_t t1 = msclock ( ) ;
2016-04-23 18:18:34 +08:00
2017-03-07 02:11:08 +08:00
e_sector = calloc ( SectorsCnt , sizeof ( sector_t ) ) ;
2011-06-10 21:35:10 +08:00
if ( e_sector = = NULL ) return 1 ;
2014-09-11 01:04:50 +08:00
//test current key and additional standard keys first
2017-12-13 03:05:36 +08:00
// add parameter key
memcpy ( keyBlock + ( MIFARE_DEFAULTKEYS_SIZE * 6 ) , key , 6 ) ;
2017-12-07 03:14:18 +08:00
for ( int cnt = 0 ; cnt < MIFARE_DEFAULTKEYS_SIZE ; cnt + + ) {
num_to_bytes ( g_mifare_default_keys [ cnt ] , 6 , ( uint8_t * ) ( keyBlock + cnt * 6 ) ) ;
}
2011-06-10 21:35:10 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Testing known keys. Sector count=%d " , SectorsCnt ) ;
2017-12-13 03:05:36 +08:00
res = mfCheckKeys_fast ( SectorsCnt , true , true , 1 , MIFARE_DEFAULTKEYS_SIZE + 1 , keyBlock , e_sector ) ;
2011-06-10 21:35:10 +08:00
2017-07-28 07:35:49 +08:00
uint64_t t2 = msclock ( ) - t1 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Time to check %d known keys: %.0f seconds \n " , MIFARE_DEFAULTKEYS_SIZE , ( float ) t2 / 1000.0 ) ;
PrintAndLogEx ( SUCCESS , " enter nested attack " ) ;
2013-09-15 17:33:17 +08:00
2011-06-10 21:35:10 +08:00
// nested sectors
iterations = 0 ;
2013-09-15 17:33:17 +08:00
bool calibrate = true ;
2016-02-10 20:20:23 +08:00
2018-02-07 03:08:42 +08:00
for ( i = 0 ; i < MIFARE_SECTOR_RETRY ; i + + ) {
2016-01-26 03:28:34 +08:00
for ( uint8_t sectorNo = 0 ; sectorNo < SectorsCnt ; + + sectorNo ) {
for ( trgKeyType = 0 ; trgKeyType < 2 ; + + trgKeyType ) {
2014-09-11 01:04:50 +08:00
if ( e_sector [ sectorNo ] . foundKey [ trgKeyType ] ) continue ;
2011-06-10 21:35:10 +08:00
2016-01-26 03:28:34 +08:00
int16_t isOK = mfnested ( blockNo , keyType , key , FirstBlockOfSector ( sectorNo ) , trgKeyType , keyBlock , calibrate ) ;
switch ( isOK ) {
2018-02-21 14:52:22 +08:00
case - 1 : PrintAndLogEx ( WARNING , " error: No response from Proxmark. \n " ) ; break ;
case - 2 : PrintAndLogEx ( WARNING , " button pressed. Aborted. \n " ) ; break ;
case - 3 : PrintAndLogEx ( FAILED , " Tag isn't vulnerable to Nested Attack (PRNG is not predictable). \n " ) ; break ;
2016-01-26 03:28:34 +08:00
case - 4 : //key not found
calibrate = false ;
iterations + + ;
continue ;
case - 5 :
calibrate = false ;
iterations + + ;
e_sector [ sectorNo ] . foundKey [ trgKeyType ] = 1 ;
e_sector [ sectorNo ] . Key [ trgKeyType ] = bytes_to_num ( keyBlock , 6 ) ;
2017-12-13 03:05:36 +08:00
res = mfCheckKeys_fast ( SectorsCnt , true , true , 2 , 1 , keyBlock , e_sector ) ;
2016-01-26 03:28:34 +08:00
continue ;
2018-02-21 14:52:22 +08:00
default : PrintAndLogEx ( WARNING , " unknown Error. \n " ) ;
2011-06-10 21:35:10 +08:00
}
2016-01-26 03:28:34 +08:00
free ( e_sector ) ;
return 2 ;
2011-06-10 21:35:10 +08:00
}
2013-09-15 17:33:17 +08:00
}
2011-06-10 21:35:10 +08:00
}
2016-02-10 20:20:23 +08:00
2017-07-28 07:35:49 +08:00
t1 = msclock ( ) - t1 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " time in nested: %.0f seconds \n " , ( float ) t1 / 1000.0 ) ;
2016-04-23 18:18:34 +08:00
2011-06-10 21:35:10 +08:00
2016-01-17 06:02:04 +08:00
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " trying to read key B... " ) ;
2016-01-17 06:02:04 +08:00
for ( i = 0 ; i < SectorsCnt ; i + + ) {
// KEY A but not KEY B
if ( e_sector [ i ] . foundKey [ 0 ] & & ! e_sector [ i ] . foundKey [ 1 ] ) {
uint8_t sectrail = ( FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " reading block %d " , sectrail ) ;
2016-01-21 05:26:01 +08:00
2016-01-17 06:02:04 +08:00
UsbCommand c = { CMD_MIFARE_READBL , { sectrail , 0 , 0 } } ;
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , c . d . asBytes ) ; // KEY A
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
UsbCommand resp ;
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) continue ;
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
2016-01-21 02:51:30 +08:00
if ( ! isOK ) continue ;
2016-01-17 06:02:04 +08:00
2016-01-21 02:51:30 +08:00
uint8_t * data = resp . d . asBytes ;
key64 = bytes_to_num ( data + 10 , 6 ) ;
if ( key64 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " data: %s " , sprint_hex ( data + 10 , 6 ) ) ;
2017-07-12 00:31:10 +08:00
e_sector [ i ] . foundKey [ 1 ] = true ;
2016-01-21 02:51:30 +08:00
e_sector [ i ] . Key [ 1 ] = key64 ;
2016-01-17 06:02:04 +08:00
}
}
}
2016-02-10 20:20:23 +08:00
2013-09-15 17:33:17 +08:00
2011-06-10 21:35:10 +08:00
//print them
2016-01-21 02:51:30 +08:00
printKeyTable ( SectorsCnt , e_sector ) ;
2011-06-10 21:35:10 +08:00
2011-06-18 02:39:54 +08:00
// transfer them to the emulator
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 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " key transferred to emulator memory. " ) ;
2011-06-18 02:39:54 +08:00
}
}
2011-09-01 16:13:18 +08:00
// Create dump file
2011-08-30 17:52:18 +08:00
if ( createDumpFile ) {
2018-02-05 00:30:40 +08:00
fptr = GenerateFilename ( " hf-mf- " , " -key.bin " ) ;
2018-02-07 22:10:59 +08:00
if ( fptr = = NULL )
return 1 ;
2018-02-05 00:30:40 +08:00
if ( ( fkeys = fopen ( fptr , " wb " ) ) = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " could not create file %s " , fptr ) ;
2011-08-30 17:52:18 +08:00
free ( e_sector ) ;
return 1 ;
}
2017-07-31 19:50:55 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " saving keys to binary file %s... " , fptr ) ;
2017-07-31 19:50:55 +08:00
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 ) ;
2017-07-31 19:50:55 +08:00
} else {
2011-09-01 16:13:18 +08:00
fwrite ( & standart , 1 , 6 , fkeys ) ;
}
2011-08-30 17:52:18 +08:00
}
2017-07-31 19:50:55 +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 ) ;
2017-07-31 19:50:55 +08:00
} else {
2011-09-01 16:13:18 +08:00
fwrite ( & standart , 1 , 6 , fkeys ) ;
}
2011-08-30 17:52:18 +08:00
}
2017-07-31 19:50:55 +08:00
fflush ( fkeys ) ;
2011-08-30 17:52:18 +08:00
fclose ( fkeys ) ;
2017-07-31 19:50:55 +08:00
}
2011-06-10 21:35:10 +08:00
free ( e_sector ) ;
}
return 0 ;
}
2016-04-18 19:18:02 +08:00
int CmdHF14AMfNestedHard ( const char * Cmd ) {
2015-11-27 23:24:00 +08:00
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 } ;
2015-12-15 15:51:29 +08:00
uint8_t trgkey [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
2018-02-08 23:01:05 +08:00
uint8_t cmdp = 0 ;
char filename [ FILE_PATH_SIZE ] , * fptr ;
char szTemp [ FILE_PATH_SIZE ] ;
2015-11-27 23:24:00 +08:00
char ctmp ;
2015-12-15 15:51:29 +08:00
bool know_target_key = false ;
2015-11-27 23:24:00 +08:00
bool nonce_file_read = false ;
bool nonce_file_write = false ;
bool slow = false ;
2016-01-13 16:31:13 +08:00
int tests = 0 ;
2018-02-08 23:01:05 +08:00
switch ( tolower ( param_getchar ( Cmd , cmdp ) ) ) {
case ' h ' : return usage_hf14_hardnested ( ) ;
2018-02-09 20:53:11 +08:00
case ' r ' :
fptr = GenerateFilename ( " hf-mf- " , " -nonces.bin " ) ;
if ( fptr = = NULL )
strncpy ( filename , " nonces.bin " , FILE_PATH_SIZE ) ;
else
strncpy ( filename , fptr , FILE_PATH_SIZE ) ;
2018-02-08 23:01:05 +08:00
nonce_file_read = true ;
if ( ! param_gethex ( Cmd , cmdp + 1 , trgkey , 12 ) ) {
know_target_key = true ;
}
cmdp + + ;
break ;
case ' t ' :
tests = param_get32ex ( Cmd , cmdp + 1 , 100 , 10 ) ;
if ( ! param_gethex ( Cmd , cmdp + 2 , trgkey , 12 ) ) {
know_target_key = true ;
}
cmdp + = 2 ;
break ;
default :
2018-02-09 00:44:17 +08:00
if ( param_getchar ( Cmd , cmdp ) = = 0x00 )
{
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Block number is missing " ) ;
2018-02-09 00:44:17 +08:00
return 1 ;
}
2018-02-08 23:01:05 +08:00
blockNo = param_get8 ( Cmd , cmdp ) ;
ctmp = param_getchar ( Cmd , cmdp + 1 ) ;
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key type must be A or B " ) ;
2015-11-27 23:24:00 +08:00
return 1 ;
}
2018-02-08 23:01:05 +08:00
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' ) {
keyType = 1 ;
}
if ( param_gethex ( Cmd , cmdp + 2 , key , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key must include 12 HEX symbols " ) ;
2018-02-08 23:01:05 +08:00
return 1 ;
}
2018-02-09 00:44:17 +08:00
if ( param_getchar ( Cmd , cmdp + 3 ) = = 0x00 )
{
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Target block number is missing " ) ;
2018-02-09 00:44:17 +08:00
return 1 ;
}
2018-02-08 23:01:05 +08:00
trgBlockNo = param_get8 ( Cmd , cmdp + 3 ) ;
2018-02-09 00:44:17 +08:00
2018-02-08 23:01:05 +08:00
ctmp = param_getchar ( Cmd , cmdp + 4 ) ;
if ( ctmp ! = ' a ' & & ctmp ! = ' A ' & & ctmp ! = ' b ' & & ctmp ! = ' B ' ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Target key type must be A or B " ) ;
2018-02-08 23:01:05 +08:00
return 1 ;
}
if ( ctmp ! = ' A ' & & ctmp ! = ' a ' ) {
trgKeyType = 1 ;
}
cmdp + = 5 ;
}
if ( ! param_gethex ( Cmd , cmdp , trgkey , 12 ) ) {
know_target_key = true ;
cmdp + + ;
}
while ( ( ctmp = param_getchar ( Cmd , cmdp ) ) ) {
switch ( tolower ( ctmp ) )
{
case ' s ' :
slow = true ;
break ;
case ' w ' :
nonce_file_write = true ;
fptr = GenerateFilename ( " hf-mf- " , " -nonces.bin " ) ;
if ( fptr = = NULL )
return 1 ;
strncpy ( filename , fptr , FILE_PATH_SIZE ) ;
break ;
case ' u ' :
param_getstr ( Cmd , cmdp + 1 , szTemp , FILE_PATH_SIZE ) ;
snprintf ( filename , FILE_PATH_SIZE , " hf-mf-%s-nonces.bin " , szTemp ) ;
cmdp + + ;
break ;
case ' f ' :
param_getstr ( Cmd , cmdp + 1 , szTemp , FILE_PATH_SIZE ) ;
strncpy ( filename , szTemp , FILE_PATH_SIZE ) ;
cmdp + + ;
break ;
default :
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Unknown parameter '%c' \n " , ctmp ) ;
2018-02-08 23:01:05 +08:00
usage_hf14_hardnested ( ) ;
return 1 ;
2015-11-27 23:24:00 +08:00
}
2018-02-08 23:01:05 +08:00
cmdp + + ;
2015-11-27 23:24:00 +08:00
}
2017-07-31 19:37:41 +08:00
2017-08-26 18:57:18 +08:00
if ( ! know_target_key ) {
uint64_t key64 = 0 ;
// check if we can authenticate to sector
int res = mfCheckKeys ( blockNo , keyType , true , 1 , key , & key64 ) ;
if ( res ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key is wrong. Can't authenticate to block:%3d key type:%c " , blockNo , keyType ? ' B ' : ' A ' ) ;
2017-08-26 18:57:18 +08:00
return 3 ;
}
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --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 " ,
2015-11-27 23:24:00 +08:00
trgBlockNo ,
trgKeyType ? ' B ' : ' A ' ,
2015-12-15 15:51:29 +08:00
trgkey [ 0 ] , trgkey [ 1 ] , trgkey [ 2 ] , trgkey [ 3 ] , trgkey [ 4 ] , trgkey [ 5 ] ,
2016-04-25 03:43:38 +08:00
know_target_key ? " " : " (not set) " ,
nonce_file_write ? " write " : nonce_file_read ? " read " : " none " ,
slow ? " Yes " : " No " ,
2016-01-13 16:31:13 +08:00
tests ) ;
2015-12-15 15:51:29 +08:00
2017-07-30 15:17:48 +08:00
uint64_t foundkey = 0 ;
2018-02-08 23:01:05 +08:00
int16_t isOK = mfnestedhard ( blockNo , keyType , key , trgBlockNo , trgKeyType , know_target_key ? trgkey : NULL , nonce_file_read , nonce_file_write , slow , tests , & foundkey , filename ) ;
2015-12-15 15:51:29 +08:00
2017-12-18 18:29:34 +08:00
DropField ( ) ;
2015-11-27 23:24:00 +08:00
if ( isOK ) {
switch ( isOK ) {
2018-02-21 15:47:42 +08:00
case 1 : PrintAndLogEx ( WARNING , " Error: No response from Proxmark. \n " ) ; break ;
2018-02-21 14:52:22 +08:00
case 2 : PrintAndLogEx ( NORMAL , " Button pressed. Aborted. \n " ) ; break ;
2015-11-27 23:24:00 +08:00
default : break ;
}
return 2 ;
}
return 0 ;
}
2017-10-30 02:28:23 +08:00
int randInRange ( int min , int max ) {
2017-12-03 02:07:10 +08:00
return min + ( int ) ( rand ( ) / ( double ) ( RAND_MAX ) * ( max - min + 1 ) ) ;
2017-10-05 22:00:56 +08:00
}
2018-02-05 00:30:40 +08:00
//Fisher– Yates shuffle
2017-10-05 22:00:56 +08:00
void shuffle ( uint8_t * array , uint16_t len ) {
uint8_t tmp [ 6 ] ;
uint16_t x ;
time_t t ;
srand ( ( unsigned ) time ( & t ) ) ;
while ( len ) {
x = randInRange ( 0 , ( len - = 6 ) ) | 0 ; // 0 = i < n
x % = 6 ;
memcpy ( tmp , array + x , 6 ) ;
memcpy ( array + x , array + len , 6 ) ;
memcpy ( array + len , tmp , 6 ) ;
}
}
int CmdHF14AMfChk_fast ( const char * Cmd ) {
2017-12-10 16:44:49 +08:00
char ctmp = 0x00 ;
ctmp = param_getchar ( Cmd , 0 ) ;
if ( strlen ( Cmd ) < 1 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_chk_fast ( ) ;
2017-10-05 22:00:56 +08:00
FILE * f ;
char filename [ FILE_PATH_SIZE ] = { 0 } ;
char buf [ 13 ] ;
2018-02-05 00:30:40 +08:00
char * fptr ;
2017-12-13 03:05:36 +08:00
uint8_t tempkey [ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
2017-10-05 22:00:56 +08:00
uint8_t * keyBlock = NULL , * p ;
2017-12-13 03:05:36 +08:00
uint8_t sectorsCnt = 1 ;
2017-10-05 22:00:56 +08:00
int i , keycnt = 0 ;
2018-01-01 02:36:12 +08:00
int clen = 0 ;
2017-10-05 22:00:56 +08:00
int transferToEml = 0 , createDumpFile = 0 ;
2017-12-10 16:44:49 +08:00
uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE ;
2017-12-13 03:05:36 +08:00
sector_t * e_sector = NULL ;
2017-12-07 03:14:18 +08:00
keyBlock = calloc ( MIFARE_DEFAULTKEYS_SIZE , 6 ) ;
2017-10-05 22:00:56 +08:00
if ( keyBlock = = NULL ) return 1 ;
2017-12-07 03:14:18 +08:00
for ( int cnt = 0 ; cnt < MIFARE_DEFAULTKEYS_SIZE ; cnt + + )
2018-02-09 20:40:28 +08:00
num_to_bytes ( g_mifare_default_keys [ cnt ] , 6 , keyBlock + cnt * 6 ) ;
2017-12-07 03:14:18 +08:00
2017-10-05 22:00:56 +08:00
// sectors
2017-12-10 16:44:49 +08:00
switch ( ctmp ) {
2017-12-13 03:05:36 +08:00
case ' 0 ' : sectorsCnt = 5 ; break ;
case ' 1 ' : sectorsCnt = 16 ; break ;
case ' 2 ' : sectorsCnt = 32 ; break ;
case ' 4 ' : sectorsCnt = 40 ; break ;
default : sectorsCnt = 16 ;
2017-10-05 22:00:56 +08:00
}
2018-01-01 02:36:12 +08:00
for ( i = 1 ; param_getchar ( Cmd , i ) ; i + + ) {
ctmp = param_getchar ( Cmd , i ) ;
clen = param_getlength ( Cmd , i ) ;
if ( clen = = 12 ) {
if ( param_gethex ( Cmd , i , keyBlock + 6 * keycnt , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " not hex, skipping " ) ;
2018-01-01 02:36:12 +08:00
continue ;
}
2017-12-07 03:14:18 +08:00
if ( keyitems - keycnt < 2 ) {
p = realloc ( keyBlock , 6 * ( keyitems + = 64 ) ) ;
2017-10-05 22:00:56 +08:00
if ( ! p ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Cannot allocate memory for Keys " ) ;
2017-10-05 22:00:56 +08:00
free ( keyBlock ) ;
return 2 ;
}
keyBlock = p ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " [%2d] key %s " , keycnt , sprint_hex ( ( keyBlock + 6 * keycnt ) , 6 ) ) ;
2017-10-05 22:00:56 +08:00
keycnt + + ;
2018-01-01 02:36:12 +08:00
} else if ( clen = = 1 ) {
if ( ctmp = = ' t ' | | ctmp = = ' T ' ) { transferToEml = 1 ; continue ; }
if ( ctmp = = ' d ' | | ctmp = = ' D ' ) { createDumpFile = 1 ; continue ; }
2017-10-05 22:00:56 +08:00
} else {
// May be a dic file
2018-01-01 02:36:12 +08:00
if ( param_getstr ( Cmd , i , filename , FILE_PATH_SIZE ) > = FILE_PATH_SIZE ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Filename too long " ) ;
2018-01-01 02:36:12 +08:00
continue ;
}
f = fopen ( filename , " r " ) ;
if ( ! f ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " File: %s: not found or locked. " , filename ) ;
2018-01-01 02:36:12 +08:00
continue ;
2017-10-05 22:00:56 +08:00
}
2018-01-01 02:36:12 +08:00
// read file
while ( fgets ( buf , sizeof ( buf ) , f ) ) {
if ( strlen ( buf ) < 12 | | buf [ 11 ] = = ' \n ' )
continue ;
while ( fgetc ( f ) ! = ' \n ' & & ! feof ( f ) ) ; //goto next line
2017-10-05 22:00:56 +08:00
2018-01-01 02:36:12 +08:00
if ( buf [ 0 ] = = ' # ' ) continue ; //The line start with # is comment, skip
2017-10-05 22:00:56 +08:00
2018-01-01 02:36:12 +08:00
if ( ! isxdigit ( buf [ 0 ] ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " File content error. '%s' must include 12 HEX symbols " , buf ) ;
2018-01-01 02:36:12 +08:00
continue ;
}
buf [ 12 ] = 0 ;
if ( keyitems - keycnt < 2 ) {
p = realloc ( keyBlock , 6 * ( keyitems + = 64 ) ) ;
if ( ! p ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Cannot allocate memory for default keys " ) ;
2018-01-01 02:36:12 +08:00
free ( keyBlock ) ;
fclose ( f ) ;
return 2 ;
2017-10-05 22:00:56 +08:00
}
2018-01-01 02:36:12 +08:00
keyBlock = p ;
2017-10-05 22:00:56 +08:00
}
2018-01-01 02:36:12 +08:00
int pos = 6 * keycnt ;
memset ( keyBlock + pos , 0 , 6 ) ;
num_to_bytes ( strtoll ( buf , NULL , 16 ) , 6 , keyBlock + pos ) ;
keycnt + + ;
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-10-05 22:00:56 +08:00
}
2018-01-01 02:36:12 +08:00
fclose ( f ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Loaded %2d keys from %s " , keycnt , filename ) ;
2017-10-05 22:00:56 +08:00
}
}
if ( keycnt = = 0 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " No key specified, trying default keys " ) ;
2017-12-07 03:14:18 +08:00
for ( ; keycnt < MIFARE_DEFAULTKEYS_SIZE ; keycnt + + )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " [%2d] %02x%02x%02x%02x%02x%02x " , keycnt ,
2017-10-05 22:00:56 +08:00
( keyBlock + 6 * keycnt ) [ 0 ] , ( keyBlock + 6 * keycnt ) [ 1 ] , ( keyBlock + 6 * keycnt ) [ 2 ] ,
2018-02-09 20:40:28 +08:00
( keyBlock + 6 * keycnt ) [ 3 ] , ( keyBlock + 6 * keycnt ) [ 4 ] , ( keyBlock + 6 * keycnt ) [ 5 ] ) ;
2017-10-05 22:00:56 +08:00
}
2017-12-13 03:05:36 +08:00
// // initialize storage for found keys
e_sector = calloc ( sectorsCnt , sizeof ( sector_t ) ) ;
2017-10-05 22:00:56 +08:00
if ( e_sector = = NULL ) {
free ( keyBlock ) ;
return 1 ;
}
uint32_t chunksize = keycnt > ( USB_CMD_DATA_SIZE / 6 ) ? ( USB_CMD_DATA_SIZE / 6 ) : keycnt ;
bool firstChunk = true , lastChunk = false ;
// time
uint64_t t1 = msclock ( ) ;
2017-12-11 08:44:55 +08:00
// strategys. 1= deep first on sector 0 AB, 2= width first on all sectors
for ( uint8_t strategy = 1 ; strategy < 3 ; strategy + + ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Running strategy %u " , strategy ) ;
2017-12-11 08:44:55 +08:00
// main keychunk loop
for ( uint32_t i = 0 ; i < keycnt ; i + = chunksize ) {
2017-12-13 17:17:30 +08:00
if ( ukbhit ( ) ) {
int gc = getchar ( ) ; ( void ) gc ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n aborted via keyboard! \n " ) ;
2017-12-13 17:17:30 +08:00
goto out ;
}
2017-12-11 08:44:55 +08:00
uint32_t size = ( ( keycnt - i ) > chunksize ) ? chunksize : keycnt - i ;
// last chunk?
if ( size = = keycnt - i )
lastChunk = true ;
2017-12-13 03:05:36 +08:00
int res = mfCheckKeys_fast ( sectorsCnt , firstChunk , lastChunk , strategy , size , keyBlock + ( i * 6 ) , e_sector ) ;
2017-10-05 22:00:56 +08:00
2017-12-13 03:05:36 +08:00
if ( firstChunk )
firstChunk = false ;
2017-12-18 19:14:02 +08:00
// all keys, aborted
if ( res = = 0 | | res = = 2 )
2017-12-12 04:43:29 +08:00
goto out ;
2017-12-12 05:33:50 +08:00
} // end chunks of keys
2017-12-18 19:15:03 +08:00
firstChunk = true ;
lastChunk = false ;
2017-12-12 05:33:50 +08:00
} // end strategy
2017-12-12 04:43:29 +08:00
out :
2017-10-05 22:00:56 +08:00
t1 = msclock ( ) - t1 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Time in checkkeys (fast): %.1fs \n " , ( float ) ( t1 / 1000.0 ) ) ;
2017-10-05 22:00:56 +08:00
2017-12-13 03:05:36 +08:00
printKeyTable ( sectorsCnt , e_sector ) ;
2017-10-05 22:00:56 +08:00
if ( transferToEml ) {
uint8_t block [ 16 ] = { 0x00 } ;
2017-12-13 03:05:36 +08:00
for ( uint8_t i = 0 ; i < sectorsCnt ; + + i ) {
2017-10-05 22:00:56 +08:00
mfEmlGetMem ( block , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ;
/*
if ( e_sector [ i ] . foundKey [ 0 ] )
memcpy ( block , e_sector [ i ] . keyA , 6 ) ;
if ( e_sector [ i ] . foundKey [ 1 ] )
memcpy ( block + 10 , e_sector [ i ] . keyB , 6 ) ;
mfEmlSetMem ( block , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ;
*/
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Found keys have been transferred to the emulator memory " ) ;
2017-10-05 22:00:56 +08:00
}
if ( createDumpFile ) {
2018-02-05 00:30:40 +08:00
fptr = GenerateFilename ( " hf-mf- " , " -key.bin " ) ;
2018-02-07 22:10:59 +08:00
if ( fptr = = NULL )
return 1 ;
2018-02-05 00:30:40 +08:00
FILE * fkeys = fopen ( fptr , " wb " ) ;
2017-10-05 22:00:56 +08:00
if ( fkeys = = NULL ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " Could not create file %s " , filename ) ;
2017-10-05 22:00:56 +08:00
free ( keyBlock ) ;
free ( e_sector ) ;
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Printing keys to binary file %s... " , filename ) ;
2017-10-05 22:00:56 +08:00
2017-12-13 03:05:36 +08:00
for ( i = 0 ; i < sectorsCnt ; i + + ) {
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , tempkey ) ;
fwrite ( tempkey , 1 , 6 , fkeys ) ;
}
2017-10-05 22:00:56 +08:00
2017-12-13 03:05:36 +08:00
for ( i = 0 ; i < sectorsCnt ; i + + ) {
num_to_bytes ( e_sector [ i ] . Key [ 1 ] , 6 , tempkey ) ;
fwrite ( tempkey , 1 , 6 , fkeys ) ;
}
2017-10-05 22:00:56 +08:00
fclose ( fkeys ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Found keys have been dumped to file %s. 0xffffffffffff has been inserted for unknown keys. " , filename ) ;
2017-10-05 22:00:56 +08:00
}
free ( keyBlock ) ;
free ( e_sector ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2017-10-05 22:00:56 +08:00
return 0 ;
}
2016-04-18 19:18:02 +08:00
int CmdHF14AMfChk ( const char * Cmd ) {
2016-04-23 18:18:34 +08:00
2018-01-01 02:36:12 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2017-12-10 16:44:49 +08:00
if ( strlen ( Cmd ) < 3 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_chk ( ) ;
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-03-07 02:11:08 +08:00
sector_t * e_sector = NULL ;
2017-12-10 16:44:49 +08:00
2011-06-10 21:35:10 +08:00
uint8_t blockNo = 0 ;
2012-05-30 11:45:55 +08:00
uint8_t SectorsCnt = 1 ;
2011-06-10 21:35:10 +08:00
uint8_t keyType = 0 ;
2017-12-10 16:44:49 +08:00
uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE ;
uint64_t key64 = 0 ;
2018-01-01 02:36:12 +08:00
uint8_t tempkey [ 6 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
2018-02-05 00:30:40 +08:00
char * fptr ;
2018-01-01 02:36:12 +08:00
int clen = 0 ;
2012-05-30 11:45:55 +08:00
int transferToEml = 0 ;
2017-12-10 16:44:49 +08:00
int createDumpFile = 0 ;
int i , res , keycnt = 0 ;
2011-06-10 21:35:10 +08:00
2017-12-07 03:14:18 +08:00
keyBlock = calloc ( MIFARE_DEFAULTKEYS_SIZE , 6 ) ;
2012-05-30 11:45:55 +08:00
if ( keyBlock = = NULL ) return 1 ;
2017-12-07 03:14:18 +08:00
for ( int cnt = 0 ; cnt < MIFARE_DEFAULTKEYS_SIZE ; cnt + + )
num_to_bytes ( g_mifare_default_keys [ cnt ] , 6 , ( uint8_t * ) ( keyBlock + cnt * 6 ) ) ;
2012-05-30 11:45:55 +08:00
if ( param_getchar ( Cmd , 0 ) = = ' * ' ) {
blockNo = 3 ;
2017-07-11 23:45:23 +08:00
SectorsCnt = NumOfSectors ( param_getchar ( Cmd + 1 , 0 ) ) ;
2016-01-26 03:28:34 +08:00
} else {
2012-05-30 11:45:55 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
2016-01-26 03:28:34 +08:00
}
2012-05-30 11:45:55 +08:00
2011-06-10 21:35:10 +08:00
ctmp = param_getchar ( Cmd , 1 ) ;
2018-01-01 02:36:12 +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 :
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Key type must be A , B or ? " ) ;
2018-01-01 02:36:12 +08:00
free ( keyBlock ) ;
return 1 ;
} ;
}
for ( i = 2 ; param_getchar ( Cmd , i ) ; i + + ) {
ctmp = param_getchar ( Cmd , i ) ;
clen = param_getlength ( Cmd , i ) ;
if ( clen = = 12 ) {
if ( param_gethex ( Cmd , i , keyBlock + 6 * keycnt , 12 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " not hex, skipping " ) ;
2018-01-01 02:36:12 +08:00
continue ;
}
2017-12-07 03:14:18 +08:00
if ( keyitems - keycnt < 2 ) {
p = realloc ( keyBlock , 6 * ( keyitems + = 64 ) ) ;
2012-05-30 11:45:55 +08:00
if ( ! p ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " cannot allocate memory for Keys " ) ;
2012-05-30 11:45:55 +08:00
free ( keyBlock ) ;
return 2 ;
}
keyBlock = p ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " [%2d] key %s " , keycnt , sprint_hex ( ( keyBlock + 6 * keycnt ) , 6 ) ) ; ;
2012-05-30 11:45:55 +08:00
keycnt + + ;
2018-01-01 02:36:12 +08:00
} else if ( clen = = 1 ) {
if ( ctmp = = ' t ' | | ctmp = = ' T ' ) { transferToEml = 1 ; continue ; }
if ( ctmp = = ' d ' | | ctmp = = ' D ' ) { createDumpFile = 1 ; continue ; }
2012-05-30 11:45:55 +08:00
} else {
// May be a dic file
2018-01-01 02:36:12 +08:00
if ( param_getstr ( Cmd , i , filename , sizeof ( filename ) ) > = FILE_PATH_SIZE ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " File name too long " ) ;
2018-01-01 02:36:12 +08:00
continue ;
}
f = fopen ( filename , " r " ) ;
if ( ! f ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " File: %s: not found or locked. " , filename ) ;
2018-01-01 02:36:12 +08:00
continue ;
2012-05-30 11:45:55 +08:00
}
2018-01-01 02:36:12 +08:00
// load keys from dictionary file
while ( fgets ( buf , sizeof ( buf ) , f ) ) {
if ( strlen ( buf ) < 12 | | buf [ 11 ] = = ' \n ' )
continue ;
while ( fgetc ( f ) ! = ' \n ' & & ! feof ( f ) ) ; //goto next line
2012-05-30 11:45:55 +08:00
2018-01-01 02:36:12 +08:00
if ( buf [ 0 ] = = ' # ' ) continue ; //The line start with # is comment, skip
2011-06-10 21:35:10 +08:00
2018-01-01 02:36:12 +08:00
// codesmell, only checks first char?
if ( ! isxdigit ( buf [ 0 ] ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " File content error. '%s' must include 12 HEX symbols " , buf ) ;
2018-01-01 02:36:12 +08:00
continue ;
}
buf [ 12 ] = 0 ;
if ( keyitems - keycnt < 2 ) {
p = realloc ( keyBlock , 6 * ( keyitems + = 64 ) ) ;
if ( ! p ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Cannot allocate memory for defKeys " ) ;
2018-01-01 02:36:12 +08:00
free ( keyBlock ) ;
fclose ( f ) ;
return 2 ;
2012-05-30 11:45:55 +08:00
}
2018-01-01 02:36:12 +08:00
keyBlock = p ;
2012-05-30 11:45:55 +08:00
}
2018-01-01 02:36:12 +08:00
memset ( keyBlock + 6 * keycnt , 0 , 6 ) ;
num_to_bytes ( strtoll ( buf , NULL , 16 ) , 6 , keyBlock + 6 * keycnt ) ;
2018-02-21 14:52:22 +08:00
//PrintAndLogEx(NORMAL, "check key[%2d] %012" PRIx64, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6));
2018-01-01 02:36:12 +08:00
keycnt + + ;
memset ( buf , 0 , sizeof ( buf ) ) ;
2012-05-30 11:45:55 +08:00
}
2018-01-01 02:36:12 +08:00
fclose ( f ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Loaded %2d keys from %s " , keycnt , filename ) ;
2011-06-10 21:35:10 +08:00
}
}
if ( keycnt = = 0 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " No key specified, trying default keys " ) ;
2017-12-07 03:14:18 +08:00
for ( ; keycnt < MIFARE_DEFAULTKEYS_SIZE ; keycnt + + )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " [%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 ) ;
}
// initialize storage for found keys
2017-03-07 02:11:08 +08:00
e_sector = calloc ( SectorsCnt , sizeof ( sector_t ) ) ;
2016-01-21 02:51:30 +08:00
if ( e_sector = = NULL ) {
free ( keyBlock ) ;
return 1 ;
2011-06-10 21:35:10 +08:00
}
2016-01-21 02:51:30 +08:00
2016-04-23 17:32:37 +08:00
// empty e_sector
for ( int i = 0 ; i < SectorsCnt ; + + i ) {
e_sector [ i ] . Key [ 0 ] = 0xffffffffffff ;
e_sector [ i ] . Key [ 1 ] = 0xffffffffffff ;
2017-07-12 00:31:10 +08:00
e_sector [ i ] . foundKey [ 0 ] = false ;
e_sector [ i ] . foundKey [ 1 ] = false ;
2016-04-23 17:32:37 +08:00
}
2016-01-21 02:51:30 +08:00
uint8_t trgKeyType = 0 ;
2016-02-10 20:20:23 +08:00
uint32_t max_keys = keycnt > ( USB_CMD_DATA_SIZE / 6 ) ? ( USB_CMD_DATA_SIZE / 6 ) : keycnt ;
2016-01-21 02:51:30 +08:00
2016-01-15 19:45:15 +08:00
// time
2017-07-28 07:35:49 +08:00
uint64_t t1 = msclock ( ) ;
2016-01-21 02:51:30 +08:00
// check keys.
2016-02-17 06:46:34 +08:00
for ( trgKeyType = ! keyType ; trgKeyType < 2 ; ( keyType = = 2 ) ? ( + + trgKeyType ) : ( trgKeyType = 2 ) ) {
2016-02-10 20:20:23 +08:00
2016-01-21 02:51:30 +08:00
int b = blockNo ;
2014-09-11 01:04:50 +08:00
for ( int i = 0 ; i < SectorsCnt ; + + i ) {
2016-01-21 02:51:30 +08:00
// skip already found keys.
if ( e_sector [ i ] . foundKey [ trgKeyType ] ) continue ;
2016-04-23 17:32:37 +08:00
2016-01-21 02:51:30 +08:00
for ( uint32_t c = 0 ; c < keycnt ; c + = max_keys ) {
2017-12-13 17:17:30 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2017-12-13 17:17:30 +08:00
if ( ukbhit ( ) ) {
int gc = getchar ( ) ; ( void ) gc ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n aborted via keyboard! \n " ) ;
2017-12-13 17:17:30 +08:00
goto out ;
}
2016-01-21 02:51:30 +08:00
uint32_t size = keycnt - c > max_keys ? max_keys : keycnt - c ;
res = mfCheckKeys ( b , trgKeyType , true , size , & keyBlock [ 6 * c ] , & key64 ) ;
if ( ! res ) {
e_sector [ i ] . Key [ trgKeyType ] = key64 ;
2017-07-15 02:54:11 +08:00
e_sector [ i ] . foundKey [ trgKeyType ] = true ;
2016-01-21 02:51:30 +08:00
break ;
2012-05-30 11:45:55 +08:00
}
2017-12-13 17:17:30 +08:00
2012-05-30 11:45:55 +08:00
}
2016-01-21 02:51:30 +08:00
b < 127 ? ( b + = 4 ) : ( b + = 16 ) ;
2012-05-30 11:45:55 +08:00
}
2011-06-10 21:35:10 +08:00
}
2017-07-28 07:35:49 +08:00
t1 = msclock ( ) - t1 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n Time in checkkeys: %.0f seconds \n " , ( float ) t1 / 1000.0 ) ;
2016-02-10 20:20:23 +08:00
2016-04-23 19:02:20 +08:00
2016-01-21 02:51:30 +08:00
// 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
2016-04-23 17:32:37 +08:00
if ( keyType ! = 1 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " testing to read key B... " ) ;
2016-04-23 17:32:37 +08:00
for ( i = 0 ; i < SectorsCnt ; i + + ) {
// KEY A but not KEY B
if ( e_sector [ i ] . foundKey [ 0 ] & & ! e_sector [ i ] . foundKey [ 1 ] ) {
uint8_t sectrail = ( FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 ) ;
2016-01-21 02:51:30 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Reading block %d " , sectrail ) ;
2016-04-23 17:32:37 +08:00
UsbCommand c = { CMD_MIFARE_READBL , { sectrail , 0 , 0 } } ;
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , c . d . asBytes ) ; // KEY A
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
UsbCommand resp ;
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) continue ;
uint8_t isOK = resp . arg [ 0 ] & 0xff ;
if ( ! isOK ) continue ;
uint8_t * data = resp . d . asBytes ;
key64 = bytes_to_num ( data + 10 , 6 ) ;
if ( key64 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Data:%s " , sprint_hex ( data + 10 , 6 ) ) ;
2016-04-23 17:32:37 +08:00
e_sector [ i ] . foundKey [ 1 ] = 1 ;
e_sector [ i ] . Key [ 1 ] = key64 ;
}
2016-01-21 02:51:30 +08:00
}
}
2016-01-20 04:48:29 +08:00
}
2016-02-10 20:20:23 +08:00
2017-12-13 17:17:30 +08:00
out :
2017-07-30 15:17:48 +08:00
//print keys
2016-01-21 02:51:30 +08:00
printKeyTable ( SectorsCnt , e_sector ) ;
2014-09-12 02:58:34 +08:00
if ( transferToEml ) {
2016-01-21 02:51:30 +08:00
uint8_t block [ 16 ] = { 0x00 } ;
for ( uint8_t i = 0 ; i < SectorsCnt ; + + i ) {
mfEmlGetMem ( block , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ;
if ( e_sector [ i ] . foundKey [ 0 ] )
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , block ) ;
if ( e_sector [ i ] . foundKey [ 1 ] )
num_to_bytes ( e_sector [ i ] . Key [ 1 ] , 6 , block + 10 ) ;
mfEmlSetMem ( block , FirstBlockOfSector ( i ) + NumBlocksPerSector ( i ) - 1 , 1 ) ;
2014-09-12 02:58:34 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Found keys have been transferred to the emulator memory " ) ;
2014-09-12 02:58:34 +08:00
}
2016-01-21 02:51:30 +08:00
2012-05-30 11:45:55 +08:00
if ( createDumpFile ) {
2018-02-05 00:30:40 +08:00
fptr = GenerateFilename ( " hf-mf- " , " -key.bin " ) ;
2018-02-07 22:10:59 +08:00
if ( fptr = = NULL )
return 1 ;
2018-02-05 00:30:40 +08:00
FILE * fkeys = fopen ( fptr , " wb " ) ;
2014-09-12 02:58:34 +08:00
if ( fkeys = = NULL ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " Could not create file %s " , fptr ) ;
2014-09-12 02:58:34 +08:00
free ( keyBlock ) ;
2016-01-21 02:51:30 +08:00
free ( e_sector ) ;
2012-05-30 11:45:55 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Printing keys to binary file %s... " , fptr ) ;
2016-01-21 02:51:30 +08:00
for ( i = 0 ; i < SectorsCnt ; i + + ) {
num_to_bytes ( e_sector [ i ] . Key [ 0 ] , 6 , tempkey ) ;
fwrite ( tempkey , 1 , 6 , fkeys ) ;
}
for ( i = 0 ; i < SectorsCnt ; i + + ) {
num_to_bytes ( e_sector [ i ] . Key [ 1 ] , 6 , tempkey ) ;
fwrite ( tempkey , 1 , 6 , fkeys ) ;
2012-05-30 11:45:55 +08:00
}
fclose ( fkeys ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Found keys have been dumped to file %s. 0xffffffffffff has been inserted for unknown keys. " , fptr ) ;
2012-05-30 11:45:55 +08:00
}
2017-12-13 17:17:30 +08:00
2014-09-12 02:58:34 +08:00
free ( keyBlock ) ;
2016-01-21 02:51:30 +08:00
free ( e_sector ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2014-09-12 02:58:34 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
2017-01-30 06:09:23 +08:00
2017-03-07 02:11:08 +08:00
sector_t * k_sector = NULL ;
2016-08-05 03:51:26 +08:00
uint8_t k_sectorsCount = 16 ;
2017-01-30 06:09:23 +08:00
static void emptySectorTable ( ) {
2011-06-10 21:35:10 +08:00
2016-08-05 03:51:26 +08:00
// initialize storage for found keys
2016-08-08 11:07:25 +08:00
if ( k_sector = = NULL )
2017-03-07 02:11:08 +08:00
k_sector = calloc ( k_sectorsCount , sizeof ( sector_t ) ) ;
2016-08-05 03:51:26 +08:00
if ( k_sector = = NULL )
return ;
// empty e_sector
for ( int i = 0 ; i < k_sectorsCount ; + + i ) {
k_sector [ i ] . Key [ 0 ] = 0xffffffffffff ;
k_sector [ i ] . Key [ 1 ] = 0xffffffffffff ;
2017-07-12 00:31:10 +08:00
k_sector [ i ] . foundKey [ 0 ] = false ;
k_sector [ i ] . foundKey [ 1 ] = false ;
2014-02-01 05:17:34 +08:00
}
2017-01-30 06:09:23 +08:00
}
void showSectorTable ( ) {
if ( k_sector ! = NULL ) {
printKeyTable ( k_sectorsCount , k_sector ) ;
free ( k_sector ) ;
k_sector = NULL ;
}
}
void readerAttack ( nonces_t data , bool setEmulatorMem , bool verbose ) {
2016-04-18 19:18:02 +08:00
2017-01-30 06:09:23 +08:00
uint64_t key = 0 ;
2017-07-12 00:31:10 +08:00
bool success = false ;
2017-01-29 20:21:17 +08:00
2017-01-30 06:09:23 +08:00
if ( k_sector = = NULL )
emptySectorTable ( ) ;
2017-07-28 02:58:59 +08:00
success = mfkey32_moebius ( data , & key ) ;
2017-01-30 06:09:23 +08:00
if ( success ) {
uint8_t sector = data . sector ;
uint8_t keytype = data . keytype ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Reader is trying authenticate with: Key %s, sector %02d: [%012 " PRIx64 " ] "
2017-01-30 06:09:23 +08:00
, keytype ? " B " : " A "
, sector
, key
) ;
k_sector [ sector ] . Key [ keytype ] = key ;
2017-07-12 00:31:10 +08:00
k_sector [ sector ] . foundKey [ keytype ] = true ;
2017-01-30 06:09:23 +08:00
//set emulator memory for keys
if ( setEmulatorMem ) {
uint8_t memBlock [ 16 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0x0F , 0x80 , 0x69 , 0 , 0 , 0 , 0 , 0 , 0 } ;
num_to_bytes ( k_sector [ sector ] . Key [ 0 ] , 6 , memBlock ) ;
num_to_bytes ( k_sector [ sector ] . Key [ 1 ] , 6 , memBlock + 10 ) ;
//iceman, guessing this will not work so well for 4K tags.
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Setting Emulator Memory Block %02d: [%s] "
2017-01-30 06:09:23 +08:00
, ( sector * 4 ) + 3
, sprint_hex ( memBlock , sizeof ( memBlock ) )
) ;
mfEmlSetMem ( memBlock , ( sector * 4 ) + 3 , 1 ) ;
2016-08-05 03:51:26 +08:00
}
2014-02-01 05:17:34 +08:00
}
2016-08-05 03:51:26 +08:00
}
int CmdHF14AMf1kSim ( const char * Cmd ) {
2014-02-01 05:17:34 +08:00
2016-08-05 03:51:26 +08:00
uint8_t uid [ 10 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t exitAfterNReads = 0 ;
uint8_t flags = ( FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA ) ;
2016-10-27 18:38:53 +08:00
int uidlen = 0 ;
2016-08-05 03:51:26 +08:00
uint8_t cmdp = 0 ;
2017-07-12 00:31:10 +08:00
bool errors = false ;
bool verbose = false ;
bool setEmulatorMem = false ;
2017-01-30 06:09:23 +08:00
nonces_t data [ 1 ] ;
2017-07-15 02:54:11 +08:00
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 & & ! errors ) {
2016-08-05 03:51:26 +08:00
switch ( param_getchar ( Cmd , cmdp ) ) {
case ' e ' :
case ' E ' :
2017-07-12 00:31:10 +08:00
setEmulatorMem = true ;
2016-08-05 03:51:26 +08:00
cmdp + + ;
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 , cmdp + 1 ) ;
cmdp + = 2 ;
break ;
case ' u ' :
case ' U ' :
param_gethex_ex ( Cmd , cmdp + 1 , uid , & uidlen ) ;
switch ( uidlen ) {
case 20 : flags = FLAG_10B_UID_IN_DATA ; break ;
case 14 : flags = FLAG_7B_UID_IN_DATA ; break ;
case 8 : flags = FLAG_4B_UID_IN_DATA ; break ;
default : return usage_hf14_mf1ksim ( ) ;
}
2017-01-30 06:09:23 +08:00
cmdp + = 2 ;
2016-08-05 03:51:26 +08:00
break ;
2016-10-27 20:36:43 +08:00
case ' v ' :
case ' V ' :
2017-07-12 00:31:10 +08:00
verbose = true ;
2016-10-27 20:36:43 +08:00
cmdp + + ;
break ;
2016-08-05 03:51:26 +08:00
case ' x ' :
case ' X ' :
flags | = FLAG_NR_AR_ATTACK ;
cmdp + + ;
break ;
default :
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Unknown parameter '%c' " , param_getchar ( Cmd , cmdp ) ) ;
2017-07-12 00:31:10 +08:00
errors = true ;
2016-08-05 03:51:26 +08:00
break ;
}
2014-02-01 05:17:34 +08:00
}
2016-08-05 03:51:26 +08:00
//Validations
2018-01-12 05:07:26 +08:00
if ( errors ) return usage_hf14_mf1ksim ( ) ;
2016-01-20 00:22:18 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " uid:%s, numreads:%d, flags:%d (0x%02x) "
2016-04-18 19:18:02 +08:00
, ( uidlen = = 0 ) ? " N/A " : sprint_hex ( uid , uidlen > > 1 )
2016-01-20 00:22:18 +08:00
, exitAfterNReads
, flags
, flags ) ;
2014-02-01 05:17:34 +08:00
2016-04-18 19:18:02 +08:00
UsbCommand c = { CMD_SIMULATE_MIFARE_CARD , { flags , exitAfterNReads , 0 } } ;
2014-09-11 01:04:50 +08:00
memcpy ( c . d . asBytes , uid , sizeof ( uid ) ) ;
2015-10-13 03:30:54 +08:00
clearCommandBuffer ( ) ;
2014-09-11 01:04:50 +08:00
SendCommand ( & c ) ;
2017-01-30 06:09:23 +08:00
UsbCommand resp ;
2014-02-01 05:17:34 +08:00
2017-01-30 06:09:23 +08:00
if ( flags & FLAG_INTERACTIVE ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Press pm3-button or send another cmd to abort simulation " ) ;
2016-08-05 03:51:26 +08:00
2017-07-30 15:17:48 +08:00
while ( ! ukbhit ( ) ) {
2016-01-20 00:22:18 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) continue ;
2015-12-15 16:34:55 +08:00
if ( ! ( flags & FLAG_NR_AR_ATTACK ) ) break ;
if ( ( resp . arg [ 0 ] & 0xffff ) ! = CMD_SIMULATE_MIFARE_CARD ) break ;
2017-01-30 06:09:23 +08:00
memcpy ( data , resp . d . asBytes , sizeof ( data ) ) ;
readerAttack ( data [ 0 ] , setEmulatorMem , verbose ) ;
2016-01-20 00:22:18 +08:00
}
2017-01-30 06:09:23 +08:00
showSectorTable ( ) ;
2016-01-20 00:22:18 +08:00
}
2014-09-11 01:04:50 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
2016-04-18 19:18:02 +08:00
int CmdHF14AMfSniff ( const char * Cmd ) {
2017-07-12 00:31:10 +08:00
bool wantLogToFile = false ;
bool wantDecrypt = false ;
//bool wantSaveToEml = false; TODO
bool wantSaveToEmlFile = false ;
2016-04-18 19:18:02 +08:00
//var
2018-01-09 23:25:58 +08:00
int res = 0 , len = 0 , blockLen = 0 ;
int pckNum = 0 , num = 0 ;
uint8_t sak = 0 ;
2016-04-18 19:18:02 +08:00
uint8_t uid [ 10 ] ;
uint8_t uid_len = 0 ;
uint8_t atqa [ 2 ] = { 0x00 , 0x00 } ;
2017-07-12 00:31:10 +08:00
bool isTag = false ;
2016-04-18 19:18:02 +08:00
uint8_t * buf = NULL ;
uint16_t bufsize = 0 ;
uint8_t * bufPtr = NULL ;
uint16_t traceLen = 0 ;
memset ( uid , 0x00 , sizeof ( uid ) ) ;
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_sniff ( ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
ctmp = param_getchar ( Cmd , i ) ;
if ( ctmp = = ' l ' | | ctmp = = ' L ' ) wantLogToFile = true ;
if ( ctmp = = ' d ' | | ctmp = = ' D ' ) wantDecrypt = true ;
//if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO
if ( ctmp = = ' f ' | | ctmp = = ' F ' ) wantSaveToEmlFile = true ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " ------------------------------------------------------------------------- \n " ) ;
PrintAndLogEx ( NORMAL , " Executing mifare sniffing command. \n " ) ;
PrintAndLogEx ( NORMAL , " Press the key on the proxmark3 device to abort both proxmark3 and client. \n " ) ;
PrintAndLogEx ( NORMAL , " Press the key on pc keyboard to abort the client. \n " ) ;
PrintAndLogEx ( NORMAL , " ------------------------------------------------------------------------- \n " ) ;
2016-04-18 19:18:02 +08:00
UsbCommand c = { CMD_MIFARE_SNIFFER , { 0 , 0 , 0 } } ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
2018-01-09 23:25:58 +08:00
UsbCommand resp ;
2016-04-18 19:18:02 +08:00
// wait cycle
while ( true ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2016-04-18 19:18:02 +08:00
if ( ukbhit ( ) ) {
2018-01-09 23:25:58 +08:00
int gc = getchar ( ) ; ( void ) gc ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n [!] aborted via keyboard! \n " ) ;
2016-04-18 19:18:02 +08:00
break ;
}
2018-01-09 23:25:58 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 2000 ) ) {
continue ;
}
2017-08-29 21:47:26 +08:00
res = resp . arg [ 0 ] & 0xff ;
traceLen = resp . arg [ 1 ] ;
len = resp . arg [ 2 ] ;
2018-01-17 07:29:41 +08:00
2017-08-29 21:47:26 +08:00
if ( res = = 0 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " hf mifare sniff finished " ) ;
2017-08-29 21:47:26 +08:00
free ( buf ) ;
return 0 ;
}
2016-04-18 19:18:02 +08:00
2017-08-29 21:47:26 +08:00
if ( res = = 1 ) { // there is (more) data to be transferred
if ( pckNum = = 0 ) { // first packet, (re)allocate necessary buffer
if ( traceLen > bufsize | | buf = = NULL ) {
uint8_t * p ;
if ( buf = = NULL ) // not yet allocated
p = malloc ( traceLen ) ;
2018-01-09 23:25:58 +08:00
else // need more memory
2017-08-29 21:47:26 +08:00
p = realloc ( buf , traceLen ) ;
if ( p = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Cannot allocate memory for trace " ) ;
2017-08-29 21:47:26 +08:00
free ( buf ) ;
return 2 ;
2016-04-18 19:18:02 +08:00
}
2017-08-29 21:47:26 +08:00
buf = p ;
2016-04-18 19:18:02 +08:00
}
2017-08-29 21:47:26 +08:00
bufPtr = buf ;
bufsize = traceLen ;
memset ( buf , 0x00 , traceLen ) ;
}
if ( bufPtr = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Cannot allocate memory for trace " ) ;
2017-08-29 21:47:26 +08:00
free ( buf ) ;
return 2 ;
2016-04-18 19:18:02 +08:00
}
2017-08-29 21:47:26 +08:00
// what happens if LEN is bigger then TRACELEN --iceman
memcpy ( bufPtr , resp . d . asBytes , len ) ;
bufPtr + = len ;
pckNum + + ;
}
2016-04-18 19:18:02 +08:00
2017-08-29 21:47:26 +08:00
if ( res = = 2 ) { // received all data, start displaying
blockLen = bufPtr - buf ;
bufPtr = buf ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " > \n " ) ;
PrintAndLogEx ( SUCCESS , " received trace len: %d packages: %d " , blockLen , pckNum ) ;
2017-08-29 21:47:26 +08:00
while ( bufPtr - buf < blockLen ) {
bufPtr + = 6 ; // skip (void) timing information
len = * ( ( uint16_t * ) bufPtr ) ;
if ( len & 0x8000 ) {
isTag = true ;
len & = 0x7fff ;
} else {
isTag = false ;
}
bufPtr + = 2 ;
2018-01-17 07:29:41 +08:00
// the uid identification package
// 0xFF 0xFF xx xx xx xx xx xx xx xx xx xx aa aa cc 0xFF 0xFF
// x = uid, a = atqa, c = sak
2017-08-29 21:47:26 +08:00
if ( ( len = = 17 ) & & ( bufPtr [ 0 ] = = 0xff ) & & ( bufPtr [ 1 ] = = 0xff ) & & ( bufPtr [ 15 ] = = 0xff ) & & ( bufPtr [ 16 ] = = 0xff ) ) {
memcpy ( uid , bufPtr + 2 , 10 ) ;
memcpy ( atqa , bufPtr + 2 + 10 , 2 ) ;
switch ( atqa [ 0 ] & 0xC0 ) {
case 0x80 : uid_len = 10 ; break ;
case 0x40 : uid_len = 7 ; break ;
default : uid_len = 4 ; break ;
2016-04-18 19:18:02 +08:00
}
2017-08-29 21:47:26 +08:00
sak = bufPtr [ 14 ] ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " UID %s | ATQA %02x %02x | SAK 0x%02x " ,
2017-08-29 21:47:26 +08:00
sprint_hex ( uid , uid_len ) ,
atqa [ 1 ] ,
atqa [ 0 ] ,
sak ) ;
if ( wantLogToFile | | wantDecrypt ) {
FillFileNameByUID ( logHexFileName , uid , " .log " , uid_len ) ;
AddLogCurrentDT ( logHexFileName ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Trace saved to %s " , logHexFileName ) ;
2017-08-29 21:47:26 +08:00
}
if ( wantDecrypt )
mfTraceInit ( uid , uid_len , atqa , sak , wantSaveToEmlFile ) ;
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " %03d| %s |%s " , num , isTag ? " TAG " : " RDR " , sprint_hex ( bufPtr , len ) ) ;
2017-08-29 21:47:26 +08:00
if ( wantLogToFile )
AddLogHex ( logHexFileName , isTag ? " TAG| " : " RDR| " , bufPtr , len ) ;
if ( wantDecrypt )
mfTraceDecode ( bufPtr , len , wantSaveToEmlFile ) ;
num + + ;
2016-04-18 19:18:02 +08:00
}
2017-08-29 21:47:26 +08:00
bufPtr + = len ;
bufPtr + = ( ( len - 1 ) / 8 + 1 ) ; // ignore parity
2016-04-18 19:18:02 +08:00
}
2017-08-29 21:47:26 +08:00
pckNum = 0 ;
}
2016-04-18 19:18:02 +08:00
} // while (true)
free ( buf ) ;
return 0 ;
}
2016-04-14 17:09:17 +08:00
int CmdHF14AMfDbg ( const char * Cmd ) {
2016-04-18 19:18:02 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2016-08-05 03:51:26 +08:00
if ( strlen ( Cmd ) < 1 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_dbg ( ) ;
2016-04-18 19:18:02 +08:00
uint8_t dbgMode = param_get8ex ( Cmd , 0 , 0 , 10 ) ;
if ( dbgMode > 4 ) return usage_hf14_dbg ( ) ;
2011-06-10 21:35:10 +08:00
2015-10-13 03:30:54 +08:00
UsbCommand c = { CMD_MIFARE_SET_DBGMODE , { dbgMode , 0 , 0 } } ;
SendCommand ( & c ) ;
return 0 ;
2011-06-10 21:35:10 +08:00
}
2016-08-08 23:49:30 +08:00
int CmdHF14AMfKeyBrute ( const char * Cmd ) {
uint8_t blockNo = 0 , keytype = 0 ;
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
uint64_t foundkey = 0 ;
char cmdp = param_getchar ( Cmd , 0 ) ;
if ( cmdp = = ' H ' | | cmdp = = ' h ' ) return usage_hf14_keybrute ( ) ;
// block number
blockNo = param_get8 ( Cmd , 0 ) ;
// keytype
cmdp = param_getchar ( Cmd , 1 ) ;
if ( cmdp = = ' B ' | | cmdp = = ' b ' ) keytype = 1 ;
// key
if ( param_gethex ( Cmd , 2 , key , 12 ) ) return usage_hf14_keybrute ( ) ;
2017-07-28 07:35:49 +08:00
uint64_t t1 = msclock ( ) ;
2016-08-08 23:49:30 +08:00
if ( mfKeyBrute ( blockNo , keytype , key , & foundkey ) )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " found valid key: %012 " PRIx64 " \n " , foundkey ) ;
2016-08-08 23:49:30 +08:00
else
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " key not found " ) ;
2016-08-08 23:49:30 +08:00
2017-07-28 07:35:49 +08:00
t1 = msclock ( ) - t1 ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ; PrintAndLogEx ( SUCCESS , " time in keybrute: %.0f seconds \n " , ( float ) t1 / 1000.0 ) ;
2016-08-08 23:49:30 +08:00
return 0 ;
}
2017-03-07 02:11:08 +08:00
void printKeyTable ( uint8_t sectorscnt , sector_t * e_sector ) {
2017-12-07 06:56:07 +08:00
char strA [ 12 + 1 ] = { 0 } ;
char strB [ 12 + 1 ] = { 0 } ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |---|----------------|---|----------------|---| " ) ;
PrintAndLogEx ( NORMAL , " |sec|key A |res|key B |res| " ) ;
PrintAndLogEx ( NORMAL , " |---|----------------|---|----------------|---| " ) ;
2016-04-14 17:09:17 +08:00
for ( uint8_t i = 0 ; i < sectorscnt ; + + i ) {
2017-12-07 06:56:07 +08:00
snprintf ( strA , sizeof ( strA ) , " ------------ " ) ;
snprintf ( strB , sizeof ( strB ) , " ------------ " ) ;
if ( e_sector [ i ] . foundKey [ 0 ] )
snprintf ( strA , sizeof ( strA ) , " %012 " PRIx64 , e_sector [ i ] . Key [ 0 ] ) ;
if ( e_sector [ i ] . foundKey [ 1 ] )
snprintf ( strB , sizeof ( strB ) , " %012 " PRIx64 , e_sector [ i ] . Key [ 1 ] ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |%03d| %s | %d | %s | %d | "
2017-12-07 06:56:07 +08:00
, i
, strA , e_sector [ i ] . foundKey [ 0 ]
, strB , e_sector [ i ] . foundKey [ 1 ]
2016-04-14 17:09:17 +08:00
) ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |---|----------------|---|----------------|---| " ) ;
2016-04-14 17:09:17 +08:00
}
// EMULATOR COMMANDS
2017-07-11 23:45:23 +08:00
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 } ;
2017-07-11 23:45:23 +08:00
char c = param_getchar ( Cmd , 0 ) ;
2018-02-02 20:01:11 +08:00
if ( strlen ( Cmd ) < 1 | | c = = ' h ' | | c = = ' H ' ) return usage_hf14_eget ( ) ;
2011-06-18 02:39:54 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " " ) ;
2014-09-11 01:04:50 +08:00
if ( ! mfEmlGetMem ( data , blockNo , 1 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " data[%3d]:%s " , blockNo , sprint_hex ( data , 16 ) ) ;
2011-06-18 02:39:54 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Command execute timeout " ) ;
2011-06-18 02:39:54 +08:00
}
return 0 ;
}
2017-07-11 23:45:23 +08:00
int CmdHF14AMfEClear ( const char * Cmd ) {
char c = param_getchar ( Cmd , 0 ) ;
2018-02-02 20:01:11 +08:00
if ( c = = ' h ' | | c = = ' H ' ) return usage_hf14_eclr ( ) ;
2017-07-11 23:45:23 +08:00
UsbCommand cmd = { CMD_MIFARE_EML_MEMCLR , { 0 , 0 , 0 } } ;
clearCommandBuffer ( ) ;
SendCommand ( & cmd ) ;
2015-10-13 03:30:54 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
2017-07-11 23:45:23 +08:00
int CmdHF14AMfESet ( const char * Cmd ) {
char c = param_getchar ( Cmd , 0 ) ;
2011-06-18 02:39:54 +08:00
uint8_t memBlock [ 16 ] ;
uint8_t blockNo = 0 ;
memset ( memBlock , 0x00 , sizeof ( memBlock ) ) ;
2017-07-11 23:45:23 +08:00
if ( strlen ( Cmd ) < 3 | | c = = ' h ' | | c = = ' H ' )
return usage_hf14_eset ( ) ;
2011-06-18 02:39:54 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
if ( param_gethex ( Cmd , 1 , memBlock , 32 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " block data must include 32 HEX symbols " ) ;
2011-06-18 02:39:54 +08:00
return 1 ;
}
// 1 - blocks count
2018-01-27 02:31:13 +08:00
return mfEmlSetMem ( memBlock , blockNo , 1 ) ;
2011-06-10 21:35:10 +08:00
}
2017-07-11 23:45:23 +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 ;
2015-10-05 00:01:33 +08:00
uint8_t blockWidth = 32 ;
2017-12-03 03:45:53 +08:00
uint32_t tmp ;
2017-07-11 23:45:23 +08:00
char c = param_getchar ( Cmd , 0 ) ;
2015-01-08 05:00:29 +08:00
2017-07-11 23:45:23 +08:00
if ( c = = ' h ' | | c = = ' H ' | | c = = 0x00 )
return usage_hf14_eload ( ) ;
2011-06-22 09:25:16 +08:00
2017-07-11 23:45:23 +08:00
switch ( c ) {
2015-01-08 05:00:29 +08:00
case ' 0 ' : numBlocks = 5 * 4 ; break ;
case ' 1 ' :
case ' \0 ' : numBlocks = 16 * 4 ; break ;
case ' 2 ' : numBlocks = 32 * 4 ; break ;
case ' 4 ' : numBlocks = 256 ; break ;
2015-12-15 16:34:55 +08:00
case ' U ' : // fall through
case ' u ' : numBlocks = 255 ; blockWidth = 8 ; break ;
2015-01-08 05:00:29 +08:00
default : {
numBlocks = 16 * 4 ;
nameParamNo = 0 ;
}
}
2015-12-15 16:34:55 +08:00
uint32_t numblk2 = param_get32ex ( Cmd , 2 , 0 , 10 ) ;
if ( numblk2 > 0 ) numBlocks = numblk2 ;
2015-01-08 05:00:29 +08:00
2017-11-12 06:23:01 +08:00
len = param_getstr ( Cmd , nameParamNo , filename , sizeof ( filename ) ) ;
2015-01-08 05:00:29 +08:00
2016-01-13 06:35:06 +08:00
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2011-06-22 09:25:16 +08:00
2015-05-25 03:50:15 +08:00
fnameptr + = len ;
2011-06-22 09:25:16 +08:00
sprintf ( fnameptr , " .eml " ) ;
// open file
f = fopen ( filename , " r " ) ;
if ( f = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File %s not found or locked " , filename ) ;
2011-06-22 09:25:16 +08:00
return 1 ;
}
blockNum = 0 ;
2017-08-28 15:39:20 +08:00
while ( ! feof ( f ) ) {
2011-06-22 09:25:16 +08:00
memset ( buf , 0 , sizeof ( buf ) ) ;
2015-01-08 05:00:29 +08:00
2013-03-14 23:03:04 +08:00
if ( fgets ( buf , sizeof ( buf ) , f ) = = NULL ) {
2015-01-08 05:00:29 +08:00
if ( blockNum > = numBlocks ) break ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " 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
}
2015-01-08 05:00:29 +08:00
2015-10-05 00:01:33 +08:00
if ( strlen ( buf ) < blockWidth ) {
2012-05-30 11:45:55 +08:00
if ( strlen ( buf ) & & feof ( f ) )
break ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File content error. Block data must include %d HEX symbols " , blockWidth ) ;
2014-10-28 05:33:37 +08:00
fclose ( f ) ;
2011-06-22 09:25:16 +08:00
return 2 ;
}
2015-01-08 05:00:29 +08:00
2015-10-05 00:01:33 +08:00
for ( i = 0 ; i < blockWidth ; i + = 2 ) {
2017-12-03 03:45:53 +08:00
sscanf ( & buf [ i ] , " %02x " , & tmp ) ;
buf8 [ i / 2 ] = tmp & 0xFF ;
2014-09-11 01:04:50 +08:00
}
2015-10-05 00:01:33 +08:00
if ( mfEmlSetMem_xt ( buf8 , blockNum , 1 , blockWidth / 2 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " 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 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2011-06-22 09:25:16 +08:00
blockNum + + ;
2015-01-08 05:00:29 +08:00
if ( blockNum > = numBlocks ) break ;
2011-06-22 09:25:16 +08:00
}
fclose ( f ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2017-12-03 22:23:24 +08:00
// Ultralight /Ntag
if ( blockWidth = = 8 ) {
if ( ( blockNum ! = numBlocks ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Warning, Ultralight/Ntag file content, Loaded %d blocks into emulator memory " , blockNum ) ;
2017-12-03 22:23:24 +08:00
return 0 ;
}
} else {
if ( ( blockNum ! = numBlocks ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory " , blockNum , numBlocks ) ;
2017-12-03 22:23:24 +08:00
return 4 ;
}
2011-06-22 09:25:16 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " 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
}
2017-07-11 23:45:23 +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 ;
2011-06-22 09:25:16 +08:00
memset ( filename , 0 , sizeof ( filename ) ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
2017-07-11 23:45:23 +08:00
char c = param_getchar ( Cmd , 0 ) ;
2015-01-08 05:00:29 +08:00
2018-02-02 20:01:11 +08:00
if ( c = = ' h ' | | c = = ' H ' ) return usage_hf14_esave ( ) ;
2011-06-22 09:25:16 +08:00
2017-07-11 23:45:23 +08:00
switch ( c ) {
2015-01-08 05:00:29 +08:00
case ' 0 ' : numBlocks = 5 * 4 ; break ;
case ' 1 ' :
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 06:23:01 +08:00
len = param_getstr ( Cmd , nameParamNo , filename , sizeof ( filename ) ) ;
2015-01-08 05:00:29 +08:00
2016-01-13 06:35:06 +08:00
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2011-06-22 09:25:16 +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 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can \' t get UID from block: %d " , 0 ) ;
2015-05-25 02:14:22 +08:00
len = sprintf ( fnameptr , " dump " ) ;
2015-05-25 03:50:15 +08:00
fnameptr + = len ;
}
else {
for ( j = 0 ; j < 7 ; j + + , fnameptr + = 2 )
2015-05-25 02:14:22 +08:00
sprintf ( fnameptr , " %02X " , buf [ j ] ) ;
2011-06-22 09:25:16 +08:00
}
} else {
2015-05-25 03:50:15 +08:00
fnameptr + = len ;
2011-06-22 09:25:16 +08:00
}
2015-01-08 05:00:29 +08:00
// add file extension
2011-06-22 09:25:16 +08:00
sprintf ( fnameptr , " .eml " ) ;
// open file
f = fopen ( filename , " w+ " ) ;
2015-01-08 05:00:29 +08:00
if ( ! f ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can't open file %s " , filename ) ;
2015-01-08 05:00:29 +08:00
return 1 ;
}
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 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Cant get block: %d " , i ) ;
2011-06-22 09:25:16 +08:00
break ;
}
for ( j = 0 ; j < 16 ; j + + )
2015-01-05 22:51:27 +08:00
fprintf ( f , " %02X " , buf [ j ] ) ;
2011-06-22 09:25:16 +08:00
fprintf ( f , " \n " ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2011-06-22 09:25:16 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2011-06-22 09:25:16 +08:00
fclose ( f ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Saved %d blocks to file: %s " , numBlocks , filename ) ;
2017-08-28 23:10:23 +08:00
return 0 ;
2011-06-10 21:35:10 +08:00
}
2017-07-11 23:45:23 +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-11 23:45:23 +08:00
char c = param_getchar ( Cmd , 0 ) ;
2014-09-11 01:04:50 +08:00
2017-07-11 23:45:23 +08:00
if ( strlen ( Cmd ) < 1 | | c = = ' h ' | | c = = ' H ' )
return usage_hf14_ecfill ( ) ;
2011-06-18 02:39:54 +08:00
2017-07-11 23:45:23 +08:00
if ( c ! = ' a ' & & c ! = ' A ' & & c ! = ' b ' & & c ! = ' B ' ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Key type must be A or B " ) ;
2011-06-18 02:39:54 +08:00
return 1 ;
}
2017-07-11 23:45:23 +08:00
if ( c ! = ' A ' & & c ! = ' a ' ) keyType = 1 ;
2011-06-18 02:39:54 +08:00
2017-07-11 23:45:23 +08:00
c = param_getchar ( Cmd , 1 ) ;
numSectors = NumOfSectors ( c ) ;
2014-09-11 01:04:50 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --params: numSectors: %d, keyType: %c \n " , numSectors , ( keyType = = 0 ) ? ' A ' : ' B ' ) ;
2017-07-11 23:45:23 +08:00
UsbCommand cmd = { CMD_MIFARE_EML_CARDLOAD , { numSectors , keyType , 0 } } ;
clearCommandBuffer ( ) ;
SendCommand ( & cmd ) ;
2014-09-11 01:04:50 +08:00
return 0 ;
2011-06-18 02:39:54 +08:00
}
2017-07-11 23:45:23 +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 ;
2015-10-13 03:30:54 +08:00
2017-07-11 23:45:23 +08:00
char c = param_getchar ( Cmd , 0 ) ;
2011-06-18 02:39:54 +08:00
2017-07-11 23:45:23 +08:00
if ( c = = ' h ' | | c = = ' H ' )
2017-07-13 19:10:46 +08:00
return usage_hf14_ekeyprn ( ) ;
2015-01-08 05:00:29 +08:00
2017-07-11 23:45:23 +08:00
numSectors = NumOfSectors ( c ) ;
2015-01-08 05:00:29 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |---|----------------|----------------| " ) ;
PrintAndLogEx ( NORMAL , " |sec|key A |key B | " ) ;
PrintAndLogEx ( NORMAL , " |---|----------------|----------------| " ) ;
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 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " 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 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |%03d| %012 " PRIx64 " | %012 " PRIx64 " | " , i , keyA , keyB ) ;
2011-06-18 02:39:54 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " |---|----------------|----------------| " ) ;
2011-06-18 02:39:54 +08:00
return 0 ;
}
2016-04-14 17:09:17 +08:00
// CHINESE MAGIC COMMANDS
int CmdHF14AMfCSetUID ( const char * Cmd ) {
2012-07-05 15:31:56 +08:00
uint8_t wipeCard = 0 ;
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 } ;
uint8_t atqaPresent = 1 ;
2012-07-05 15:31:56 +08:00
int res ;
2015-02-10 10:31:53 +08:00
char ctmp ;
int argi = 0 ;
2017-07-11 23:45:23 +08:00
if ( strlen ( Cmd ) < 1 | | param_getchar ( Cmd , argi ) = = ' h ' )
return usage_hf14_csetuid ( ) ;
if ( param_getchar ( Cmd , argi ) & & param_gethex ( Cmd , argi , uid , 8 ) )
return usage_hf14_csetuid ( ) ;
2012-07-05 15:31:56 +08:00
2015-02-10 10:31:53 +08:00
argi + + ;
ctmp = param_getchar ( Cmd , argi ) ;
if ( ctmp = = ' w ' | | ctmp = = ' W ' ) {
wipeCard = 1 ;
atqaPresent = 0 ;
}
if ( atqaPresent ) {
if ( param_getchar ( Cmd , argi ) ) {
if ( param_gethex ( Cmd , argi , atqa , 4 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " ATQA must include 4 HEX symbols " ) ;
2015-02-10 10:31:53 +08:00
return 1 ;
}
argi + + ;
if ( ! param_getchar ( Cmd , argi ) | | param_gethex ( Cmd , argi , sak , 2 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " SAK must include 2 HEX symbols " ) ;
2015-02-10 10:31:53 +08:00
return 1 ;
}
argi + + ;
} else
atqaPresent = 0 ;
}
if ( ! wipeCard ) {
ctmp = param_getchar ( Cmd , argi ) ;
if ( ctmp = = ' w ' | | ctmp = = ' W ' ) {
wipeCard = 1 ;
}
}
2012-07-05 15:31:56 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --wipe card:%s uid:%s " , ( wipeCard ) ? " YES " : " NO " , sprint_hex ( uid , 4 ) ) ;
2012-07-05 15:31:56 +08:00
2016-03-23 21:04:10 +08:00
res = mfCSetUID ( uid , ( atqaPresent ) ? atqa : NULL , ( atqaPresent ) ? sak : NULL , oldUid , wipeCard ) ;
2012-07-05 15:31:56 +08:00
if ( res ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can't set UID. error=%d " , res ) ;
2017-07-11 23:45:23 +08:00
return 1 ;
}
2012-07-05 15:31:56 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " old UID:%s " , sprint_hex ( oldUid , 4 ) ) ;
PrintAndLogEx ( SUCCESS , " new UID:%s " , sprint_hex ( uid , 4 ) ) ;
2012-07-05 15:31:56 +08:00
return 0 ;
}
2016-04-14 17:09:17 +08:00
int CmdHF14AMfCSetBlk ( const char * Cmd ) {
2015-11-10 18:45:45 +08:00
uint8_t block [ 16 ] = { 0x00 } ;
2012-07-05 16:09:41 +08:00
uint8_t blockNo = 0 ;
2015-11-10 04:46:15 +08:00
uint8_t params = MAGIC_SINGLE ;
2012-07-05 16:09:41 +08:00
int res ;
2017-07-11 23:45:23 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2012-07-05 16:09:41 +08:00
2017-07-11 23:45:23 +08:00
if ( strlen ( Cmd ) < 1 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_csetblk ( ) ;
2012-07-05 16:09:41 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
2017-07-11 23:45:23 +08:00
if ( param_gethex ( Cmd , 1 , block , 32 ) ) return usage_hf14_csetblk ( ) ;
ctmp = param_getchar ( Cmd , 2 ) ;
2015-11-10 04:46:15 +08:00
if ( ctmp = = ' w ' | | ctmp = = ' W ' )
params | = MAGIC_WIPE ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --block number:%2d data:%s " , blockNo , sprint_hex ( block , 16 ) ) ;
2012-07-05 16:09:41 +08:00
2015-11-10 18:45:45 +08:00
res = mfCSetBlock ( blockNo , block , NULL , params ) ;
2012-07-05 16:09:41 +08:00
if ( res ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can't write block. error=%d " , res ) ;
2015-04-09 03:08:05 +08:00
return 1 ;
}
2012-07-05 15:31:56 +08:00
return 0 ;
}
2016-04-14 17:09:17 +08:00
int CmdHF14AMfCLoad ( const char * Cmd ) {
2012-07-05 18:59:15 +08:00
FILE * f ;
2015-11-10 04:46:15 +08:00
char filename [ FILE_PATH_SIZE ] ;
2012-07-05 18:59:15 +08:00
char * fnameptr = filename ;
2017-08-28 23:10:23 +08:00
char buf [ 35 ] = { 0x00 } ; // 32+newline chars+1 null terminator
2017-07-11 23:45:23 +08:00
uint8_t buf8 [ 16 ] = { 0x00 } ;
2012-07-05 18:59:15 +08:00
uint8_t fillFromEmulator = 0 ;
2017-12-03 03:45:53 +08:00
uint32_t tmp ;
2015-03-14 00:23:26 +08:00
int i , len , blockNum , flags = 0 ;
2015-10-13 03:30:54 +08:00
2015-11-10 04:46:15 +08:00
memset ( filename , 0 , sizeof ( filename ) ) ;
2015-10-13 03:30:54 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
if ( ctmp = = ' h ' | | ctmp = = ' H ' | | ctmp = = 0x00 ) return usage_hf14_cload ( ) ;
2012-07-05 18:59:15 +08:00
if ( ctmp = = ' e ' | | ctmp = = ' E ' ) fillFromEmulator = 1 ;
if ( fillFromEmulator ) {
for ( blockNum = 0 ; blockNum < 16 * 4 ; blockNum + = 1 ) {
if ( mfEmlGetMem ( buf8 , blockNum , 1 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Cant get block: %d " , blockNum ) ;
2012-07-05 18:59:15 +08:00
return 2 ;
}
2015-11-10 04:46:15 +08:00
if ( blockNum = = 0 ) flags = MAGIC_INIT + MAGIC_WUPC ; // switch on field and send magic sequence
2017-07-11 23:45:23 +08:00
if ( blockNum = = 1 ) flags = 0 ; // just write
2015-11-10 04:46:15 +08:00
if ( blockNum = = 16 * 4 - 1 ) flags = MAGIC_HALT + MAGIC_OFF ; // Done. Magic Halt and switch off field.
2012-07-05 18:59:15 +08:00
2015-11-10 04:46:15 +08:00
if ( mfCSetBlock ( blockNum , buf8 , NULL , flags ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Cant set magic card block: %d " , blockNum ) ;
2012-07-05 18:59:15 +08:00
return 3 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2012-07-05 18:59:15 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2012-07-05 18:59:15 +08:00
return 0 ;
2017-07-11 23:45:23 +08:00
}
len = strlen ( Cmd ) ;
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
memcpy ( filename , Cmd , len ) ;
fnameptr + = len ;
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
sprintf ( fnameptr , " .eml " ) ;
// open file
f = fopen ( filename , " r " ) ;
if ( f = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File not found or locked. " ) ;
2017-07-11 23:45:23 +08:00
return 1 ;
}
blockNum = 0 ;
2017-08-28 15:39:20 +08:00
while ( ! feof ( f ) ) {
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
memset ( buf , 0 , sizeof ( buf ) ) ;
2015-01-21 04:48:39 +08:00
2017-07-11 23:45:23 +08:00
if ( fgets ( buf , sizeof ( buf ) , f ) = = NULL ) {
fclose ( f ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File reading error. " ) ;
2017-07-11 23:45:23 +08:00
return 2 ;
}
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
if ( strlen ( buf ) < 32 ) {
if ( strlen ( buf ) & & feof ( f ) )
break ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File content error. Block data must include 32 HEX symbols " ) ;
2017-07-11 23:45:23 +08:00
fclose ( f ) ;
return 2 ;
}
2017-12-03 03:45:53 +08:00
for ( i = 0 ; i < 32 ; i + = 2 ) {
sscanf ( & buf [ i ] , " %02x " , & tmp ) ;
buf8 [ i / 2 ] = tmp & 0xFF ;
}
2017-07-11 23:45:23 +08:00
if ( blockNum = = 0 ) flags = MAGIC_INIT + MAGIC_WUPC ; // switch on field and send magic sequence
if ( blockNum = = 1 ) flags = 0 ; // just write
if ( blockNum = = 16 * 4 - 1 ) flags = MAGIC_HALT + MAGIC_OFF ; // Done. Switch off field.
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
if ( mfCSetBlock ( blockNum , buf8 , NULL , flags ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can't set magic card block: %d " , blockNum ) ;
2017-07-11 23:45:23 +08:00
fclose ( f ) ;
return 3 ;
2012-07-05 18:59:15 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2017-07-11 23:45:23 +08:00
blockNum + + ;
2012-07-05 18:59:15 +08:00
2017-07-11 23:45:23 +08:00
if ( blockNum > = 16 * 4 ) break ; // magic card type - mifare 1K
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2017-07-11 23:45:23 +08:00
fclose ( f ) ;
// 64 or 256blocks.
if ( blockNum ! = 16 * 4 & & blockNum ! = 32 * 4 + 8 * 16 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File content error. There must be 64 blocks " ) ;
2017-07-11 23:45:23 +08:00
return 4 ;
2012-07-05 18:59:15 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Loaded %d blocks from file: %s " , blockNum , filename ) ;
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 ) {
2017-08-29 03:25:29 +08:00
uint8_t data [ 16 ] = { 0 } ;
2012-07-05 22:05:01 +08:00
uint8_t blockNo = 0 ;
int res ;
2015-11-10 04:46:15 +08:00
memset ( data , 0x00 , sizeof ( data ) ) ;
2012-07-05 22:05:01 +08:00
2017-07-11 23:45:23 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( strlen ( Cmd ) < 1 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_cgetblk ( ) ;
2012-07-05 22:05:01 +08:00
blockNo = param_get8 ( Cmd , 0 ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " --block number:%2d " , blockNo ) ;
2012-07-05 22:05:01 +08:00
2015-11-10 04:46:15 +08:00
res = mfCGetBlock ( blockNo , data , MAGIC_SINGLE ) ;
2012-07-05 22:05:01 +08:00
if ( res ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can't read block. error=%d " , res ) ;
2015-11-10 04:46:15 +08:00
return 1 ;
}
2012-07-05 22:05:01 +08:00
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " data: %s " , sprint_hex ( data , sizeof ( data ) ) ) ;
2012-07-05 22:05:01 +08:00
return 0 ;
}
int CmdHF14AMfCGetSc ( const char * Cmd ) {
2017-08-29 03:25:29 +08:00
uint8_t data [ 16 ] = { 0 } ;
2017-07-11 23:45:23 +08:00
uint8_t sector = 0 ;
2012-07-05 22:05:01 +08:00
int i , res , flags ;
2017-07-11 23:45:23 +08:00
2015-11-10 04:46:15 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
2017-07-11 23:45:23 +08:00
if ( strlen ( Cmd ) < 1 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_cgetsc ( ) ;
2012-07-05 22:05:01 +08:00
2017-07-11 23:45:23 +08:00
sector = param_get8 ( Cmd , 0 ) ;
if ( sector > 39 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Sector number must be less then 40 " ) ;
2012-07-05 22:05:01 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n # | data | Sector | %02d/ 0x%02X " , sector , sector ) ;
PrintAndLogEx ( NORMAL , " ----+------------------------------------------------ " ) ;
2017-07-11 23:45:23 +08:00
uint8_t blocks = 4 ;
uint8_t start = sector * 4 ;
if ( sector > 32 ) {
blocks = 16 ;
start = 128 + ( sector - 32 ) * 16 ;
}
2015-11-10 04:46:15 +08:00
flags = MAGIC_INIT + MAGIC_WUPC ;
2017-07-11 23:45:23 +08:00
for ( i = 0 ; i < blocks ; i + + ) {
2012-07-05 22:05:01 +08:00
if ( i = = 1 ) flags = 0 ;
2017-07-11 23:45:23 +08:00
if ( i = = blocks - 1 ) flags = MAGIC_HALT + MAGIC_OFF ;
2012-07-05 22:05:01 +08:00
2017-07-11 23:45:23 +08:00
res = mfCGetBlock ( start + i , data , flags ) ;
2012-07-05 22:05:01 +08:00
if ( res ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Can't read block. %d error=%d " , start + i , res ) ;
2012-07-05 22:05:01 +08:00
return 1 ;
2017-07-11 23:45:23 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " %3d | %s " , start + i , sprint_hex ( data , 16 ) ) ;
2012-07-05 22:05:01 +08:00
}
return 0 ;
}
int CmdHF14AMfCSave ( const char * Cmd ) {
2017-07-11 23:45:23 +08:00
FILE * feml ;
FILE * fbin ;
char filename [ 2 ] [ FILE_PATH_SIZE ] ;
char * femlptr = filename [ 0 ] ;
char * fbinptr = filename [ 1 ] ;
bool fillFromEmulator = false ;
bool errors = false ;
bool hasname = false ;
uint8_t buf [ 16 ] ;
2012-07-05 22:05:01 +08:00
int i , j , len , flags ;
2017-07-11 23:45:23 +08:00
uint8_t numblocks = 0 ;
uint8_t cmdp = 0 ;
char ctmp ;
2012-07-05 22:05:01 +08:00
2015-11-10 04:46:15 +08:00
memset ( filename , 0 , sizeof ( filename ) ) ;
memset ( buf , 0 , sizeof ( buf ) ) ;
2012-07-05 22:05:01 +08:00
2017-07-15 02:54:11 +08:00
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 & & ! errors ) {
2017-07-11 23:45:23 +08:00
ctmp = param_getchar ( Cmd , cmdp ) ;
switch ( ctmp ) {
case ' e ' :
case ' E ' :
fillFromEmulator = true ;
cmdp + + ;
break ;
case ' h ' :
case ' H ' :
return usage_hf14_csave ( ) ;
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 4 ' :
numblocks = NumOfBlocks ( ctmp ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Saving magic mifare %cK " , ctmp ) ;
2017-07-11 23:45:23 +08:00
cmdp + + ;
break ;
case ' u ' :
case ' U ' :
// get filename based on UID
if ( mfCGetBlock ( 0 , buf , MAGIC_SINGLE ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Cant get block: %d " , 0 ) ;
2017-07-11 23:45:23 +08:00
femlptr + = sprintf ( femlptr , " dump " ) ;
fbinptr + = sprintf ( fbinptr , " dump " ) ;
} else {
for ( j = 0 ; j < 7 ; j + + ) {
femlptr + = sprintf ( femlptr , " %02x " , buf [ j ] ) ;
fbinptr + = sprintf ( fbinptr , " %02x " , buf [ j ] ) ;
}
}
hasname = true ;
cmdp + + ;
break ;
2017-08-29 20:40:34 +08:00
case ' o ' :
case ' O ' :
2017-07-11 23:45:23 +08:00
// input file
2017-11-12 06:23:01 +08:00
len = param_getstr ( Cmd , cmdp + 1 , filename [ 0 ] , FILE_PATH_SIZE ) ;
len = param_getstr ( Cmd , cmdp + 1 , filename [ 1 ] , FILE_PATH_SIZE ) ;
2017-08-29 20:40:34 +08:00
2017-07-11 23:45:23 +08:00
if ( len < 1 ) {
errors = true ;
break ;
}
if ( len > FILE_PATH_SIZE - 5 ) len = FILE_PATH_SIZE - 5 ;
2017-08-29 20:40:34 +08:00
2017-07-11 23:45:23 +08:00
femlptr + = len ;
fbinptr + = len ;
hasname = true ;
cmdp + = 2 ;
break ;
default :
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Unknown parameter '%c' " , param_getchar ( Cmd , cmdp ) ) ;
2017-07-11 23:45:23 +08:00
errors = true ;
break ;
}
}
// must have filename when saving.
if ( ! hasname & & ! fillFromEmulator ) errors = true ;
//Validations
2017-07-15 02:54:11 +08:00
if ( errors | | cmdp = = 0 ) return usage_hf14_csave ( ) ;
2017-07-11 23:45:23 +08:00
2012-07-05 22:05:01 +08:00
if ( fillFromEmulator ) {
// put into emulator
2015-11-10 04:46:15 +08:00
flags = MAGIC_INIT + MAGIC_WUPC ;
2017-07-11 23:45:23 +08:00
for ( i = 0 ; i < numblocks ; i + + ) {
2012-07-05 22:05:01 +08:00
if ( i = = 1 ) flags = 0 ;
2017-07-11 23:45:23 +08:00
if ( i = = numblocks - 1 ) flags = MAGIC_HALT + MAGIC_OFF ;
2012-07-05 22:05:01 +08:00
if ( mfCGetBlock ( i , buf , flags ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Cant get block: %d " , i ) ;
2017-07-11 23:45:23 +08:00
return 3 ;
2012-07-05 22:05:01 +08:00
}
if ( mfEmlSetMem ( buf , i , 1 ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Cant set emul block: %d " , i ) ;
2012-07-05 22:05:01 +08:00
return 3 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2012-07-05 22:05:01 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2012-07-05 22:05:01 +08:00
return 0 ;
2017-07-11 23:45:23 +08:00
}
2012-07-05 22:05:01 +08:00
2017-07-11 23:45:23 +08:00
sprintf ( femlptr , " .eml " ) ;
sprintf ( fbinptr , " .bin " ) ;
2012-07-05 22:05:01 +08:00
2017-07-11 23:45:23 +08:00
if ( ( feml = fopen ( filename [ 0 ] , " w+ " ) ) = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File not found or locked " ) ;
2017-07-11 23:45:23 +08:00
return 1 ;
}
if ( ( fbin = fopen ( filename [ 1 ] , " wb " ) ) = = NULL ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " File not found or locked " ) ;
2017-07-11 23:45:23 +08:00
return 1 ;
}
// dump to files
flags = MAGIC_INIT + MAGIC_WUPC ;
for ( i = 0 ; i < numblocks ; i + + ) {
if ( i = = 1 ) flags = 0 ;
if ( i = = numblocks - 1 ) flags = MAGIC_HALT + MAGIC_OFF ;
if ( mfCGetBlock ( i , buf , flags ) ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Cant get block: %d " , i ) ;
2017-07-11 23:45:23 +08:00
break ;
2015-01-08 05:00:29 +08:00
}
2017-07-11 23:45:23 +08:00
// eml
for ( j = 0 ; j < 16 ; j + + )
fprintf ( feml , " %02x " , buf [ j ] ) ;
fprintf ( feml , " \n " ) ;
2012-07-05 22:05:01 +08:00
2017-07-11 23:45:23 +08:00
// bin
fwrite ( buf , 1 , sizeof ( buf ) , fbin ) ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " . " ) ; fflush ( stdout ) ;
2012-07-05 22:05:01 +08:00
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n " ) ;
2017-07-11 23:45:23 +08:00
fflush ( feml ) ; fflush ( fbin ) ;
fclose ( feml ) ; fclose ( fbin ) ;
for ( uint8_t i = 0 ; i < 2 ; + + i )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( SUCCESS , " Saved %d blocks to file: %s " , numblocks , filename [ i ] ) ;
2017-07-11 23:45:23 +08:00
return 0 ;
2012-07-05 22:05:01 +08:00
}
2015-10-08 05:00:46 +08:00
//needs nt, ar, at, Data to decrypt
2017-08-26 18:57:18 +08:00
int CmdHf14AMfDecryptBytes ( const char * Cmd ) {
2017-08-31 01:13:49 +08:00
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( strlen ( Cmd ) < 1 | | ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_decryptbytes ( ) ;
2015-10-11 15:07:29 +08:00
uint32_t nt = param_get32ex ( Cmd , 0 , 0 , 16 ) ;
uint32_t ar_enc = param_get32ex ( Cmd , 1 , 0 , 16 ) ;
uint32_t at_enc = param_get32ex ( Cmd , 2 , 0 , 16 ) ;
2017-08-31 01:13:49 +08:00
int len = param_getlength ( Cmd , 3 ) ;
if ( len & 1 ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Uneven hex string length. LEN=%d " , len ) ;
2017-08-31 01:13:49 +08:00
return 1 ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " nt \t %08X " , nt ) ;
PrintAndLogEx ( NORMAL , " ar enc \t %08X " , ar_enc ) ;
PrintAndLogEx ( NORMAL , " at enc \t %08X " , at_enc ) ;
2017-08-31 01:13:49 +08:00
uint8_t * data = malloc ( len ) ;
2015-10-11 15:07:29 +08:00
param_gethex_ex ( Cmd , 3 , data , & len ) ;
2017-08-31 01:13:49 +08:00
len > > = 1 ;
tryDecryptWord ( nt , ar_enc , at_enc , data , len ) ;
free ( data ) ;
return 0 ;
2015-10-08 05:00:46 +08:00
}
2015-01-27 15:34:48 +08:00
2017-03-09 21:36:19 +08:00
int CmdHf14AMfSetMod ( const char * Cmd ) {
uint8_t key [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
uint8_t mod = 2 ;
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp = = ' 0 ' ) {
mod = 0 ;
} else if ( ctmp = = ' 1 ' ) {
mod = 1 ;
}
int gethexfail = param_gethex ( Cmd , 1 , key , 12 ) ;
if ( mod = = 2 | | gethexfail ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Sets the load modulation strength of a MIFARE Classic EV1 card. " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf mf setmod <0|1> <block 0 key A> " ) ;
PrintAndLogEx ( NORMAL , " 0 = normal modulation " ) ;
PrintAndLogEx ( NORMAL , " 1 = strong modulation (default) " ) ;
2017-03-09 21:36:19 +08:00
return 1 ;
}
UsbCommand c = { CMD_MIFARE_SETMOD , { mod , 0 , 0 } } ;
memcpy ( c . d . asBytes , key , 6 ) ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
UsbCommand resp ;
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
uint8_t ok = resp . arg [ 0 ] & 0xff ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " isOk:%02x " , ok ) ;
2017-07-11 23:45:23 +08:00
if ( ! ok )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( FAILED , " Failed. " ) ;
2017-03-09 21:36:19 +08:00
} else {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Command execute timeout " ) ;
2017-03-09 21:36:19 +08:00
}
return 0 ;
}
2017-12-05 02:36:26 +08:00
// Mifare NACK bug detection
int CmdHf14AMfNack ( const char * Cmd ) {
2017-12-06 06:34:52 +08:00
bool verbose = false ;
char ctmp = param_getchar ( Cmd , 0 ) ;
if ( ctmp = = ' h ' | | ctmp = = ' H ' ) return usage_hf14_nack ( ) ;
if ( ctmp = = ' v ' | | ctmp = = ' V ' ) verbose = true ;
if ( verbose )
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Started testing card for NACK bug. Press key to abort " ) ;
2017-12-05 02:36:26 +08:00
2017-12-06 06:34:52 +08:00
detect_classic_nackbug ( verbose ) ;
2017-12-05 02:36:26 +08:00
return 0 ;
}
2017-08-26 18:57:18 +08:00
int CmdHF14AMfice ( const char * Cmd ) {
uint8_t blockNo = 0 ;
uint8_t keyType = 0 ;
uint8_t trgBlockNo = 0 ;
uint8_t trgKeyType = 1 ;
bool slow = false ;
bool initialize = true ;
bool acquisition_completed = false ;
2018-02-08 22:52:53 +08:00
uint8_t cmdp = 0 ;
2017-08-26 18:57:18 +08:00
uint32_t flags = 0 ;
uint32_t total_num_nonces = 0 ;
2018-02-08 22:52:53 +08:00
char ctmp ;
char filename [ FILE_PATH_SIZE ] , * fptr ;
2017-08-26 18:57:18 +08:00
FILE * fnonces = NULL ;
UsbCommand resp ;
uint32_t part_limit = 3000 ;
2018-02-08 22:52:53 +08:00
uint32_t limit = 50000 ;
while ( ( ctmp = param_getchar ( Cmd , cmdp ) ) ) {
switch ( tolower ( ctmp ) )
{
case ' h ' :
return usage_hf14_ice ( ) ;
case ' f ' :
param_getstr ( Cmd , cmdp + 1 , filename , FILE_PATH_SIZE ) ;
cmdp + + ;
break ;
case ' l ' :
limit = param_get32ex ( Cmd , cmdp + 1 , 50000 , 10 ) ;
cmdp + + ;
break ;
default :
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( WARNING , " Unknown parameter '%c' \n " , ctmp ) ;
2018-02-08 22:52:53 +08:00
usage_hf14_ice ( ) ;
return 1 ;
}
cmdp + + ;
}
if ( filename [ 0 ] = = ' \0 ' )
{
fptr = GenerateFilename ( " hf-mf- " , " -nonces.bin " ) ;
if ( fptr = = NULL )
return 1 ;
strcpy ( filename , fptr ) ;
}
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Collecting %u nonces \n " , limit ) ;
2017-08-26 18:57:18 +08:00
2018-02-08 22:52:53 +08:00
if ( ( fnonces = fopen ( filename , " wb " ) ) = = NULL ) {
2018-02-21 18:45:53 +08:00
PrintAndLogEx ( WARNING , " Could not create file %s " , filename ) ;
2017-08-26 18:57:18 +08:00
return 3 ;
}
clearCommandBuffer ( ) ;
uint64_t t1 = msclock ( ) ;
do {
if ( ukbhit ( ) ) {
int gc = getchar ( ) ; ( void ) gc ;
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " \n aborted via keyboard! \n " ) ;
2017-08-26 18:57:18 +08:00
break ;
}
flags = 0 ;
flags | = initialize ? 0x0001 : 0 ;
flags | = slow ? 0x0002 : 0 ;
UsbCommand c = { CMD_MIFARE_ACQUIRE_NONCES , { blockNo + keyType * 0x100 , trgBlockNo + trgKeyType * 0x100 , flags } } ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 3000 ) ) goto out ;
if ( resp . arg [ 0 ] ) goto out ;
uint32_t items = resp . arg [ 2 ] ;
if ( fnonces ) {
fwrite ( resp . d . asBytes , 1 , items * 4 , fnonces ) ;
fflush ( fnonces ) ;
}
total_num_nonces + = items ;
if ( total_num_nonces > part_limit ) {
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " Total nonces %u \n " , total_num_nonces ) ;
2017-08-26 18:57:18 +08:00
part_limit + = 3000 ;
}
acquisition_completed = ( total_num_nonces > limit ) ;
initialize = false ;
} while ( ! acquisition_completed ) ;
out :
2018-02-21 14:52:22 +08:00
PrintAndLogEx ( NORMAL , " time: % " PRIu64 " seconds \n " , ( msclock ( ) - t1 ) / 1000 ) ;
2017-08-26 18:57:18 +08:00
if ( fnonces ) {
fflush ( fnonces ) ;
fclose ( fnonces ) ;
}
UsbCommand c = { CMD_MIFARE_ACQUIRE_NONCES , { blockNo + keyType * 0x100 , trgBlockNo + trgKeyType * 0x100 , 4 } } ;
clearCommandBuffer ( ) ;
SendCommand ( & c ) ;
return 0 ;
}
2016-01-13 06:29:05 +08:00
static command_t CommandTable [ ] = {
{ " help " , CmdHelp , 1 , " This help " } ,
2018-02-05 23:50:06 +08:00
{ " darkside " , CmdHF14ADarkside , 0 , " Darkside attack. read parity error messages. " } ,
{ " nested " , CmdHF14AMfNested , 0 , " Nested attack. Test nested authentication " } ,
{ " hardnested " , CmdHF14AMfNestedHard , 0 , " Nested attack for hardened Mifare cards " } ,
{ " keybrute " , CmdHF14AMfKeyBrute , 0 , " J_Run's 2nd phase of multiple sector nested authentication key recovery " } ,
{ " nack " , CmdHf14AMfNack , 0 , " Test for Mifare NACK bug " } ,
{ " chk " , CmdHF14AMfChk , 0 , " Check keys " } ,
{ " fchk " , CmdHF14AMfChk_fast , 0 , " Check keys fast, targets all keys on card " } ,
{ " decrypt " , CmdHf14AMfDecryptBytes , 1 , " [nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace " } ,
{ " ----------- " , CmdHelp , 1 , " " } ,
2016-01-13 06:29:05 +08:00
{ " 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-02-05 23:50:06 +08:00
{ " setmod " , CmdHf14AMfSetMod , 0 , " Set MIFARE Classic EV1 load modulation strength " } ,
2018-01-18 21:11:22 +08:00
// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
2018-02-05 23:50:06 +08:00
{ " ----------- " , CmdHelp , 1 , " " } ,
2016-01-13 06:29:05 +08:00
{ " 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 " } ,
2018-02-05 23:50:06 +08:00
{ " ----------- " , CmdHelp , 1 , " " } ,
2016-01-13 06:29:05 +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 " } ,
2018-02-05 23:50:06 +08:00
2017-08-26 18:57:18 +08:00
{ " ice " , CmdHF14AMfice , 0 , " collect Mifare Classic nonces to file " } ,
2016-01-13 06:29:05 +08:00
{ NULL , NULL , 0 , NULL }
2011-06-10 21:35:10 +08:00
} ;
2016-01-13 06:29:05 +08:00
int CmdHFMF ( const char * Cmd ) {
2016-01-13 05:30:22 +08:00
clearCommandBuffer ( ) ;
2015-11-10 04:46:15 +08:00
CmdsParse ( CommandTable , Cmd ) ;
return 0 ;
2011-06-10 21:35:10 +08:00
}
2016-01-13 06:29:05 +08:00
int CmdHelp ( const char * Cmd ) {
2015-11-10 04:46:15 +08:00
CmdsHelp ( CommandTable ) ;
return 0 ;
2011-06-10 21:35:10 +08:00
}