Merge pull request #2654 from Antiklesys/master
[RRG-proxmark3.git] / client / src / cmdhfmf.c
blobf80005c639e9d2b098f28e50f5046a7d405d121f
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // High frequency MIFARE commands
17 //-----------------------------------------------------------------------------
19 #include "cmdhfmf.h"
20 #include <ctype.h>
22 #include "bruteforce.h"
23 #include "cmdparser.h" // command_t
24 #include "commonutil.h" // ARRAYLEN
25 #include "comms.h" // clearCommandBuffer
26 #include "fileutils.h"
27 #include "cmdtrace.h"
28 #include "mifare/mifaredefault.h" // mifare default key array
29 #include "cliparser.h" // argtable
30 #include "hardnested_bf_core.h" // SetSIMDInstr
31 #include "mifare/mad.h"
32 #include "nfc/ndef.h"
33 #include "protocols.h"
34 #include "util_posix.h" // msclock
35 #include "cmdhfmfhard.h"
36 #include "crapto1/crapto1.h" // prng_successor
37 #include "cmdhf14a.h" // exchange APDU
38 #include "crypto/libpcrypto.h"
39 #include "wiegand_formats.h"
40 #include "wiegand_formatutils.h"
41 #include "cmdhw.h" // set_fpga_mode
42 #include "loclass/cipherutils.h" // BitstreamOut_t
43 #include "proxendian.h"
44 #include "preferences.h"
45 #include "mifare/gen4.h"
46 #include "generator.h" // keygens.
47 #include "fpga.h"
48 #include "mifare/mifarehost.h"
50 static int CmdHelp(const char *Cmd);
53 static int usage_hf14_keybrute(void) {
54 PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery");
55 PrintAndLogEx(NORMAL, "You have a known 4 last bytes of a key recovered with mf_nonce_brute tool.");
56 PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced");
57 PrintAndLogEx(NORMAL, "");
58 PrintAndLogEx(NORMAL, " ---[ This attack is obsolete, try hardnested instead ]---");
59 PrintAndLogEx(NORMAL, "Options:");
60 PrintAndLogEx(NORMAL, " h this help");
61 PrintAndLogEx(NORMAL, " <block number> target block number");
62 PrintAndLogEx(NORMAL, " <A|B> target key type");
63 PrintAndLogEx(NORMAL, " <key> candidate key from mf_nonce_brute tool");
64 PrintAndLogEx(NORMAL, "Examples:");
65 PrintAndLogEx(NORMAL, _YELLOW_(" hf mf keybrute --blk 1 -k 000011223344"));
66 return 0;
70 int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
72 // ref: MIFARE Classic EV1 Originality Signature Validation
73 #define PUBLIC_MFCEV1_ECDA_KEYLEN 33
74 const ecdsa_publickey_t nxp_mfc_public_keys[] = {
75 {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
76 {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
77 {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
78 {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
79 {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
80 {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
81 {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
82 {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
83 {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
84 {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
87 uint8_t i;
88 bool is_valid = false;
90 for (i = 0; i < ARRAYLEN(nxp_mfc_public_keys); i++) {
92 int dl = 0;
93 uint8_t key[PUBLIC_MFCEV1_ECDA_KEYLEN];
94 param_gethex_to_eol(nxp_mfc_public_keys[i].value, 0, key, PUBLIC_MFCEV1_ECDA_KEYLEN, &dl);
96 int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, uidlen, signature, signature_len, false);
97 is_valid = (res == 0);
98 if (is_valid)
99 break;
102 PrintAndLogEx(INFO, "");
103 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
104 if (is_valid == false || i == ARRAYLEN(nxp_mfc_public_keys)) {
105 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
106 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
107 PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
108 return PM3_ESOFT;
111 PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfc_public_keys[i].desc);
112 PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfc_public_keys[i].value);
113 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
114 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
115 PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
116 return PM3_SUCCESS;
119 static int mf_read_uid(uint8_t *uid, int *uidlen, int *nxptype) {
120 clearCommandBuffer();
121 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
122 PacketResponseNG resp;
123 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
124 PrintAndLogEx(DEBUG, "iso14443a card select failed");
125 DropField();
126 return PM3_ERFTRANS;
129 iso14a_card_select_t card;
130 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
132 if (nxptype) {
133 uint64_t select_status = resp.oldarg[0];
134 *nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
137 memcpy(uid, card.uid, card.uidlen * sizeof(uint8_t));
138 *uidlen = card.uidlen;
139 return PM3_SUCCESS;
142 static char *GenerateFilename(const char *prefix, const char *suffix) {
143 if (! IfPm3Iso14443a()) {
144 return NULL;
146 uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
147 int uidlen = 0;
148 char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid) * 2 + 1, sizeof(uint8_t));
150 int res = mf_read_uid(uid, &uidlen, NULL);
151 if (res != PM3_SUCCESS || !uidlen) {
152 PrintAndLogEx(WARNING, "No tag found.");
153 free(fptr);
154 return NULL;
157 strcpy(fptr, prefix);
158 FillFileNameByUID(fptr, uid, suffix, uidlen);
159 return fptr;
162 static int initSectorTable(sector_t **src, size_t items) {
164 (*src) = calloc(items, sizeof(sector_t));
165 if (*src == NULL)
166 return PM3_EMALLOC;
168 // empty e_sector
169 for (size_t i = 0; i < items; i++) {
170 for (uint8_t j = 0; j < 2; j++) {
171 (*src)[i].Key[j] = 0xffffffffffff;
172 (*src)[i].foundKey[j] = 0;
175 return PM3_SUCCESS;
178 static void decode_print_st(uint16_t blockno, uint8_t *data) {
179 if (mfIsSectorTrailer(blockno)) {
180 PrintAndLogEx(NORMAL, "");
181 PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Sector trailer decoder") " --------------------------");
182 PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6));
183 PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3));
184 PrintAndLogEx(INFO, "user / gpb... " _GREEN_("%02x"), data[9]);
185 PrintAndLogEx(INFO, "key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6));
186 PrintAndLogEx(INFO, "");
187 PrintAndLogEx(INFO, " # | access rights");
188 PrintAndLogEx(INFO, "----+-----------------------------------------------------------------------");
190 if (mfValidateAccessConditions(&data[6]) == false) {
191 PrintAndLogEx(WARNING, _RED_("Invalid Access Conditions"));
195 int bln = mfFirstBlockOfSector(mfSectorNum(blockno));
196 int blinc = (mfNumBlocksPerSector(mfSectorNum(blockno)) > 4) ? 5 : 1;
197 for (int i = 0; i < 4; i++) {
198 PrintAndLogEx(INFO, "%3d%c| " _YELLOW_("%s"), bln, ((blinc > 1) && (i < 3) ? '+' : ' '), mfGetAccessConditionsDesc(i, &data[6]));
199 bln += blinc;
201 if (i == 3) {
202 uint8_t cond = mf_get_accesscondition(i, &data[6]);
203 if (cond == 0 || cond == 1 || cond == 2) {
204 PrintAndLogEx(INFO, "");
205 PrintAndLogEx(INFO, "OBS! Key B is readable, it SHALL NOT be able to authenticate on original MFC");
211 PrintAndLogEx(INFO, "----------------------------------------------------------------------------");
212 PrintAndLogEx(NORMAL, "");
216 static uint8_t NumOfSectors(char card) {
217 switch (card) {
218 case '0' :
219 return MIFARE_MINI_MAXSECTOR;
220 case '1' :
221 return MIFARE_1K_MAXSECTOR;
222 case '2' :
223 return MIFARE_2K_MAXSECTOR;
224 case '4' :
225 return MIFARE_4K_MAXSECTOR;
226 default :
227 return 0;
231 static char GetFormatFromSector(uint8_t sectors) {
232 switch (sectors) {
233 case MIFARE_MINI_MAXSECTOR:
234 return '0';
235 case MIFARE_1K_MAXSECTOR:
236 return '1';
237 case MIFARE_2K_MAXSECTOR:
238 return '2';
239 case MIFARE_4K_MAXSECTOR:
240 return '4';
241 default :
242 return ' ';
246 bool mfc_value(const uint8_t *d, int32_t *val) {
247 // values
248 int32_t a = (int32_t)MemLeToUint4byte(d);
249 uint32_t a_inv = MemLeToUint4byte(d + 4);
250 uint32_t b = MemLeToUint4byte(d + 8);
252 int val_checks = (
253 (a == b) && (a == ~a_inv) &&
254 (d[12] == (~d[13] & 0xFF)) &&
255 (d[14] == (~d[15] & 0xFF))
258 if (val) {
259 *val = a;
261 return val_checks;
264 void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) {
266 if (blockno == 0) {
267 char ascii[24] = {0};
268 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
269 PrintAndLogEx(INFO, "%3d | " _RED_("%s") "| " _RED_("%s"),
270 blockno,
271 sprint_hex(d, MFBLOCK_SIZE),
272 ascii
274 } else if (mfIsSectorTrailer(blockno)) {
276 char keya[26] = {0};
277 hex_to_buffer((uint8_t *)keya, d, MIFARE_KEY_SIZE, sizeof(keya) - 1, 0, 1, true);
279 char acl[20] = {0};
280 hex_to_buffer((uint8_t *)acl, d + MIFARE_KEY_SIZE, 3, sizeof(acl) - 1, 0, 1, true);
282 char keyb[26] = {0};
283 hex_to_buffer((uint8_t *)keyb, d + 10, MIFARE_KEY_SIZE, sizeof(keyb) - 1, 0, 1, true);
285 char ascii[24] = {0};
286 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
288 PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
289 blockno,
290 keya,
291 acl,
292 d[9],
293 keyb,
294 ascii
297 } else {
298 int32_t value = 0;
299 if (verbose && mfc_value(d, &value)) {
300 PrintAndLogEx(INFO, "%3d | " _CYAN_("%s") " %"PRIi32, blockno, sprint_hex_ascii(d, MFBLOCK_SIZE), value);
301 } else {
302 PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
307 static void mf_print_block(uint8_t blockno, uint8_t *d, bool verbose) {
308 uint8_t sectorno = mfSectorNum(blockno);
310 char secstr[6] = " ";
311 if (mfFirstBlockOfSector(sectorno) == blockno) {
312 sprintf(secstr, " %3d ", sectorno);
315 if (blockno == 0) {
316 char ascii[24] = {0};
317 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
318 PrintAndLogEx(INFO, "%s| %3d | " _RED_("%s") "| " _RED_("%s"),
319 secstr,
320 blockno,
321 sprint_hex(d, MFBLOCK_SIZE),
322 ascii
325 } else if (mfIsSectorTrailer(blockno)) {
327 char keya[26] = {0};
328 hex_to_buffer((uint8_t *)keya, d, MIFARE_KEY_SIZE, sizeof(keya) - 1, 0, 1, true);
330 char acl[20] = {0};
331 hex_to_buffer((uint8_t *)acl, d + MIFARE_KEY_SIZE, 3, sizeof(acl) - 1, 0, 1, true);
333 char keyb[26] = {0};
334 hex_to_buffer((uint8_t *)keyb, d + 10, MIFARE_KEY_SIZE, sizeof(keyb) - 1, 0, 1, true);
336 char ascii[24] = {0};
337 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
339 PrintAndLogEx(INFO, "%s| %3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
340 secstr,
341 blockno,
342 keya,
343 acl,
344 d[9],
345 keyb,
346 ascii
348 } else {
349 int32_t value = 0;
350 if (verbose && mfc_value(d, &value)) {
351 PrintAndLogEx(INFO, "%s| %3d | " _CYAN_("%s") " %"PRIi32, secstr, blockno, sprint_hex_ascii(d, MFBLOCK_SIZE), value);
352 } else {
353 PrintAndLogEx(INFO, "%s| %3d | %s ", secstr, blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
358 static void mf_print_blocks(uint16_t n, uint8_t *d, bool verbose) {
359 PrintAndLogEx(NORMAL, "");
360 PrintAndLogEx(INFO, "-----+-----+-------------------------------------------------+-----------------");
361 PrintAndLogEx(INFO, " sec | blk | data | ascii");
362 PrintAndLogEx(INFO, "-----+-----+-------------------------------------------------+-----------------");
363 for (uint16_t i = 0; i < n; i++) {
364 mf_print_block(i, d + (i * MFBLOCK_SIZE), verbose);
366 PrintAndLogEx(INFO, "-----+-----+-------------------------------------------------+-----------------");
367 if (verbose) {
368 PrintAndLogEx(HINT, _CYAN_("cyan") " = value block with decoded value");
371 // MAD detection
372 if (HasMADKey(d)) {
373 PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
375 PrintAndLogEx(NORMAL, "");
378 // assumes n is in number of blocks 0..255
379 static int mf_print_keys(uint16_t n, uint8_t *d) {
380 uint8_t sectors = 0;
381 switch (n) {
382 case MIFARE_MINI_MAXBLOCK:
383 sectors = MIFARE_MINI_MAXSECTOR;
384 break;
385 case MIFARE_2K_MAXBLOCK:
386 sectors = MIFARE_2K_MAXSECTOR;
387 break;
388 case MIFARE_4K_MAXBLOCK:
389 sectors = MIFARE_4K_MAXSECTOR;
390 break;
391 case MIFARE_1K_MAXBLOCK:
392 sectors = MIFARE_1K_MAXSECTOR;
393 break;
394 default:
395 sectors = MIFARE_1K_MAXSECTOR;
396 n = MIFARE_1K_MAXBLOCK;
397 break;
400 sector_t *e_sector = calloc(sectors, sizeof(sector_t));
401 if (e_sector == NULL) {
402 return PM3_EMALLOC;
405 for (uint16_t i = 0; i < n; i++) {
406 if (mfIsSectorTrailer(i) == false) {
407 continue;
409 // zero based index...
410 uint8_t lookup = mfSectorNum(i);
411 uint8_t sec = MIN(sectors - 1, lookup);
412 e_sector[sec].foundKey[0] = 1;
413 e_sector[sec].Key[0] = bytes_to_num(d + (i * MFBLOCK_SIZE), MIFARE_KEY_SIZE);
414 e_sector[sec].foundKey[1] = 1;
415 e_sector[sec].Key[1] = bytes_to_num(d + (i * MFBLOCK_SIZE) + 10, MIFARE_KEY_SIZE);
417 printKeyTable(sectors, e_sector);
418 free(e_sector);
419 return PM3_SUCCESS;
422 // MFC dump , extract and save the keys to key file
423 // assumes n is in number of blocks 0..255
424 static int mf_save_keys_from_arr(uint16_t n, uint8_t *d) {
425 uint8_t sectors = 0;
426 switch (n) {
427 case MIFARE_MINI_MAXBLOCK:
428 sectors = MIFARE_MINI_MAXSECTOR;
429 break;
430 case MIFARE_2K_MAXBLOCK:
431 sectors = MIFARE_2K_MAXSECTOR;
432 break;
433 case MIFARE_4K_MAXBLOCK:
434 sectors = MIFARE_4K_MAXSECTOR;
435 break;
436 case MIFARE_1K_MAXBLOCK:
437 default:
438 sectors = MIFARE_1K_MAXSECTOR;
439 break;
442 uint16_t keysize = 2 * MIFARE_KEY_SIZE * sectors;
444 uint8_t *keys = calloc(keysize, sizeof(uint8_t));
445 if (keys == NULL) {
446 return PM3_EMALLOC;
449 uint8_t sector = 0;
450 for (uint16_t i = 0; i < n; i++) {
451 if (mfIsSectorTrailer(i)) {
452 // key A offset in ST block
453 memcpy(keys + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE), MIFARE_KEY_SIZE);
455 // key B offset in ST block
456 memcpy(keys + (MIFARE_KEY_SIZE * sectors) + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE) + 10, MIFARE_KEY_SIZE);
458 sector++;
462 char fn[FILE_PATH_SIZE] = {0};
463 snprintf(fn, sizeof(fn), "hf-mf-%s-key", sprint_hex_inrow(d, 4));
464 saveFileEx(fn, ".bin", keys, keysize, spDump);
465 free(keys);
466 return PM3_SUCCESS;
470 static void mf_print_values(uint16_t n, uint8_t *d) {
472 PrintAndLogEx(NORMAL, "");
473 PrintAndLogEx(INFO, "Looking for value blocks...");
474 PrintAndLogEx(NORMAL, "");
475 uint8_t cnt = 0;
476 int32_t value = 0;
477 for (uint16_t i = 0; i < n; i++) {
479 if (mfc_value(d + (i * MFBLOCK_SIZE), &value)) {
480 PrintAndLogEx(INFO, "%03d | " _YELLOW_("%" PRIi32) " " _YELLOW_("0x%" PRIX32), i, value, value);
481 ++cnt;
485 if (cnt) {
486 PrintAndLogEx(INFO, "Found %u value blocks in file", cnt);
487 PrintAndLogEx(NORMAL, "");
492 void mf_print_sector_hdr(uint8_t sector) {
493 PrintAndLogEx(NORMAL, "");
494 PrintAndLogEx(INFO, " # | sector " _GREEN_("%02d") " / " _GREEN_("0x%02X") " | ascii", sector, sector);
495 PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
499 // assumes n is in number of blocks 0..255
500 static void mf_analyse_acl(uint16_t n, uint8_t *d) {
502 for (uint16_t b = 3; b < n; b++) {
503 if (mfIsSectorTrailer(b) == false) {
504 continue;
507 uint8_t block[MFBLOCK_SIZE] = {0x00};
508 memcpy(block, d + (b * MFBLOCK_SIZE), MFBLOCK_SIZE);
510 // ensure access right isn't messed up.
511 if (mfValidateAccessConditions(&block[6]) == false) {
512 PrintAndLogEx(WARNING, "Invalid Access Conditions on sector " _YELLOW_("%u"), mfSectorNum(b));
515 // Warn if ACL is strict read-only
516 uint8_t bar = mfNumBlocksPerSector(mfSectorNum(b));
517 for (uint8_t foo = 0; foo < bar; foo++) {
518 if (mfReadOnlyAccessConditions(foo, &block[6])) {
519 PrintAndLogEx(WARNING, _YELLOW_("s%u / b%u") " - Strict ReadOnly Access Conditions detected", mfSectorNum(b), b - bar + 1 + foo);
526 Sector trailer sanity checks.
527 Warn if ACL is strict read-only, or invalid ACL.
529 static int mf_analyse_st_block(uint8_t blockno, uint8_t *block, bool force) {
531 if (mfIsSectorTrailer(blockno) == false) {
532 return PM3_SUCCESS;
535 PrintAndLogEx(INFO, "Sector trailer (ST) write detected");
537 // ensure access right isn't messed up.
538 if (mfValidateAccessConditions(&block[6]) == false) {
539 PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing with default values");
540 memcpy(block + 6, "\xFF\x07\x80\x69", 4);
543 bool ro_detected = false;
544 uint8_t bar = mfNumBlocksPerSector(mfSectorNum(blockno));
545 for (uint8_t foo = 0; foo < bar; foo++) {
546 if (mfReadOnlyAccessConditions(foo, &block[6])) {
547 PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", blockno - bar + 1 + foo);
548 ro_detected = true;
551 if (ro_detected) {
552 if (force) {
553 PrintAndLogEx(WARNING, " --force override, continuing...");
554 } else {
555 PrintAndLogEx(INFO, "Exiting, please run `" _YELLOW_("hf mf acl -d %s") "` to understand", sprint_hex_inrow(&block[6], 3));
556 PrintAndLogEx(INFO, "Use `" _YELLOW_("--force") "` to override and write this data");
557 return PM3_EINVARG;
559 } else {
560 PrintAndLogEx(SUCCESS, "ST checks ( " _GREEN_("ok") " )");
563 return PM3_SUCCESS;
566 /* Reads data from tag
567 * @param card: (output) card info
568 * @param carddata: (output) card data
569 * @param numSectors: size of the card
570 * @param keyFileName: filename containing keys or NULL.
572 static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t numSectors, char *keyfn) {
574 // Select card to get UID/UIDLEN/ATQA/SAK information
575 clearCommandBuffer();
576 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
577 PacketResponseNG resp;
578 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
579 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
580 return PM3_ETIMEOUT;
583 uint64_t select_status = resp.oldarg[0];
584 if (select_status == 0) {
585 PrintAndLogEx(DEBUG, "iso14443a card select failed");
586 return PM3_ESOFT;
589 // store card info
590 memcpy(card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
592 char *fptr = NULL;
593 if (keyfn == NULL || keyfn[0] == '\0') {
594 fptr = GenerateFilename("hf-mf-", "-key.bin");
595 if (fptr == NULL)
596 return PM3_ESOFT;
598 keyfn = fptr ;
601 PrintAndLogEx(INFO, "Using... %s", keyfn);
603 size_t alen = 0, blen = 0;
604 uint8_t *keyA, *keyB;
605 if (loadFileBinaryKey(keyfn, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) {
606 free(fptr);
607 return PM3_ESOFT;
610 PrintAndLogEx(INFO, "Reading sector access bits...");
611 PrintAndLogEx(INFO, "." NOLF);
613 uint8_t rights[40][4] = {0};
615 mf_readblock_t payload;
616 uint8_t current_key;
617 for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) {
618 current_key = MF_KEY_A;
619 for (uint8_t tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
620 PrintAndLogEx(NORMAL, "." NOLF);
621 fflush(stdout);
623 if (kbd_enter_pressed()) {
624 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
625 free(fptr);
626 free(keyA);
627 free(keyB);
628 return PM3_EOPABORTED;
631 payload.blockno = mfFirstBlockOfSector(sectorNo) + mfNumBlocksPerSector(sectorNo) - 1;
632 payload.keytype = current_key;
634 memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
636 clearCommandBuffer();
637 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
639 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) {
641 uint8_t *data = resp.data.asBytes;
642 if (resp.status == PM3_SUCCESS) {
643 rights[sectorNo][0] = ((data[7] & 0x10) >> 2) | ((data[8] & 0x1) << 1) | ((data[8] & 0x10) >> 4); // C1C2C3 for data area 0
644 rights[sectorNo][1] = ((data[7] & 0x20) >> 3) | ((data[8] & 0x2) << 0) | ((data[8] & 0x20) >> 5); // C1C2C3 for data area 1
645 rights[sectorNo][2] = ((data[7] & 0x40) >> 4) | ((data[8] & 0x4) >> 1) | ((data[8] & 0x40) >> 6); // C1C2C3 for data area 2
646 rights[sectorNo][3] = ((data[7] & 0x80) >> 5) | ((data[8] & 0x8) >> 2) | ((data[8] & 0x80) >> 7); // C1C2C3 for sector trailer
647 break;
648 } else if (tries == (MIFARE_SECTOR_RETRY / 2)) { // after half unsuccessful tries, give key B a go
649 PrintAndLogEx(WARNING, "\nTrying with " _YELLOW_("key B") " instead...");
650 current_key = MF_KEY_B;
651 PrintAndLogEx(INFO, "." NOLF);
652 } else if (tries == (MIFARE_SECTOR_RETRY - 1)) { // on last try set defaults
653 PrintAndLogEx(FAILED, "\nFailed to read access rights for sector %2d ( fallback to default )", sectorNo);
654 rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00;
655 rights[sectorNo][3] = 0x01;
657 } else {
658 PrintAndLogEx(FAILED, "\nTimeout reading access rights for sector... %2d ( fallback to default )", sectorNo);
659 rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00;
660 rights[sectorNo][3] = 0x01;
665 PrintAndLogEx(NORMAL, "");
666 PrintAndLogEx(SUCCESS, "Finished reading sector access bits");
667 PrintAndLogEx(INFO, "Dumping all blocks from card...");
669 for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) {
670 for (uint8_t blockNo = 0; blockNo < mfNumBlocksPerSector(sectorNo); blockNo++) {
671 bool received = false;
672 current_key = MF_KEY_A;
673 uint8_t data_area = (sectorNo < 32) ? blockNo : blockNo / 5;
674 if (rights[sectorNo][data_area] == 0x07) { // no key would work
675 PrintAndLogEx(WARNING, "Access rights prevent reading sector... " _YELLOW_("%2d") " block... " _YELLOW_("%3d") " ( skip )", sectorNo, blockNo);
676 continue;
679 for (uint8_t tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
681 if (mfIsSectorTrailerBasedOnBlocks(sectorNo, blockNo)) {
683 // sector trailer. At least the Access Conditions can always be read with key A.
684 payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
685 payload.keytype = current_key;
686 memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
688 clearCommandBuffer();
689 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
690 received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
691 } else {
692 // data block. Check if it can be read with key A or key B
693 if ((rights[sectorNo][data_area] == 0x03) || (rights[sectorNo][data_area] == 0x05)) {
694 // only key B would work
695 payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
696 payload.keytype = MF_KEY_B;
697 memcpy(payload.key, keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
699 clearCommandBuffer();
700 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
701 received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
702 } else {
703 // key A would work
704 payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
705 payload.keytype = current_key;
706 memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
708 clearCommandBuffer();
709 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
710 received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
714 if (received) {
715 if (resp.status == PM3_SUCCESS) {
716 // break the re-try loop
717 break;
719 if ((current_key == MF_KEY_A) && (tries == (MIFARE_SECTOR_RETRY / 2))) {
720 // Half the tries failed with key A. Swap for key B
721 current_key = MF_KEY_B;
723 // clear out keyA since it failed.
724 memset(keyA + (sectorNo * MIFARE_KEY_SIZE), 0x00, MIFARE_KEY_SIZE);
729 if (received) {
731 if (resp.status == PM3_SUCCESS) {
733 uint8_t *data = resp.data.asBytes;
735 if (mfIsSectorTrailerBasedOnBlocks(sectorNo, blockNo)) {
736 // sector trailer. Fill in the keys.
737 memcpy(data, keyA + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
738 memcpy(data + 10, keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
741 memcpy(carddata + (MFBLOCK_SIZE * (mfFirstBlockOfSector(sectorNo) + blockNo)), data, MFBLOCK_SIZE);
742 PrintAndLogEx(INPLACE, "Sector... " _YELLOW_("%2d") " block..." _YELLOW_("%2d") " ( " _GREEN_("ok") " )", sectorNo, blockNo);
743 } else {
744 PrintAndLogEx(FAILED, "\nSector... %2d Block... %2d ( " _RED_("fail") " )", sectorNo, blockNo);
746 } else {
747 PrintAndLogEx(WARNING, "Timeout reading sector... %2d block... %2d", sectorNo, blockNo);
752 free(fptr);
753 free(keyA);
754 free(keyB);
755 PrintAndLogEx(SUCCESS, "\nSucceeded in dumping all blocks");
756 return PM3_SUCCESS ;
759 static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey, int userkeylen, const char *filename, int fnlen, bool load_default) {
760 // Handle Keys
761 *pkeycnt = 0;
762 *pkeyBlock = NULL;
763 uint8_t *p;
764 // Handle user supplied key
765 // (it considers *pkeycnt and *pkeyBlock as possibly non-null so logic can be easily reordered)
766 if (userkeylen >= MIFARE_KEY_SIZE) {
767 int numKeys = userkeylen / MIFARE_KEY_SIZE;
768 p = realloc(*pkeyBlock, numKeys * MIFARE_KEY_SIZE);
769 if (!p) {
770 PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
771 free(*pkeyBlock);
772 return PM3_EMALLOC;
774 *pkeyBlock = p;
776 memcpy(*pkeyBlock, userkey, numKeys * MIFARE_KEY_SIZE);
778 for (int i = 0; i < numKeys; i++) {
779 PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", i, sprint_hex(*pkeyBlock + i * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE));
781 *pkeycnt += numKeys;
782 PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " user keys", numKeys);
785 if (load_default) {
786 // Handle default keys
787 p = realloc(*pkeyBlock, (*pkeycnt + ARRAYLEN(g_mifare_default_keys)) * MIFARE_KEY_SIZE);
788 if (!p) {
789 PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
790 free(*pkeyBlock);
791 return PM3_EMALLOC;
793 *pkeyBlock = p;
794 // Copy default keys to list
795 for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) {
796 num_to_bytes(g_mifare_default_keys[i], MIFARE_KEY_SIZE, (uint8_t *)(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE));
797 PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE));
799 *pkeycnt += ARRAYLEN(g_mifare_default_keys);
800 PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%zu") " hardcoded keys", ARRAYLEN(g_mifare_default_keys));
803 // Handle user supplied dictionary file
804 if (fnlen > 0) {
805 uint32_t loaded_numKeys = 0;
806 uint8_t *keyBlock_tmp = NULL;
807 int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock_tmp, MIFARE_KEY_SIZE, &loaded_numKeys);
808 if (res != PM3_SUCCESS || loaded_numKeys == 0 || keyBlock_tmp == NULL) {
809 PrintAndLogEx(FAILED, "An error occurred while loading the dictionary!");
810 free(keyBlock_tmp);
811 free(*pkeyBlock);
812 return PM3_EFILE;
813 } else {
814 p = realloc(*pkeyBlock, (*pkeycnt + loaded_numKeys) * MIFARE_KEY_SIZE);
815 if (!p) {
816 PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
817 free(keyBlock_tmp);
818 free(*pkeyBlock);
819 return PM3_EMALLOC;
821 *pkeyBlock = p;
822 memcpy(*pkeyBlock + *pkeycnt * MIFARE_KEY_SIZE, keyBlock_tmp, loaded_numKeys * MIFARE_KEY_SIZE);
823 *pkeycnt += loaded_numKeys;
824 free(keyBlock_tmp);
827 return PM3_SUCCESS;
830 static int CmdHF14AMfAcl(const char *Cmd) {
831 CLIParserContext *ctx;
832 CLIParserInit(&ctx, "hf mf acl",
833 "Print decoded MIFARE access rights (ACL), \n"
834 " A = key A\n"
835 " B = key B\n"
836 " AB = both key A and B\n"
837 " ACCESS = access bytes inside sector trailer block\n"
838 " Increment, decrement, transfer, restore is for value blocks",
839 "hf mf acl\n"
840 "hf mf acl -d FF0780\n");
842 void *argtable[] = {
843 arg_param_begin,
844 arg_str1("d", "data", "<hex>", "ACL bytes specified as 3 hex bytes"),
845 arg_param_end
847 CLIExecWithReturn(ctx, Cmd, argtable, true);
849 int acllen = 0;
850 uint8_t acl[3] = {0};
851 CLIGetHexWithReturn(ctx, 1, acl, &acllen);
853 CLIParserFree(ctx);
855 PrintAndLogEx(NORMAL, "");
857 // look up common default ACL bytes and print a fingerprint line about it.
858 if (memcmp(acl, "\xFF\x07\x80", 3) == 0) {
859 PrintAndLogEx(INFO, "ACL... " _GREEN_("%s") " (transport configuration)", sprint_hex(acl, sizeof(acl)));
861 if (mfValidateAccessConditions(acl) == false) {
862 PrintAndLogEx(ERR, _RED_("Invalid Access Conditions, NEVER write these on a card!"));
864 PrintAndLogEx(NORMAL, "");
865 PrintAndLogEx(INFO, " # | Access rights");
866 PrintAndLogEx(INFO, "----+-----------------------------------------------------------------");
867 for (int i = 0; i < 4; i++) {
868 PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), i, mfGetAccessConditionsDesc(i, acl));
870 PrintAndLogEx(NORMAL, "");
871 return PM3_SUCCESS;
874 static int CmdHF14AMfDarkside(const char *Cmd) {
875 CLIParserContext *ctx;
876 CLIParserInit(&ctx, "hf mf darkside",
877 "Darkside attack",
878 "hf mf darkside\n"
879 "hf mf darkside --blk 16\n"
880 "hf mf darkside --blk 16 -b\n");
882 void *argtable[] = {
883 arg_param_begin,
884 arg_int0(NULL, "blk", "<dec> ", "Target block"),
885 arg_lit0("b", NULL, "Target key B instead of default key A"),
886 arg_int0("c", NULL, "<dec>", "Target key type is key A + offset"),
887 arg_param_end
889 CLIExecWithReturn(ctx, Cmd, argtable, true);
891 uint8_t blockno = arg_get_u32_def(ctx, 1, 0) & 0xFF;
892 uint8_t key_type = MF_KEY_A;
894 if (arg_get_lit(ctx, 2)) {
895 PrintAndLogEx(INFO, "Targeting key B");
896 key_type = MF_KEY_B;
899 uint8_t prev_keytype = key_type;
900 key_type = arg_get_int_def(ctx, 3, key_type);
901 if (arg_get_lit(ctx, 2) && (key_type != prev_keytype)) {
902 CLIParserFree(ctx);
903 PrintAndLogEx(WARNING, "Choose one single target key type");
904 return PM3_EINVARG;
906 // mf_dark_side expects the full command byte 0x6x
907 key_type += MIFARE_AUTH_KEYA;
909 CLIParserFree(ctx);
911 uint64_t key = 0;
912 uint64_t t1 = msclock();
913 int ret = mf_dark_side(blockno, key_type, &key);
914 t1 = msclock() - t1;
916 if (ret != PM3_SUCCESS) return ret;
918 PrintAndLogEx(SUCCESS, "found valid key: " _GREEN_("%012" PRIx64), key);
919 PrintAndLogEx(SUCCESS, "time in darkside " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
920 return PM3_SUCCESS;
923 static int CmdHF14AMfWrBl(const char *Cmd) {
925 CLIParserContext *ctx;
926 CLIParserInit(&ctx, "hf mf wrbl",
927 "Write MIFARE Classic block with 16 hex bytes of data\n"
928 " \n"
929 "Sector 0 / Block 0 - Manufacturer block\n"
930 "When writing to block 0 you must use a VALID block 0 data (UID, BCC, SAK, ATQA)\n"
931 "Writing an invalid block 0 means rendering your Magic GEN2 card undetectable. \n"
932 "Look in the magic_cards_notes.md file for help to resolve it.\n"
933 " \n"
934 "`--force` param is used to override warnings like bad ACL and BLOCK 0 writes.\n"
935 " if not specified, it will exit if detected",
936 "hf mf wrbl --blk 1 -d 000102030405060708090a0b0c0d0e0f\n"
937 "hf mf wrbl --blk 1 -k A0A1A2A3A4A5 -d 000102030405060708090a0b0c0d0e0f\n"
939 void *argtable[] = {
940 arg_param_begin,
941 arg_int1(NULL, "blk", "<dec>", "block number"),
942 arg_lit0("a", NULL, "input key type is key A (def)"),
943 arg_lit0("b", NULL, "input key type is key B"),
944 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
945 arg_lit0(NULL, "force", "override warnings"),
946 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
947 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
948 arg_param_end
950 CLIExecWithReturn(ctx, Cmd, argtable, false);
952 int b = arg_get_int_def(ctx, 1, 1);
954 uint8_t keytype = MF_KEY_A;
955 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
956 CLIParserFree(ctx);
957 PrintAndLogEx(WARNING, "Choose one single input key type");
958 return PM3_EINVARG;
959 } else if (arg_get_lit(ctx, 3)) {
960 keytype = MF_KEY_B;
962 uint8_t prev_keytype = keytype;
963 keytype = arg_get_int_def(ctx, 4, keytype);
964 if ((arg_get_lit(ctx, 2) || arg_get_lit(ctx, 3)) && (keytype != prev_keytype)) {
965 CLIParserFree(ctx);
966 PrintAndLogEx(WARNING, "Choose one single input key type");
967 return PM3_EINVARG;
969 bool force = arg_get_lit(ctx, 5);
971 int keylen = 0;
972 uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
973 CLIGetHexWithReturn(ctx, 6, key, &keylen);
975 uint8_t block[MFBLOCK_SIZE] = {0x00};
976 int blen = 0;
977 CLIGetHexWithReturn(ctx, 7, block, &blen);
978 CLIParserFree(ctx);
980 if (keylen && keylen != 6) {
981 PrintAndLogEx(WARNING, "Key must be 12 hex digits. Got %d", keylen);
982 return PM3_EINVARG;
985 if (blen != MFBLOCK_SIZE) {
986 PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", blen);
987 return PM3_EINVARG;
990 if (b > 255) {
991 return PM3_EINVARG;
994 // BLOCK 0 detection
995 if (b == 0 && force == false) {
996 PrintAndLogEx(NORMAL, "");
997 PrintAndLogEx(INFO, "Targeting Sector 0 / Block 0 - Manufacturer block");
998 PrintAndLogEx(INFO, "Read the helptext for details before writing to this block");
999 PrintAndLogEx(INFO, "You must use param `" _YELLOW_("--force") "` to write to this block");
1000 PrintAndLogEx(NORMAL, "");
1001 return PM3_EINVARG;
1004 uint8_t blockno = (uint8_t)b;
1006 if (mf_analyse_st_block(blockno, block, force) != PM3_SUCCESS) {
1007 return PM3_EINVARG;
1010 if (keytype < 2) {
1011 PrintAndLogEx(INFO, "Writing block no %d, key type:%c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
1012 } else {
1013 PrintAndLogEx(INFO, "Writing block no %d, key type:%02x - %s", blockno, MIFARE_AUTH_KEYA + keytype, sprint_hex_inrow(key, sizeof(key)));
1016 PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block)));
1018 uint8_t data[26];
1019 memcpy(data, key, sizeof(key));
1020 memcpy(data + 10, block, sizeof(block));
1021 clearCommandBuffer();
1022 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, keytype, 0, data, sizeof(data));
1024 PacketResponseNG resp;
1025 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1026 PrintAndLogEx(FAILED, "command execution time out");
1027 return PM3_ETIMEOUT;
1030 int status = resp.oldarg[0];
1031 if (status > 0) {
1032 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
1033 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf rdbl") "` to verify");
1034 } else if (status == PM3_ETEAROFF) {
1035 return status;
1036 } else {
1037 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
1038 // suggest the opposite keytype than what was used.
1039 PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype `" _YELLOW_("hf mf wrbl -%c ...") "` instead", (keytype == MF_KEY_A) ? 'b' : 'a');
1041 return PM3_SUCCESS;
1044 static int CmdHF14AMfRdBl(const char *Cmd) {
1045 CLIParserContext *ctx;
1046 CLIParserInit(&ctx, "hf mf rdbl",
1047 "Read MIFARE Classic block",
1048 "hf mf rdbl --blk 0\n"
1049 "hf mf rdbl --blk 0 -k A0A1A2A3A4A5\n"
1050 "hf mf rdbl --blk 3 -v -> get block 3, decode sector trailer\n"
1052 void *argtable[] = {
1053 arg_param_begin,
1054 arg_int1(NULL, "blk", "<dec>", "block number"),
1055 arg_lit0("a", NULL, "input key type is key A (def)"),
1056 arg_lit0("b", NULL, "input key type is key B"),
1057 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
1058 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
1059 arg_lit0("v", "verbose", "verbose output"),
1060 arg_param_end
1062 CLIExecWithReturn(ctx, Cmd, argtable, false);
1063 int b = arg_get_int_def(ctx, 1, 0);
1065 uint8_t keytype = MF_KEY_A;
1066 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
1067 CLIParserFree(ctx);
1068 PrintAndLogEx(WARNING, "Choose one single input key type");
1069 return PM3_EINVARG;
1070 } else if (arg_get_lit(ctx, 3)) {
1071 keytype = MF_KEY_B;
1073 keytype = arg_get_int_def(ctx, 4, keytype);
1074 uint8_t prev_keytype = keytype;
1075 keytype = arg_get_int_def(ctx, 4, keytype);
1076 if ((arg_get_lit(ctx, 2) || arg_get_lit(ctx, 3)) && (keytype != prev_keytype)) {
1077 CLIParserFree(ctx);
1078 PrintAndLogEx(WARNING, "Choose one single input key type");
1079 return PM3_EINVARG;
1082 int keylen = 0;
1083 uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1084 CLIGetHexWithReturn(ctx, 5, key, &keylen);
1085 bool verbose = arg_get_lit(ctx, 6);
1086 CLIParserFree(ctx);
1088 if (keylen && keylen != 6) {
1089 PrintAndLogEx(WARNING, "Key must be 12 hex digits. Got %d", keylen);
1090 return PM3_EINVARG;
1093 if (b > 255) {
1094 return PM3_EINVARG;
1096 uint8_t blockno = (uint8_t)b;
1098 uint8_t data[16] = {0};
1099 int res = mf_read_block(blockno, keytype, key, data);
1100 if (res == PM3_SUCCESS) {
1102 uint8_t sector = mfSectorNum(blockno);
1103 mf_print_sector_hdr(sector);
1104 mf_print_block_one(blockno, data, verbose);
1105 if (verbose) {
1106 decode_print_st(blockno, data);
1109 PrintAndLogEx(NORMAL, "");
1110 return res;
1113 static int CmdHF14AMfRdSc(const char *Cmd) {
1115 CLIParserContext *ctx;
1116 CLIParserInit(&ctx, "hf mf rdsc",
1117 "Read MIFARE Classic sector",
1118 "hf mf rdsc -s 0\n"
1119 "hf mf rdsc -s 0 -k A0A1A2A3A4A5\n"
1121 void *argtable[] = {
1122 arg_param_begin,
1123 arg_lit0("a", NULL, "input key specified is A key (def)"),
1124 arg_lit0("b", NULL, "input key specified is B key"),
1125 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
1126 arg_str0("k", "key", "<hex>", "key specified as 6 hex bytes"),
1127 arg_int1("s", "sec", "<dec>", "sector number"),
1128 arg_lit0("v", "verbose", "verbose output"),
1129 arg_param_end
1131 CLIExecWithReturn(ctx, Cmd, argtable, false);
1132 uint8_t keytype = MF_KEY_A;
1133 if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) {
1134 CLIParserFree(ctx);
1135 PrintAndLogEx(WARNING, "Choose one single input key type");
1136 return PM3_EINVARG;
1137 } else if (arg_get_lit(ctx, 2)) {
1138 keytype = MF_KEY_B;
1140 uint8_t prev_keytype = keytype;
1141 keytype = arg_get_int_def(ctx, 3, keytype);
1142 if ((arg_get_lit(ctx, 1) || arg_get_lit(ctx, 2)) && (keytype != prev_keytype)) {
1143 CLIParserFree(ctx);
1144 PrintAndLogEx(WARNING, "Choose one single input key type");
1145 return PM3_EINVARG;
1148 int keylen = 0;
1149 uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1150 CLIGetHexWithReturn(ctx, 4, key, &keylen);
1152 int s = arg_get_int_def(ctx, 5, 0);
1153 bool verbose = arg_get_lit(ctx, 6);
1154 CLIParserFree(ctx);
1156 if (keylen && keylen != 6) {
1157 PrintAndLogEx(WARNING, "Key must be 12 hex digits. Got %d", keylen);
1158 return PM3_EINVARG;
1161 if (s >= MIFARE_4K_MAXSECTOR) {
1162 PrintAndLogEx(WARNING, "Sector number must be less then 40");
1163 return PM3_EINVARG;
1166 uint8_t sector = (uint8_t)s;
1167 uint16_t sc_size = mfNumBlocksPerSector(sector) * MFBLOCK_SIZE;
1169 uint8_t *data = calloc(sc_size, sizeof(uint8_t));
1170 if (data == NULL) {
1171 PrintAndLogEx(ERR, "failed to allocate memory");
1172 return PM3_EMALLOC;
1175 int res = mf_read_sector(sector, keytype, key, data);
1176 if (res == PM3_SUCCESS) {
1178 uint8_t blocks = mfNumBlocksPerSector(sector);
1179 uint8_t start = mfFirstBlockOfSector(sector);
1181 mf_print_sector_hdr(sector);
1182 for (int i = 0; i < blocks; i++) {
1183 mf_print_block_one(start + i, data + (i * MFBLOCK_SIZE), verbose);
1186 if (verbose) {
1187 decode_print_st(start + blocks - 1, data + ((blocks - 1) * MFBLOCK_SIZE));
1190 free(data);
1191 PrintAndLogEx(NORMAL, "");
1192 return PM3_SUCCESS;
1195 static int FastDumpWithEcFill(uint8_t numsectors) {
1197 uint8_t dbg_curr = DBG_NONE;
1198 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
1199 return PM3_EFAILED;
1203 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
1204 return PM3_EFAILED;
1208 mfc_eload_t payload;
1209 payload.sectorcnt = numsectors;
1210 payload.keytype = MF_KEY_A;
1212 // ecfill key A
1213 clearCommandBuffer();
1214 SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
1216 PacketResponseNG resp;
1217 bool res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2500);
1218 if (res == false) {
1219 PrintAndLogEx(WARNING, "command execution time out");
1220 return PM3_ETIMEOUT;
1223 if (resp.status != PM3_SUCCESS) {
1224 PrintAndLogEx(FAILED, "fast dump reported back failure w KEY A, swapping to KEY B");
1226 // ecfill key B
1227 payload.keytype = MF_KEY_B;
1229 clearCommandBuffer();
1230 SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
1231 res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2500);
1232 if (res == false) {
1233 PrintAndLogEx(WARNING, "command execution time out");
1234 setDeviceDebugLevel(dbg_curr, false);
1235 return PM3_ETIMEOUT;
1238 if (resp.status != PM3_SUCCESS) {
1239 PrintAndLogEx(FAILED, "fast dump reported back failure w KEY B");
1240 PrintAndLogEx(FAILED, "Dump file is " _RED_("PARTIAL") " complete");
1244 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
1245 return PM3_EFAILED;
1248 return PM3_SUCCESS;
1251 static int CmdHF14AMfDump(const char *Cmd) {
1252 CLIParserContext *ctx;
1253 CLIParserInit(&ctx, "hf mf dump",
1254 "Dump MIFARE Classic tag to file (bin/json)\n"
1255 "If no <name> given, UID will be used as filename",
1256 "hf mf dump --mini --> MIFARE Mini\n"
1257 "hf mf dump --1k --> MIFARE Classic 1k\n"
1258 "hf mf dump --2k --> MIFARE 2k\n"
1259 "hf mf dump --4k --> MIFARE 4k\n"
1260 "hf mf dump --keys hf-mf-066C8B78-key.bin --> MIFARE 1k with keys from specified file\n");
1262 void *argtable[] = {
1263 arg_param_begin,
1264 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
1265 arg_str0("k", "keys", "<fn>", "filename of keys"),
1266 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
1267 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
1268 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
1269 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
1270 arg_lit0(NULL, "ns", "no save to file"),
1271 arg_lit0("v", "verbose", "verbose output"),
1272 arg_param_end
1274 CLIExecWithReturn(ctx, Cmd, argtable, true);
1276 int datafnlen = 0;
1277 char dataFilename[FILE_PATH_SIZE] = {0};
1278 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)dataFilename, FILE_PATH_SIZE, &datafnlen);
1280 int keyfnlen = 0;
1281 char keyFilename[FILE_PATH_SIZE] = {0};
1282 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
1284 bool m0 = arg_get_lit(ctx, 3);
1285 bool m1 = arg_get_lit(ctx, 4);
1286 bool m2 = arg_get_lit(ctx, 5);
1287 bool m4 = arg_get_lit(ctx, 6);
1288 bool nosave = arg_get_lit(ctx, 7);
1289 bool verbose = arg_get_lit(ctx, 8);
1290 CLIParserFree(ctx);
1292 uint64_t t1 = msclock();
1294 // validations
1295 if ((m0 + m1 + m2 + m4) > 1) {
1296 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
1297 return PM3_EINVARG;
1298 } else if ((m0 + m1 + m2 + m4) == 0) {
1299 m1 = true;
1302 uint8_t numSectors = MIFARE_1K_MAXSECTOR;
1303 uint16_t bytes = MIFARE_1K_MAX_BYTES;
1304 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
1306 if (m0) {
1307 numSectors = MIFARE_MINI_MAXSECTOR;
1308 bytes = MIFARE_MINI_MAX_BYTES;
1309 block_cnt = MIFARE_MINI_MAXBLOCK;
1310 } else if (m1) {
1311 numSectors = MIFARE_1K_MAXSECTOR;
1312 bytes = MIFARE_1K_MAX_BYTES;
1313 block_cnt = MIFARE_1K_MAXBLOCK;
1314 } else if (m2) {
1315 numSectors = MIFARE_2K_MAXSECTOR;
1316 bytes = MIFARE_2K_MAX_BYTES;
1317 block_cnt = MIFARE_2K_MAXBLOCK;
1318 } else if (m4) {
1319 numSectors = MIFARE_4K_MAXSECTOR;
1320 bytes = MIFARE_4K_MAX_BYTES;
1321 block_cnt = MIFARE_4K_MAXBLOCK;
1322 } else {
1323 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
1324 return PM3_EINVARG;
1327 // read card
1328 iso14a_card_select_t card ;
1329 uint8_t *mem = calloc(MIFARE_4K_MAX_BYTES, sizeof(uint8_t));
1330 if (mem == NULL) {
1331 PrintAndLogEx(ERR, "failed to allocate memory");
1332 return PM3_EMALLOC;
1334 int res = mfc_read_tag(&card, mem, numSectors, keyFilename);
1335 if (res != PM3_SUCCESS) {
1336 free(mem);
1337 return res;
1340 PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock() - t1) / 1000);
1342 mf_print_blocks(block_cnt, mem, verbose);
1344 if (verbose) {
1345 mf_print_keys(block_cnt, mem);
1346 mf_analyse_acl(block_cnt, mem);
1349 // Skip saving card data to file
1350 if (nosave) {
1351 PrintAndLogEx(INFO, "Called with no save option");
1352 free(mem);
1353 return PM3_SUCCESS;
1356 // Save to file
1357 if (strlen(dataFilename) < 1) {
1358 char *fptr = GenerateFilename("hf-mf-", "-dump");
1359 if (fptr == NULL) {
1360 free(mem);
1361 return PM3_ESOFT;
1364 strcpy(dataFilename, fptr);
1365 free(fptr);
1368 pm3_save_mf_dump(dataFilename, mem, bytes, jsfCardMemory);
1369 free(mem);
1370 return PM3_SUCCESS;
1373 static int CmdHF14AMfRestore(const char *Cmd) {
1375 CLIParserContext *ctx;
1376 CLIParserInit(&ctx, "hf mf restore",
1377 "Restore MIFARE Classic dump file to tag.\n"
1378 "\n"
1379 "The key file and dump file will program the card sector trailers.\n"
1380 "By default we authenticate to card with key 0xFFFFFFFFFFFF.\n"
1381 "If access rights in dump file is all zeros, it will be replaced with default values\n"
1382 "\n"
1383 "`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n"
1384 " if not specified, it will read the card uid instead.\n"
1385 " `--ka` param you can indicate that the key file should be used for authentication instead.\n"
1386 " if so we also try both B/A keys\n"
1387 "`--force` param is used to override warnings and allow bad ACL block writes.\n"
1388 " if not specified, it will skip blocks with bad ACL.\n",
1389 "hf mf restore\n"
1390 "hf mf restore --1k --uid 04010203\n"
1391 "hf mf restore --1k --uid 04010203 -k hf-mf-AABBCCDD-key.bin\n"
1392 "hf mf restore --4k"
1395 void *argtable[] = {
1396 arg_param_begin,
1397 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
1398 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
1399 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
1400 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
1401 arg_str0("u", "uid", "<hex>", "uid, (4|7|10 hex bytes)"),
1402 arg_str0("f", "file", "<fn>", "specify a filename for dump file"),
1403 arg_str0("k", "kfn", "<fn>", "key filename"),
1404 arg_lit0(NULL, "ka", "use specified keyfile to authenticate"),
1405 arg_lit0(NULL, "force", "override warnings"),
1406 arg_param_end
1408 CLIExecWithReturn(ctx, Cmd, argtable, true);
1410 bool m0 = arg_get_lit(ctx, 1);
1411 bool m1 = arg_get_lit(ctx, 2);
1412 bool m2 = arg_get_lit(ctx, 3);
1413 bool m4 = arg_get_lit(ctx, 4);
1415 int uidlen = 0;
1416 char uid[20] = {0};
1417 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)uid, sizeof(uid), &uidlen);
1419 int datafnlen = 0;
1420 char datafilename[FILE_PATH_SIZE] = {0};
1421 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)datafilename, FILE_PATH_SIZE, &datafnlen);
1423 int keyfnlen = 0;
1424 char keyfilename[FILE_PATH_SIZE] = {0};
1425 CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)keyfilename, FILE_PATH_SIZE, &keyfnlen);
1427 bool use_keyfile_for_auth = arg_get_lit(ctx, 8);
1428 bool force = arg_get_lit(ctx, 9);
1430 CLIParserFree(ctx);
1432 // validations
1433 if ((m0 + m1 + m2 + m4) > 1) {
1434 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
1435 return PM3_EINVARG;
1436 } else if ((m0 + m1 + m2 + m4) == 0) {
1437 m1 = true;
1440 uint8_t sectors = MIFARE_1K_MAXSECTOR;
1442 if (m0) {
1443 sectors = MIFARE_MINI_MAXSECTOR;
1444 } else if (m1) {
1445 sectors = MIFARE_1K_MAXSECTOR;
1446 } else if (m2) {
1447 sectors = MIFARE_2K_MAXSECTOR;
1448 } else if (m4) {
1449 sectors = MIFARE_4K_MAXSECTOR;
1450 } else {
1451 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
1452 return PM3_EINVARG;
1455 // if user specified UID, use it in file templates
1456 if (uidlen) {
1458 if (keyfnlen == 0) {
1459 snprintf(keyfilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", uid);
1460 keyfnlen = strlen(keyfilename);
1463 if (datafnlen == 0) {
1464 snprintf(datafilename, FILE_PATH_SIZE, "hf-mf-%s-dump.bin", uid);
1465 datafnlen = strlen(datafilename);
1469 // try reading card uid and create filename
1470 if (keyfnlen == 0) {
1471 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
1472 if (fptr == NULL)
1473 return PM3_ESOFT;
1475 strncpy(keyfilename, fptr, sizeof(keyfilename) - 1);
1476 free(fptr);
1480 size_t alen = 0, blen = 0;
1481 uint8_t *keyA, *keyB;
1482 if (loadFileBinaryKey(keyfilename, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) {
1483 return PM3_ESOFT;
1486 PrintAndLogEx(INFO, "Using key file `" _YELLOW_("%s") "`", keyfilename);
1488 // try reading card uid and create filename
1489 if (datafnlen == 0) {
1490 char *fptr = GenerateFilename("hf-mf-", "-dump.bin");
1491 if (fptr == NULL) {
1492 if (keyA) {
1493 free(keyA);
1495 if (keyB) {
1496 free(keyB);
1498 return PM3_ESOFT;
1500 strcpy(datafilename, fptr);
1501 free(fptr);
1504 // read dump file
1505 uint8_t *dump = NULL;
1506 size_t bytes_read = 0;
1507 int res = pm3_load_dump(datafilename, (void **)&dump, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
1508 if (res != PM3_SUCCESS) {
1509 free(keyA);
1510 free(keyB);
1511 return res;
1514 // default authentication key
1515 uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1517 PrintAndLogEx(NORMAL, "");
1518 PrintAndLogEx(INFO, " blk | data | status");
1519 PrintAndLogEx(INFO, "-----+-------------------------------------------------+----------------");
1521 // main loop for restoring.
1522 // a bit more complicated than needed
1523 // this is because of two things.
1524 // 1. we are setting keys from a key file or using the existing ones in the dump
1525 // 2. we need to authenticate against a card which might not have default keys.
1526 uint8_t *ref_dump = dump;
1527 for (uint8_t s = 0; s < sectors; s++) {
1528 for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) {
1530 uint8_t bldata[MFBLOCK_SIZE] = {0x00};
1531 memcpy(bldata, dump, MFBLOCK_SIZE);
1533 bool skip = false;
1534 // if sector trailer
1535 if (mfIsSectorTrailerBasedOnBlocks(s, b)) {
1536 // keep the current keys on the card
1537 if (use_keyfile_for_auth == false) {
1538 // replace KEY A
1539 memcpy(bldata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1541 // replace KEY B
1542 memcpy(bldata + 10, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1545 // ensure access right isn't messed up.
1546 if (mfValidateAccessConditions(&bldata[6]) == false) {
1547 PrintAndLogEx(WARNING, "Invalid Access Conditions on sector %i, replacing with default values", s);
1548 memcpy(bldata + 6, "\xFF\x07\x80\x69", 4);
1551 // Warn if ACL is strict read-only
1552 for (uint8_t foo = 0; foo < mfNumBlocksPerSector(s); foo++) {
1553 if (mfReadOnlyAccessConditions(foo, &bldata[6])) {
1554 PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", foo);
1556 // if --force isn't used, skip writing this block
1557 if (force == false) {
1558 PrintAndLogEx(INFO, "Skipping, use `" _YELLOW_("--force") "` to override and write this data");
1559 skip = true;
1565 if (bytes_read) {
1566 dump += MFBLOCK_SIZE;
1567 bytes_read -= MFBLOCK_SIZE;
1569 if (skip) {
1570 continue;
1573 uint8_t wdata[26];
1574 memcpy(wdata + 10, bldata, sizeof(bldata));
1576 for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
1577 if (use_keyfile_for_auth) {
1579 if (kt == MF_KEY_A) {
1580 memcpy(wdata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1581 } else {
1582 memcpy(wdata, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1585 } else {
1586 // use default key to authenticate for the write command
1587 memcpy(wdata, default_key, MIFARE_KEY_SIZE);
1590 uint16_t blockno = (mfFirstBlockOfSector(s) + b);
1592 clearCommandBuffer();
1593 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, kt, 0, wdata, sizeof(wdata));
1594 PacketResponseNG resp;
1595 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1596 PrintAndLogEx(WARNING, "command execution time out");
1597 continue;
1600 int isOK = resp.oldarg[0] & 0xff;
1601 if (isOK == 1) {
1602 // if success, skip to next block
1603 PrintAndLogEx(INFO, " %3d | %s| ( " _GREEN_("ok") " )", blockno, sprint_hex(bldata, sizeof(bldata)));
1604 break;
1606 // write somehow failed. Lets determine why.
1607 if (isOK == PM3_ETEAROFF) {
1608 PrintAndLogEx(INFO, "Tear off triggered. Recommendation is not to use tear-off with restore command");
1609 goto out;
1612 PrintAndLogEx(INFO, " %3d | %s| ( " _RED_("fail") " ) key " _YELLOW_("%c"),
1613 blockno,
1614 sprint_hex(bldata, sizeof(bldata)),
1615 (kt == MF_KEY_A) ? 'A' : 'B'
1617 } // end loop key types
1618 } // end loop B
1619 } // end loop S
1621 out:
1622 free(ref_dump);
1623 free(keyA);
1624 free(keyB);
1625 PrintAndLogEx(INFO, "-----+-------------------------------------------------+----------------");
1626 PrintAndLogEx(NORMAL, "");
1627 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf dump --ns") "` to verify");
1628 PrintAndLogEx(INFO, "Done!");
1629 return PM3_SUCCESS;
1632 static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't find keys...
1633 CLIParserContext *ctx;
1634 CLIParserInit(&ctx, "hf mf nested",
1635 "Execute Nested attack against MIFARE Classic card for key recovery",
1636 "hf mf nested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta --> Use block 0 Key A to find block 4 Key A (single sector key recovery)\n"
1637 "hf mf nested --mini --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n"
1638 "hf mf nested --1k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n"
1639 "hf mf nested --2k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n"
1640 "hf mf nested --4k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k");
1642 void *argtable[] = {
1643 arg_param_begin,
1644 arg_str0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
1645 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
1646 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
1647 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
1648 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
1649 arg_int0(NULL, "blk", "<dec>", "Input block number"),
1650 arg_lit0("a", NULL, "Input key specified is A key (default)"),
1651 arg_lit0("b", NULL, "Input key specified is B key"),
1652 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
1653 arg_int0(NULL, "tblk", "<dec>", "Target block number"),
1654 arg_lit0(NULL, "ta", "Target A key (default)"),
1655 arg_lit0(NULL, "tb", "Target B key"),
1656 arg_int0(NULL, "tc", "<dec>", "Nested input key type is key A + offset (you must specify a single block as well!)"),
1657 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
1658 arg_lit0(NULL, "dump", "Dump found keys to file"),
1659 arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
1660 arg_lit0("i", NULL, "Ignore static encrypted nonces"),
1661 arg_param_end
1663 CLIExecWithReturn(ctx, Cmd, argtable, false);
1665 int keylen = 0;
1666 uint8_t key[6] = {0};
1667 CLIGetHexWithReturn(ctx, 1, key, &keylen);
1669 bool m0 = arg_get_lit(ctx, 2);
1670 bool m1 = arg_get_lit(ctx, 3);
1671 bool m2 = arg_get_lit(ctx, 4);
1672 bool m4 = arg_get_lit(ctx, 5);
1674 uint8_t blockNo = arg_get_u32_def(ctx, 6, 0);
1676 uint8_t keyType = MF_KEY_A;
1678 if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) {
1679 CLIParserFree(ctx);
1680 PrintAndLogEx(WARNING, "Choose one single input key type");
1681 return PM3_EINVARG;
1682 } else if (arg_get_lit(ctx, 8)) {
1683 keyType = MF_KEY_B;
1685 uint8_t prev_keytype = keyType;
1686 keyType = arg_get_int_def(ctx, 9, keyType);
1687 if ((arg_get_lit(ctx, 7) || arg_get_lit(ctx, 8)) && (keyType != prev_keytype)) {
1688 CLIParserFree(ctx);
1689 PrintAndLogEx(WARNING, "Choose one single input key type");
1690 return PM3_EINVARG;
1693 int trgBlockNo = arg_get_int_def(ctx, 10, -1);
1695 uint8_t trgKeyType = MF_KEY_A;
1697 if (arg_get_lit(ctx, 11) && arg_get_lit(ctx, 12)) {
1698 CLIParserFree(ctx);
1699 PrintAndLogEx(WARNING, "Choose one single target key type");
1700 return PM3_EINVARG;
1701 } else if (arg_get_lit(ctx, 12)) {
1702 trgKeyType = MF_KEY_B;
1704 uint8_t prev_trgkeytype = trgKeyType;
1705 trgKeyType = arg_get_int_def(ctx, 13, trgKeyType);
1706 if ((arg_get_lit(ctx, 11) || arg_get_lit(ctx, 12)) && (trgKeyType != prev_trgkeytype)) {
1707 CLIParserFree(ctx);
1708 PrintAndLogEx(WARNING, "Choose one single target key type");
1709 return PM3_EINVARG;
1711 bool transferToEml = arg_get_lit(ctx, 14);
1712 bool createDumpFile = arg_get_lit(ctx, 15);
1713 bool singleSector = trgBlockNo > -1;
1714 bool use_flashmemory = arg_get_lit(ctx, 16);
1715 bool ignore_static_encrypted = arg_get_lit(ctx, 17);
1717 CLIParserFree(ctx);
1719 //validations
1720 if ((m0 + m1 + m2 + m4) > 1) {
1721 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
1722 return PM3_EINVARG;
1725 uint8_t SectorsCnt = 1;
1726 if (m0) {
1727 SectorsCnt = MIFARE_MINI_MAXSECTOR;
1728 } else if (m1) {
1729 SectorsCnt = MIFARE_1K_MAXSECTOR;
1730 } else if (m2) {
1731 SectorsCnt = MIFARE_2K_MAXSECTOR;
1732 } else if (m4) {
1733 SectorsCnt = MIFARE_4K_MAXSECTOR;
1736 if (singleSector) {
1737 uint8_t MinSectorsCnt = 0;
1738 // find a MIFARE type that can accommodate the provided block number
1739 uint8_t s = MAX(mfSectorNum(trgBlockNo), mfSectorNum(blockNo));
1740 if (s < MIFARE_MINI_MAXSECTOR) {
1741 MinSectorsCnt = MIFARE_MINI_MAXSECTOR;
1742 } else if (s < MIFARE_1K_MAXSECTOR) {
1743 MinSectorsCnt = MIFARE_1K_MAXSECTOR;
1744 } else if (s < MIFARE_2K_MAXSECTOR) {
1745 MinSectorsCnt = MIFARE_2K_MAXSECTOR;
1746 } else if (s < MIFARE_4K_MAXSECTOR) {
1747 MinSectorsCnt = MIFARE_4K_MAXSECTOR;
1748 } else {
1749 PrintAndLogEx(WARNING, "Provided block out of possible MIFARE Type memory map");
1750 return PM3_EINVARG;
1752 if (SectorsCnt == 1) {
1753 SectorsCnt = MinSectorsCnt;
1754 } else if (SectorsCnt < MinSectorsCnt) {
1755 PrintAndLogEx(WARNING, "Provided block out of provided MIFARE Type memory map");
1756 return PM3_EINVARG;
1759 if (SectorsCnt == 1) {
1760 SectorsCnt = MIFARE_1K_MAXSECTOR;
1763 if (keylen != 6) {
1764 PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols");
1765 return PM3_EINVARG;
1768 sector_t *e_sector = NULL;
1769 uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6];
1770 uint64_t key64 = 0;
1772 // check if tag doesn't have static nonce
1773 if (detect_classic_static_nonce() == NONCE_STATIC) {
1774 PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
1775 PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf staticnested`"));
1776 return PM3_EOPABORTED;
1779 // check if we can authenticate to sector
1780 if (mf_check_keys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) {
1781 if (keyType < 2) {
1782 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
1783 } else {
1784 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockNo, MIFARE_AUTH_KEYA + keyType);
1786 return PM3_EOPABORTED;
1789 if (singleSector) {
1790 int16_t isOK = mf_nested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, !ignore_static_encrypted);
1791 switch (isOK) {
1792 case PM3_ETIMEOUT:
1793 PrintAndLogEx(ERR, "command execution time out\n");
1794 break;
1795 case PM3_EOPABORTED:
1796 PrintAndLogEx(WARNING, "Button pressed. Aborted\n");
1797 break;
1798 case PM3_EFAILED:
1799 PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable).\n");
1800 break;
1801 case PM3_ESOFT:
1802 PrintAndLogEx(FAILED, "No valid key found");
1803 break;
1804 case PM3_ESTATIC_NONCE:
1805 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
1806 break;
1807 case PM3_SUCCESS:
1808 key64 = bytes_to_num(keyBlock, 6);
1810 // transfer key to the emulator
1811 if (transferToEml) {
1812 uint8_t sectortrailer;
1814 if (trgBlockNo < 32 * 4) { // 4 block sector
1815 sectortrailer = trgBlockNo | 0x03;
1816 } else { // 16 block sector
1817 sectortrailer = trgBlockNo | 0x0f;
1819 mf_eml_get_mem(keyBlock, sectortrailer, 1);
1821 if (trgKeyType == MF_KEY_A)
1822 num_to_bytes(key64, 6, keyBlock);
1823 else
1824 num_to_bytes(key64, 6, &keyBlock[10]);
1826 mf_elm_set_mem(keyBlock, sectortrailer, 1);
1827 PrintAndLogEx(SUCCESS, "Key transferred to emulator memory.");
1829 return PM3_SUCCESS;
1830 default :
1831 PrintAndLogEx(ERR, "Unknown error\n");
1833 return PM3_SUCCESS;
1835 } else { // ------------------------------------ multiple sectors working
1836 uint64_t t1 = msclock();
1838 e_sector = calloc(SectorsCnt, sizeof(sector_t));
1839 if (e_sector == NULL) return PM3_EMALLOC;
1841 // add our known key
1842 e_sector[mfSectorNum(blockNo)].foundKey[keyType] = 1;
1843 e_sector[mfSectorNum(blockNo)].Key[keyType] = key64;
1845 //test current key and additional standard keys first
1846 // add parameter key
1847 memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6);
1849 for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) {
1850 num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
1853 PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt);
1854 int res = mf_check_keys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, use_flashmemory, false);
1855 if (res == PM3_SUCCESS) {
1856 PrintAndLogEx(SUCCESS, "Fast check found all keys");
1857 goto jumptoend;
1860 uint64_t t2 = msclock() - t1;
1861 PrintAndLogEx(SUCCESS, "Time to check " _YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0);
1862 PrintAndLogEx(SUCCESS, "enter nested key recovery");
1864 // nested sectors
1865 bool calibrate = !ignore_static_encrypted;
1867 for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) {
1868 for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) {
1869 for (int i = 0; i < MIFARE_SECTOR_RETRY; i++) {
1871 if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
1873 int16_t isOK = mf_nested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
1874 switch (isOK) {
1875 case PM3_ETIMEOUT:
1876 PrintAndLogEx(ERR, "command execution time out\n");
1877 break;
1878 case PM3_EOPABORTED:
1879 PrintAndLogEx(WARNING, "button pressed. Aborted\n");
1880 break;
1881 case PM3_EFAILED :
1882 PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable)\n");
1883 break;
1884 case PM3_ESOFT:
1885 //key not found
1886 calibrate = false;
1887 continue;
1888 case PM3_ESTATIC_NONCE:
1889 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
1890 break;
1891 case PM3_SUCCESS:
1892 calibrate = false;
1893 e_sector[sectorNo].foundKey[trgKeyType] = 1;
1894 e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
1896 mf_check_keys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false);
1897 continue;
1898 default :
1899 PrintAndLogEx(ERR, "Unknown error\n");
1901 free(e_sector);
1902 return PM3_ESOFT;
1907 t1 = msclock() - t1;
1908 PrintAndLogEx(SUCCESS, "time in nested " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
1911 // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
1912 PrintAndLogEx(INFO, "trying to read key B...");
1913 for (int i = 0; i < SectorsCnt; i++) {
1914 // KEY A but not KEY B
1915 if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
1917 uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
1919 PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
1921 mf_readblock_t payload;
1922 payload.blockno = sectrail;
1923 payload.keytype = MF_KEY_A;
1925 num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
1927 clearCommandBuffer();
1928 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
1930 PacketResponseNG resp;
1931 if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
1933 if (resp.status != PM3_SUCCESS) continue;
1935 uint8_t *data = resp.data.asBytes;
1936 key64 = bytes_to_num(data + 10, 6);
1937 if (key64) {
1938 PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6));
1939 e_sector[i].foundKey[1] = true;
1940 e_sector[i].Key[1] = key64;
1945 jumptoend:
1947 PrintAndLogEx(NORMAL, "");
1948 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
1950 //print them
1951 printKeyTable(SectorsCnt, e_sector);
1953 // transfer them to the emulator
1954 if (transferToEml) {
1955 // fast push mode
1956 g_conn.block_after_ACK = true;
1957 for (int i = 0; i < SectorsCnt; i++) {
1958 mf_eml_get_mem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
1960 if (e_sector[i].foundKey[0])
1961 num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
1963 if (e_sector[i].foundKey[1])
1964 num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
1966 if (i == SectorsCnt - 1) {
1967 // Disable fast mode on last packet
1968 g_conn.block_after_ACK = false;
1970 mf_elm_set_mem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
1972 PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
1975 // Create dump file
1976 if (createDumpFile) {
1977 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
1978 if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
1979 PrintAndLogEx(ERR, "Failed to save keys to file");
1980 free(e_sector);
1981 free(fptr);
1982 return PM3_EFILE;
1984 free(fptr);
1986 free(e_sector);
1988 return PM3_SUCCESS;
1991 static int CmdHF14AMfNestedStatic(const char *Cmd) {
1992 CLIParserContext *ctx;
1993 CLIParserInit(&ctx, "hf mf staticnested",
1994 "Execute static nested attack against MIFARE Classic card with static nonce for key recovery.\n"
1995 "Supply a known key from one block to recover all keys",
1996 "hf mf staticnested --mini --blk 0 -a -k FFFFFFFFFFFF\n"
1997 "hf mf staticnested --1k --blk 0 -a -k FFFFFFFFFFFF\n"
1998 "hf mf staticnested --2k --blk 0 -a -k FFFFFFFFFFFF\n"
1999 "hf mf staticnested --4k --blk 0 -a -k FFFFFFFFFFFF\n");
2001 void *argtable[] = {
2002 arg_param_begin,
2003 arg_str0("k", "key", "<hex>", "Known key (12 hex symbols)"),
2004 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
2005 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
2006 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
2007 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
2008 arg_int0(NULL, "blk", "<dec>", "Input block number"),
2009 arg_lit0("a", NULL, "Input key specified is keyA (def)"),
2010 arg_lit0("b", NULL, "Input key specified is keyB"),
2011 arg_lit0("e", "emukeys", "Fill simulator keys from found keys"),
2012 arg_lit0(NULL, "dumpkeys", "Dump found keys to file"),
2013 arg_param_end
2015 CLIExecWithReturn(ctx, Cmd, argtable, false);
2017 int keylen = 0;
2018 uint8_t key[6] = {0};
2019 CLIGetHexWithReturn(ctx, 1, key, &keylen);
2021 bool m0 = arg_get_lit(ctx, 2);
2022 bool m1 = arg_get_lit(ctx, 3);
2023 bool m2 = arg_get_lit(ctx, 4);
2024 bool m4 = arg_get_lit(ctx, 5);
2026 uint8_t blockNo = arg_get_u32_def(ctx, 6, 0);
2028 uint8_t keyType = MF_KEY_A;
2030 if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) {
2031 CLIParserFree(ctx);
2032 PrintAndLogEx(WARNING, "Choose one single input key type");
2033 return PM3_EINVARG;
2034 } else if (arg_get_lit(ctx, 8)) {
2035 keyType = MF_KEY_B;
2038 bool transferToEml = arg_get_lit(ctx, 9);
2039 bool createDumpFile = arg_get_lit(ctx, 10);
2040 CLIParserFree(ctx);
2042 //validations
2043 if ((m0 + m1 + m2 + m4) > 1) {
2044 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
2045 return PM3_EINVARG;
2048 uint8_t SectorsCnt = 1;
2049 if (m0) {
2050 SectorsCnt = MIFARE_MINI_MAXSECTOR;
2051 } else if (m1) {
2052 SectorsCnt = MIFARE_1K_MAXSECTOR;
2053 } else if (m2) {
2054 SectorsCnt = MIFARE_2K_MAXSECTOR;
2055 } else if (m4) {
2056 SectorsCnt = MIFARE_4K_MAXSECTOR;
2057 } else {
2058 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
2059 return PM3_EINVARG;
2062 if (keylen != 6) {
2063 PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols");
2064 return PM3_EINVARG;
2067 sector_t *e_sector = NULL;
2069 uint8_t trgKeyType = MF_KEY_A;
2071 uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6];
2072 uint64_t key64 = 0;
2074 // check if tag have static nonce
2075 if (detect_classic_static_nonce() != NONCE_STATIC) {
2076 PrintAndLogEx(WARNING, "Normal nonce detected, or failed read of card. Quitting...");
2077 PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf nested`"));
2078 return PM3_EOPABORTED;
2081 // check if we can authenticate to sector
2082 if (mf_check_keys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) {
2083 if (keyType < 2) {
2084 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
2085 } else {
2086 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockNo, MIFARE_AUTH_KEYA + keyType);
2088 return PM3_EOPABORTED;
2091 if (IfPm3Flash()) {
2092 PrintAndLogEx(INFO, "RDV4 with flashmemory supported detected.");
2095 uint64_t t1 = msclock();
2097 e_sector = calloc(SectorsCnt, sizeof(sector_t));
2098 if (e_sector == NULL)
2099 return PM3_EMALLOC;
2101 // add our known key
2102 e_sector[mfSectorNum(blockNo)].foundKey[keyType] = 1;
2103 e_sector[mfSectorNum(blockNo)].Key[keyType] = key64;
2105 //test current key and additional standard keys first
2106 // add parameter key
2107 memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6);
2109 for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) {
2110 num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
2113 PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt);
2114 int res = mf_check_keys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false, false);
2115 if (res == PM3_SUCCESS) {
2116 // all keys found
2117 PrintAndLogEx(SUCCESS, "Fast check found all keys");
2118 goto jumptoend;
2121 uint64_t t2 = msclock() - t1;
2122 PrintAndLogEx(SUCCESS, "Time to check "_YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0);
2123 PrintAndLogEx(SUCCESS, "enter static nested key recovery");
2125 // nested sectors
2126 for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) {
2127 for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) {
2129 for (int i = 0; i < 1; i++) {
2131 if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
2133 int16_t isOK = mf_static_nested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock);
2134 switch (isOK) {
2135 case PM3_ETIMEOUT :
2136 PrintAndLogEx(ERR, "command execution time out");
2137 break;
2138 case PM3_EOPABORTED :
2139 PrintAndLogEx(WARNING, "aborted via keyboard.");
2140 break;
2141 case PM3_ESOFT :
2142 continue;
2143 case PM3_SUCCESS :
2144 e_sector[sectorNo].foundKey[trgKeyType] = 1;
2145 e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
2147 // mfCheckKeys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false);
2148 continue;
2149 default :
2150 PrintAndLogEx(ERR, "unknown error.\n");
2152 free(e_sector);
2153 return PM3_ESOFT;
2158 t1 = msclock() - t1;
2159 PrintAndLogEx(SUCCESS, "time in static nested " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
2162 // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
2163 PrintAndLogEx(INFO, "trying to read key B...");
2164 for (int i = 0; i < SectorsCnt; i++) {
2165 // KEY A but not KEY B
2166 if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
2168 uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
2170 PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
2172 mf_readblock_t payload;
2173 payload.blockno = sectrail;
2174 payload.keytype = MF_KEY_A;
2176 num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
2178 clearCommandBuffer();
2179 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
2181 PacketResponseNG resp;
2182 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) {
2183 continue;
2186 if (resp.status != PM3_SUCCESS) continue;
2188 uint8_t *data = resp.data.asBytes;
2189 key64 = bytes_to_num(data + 10, 6);
2190 if (key64) {
2191 PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6));
2192 e_sector[i].foundKey[1] = true;
2193 e_sector[i].Key[1] = key64;
2198 jumptoend:
2200 PrintAndLogEx(NORMAL, "");
2201 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
2203 //print them
2204 printKeyTable(SectorsCnt, e_sector);
2206 // transfer them to the emulator
2207 if (transferToEml) {
2208 // fast push mode
2209 g_conn.block_after_ACK = true;
2210 for (int i = 0; i < SectorsCnt; i++) {
2211 mf_eml_get_mem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
2213 if (e_sector[i].foundKey[0])
2214 num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
2216 if (e_sector[i].foundKey[1])
2217 num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
2219 if (i == SectorsCnt - 1) {
2220 // Disable fast mode on last packet
2221 g_conn.block_after_ACK = false;
2223 mf_elm_set_mem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
2225 PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
2228 // Create dump file
2229 if (createDumpFile) {
2230 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
2231 if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
2232 PrintAndLogEx(ERR, "Failed to save keys to file");
2233 free(e_sector);
2234 free(fptr);
2235 return PM3_EFILE;
2237 free(fptr);
2239 free(e_sector);
2241 return PM3_SUCCESS;
2244 static int CmdHF14AMfNestedHard(const char *Cmd) {
2246 CLIParserContext *ctx;
2247 CLIParserInit(&ctx, "hf mf hardnested",
2248 "Nested attack for hardened MIFARE Classic cards.\n"
2249 "if card is EV1, command can detect and use known key see example below\n"
2250 " \n"
2251 "`--i<X>` set type of SIMD instructions. Without this flag programs autodetect it.\n"
2252 " or \n"
2253 " hf mf hardnested -r --tk [known target key]\n"
2254 "Add the known target key to check if it is present in the remaining key space\n"
2255 " hf mf hardnested --blk 0 -a -k A0A1A2A3A4A5 --tblk 4 --ta --tk FFFFFFFFFFFF\n"
2257 "hf mf hardnested --tblk 4 --ta --> works for MFC EV1\n"
2258 "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta\n"
2259 "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -w\n"
2260 "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -f nonces.bin -w -s\n"
2261 "hf mf hardnested -r\n"
2262 "hf mf hardnested -r --tk a0a1a2a3a4a5\n"
2263 "hf mf hardnested -t --tk a0a1a2a3a4a5\n"
2264 "hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk FFFFFFFFFFFF\n"
2267 void *argtable[] = {
2268 arg_param_begin,
2269 arg_str0("k", "key", "<hex>", "Key, 12 hex bytes"), // 1
2270 arg_int0(NULL, "blk", "<dec>", "Input block number"), // 2
2271 arg_lit0("a", NULL, "Input key A (def)"), // 3
2272 arg_lit0("b", NULL, "Input key B"),
2273 arg_int0(NULL, "tblk", "<dec>", "Target block number"),
2274 arg_lit0(NULL, "ta", "Target key A"),
2275 arg_lit0(NULL, "tb", "Target key B"),
2276 arg_str0(NULL, "tk", "<hex>", "Target key, 12 hex bytes"), // 8
2277 arg_str0("u", "uid", "<hex>", "R/W `hf-mf-<UID>-nonces.bin` instead of default name"),
2278 arg_str0("f", "file", "<fn>", "R/W <name> instead of default name"),
2279 arg_lit0("r", "read", "Read `hf-mf-<UID>-nonces.bin` if tag present, otherwise `nonces.bin`, and start attack"),
2280 arg_lit0("s", "slow", "Slower acquisition (required by some non standard cards)"),
2281 arg_lit0("t", "tests", "Run tests"),
2282 arg_lit0("w", "wr", "Acquire nonces and UID, and write them to file `hf-mf-<UID>-nonces.bin`"),
2284 arg_lit0(NULL, "in", "None (use CPU regular instruction set)"),
2285 #if defined(COMPILER_HAS_SIMD_X86)
2286 arg_lit0(NULL, "im", "MMX"),
2287 arg_lit0(NULL, "is", "SSE2"),
2288 arg_lit0(NULL, "ia", "AVX"),
2289 arg_lit0(NULL, "i2", "AVX2"),
2290 #endif
2291 #if defined(COMPILER_HAS_SIMD_AVX512)
2292 arg_lit0(NULL, "i5", "AVX512"),
2293 #endif
2294 #if defined(COMPILER_HAS_SIMD_NEON)
2295 arg_lit0(NULL, "ie", "NEON"),
2296 #endif
2297 arg_param_end
2299 CLIExecWithReturn(ctx, Cmd, argtable, false);
2301 int keylen = 0;
2302 uint8_t key[6] = {0};
2303 CLIGetHexWithReturn(ctx, 1, key, &keylen);
2305 uint8_t blockno = arg_get_u32_def(ctx, 2, 0);
2307 uint8_t keytype = MF_KEY_A;
2308 if (arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) {
2309 CLIParserFree(ctx);
2310 PrintAndLogEx(WARNING, "Choose one single input key type");
2311 return PM3_EINVARG;
2312 } else if (arg_get_lit(ctx, 4)) {
2313 keytype = MF_KEY_B;
2316 uint8_t trg_blockno = arg_get_u32_def(ctx, 5, 0);
2318 uint8_t trg_keytype = MF_KEY_A;
2319 if (arg_get_lit(ctx, 6) && arg_get_lit(ctx, 7)) {
2320 CLIParserFree(ctx);
2321 PrintAndLogEx(WARNING, "Choose one single target key type");
2322 return PM3_EINVARG;
2323 } else if (arg_get_lit(ctx, 7)) {
2324 trg_keytype = MF_KEY_B;
2327 int trg_keylen = 0;
2328 uint8_t trg_key[6] = {0};
2329 CLIGetHexWithReturn(ctx, 8, trg_key, &trg_keylen);
2331 int uidlen = 0;
2332 char uid[14] = {0};
2333 CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)uid, sizeof(uid), &uidlen);
2335 int fnlen = 0;
2336 char filename[FILE_PATH_SIZE] = {0};
2337 CLIParamStrToBuf(arg_get_str(ctx, 10), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2339 bool nonce_file_read = arg_get_lit(ctx, 11);
2340 bool slow = arg_get_lit(ctx, 12);
2341 bool tests = arg_get_lit(ctx, 13);
2342 bool nonce_file_write = arg_get_lit(ctx, 14);
2344 bool in = arg_get_lit(ctx, 15);
2345 #if defined(COMPILER_HAS_SIMD_X86)
2346 bool im = arg_get_lit(ctx, 16);
2347 bool is = arg_get_lit(ctx, 17);
2348 bool ia = arg_get_lit(ctx, 18);
2349 bool i2 = arg_get_lit(ctx, 19);
2350 #endif
2351 #if defined(COMPILER_HAS_SIMD_AVX512)
2352 bool i5 = arg_get_lit(ctx, 20);
2353 #endif
2354 #if defined(COMPILER_HAS_SIMD_NEON)
2355 bool ie = arg_get_lit(ctx, 16);
2356 #endif
2357 CLIParserFree(ctx);
2359 // set SIM instructions
2360 SetSIMDInstr(SIMD_AUTO);
2362 #if defined(COMPILER_HAS_SIMD_AVX512)
2363 if (i5)
2364 SetSIMDInstr(SIMD_AVX512);
2365 #endif
2367 #if defined(COMPILER_HAS_SIMD_X86)
2368 if (i2)
2369 SetSIMDInstr(SIMD_AVX2);
2370 if (ia)
2371 SetSIMDInstr(SIMD_AVX);
2372 if (is)
2373 SetSIMDInstr(SIMD_SSE2);
2374 if (im)
2375 SetSIMDInstr(SIMD_MMX);
2376 #endif
2378 #if defined(COMPILER_HAS_SIMD_NEON)
2379 if (ie)
2380 SetSIMDInstr(SIMD_NEON);
2381 #endif
2383 if (in)
2384 SetSIMDInstr(SIMD_NONE);
2387 bool known_target_key = (trg_keylen);
2389 if (nonce_file_read) {
2390 char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
2391 if (fptr == NULL)
2392 strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1);
2393 else
2394 strncpy(filename, fptr, FILE_PATH_SIZE - 1);
2395 free(fptr);
2398 if (nonce_file_write) {
2399 char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
2400 if (fptr == NULL) {
2401 return PM3_EFILE;
2403 strncpy(filename, fptr, FILE_PATH_SIZE - 1);
2404 free(fptr);
2407 if (uidlen) {
2408 snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid);
2411 if (g_session.pm3_present && !tests) {
2412 // detect MFC EV1 Signature
2413 if (detect_mfc_ev1_signature() && keylen == 0) {
2414 PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
2415 blockno = 69;
2416 keytype = MF_KEY_B;
2417 memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
2420 if (known_target_key == false && nonce_file_read == false) {
2421 // check if tag doesn't have static nonce
2422 if (detect_classic_static_nonce() == NONCE_STATIC) {
2423 PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
2424 PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`");
2425 return PM3_EOPABORTED;
2428 uint64_t key64 = 0;
2429 // check if we can authenticate to sector
2430 if (mf_check_keys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) {
2431 if (keytype < 2) {
2432 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockno, keytype ? 'B' : 'A');
2433 } else {
2434 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockno, MIFARE_AUTH_KEYA + keytype);
2436 return PM3_EWRONGANSWER;
2441 PrintAndLogEx(INFO, "Target block no " _YELLOW_("%3d") ", target key type: " _YELLOW_("%c") ", known target key: " _YELLOW_("%02x%02x%02x%02x%02x%02x%s"),
2442 trg_blockno,
2443 (trg_keytype == MF_KEY_B) ? 'B' : 'A',
2444 trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5],
2445 known_target_key ? "" : " (not set)"
2447 PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") ", Slow: " _YELLOW_("%s") ", Tests: " _YELLOW_("%d"),
2448 nonce_file_write ? "write" : nonce_file_read ? "read" : "none",
2449 slow ? "Yes" : "No",
2450 tests);
2452 uint64_t foundkey = 0;
2453 int16_t isOK = mfnestedhard(blockno, keytype, key, trg_blockno, trg_keytype, known_target_key ? trg_key : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename);
2454 switch (isOK) {
2455 case PM3_ETIMEOUT :
2456 PrintAndLogEx(ERR, "Error: No response from Proxmark3\n");
2457 break;
2458 case PM3_EOPABORTED:
2459 PrintAndLogEx(WARNING, "Button pressed. Aborted\n");
2460 break;
2461 case PM3_ESTATIC_NONCE:
2462 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
2463 break;
2464 case PM3_EFAILED: {
2465 PrintAndLogEx(FAILED, "\nFailed to recover a key...");
2466 break;
2468 default :
2469 break;
2472 if ((tests == 0) && IfPm3Iso14443a()) {
2473 DropField();
2475 return isOK;
2478 static int CmdHF14AMfAutoPWN(const char *Cmd) {
2480 CLIParserContext *ctx;
2481 CLIParserInit(&ctx, "hf mf autopwn",
2482 "This command automates the key recovery process on MIFARE Classic cards.\n"
2483 "It uses the fchk, chk, darkside, nested, hardnested and staticnested to recover keys.\n"
2484 "If all keys are found, it try dumping card content both to file and emulator memory.",
2485 "hf mf autopwn\n"
2486 "hf mf autopwn -s 0 -a -k FFFFFFFFFFFF --> target MFC 1K card, Sector 0 with known key A 'FFFFFFFFFFFF'\n"
2487 "hf mf autopwn --1k -f mfc_default_keys --> target MFC 1K card, default dictionary\n"
2488 "hf mf autopwn --1k -s 0 -a -k FFFFFFFFFFFF -f mfc_default_keys --> combo of the two above samples\n"
2489 "hf mf autopwn --1k -s 0 -a -k FFFFFFFFFFFF -k a0a1a2a3a4a5 --> multiple user supplied keys"
2492 void *argtable[] = {
2493 arg_param_begin,
2494 arg_strx0("k", "key", "<hex>", "Known key, 12 hex bytes"),
2495 arg_int0("s", "sector", "<dec>", "Input sector number"),
2496 arg_lit0("a", NULL, "Input key A (def)"),
2497 arg_lit0("b", NULL, "Input key B"),
2498 arg_str0("f", "file", "<fn>", "filename of dictionary"),
2499 arg_lit0(NULL, "slow", "Slower acquisition (required by some non standard cards)"),
2500 arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"),
2501 arg_lit0("v", "verbose", "verbose output"),
2503 arg_lit0(NULL, "ns", "No save to file"),
2505 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
2506 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
2507 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
2508 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
2510 arg_lit0(NULL, "in", "None (use CPU regular instruction set)"),
2511 #if defined(COMPILER_HAS_SIMD_X86)
2512 arg_lit0(NULL, "im", "MMX"),
2513 arg_lit0(NULL, "is", "SSE2"),
2514 arg_lit0(NULL, "ia", "AVX"),
2515 arg_lit0(NULL, "i2", "AVX2"),
2516 #endif
2517 #if defined(COMPILER_HAS_SIMD_AVX512)
2518 arg_lit0(NULL, "i5", "AVX512"),
2519 #endif
2520 #if defined(COMPILER_HAS_SIMD_NEON)
2521 arg_lit0(NULL, "ie", "NEON"),
2522 #endif
2523 arg_param_end
2525 CLIExecWithReturn(ctx, Cmd, argtable, true);
2527 int in_keys_len = 0;
2528 uint8_t in_keys[100 * MIFARE_KEY_SIZE] = {0};
2529 CLIGetHexWithReturn(ctx, 1, in_keys, &in_keys_len);
2531 uint8_t sectorno = arg_get_u32_def(ctx, 2, 0);
2533 uint8_t keytype = MF_KEY_A;
2534 if (arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) {
2535 CLIParserFree(ctx);
2536 PrintAndLogEx(WARNING, "Choose one single input key type");
2537 return PM3_EINVARG;
2538 } else if (arg_get_lit(ctx, 4)) {
2539 keytype = MF_KEY_B;
2542 int fnlen = 0;
2543 char filename[FILE_PATH_SIZE] = {0};
2544 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2546 bool slow = arg_get_lit(ctx, 6);
2547 bool legacy_mfchk = arg_get_lit(ctx, 7);
2548 bool verbose = arg_get_lit(ctx, 8);
2550 bool no_save = arg_get_lit(ctx, 9);
2552 bool m0 = arg_get_lit(ctx, 10);
2553 bool m1 = arg_get_lit(ctx, 11);
2554 bool m2 = arg_get_lit(ctx, 12);
2555 bool m4 = arg_get_lit(ctx, 13);
2557 bool in = arg_get_lit(ctx, 14);
2558 #if defined(COMPILER_HAS_SIMD_X86)
2559 bool im = arg_get_lit(ctx, 15);
2560 bool is = arg_get_lit(ctx, 16);
2561 bool ia = arg_get_lit(ctx, 17);
2562 bool i2 = arg_get_lit(ctx, 18);
2563 #endif
2564 #if defined(COMPILER_HAS_SIMD_AVX512)
2565 bool i5 = arg_get_lit(ctx, 19);
2566 #endif
2567 #if defined(COMPILER_HAS_SIMD_NEON)
2568 bool ie = arg_get_lit(ctx, 15);
2569 #endif
2571 CLIParserFree(ctx);
2573 //validations
2574 if ((m0 + m1 + m2 + m4) > 1) {
2575 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
2576 return PM3_EINVARG;
2577 } else if ((m0 + m1 + m2 + m4) == 0) {
2578 m1 = true;
2581 uint8_t sector_cnt = MIFARE_1K_MAXSECTOR;
2582 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
2584 if (m0) {
2585 sector_cnt = MIFARE_MINI_MAXSECTOR;
2586 block_cnt = MIFARE_MINI_MAXBLOCK;
2587 } else if (m1) {
2588 sector_cnt = MIFARE_1K_MAXSECTOR;
2589 block_cnt = MIFARE_1K_MAXBLOCK;
2590 } else if (m2) {
2591 sector_cnt = MIFARE_2K_MAXSECTOR;
2592 block_cnt = MIFARE_2K_MAXBLOCK;
2593 } else if (m4) {
2594 sector_cnt = MIFARE_4K_MAXSECTOR;
2595 block_cnt = MIFARE_4K_MAXBLOCK;
2596 } else {
2597 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
2598 return PM3_EINVARG;
2602 // set SIM instructions
2603 SetSIMDInstr(SIMD_AUTO);
2605 #if defined(COMPILER_HAS_SIMD_AVX512)
2606 if (i5)
2607 SetSIMDInstr(SIMD_AVX512);
2608 #endif
2610 #if defined(COMPILER_HAS_SIMD_X86)
2611 if (i2)
2612 SetSIMDInstr(SIMD_AVX2);
2613 if (ia)
2614 SetSIMDInstr(SIMD_AVX);
2615 if (is)
2616 SetSIMDInstr(SIMD_SSE2);
2617 if (im)
2618 SetSIMDInstr(SIMD_MMX);
2619 #endif
2621 #if defined(COMPILER_HAS_SIMD_NEON)
2622 if (ie)
2623 SetSIMDInstr(SIMD_NEON);
2624 #endif
2626 if (in) {
2627 SetSIMDInstr(SIMD_NONE);
2630 // Nested and Hardnested parameter
2631 uint64_t key64 = 0;
2632 bool calibrate = true;
2634 // Attack key storage variables
2635 uint8_t *keyBlock = NULL;
2636 uint32_t key_cnt = 0;
2637 uint8_t tmp_key[MIFARE_KEY_SIZE] = {0};
2639 // Nested and Hardnested returned status
2640 uint64_t foundkey = 0;
2641 int current_sector_i = 0, current_key_type_i = 0;
2643 // Dumping and transfere to simulater memory
2644 uint8_t block[MFBLOCK_SIZE] = {0x00};
2645 int bytes;
2647 // Settings
2648 int prng_type = PM3_EUNDEF;
2649 int isOK = 0;
2650 // ------------------------------
2652 uint64_t tagT = GetHF14AMfU_Type();
2653 if (tagT != MFU_TT_UL_ERROR) {
2654 PrintAndLogEx(ERR, "Detected a MIFARE Ultralight/C/NTAG Compatible card.");
2655 PrintAndLogEx(ERR, "This command targets " _YELLOW_("MIFARE Classic"));
2656 return PM3_ESOFT;
2659 // Select card to get UID/UIDLEN/ATQA/SAK information
2660 clearCommandBuffer();
2661 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
2662 PacketResponseNG resp;
2663 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
2664 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
2665 return PM3_ETIMEOUT;
2668 uint64_t select_status = resp.oldarg[0];
2669 if (select_status == 0) {
2670 // iso14443a card select failed
2671 PrintAndLogEx(FAILED, "No tag detected or other tag communication error");
2672 PrintAndLogEx(HINT, "Hint: Try some distance or position of the card");
2673 return PM3_ECARDEXCHANGE;
2676 // store card info
2677 iso14a_card_select_t card;
2678 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
2680 bool known_key = (in_keys_len > 5);
2681 uint8_t key[MIFARE_KEY_SIZE] = {0};
2682 if (known_key) {
2683 memcpy(key, in_keys, sizeof(key));
2686 // Add KDF keys...
2687 uint16_t key1_offset = in_keys_len;
2688 uint64_t key1 = 0;
2690 // iceman: todo, need to add all generated keys
2691 mfc_algo_mizip_one(card.uid, 0, MF_KEY_A, &key1);
2692 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (0 * MIFARE_KEY_SIZE));
2694 mfc_algo_di_one(card.uid, 0, MF_KEY_A, &key1);
2695 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (1 * MIFARE_KEY_SIZE));
2697 mfc_algo_sky_one(card.uid, 15, MF_KEY_A, &key1);
2698 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (2 * MIFARE_KEY_SIZE));
2700 // one key
2701 mfc_algo_saflok_one(card.uid, 0, MF_KEY_A, &key1);
2702 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (3 * MIFARE_KEY_SIZE));
2704 mfc_algo_touch_one(card.uid, 0, MF_KEY_A, &key1);
2705 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (4 * MIFARE_KEY_SIZE));
2707 in_keys_len += (MIFARE_KEY_SIZE * 5);
2709 // detect MFC EV1 Signature
2710 bool is_ev1 = detect_mfc_ev1_signature();
2711 if (is_ev1) {
2712 // hidden sectors on MFC EV1
2713 sector_cnt += 2;
2716 // create/initialize key storage structure
2717 sector_t *e_sector = NULL;
2718 size_t e_sector_cnt = (sector_cnt > sectorno) ? sector_cnt : sectorno + 1;
2719 if (initSectorTable(&e_sector, e_sector_cnt) != PM3_SUCCESS) {
2720 return PM3_EMALLOC;
2723 if (is_ev1) {
2724 PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
2726 // use found key if not supplied
2727 if (known_key == false) {
2728 known_key = true;
2729 sectorno = 17;
2730 keytype = MF_KEY_B;
2731 memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
2735 // read uid to generate a filename for the key file
2736 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
2738 // check if tag doesn't have static nonce
2739 int has_staticnonce = detect_classic_static_nonce();
2741 // card prng type (weak=1 / hard=0 / select/card comm error = negative value)
2742 if (has_staticnonce == NONCE_NORMAL) {
2743 prng_type = detect_classic_prng();
2744 if (prng_type < 0) {
2745 PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error (%i)", prng_type);
2746 free(e_sector);
2747 free(fptr);
2748 return PM3_ESOFT;
2752 // print parameters
2753 if (verbose) {
2754 PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " =======================");
2755 PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sector_cnt);
2756 PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), known_key ? "True" : "False");
2757 PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), sectorno);
2758 PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A');
2759 PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key)));
2761 if (has_staticnonce == NONCE_STATIC)
2762 PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC"));
2763 else if (has_staticnonce == NONCE_NORMAL)
2764 PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD");
2765 else
2766 PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("Could not determine PRNG,") " " _RED_("read failed."));
2768 PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE");
2769 PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False");
2771 PrintAndLogEx(INFO, "========================================================================");
2774 // check the user supplied key
2775 if (known_key == false) {
2776 PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail");
2779 // Start the timer
2780 uint64_t t1 = msclock();
2782 int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen, true);
2783 if (ret != PM3_SUCCESS) {
2784 free(e_sector);
2785 return ret;
2788 int32_t res = PM3_SUCCESS;
2790 // Use the dictionary to find sector keys on the card
2791 if (verbose) PrintAndLogEx(INFO, "======================= " _YELLOW_("START DICTIONARY ATTACK") " =======================");
2793 if (legacy_mfchk) {
2794 PrintAndLogEx(INFO, "." NOLF);
2795 // Check all the sectors
2796 for (int i = 0; i < sector_cnt; i++) {
2797 for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
2798 // Check if the key is known
2799 if (e_sector[i].foundKey[j] == 0) {
2800 for (uint32_t k = 0; k < key_cnt; k++) {
2801 PrintAndLogEx(NORMAL, "." NOLF);
2802 fflush(stdout);
2804 if (mf_check_keys(mfFirstBlockOfSector(i), j, true, 1, (keyBlock + (MIFARE_KEY_SIZE * k)), &key64) == PM3_SUCCESS) {
2805 e_sector[i].Key[j] = bytes_to_num((keyBlock + (MIFARE_KEY_SIZE * k)), MIFARE_KEY_SIZE);
2806 e_sector[i].foundKey[j] = 'D';
2807 break;
2813 PrintAndLogEx(NORMAL, "");
2814 } else {
2816 uint32_t chunksize = key_cnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : key_cnt;
2817 bool firstChunk = true, lastChunk = false;
2819 for (uint8_t strategy = 1; strategy < 3; strategy++) {
2820 PrintAndLogEx(INFO, "running strategy %u", strategy);
2821 // main keychunk loop
2822 for (uint32_t i = 0; i < key_cnt; i += chunksize) {
2824 if (kbd_enter_pressed()) {
2825 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
2826 i = key_cnt;
2827 strategy = 3;
2828 break; // Exit the loop
2830 uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i;
2831 // last chunk?
2832 if (size == key_cnt - i) {
2833 lastChunk = true;
2836 res = mf_check_keys_fast(sector_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, verbose);
2837 if (firstChunk) {
2838 firstChunk = false;
2840 // all keys, aborted
2841 if (res == PM3_SUCCESS) {
2842 i = key_cnt;
2843 strategy = 3;
2844 break; // Exit the loop
2846 } // end chunks of keys
2847 firstChunk = true;
2848 lastChunk = false;
2849 } // end strategy
2852 // Analyse the dictionary attack
2853 uint8_t num_found_keys = 0;
2854 for (int i = 0; i < sector_cnt; i++) {
2855 for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
2856 if (e_sector[i].foundKey[j] != 1) {
2857 continue;
2860 ++num_found_keys;
2862 e_sector[i].foundKey[j] = 'D';
2863 num_to_bytes(e_sector[i].Key[j], MIFARE_KEY_SIZE, tmp_key);
2865 // Store valid credentials for the nested / hardnested attack if none exist
2866 if (known_key == false) {
2867 num_to_bytes(e_sector[i].Key[j], MIFARE_KEY_SIZE, key);
2868 known_key = true;
2869 sectorno = i;
2870 keytype = j;
2871 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)",
2873 (j == MF_KEY_B) ? 'B' : 'A',
2874 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
2876 } else {
2877 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
2879 (j == MF_KEY_B) ? 'B' : 'A',
2880 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
2886 if (num_found_keys == sector_cnt * 2) {
2887 goto all_found;
2890 // Check if at least one sector key was found
2891 if (known_key == false) {
2893 // Check if the darkside attack can be used
2894 if (prng_type && has_staticnonce != NONCE_STATIC) {
2895 if (verbose) {
2896 PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " =======================");
2899 PrintAndLogEx(NORMAL, "");
2901 isOK = mf_dark_side(mfFirstBlockOfSector(sectorno), MIFARE_AUTH_KEYA + keytype, &key64);
2903 if (isOK != PM3_SUCCESS)
2904 goto noValidKeyFound;
2906 PrintAndLogEx(SUCCESS, "Found valid key [ " _GREEN_("%012" PRIx64) " ]\n", key64);
2908 // Store the keys
2909 num_to_bytes(key64, MIFARE_KEY_SIZE, key);
2910 e_sector[sectorno].Key[keytype] = key64;
2911 e_sector[sectorno].foundKey[keytype] = 'S';
2912 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%012" PRIx64) " ] (used for nested / hardnested attack)",
2913 sectorno,
2914 (keytype == MF_KEY_B) ? 'B' : 'A',
2915 key64
2917 } else {
2919 noValidKeyFound:
2920 PrintAndLogEx(FAILED, "No usable key was found!");
2921 free(keyBlock);
2922 free(e_sector);
2923 free(fptr);
2924 return PM3_ESOFT;
2928 free(keyBlock);
2929 // Clear the needed variables
2930 num_to_bytes(0, MIFARE_KEY_SIZE, tmp_key);
2931 bool nested_failed = false;
2933 // Iterate over each sector and key(A/B)
2934 for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) {
2936 for (current_key_type_i = MF_KEY_A; current_key_type_i <= MF_KEY_B; current_key_type_i++) {
2938 // If the key is already known, just skip it
2939 if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
2941 if (has_staticnonce == NONCE_STATIC)
2942 goto tryStaticnested;
2944 // Try the found keys are reused
2945 if (bytes_to_num(tmp_key, MIFARE_KEY_SIZE) != 0) {
2946 // <!> The fast check --> mfCheckKeys_fast(sector_cnt, true, true, 2, 1, tmp_key, e_sector, false, verbose);
2947 // <!> Returns false keys, so we just stick to the slower mfchk.
2948 for (int i = 0; i < sector_cnt; i++) {
2949 for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
2950 // Check if the sector key is already broken
2951 if (e_sector[i].foundKey[j])
2952 continue;
2954 // Check if the key works
2955 if (mf_check_keys(mfFirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) {
2956 e_sector[i].Key[j] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE);
2957 e_sector[i].foundKey[j] = 'R';
2958 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
2960 (j == MF_KEY_B) ? 'B' : 'A',
2961 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
2967 // Clear the last found key
2968 num_to_bytes(0, MIFARE_KEY_SIZE, tmp_key);
2970 if (current_key_type_i == MF_KEY_B) {
2971 if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) {
2972 if (verbose) {
2973 PrintAndLogEx(INFO, "======================= " _YELLOW_("START READ B KEY ATTACK") " =======================");
2974 PrintAndLogEx(INFO, "reading B key of sector %3d with key type %c",
2975 current_sector_i,
2976 (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
2978 uint8_t sectrail = (mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1);
2980 mf_readblock_t payload;
2981 payload.blockno = sectrail;
2982 payload.keytype = MF_KEY_A;
2984 num_to_bytes(e_sector[current_sector_i].Key[0], MIFARE_KEY_SIZE, payload.key); // KEY A
2986 clearCommandBuffer();
2987 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
2989 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) goto skipReadBKey;
2991 if (resp.status != PM3_SUCCESS) goto skipReadBKey;
2993 uint8_t *data = resp.data.asBytes;
2994 key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE);
2995 if (key64) {
2996 e_sector[current_sector_i].foundKey[current_key_type_i] = 'A';
2997 e_sector[current_sector_i].Key[current_key_type_i] = key64;
2998 num_to_bytes(key64, MIFARE_KEY_SIZE, tmp_key);
2999 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
3000 current_sector_i,
3001 (current_key_type_i == MF_KEY_B) ? 'B' : 'A',
3002 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
3004 } else {
3005 if (verbose) {
3006 PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c",
3007 current_sector_i,
3008 (current_key_type_i == MF_KEY_B) ? 'B' : 'A'
3010 PrintAndLogEx(INFO, " -- reading the B key was not possible, maybe due to access rights?");
3018 // Use the nested / hardnested attack
3019 skipReadBKey:
3020 if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
3022 if (has_staticnonce == NONCE_STATIC)
3023 goto tryStaticnested;
3025 if (prng_type && (nested_failed == false)) {
3026 uint8_t retries = 0;
3027 if (verbose) {
3028 PrintAndLogEx(INFO, "======================= " _YELLOW_("START NESTED ATTACK") " =======================");
3029 PrintAndLogEx(INFO, "sector no %3d, target key type %c",
3030 current_sector_i,
3031 (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
3033 tryNested:
3034 isOK = mf_nested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate);
3036 switch (isOK) {
3037 case PM3_ETIMEOUT: {
3038 PrintAndLogEx(ERR, "\nError: No response from Proxmark3.");
3039 free(e_sector);
3040 free(fptr);
3041 return isOK;
3043 case PM3_EOPABORTED: {
3044 PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
3045 free(e_sector);
3046 free(fptr);
3047 return isOK;
3049 case PM3_EFAILED: {
3050 PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is probably not predictable).");
3051 PrintAndLogEx(FAILED, "Nested attack failed --> try hardnested");
3052 goto tryHardnested;
3054 case PM3_ESOFT: {
3055 // key not found
3056 calibrate = false;
3057 // this can happen on some old cards, it's worth trying some more before switching to slower hardnested
3058 if (retries++ < MIFARE_SECTOR_RETRY) {
3059 PrintAndLogEx(FAILED, "Nested attack failed, trying again (%i/%i)", retries, MIFARE_SECTOR_RETRY);
3060 goto tryNested;
3061 } else {
3062 PrintAndLogEx(FAILED, "Nested attack failed, moving to hardnested");
3063 nested_failed = true;
3064 goto tryHardnested;
3066 break;
3068 case PM3_ESTATIC_NONCE: {
3069 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
3071 e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;
3072 e_sector[current_sector_i].foundKey[current_key_type_i] = false;
3073 // Show the results to the user
3074 PrintAndLogEx(NORMAL, "");
3075 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3076 printKeyTable(sector_cnt, e_sector);
3077 PrintAndLogEx(NORMAL, "");
3078 free(e_sector);
3079 free(fptr);
3080 return isOK;
3082 case PM3_SUCCESS: {
3083 calibrate = false;
3084 e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE);
3085 e_sector[current_sector_i].foundKey[current_key_type_i] = 'N';
3086 break;
3088 default: {
3089 PrintAndLogEx(ERR, "unknown Error.\n");
3090 free(e_sector);
3091 free(fptr);
3092 return isOK;
3096 } else {
3097 tryHardnested: // If the nested attack fails then we try the hardnested attack
3098 if (verbose) {
3099 PrintAndLogEx(INFO, "======================= " _YELLOW_("START HARDNESTED ATTACK") " =======================");
3100 PrintAndLogEx(INFO, "sector no %3d, target key type %c, Slow %s",
3101 current_sector_i,
3102 (current_key_type_i == MF_KEY_B) ? 'B' : 'A',
3103 slow ? "Yes" : "No");
3106 foundkey = 0;
3107 isOK = mfnestedhard(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL);
3108 DropField();
3109 if (isOK != PM3_SUCCESS) {
3110 switch (isOK) {
3111 case PM3_ETIMEOUT: {
3112 PrintAndLogEx(ERR, "\nError: No response from Proxmark3");
3113 break;
3115 case PM3_EOPABORTED: {
3116 PrintAndLogEx(NORMAL, "\nButton pressed, user aborted");
3117 break;
3119 case PM3_ESTATIC_NONCE: {
3120 PrintAndLogEx(ERR, "\nError: Static encrypted nonce detected. Aborted\n");
3122 e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;
3123 e_sector[current_sector_i].foundKey[current_key_type_i] = false;
3125 // Show the results to the user
3126 PrintAndLogEx(NORMAL, "");
3127 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3128 printKeyTable(sector_cnt, e_sector);
3129 PrintAndLogEx(NORMAL, "");
3130 break;
3132 case PM3_EFAILED: {
3133 PrintAndLogEx(FAILED, "\nFailed to recover a key...");
3134 continue;
3136 default: {
3137 break;
3140 free(e_sector);
3141 free(fptr);
3142 return PM3_ESOFT;
3145 // Copy the found key to the tmp_key variale (for the following print statement, and the mfCheckKeys above)
3146 num_to_bytes(foundkey, MIFARE_KEY_SIZE, tmp_key);
3147 e_sector[current_sector_i].Key[current_key_type_i] = foundkey;
3148 e_sector[current_sector_i].foundKey[current_key_type_i] = 'H';
3151 if (has_staticnonce == NONCE_STATIC) {
3152 tryStaticnested:
3153 if (verbose) {
3154 PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " =======================");
3155 PrintAndLogEx(INFO, "sector no %3d, target key type %c",
3156 current_sector_i,
3157 (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
3160 isOK = mf_static_nested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key);
3161 DropField();
3162 switch (isOK) {
3163 case PM3_ETIMEOUT: {
3164 PrintAndLogEx(ERR, "\nError: No response from Proxmark3");
3165 free(e_sector);
3166 free(fptr);
3167 return isOK;
3169 case PM3_EOPABORTED: {
3170 PrintAndLogEx(WARNING, "\nButton pressed, user aborted");
3171 free(e_sector);
3172 free(fptr);
3173 return isOK;
3175 case PM3_SUCCESS: {
3176 e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE);
3177 e_sector[current_sector_i].foundKey[current_key_type_i] = 'C';
3178 break;
3180 default: {
3181 break;
3186 // Check if the key was found
3187 if (e_sector[current_sector_i].foundKey[current_key_type_i]) {
3188 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
3189 current_sector_i,
3190 (current_key_type_i == MF_KEY_B) ? 'B' : 'A',
3191 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
3199 all_found:
3201 // Show the results to the user
3202 PrintAndLogEx(NORMAL, "");
3203 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3205 printKeyTable(sector_cnt, e_sector);
3207 if (no_save == false) {
3209 // Dump the keys
3210 PrintAndLogEx(NORMAL, "");
3211 if (createMfcKeyDump(fptr, sector_cnt, e_sector) != PM3_SUCCESS) {
3212 PrintAndLogEx(ERR, "Failed to save keys to file");
3216 // clear emulator mem
3217 clearCommandBuffer();
3218 SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0);
3220 PrintAndLogEx(INFO, "transferring keys to simulator memory " NOLF);
3222 bool transfer_status = true;
3223 for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) {
3224 mf_eml_get_mem(block, current_sector_i, 1);
3225 if (e_sector[current_sector_i].foundKey[0])
3226 num_to_bytes(e_sector[current_sector_i].Key[0], MIFARE_KEY_SIZE, block);
3227 if (e_sector[current_sector_i].foundKey[1])
3228 num_to_bytes(e_sector[current_sector_i].Key[1], MIFARE_KEY_SIZE, block + 10);
3230 transfer_status |= mf_elm_set_mem(block, mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1, 1);
3232 PrintAndLogEx(NORMAL, "( %s )", (transfer_status) ? _GREEN_("ok") : _RED_("fail"));
3234 PrintAndLogEx(INFO, "dumping card content to emulator memory (Cmd Error: 04 can occur)");
3236 // use ecfill trick
3237 FastDumpWithEcFill(sector_cnt);
3239 if (no_save) {
3240 PrintAndLogEx(INFO, "Called with no save option");
3241 PrintAndLogEx(NORMAL, "");
3242 goto out;
3245 bytes = block_cnt * MFBLOCK_SIZE;
3246 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
3247 if (dump == NULL) {
3248 PrintAndLogEx(ERR, "Fail, cannot allocate memory");
3249 free(e_sector);
3250 free(fptr);
3251 return PM3_EMALLOC;
3254 PrintAndLogEx(INFO, "downloading card content from emulator memory");
3255 if (GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false) == false) {
3256 PrintAndLogEx(ERR, "Fail, transfer from device time-out");
3257 free(e_sector);
3258 free(dump);
3259 free(fptr);
3260 return PM3_ETIMEOUT;
3263 free(fptr);
3264 fptr = GenerateFilename("hf-mf-", "-dump");
3265 if (fptr == NULL) {
3266 free(dump);
3267 free(e_sector);
3268 free(fptr);
3269 return PM3_ESOFT;
3272 strncpy(filename, fptr, sizeof(filename) - 1);
3273 free(fptr);
3275 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
3276 free(dump);
3278 out:
3279 // Generate and show statistics
3280 t1 = msclock() - t1;
3281 PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0);
3283 free(e_sector);
3284 return PM3_SUCCESS;
3287 static int CmdHF14AMfChk_fast(const char *Cmd) {
3288 CLIParserContext *ctx;
3289 CLIParserInit(&ctx, "hf mf fchk",
3290 "This is a improved checkkeys method speedwise. It checks MIFARE Classic tags sector keys against a dictionary file with keys",
3291 "hf mf fchk --mini -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n"
3292 "hf mf fchk --1k -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n"
3293 "hf mf fchk --2k -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n"
3294 "hf mf fchk --4k -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k\n"
3295 "hf mf fchk --1k -f mfc_default_keys.dic --> Target 1K using default dictionary file\n"
3296 "hf mf fchk --1k --emu --> Target 1K, write keys to emulator memory\n"
3297 "hf mf fchk --1k --dump --> Target 1K, write keys to file\n"
3298 "hf mf fchk --1k --mem --> Target 1K, use dictionary from flash memory");
3300 void *argtable[] = {
3301 arg_param_begin,
3302 arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
3303 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
3304 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
3305 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
3306 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
3307 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
3308 arg_lit0(NULL, "dump", "Dump found keys to binary file"),
3309 arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
3310 arg_str0("f", "file", "<fn>", "filename of dictionary"),
3311 arg_int0(NULL, "blk", "<dec>", "block number (single block recovery mode)"),
3312 arg_lit0("a", NULL, "single block recovery key A"),
3313 arg_lit0("b", NULL, "single block recovery key B"),
3314 arg_lit0(NULL, "no-default", "Skip check default keys"),
3315 arg_param_end
3317 CLIExecWithReturn(ctx, Cmd, argtable, true);
3319 int keylen = 0;
3320 uint8_t key[100 * MIFARE_KEY_SIZE] = {0};
3321 CLIGetHexWithReturn(ctx, 1, key, &keylen);
3323 bool m0 = arg_get_lit(ctx, 2);
3324 bool m1 = arg_get_lit(ctx, 3);
3325 bool m2 = arg_get_lit(ctx, 4);
3326 bool m4 = arg_get_lit(ctx, 5);
3328 bool transferToEml = arg_get_lit(ctx, 6);
3329 bool createDumpFile = arg_get_lit(ctx, 7);
3330 bool use_flashmemory = arg_get_lit(ctx, 8);
3332 int fnlen = 0;
3333 char filename[FILE_PATH_SIZE] = {0};
3334 CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3336 int blockn = arg_get_int_def(ctx, 10, -1);
3337 uint8_t keytype = MF_KEY_A;
3338 if (arg_get_lit(ctx, 11) && arg_get_lit(ctx, 12)) {
3339 CLIParserFree(ctx);
3340 PrintAndLogEx(WARNING, "Choose one single input key type");
3341 return PM3_EINVARG;
3342 } else if (arg_get_lit(ctx, 12)) {
3343 keytype = MF_KEY_B;
3345 bool load_default = ! arg_get_lit(ctx, 13);
3347 CLIParserFree(ctx);
3349 //validations
3351 if ((m0 + m1 + m2 + m4) > 1) {
3352 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
3353 return PM3_EINVARG;
3354 } else if ((m0 + m1 + m2 + m4) == 0) {
3355 m1 = true;
3358 uint8_t sectorsCnt = MIFARE_1K_MAXSECTOR;
3359 if (m0) {
3360 sectorsCnt = MIFARE_MINI_MAXSECTOR;
3361 } else if (m1) {
3362 sectorsCnt = MIFARE_1K_MAXSECTOR;
3363 } else if (m2) {
3364 sectorsCnt = MIFARE_2K_MAXSECTOR;
3365 } else if (m4) {
3366 sectorsCnt = MIFARE_4K_MAXSECTOR;
3367 } else {
3368 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
3369 return PM3_EINVARG;
3372 uint8_t *keyBlock = NULL;
3373 uint32_t keycnt = 0;
3374 int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default);
3375 if (ret != PM3_SUCCESS) {
3376 return ret;
3379 // create/initialize key storage structure
3380 sector_t *e_sector = NULL;
3381 if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
3382 free(keyBlock);
3383 return PM3_EMALLOC;
3386 uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : keycnt;
3387 bool firstChunk = true, lastChunk = false;
3389 int i = 0;
3391 // time
3392 uint64_t t1 = msclock();
3394 uint16_t singleSectorParams = 0;
3395 if (blockn != -1) {
3396 singleSectorParams = (blockn & 0xFF) | keytype << 8 | 1 << 15;
3398 if (use_flashmemory) {
3399 PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");
3400 mf_check_keys_fast_ex(sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory, false, false, singleSectorParams);
3401 } else {
3403 // strategies. 1= deep first on sector 0 AB, 2= width first on all sectors
3404 for (uint8_t strategy = 1; strategy < 3; strategy++) {
3405 PrintAndLogEx(INFO, "Running strategy %u", strategy);
3407 // main keychunk loop
3408 for (i = 0; i < keycnt; i += chunksize) {
3410 if (kbd_enter_pressed()) {
3411 PrintAndLogEx(NORMAL, "");
3412 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
3413 // field is still ON if not on last chunk
3414 clearCommandBuffer();
3415 SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0);
3416 // TODO: we're missing these cleanups on arm side, not sure if it's important...
3417 // set_tracing(false);
3418 // BigBuf_free();
3419 // BigBuf_Clear_ext(false);
3420 goto out;
3422 PrintAndLogEx(INPLACE, "Testing %5i/%5i %02.1f%%", i, keycnt, (float)i * 100 / keycnt);
3423 uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i;
3425 // last chunk?
3426 if (size == keycnt - i)
3427 lastChunk = true;
3429 int res = mf_check_keys_fast_ex(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, false, true, singleSectorParams);
3430 if (firstChunk)
3431 firstChunk = false;
3433 // all keys, aborted
3434 if (res == PM3_SUCCESS || res == 2) {
3435 PrintAndLogEx(NORMAL, "");
3436 goto out;
3438 } // end chunks of keys
3439 PrintAndLogEx(INPLACE, "Testing %5i/%5i 100.00%%", keycnt, keycnt);
3440 PrintAndLogEx(NORMAL, "");
3441 firstChunk = true;
3442 lastChunk = false;
3443 if (blockn != -1) break;
3444 } // end strategy
3446 out:
3447 t1 = msclock() - t1;
3448 PrintAndLogEx(INFO, "Time in checkkeys (fast) " _YELLOW_("%.1fs") "\n", (float)(t1 / 1000.0));
3450 if (blockn != -1) {
3451 goto out2;
3454 // check..
3455 uint8_t found_keys = 0;
3456 for (i = 0; i < sectorsCnt; ++i) {
3458 if (e_sector[i].foundKey[0])
3459 found_keys++;
3461 if (e_sector[i].foundKey[1])
3462 found_keys++;
3465 if (found_keys == 0) {
3466 PrintAndLogEx(WARNING, "No keys found");
3467 } else {
3469 PrintAndLogEx(NORMAL, "");
3470 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3472 printKeyTable(sectorsCnt, e_sector);
3474 if (use_flashmemory && found_keys == (sectorsCnt << 1)) {
3475 PrintAndLogEx(SUCCESS, "Card dumped as well. run " _YELLOW_("`%s %c`"),
3476 "hf mf esave",
3477 GetFormatFromSector(sectorsCnt)
3481 if (transferToEml) {
3482 // fast push mode
3483 g_conn.block_after_ACK = true;
3484 uint8_t block[MFBLOCK_SIZE] = {0x00};
3485 for (i = 0; i < sectorsCnt; ++i) {
3486 uint8_t b = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
3487 mf_eml_get_mem(block, b, 1);
3489 if (e_sector[i].foundKey[0])
3490 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block);
3492 if (e_sector[i].foundKey[1])
3493 num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10);
3495 if (i == sectorsCnt - 1) {
3496 // Disable fast mode on last packet
3497 g_conn.block_after_ACK = false;
3499 mf_elm_set_mem(block, b, 1);
3501 PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
3503 if (found_keys == (sectorsCnt << 1)) {
3504 FastDumpWithEcFill(sectorsCnt);
3508 if (createDumpFile) {
3510 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
3511 if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) {
3512 PrintAndLogEx(ERR, "Failed to save keys to file");
3514 free(fptr);
3517 out2:
3518 free(keyBlock);
3519 free(e_sector);
3520 PrintAndLogEx(NORMAL, "");
3521 return PM3_SUCCESS;
3524 static int CmdHF14AMfSmartBrute(const char *Cmd) {
3525 CLIParserContext *ctx;
3526 CLIParserInit(&ctx, "hf mf brute",
3527 "This is a smart bruteforce, exploiting common patterns, bugs and bad designs in key generators.",
3528 "hf mf brute --mini --> Key recovery against MIFARE Mini\n"
3529 "hf mf brute --1k --> Key recovery against MIFARE Classic 1k\n"
3530 "hf mf brute --2k --> Key recovery against MIFARE 2k\n"
3531 "hf mf brute --4k --> Key recovery against MIFARE 4k\n"
3532 "hf mf brute --1k --emu --> Target 1K, write keys to emulator memory\n"
3533 "hf mf brute --1k --dump --> Target 1K, write keys to file\n");
3535 void *argtable[] = {
3536 arg_param_begin,
3537 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
3538 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
3539 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
3540 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
3541 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
3542 arg_lit0(NULL, "dump", "Dump found keys to binary file"),
3543 arg_param_end
3545 CLIExecWithReturn(ctx, Cmd, argtable, true);
3548 bool m0 = arg_get_lit(ctx, 2);
3549 bool m1 = arg_get_lit(ctx, 3);
3550 bool m2 = arg_get_lit(ctx, 4);
3551 bool m4 = arg_get_lit(ctx, 5);
3553 bool transferToEml = arg_get_lit(ctx, 6);
3554 bool createDumpFile = arg_get_lit(ctx, 7);
3556 CLIParserFree(ctx);
3558 //validations
3560 if ((m0 + m1 + m2 + m4) > 1) {
3561 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
3562 return PM3_EINVARG;
3563 } else if ((m0 + m1 + m2 + m4) == 0) {
3564 m1 = true;
3567 uint8_t sectorsCnt = MIFARE_1K_MAXSECTOR;
3568 if (m0) {
3569 sectorsCnt = MIFARE_MINI_MAXSECTOR;
3570 } else if (m1) {
3571 sectorsCnt = MIFARE_1K_MAXSECTOR;
3572 } else if (m2) {
3573 sectorsCnt = MIFARE_2K_MAXSECTOR;
3574 } else if (m4) {
3575 sectorsCnt = MIFARE_4K_MAXSECTOR;
3576 } else {
3577 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
3578 return PM3_EINVARG;
3581 uint32_t chunksize = 100 > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : 100;
3582 uint8_t *keyBlock = calloc(MIFARE_KEY_SIZE, chunksize);
3584 if (keyBlock == NULL)
3585 return PM3_EMALLOC;
3587 // create/initialize key storage structure
3588 sector_t *e_sector = NULL;
3589 if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
3590 free(keyBlock);
3591 return PM3_EMALLOC;
3594 // initialize bruteforce engine
3595 generator_context_t bctx;
3596 bf_generator_init(&bctx, BF_MODE_SMART, BF_KEY_SIZE_48);
3598 int i = 0, ret;
3599 int smart_mode_stage = -1;
3600 uint64_t generator_key;
3602 // time
3603 uint64_t t0 = msclock();
3604 uint64_t t1 = msclock();
3605 uint64_t keys_checked = 0;
3606 uint64_t total_keys_checked = 0;
3608 uint32_t keycnt = 0;
3609 bool firstChunk = true, lastChunk = false;
3611 while (!lastChunk) {
3612 keycnt = 0;
3614 // generate block of keys from generator
3615 memset(keyBlock, 0, MIFARE_KEY_SIZE * chunksize);
3617 for (i = 0; i < chunksize; i++) {
3619 ret = bf_generate(&bctx);
3621 if (ret == BF_GENERATOR_ERROR) {
3622 PrintAndLogEx(ERR, "Internal bruteforce generator error");
3623 free(keyBlock);
3624 free(e_sector);
3625 return PM3_EFAILED;
3627 } else if (ret == BF_GENERATOR_END) {
3629 lastChunk = true;
3630 break;
3632 } else if (ret == BF_GENERATOR_NEXT) {
3634 generator_key = bf_get_key48(&bctx);
3635 num_to_bytes(generator_key, MIFARE_KEY_SIZE, keyBlock + (i * MIFARE_KEY_SIZE));
3636 keycnt++;
3638 if (smart_mode_stage != bctx.smart_mode_stage) {
3640 smart_mode_stage = bctx.smart_mode_stage;
3641 PrintAndLogEx(INFO, "Running bruteforce stage %d", smart_mode_stage);
3643 if (keys_checked) {
3645 PrintAndLogEx(INFO, "Current cracking speed (keys/s): %lu",
3646 keys_checked / ((msclock() - t1) / 1000)
3649 t1 = msclock();
3650 keys_checked = 0;
3656 int strategy = 2; // width first on all sectors
3657 ret = mf_check_keys_fast(sectorsCnt, firstChunk, lastChunk, strategy, keycnt, keyBlock, e_sector, false, false);
3659 keys_checked += keycnt;
3660 total_keys_checked += keycnt;
3662 if (firstChunk)
3663 firstChunk = false;
3665 if (ret == PM3_SUCCESS || ret == 2)
3666 goto out;
3670 out:
3671 PrintAndLogEx(INFO, "Time in brute mode: " _YELLOW_("%.1fs") "\n", (float)((msclock() - t0) / 1000.0));
3672 PrintAndLogEx(INFO, "Total keys checked: " _YELLOW_("%lu") "\n", total_keys_checked);
3673 // check..
3674 uint8_t found_keys = 0;
3675 for (i = 0; i < sectorsCnt; ++i) {
3677 if (e_sector[i].foundKey[0]) {
3678 found_keys++;
3681 if (e_sector[i].foundKey[1]) {
3682 found_keys++;
3686 if (found_keys == 0) {
3687 PrintAndLogEx(WARNING, "No keys found");
3688 } else {
3690 PrintAndLogEx(NORMAL, "");
3691 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3693 printKeyTable(sectorsCnt, e_sector);
3695 if (transferToEml) {
3696 // fast push mode
3697 g_conn.block_after_ACK = true;
3698 uint8_t block[MFBLOCK_SIZE] = {0x00};
3699 for (i = 0; i < sectorsCnt; ++i) {
3700 uint8_t b = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
3701 mf_eml_get_mem(block, b, 1);
3703 if (e_sector[i].foundKey[0])
3704 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block);
3706 if (e_sector[i].foundKey[1])
3707 num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10);
3709 if (i == sectorsCnt - 1) {
3710 // Disable fast mode on last packet
3711 g_conn.block_after_ACK = false;
3713 mf_elm_set_mem(block, b, 1);
3715 PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
3717 if (found_keys == (sectorsCnt << 1)) {
3718 FastDumpWithEcFill(sectorsCnt);
3722 if (createDumpFile) {
3724 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
3725 if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) {
3726 PrintAndLogEx(ERR, "Failed to save keys to file");
3728 free(fptr);
3733 free(keyBlock);
3734 free(e_sector);
3735 PrintAndLogEx(NORMAL, "");
3736 return PM3_SUCCESS;
3739 static int CmdHF14AMfChk(const char *Cmd) {
3740 CLIParserContext *ctx;
3741 CLIParserInit(&ctx, "hf mf chk",
3742 "Check keys on MIFARE Classic card",
3743 "hf mf chk --mini -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE Mini\n"
3744 "hf mf chk --1k -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE Classic 1k\n"
3745 "hf mf chk --2k -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE 2k\n"
3746 "hf mf chk --4k -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE 4k\n"
3747 "hf mf chk --1k --emu --> Check all sectors, all keys, 1K, and write to emulator memory\n"
3748 "hf mf chk --1k --dump --> Check all sectors, all keys, 1K, and write to file\n"
3749 "hf mf chk -a --tblk 0 -f mfc_default_keys.dic --> Check dictionary against block 0, key A");
3751 void *argtable[] = {
3752 arg_param_begin,
3753 arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
3754 arg_int0(NULL, "tblk", "<dec>", "Target block number"),
3755 arg_lit0("a", NULL, "Target Key A"),
3756 arg_lit0("b", NULL, "Target Key B"),
3757 arg_lit0("*", "all", "Target both key A & B (default)"),
3758 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
3759 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
3760 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
3761 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
3762 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
3763 arg_lit0(NULL, "dump", "Dump found keys to binary file"),
3764 arg_str0("f", "file", "<fn>", "Filename of dictionary"),
3765 arg_lit0(NULL, "no-default", "Skip check default keys"),
3766 arg_param_end
3768 CLIExecWithReturn(ctx, Cmd, argtable, true);
3770 int keylen = 0;
3771 uint8_t key[100 * MIFARE_KEY_SIZE] = {0};
3772 CLIGetHexWithReturn(ctx, 1, key, &keylen);
3774 int blockNo = arg_get_int_def(ctx, 2, -1);
3776 uint8_t keyType = 2;
3778 if ((arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) || arg_get_lit(ctx, 5)) {
3779 keyType = 2;
3780 } else if (arg_get_lit(ctx, 3)) {
3781 keyType = MF_KEY_A;
3782 } else if (arg_get_lit(ctx, 4)) {
3783 keyType = MF_KEY_B;
3786 bool m0 = arg_get_lit(ctx, 6);
3787 bool m1 = arg_get_lit(ctx, 7);
3788 bool m2 = arg_get_lit(ctx, 8);
3789 bool m4 = arg_get_lit(ctx, 9);
3791 bool transferToEml = arg_get_lit(ctx, 10);
3792 bool createDumpFile = arg_get_lit(ctx, 11);
3794 int fnlen = 0;
3795 char filename[FILE_PATH_SIZE] = {0};
3796 CLIParamStrToBuf(arg_get_str(ctx, 12), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3797 bool load_default = ! arg_get_lit(ctx, 13);
3799 CLIParserFree(ctx);
3801 bool singleSector = (blockNo > -1);
3802 if (singleSector == false) {
3803 // start from first trailer block
3804 blockNo = 3;
3807 //validations
3808 if ((m0 + m1 + m2 + m4) > 1) {
3809 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
3810 return PM3_EINVARG;
3813 size_t sectors_cnt = 1;
3814 if (m0) {
3815 sectors_cnt = MIFARE_MINI_MAXSECTOR;
3816 } else if (m1) {
3817 sectors_cnt = MIFARE_1K_MAXSECTOR;
3818 } else if (m2) {
3819 sectors_cnt = MIFARE_2K_MAXSECTOR;
3820 } else if (m4) {
3821 sectors_cnt = MIFARE_4K_MAXSECTOR;
3824 if (singleSector) {
3826 // find a MIFARE type that can accommodate the provided block number
3827 size_t min_sectors_cnt = 0;
3828 uint8_t s = mfSectorNum(blockNo);
3830 if (s < MIFARE_MINI_MAXSECTOR) {
3831 min_sectors_cnt = MIFARE_MINI_MAXSECTOR;
3832 } else if (s < MIFARE_1K_MAXSECTOR) {
3833 min_sectors_cnt = MIFARE_1K_MAXSECTOR;
3834 } else if (s < MIFARE_2K_MAXSECTOR) {
3835 min_sectors_cnt = MIFARE_2K_MAXSECTOR;
3836 } else if (s < MIFARE_4K_MAXSECTOR) {
3837 min_sectors_cnt = MIFARE_4K_MAXSECTOR;
3838 } else {
3839 PrintAndLogEx(WARNING, "Provided block out of possible MIFARE Type memory map");
3840 return PM3_EINVARG;
3843 if (sectors_cnt == 1) {
3844 sectors_cnt = min_sectors_cnt;
3845 } else if (sectors_cnt < min_sectors_cnt) {
3846 PrintAndLogEx(WARNING, "Provided block out of provided MIFARE Type memory map");
3847 return PM3_EINVARG;
3851 if (sectors_cnt == 1) {
3852 sectors_cnt = MIFARE_1K_MAXSECTOR;
3855 uint8_t *keyBlock = NULL;
3856 uint32_t keycnt = 0;
3857 int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default);
3858 if (ret != PM3_SUCCESS) {
3859 return ret;
3862 uint64_t key64 = 0;
3864 // create/initialize key storage structure
3865 sector_t *e_sector = NULL;
3866 if (initSectorTable(&e_sector, sectors_cnt) != PM3_SUCCESS) {
3867 free(keyBlock);
3868 return PM3_EMALLOC;
3871 uint8_t trgKeyType = MF_KEY_A;
3872 uint16_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
3874 PrintAndLogEx(INFO, "Start check for keys...");
3875 PrintAndLogEx(INFO, "." NOLF);
3877 // fast push mode
3878 g_conn.block_after_ACK = true;
3880 // clear trace log by first check keys call only
3881 bool clearLog = true;
3883 // time
3884 uint64_t t1 = msclock();
3886 // check keys.
3887 for (trgKeyType = (keyType == 2) ? 0 : keyType; trgKeyType < 2; (keyType == 2) ? (++trgKeyType) : (trgKeyType = 2)) {
3889 // loop sectors but block is used as to keep track of from which blocks to test
3890 int b = blockNo;
3891 for (int i = mfSectorNum(b); i < sectors_cnt; ++i) {
3893 // skip already found keys.
3894 if (e_sector[i].foundKey[trgKeyType]) continue;
3896 for (uint32_t c = 0; c < keycnt; c += max_keys) {
3898 PrintAndLogEx(NORMAL, "." NOLF);
3899 fflush(stdout);
3901 if (kbd_enter_pressed()) {
3902 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
3903 goto out;
3906 uint32_t size = keycnt - c > max_keys ? max_keys : keycnt - c;
3908 if (mf_check_keys(b, trgKeyType, clearLog, size, &keyBlock[MIFARE_KEY_SIZE * c], &key64) == PM3_SUCCESS) {
3909 e_sector[i].Key[trgKeyType] = key64;
3910 e_sector[i].foundKey[trgKeyType] = true;
3911 clearLog = false;
3912 break;
3914 clearLog = false;
3916 if (singleSector)
3917 break;
3919 b < 127 ? (b += 4) : (b += 16);
3922 t1 = msclock() - t1;
3923 PrintAndLogEx(INFO, "\ntime in checkkeys " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
3925 // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
3926 if (keyType != MF_KEY_B) {
3927 PrintAndLogEx(INFO, "testing to read key B...");
3929 // loop sectors but block is used as to keep track of from which blocks to test
3930 int b = blockNo;
3931 for (int i = mfSectorNum(b); i < sectors_cnt; i++) {
3933 // KEY A but not KEY B
3934 if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
3936 uint8_t sectrail = mfSectorTrailerOfSector(i);
3937 PrintAndLogEx(INFO, "Sector: %u, First block: %u, Last block: %u, Num of blocks: %u", i, mfFirstBlockOfSector(i), sectrail, mfNumBlocksPerSector(i));
3938 PrintAndLogEx(INFO, "Reading sector trailer");
3940 mf_readblock_t payload;
3941 payload.blockno = sectrail;
3942 payload.keytype = MF_KEY_A;
3944 // Use key A
3945 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, payload.key);
3947 clearCommandBuffer();
3948 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
3950 PacketResponseNG resp;
3951 if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
3953 if (resp.status != PM3_SUCCESS) continue;
3955 uint8_t *data = resp.data.asBytes;
3956 key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE);
3957 if (key64) {
3958 PrintAndLogEx(NORMAL, "Data:%s", sprint_hex(data + 10, MIFARE_KEY_SIZE));
3959 e_sector[i].foundKey[1] = 1;
3960 e_sector[i].Key[1] = key64;
3963 if (singleSector)
3964 break;
3965 b < 127 ? (b += 4) : (b += 16);
3969 out:
3970 PrintAndLogEx(NORMAL, "");
3971 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3973 //print keys
3974 // if (singleSector)
3975 // printKeyTableEx(1, e_sector, mfSectorNum(blockNo));
3976 // else
3977 printKeyTable(sectors_cnt, e_sector);
3979 if (transferToEml) {
3980 // fast push mode
3981 g_conn.block_after_ACK = true;
3982 uint8_t block[MFBLOCK_SIZE] = {0x00};
3983 for (int i = 0; i < sectors_cnt; ++i) {
3984 uint8_t blockno = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
3985 mf_eml_get_mem(block, blockno, 1);
3987 if (e_sector[i].foundKey[0])
3988 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block);
3990 if (e_sector[i].foundKey[1])
3991 num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10);
3993 if (i == sectors_cnt - 1) {
3994 // Disable fast mode on last packet
3995 g_conn.block_after_ACK = false;
3997 mf_elm_set_mem(block, blockno, 1);
3999 PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
4002 if (createDumpFile) {
4003 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
4004 if (createMfcKeyDump(fptr, sectors_cnt, e_sector) != PM3_SUCCESS) {
4005 PrintAndLogEx(ERR, "Failed to save keys to file");
4007 free(fptr);
4010 free(keyBlock);
4011 free(e_sector);
4013 // Disable fast mode and send a dummy command to make it effective
4014 g_conn.block_after_ACK = false;
4015 SendCommandNG(CMD_PING, NULL, 0);
4016 if (!WaitForResponseTimeout(CMD_PING, NULL, 1000)) {
4017 PrintAndLogEx(WARNING, "command execution time out");
4018 return PM3_ETIMEOUT;
4021 PrintAndLogEx(NORMAL, "");
4022 return PM3_SUCCESS;
4025 void showSectorTable(sector_t *k_sector, size_t k_sectors_cnt) {
4026 if (k_sector != NULL) {
4027 printKeyTable(k_sectors_cnt, k_sector);
4028 free(k_sector);
4032 void readerAttack(sector_t *k_sector, size_t k_sectors_cnt, nonces_t data, bool setEmulatorMem, bool verbose) {
4034 // init if needed
4035 if (k_sector == NULL) {
4036 if (initSectorTable(&k_sector, k_sectors_cnt) != PM3_SUCCESS) {
4037 return;
4041 uint64_t key = 0;
4042 bool found = false;
4043 if ((nonce_state)data.state == SECOND) {
4044 found = mfkey32_moebius(&data, &key);
4045 } else if ((nonce_state)data.state == NESTED) {
4046 found = mfkey32_nested(&data, &key);
4048 if (found) {
4049 uint8_t sector = data.sector;
4050 uint8_t keytype = data.keytype;
4052 PrintAndLogEx(INFO, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]"
4053 , (keytype == MF_KEY_B) ? "B" : "A"
4054 , sector
4055 , key
4058 k_sector[sector].Key[keytype] = key;
4059 k_sector[sector].foundKey[keytype] = true;
4061 //set emulator memory for keys
4062 if (setEmulatorMem) {
4063 uint8_t memBlock[16];
4064 mf_eml_get_mem(memBlock, (sector * 4) + 3, 1);
4065 if ((memBlock[6] == 0) && (memBlock[7] == 0) && (memBlock[8] == 0)) {
4066 // ACL not yet set?
4067 memBlock[6] = 0xFF;
4068 memBlock[7] = 0x07;
4069 memBlock[8] = 0x80;
4071 num_to_bytes(k_sector[sector].Key[keytype], 6, memBlock + ((keytype == MF_KEY_B) ? 10 : 0));
4072 //iceman, guessing this will not work so well for 4K tags.
4073 PrintAndLogEx(INFO, "Setting Emulator Memory Block %02d: [%s]"
4074 , (sector * 4) + 3
4075 , sprint_hex(memBlock, sizeof(memBlock))
4077 mf_elm_set_mem(memBlock, (sector * 4) + 3, 1);
4081 free(k_sector);
4084 static int CmdHF14AMfSim(const char *Cmd) {
4085 CLIParserContext *ctx;
4086 CLIParserInit(&ctx, "hf mf sim",
4087 "Simulate MIFARE Classic family type based upon\n"
4088 "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
4089 "from emulator memory. See `hf mf eload` first.\n"
4090 "The UID from emulator memory will be used if not specified.",
4091 "hf mf sim --mini --> MIFARE Mini\n"
4092 "hf mf sim --1k --> MIFARE Classic 1k (default)\n"
4093 "hf mf sim --1k -u 0a0a0a0a --> MIFARE Classic 1k with 4b UID\n"
4094 "hf mf sim --1k -u 11223344556677 --> MIFARE Classic 1k with 7b UID\n"
4095 "hf mf sim --1k -u 11223344 -i -x --> Perform reader attack in interactive mode\n"
4096 "hf mf sim --2k --> MIFARE 2k\n"
4097 "hf mf sim --4k --> MIFARE 4k"
4098 "hf mf sim --1k -x -e --> Keep simulation running and populate with found reader keys\n"
4101 void *argtable[] = {
4102 arg_param_begin,
4103 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
4104 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4105 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
4106 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4107 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4108 arg_str0(NULL, "atqa", "<hex>", "Provide explicit ATQA (2 bytes)"),
4109 arg_str0(NULL, "sak", "<hex>", "Provide explicit SAK (1 bytes)"),
4110 arg_int0("n", "num", "<dec> ", "Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
4111 arg_lit0("i", "interactive", "Console will not be returned until simulation finishes or is aborted"),
4112 arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader."),
4113 arg_lit0("y", NULL, "Performs the nested 'reader attack'. This requires preloading nt & nt_enc in emulator memory. Implies -x."),
4114 arg_lit0("e", "emukeys", "Fill simulator keys from found keys. Requires -x or -y. Implies -i. Simulation will restart automatically."),
4115 // If access bits show that key B is Readable, any subsequent memory access should be refused.
4116 arg_lit0(NULL, "allowkeyb", "Allow key B even if readable"),
4117 arg_lit0("v", "verbose", "Verbose output"),
4118 arg_lit0(NULL, "cve", "Trigger CVE 2021_0430"),
4119 arg_param_end
4121 CLIExecWithReturn(ctx, Cmd, argtable, true);
4123 uint16_t flags = 0;
4125 int uidlen = 0;
4126 uint8_t uid[10] = {0};
4127 CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
4129 if (uidlen > 0) {
4130 FLAG_SET_UID_IN_DATA(flags, uidlen);
4131 if (IS_FLAG_UID_IN_EMUL(flags)) {
4132 PrintAndLogEx(WARNING, "Invalid parameter for UID");
4133 CLIParserFree(ctx);
4134 return PM3_EINVARG;
4138 bool m0 = arg_get_lit(ctx, 2);
4139 bool m1 = arg_get_lit(ctx, 3);
4140 bool m2 = arg_get_lit(ctx, 4);
4141 bool m4 = arg_get_lit(ctx, 5);
4143 int atqalen = 0;
4144 uint8_t atqa[2] = {0};
4145 CLIGetHexWithReturn(ctx, 6, atqa, &atqalen);
4147 int saklen = 0;
4148 uint8_t sak[1] = {0};
4149 CLIGetHexWithReturn(ctx, 7, sak, &saklen);
4151 uint8_t exitAfterNReads = arg_get_u32_def(ctx, 8, 0);
4153 if (arg_get_lit(ctx, 9)) {
4154 flags |= FLAG_INTERACTIVE;
4157 if (arg_get_lit(ctx, 10)) {
4158 flags |= FLAG_NR_AR_ATTACK;
4161 if (arg_get_lit(ctx, 11)) {
4162 flags |= FLAG_NESTED_AUTH_ATTACK;
4165 bool setEmulatorMem = arg_get_lit(ctx, 12);
4167 if (arg_get_lit(ctx, 13)) {
4168 flags |= FLAG_MF_USE_READ_KEYB;
4171 bool verbose = arg_get_lit(ctx, 14);
4173 if (arg_get_lit(ctx, 15)) {
4174 flags |= FLAG_CVE21_0430;
4176 CLIParserFree(ctx);
4178 //Validations
4179 if (atqalen > 0) {
4180 if (atqalen != 2) {
4181 PrintAndLogEx(WARNING, "Wrong ATQA length");
4182 return PM3_EINVARG;
4184 flags |= FLAG_ATQA_IN_DATA;
4187 if (saklen > 0) {
4188 if (saklen != 1) {
4189 PrintAndLogEx(WARNING, "Wrong SAK length");
4190 return PM3_EINVARG;
4192 flags |= FLAG_SAK_IN_DATA;
4195 size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
4196 char csize[13] = { 0 };
4198 if ((m0 + m1 + m2 + m4) > 1) {
4199 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4200 return PM3_EINVARG;
4203 if (m0) {
4204 FLAG_SET_MF_SIZE(flags, MIFARE_MINI_MAX_BYTES);
4205 snprintf(csize, sizeof(csize), "MINI");
4206 k_sectors_cnt = MIFARE_MINI_MAXSECTOR;
4207 } else if (m1) {
4208 FLAG_SET_MF_SIZE(flags, MIFARE_1K_MAX_BYTES);
4209 snprintf(csize, sizeof(csize), "1K");
4210 k_sectors_cnt = MIFARE_1K_MAXSECTOR;
4211 } else if (m2) {
4212 FLAG_SET_MF_SIZE(flags, MIFARE_2K_MAX_BYTES);
4213 snprintf(csize, sizeof(csize), "2K with RATS");
4214 k_sectors_cnt = MIFARE_2K_MAXSECTOR;
4215 } else if (m4) {
4216 FLAG_SET_MF_SIZE(flags, MIFARE_4K_MAX_BYTES);
4217 snprintf(csize, sizeof(csize), "4K");
4218 k_sectors_cnt = MIFARE_4K_MAXSECTOR;
4219 } else {
4220 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
4221 return PM3_EINVARG;
4224 if ((flags & FLAG_NESTED_AUTH_ATTACK) == FLAG_NESTED_AUTH_ATTACK) {
4225 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
4226 PrintAndLogEx(INFO, "Note: option -y implies -x");
4227 flags |= FLAG_NR_AR_ATTACK;
4231 if (setEmulatorMem) {
4232 if ((flags & FLAG_INTERACTIVE) != FLAG_INTERACTIVE) {
4233 PrintAndLogEx(INFO, "Note: option -e implies -i");
4234 flags |= FLAG_INTERACTIVE;
4236 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
4237 PrintAndLogEx(WARNING, "Option -e requires -x or -y");
4238 return PM3_EINVARG;
4242 PrintAndLogEx(INFO, _YELLOW_("MIFARE %s") " | %i bytes UID " _YELLOW_("%s") ""
4243 , csize
4244 , uidlen
4245 , (uidlen == 0) ? "n/a" : sprint_hex(uid, uidlen)
4248 PrintAndLogEx(INFO, "Options [ numreads: %d, flags: 0x%04x ]"
4249 , exitAfterNReads
4250 , flags);
4252 struct {
4253 uint16_t flags;
4254 uint8_t exitAfter;
4255 uint8_t uid[10];
4256 uint16_t atqa;
4257 uint8_t sak;
4258 } PACKED payload;
4260 payload.flags = flags;
4261 payload.exitAfter = exitAfterNReads;
4262 memcpy(payload.uid, uid, uidlen);
4263 payload.atqa = (atqa[1] << 8) | atqa[0];
4264 payload.sak = sak[0];
4266 clearCommandBuffer();
4268 if (flags & FLAG_INTERACTIVE) {
4269 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or a key to abort simulation");
4270 } else {
4271 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
4273 bool cont;
4274 do {
4275 cont = false;
4276 SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
4277 if (flags & FLAG_INTERACTIVE) {
4278 PacketResponseNG resp;
4279 sector_t *k_sector = NULL;
4281 bool keypress = kbd_enter_pressed();
4282 while (keypress == false) {
4284 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
4285 keypress = kbd_enter_pressed();
4286 continue;
4289 if (resp.status != PM3_SUCCESS)
4290 break;
4292 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
4293 break;
4295 const nonces_t *data = (nonces_t *)resp.data.asBytes;
4296 readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
4297 if (setEmulatorMem) {
4298 cont = true;
4300 break;
4302 if (keypress) {
4303 if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
4304 // inform device to break the sim loop since client has exited
4305 PrintAndLogEx(INFO, "Key pressed, please wait a few seconds for the pm3 to stop...");
4306 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
4311 } while (cont);
4312 return PM3_SUCCESS;
4316 static int CmdHF14AMfKeyBrute(const char *Cmd) {
4318 uint8_t blockNo = 0, keytype = MF_KEY_A;
4319 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
4320 uint64_t foundkey = 0;
4322 char cmdp = tolower(param_getchar(Cmd, 0));
4323 if (cmdp == 'h') return usage_hf14_keybrute();
4325 // block number
4326 blockNo = param_get8(Cmd, 0);
4328 // keytype
4329 cmdp = tolower(param_getchar(Cmd, 1));
4330 if (cmdp == 'b') keytype = MF_KEY_B;
4332 // key
4333 int keylen = 0;
4334 if (param_gethex_ex(Cmd, 2, key, &keylen) && (keylen != 12)) {
4335 return usage_hf14_keybrute();
4338 uint64_t t1 = msclock();
4340 if (mfKeyBrute(blockNo, keytype, key, &foundkey))
4341 PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 " \n", foundkey);
4342 else
4343 PrintAndLogEx(FAILED, "key not found");
4345 t1 = msclock() - t1;
4346 PrintAndLogEx(SUCCESS, "\ntime in keybrute " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
4347 return PM3_SUCCESS;
4351 void printKeyTable(size_t sectorscnt, sector_t *e_sector) {
4352 printKeyTableEx(sectorscnt, e_sector, 0);
4355 void printKeyTableEx(size_t sectorscnt, sector_t *e_sector, uint8_t start_sector) {
4356 char strA[26 + 1] = {0};
4357 char strB[26 + 1] = {0};
4358 char resA[20 + 1] = {0};
4359 char resB[20 + 1] = {0};
4361 uint64_t ndef_key = 0xD3F7D3F7D3F7;
4362 bool has_ndef_key = false;
4363 bool extended_legend = false;
4365 PrintAndLogEx(NORMAL, "");
4366 PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
4367 PrintAndLogEx(SUCCESS, " Sec | Blk | key A |res| key B |res");
4368 PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
4370 for (size_t i = 0; i < sectorscnt; i++) {
4372 if ((e_sector[i].foundKey[0] > 1) || (e_sector[i].foundKey[1] > 1)) {
4373 extended_legend = true;
4376 if (e_sector[i].Key[0] == ndef_key || e_sector[i].Key[1] == ndef_key) {
4377 has_ndef_key = true;
4380 if (e_sector[i].foundKey[0]) {
4381 snprintf(strA, sizeof(strA), _GREEN_("%012" PRIX64), e_sector[i].Key[0]);
4382 if (extended_legend) {
4383 snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[0]);
4384 } else {
4385 snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%d"), e_sector[i].foundKey[0]);
4387 } else {
4388 snprintf(strA, sizeof(strA), _RED_("%s"), "------------");
4389 snprintf(resA, sizeof(resA), _RED_("0"));
4392 if (e_sector[i].foundKey[1]) {
4393 snprintf(strB, sizeof(strB), _GREEN_("%012" PRIX64), e_sector[i].Key[1]);
4394 if (extended_legend) {
4395 snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[1]);
4396 } else {
4397 snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%d"), e_sector[i].foundKey[1]);
4399 } else {
4400 snprintf(strB, sizeof(strB), _RED_("%s"), "------------");
4401 snprintf(resB, sizeof(resB), _RED_("0"));
4404 // keep track if we use start_sector or i
4405 // show one sector or all.
4406 uint8_t s = start_sector;
4407 if (start_sector == 0) {
4408 s = i;
4411 char extra[24] = {0x00};
4412 if (sectorscnt == 18 && i > 15) {
4413 strcat(extra, "( " _MAGENTA_("*") " )");
4416 PrintAndLogEx(SUCCESS, " " _YELLOW_("%03d") " | %03d | %s | %s | %s | %s %s"
4418 , mfSectorTrailerOfSector(s)
4419 , strA, resA
4420 , strB, resB
4421 , extra
4425 PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
4427 if (extended_legend) {
4428 PrintAndLogEx(INFO, "( "
4429 _YELLOW_("D") ":Dictionary / "
4430 _YELLOW_("S") ":darkSide / "
4431 _YELLOW_("U") ":User / "
4432 _YELLOW_("R") ":Reused / "
4433 _YELLOW_("N") ":Nested / "
4434 _YELLOW_("H") ":Hardnested / "
4435 _YELLOW_("C") ":statiCnested / "
4436 _YELLOW_("A") ":keyA "
4437 " )"
4439 if (sectorscnt == 18) {
4440 PrintAndLogEx(INFO, "( " _MAGENTA_("*") " ) These sectors used for signature. Lays outside of user memory");
4443 } else {
4444 PrintAndLogEx(SUCCESS, "( " _RED_("0") ":Failed / " _GREEN_("1") ":Success )");
4447 // MAD detection
4448 if (e_sector[MF_MAD1_SECTOR].foundKey[0] && e_sector[MF_MAD1_SECTOR].Key[0] == 0xA0A1A2A3A4A5) {
4449 PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
4451 // NDEF detection
4452 if (has_ndef_key) {
4453 PrintAndLogEx(HINT, "NDEF key detected. Try " _YELLOW_("`hf mf ndefread`") " for more details");
4455 PrintAndLogEx(NORMAL, "");
4459 // EMULATOR COMMANDS
4460 static int CmdHF14AMfEGetBlk(const char *Cmd) {
4461 CLIParserContext *ctx;
4462 CLIParserInit(&ctx, "hf mf egetblk",
4463 "Get emulator memory block",
4464 "hf mf egetblk --blk 0 -> get block 0 (manufacturer)\n"
4465 "hf mf egetblk --blk 3 -v -> get block 3, decode sector trailer\n"
4467 void *argtable[] = {
4468 arg_param_begin,
4469 arg_int1("b", "blk", "<dec>", "block number"),
4470 arg_lit0("v", "verbose", "verbose output"),
4471 arg_param_end
4473 CLIExecWithReturn(ctx, Cmd, argtable, false);
4474 int b = arg_get_int_def(ctx, 1, 0);
4475 bool verbose = arg_get_lit(ctx, 2);
4476 CLIParserFree(ctx);
4478 if (b > 255) {
4479 return PM3_EINVARG;
4481 uint8_t blockno = (uint8_t)b;
4483 uint8_t data[16] = {0x00};
4484 if (mf_eml_get_mem(data, blockno, 1) == PM3_SUCCESS) {
4486 uint8_t sector = mfSectorNum(blockno);
4487 mf_print_sector_hdr(sector);
4488 mf_print_block_one(blockno, data, verbose);
4490 if (verbose) {
4491 decode_print_st(blockno, data);
4492 } else {
4493 PrintAndLogEx(NORMAL, "");
4495 return PM3_SUCCESS;
4498 static int CmdHF14AMfEGetSc(const char *Cmd) {
4499 CLIParserContext *ctx;
4500 CLIParserInit(&ctx, "hf mf egetsc",
4501 "Get emulator memory sector",
4502 "hf mf egetsc -s 0"
4504 void *argtable[] = {
4505 arg_param_begin,
4506 arg_int1("s", "sec", "<dec>", "sector number"),
4507 arg_lit0("v", "verbose", "verbose output"),
4508 arg_param_end
4510 CLIExecWithReturn(ctx, Cmd, argtable, false);
4511 int s = arg_get_int_def(ctx, 1, 0);
4512 bool verbose = arg_get_lit(ctx, 2);
4513 CLIParserFree(ctx);
4515 if (s >= MIFARE_4K_MAXSECTOR) {
4516 PrintAndLogEx(WARNING, "Sector number must be less then 40");
4517 return PM3_EINVARG;
4520 uint8_t sector = (uint8_t)s;
4521 mf_print_sector_hdr(sector);
4523 uint8_t blocks = mfNumBlocksPerSector(sector);
4524 uint8_t start = mfFirstBlockOfSector(sector);
4526 uint8_t data[16] = {0};
4527 for (int i = 0; i < blocks; i++) {
4528 int res = mf_eml_get_mem(data, start + i, 1);
4529 if (res == PM3_SUCCESS) {
4530 mf_print_block_one(start + i, data, verbose);
4533 if (verbose) {
4534 decode_print_st(start + blocks - 1, data);
4535 } else {
4536 PrintAndLogEx(NORMAL, "");
4538 return PM3_SUCCESS;
4541 static int CmdHF14AMfEClear(const char *Cmd) {
4542 CLIParserContext *ctx;
4543 CLIParserInit(&ctx, "hf mf eclr",
4544 "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF",
4545 "hf mf eclr"
4547 void *argtable[] = {
4548 arg_param_begin,
4549 arg_param_end
4551 CLIExecWithReturn(ctx, Cmd, argtable, true);
4552 CLIParserFree(ctx);
4553 clearCommandBuffer();
4554 SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0);
4555 return PM3_SUCCESS;
4558 static int CmdHF14AMfESet(const char *Cmd) {
4560 CLIParserContext *ctx;
4561 CLIParserInit(&ctx, "hf mf esetblk",
4562 "Set emulator memory block",
4563 "hf mf esetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
4565 void *argtable[] = {
4566 arg_param_begin,
4567 arg_int1("b", "blk", "<dec>", "block number"),
4568 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
4569 arg_param_end
4571 CLIExecWithReturn(ctx, Cmd, argtable, false);
4573 int b = arg_get_int_def(ctx, 1, 0);
4575 uint8_t data[16] = {0x00};
4576 int datalen = 0;
4577 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &datalen);
4578 CLIParserFree(ctx);
4579 if (res) {
4580 PrintAndLogEx(FAILED, "Error parsing bytes");
4581 return PM3_EINVARG;
4584 if (b > 255) {
4585 return PM3_EINVARG;
4588 if (datalen != sizeof(data)) {
4589 PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", datalen);
4590 return PM3_EINVARG;
4593 // 1 - blocks count
4594 return mf_elm_set_mem(data, b, 1);
4597 int CmdHF14AMfELoad(const char *Cmd) {
4599 CLIParserContext *ctx;
4600 CLIParserInit(&ctx, "hf mf eload",
4601 "Load emulator memory with data from (bin/eml/json) dump file",
4602 "hf mf eload -f hf-mf-01020304.bin\n"
4603 "hf mf eload --4k -f hf-mf-01020304.eml\n"
4605 void *argtable[] = {
4606 arg_param_begin,
4607 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
4608 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4609 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4610 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4611 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4612 arg_lit0(NULL, "ul", "MIFARE Ultralight family"),
4613 arg_lit0("m", "mem", "use RDV4 spiffs"),
4614 arg_int0("q", "qty", "<dec>", "manually set number of blocks (overrides)"),
4615 arg_lit0("v", "verbose", "verbose output"),
4616 arg_param_end
4618 CLIExecWithReturn(ctx, Cmd, argtable, false);
4620 int fnlen = 0;
4621 char filename[FILE_PATH_SIZE];
4622 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
4624 bool m0 = arg_get_lit(ctx, 2);
4625 bool m1 = arg_get_lit(ctx, 3);
4626 bool m2 = arg_get_lit(ctx, 4);
4627 bool m4 = arg_get_lit(ctx, 5);
4628 bool mu = arg_get_lit(ctx, 6);
4630 bool use_spiffs = arg_get_lit(ctx, 7);
4631 int numblks = arg_get_int_def(ctx, 8, -1);
4632 bool verbose = arg_get_lit(ctx, 9);
4633 CLIParserFree(ctx);
4635 // validations
4636 if ((m0 + m1 + m2 + m4 + mu) > 1) {
4637 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4638 return PM3_EINVARG;
4639 } else if ((m0 + m1 + m2 + m4 + mu) == 0) {
4640 m1 = true;
4643 uint8_t block_width = 16;
4644 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
4645 uint8_t hdr_len = 0;
4647 if (m0) {
4648 block_cnt = MIFARE_MINI_MAXBLOCK;
4649 } else if (m1) {
4650 block_cnt = MIFARE_1K_MAXBLOCK;
4651 } else if (m2) {
4652 block_cnt = MIFARE_2K_MAXBLOCK;
4653 } else if (m4) {
4654 block_cnt = MIFARE_4K_MAXBLOCK;
4655 } else if (mu) {
4656 block_cnt = MFU_MAX_BLOCKS;
4657 block_width = MFU_BLOCK_SIZE;
4658 hdr_len = MFU_DUMP_PREFIX_LENGTH;
4659 } else {
4660 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
4661 return PM3_EINVARG;
4664 PrintAndLogEx(INFO, "Upload " _YELLOW_("%u") " blocks " _YELLOW_("%u") " bytes", block_cnt, block_cnt * block_width);
4666 if (numblks > 0) {
4667 block_cnt = MIN(numblks, block_cnt);
4668 PrintAndLogEx(INFO, "overriding number of blocks, will use " _YELLOW_("%u") " blocks " _YELLOW_("%u") " bytes", block_cnt, block_cnt * block_width);
4671 // ICEMAN: bug. if device has been using ICLASS commands,
4672 // the device needs to load the HF fpga image. It takes 1.5 second.
4673 set_fpga_mode(FPGA_BITSTREAM_HF);
4675 // use RDV4 spiffs
4676 if (use_spiffs && IfPm3Flash() == false) {
4677 PrintAndLogEx(WARNING, "Device not compiled to support spiffs");
4678 return PM3_EINVARG;
4681 if (use_spiffs) {
4683 if (fnlen > 32) {
4684 PrintAndLogEx(WARNING, "filename too long for spiffs, expected 32, got %u", fnlen);
4685 return PM3_EINVARG;
4688 clearCommandBuffer();
4689 SendCommandNG(CMD_SPIFFS_ELOAD, (uint8_t *)filename, fnlen);
4690 PacketResponseNG resp;
4691 if (WaitForResponseTimeout(CMD_SPIFFS_ELOAD, &resp, 2000) == false) {
4692 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
4693 return PM3_ETIMEOUT;
4696 if (resp.status != PM3_SUCCESS) {
4697 PrintAndLogEx(FAILED, "Loading file from spiffs to emulator memory failed");
4698 return PM3_EFLASH;
4701 PrintAndLogEx(SUCCESS, "File transfered from spiffs to device emulator memory");
4702 return PM3_SUCCESS;
4705 uint8_t *data = NULL;
4706 size_t bytes_read = 0;
4707 int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (block_width * block_cnt + hdr_len));
4708 if (res != PM3_SUCCESS) {
4709 return res;
4712 // 64 or 256 blocks.
4713 if ((bytes_read % block_width) != 0) {
4714 PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth ");
4715 free(data);
4716 return PM3_ESOFT;
4719 // convert plain or old mfu format to new format
4720 if (block_width == MFU_BLOCK_SIZE) {
4721 res = convert_mfu_dump_format(&data, &bytes_read, true);
4722 if (res != PM3_SUCCESS) {
4723 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
4724 free(data);
4725 return res;
4728 if (verbose) {
4729 mfu_dump_t *mfu_dump = (mfu_dump_t *)data;
4730 mfu_print_dump(mfu_dump, mfu_dump->pages + 1, 0, false);
4733 // update expected blocks to match converted data.
4734 block_cnt = bytes_read / MFU_BLOCK_SIZE;
4735 PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width);
4738 PrintAndLogEx(INFO, "Uploading to emulator memory");
4739 PrintAndLogEx(INFO, "." NOLF);
4741 // fast push mode
4742 g_conn.block_after_ACK = true;
4744 size_t offset = 0;
4745 int cnt = 0;
4747 // 12 is the size of the struct the fct mf_eml_set_mem_xt uses to transfer to device
4748 uint16_t max_avail_blocks = ((PM3_CMD_DATA_SIZE - 12) / block_width) * block_width;
4750 while (bytes_read && cnt < block_cnt) {
4751 if (bytes_read == block_width) {
4752 // Disable fast mode on last packet
4753 g_conn.block_after_ACK = false;
4756 uint16_t chunk_size = MIN(max_avail_blocks, bytes_read);
4757 uint16_t blocks_to_send = chunk_size / block_width;
4759 if (mf_eml_set_mem_xt(data + offset, cnt, blocks_to_send, block_width) != PM3_SUCCESS) {
4760 PrintAndLogEx(FAILED, "Can't set emulator mem at block: %3d", cnt);
4761 free(data);
4762 return PM3_ESOFT;
4764 cnt += blocks_to_send;
4765 offset += chunk_size;
4766 bytes_read -= chunk_size;
4767 PrintAndLogEx(NORMAL, "." NOLF);
4768 fflush(stdout);
4770 free(data);
4771 PrintAndLogEx(NORMAL, "");
4773 if (block_width == MFU_BLOCK_SIZE) {
4774 PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim -h`"));
4775 // MFU / NTAG
4776 if ((cnt != block_cnt)) {
4777 PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", cnt, block_cnt);
4778 return PM3_SUCCESS;
4780 } else {
4781 PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim -h`"));
4782 // MFC
4783 if ((cnt != block_cnt)) {
4784 PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", cnt, block_cnt);
4785 return PM3_SUCCESS;
4787 PrintAndLogEx(INFO, "Done!");
4789 return PM3_SUCCESS;
4792 static int CmdHF14AMfESave(const char *Cmd) {
4794 CLIParserContext *ctx;
4795 CLIParserInit(&ctx, "hf mf esave",
4796 "Save emulator memory to file (bin/json) ",
4797 "hf mf esave\n"
4798 "hf mf esave --4k\n"
4799 "hf mf esave --4k -f hf-mf-01020304.eml"
4801 void *argtable[] = {
4802 arg_param_begin,
4803 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
4804 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4805 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4806 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4807 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4808 arg_param_end
4810 CLIExecWithReturn(ctx, Cmd, argtable, true);
4812 int fnlen = 0;
4813 char filename[FILE_PATH_SIZE];
4814 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
4816 bool m0 = arg_get_lit(ctx, 2);
4817 bool m1 = arg_get_lit(ctx, 3);
4818 bool m2 = arg_get_lit(ctx, 4);
4819 bool m4 = arg_get_lit(ctx, 5);
4820 CLIParserFree(ctx);
4822 // validations
4823 if ((m0 + m1 + m2 + m4) > 1) {
4824 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4825 return PM3_EINVARG;
4826 } else if ((m0 + m1 + m2 + m4) == 0) {
4827 m1 = true;
4830 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
4832 if (m0) {
4833 block_cnt = MIFARE_MINI_MAXBLOCK;
4834 } else if (m1) {
4835 block_cnt = MIFARE_1K_MAXBLOCK;
4836 } else if (m2) {
4837 block_cnt = MIFARE_2K_MAXBLOCK;
4838 } else if (m4) {
4839 block_cnt = MIFARE_4K_MAXBLOCK;
4842 int bytes = block_cnt * MFBLOCK_SIZE;
4844 // reserv memory
4845 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
4846 if (dump == NULL) {
4847 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
4848 return PM3_EMALLOC;
4850 memset(dump, 0, bytes);
4852 PrintAndLogEx(INFO, "downloading %u bytes from emulator memory", bytes);
4853 if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
4854 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
4855 free(dump);
4856 return PM3_ETIMEOUT;
4859 // user supplied filename?
4860 if (fnlen < 1) {
4861 char *fptr = filename;
4862 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
4863 FillFileNameByUID(fptr, dump, "-dump", 4);
4866 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
4867 free(dump);
4868 return PM3_SUCCESS;
4871 static int CmdHF14AMfEView(const char *Cmd) {
4873 CLIParserContext *ctx;
4874 CLIParserInit(&ctx, "hf mf eview",
4875 "It displays emulator memory",
4876 "hf mf eview\n"
4877 "hf mf eview --4k"
4879 void *argtable[] = {
4880 arg_param_begin,
4881 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4882 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4883 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4884 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4885 arg_lit0("v", "verbose", "verbose output"),
4886 arg_lit0(NULL, "sk", "Save extracted keys to binary file"),
4887 arg_param_end
4889 CLIExecWithReturn(ctx, Cmd, argtable, true);
4890 bool m0 = arg_get_lit(ctx, 1);
4891 bool m1 = arg_get_lit(ctx, 2);
4892 bool m2 = arg_get_lit(ctx, 3);
4893 bool m4 = arg_get_lit(ctx, 4);
4894 bool verbose = arg_get_lit(ctx, 5);
4895 bool save_keys = arg_get_lit(ctx, 6);
4896 CLIParserFree(ctx);
4898 // validations
4899 if ((m0 + m1 + m2 + m4) > 1) {
4900 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4901 return PM3_EINVARG;
4902 } else if ((m0 + m1 + m2 + m4) == 0) {
4903 m1 = true;
4906 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
4908 if (m0) {
4909 block_cnt = MIFARE_MINI_MAXBLOCK;
4910 } else if (m1) {
4911 block_cnt = MIFARE_1K_MAXBLOCK;
4912 } else if (m2) {
4913 block_cnt = MIFARE_2K_MAXBLOCK;
4914 } else if (m4) {
4915 block_cnt = MIFARE_4K_MAXBLOCK;
4916 } else {
4917 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
4918 return PM3_EINVARG;
4921 int bytes = block_cnt * MFBLOCK_SIZE;
4923 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
4924 if (dump == NULL) {
4925 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
4926 return PM3_EMALLOC;
4929 PrintAndLogEx(INFO, "downloading emulator memory");
4930 if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
4931 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
4932 free(dump);
4933 return PM3_ETIMEOUT;
4936 mf_print_blocks(block_cnt, dump, verbose);
4938 if (verbose) {
4939 mf_print_keys(block_cnt, dump);
4942 if (save_keys) {
4943 mf_save_keys_from_arr(block_cnt, dump);
4946 free(dump);
4947 return PM3_SUCCESS;
4950 static int CmdHF14AMfECFill(const char *Cmd) {
4952 CLIParserContext *ctx;
4953 CLIParserInit(&ctx, "hf mf ecfill",
4954 "Dump card and transfer the data to emulator memory.\n"
4955 "Keys must be in the emulator memory",
4956 "hf mf ecfill --> use key type A\n"
4957 "hf mf ecfill --4k -b --> target 4K card with key type B"
4959 void *argtable[] = {
4960 arg_param_begin,
4961 arg_lit0("a", NULL, "input key type is key A(def)"),
4962 arg_lit0("b", NULL, "input key type is key B"),
4963 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
4964 arg_str0("k", "key", "<hex>", "key, 6 hex bytes, only for option -c"),
4965 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4966 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4967 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4968 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4969 arg_param_end
4971 CLIExecWithReturn(ctx, Cmd, argtable, true);
4972 uint8_t keytype = MF_KEY_A;
4973 if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) {
4974 CLIParserFree(ctx);
4975 PrintAndLogEx(WARNING, "Choose one single input key type");
4976 return PM3_EINVARG;
4977 } else if (arg_get_lit(ctx, 2)) {
4978 keytype = MF_KEY_B;
4980 uint8_t prev_keytype = keytype;
4981 keytype = arg_get_int_def(ctx, 3, keytype);
4982 if ((arg_get_lit(ctx, 1) || arg_get_lit(ctx, 2)) && (keytype != prev_keytype)) {
4983 CLIParserFree(ctx);
4984 PrintAndLogEx(WARNING, "Choose one single input key type");
4985 return PM3_EINVARG;
4987 int keylen = 0;
4988 uint8_t key[6] = {0};
4989 CLIGetHexWithReturn(ctx, 4, key, &keylen);
4990 if ((keytype > MF_KEY_B) && (keylen != 6)) {
4991 PrintAndLogEx(WARNING, "Missing key");
4992 return PM3_EINVARG;
4994 if ((keytype <= MF_KEY_B) && (keylen > 0)) {
4995 PrintAndLogEx(WARNING, "Ignoring provided key");
4998 bool m0 = arg_get_lit(ctx, 5);
4999 bool m1 = arg_get_lit(ctx, 6);
5000 bool m2 = arg_get_lit(ctx, 7);
5001 bool m4 = arg_get_lit(ctx, 8);
5002 CLIParserFree(ctx);
5004 // validations
5005 if ((m0 + m1 + m2 + m4) > 1) {
5006 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5007 return PM3_EINVARG;
5008 } else if ((m0 + m1 + m2 + m4) == 0) {
5009 m1 = true;
5012 uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR;
5014 if (m0) {
5015 sectors_cnt = MIFARE_MINI_MAXSECTOR;
5016 } else if (m1) {
5017 sectors_cnt = MIFARE_1K_MAXSECTOR;
5018 } else if (m2) {
5019 sectors_cnt = MIFARE_2K_MAXSECTOR;
5020 } else if (m4) {
5021 sectors_cnt = MIFARE_4K_MAXSECTOR;
5022 } else {
5023 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5024 return PM3_EINVARG;
5027 mfc_eload_t payload = {
5028 .sectorcnt = sectors_cnt,
5029 .keytype = keytype
5031 memcpy(payload.key, key, sizeof(payload.key));
5033 clearCommandBuffer();
5034 uint64_t t1 = msclock();
5035 SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
5037 PacketResponseNG resp;
5038 if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 1500) == false) {
5039 PrintAndLogEx(WARNING, "command execution time out");
5040 return PM3_ETIMEOUT;
5042 t1 = msclock() - t1;
5044 if (resp.status == PM3_SUCCESS)
5045 PrintAndLogEx(SUCCESS, "Fill ( " _GREEN_("ok") " ) in " _YELLOW_("%" PRIu64) " ms", t1);
5046 else
5047 PrintAndLogEx(FAILED, "Fill ( " _RED_("fail") " )");
5049 return resp.status;
5052 static int CmdHF14AMfEKeyPrn(const char *Cmd) {
5054 CLIParserContext *ctx;
5055 CLIParserInit(&ctx, "hf mf ekeyprn",
5056 "Download and print the keys from emulator memory",
5057 "hf mf ekeyprn --1k --> print MFC 1K keyset\n"
5058 "hf mf ekeyprn -w --> write keys to binary file"
5060 void *argtable[] = {
5061 arg_param_begin,
5062 arg_lit0("w", "write", "write keys to binary file `hf-mf-<UID>-key.bin`"),
5063 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5064 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5065 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5066 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5067 arg_param_end
5069 CLIExecWithReturn(ctx, Cmd, argtable, true);
5071 bool create_dumpfile = arg_get_lit(ctx, 1);
5072 bool m0 = arg_get_lit(ctx, 2);
5073 bool m1 = arg_get_lit(ctx, 3);
5074 bool m2 = arg_get_lit(ctx, 4);
5075 bool m4 = arg_get_lit(ctx, 5);
5076 CLIParserFree(ctx);
5078 // validations
5079 if ((m0 + m1 + m2 + m4) > 1) {
5080 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5081 return PM3_EINVARG;
5082 } else if ((m0 + m1 + m2 + m4) == 0) {
5083 m1 = true;
5086 size_t sectors_cnt = MIFARE_1K_MAXSECTOR;
5088 if (m0) {
5089 sectors_cnt = MIFARE_MINI_MAXSECTOR;
5090 } else if (m1) {
5091 sectors_cnt = MIFARE_1K_MAXSECTOR;
5092 } else if (m2) {
5093 sectors_cnt = MIFARE_2K_MAXSECTOR;
5094 } else if (m4) {
5095 sectors_cnt = MIFARE_4K_MAXSECTOR;
5096 } else {
5097 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5098 return PM3_EINVARG;
5101 // create/initialize key storage structure
5102 sector_t *e_sector = NULL;
5103 if (initSectorTable(&e_sector, sectors_cnt) != PM3_SUCCESS) {
5104 return PM3_EMALLOC;
5107 // read UID from EMUL
5108 uint8_t data[16];
5109 if (mf_eml_get_mem(data, 0, 1) != PM3_SUCCESS) {
5110 PrintAndLogEx(WARNING, "error get block 0");
5111 free(e_sector);
5112 return PM3_ESOFT;
5115 // assuming 4byte UID.
5116 uint8_t uid[4];
5117 memcpy(uid, data, sizeof(uid));
5119 // download keys from EMUL
5120 for (int i = 0; i < sectors_cnt; i++) {
5122 if (mf_eml_get_mem(data, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1) != PM3_SUCCESS) {
5123 PrintAndLogEx(WARNING, "error get block %d", mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
5124 e_sector[i].foundKey[0] = false;
5125 e_sector[i].foundKey[1] = false;
5126 } else {
5127 e_sector[i].foundKey[0] = true;
5128 e_sector[i].Key[0] = bytes_to_num(data, 6);
5129 e_sector[i].foundKey[1] = true;
5130 e_sector[i].Key[1] = bytes_to_num(data + 10, 6);
5134 // print keys
5135 printKeyTable(sectors_cnt, e_sector);
5137 // dump the keys
5138 if (create_dumpfile) {
5140 char filename[FILE_PATH_SIZE] = {0};
5141 char *fptr = filename;
5142 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
5143 FillFileNameByUID(fptr + strlen(fptr), uid, "-key", sizeof(uid));
5144 createMfcKeyDump(filename, sectors_cnt, e_sector);
5147 free(e_sector);
5148 return PM3_SUCCESS;
5151 // CHINESE MAGIC COMMANDS
5152 static int CmdHF14AMfCSetUID(const char *Cmd) {
5154 CLIParserContext *ctx;
5155 CLIParserInit(&ctx, "hf mf csetuid",
5156 "Set UID, ATQA, and SAK for magic gen1a card",
5157 "hf mf csetuid -u 01020304\n"
5158 "hf mf csetuid -w -u 01020304 --atqa 0004 --sak 08"
5160 void *argtable[] = {
5161 arg_param_begin,
5162 arg_lit0("w", "wipe", "wipes card with backdoor cmd`"),
5163 arg_str0("u", "uid", "<hex>", "UID, 4/7 hex bytes"),
5164 arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
5165 arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
5166 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5167 arg_param_end
5169 CLIExecWithReturn(ctx, Cmd, argtable, true);
5171 uint8_t wipe_card = arg_get_lit(ctx, 1);
5173 int uidlen = 0;
5174 uint8_t uid[7] = {0x00};
5175 CLIGetHexWithReturn(ctx, 2, uid, &uidlen);
5177 int alen = 0;
5178 uint8_t atqa[2] = {0x00};
5179 CLIGetHexWithReturn(ctx, 3, atqa, &alen);
5181 int slen = 0;
5182 uint8_t sak[1] = {0x00};
5183 CLIGetHexWithReturn(ctx, 4, sak, &slen);
5184 uint8_t gdm = arg_get_lit(ctx, 5);
5185 CLIParserFree(ctx);
5187 // sanity checks
5188 if (uidlen != 4 && uidlen != 7) {
5189 PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen);
5190 return PM3_EINVARG;
5192 if (alen && alen != 2) {
5193 PrintAndLogEx(FAILED, "ATQA must be 2 hex bytes. Got %d", alen);
5194 return PM3_EINVARG;
5196 if (slen && slen != 1) {
5197 PrintAndLogEx(FAILED, "SAK must be 1 hex byte. Got %d", slen);
5198 return PM3_EINVARG;
5201 uint8_t old_uid[7] = {0};
5202 uint8_t verify_uid[7] = {0};
5204 int res = mf_chinese_set_uid(
5205 uid,
5206 uidlen,
5207 (alen) ? atqa : NULL,
5208 (slen) ? sak : NULL,
5209 old_uid,
5210 verify_uid,
5211 wipe_card,
5215 if (res) {
5216 PrintAndLogEx(ERR, "Can't set UID. error %d", res);
5217 return PM3_ESOFT;
5220 res = memcmp(uid, verify_uid, uidlen);
5222 PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen));
5223 PrintAndLogEx(SUCCESS, "New UID... %s ( %s )",
5224 sprint_hex(verify_uid, uidlen),
5225 (res == 0) ? _GREEN_("verified") : _RED_("fail")
5227 return PM3_SUCCESS;
5230 static int CmdHF14AMfCWipe(const char *cmd) {
5231 CLIParserContext *ctx;
5232 CLIParserInit(&ctx, "hf mf cwipe",
5233 "Wipe gen1 magic chinese card.\n"
5234 "Set UID / ATQA / SAK / Data / Keys / Access to default values",
5235 "hf mf cwipe\n"
5236 "hf mf cwipe -u 09080706 -a 0004 -s 18 --> set UID, ATQA and SAK and wipe card");
5238 void *argtable[] = {
5239 arg_param_begin,
5240 arg_str0("u", "uid", "<hex>", "UID, 4 hex bytes"),
5241 arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
5242 arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
5243 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5244 arg_param_end
5246 CLIExecWithReturn(ctx, cmd, argtable, true);
5248 int uidlen = 0;
5249 uint8_t uid[8] = {0x00};
5250 CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
5252 int alen = 0;
5253 uint8_t atqa[2] = {0x00};
5254 CLIGetHexWithReturn(ctx, 2, atqa, &alen);
5256 int slen = 0;
5257 uint8_t sak[1] = {0x00};
5258 CLIGetHexWithReturn(ctx, 3, sak, &slen);
5259 uint8_t gdm = arg_get_lit(ctx, 4);
5260 CLIParserFree(ctx);
5262 if (uidlen && uidlen != 4) {
5263 PrintAndLogEx(ERR, "UID length must be 4 bytes, got %d", uidlen);
5264 return PM3_EINVARG;
5266 if (alen && alen != 2) {
5267 PrintAndLogEx(ERR, "ATQA length must be 2 bytes, got %d", alen);
5268 return PM3_EINVARG;
5270 if (slen && slen != 1) {
5271 PrintAndLogEx(ERR, "SAK length must be 1 byte, got %d", slen);
5272 return PM3_EINVARG;
5275 int res = mf_chinese_wipe((uidlen) ? uid : NULL, (alen) ? atqa : NULL, (slen) ? sak : NULL, gdm);
5276 if (res) {
5277 PrintAndLogEx(ERR, "Can't wipe card. error %d", res);
5278 return PM3_ESOFT;
5281 PrintAndLogEx(SUCCESS, "Card wiped successfully");
5282 return PM3_SUCCESS;
5285 static int CmdHF14AMfCSetBlk(const char *Cmd) {
5287 CLIParserContext *ctx;
5288 CLIParserInit(&ctx, "hf mf csetblk",
5289 "Set block data on a magic gen1a card",
5290 "hf mf csetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
5292 void *argtable[] = {
5293 arg_param_begin,
5294 arg_int1("b", "blk", "<dec>", "block number"),
5295 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
5296 arg_lit0("w", "wipe", "wipes card with backdoor cmd before writing"),
5297 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5298 arg_param_end
5300 CLIExecWithReturn(ctx, Cmd, argtable, false);
5302 int b = arg_get_int_def(ctx, 1, -1);
5304 uint8_t data[MFBLOCK_SIZE] = {0x00};
5305 int datalen = 0;
5306 CLIGetHexWithReturn(ctx, 2, data, &datalen);
5308 uint8_t wipe_card = arg_get_lit(ctx, 3);
5309 uint8_t gdm = arg_get_lit(ctx, 4);
5310 CLIParserFree(ctx);
5312 if (b < 0 || b >= MIFARE_1K_MAXBLOCK) {
5313 PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
5314 return PM3_EINVARG;
5317 if (datalen != MFBLOCK_SIZE) {
5318 PrintAndLogEx(FAILED, "expected 16 bytes data, got %i", datalen);
5319 return PM3_EINVARG;
5322 uint8_t params = MAGIC_SINGLE;
5323 if (gdm) {
5324 params |= MAGIC_GDM_ALT_WUPC;
5325 } else {
5326 params |= MAGIC_WUPC;
5329 if (wipe_card) {
5330 params |= MAGIC_WIPE;
5333 PrintAndLogEx(INFO, "Writing block number:%2d data:%s", b, sprint_hex_inrow(data, sizeof(data)));
5335 int res = mf_chinese_set_block(b, data, NULL, params);
5336 if (res) {
5337 PrintAndLogEx(ERR, "Can't write block. error=%d", res);
5338 return PM3_ESOFT;
5340 return PM3_SUCCESS;
5343 static int CmdHF14AMfCLoad(const char *Cmd) {
5345 CLIParserContext *ctx;
5346 CLIParserInit(&ctx, "hf mf cload",
5347 "Load magic gen1a card with data from (bin/eml/json) dump file\n"
5348 "or from emulator memory.",
5349 "hf mf cload --emu\n"
5350 "hf mf cload -f hf-mf-01020304.eml\n"
5352 void *argtable[] = {
5353 arg_param_begin,
5354 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5355 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5356 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5357 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5358 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5359 arg_lit0(NULL, "emu", "from emulator memory"),
5360 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5361 arg_param_end
5363 CLIExecWithReturn(ctx, Cmd, argtable, false);
5365 int fnlen = 0;
5366 char filename[FILE_PATH_SIZE] = {0};
5367 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5369 bool m0 = arg_get_lit(ctx, 2);
5370 bool m1 = arg_get_lit(ctx, 3);
5371 bool m2 = arg_get_lit(ctx, 4);
5372 bool m4 = arg_get_lit(ctx, 5);
5373 bool fill_from_emulator = arg_get_lit(ctx, 6);
5374 bool gdm = arg_get_lit(ctx, 7);
5376 CLIParserFree(ctx);
5378 if ((m0 + m1 + m2 + m4) > 1) {
5379 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5380 return PM3_EINVARG;
5381 } else if ((m0 + m1 + m2 + m4) == 0) {
5382 m1 = true;
5385 char s[6];
5386 memset(s, 0, sizeof(s));
5387 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
5388 if (m0) {
5389 block_cnt = MIFARE_MINI_MAXBLOCK;
5390 strncpy(s, "Mini", 5);
5391 } else if (m1) {
5392 block_cnt = MIFARE_1K_MAXBLOCK;
5393 strncpy(s, "1K", 3);
5394 } else if (m2) {
5395 block_cnt = MIFARE_2K_MAXBLOCK;
5396 strncpy(s, "2K", 3);
5397 } else if (m4) {
5398 block_cnt = MIFARE_4K_MAXBLOCK;
5399 strncpy(s, "4K", 3);
5400 } else {
5401 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5402 return PM3_EINVARG;
5406 if (fill_from_emulator) {
5408 PrintAndLogEx(INFO, "Start upload from emulator memory");
5409 PrintAndLogEx(INFO, "." NOLF);
5411 for (int b = 0; b < block_cnt; b++) {
5412 int flags = 0;
5413 uint8_t buf8[MFBLOCK_SIZE] = {0x00};
5415 // read from emul memory
5416 if (mf_eml_get_mem(buf8, b, 1)) {
5417 PrintAndLogEx(WARNING, "Can't read from emul block: %d", b);
5418 return PM3_ESOFT;
5421 // switch on field and send magic sequence
5422 if (b == 0) {
5423 flags = MAGIC_INIT | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
5426 // just write
5427 if (b == 1) {
5428 flags = 0;
5431 // Done. Magic Halt and switch off field.
5432 if (b == (block_cnt - 1)) {
5433 flags = MAGIC_HALT + MAGIC_OFF;
5436 // write to card
5437 if (mf_chinese_set_block(b, buf8, NULL, flags)) {
5438 PrintAndLogEx(WARNING, "Can't set magic card block: %d", b);
5439 return PM3_ESOFT;
5441 PrintAndLogEx(NORMAL, "." NOLF);
5442 fflush(stdout);
5444 PrintAndLogEx(NORMAL, "");
5445 return PM3_SUCCESS;
5448 // reserve memory
5449 uint8_t *data = NULL;
5450 size_t bytes_read = 0;
5451 int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * block_cnt));
5452 if (res != PM3_SUCCESS) {
5453 return res;
5456 if (bytes_read != (block_cnt * MFBLOCK_SIZE)) {
5457 PrintAndLogEx(ERR, "File content error. Read %zu bytes", bytes_read);
5458 free(data);
5459 return PM3_EFILE;
5462 PrintAndLogEx(INFO, "Copying to magic gen1a card");
5463 PrintAndLogEx(INFO, "." NOLF);
5465 int blockno = 0;
5466 int flags = 0;
5467 while (bytes_read) {
5469 // switch on field and send magic sequence
5470 if (blockno == 0) {
5471 flags = MAGIC_INIT | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
5474 // write
5475 if (blockno == 1) {
5476 flags = 0;
5479 // switch off field
5480 if (blockno == (block_cnt - 1)) {
5481 flags = MAGIC_HALT + MAGIC_OFF;
5484 if (mf_chinese_set_block(blockno, data + (MFBLOCK_SIZE * blockno), NULL, flags)) {
5485 PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockno);
5486 free(data);
5487 return PM3_ESOFT;
5490 bytes_read -= MFBLOCK_SIZE;
5492 PrintAndLogEx(NORMAL, "." NOLF);
5493 fflush(stdout);
5495 blockno++;
5497 if (blockno >= block_cnt) break;
5499 PrintAndLogEx(NORMAL, "\n");
5501 free(data);
5503 // confirm number written blocks. Must be 20, 64 or 256 blocks
5504 if (blockno != block_cnt) {
5505 PrintAndLogEx(ERR, "File content error. There must be %d blocks", block_cnt);
5506 return PM3_EFILE;
5509 PrintAndLogEx(SUCCESS, "Card loaded " _YELLOW_("%d") " blocks from file", block_cnt);
5510 PrintAndLogEx(INFO, "Done!");
5511 return PM3_SUCCESS;
5514 static int CmdHF14AMfCGetBlk(const char *Cmd) {
5515 CLIParserContext *ctx;
5516 CLIParserInit(&ctx, "hf mf cgetblk",
5517 "Get block data from magic Chinese card.\n"
5518 "Only works with magic gen1a cards",
5519 "hf mf cgetblk --blk 0 --> get block 0 (manufacturer)\n"
5520 "hf mf cgetblk --blk 3 -v --> get block 3, decode sector trailer\n"
5522 void *argtable[] = {
5523 arg_param_begin,
5524 arg_int1("b", "blk", "<dec>", "block number"),
5525 arg_lit0("v", "verbose", "verbose output"),
5526 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5527 arg_param_end
5529 CLIExecWithReturn(ctx, Cmd, argtable, false);
5530 int b = arg_get_int_def(ctx, 1, 0);
5531 bool verbose = arg_get_lit(ctx, 2);
5532 bool gdm = arg_get_lit(ctx, 3);
5533 CLIParserFree(ctx);
5535 if (b > 255) {
5536 return PM3_EINVARG;
5539 uint8_t blockno = (uint8_t)b;
5540 uint8_t data[16] = {0};
5541 int res = mf_chinese_get_block(blockno, data, MAGIC_SINGLE | (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC));
5542 if (res) {
5543 PrintAndLogEx(ERR, "Can't read block. error=%d", res);
5544 return PM3_ESOFT;
5547 uint8_t sector = mfSectorNum(blockno);
5548 mf_print_sector_hdr(sector);
5549 mf_print_block_one(blockno, data, verbose);
5551 if (verbose) {
5552 decode_print_st(blockno, data);
5553 } else {
5554 PrintAndLogEx(NORMAL, "");
5556 return PM3_SUCCESS;
5559 static int CmdHF14AMfCGetSc(const char *Cmd) {
5560 CLIParserContext *ctx;
5561 CLIParserInit(&ctx, "hf mf cgetsc",
5562 "Get sector data from magic Chinese card.\n"
5563 "Only works with magic gen1a cards",
5564 "hf mf cgetsc -s 0"
5566 void *argtable[] = {
5567 arg_param_begin,
5568 arg_int1("s", "sec", "<dec>", "sector number"),
5569 arg_lit0("v", "verbose", "verbose output"),
5570 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5571 arg_param_end
5573 CLIExecWithReturn(ctx, Cmd, argtable, false);
5574 int s = arg_get_int_def(ctx, 1, 0);
5575 bool verbose = arg_get_lit(ctx, 2);
5576 bool gdm = arg_get_lit(ctx, 3);
5577 CLIParserFree(ctx);
5579 if (s >= MIFARE_4K_MAXSECTOR) {
5580 PrintAndLogEx(WARNING, "Sector number must be less then 40");
5581 return PM3_EINVARG;
5584 uint8_t sector = (uint8_t)s;
5585 mf_print_sector_hdr(sector);
5587 uint8_t blocks = 4;
5588 uint8_t start = sector * 4;
5589 if (sector >= 32) {
5590 blocks = 16;
5591 start = 128 + (sector - 32) * 16;
5594 int flags = MAGIC_INIT + (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
5595 uint8_t data[16] = {0};
5596 for (int i = 0; i < blocks; i++) {
5597 if (i == 1) flags = 0;
5598 if (i == blocks - 1) flags = MAGIC_HALT + MAGIC_OFF;
5600 int res = mf_chinese_get_block(start + i, data, flags);
5601 if (res) {
5602 PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res);
5603 return PM3_ESOFT;
5605 mf_print_block_one(start + i, data, verbose);
5607 if (verbose) {
5608 decode_print_st(start + blocks - 1, data);
5609 } else {
5610 PrintAndLogEx(NORMAL, "");
5612 return PM3_SUCCESS;
5615 static int CmdHF14AMfCSave(const char *Cmd) {
5616 CLIParserContext *ctx;
5617 CLIParserInit(&ctx, "hf mf csave",
5618 "Save magic gen1a card memory to file (bin/json)"
5619 "or into emulator memory",
5620 "hf mf csave\n"
5621 "hf mf csave --4k"
5623 void *argtable[] = {
5624 arg_param_begin,
5625 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5626 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5627 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5628 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5629 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5630 arg_lit0(NULL, "emu", "to emulator memory"),
5631 arg_lit0(NULL, "gdm", "to emulator memory"),
5632 arg_param_end
5634 CLIExecWithReturn(ctx, Cmd, argtable, true);
5636 int fnlen = 0;
5637 char filename[FILE_PATH_SIZE];
5638 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5640 bool m0 = arg_get_lit(ctx, 2);
5641 bool m1 = arg_get_lit(ctx, 3);
5642 bool m2 = arg_get_lit(ctx, 4);
5643 bool m4 = arg_get_lit(ctx, 5);
5644 bool fill_emulator = arg_get_lit(ctx, 6);
5645 bool gdm = arg_get_lit(ctx, 7);
5646 CLIParserFree(ctx);
5648 // validations
5649 if ((m0 + m1 + m2 + m4) > 1) {
5650 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5651 return PM3_EINVARG;
5652 } else if ((m0 + m1 + m2 + m4) == 0) {
5653 m1 = true;
5656 char s[6];
5657 memset(s, 0, sizeof(s));
5658 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
5659 if (m0) {
5660 block_cnt = MIFARE_MINI_MAXBLOCK;
5661 strncpy(s, "Mini", 5);
5662 } else if (m1) {
5663 block_cnt = MIFARE_1K_MAXBLOCK;
5664 strncpy(s, "1K", 3);
5665 } else if (m2) {
5666 block_cnt = MIFARE_2K_MAXBLOCK;
5667 strncpy(s, "2K", 3);
5668 } else if (m4) {
5669 block_cnt = MIFARE_4K_MAXBLOCK;
5670 strncpy(s, "4K", 3);
5671 } else {
5672 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5673 return PM3_EINVARG;
5676 PrintAndLogEx(SUCCESS, "Dumping magic Gen1a MIFARE Classic " _GREEN_("%s") " card memory", s);
5677 PrintAndLogEx(INFO, "." NOLF);
5679 // Select card to get UID/UIDLEN information
5680 clearCommandBuffer();
5681 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
5682 PacketResponseNG resp;
5683 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
5684 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
5685 return PM3_ETIMEOUT;
5689 0: couldn't read
5690 1: OK, with ATS
5691 2: OK, no ATS
5692 3: proprietary Anticollision
5694 uint64_t select_status = resp.oldarg[0];
5695 if (select_status == 0) {
5696 PrintAndLogEx(DEBUG, "iso14443a card select failed");
5697 return PM3_SUCCESS;
5700 // store card info
5701 iso14a_card_select_t card;
5702 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
5704 // reserve memory
5705 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
5706 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
5707 if (dump == NULL) {
5708 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
5709 return PM3_EMALLOC;
5712 // switch on field and send magic sequence
5713 uint8_t flags = MAGIC_INIT + (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
5714 for (uint16_t i = 0; i < block_cnt; i++) {
5716 // read
5717 if (i == 1) {
5718 flags = 0;
5720 // switch off field
5721 if (i == block_cnt - 1) {
5722 flags = MAGIC_HALT + MAGIC_OFF;
5725 if (mf_chinese_get_block(i, dump + (i * MFBLOCK_SIZE), flags)) {
5726 PrintAndLogEx(WARNING, "Can't get magic card block: %d", i);
5727 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
5728 free(dump);
5729 return PM3_ESOFT;
5731 PrintAndLogEx(NORMAL, "." NOLF);
5732 fflush(stdout);
5734 PrintAndLogEx(NORMAL, "");
5736 if (fill_emulator) {
5737 PrintAndLogEx(INFO, "uploading to emulator memory");
5738 PrintAndLogEx(INFO, "." NOLF);
5739 // fast push mode
5740 g_conn.block_after_ACK = true;
5741 for (int i = 0; i < block_cnt; i += 5) {
5742 if (i == block_cnt - 1) {
5743 // Disable fast mode on last packet
5744 g_conn.block_after_ACK = false;
5746 if (mf_elm_set_mem(dump + (i * MFBLOCK_SIZE), i, 5) != PM3_SUCCESS) {
5747 PrintAndLogEx(WARNING, "Can't set emul block: " _YELLOW_("%d"), i);
5749 if (i % 64 == 0) {
5750 PrintAndLogEx(NORMAL, "");
5751 PrintAndLogEx(INFO, "" NOLF) ;
5753 PrintAndLogEx(NORMAL, "." NOLF);
5754 fflush(stdout);
5756 PrintAndLogEx(NORMAL, "");
5757 PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", bytes);
5760 // user supplied filename?
5761 if (fnlen < 1) {
5762 char *fptr = filename;
5763 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
5764 FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
5767 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
5768 free(dump);
5769 return PM3_SUCCESS;
5772 static int CmdHF14AMfCView(const char *Cmd) {
5774 CLIParserContext *ctx;
5775 CLIParserInit(&ctx, "hf mf cview",
5776 "View `magic gen1a` card memory",
5777 "hf mf cview\n"
5778 "hf mf cview --4k"
5780 void *argtable[] = {
5781 arg_param_begin,
5782 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5783 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5784 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5785 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5786 arg_lit0("v", "verbose", "verbose output"),
5787 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
5788 arg_param_end
5790 CLIExecWithReturn(ctx, Cmd, argtable, true);
5791 bool m0 = arg_get_lit(ctx, 1);
5792 bool m1 = arg_get_lit(ctx, 2);
5793 bool m2 = arg_get_lit(ctx, 3);
5794 bool m4 = arg_get_lit(ctx, 4);
5795 bool verbose = arg_get_lit(ctx, 5);
5796 bool gdm = arg_get_lit(ctx, 6);
5797 CLIParserFree(ctx);
5799 // validations
5800 if ((m0 + m1 + m2 + m4) > 1) {
5801 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5802 return PM3_EINVARG;
5803 } else if ((m0 + m1 + m2 + m4) == 0) {
5804 m1 = true;
5807 char s[6];
5808 memset(s, 0, sizeof(s));
5809 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
5810 if (m0) {
5811 block_cnt = MIFARE_MINI_MAXBLOCK;
5812 strncpy(s, "Mini", 5);
5813 } else if (m1) {
5814 block_cnt = MIFARE_1K_MAXBLOCK;
5815 strncpy(s, "1K", 3);
5816 } else if (m2) {
5817 block_cnt = MIFARE_2K_MAXBLOCK;
5818 strncpy(s, "2K", 3);
5819 } else if (m4) {
5820 block_cnt = MIFARE_4K_MAXBLOCK;
5821 strncpy(s, "4K", 3);
5822 } else {
5823 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5824 return PM3_EINVARG;
5826 PrintAndLogEx(SUCCESS, "View magic Gen1a MIFARE Classic " _GREEN_("%s"), s);
5827 PrintAndLogEx(INFO, "." NOLF);
5829 // Select card to get UID/UIDLEN information
5830 clearCommandBuffer();
5831 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
5832 PacketResponseNG resp;
5833 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
5834 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
5835 return PM3_ETIMEOUT;
5839 0: couldn't read
5840 1: OK, with ATS
5841 2: OK, no ATS
5842 3: proprietary Anticollision
5844 uint64_t select_status = resp.oldarg[0];
5846 if (select_status == 0) {
5847 PrintAndLogEx(DEBUG, "iso14443a card select failed");
5848 return PM3_ERFTRANS;
5851 iso14a_card_select_t card;
5852 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
5854 // reserve memory
5855 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
5856 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
5857 if (dump == NULL) {
5858 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
5859 return PM3_EMALLOC;
5862 // switch on field and send magic sequence
5863 uint8_t flags = MAGIC_INIT + (gdm ? MAGIC_GDM_ALT_WUPC : MAGIC_WUPC);
5864 for (uint16_t i = 0; i < block_cnt; i++) {
5865 // read
5866 if (i == 1) {
5867 flags = 0;
5869 // switch off field
5870 if (i == block_cnt - 1) {
5871 flags = MAGIC_HALT + MAGIC_OFF;
5874 if (mf_chinese_get_block(i, dump + (i * MFBLOCK_SIZE), flags)) {
5875 PrintAndLogEx(WARNING, "Can't get magic card block: " _YELLOW_("%u"), i);
5876 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
5877 free(dump);
5878 return PM3_ESOFT;
5880 PrintAndLogEx(NORMAL, "." NOLF);
5881 fflush(stdout);
5884 PrintAndLogEx(NORMAL, "");
5885 mf_print_blocks(block_cnt, dump, verbose);
5887 if (verbose) {
5888 mf_print_keys(block_cnt, dump);
5891 free(dump);
5892 return PM3_SUCCESS;
5895 //needs nt, ar, at, Data to decrypt
5896 static int CmdHf14AMfDecryptBytes(const char *Cmd) {
5897 CLIParserContext *ctx;
5898 CLIParserInit(&ctx, "hf mf decrypt",
5899 "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values",
5900 "hf mf decrypt --nt b830049b --ar 9248314a --at 9280e203 -d 41e586f9\n"
5901 " -> 41e586f9 becomes 3003999a\n"
5902 " -> which annotates 30 03 [99 9a] read block 3 [crc]"
5904 void *argtable[] = {
5905 arg_param_begin,
5906 arg_str1(NULL, "nt", "<hex>", "tag nonce"),
5907 arg_str1(NULL, "ar", "<hex>", "ar_enc, encrypted reader response"),
5908 arg_str1(NULL, "at", "<hex>", "at_enc, encrypted tag response"),
5909 arg_str1("d", "data", "<hex>", "encrypted data, taken directly after at_enc and forward"),
5910 arg_param_end
5912 CLIExecWithReturn(ctx, Cmd, argtable, false);
5914 uint32_t nt = 0;
5915 int res = arg_get_u32_hexstr_def(ctx, 1, 0, &nt);
5916 if (res != 1) {
5917 CLIParserFree(ctx);
5918 PrintAndLogEx(WARNING, "check `nt` parameter");
5919 return PM3_EINVARG;
5922 uint32_t ar_enc = 0;
5923 res = arg_get_u32_hexstr_def(ctx, 2, 0, &ar_enc);
5924 if (res != 1) {
5925 CLIParserFree(ctx);
5926 PrintAndLogEx(WARNING, "check `ar` parameter");
5927 return PM3_EINVARG;
5930 uint32_t at_enc = 0;
5931 res = arg_get_u32_hexstr_def(ctx, 3, 0, &at_enc);
5932 if (res != 1) {
5933 CLIParserFree(ctx);
5934 PrintAndLogEx(WARNING, "check `at` parameter");
5935 return PM3_EINVARG;
5938 int datalen = 0;
5939 uint8_t data[512] = {0x00};
5940 CLIGetHexWithReturn(ctx, 4, data, &datalen);
5941 CLIParserFree(ctx);
5943 PrintAndLogEx(INFO, "nt....... %08X", nt);
5944 PrintAndLogEx(INFO, "ar enc... %08X", ar_enc);
5945 PrintAndLogEx(INFO, "at enc... %08X", at_enc);
5947 return try_decrypt_word(nt, ar_enc, at_enc, data, datalen);
5950 static int CmdHf14AMfSetMod(const char *Cmd) {
5952 CLIParserContext *ctx;
5953 CLIParserInit(&ctx, "hf mf setmod",
5954 "Sets the load modulation strength of a MIFARE Classic EV1 card",
5955 "hf mf setmod -k ffffffffffff -0"
5957 void *argtable[] = {
5958 arg_param_begin,
5959 arg_lit0("0", NULL, "normal modulation"),
5960 arg_lit0("1", NULL, "strong modulation (def)"),
5961 arg_str0("k", "key", "<hex>", "key A, Sector 0, 6 hex bytes"),
5962 arg_param_end
5964 CLIExecWithReturn(ctx, Cmd, argtable, true);
5965 bool m0 = arg_get_lit(ctx, 1);
5966 bool m1 = arg_get_lit(ctx, 2);
5968 int keylen = 0;
5969 uint8_t key[6] = {0};
5970 CLIGetHexWithReturn(ctx, 3, key, &keylen);
5971 CLIParserFree(ctx);
5973 if (m0 + m1 > 1) {
5974 PrintAndLogEx(WARNING, "please select one modulation");
5975 return PM3_EINVARG;
5978 uint8_t data[7] = {0};
5979 memcpy(data + 1, key, 6);
5981 if (m1) {
5982 data[0] = 1;
5983 } else {
5984 data[0] = 0;
5987 clearCommandBuffer();
5988 SendCommandNG(CMD_HF_MIFARE_SETMOD, data, sizeof(data));
5989 PacketResponseNG resp;
5990 if (WaitForResponseTimeout(CMD_HF_MIFARE_SETMOD, &resp, 1500) == false) {
5991 PrintAndLogEx(WARNING, "command execution time out");
5992 return PM3_ETIMEOUT;
5995 if (resp.status == PM3_SUCCESS)
5996 PrintAndLogEx(SUCCESS, "Change ( " _GREEN_("ok") " )");
5997 else
5998 PrintAndLogEx(FAILED, "Change ( " _RED_("fail") " )");
6000 return resp.status;
6003 // MIFARE NACK bug detection
6004 static int CmdHf14AMfNack(const char *Cmd) {
6005 CLIParserContext *ctx;
6006 CLIParserInit(&ctx, "hf mf nack",
6007 "Test a MIFARE Classic based card for the NACK bug",
6008 "hf mf nack"
6010 void *argtable[] = {
6011 arg_param_begin,
6012 arg_lit0("v", "verbose", "verbose output`"),
6013 arg_param_end
6015 CLIExecWithReturn(ctx, Cmd, argtable, true);
6016 bool verbose = arg_get_lit(ctx, 1);
6017 CLIParserFree(ctx);
6019 if (verbose)
6020 PrintAndLogEx(INFO, "Started testing card for NACK bug. Press Enter to abort");
6022 detect_classic_nackbug(verbose);
6023 return PM3_SUCCESS;
6027 static int CmdHF14AMfice(const char *Cmd) {
6028 CLIParserContext *ctx;
6029 CLIParserInit(&ctx, "hf mf ice",
6030 "Collect MIFARE Classic nonces to file",
6031 "hf mf ice\n"
6032 "hf mf ice -f nonces.bin");
6034 void *argtable[] = {
6035 arg_param_begin,
6036 arg_str0("f", "file", "<fn>", "filename of nonce dump"),
6037 arg_u64_0(NULL, "limit", "<dec>", "nonces to be collected"),
6038 arg_param_end
6040 CLIExecWithReturn(ctx, Cmd, argtable, true);
6042 int fnlen = 0;
6043 char filename[FILE_PATH_SIZE] = {0};
6044 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6046 uint32_t limit = arg_get_u32_def(ctx, 2, 50000);
6048 CLIParserFree(ctx);
6050 // Validations
6051 char *fptr;
6053 if (filename[0] == '\0') {
6054 fptr = GenerateFilename("hf-mf-", "-nonces.bin");
6055 if (fptr == NULL)
6056 return PM3_EFILE;
6057 strncpy(filename, fptr, sizeof(filename) - 1);
6058 free(fptr);
6061 uint8_t blockNo = 0;
6062 uint8_t keyType = MF_KEY_A;
6063 uint8_t trgBlockNo = 0;
6064 uint8_t trgKeyType = MF_KEY_B;
6065 bool slow = false;
6066 bool initialize = true;
6067 bool acquisition_completed = false;
6068 uint32_t total_num_nonces = 0;
6069 PacketResponseNG resp;
6071 uint32_t part_limit = 3000;
6073 PrintAndLogEx(NORMAL, "Collecting "_YELLOW_("%u")" nonces \n", limit);
6075 FILE *fnonces = NULL;
6076 if ((fnonces = fopen(filename, "wb")) == NULL) {
6077 PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), filename);
6078 return PM3_EFILE;
6081 clearCommandBuffer();
6083 uint64_t t1 = msclock();
6085 do {
6086 if (kbd_enter_pressed()) {
6087 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
6088 break;
6091 uint32_t flags = 0;
6092 flags |= initialize ? 0x0001 : 0;
6093 flags |= slow ? 0x0002 : 0;
6094 clearCommandBuffer();
6095 SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, NULL, 0);
6097 if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out;
6098 if (resp.oldarg[0]) goto out;
6100 uint32_t items = resp.oldarg[2];
6101 fwrite(resp.data.asBytes, 1, items * 4, fnonces);
6102 fflush(fnonces);
6104 total_num_nonces += items;
6105 if (total_num_nonces > part_limit) {
6106 PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces);
6107 part_limit += 3000;
6110 acquisition_completed = (total_num_nonces > limit);
6112 initialize = false;
6114 } while (!acquisition_completed);
6116 out:
6117 PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock() - t1) / 1000);
6119 if (fnonces) {
6120 fflush(fnonces);
6121 fclose(fnonces);
6124 clearCommandBuffer();
6125 SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, NULL, 0);
6126 return PM3_SUCCESS;
6130 static int CmdHF14AMfAuth4(const char *Cmd) {
6131 uint8_t keyn[20] = {0};
6132 int keynlen = 0;
6133 uint8_t key[16] = {0};
6134 int keylen = 0;
6136 CLIParserContext *ctx;
6137 CLIParserInit(&ctx, "hf mf auth4",
6138 "Executes AES authentication command in ISO14443-4",
6139 "hf mf auth4 -n 4000 -k 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
6140 "hf mf auth4 -n 9003 -k FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n");
6142 void *argtable[] = {
6143 arg_param_begin,
6144 arg_str1("n", NULL, "<hex>", "key num, 2 hex bytes"),
6145 arg_str1("k", "key", "<hex>", "key, 16 hex bytes"),
6146 arg_param_end
6148 CLIExecWithReturn(ctx, Cmd, argtable, true);
6149 CLIGetHexWithReturn(ctx, 1, keyn, &keynlen);
6150 CLIGetHexWithReturn(ctx, 2, key, &keylen);
6151 CLIParserFree(ctx);
6153 if (keynlen != 2) {
6154 PrintAndLogEx(ERR, "Key number must be 2 bytes. Got... %d", keynlen);
6155 return PM3_ESOFT;
6158 if (keylen != 16) {
6159 PrintAndLogEx(ERR, "Key must be 16 bytes. Got... %d", keylen);
6160 return PM3_ESOFT;
6163 return MifareAuth4(NULL, keyn, key, true, false, true, true, false);
6166 // https://www.nxp.com/docs/en/application-note/AN10787.pdf
6167 static int CmdHF14AMfMAD(const char *Cmd) {
6169 CLIParserContext *ctx;
6170 CLIParserInit(&ctx, "hf mf mad",
6171 "Checks and prints MIFARE Application Directory (MAD)",
6172 "hf mf mad -> shows MAD if exists\n"
6173 "hf mf mad --aid e103 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"
6174 "hf mf mad --dch -k ffffffffffff -> decode CardHolder information\n");
6176 void *argtable[] = {
6177 arg_param_begin,
6178 arg_lit0("v", "verbose", "verbose output"),
6179 arg_str0(NULL, "aid", "<hex>", "print all sectors with specified aid"),
6180 arg_str0("k", "key", "<hex>", "key for printing sectors"),
6181 arg_lit0("b", "keyb", "use key B for access printing sectors (by default: key A)"),
6182 arg_lit0(NULL, "be", "(optional, BigEndian)"),
6183 arg_lit0(NULL, "dch", "decode Card Holder information"),
6184 arg_str0("f", "file", "<fn>", "load dump file and decode MAD"),
6185 arg_lit0(NULL, "force", "force decode (skip key check)"),
6186 arg_param_end
6188 CLIExecWithReturn(ctx, Cmd, argtable, true);
6189 bool verbose = arg_get_lit(ctx, 1);
6190 uint8_t aid[2] = {0};
6191 int aidlen = 0;
6192 CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
6193 uint8_t userkey[6] = {0};
6194 int keylen = 0;
6195 CLIGetHexWithReturn(ctx, 3, userkey, &keylen);
6196 bool keyB = arg_get_lit(ctx, 4);
6197 bool swapmad = arg_get_lit(ctx, 5);
6198 bool decodeholder = arg_get_lit(ctx, 6);
6199 bool force = arg_get_lit(ctx, 8);
6201 int fnlen = 0;
6202 char filename[FILE_PATH_SIZE] = {0};
6203 CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6204 CLIParserFree(ctx);
6206 if (fnlen > 0) {
6208 // read dump file
6209 uint8_t *dump = NULL;
6210 size_t bytes_read = 0;
6211 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, MIFARE_4K_MAX_BYTES);
6212 if (res != PM3_SUCCESS) {
6213 return res;
6216 uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE));
6217 if (bytes_read == MIFARE_MINI_MAX_BYTES)
6218 block_cnt = MIFARE_MINI_MAXBLOCK;
6219 else if (bytes_read == MIFARE_2K_MAX_BYTES)
6220 block_cnt = MIFARE_2K_MAXBLOCK;
6221 else if (bytes_read == MIFARE_4K_MAX_BYTES)
6222 block_cnt = MIFARE_4K_MAXBLOCK;
6224 if (verbose) {
6225 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
6228 // MAD detection
6229 if ((HasMADKey(dump) == false) && (force == false)) {
6230 PrintAndLogEx(FAILED, "No MAD key was detected in the dump file");
6231 free(dump);
6232 return PM3_ESOFT;
6235 MADPrintHeader();
6236 bool haveMAD2 = false;
6237 MAD1DecodeAndPrint(dump, swapmad, verbose, &haveMAD2);
6239 int sector = DetectHID(dump, 0x484d);
6240 if (sector > -1) {
6242 // decode it
6243 PrintAndLogEx(INFO, "");
6244 PrintAndLogEx(INFO, _CYAN_("HID PACS detected"));
6246 uint8_t pacs_sector[MFBLOCK_SIZE * 3] = {0};
6247 memcpy(pacs_sector, dump + (sector * 4 * 16), sizeof(pacs_sector));
6249 if (pacs_sector[16] == 0x02) {
6251 PrintAndLogEx(SUCCESS, "Raw...... " _GREEN_("%s"), sprint_hex_inrow(pacs_sector + 24, 8));
6253 //todo: remove preamble/sentinel
6254 uint32_t top = 0, mid = 0, bot = 0;
6255 char hexstr[16 + 1] = {0};
6256 hex_to_buffer((uint8_t *)hexstr, pacs_sector + 24, 8, sizeof(hexstr) - 1, 0, 0, true);
6257 hexstring_to_u96(&top, &mid, &bot, hexstr);
6259 char binstr[64 + 1];
6260 hextobinstring(binstr, hexstr);
6261 char *pbin = binstr;
6262 while (strlen(pbin) && *(++pbin) == '0');
6264 PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s"), pbin);
6266 PrintAndLogEx(INFO, "Wiegand decode");
6267 wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
6268 HIDTryUnpack(&packed);
6272 sector = DetectHID(dump, 0x4910);
6273 if (sector > -1) {
6274 // decode it
6275 PrintAndLogEx(INFO, "");
6276 PrintAndLogEx(INFO, _CYAN_("VIGIK PACS detected"));
6279 if (haveMAD2) {
6280 MAD2DecodeAndPrint(dump + (MIFARE_1K_MAXBLOCK * MF_MAD2_SECTOR), swapmad, verbose);
6283 if (aidlen == 2 || decodeholder) {
6284 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6285 size_t madlen = 0;
6286 if (MADDecode(dump, dump + (0x10 * MIFARE_1K_MAXBLOCK), mad, &madlen, swapmad)) {
6287 PrintAndLogEx(ERR, "can't decode MAD");
6288 free(dump);
6289 return PM3_ESOFT;
6292 uint16_t aaid = 0x0004;
6293 if (aidlen == 2) {
6294 aaid = (aid[0] << 8) + aid[1];
6297 PrintAndLogEx(NORMAL, "");
6298 PrintAndLogEx(INFO, "-------- " _CYAN_("Card Holder Info 0x%04x") " --------", aaid);
6300 MADCardHolderInfoDecode(dump, bytes_read, verbose);
6302 free(dump);
6303 return PM3_SUCCESS;
6306 if (g_session.pm3_present == false)
6307 return PM3_ENOTTY;
6310 uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
6311 uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
6313 bool got_first = true;
6314 if (mf_read_sector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0) != PM3_SUCCESS) {
6315 PrintAndLogEx(WARNING, "error, read sector 0. card doesn't have MAD or doesn't have MAD on default keys");
6316 got_first = false;
6317 } else {
6318 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6321 // User supplied key
6322 if (got_first == false && keylen == 6) {
6323 PrintAndLogEx(INFO, "Trying user specified key...");
6324 if (mf_read_sector(MF_MAD1_SECTOR, MF_KEY_A, userkey, sector0) != PM3_SUCCESS) {
6325 PrintAndLogEx(ERR, "error, read sector 0. card doesn't have MAD or the custom key is wrong");
6326 } else {
6327 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6328 got_first = true;
6332 // Both default and user supplied key failed
6333 if (got_first == false) {
6334 return PM3_ESOFT;
6337 got_first = true;
6338 if (mf_read_sector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10) != PM3_SUCCESS) {
6339 if (verbose) {
6340 PrintAndLogEx(ERR, "error, read sector 0x10. card doesn't have MAD 2 or doesn't have MAD 2 on default keys");
6342 got_first = false;
6343 } else {
6344 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6347 // User supplied key
6348 if (got_first == false && keylen == 6) {
6349 PrintAndLogEx(INFO, "Trying user specified key...");
6350 if (mf_read_sector(MF_MAD2_SECTOR, MF_KEY_A, userkey, sector10) != PM3_SUCCESS) {
6351 if (verbose) {
6352 PrintAndLogEx(ERR, "error, read sector 10. card doesn't have MAD 2 or the custom key is wrong");
6354 } else {
6355 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6359 MADPrintHeader();
6361 bool haveMAD2 = false;
6362 MAD1DecodeAndPrint(sector0, swapmad, verbose, &haveMAD2);
6364 if (haveMAD2) {
6365 MAD2DecodeAndPrint(sector10, swapmad, verbose);
6368 if (aidlen == 2 || decodeholder) {
6369 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6370 size_t madlen = 0;
6371 if (MADDecode(sector0, sector10, mad, &madlen, swapmad)) {
6372 PrintAndLogEx(ERR, "can't decode MAD");
6373 return PM3_ESOFT;
6376 // copy default NDEF key
6377 uint8_t akey[6] = {0};
6378 memcpy(akey, g_mifare_ndef_key, 6);
6380 // user specified key
6381 if (keylen == 6) {
6382 memcpy(akey, userkey, sizeof(akey));
6385 uint16_t aaid = 0x0004;
6386 if (aidlen == 2) {
6388 aaid = (aid[0] << 8) + aid[1];
6390 PrintAndLogEx(NORMAL, "");
6391 PrintAndLogEx(INFO, "-------------- " _CYAN_("AID 0x%04x") " ---------------", aaid);
6393 for (int i = 0; i < madlen; i++) {
6394 if (aaid == mad[i]) {
6395 uint8_t vsector[MFBLOCK_SIZE * 4] = {0};
6396 if (mf_read_sector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
6397 PrintAndLogEx(NORMAL, "");
6398 PrintAndLogEx(ERR, "error, read sector %d", i + 1);
6399 return PM3_ESOFT;
6402 for (int j = 0; j < (verbose ? 4 : 3); j ++)
6403 PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * MFBLOCK_SIZE], MFBLOCK_SIZE));
6408 if (decodeholder) {
6410 PrintAndLogEx(NORMAL, "");
6411 PrintAndLogEx(INFO, "-------- " _CYAN_("Card Holder Info 0x%04x") " --------", aaid);
6413 uint8_t data[MIFARE_4K_MAX_BYTES] = {0};
6414 int datalen = 0;
6416 for (int i = 0; i < madlen; i++) {
6417 if (aaid == mad[i]) {
6419 uint8_t vsector[MFBLOCK_SIZE * 4] = {0};
6420 if (mf_read_sector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
6421 PrintAndLogEx(NORMAL, "");
6422 PrintAndLogEx(ERR, "error, read sector %d", i + 1);
6423 return PM3_ESOFT;
6426 // skip ST block hence only 3 blocks copy
6427 memcpy(&data[datalen], vsector, MFBLOCK_SIZE * 3);
6428 datalen += MFBLOCK_SIZE * 3;
6432 if (!datalen) {
6433 PrintAndLogEx(WARNING, "no Card Holder Info data");
6434 return PM3_SUCCESS;
6436 MADCardHolderInfoDecode(data, datalen, verbose);
6440 if (verbose) {
6441 PrintAndLogEx(NORMAL, "");
6442 PrintAndLogEx(INFO, "------------ " _CYAN_("MAD v1 sector raw") " -------------");
6443 for (int i = 0; i < 4; i ++) {
6444 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex(&sector0[i * MFBLOCK_SIZE], MFBLOCK_SIZE));
6447 PrintAndLogEx(NORMAL, "");
6448 PrintAndLogEx(INFO, "------------ " _CYAN_("MAD v2 sector raw") " -------------");
6449 for (int i = 0; i < 4; i ++) {
6450 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex(&sector10[i * MFBLOCK_SIZE], MFBLOCK_SIZE));
6454 return PM3_SUCCESS;
6457 int CmdHFMFNDEFRead(const char *Cmd) {
6459 CLIParserContext *ctx;
6460 CLIParserInit(&ctx, "hf mf ndefread",
6461 "Prints NFC Data Exchange Format (NDEF)",
6462 "hf mf ndefread -> shows NDEF parsed data\n"
6463 "hf mf ndefread -vv -> shows NDEF parsed and raw data\n"
6464 "hf mf ndefread --aid e103 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"
6465 "hf mf ndefread -f myfilename -> save raw NDEF to file"
6468 void *argtable[] = {
6469 arg_param_begin,
6470 arg_litn("v", "verbose", 0, 2, "Verbose output"),
6471 arg_str0(NULL, "aid", "<aid>", "replace default aid for NDEF"),
6472 arg_str0("k", "key", "<key>", "replace default key for NDEF"),
6473 arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"),
6474 arg_str0("f", "file", "<fn>", "save raw NDEF to file"),
6475 arg_param_end
6477 CLIExecWithReturn(ctx, Cmd, argtable, true);
6479 bool verbose = arg_get_lit(ctx, 1);
6480 bool verbose2 = arg_get_lit(ctx, 1) > 1;
6481 uint8_t aid[2] = {0};
6483 int aidlen;
6484 CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
6485 uint8_t key[6] = {0};
6487 int keylen;
6488 CLIGetHexWithReturn(ctx, 3, key, &keylen);
6489 bool keyB = arg_get_lit(ctx, 4);
6491 int fnlen = 0;
6492 char filename[FILE_PATH_SIZE] = {0};
6493 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6495 CLIParserFree(ctx);
6497 uint16_t ndef_aid = NDEF_MFC_AID;
6498 if (aidlen == 2) {
6499 ndef_aid = (aid[0] << 8) + aid[1];
6502 uint8_t ndefkey[6] = {0};
6503 memcpy(ndefkey, g_mifare_ndef_key, 6);
6504 if (keylen == 6) {
6505 memcpy(ndefkey, key, 6);
6508 uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
6509 uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
6510 uint8_t data[4096] = {0};
6511 int datalen = 0;
6513 if (verbose) {
6514 PrintAndLogEx(INFO, "reading MAD v1 sector");
6517 if (mf_read_sector(MF_MAD1_SECTOR, MF_KEY_A, g_mifare_mad_key, sector0)) {
6518 PrintAndLogEx(ERR, "error, read sector 0. card doesn't have MAD or doesn't have MAD on default keys");
6519 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -k `") " with your custom key");
6520 return PM3_ESOFT;
6523 if (verbose) {
6524 PrintAndLogEx(INFO, "reading MAD v2 sector");
6527 if (mf_read_sector(MF_MAD2_SECTOR, MF_KEY_A, g_mifare_mad_key, sector10)) {
6528 if (verbose) {
6529 PrintAndLogEx(ERR, "error, read sector 0x10. card doesn't have MAD 2 or doesn't have MAD 2 on default keys");
6530 PrintAndLogEx(INFO, "Skipping MAD 2");
6534 bool haveMAD2 = false;
6535 int res = MADCheck(sector0, sector10, verbose, &haveMAD2);
6536 if (res != PM3_SUCCESS) {
6537 PrintAndLogEx(ERR, "MAD error %d", res);
6538 return res;
6541 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6542 size_t madlen = 0;
6543 res = MADDecode(sector0, sector10, mad, &madlen, false);
6544 if (res != PM3_SUCCESS) {
6545 PrintAndLogEx(ERR, "can't decode MAD");
6546 return res;
6549 PrintAndLogEx(INFO, "reading data from tag");
6550 for (int i = 0; i < madlen; i++) {
6551 if (ndef_aid == mad[i]) {
6552 uint8_t vsector[MFBLOCK_SIZE * 4] = {0};
6553 if (mf_read_sector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) {
6554 PrintAndLogEx(ERR, "error, reading sector %d ", i + 1);
6555 return PM3_ESOFT;
6558 memcpy(&data[datalen], vsector, MFBLOCK_SIZE * 3);
6559 datalen += MFBLOCK_SIZE * 3;
6561 PrintAndLogEx(INPLACE, "%d", i);
6564 PrintAndLogEx(NORMAL, "");
6566 if (datalen == 0) {
6567 PrintAndLogEx(WARNING, "no NDEF data");
6568 return PM3_SUCCESS;
6571 if (verbose2) {
6572 PrintAndLogEx(NORMAL, "");
6573 PrintAndLogEx(INFO, "--- " _CYAN_("MFC NDEF raw") " ----------------");
6574 print_buffer(data, datalen, 1);
6577 res = NDEFDecodeAndPrint(data, datalen, verbose);
6578 if (res != PM3_SUCCESS) {
6579 PrintAndLogEx(INFO, "Trying to parse NDEF records w/o NDEF header");
6580 res = NDEFRecordsDecodeAndPrint(data, datalen, verbose);
6583 // if given a filename, save it
6584 if (fnlen) {
6585 // get total NDEF length before save. If fails, we save it all
6586 size_t n = 0;
6587 if (NDEFGetTotalLength(data, datalen, &n) != PM3_SUCCESS) {
6588 n = datalen;
6591 pm3_save_dump(filename, data, n, jsfNDEF);
6594 if (verbose == false) {
6595 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -v`") " for more details");
6596 } else {
6597 if (verbose2 == false) {
6598 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -vv`") " for more details");
6601 return PM3_SUCCESS;
6604 // https://www.nxp.com/docs/en/application-note/AN1305.pdf
6605 int CmdHFMFNDEFFormat(const char *Cmd) {
6607 CLIParserContext *ctx;
6608 CLIParserInit(&ctx, "hf mf ndefformat",
6609 "format MIFARE Classic Tag as a NFC tag with Data Exchange Format (NDEF)\n"
6610 "If no <name> given, UID will be used as filename. \n"
6611 "It will try default keys and MAD keys to detect if tag is already formatted in order to write.\n"
6612 "\n"
6613 "If not, it will try finding a key file based on your UID. ie, if you ran autopwn before",
6614 "hf mf ndefformat\n"
6615 // "hf mf ndefformat --mini --> MIFARE Mini\n"
6616 "hf mf ndefformat --1k --> MIFARE Classic 1k\n"
6617 // "hf mf ndefformat --2k --> MIFARE 2k\n"
6618 // "hf mf ndefformat --4k --> MIFARE 4k\n"
6619 "hf mf ndefformat --keys hf-mf-01020304-key.bin --> MIFARE 1k with keys from specified file\n"
6622 void *argtable[] = {
6623 arg_param_begin,
6624 arg_str0("k", "keys", "<fn>", "filename of keys"),
6625 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
6626 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
6627 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
6628 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
6629 arg_param_end
6631 CLIExecWithReturn(ctx, Cmd, argtable, true);
6633 int keyfnlen = 0;
6634 char keyFilename[FILE_PATH_SIZE] = {0};
6635 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
6637 bool m0 = arg_get_lit(ctx, 2);
6638 bool m1 = arg_get_lit(ctx, 3);
6639 bool m2 = arg_get_lit(ctx, 4);
6640 bool m4 = arg_get_lit(ctx, 5);
6642 CLIParserFree(ctx);
6644 // validations
6645 if ((m0 + m1 + m2 + m4) > 1) {
6646 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
6647 return PM3_EINVARG;
6648 } else if ((m0 + m1 + m2 + m4) == 0) {
6649 m1 = true;
6652 uint8_t numSectors = MIFARE_1K_MAXSECTOR;
6654 if (m0) {
6655 numSectors = MIFARE_MINI_MAXSECTOR;
6656 } else if (m1) {
6657 numSectors = MIFARE_1K_MAXSECTOR;
6658 } else if (m2) {
6659 numSectors = MIFARE_2K_MAXSECTOR;
6660 } else if (m4) {
6661 numSectors = MIFARE_4K_MAXSECTOR;
6662 } else {
6663 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
6664 return PM3_EINVARG;
6668 if (g_session.pm3_present == false)
6669 return PM3_ENOTTY;
6671 // Select card to get UID/UIDLEN/ATQA/SAK information
6672 clearCommandBuffer();
6673 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
6674 PacketResponseNG resp;
6675 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
6676 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
6677 return PM3_ETIMEOUT;
6680 uint64_t select_status = resp.oldarg[0];
6681 if (select_status == 0) {
6682 PrintAndLogEx(DEBUG, "iso14443a card select failed");
6683 return PM3_SUCCESS;
6686 DropField();
6689 // init keys to default key
6690 uint8_t keyA[MIFARE_4K_MAXSECTOR][MIFARE_KEY_SIZE];
6691 uint8_t keyB[MIFARE_4K_MAXSECTOR][MIFARE_KEY_SIZE];
6693 for (uint8_t i = 0; i < MIFARE_4K_MAXSECTOR; i++) {
6694 memcpy(keyA[i], g_mifare_default_key, sizeof(g_mifare_default_key));
6695 memcpy(keyB[i], g_mifare_default_key, sizeof(g_mifare_default_key));
6698 // test if MAD key is used
6699 uint64_t key64 = 0;
6701 // check if we can authenticate to sector
6702 if (mf_check_keys(0, MF_KEY_A, true, 1, (uint8_t *)g_mifare_mad_key, &key64) == PM3_SUCCESS) {
6704 // if used, assume KEY A is MAD/NDEF set.
6705 memcpy(keyA[0], g_mifare_mad_key, sizeof(g_mifare_mad_key));
6706 memcpy(keyB[0], g_mifare_mad_key_b, sizeof(g_mifare_mad_key_b));
6707 for (uint8_t i = 1; i < MIFARE_4K_MAXSECTOR; i++) {
6708 memcpy(keyA[i], g_mifare_ndef_key, sizeof(g_mifare_ndef_key));
6712 // Do we have a keyfile based from UID?
6713 if (keyfnlen == 0) {
6714 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
6715 if (fptr) {
6716 strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
6718 free(fptr);
6719 DropField();
6722 // load key file if exist
6723 if (strlen(keyFilename)) {
6725 size_t alen = 0, blen = 0;
6726 uint8_t *tmpA, *tmpB;
6727 if (loadFileBinaryKey(keyFilename, "", (void **)&tmpA, (void **)&tmpB, &alen, &blen) != PM3_SUCCESS) {
6728 goto skipfile;
6731 PrintAndLogEx(INFO, "Using `" _YELLOW_("%s") "`", keyFilename);
6733 for (int i = 0; i < numSectors; i++) {
6734 memcpy(keyA[i], tmpA + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
6735 memcpy(keyB[i], tmpB + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
6737 free(tmpA);
6738 free(tmpB);
6741 skipfile:
6744 uint8_t firstblocks[8][16] = {
6745 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6746 { 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 },
6747 { 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 },
6748 { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A },
6749 { 0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6750 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6751 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6752 { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
6755 // main loop
6756 for (int i = 0; i < numSectors; i++) {
6757 for (int j = 0; j < mfNumBlocksPerSector(j); j++) {
6759 uint8_t b = (mfFirstBlockOfSector(i) + j);
6760 uint8_t block[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
6762 switch (b) {
6763 case 0:
6764 continue;
6765 case 1:
6766 case 2:
6767 case 3:
6768 case 4:
6769 case 5:
6770 case 6:
6771 case 7:
6772 memcpy(block, firstblocks[b], MFBLOCK_SIZE);
6773 break;
6774 default: {
6775 if (mfIsSectorTrailerBasedOnBlocks(i, j)) {
6776 // ST NDEF
6777 memcpy(block, firstblocks[7], MFBLOCK_SIZE);
6779 break;
6783 // write to card, try B key first
6784 if (mf_write_block(b, MF_KEY_B, keyB[i], block) != PM3_SUCCESS) {
6785 // try A key,
6786 if (mf_write_block(b, MF_KEY_A, keyA[i], block) != PM3_SUCCESS) {
6787 return PM3_EFAILED;
6790 PrintAndLogEx(INPLACE, "Formatting block %u", b);
6794 PrintAndLogEx(NORMAL, "");
6795 return PM3_SUCCESS;
6798 int CmdHFMFNDEFWrite(const char *Cmd) {
6800 CLIParserContext *ctx;
6801 CLIParserInit(&ctx, "hf mf ndefwrite",
6802 "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n",
6803 "hf mf ndefwrite -d 0300FE -> write empty record to tag\n"
6804 "hf mf ndefwrite -f myfilename\n"
6805 "hf mf ndefwrite -d 033fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\n"
6808 void *argtable[] = {
6809 arg_param_begin,
6810 arg_str0("d", NULL, "<hex>", "raw NDEF hex bytes"),
6811 arg_str0("f", "file", "<fn>", "write raw NDEF file to tag"),
6812 arg_lit0("p", NULL, "fix NDEF record headers / terminator block if missing"),
6813 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
6814 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
6815 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
6816 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
6817 arg_lit0("v", "verbose", "verbose output"),
6818 arg_param_end
6820 CLIExecWithReturn(ctx, Cmd, argtable, false);
6822 uint8_t raw[4096] = {0};
6823 int rawlen;
6824 CLIGetHexWithReturn(ctx, 1, raw, &rawlen);
6826 int fnlen = 0;
6827 char filename[FILE_PATH_SIZE] = {0};
6828 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6830 bool fix_msg = arg_get_lit(ctx, 3);
6832 bool m0 = arg_get_lit(ctx, 4);
6833 bool m1 = arg_get_lit(ctx, 5);
6834 bool m2 = arg_get_lit(ctx, 6);
6835 bool m4 = arg_get_lit(ctx, 7);
6836 bool verbose = arg_get_lit(ctx, 8);
6838 CLIParserFree(ctx);
6840 // validations
6841 if ((m0 + m1 + m2 + m4) > 1) {
6842 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
6843 return PM3_EINVARG;
6844 } else if ((m0 + m1 + m2 + m4) == 0) {
6845 m1 = true;
6848 uint8_t numSectors = MIFARE_1K_MAXSECTOR;
6850 if (m0) {
6851 numSectors = MIFARE_MINI_MAXSECTOR;
6852 } else if (m1) {
6853 numSectors = MIFARE_1K_MAXSECTOR;
6854 } else if (m2) {
6855 numSectors = MIFARE_2K_MAXSECTOR;
6856 } else if (m4) {
6857 numSectors = MIFARE_4K_MAXSECTOR;
6858 } else {
6859 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
6860 return PM3_EINVARG;
6863 if (verbose) {
6864 PrintAndLogEx(INFO, "Number of sectors selected: %u", numSectors);
6867 if (g_session.pm3_present == false) {
6868 PrintAndLogEx(FAILED, "No Proxmark3 device present");
6869 return PM3_ENOTTY;
6872 if ((rawlen && fnlen) || (rawlen == 0 && fnlen == 0)) {
6873 PrintAndLogEx(WARNING, "Please specify either raw hex or filename");
6874 return PM3_EINVARG;
6877 // test if MAD key is used
6878 uint64_t key64 = 0;
6880 // check if we can authenticate to sector
6881 int res = mf_check_keys(0, MF_KEY_A, true, 1, (uint8_t *)g_mifare_mad_key, &key64);
6882 if (res != PM3_SUCCESS) {
6883 PrintAndLogEx(FAILED, "Sector 0 failed to authenticate with MAD default key");
6884 PrintAndLogEx(HINT, "Verify that the tag NDEF formatted");
6885 return res;
6888 // NDEF for MIFARE CLASSIC has different memory size available.
6890 int32_t bytes = rawlen;
6892 // read dump file
6893 if (fnlen) {
6894 uint8_t *dump = NULL;
6895 size_t bytes_read = 0;
6896 res = pm3_load_dump(filename, (void **)&dump, &bytes_read, sizeof(raw));
6897 if (res != PM3_SUCCESS) {
6898 return res;
6900 memcpy(raw, dump, bytes_read);
6901 bytes = bytes_read;
6902 free(dump);
6905 // Has raw bytes ndef message header?bytes
6906 switch (raw[0]) {
6907 case 0x00:
6908 case 0x01:
6909 case 0x02:
6910 case 0x03:
6911 case 0xFD:
6912 case 0xFE:
6913 break;
6914 default: {
6915 if (fix_msg == false) {
6916 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a proper header, continuing...");
6917 } else {
6918 if (bytes + 2 > sizeof(raw)) {
6919 PrintAndLogEx(WARNING, "no room for header, exiting...");
6920 return PM3_EMALLOC;
6922 uint8_t tmp_raw[4096];
6923 memcpy(tmp_raw, raw, sizeof(tmp_raw));
6924 raw[0] = 0x03;
6925 raw[1] = bytes;
6926 memcpy(raw + 2, tmp_raw, sizeof(raw) - 2);
6927 bytes += 2;
6928 PrintAndLogEx(SUCCESS, "Added generic message header (0x03)");
6933 // Has raw bytes ndef a terminator block?
6934 if (raw[bytes - 1] != 0xFE) {
6935 if (fix_msg == false) {
6936 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a terminator block, continuing...");
6937 } else {
6939 if (bytes + 1 > sizeof(raw)) {
6940 PrintAndLogEx(WARNING, "no room for terminator block, exiting...");
6941 return PM3_EMALLOC;
6943 raw[bytes] = 0xFE;
6944 bytes++;
6945 PrintAndLogEx(SUCCESS, "Added terminator block (0xFE)");
6949 if (verbose) {
6950 PrintAndLogEx(INFO, "Num of Bytes... %u", bytes);
6951 print_buffer(raw, bytes, 0);
6954 // read MAD Sector 0, block1,2
6955 uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
6956 if (mf_read_sector(MF_MAD1_SECTOR, MF_KEY_A, g_mifare_mad_key, sector0)) {
6957 PrintAndLogEx(ERR, "error, reading sector 0. Card doesn't have MAD or doesn't have MAD on default keys");
6958 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -k `") " with your custom key");
6959 return PM3_ESOFT;
6962 // read MAD Sector 10, block1,2
6963 uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
6964 if (m4) {
6965 if (mf_read_sector(MF_MAD2_SECTOR, MF_KEY_A, g_mifare_mad_key, sector10)) {
6966 PrintAndLogEx(ERR, "error, reading sector 10. Card doesn't have MAD or doesn't have MAD on default keys");
6967 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -k `") " with your custom key");
6968 return PM3_ESOFT;
6972 // decode MAD v1
6973 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6974 size_t madlen = 0;
6975 res = MADDecode(sector0, sector10, mad, &madlen, false);
6976 if (res != PM3_SUCCESS) {
6977 PrintAndLogEx(ERR, "can't decode MAD");
6978 return res;
6981 // how much memory do I have available ?
6982 // Skip sector 0 since its used for MAD
6983 uint8_t freemem[MIFARE_4K_MAXSECTOR] = {0};
6984 uint16_t sum = 0;
6985 uint8_t block_no = 0;
6986 for (uint8_t i = 1; i < (madlen & 0xFF); i++) {
6988 freemem[i] = (mad[i] == NDEF_MFC_AID);
6990 if (freemem[i]) {
6992 if (block_no == 0) {
6993 block_no = mfFirstBlockOfSector(i);
6996 if (verbose) {
6997 PrintAndLogEx(INFO, "Sector %u is NDEF formatted", i);
6999 sum += (MFBLOCK_SIZE * 3);
7003 if (verbose) {
7004 PrintAndLogEx(INFO, "Total avail ndef mem... %u", sum);
7005 PrintAndLogEx(INFO, "First block............ %u", block_no);
7008 if (sum < bytes) {
7009 PrintAndLogEx(WARNING, "Raw NDEF message is larger than available NDEF formatted memory");
7010 return PM3_EINVARG;
7013 // main loop - write blocks
7014 uint8_t *ptr_raw = raw;
7015 while (bytes > 0) {
7017 uint8_t block[MFBLOCK_SIZE] = { 0x00 };
7019 if (bytes < MFBLOCK_SIZE) {
7020 memcpy(block, ptr_raw, bytes);
7021 } else {
7022 memcpy(block, ptr_raw, MFBLOCK_SIZE);
7023 ptr_raw += MFBLOCK_SIZE;
7026 // write to card, try B key first
7027 if (mf_write_block(block_no, MF_KEY_B, g_mifare_default_key, block) != PM3_SUCCESS) {
7029 // try A key,
7031 if (mf_write_block(block_no, MF_KEY_A, g_mifare_ndef_key, block) != PM3_SUCCESS) {
7032 return PM3_EFAILED;
7036 PrintAndLogEx(INPLACE, "%u", block_no);
7038 // find next available block
7039 block_no++;
7041 if (mfIsSectorTrailer(block_no)) {
7042 block_no++;
7043 // skip sectors which isn't ndef formatted
7044 while (freemem[mfSectorNum(block_no)] == 0) {
7045 block_no++;
7049 bytes -= MFBLOCK_SIZE;
7052 PrintAndLogEx(NORMAL, "");
7053 return PM3_SUCCESS;
7056 static int CmdHFMFPersonalize(const char *Cmd) {
7057 CLIParserContext *ctx;
7058 CLIParserInit(&ctx, "hf mf personalize",
7059 "Personalize the UID of a MIFARE Classic EV1 card. This is only possible \n"
7060 "if it is a 7Byte UID card and if it is not already personalized.",
7061 "hf mf personalize --f0 -> double size UID\n"
7062 "hf mf personalize --f1 -> double size UID, optional usage of selection process shortcut\n"
7063 "hf mf personalize --f2 -> single size random ID\n"
7064 "hf mf personalize --f3 -> single size NUID\n"
7065 "hf mf personalize -b -k B0B1B2B3B4B5 --f3 -> use key B = 0xB0B1B2B3B4B5"
7068 void *argtable[] = {
7069 arg_param_begin,
7070 arg_lit0("a", NULL, "use key A to authenticate sector 0 (def)"),
7071 arg_lit0("b", NULL, "use key B to authenticate sector 0"),
7072 arg_str0("k", "key", "<hex>", "key (def FFFFFFFFFFFF)"),
7073 arg_lit0(NULL, "f0", "UIDFO, double size UID"),
7074 arg_lit0(NULL, "f1", "UIDF1, double size UID, optional usage of selection process shortcut"),
7075 arg_lit0(NULL, "f2", "UIDF2, single size random ID"),
7076 arg_lit0(NULL, "f3", "UIDF3, single size NUID"),
7077 arg_param_end
7079 CLIExecWithReturn(ctx, Cmd, argtable, true);
7081 bool use_a = arg_get_lit(ctx, 1);
7082 bool use_b = arg_get_lit(ctx, 2);
7084 if (use_a + use_b > 1) {
7085 PrintAndLogEx(ERR, "error, use only one key type");
7086 CLIParserFree(ctx);
7087 return PM3_EINVARG;
7090 uint8_t keytype = 0;
7091 if (use_b) {
7092 keytype = 1;
7095 uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
7096 int key_len;
7097 int res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 6, &key_len);
7098 if (res || (!res && key_len && key_len != 6)) {
7099 PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits");
7100 CLIParserFree(ctx);
7101 return PM3_EINVARG;
7104 bool f0 = arg_get_lit(ctx, 4);
7105 bool f1 = arg_get_lit(ctx, 5);
7106 bool f2 = arg_get_lit(ctx, 6);
7107 bool f3 = arg_get_lit(ctx, 7);
7108 CLIParserFree(ctx);
7110 uint8_t tmp = f0 + f1 + f2 + f3;
7111 if (tmp > 1) {
7112 PrintAndLogEx(WARNING, "select only one key type");
7113 return PM3_EINVARG;
7115 if (tmp == 0) {
7116 PrintAndLogEx(WARNING, "select one key type");
7117 return PM3_EINVARG;
7120 uint8_t pers_option = MIFARE_EV1_UIDF3;
7121 if (f0) {
7122 pers_option = MIFARE_EV1_UIDF0;
7123 } else if (f1) {
7124 pers_option = MIFARE_EV1_UIDF1;
7125 } else if (f2) {
7126 pers_option = MIFARE_EV1_UIDF2;
7129 CLIParserFree(ctx);
7131 struct {
7132 uint8_t keytype;
7133 uint8_t pers_option;
7134 uint8_t key[6];
7135 } PACKED payload;
7136 payload.keytype = keytype;
7137 payload.pers_option = pers_option;
7138 memcpy(payload.key, key, sizeof(payload.key));
7140 clearCommandBuffer();
7141 SendCommandNG(CMD_HF_MIFARE_PERSONALIZE_UID, (uint8_t *)&payload, sizeof(payload));
7142 PacketResponseNG resp;
7143 if (WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500) == false) {
7144 return PM3_ETIMEOUT;
7147 if (resp.status == PM3_SUCCESS) {
7148 PrintAndLogEx(SUCCESS, "Personalization ( %s )", _GREEN_("ok"));
7149 } else {
7150 PrintAndLogEx(FAILED, "Personalization ( %s )", _RED_("fail"));
7152 return PM3_SUCCESS;
7155 static int CmdHF14AMfList(const char *Cmd) {
7156 return CmdTraceListAlias(Cmd, "hf mf", "mf -c");
7159 static int CmdHf14AGen3UID(const char *Cmd) {
7160 CLIParserContext *ctx;
7161 CLIParserInit(&ctx, "hf mf gen3uid",
7162 "Set UID for magic Gen3 card _without_ changes to manufacturer block 0",
7163 "hf mf gen3uid --uid 01020304 --> set 4 byte uid\n"
7164 "hf mf gen3uid --uid 01020304050607 --> set 7 byte uid"
7166 void *argtable[] = {
7167 arg_param_begin,
7168 arg_str0("u", "uid", "<hex>", "UID 4/7 hex bytes"),
7169 arg_param_end
7171 CLIExecWithReturn(ctx, Cmd, argtable, true);
7173 uint8_t uid[7] = {0};
7174 int uidlen = 0;
7175 CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
7176 CLIParserFree(ctx);
7178 // sanity checks
7179 if (uidlen != 4 && uidlen != 7) {
7180 PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen);
7181 return PM3_EINVARG;
7184 uint8_t old_uid[10] = {0};
7186 int res = mf_chinese_gen_3_uid(uid, uidlen, old_uid);
7187 if (res != PM3_SUCCESS) {
7188 PrintAndLogEx(ERR, "Can't set UID");
7189 PrintAndLogEx(HINT, "Are you sure your card is a Gen3 ?");
7190 return PM3_ESOFT;
7193 PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen));
7194 PrintAndLogEx(SUCCESS, "New UID... %s", sprint_hex(uid, uidlen));
7195 return PM3_SUCCESS;
7198 static int CmdHf14AGen3Block(const char *Cmd) {
7199 CLIParserContext *ctx;
7200 CLIParserInit(&ctx, "hf mf gen3blk",
7201 "Overwrite full manufacturer block for magic Gen3 card\n"
7202 " - You can specify part of manufacturer block as\n"
7203 " 4/7-bytes for UID change only\n"
7204 "\n"
7205 "NOTE: BCC, SAK, ATQA will be calculated automatically"
7207 "hf mf gen3blk --> print current data\n"
7208 "hf mf gen3blk -d 01020304 --> set 4 byte uid\n"
7209 "hf mf gen3blk -d 01020304050607 --> set 7 byte uid \n"
7210 "hf mf gen3blk -d 01020304FFFFFFFF0102030405060708"
7213 void *argtable[] = {
7214 arg_param_begin,
7215 arg_str0("d", "data", "<hex>", "manufacturer block data up to 16 hex bytes"),
7216 arg_param_end
7218 CLIExecWithReturn(ctx, Cmd, argtable, true);
7220 uint8_t data[MFBLOCK_SIZE] = {0x00};
7221 int datalen = 0;
7222 CLIGetHexWithReturn(ctx, 1, data, &datalen);
7223 CLIParserFree(ctx);
7225 uint8_t new_block[MFBLOCK_SIZE] = {0x00};
7226 int res = mf_chinese_gen_3_block(data, datalen, new_block);
7227 if (res) {
7228 PrintAndLogEx(ERR, "Can't change manufacturer block data. error %d", res);
7229 return PM3_ESOFT;
7232 PrintAndLogEx(SUCCESS, "Current block... %s", sprint_hex_inrow(new_block, sizeof(new_block)));
7233 return PM3_SUCCESS;
7236 static int CmdHf14AGen3Freeze(const char *Cmd) {
7237 CLIParserContext *ctx;
7238 CLIParserInit(&ctx, "hf mf gen3freeze",
7239 "Perma lock further UID changes. No more UID changes available after operation completed\n"
7240 "\nNote: operation is " _RED_("! irreversible !"),
7242 "hf mf gen3freeze -y"
7244 void *argtable[] = {
7245 arg_param_begin,
7246 arg_lit1("y", "yes", "confirm UID lock operation"),
7247 arg_param_end
7249 CLIExecWithReturn(ctx, Cmd, argtable, false);
7250 bool confirm = arg_get_lit(ctx, 1);
7251 CLIParserFree(ctx);
7252 if (confirm == false) {
7253 PrintAndLogEx(INFO, "please confirm that you want to perma lock the card");
7254 return PM3_SUCCESS;
7257 int res = mf_chinese_gen_3_freeze();
7258 if (res != PM3_SUCCESS) {
7259 PrintAndLogEx(ERR, "Can't lock UID changes. error %d", res);
7260 } else {
7261 PrintAndLogEx(SUCCESS, "MFC Gen3 UID card is now perma-locked");
7263 return res;
7266 #define FURUI_MAX_TRACES 8
7267 static int mfc_furui_recovery(uint8_t items, uint8_t tracedata[FURUI_MAX_TRACES][18]) {
7268 // recover key from collected traces
7269 // outer loop
7270 for (uint8_t i = 0; i < items; i++) {
7272 // first
7273 nonces_t data;
7274 data.cuid = bytes_to_num(tracedata[i], 4);
7275 data.nonce = bytes_to_num(tracedata[i] + 6, 4);
7276 data.nr = bytes_to_num(tracedata[i] + 10, 4);
7277 data.ar = bytes_to_num(tracedata[i] + 14, 4);
7278 data.at = 0;
7280 // inner loop
7281 for (uint8_t j = i + 1; j < items; j++) {
7283 uint8_t *p = tracedata[j];
7284 PrintAndLogEx(INFO, "%u... %s", i, sprint_hex_inrow(p, 18));
7286 // since data stored as block number but its the same key for all blocks in one sector
7287 // we compare with sector number here
7288 uint8_t s = mfSectorNum(tracedata[i][4]);
7289 if (mfSectorNum(p[4]) == s) {
7291 data.nonce2 = bytes_to_num(p + 6, 4);
7292 data.nr2 = bytes_to_num(p + 10, 4);
7293 data.ar2 = bytes_to_num(p + 14, 4);
7294 data.sector = s;
7295 data.keytype = tracedata[i][5];
7296 data.state = FIRST;
7298 uint64_t key64 = -1;
7299 if (mfkey32_moebius(&data, &key64)) {
7300 PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ "_GREEN_("%012" PRIX64) " ]",
7301 sprint_hex_inrow(tracedata[i], 4),
7302 data.sector,
7303 (data.keytype == 0x60) ? 'A' : 'B',
7304 key64
7306 break;
7311 return PM3_SUCCESS;
7314 static int mfc_supercard_gen2_recovery(uint8_t items, uint8_t tracedata[FURUI_MAX_TRACES][18]) {
7315 for (uint8_t i = 0; i < items; i++) {
7316 uint8_t *tmp = tracedata[i];
7318 // first
7319 uint16_t NT0 = (tmp[6] << 8) | tmp[7];
7321 nonces_t data;
7322 data.cuid = bytes_to_num(tmp, 4);
7323 data.nonce = prng_successor(NT0, 31);
7324 data.nr = bytes_to_num(tmp + 8, 4);
7325 data.ar = bytes_to_num(tmp + 12, 4);
7326 data.at = 0;
7328 // second
7329 for (uint8_t j = i + 1; j < items; j++) {
7330 uint8_t *p = tracedata[j];
7332 // since data stored as block number but its the same key for all blocks in one sector
7333 // we compare with sector number here
7334 uint8_t s = mfSectorNum(tmp[5]);
7335 if (mfSectorNum(p[5]) == s) {
7337 NT0 = (p[6] << 8) | p[7];
7339 data.nonce2 = prng_successor(NT0, 31);
7340 data.nr2 = bytes_to_num(p + 8, 4);
7341 data.ar2 = bytes_to_num(p + 12, 4);
7342 data.sector = s;
7343 data.keytype = tmp[4];
7344 data.state = FIRST;
7346 uint64_t key64 = -1;
7347 if (mfkey32_moebius(&data, &key64)) {
7348 PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ "_GREEN_("%012" PRIX64) " ]",
7349 sprint_hex_inrow(tmp, 4),
7350 data.sector,
7351 (data.keytype == 0x60) ? 'A' : 'B',
7352 key64
7354 break;
7359 return PM3_SUCCESS;
7362 static int CmdHf14AMfSuperCard(const char *Cmd) {
7363 CLIParserContext *ctx;
7364 CLIParserInit(&ctx, "hf mf supercard",
7365 "Extract info from a `super card`",
7366 "hf mf supercard -> recover key\n"
7367 "hf mf supercard -r -> reset card\n"
7368 "hf mf supercard -u 11223344 -> change UID\n");
7370 void *argtable[] = {
7371 arg_param_begin,
7372 arg_lit0("r", "reset", "Reset card"),
7373 arg_str0("u", "uid", "<hex>", "New UID (4 hex bytes)"),
7374 arg_lit0(NULL, "furui", "Furui detection card"),
7375 arg_param_end
7377 CLIExecWithReturn(ctx, Cmd, argtable, true);
7378 bool reset_card = arg_get_lit(ctx, 1);
7379 uint8_t uid[4];
7380 int uidlen = 0;
7381 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), uid, sizeof(uid), &uidlen);
7382 bool is_furui = arg_get_lit(ctx, 3);
7384 CLIParserFree(ctx);
7386 // sanity checks
7387 if (res || (!res && uidlen && uidlen != sizeof(uid))) {
7388 PrintAndLogEx(ERR, "UID must include 4 hex bytes");
7389 return PM3_EINVARG;
7392 uint8_t tracedata[FURUI_MAX_TRACES][18];
7394 // Super card FURUI
7395 if (is_furui) {
7397 // no reset on super card FURUI
7398 if (uidlen || reset_card) {
7399 PrintAndLogEx(FAILED, "Not supported on this card");
7400 return PM3_SUCCESS;
7403 // read 8 traces
7404 uint8_t i;
7405 for (i = 0; i < FURUI_MAX_TRACES; i++) {
7407 uint8_t data[] = {0xAA, 0xA8, 0x00, i};
7408 uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
7409 clearCommandBuffer();
7410 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(data), 0, data, sizeof(data));
7411 if (WaitForResponseTimeout(CMD_ACK, NULL, 1500) == false) {
7412 break;
7415 PacketResponseNG resp;
7416 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
7417 break;
7420 uint16_t len = resp.oldarg[0] & 0xFFFF;
7421 if (len != 20) {
7422 break; // Not trace data
7425 PrintAndLogEx(DEBUG, ">>> %s", sprint_hex_inrow(resp.data.asBytes, len));
7426 memcpy(&tracedata[i], resp.data.asBytes, len - 2);
7429 return mfc_furui_recovery(i, tracedata);
7432 #define SUPER_MAX_TRACES 7
7434 // read 7 traces from super card generation 1,2
7435 uint8_t i = 0;
7436 for (i = 0; i < SUPER_MAX_TRACES; i++) {
7438 uint8_t data[] = {0x30, i};
7439 uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
7440 clearCommandBuffer();
7441 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(data), 0, data, sizeof(data));
7442 if (WaitForResponseTimeout(CMD_ACK, NULL, 1500) == false) {
7443 break;
7446 PacketResponseNG resp;
7447 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
7448 break;
7451 uint16_t len = resp.oldarg[0] & 0xFFFF;
7452 if (len != 18) {
7453 break; // Not trace data
7456 PrintAndLogEx(DEBUG, ">>> %s", sprint_hex_inrow(resp.data.asBytes, len));
7457 memcpy(&tracedata[i], resp.data.asBytes, len - 2);
7460 // Super card generation 2
7461 if (i == SUPER_MAX_TRACES) {
7463 // no reset on super card generation 2.
7464 if (uidlen || reset_card) {
7465 PrintAndLogEx(FAILED, "Not supported on this card");
7466 return PM3_SUCCESS;
7469 // recover key from collected traces
7470 return mfc_supercard_gen2_recovery(i, tracedata);
7473 // Super card generation 1
7475 // Commands:
7476 // a0 - set UID
7477 // b0 - read traces
7478 // c0 - clear card
7479 bool activate_field = true;
7480 bool keep_field_on = true;
7482 // change UID on a super card generation 1
7483 if (uidlen) {
7484 keep_field_on = false;
7485 uint8_t response[6];
7486 int resplen = 0;
7488 // --------------- CHANGE UID ----------------
7489 uint8_t aCHANGE[] = {0x00, 0xa6, 0xa0, 0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0x00};
7490 memcpy(aCHANGE + 5, uid, uidlen);
7491 res = ExchangeAPDU14a(
7492 aCHANGE, sizeof(aCHANGE),
7493 activate_field,
7494 keep_field_on,
7495 response, sizeof(response),
7496 &resplen
7499 if (res != PM3_SUCCESS) {
7500 PrintAndLogEx(FAILED, "Super card UID change [ " _RED_("fail") " ]");
7501 DropField();
7502 return res;
7505 PrintAndLogEx(SUCCESS, "Super card UID change ( " _GREEN_("ok") " )");
7506 return PM3_SUCCESS;
7509 // reset a super card generation 1
7510 if (reset_card) {
7511 keep_field_on = false;
7512 uint8_t response[6];
7513 int resplen = 0;
7515 // --------------- RESET CARD ----------------
7516 uint8_t aRESET[] = {0x00, 0xa6, 0xc0, 0x00};
7517 res = ExchangeAPDU14a(
7518 aRESET, sizeof(aRESET),
7519 activate_field,
7520 keep_field_on,
7521 response, sizeof(response),
7522 &resplen
7525 if (res != PM3_SUCCESS) {
7526 PrintAndLogEx(FAILED, "Super card reset [ " _RED_("fail") " ]");
7527 DropField();
7528 return res;
7530 PrintAndLogEx(SUCCESS, "Super card reset ( " _GREEN_("ok") " )");
7531 return PM3_SUCCESS;
7534 uint8_t responseA[22];
7535 uint8_t responseB[22];
7536 int respAlen = 0;
7537 int respBlen = 0;
7539 // --------------- First ----------------
7540 uint8_t aFIRST[] = {0x00, 0xa6, 0xb0, 0x00, 0x10};
7541 res = ExchangeAPDU14a(aFIRST, sizeof(aFIRST), activate_field, keep_field_on, responseA, sizeof(responseA), &respAlen);
7542 if (res != PM3_SUCCESS) {
7543 DropField();
7544 return res;
7547 // --------------- Second ----------------
7548 activate_field = false;
7549 keep_field_on = false;
7551 uint8_t aSECOND[] = {0x00, 0xa6, 0xb0, 0x01, 0x10};
7552 res = ExchangeAPDU14a(aSECOND, sizeof(aSECOND), activate_field, keep_field_on, responseB, sizeof(responseB), &respBlen);
7553 if (res != PM3_SUCCESS) {
7554 DropField();
7555 return res;
7558 uint8_t outA[16] = {0};
7559 uint8_t outB[16] = {0};
7561 uint8_t key[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
7562 for (i = 0; i < 16; i += 8) {
7563 des_decrypt(outA + i, responseA + i, key);
7564 des_decrypt(outB + i, responseB + i, key);
7567 PrintAndLogEx(DEBUG, " in : %s", sprint_hex_inrow(responseA, respAlen));
7568 PrintAndLogEx(DEBUG, "out : %s", sprint_hex_inrow(outA, sizeof(outA)));
7569 PrintAndLogEx(DEBUG, " in : %s", sprint_hex_inrow(responseB, respAlen));
7570 PrintAndLogEx(DEBUG, "out : %s", sprint_hex_inrow(outB, sizeof(outB)));
7572 if (memcmp(outA, "\x01\x01\x01\x01\x01\x01\x01\x01", 8) == 0) {
7573 PrintAndLogEx(INFO, "No trace recorded");
7574 return PM3_SUCCESS;
7577 // second trace?
7578 if (memcmp(outB, "\x01\x01\x01\x01\x01\x01\x01\x01", 8) == 0) {
7579 PrintAndLogEx(INFO, "Only one trace recorded");
7580 return PM3_SUCCESS;
7583 nonces_t data;
7585 // first
7586 uint16_t NT0 = (outA[6] << 8) | outA[7];
7587 data.cuid = bytes_to_num(outA, 4);
7588 data.nonce = prng_successor(NT0, 31);
7589 data.nr = bytes_to_num(outA + 8, 4);
7590 data.ar = bytes_to_num(outA + 12, 4);
7591 data.at = 0;
7593 // second
7594 NT0 = (outB[6] << 8) | outB[7];
7595 data.nonce2 = prng_successor(NT0, 31);
7596 data.nr2 = bytes_to_num(outB + 8, 4);
7597 data.ar2 = bytes_to_num(outB + 12, 4);
7598 data.sector = mfSectorNum(outA[5]);
7599 data.keytype = outA[4];
7600 data.state = FIRST;
7602 PrintAndLogEx(DEBUG, "A Sector %02x", data.sector);
7603 PrintAndLogEx(DEBUG, "A NT %08x", data.nonce);
7604 PrintAndLogEx(DEBUG, "A NR %08x", data.nr);
7605 PrintAndLogEx(DEBUG, "A AR %08x", data.ar);
7606 PrintAndLogEx(DEBUG, "");
7607 PrintAndLogEx(DEBUG, "B NT %08x", data.nonce2);
7608 PrintAndLogEx(DEBUG, "B NR %08x", data.nr2);
7609 PrintAndLogEx(DEBUG, "B AR %08x", data.ar2);
7611 uint64_t key64 = -1;
7612 if (mfkey32_moebius(&data, &key64)) {
7613 PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ " _GREEN_("%012" PRIX64) " ]",
7614 sprint_hex_inrow(outA, 4),
7615 data.sector,
7616 (data.keytype == 0x60) ? 'A' : 'B',
7617 key64
7619 } else {
7620 PrintAndLogEx(FAILED, "failed to recover any key");
7622 return PM3_SUCCESS;
7625 static int CmdHF14AMfWipe(const char *Cmd) {
7626 CLIParserContext *ctx;
7627 CLIParserInit(&ctx, "hf mf wipe",
7628 "Wipe card to zeros and default keys/acc. This command takes a key file to wipe card\n"
7629 "Will use UID from card to generate keyfile name if not specified.\n"
7630 "New A/B keys..... FF FF FF FF FF FF\n"
7631 "New acc rights... FF 07 80\n"
7632 "New GPB.......... 69",
7633 "hf mf wipe --> reads card uid to generate file name\n"
7634 "hf mf wipe --gen2 --> force write to S0, B0 manufacture block\n"
7635 "hf mf wipe -f mykey.bin --> use mykey.bin\n"
7637 void *argtable[] = {
7638 arg_param_begin,
7639 arg_str0("f", "file", "<fn>", "key filename"),
7640 arg_lit0(NULL, "gen2", "force write to Sector 0, block 0 (GEN2)"),
7641 arg_param_end
7643 CLIExecWithReturn(ctx, Cmd, argtable, true);
7645 int keyfnlen = 0;
7646 char keyFilename[FILE_PATH_SIZE] = {0};
7647 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
7649 bool gen2 = arg_get_lit(ctx, 2);
7650 CLIParserFree(ctx);
7652 char *fptr;
7653 if (keyfnlen == 0) {
7654 fptr = GenerateFilename("hf-mf-", "-key.bin");
7655 if (fptr == NULL) {
7656 return PM3_ESOFT;
7658 strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
7659 free(fptr);
7662 uint8_t *keys;
7663 size_t keyslen = 0;
7664 if (loadFile_safeEx(keyFilename, ".bin", (void **)&keys, (size_t *)&keyslen, false) != PM3_SUCCESS) {
7665 PrintAndLogEx(FAILED, "failed to load key file");
7666 return PM3_ESOFT;
7669 uint8_t keyA[MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE];
7670 uint8_t keyB[MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE];
7671 uint8_t num_sectors = 0;
7673 uint8_t mf[MFBLOCK_SIZE];
7674 switch (keyslen) {
7675 case (MIFARE_MINI_MAX_KEY_SIZE): {
7676 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic Mini 320b");
7677 memcpy(keyA, keys, (MIFARE_MINI_MAXSECTOR * MIFARE_KEY_SIZE));
7678 memcpy(keyB, keys + (MIFARE_MINI_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_MINI_MAXSECTOR * MIFARE_KEY_SIZE));
7679 num_sectors = NumOfSectors('0');
7680 memcpy(mf, "\x11\x22\x33\x44\x44\x09\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7681 break;
7683 case (MIFARE_1K_EV1_MAX_KEY_SIZE): {
7684 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 1K Ev1");
7685 memcpy(keyA, keys, (MIFARE_1K_EV1_MAXSECTOR * MIFARE_KEY_SIZE));
7686 memcpy(keyB, keys + (MIFARE_1K_EV1_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_1K_EV1_MAXSECTOR * MIFARE_KEY_SIZE));
7687 num_sectors = NumOfSectors('1');
7688 memcpy(mf, "\x11\x22\x33\x44\x44\x08\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7689 break;
7691 case (MIFARE_1K_MAX_KEY_SIZE): {
7692 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 1K");
7693 memcpy(keyA, keys, (MIFARE_1K_MAXSECTOR * MIFARE_KEY_SIZE));
7694 memcpy(keyB, keys + (MIFARE_1K_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_1K_MAXSECTOR * MIFARE_KEY_SIZE));
7695 num_sectors = NumOfSectors('1');
7697 memcpy(mf, "\x11\x22\x33\x44\x44\x08\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7698 break;
7700 case (MIFARE_4K_MAX_KEY_SIZE): {
7701 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 4K");
7702 memcpy(keyA, keys, (MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE));
7703 memcpy(keyB, keys + (MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE));
7704 num_sectors = NumOfSectors('4');
7705 memcpy(mf, "\x11\x22\x33\x44\x44\x18\x02\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7706 break;
7708 default: {
7709 PrintAndLogEx(INFO, "wrong key file size. got %zu", keyslen);
7710 goto out;
7714 if (gen2)
7715 PrintAndLogEx(INFO, "Forcing overwrite of sector 0 / block 0 ");
7716 else
7717 PrintAndLogEx(INFO, "Skipping sector 0 / block 0");
7719 PrintAndLogEx(NORMAL, "");
7721 uint8_t zeros[MFBLOCK_SIZE] = {0};
7722 memset(zeros, 0x00, sizeof(zeros));
7723 uint8_t st[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
7725 PrintAndLogEx(INFO, " blk | ");
7726 PrintAndLogEx(INFO, "-----+------------------------------------------------------------");
7727 // time to wipe card
7728 for (uint8_t s = 0; s < num_sectors; s++) {
7730 for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) {
7732 if (kbd_enter_pressed()) {
7733 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
7734 goto out;
7737 // Skip write to manufacture block if not enforced
7738 if (s == 0 && b == 0 && gen2 == false) {
7739 continue;
7742 uint8_t data[26];
7743 memset(data, 0, sizeof(data));
7744 if (mfIsSectorTrailerBasedOnBlocks(s, b)) {
7745 memcpy(data + 10, st, sizeof(st));
7746 } else {
7747 memcpy(data + 10, zeros, sizeof(zeros));
7750 // add correct manufacture block if UID Gen2
7751 if (s == 0 && b == 0 && gen2) {
7752 memcpy(data + 10, mf, sizeof(mf));
7755 // try both A/B keys, start with B key first
7756 for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
7758 if (kt == MF_KEY_A)
7759 memcpy(data, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
7760 else
7761 memcpy(data, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
7763 PrintAndLogEx(INFO, " %3d | %s" NOLF, mfFirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE));
7764 clearCommandBuffer();
7765 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, data, sizeof(data));
7766 PacketResponseNG resp;
7767 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
7768 int8_t isOK = resp.oldarg[0];
7769 if (isOK == 1) {
7770 PrintAndLogEx(NORMAL, "- key %c ( " _GREEN_("ok") " )", (kt == MF_KEY_A) ? 'A' : 'B');
7771 break;
7772 } else {
7773 PrintAndLogEx(NORMAL, "- key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B');
7775 } else {
7776 PrintAndLogEx(WARNING, "command execution time out");
7782 PrintAndLogEx(INFO, "-----+------------------------------------------------------------");
7783 PrintAndLogEx(NORMAL, "");
7784 PrintAndLogEx(INFO, "Done!");
7785 out:
7786 free(keys);
7787 return PM3_SUCCESS;
7790 static int CmdHF14AMfView(const char *Cmd) {
7792 CLIParserContext *ctx;
7793 CLIParserInit(&ctx, "hf mf view",
7794 "Print a MIFARE Classic dump file (bin/eml/json)",
7795 "hf mf view -f hf-mf-01020304-dump.bin"
7797 void *argtable[] = {
7798 arg_param_begin,
7799 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
7800 arg_lit0("v", "verbose", "verbose output"),
7801 arg_lit0(NULL, "sk", "Save extracted keys to binary file"),
7802 arg_param_end
7804 CLIExecWithReturn(ctx, Cmd, argtable, false);
7805 int fnlen = 0;
7806 char filename[FILE_PATH_SIZE];
7807 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
7808 bool verbose = arg_get_lit(ctx, 2);
7809 bool save_keys = arg_get_lit(ctx, 3);
7810 CLIParserFree(ctx);
7812 // read dump file
7813 uint8_t *dump = NULL;
7814 size_t bytes_read = 0;
7815 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, MIFARE_4K_MAX_BYTES);
7816 if (res != PM3_SUCCESS) {
7817 return res;
7820 uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE));
7821 if (bytes_read == MIFARE_MINI_MAX_BYTES)
7822 block_cnt = MIFARE_MINI_MAXBLOCK;
7823 else if (bytes_read == MIFARE_2K_MAX_BYTES)
7824 block_cnt = MIFARE_2K_MAXBLOCK;
7825 else if (bytes_read == MIFARE_4K_MAX_BYTES)
7826 block_cnt = MIFARE_4K_MAXBLOCK;
7828 if (verbose) {
7829 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
7832 mf_print_blocks(block_cnt, dump, verbose);
7834 if (verbose) {
7835 mf_print_keys(block_cnt, dump);
7836 mf_analyse_acl(block_cnt, dump);
7839 if (save_keys) {
7840 mf_save_keys_from_arr(block_cnt, dump);
7843 int sector = DetectHID(dump, 0x4910);
7844 if (sector > -1) {
7845 // decode it
7846 PrintAndLogEx(INFO, "");
7847 PrintAndLogEx(INFO, _CYAN_("VIGIK PACS detected"));
7849 // decode MAD v1
7850 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
7851 size_t madlen = 0;
7852 res = MADDecode(dump, NULL, mad, &madlen, false);
7853 if (res != PM3_SUCCESS) {
7854 PrintAndLogEx(ERR, "can't decode MAD");
7855 return res;
7858 typedef union UDATA {
7859 uint8_t *bytes;
7860 mfc_vigik_t *vigik;
7861 } UDATA;
7862 // allocate memory
7863 UDATA d;
7864 d.bytes = calloc(bytes_read, sizeof(uint8_t));
7865 if (d.bytes == NULL) {
7866 return PM3_EMALLOC;
7868 uint16_t dlen = 0;
7870 // vigik struture sector 0
7871 uint8_t *pdump = dump;
7873 memcpy(d.bytes + dlen, pdump, MFBLOCK_SIZE * 3);
7874 dlen += MFBLOCK_SIZE * 3;
7875 pdump += (MFBLOCK_SIZE * 4); // skip sectortrailer
7877 // extract memory from MAD sectors
7878 for (int i = 0; i <= madlen; i++) {
7879 if (0x4910 == mad[i] || 0x4916 == mad[i]) {
7880 memcpy(d.bytes + dlen, pdump, MFBLOCK_SIZE * 3);
7881 dlen += MFBLOCK_SIZE * 3;
7884 pdump += (MFBLOCK_SIZE * 4); // skip sectortrailer
7887 // convert_mfc_2_arr(pdump, bytes_read, d, &dlen);
7888 vigik_annotate(d.vigik);
7889 free(d.bytes);
7892 free(dump);
7893 return PM3_SUCCESS;
7896 static int parse_gtu_cfg(uint8_t *d, size_t n) {
7898 PrintAndLogEx(NORMAL, "");
7899 PrintAndLogEx(INFO, "---------- " _CYAN_("GTU Gen4 Configuration") " -------------------------------------");
7900 if (n != 30 && n != 32) {
7901 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d, n));
7902 PrintAndLogEx(INFO, "%zu bytes", n);
7903 PrintAndLogEx(WARNING, "Unknown config format");
7904 return PM3_SUCCESS;
7907 PrintAndLogEx(INFO, _YELLOW_("%s"), sprint_hex_inrow(d, n));
7908 PrintAndLogEx(INFO, "%zu bytes", n);
7909 PrintAndLogEx(INFO, "");
7910 PrintAndLogEx(INFO, _CYAN_("Config 1 - UID & modes"));
7911 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d, 8));
7912 PrintAndLogEx(INFO, "%02X.............. " NOLF, d[0]);
7913 bool is_ul_enabled = (d[0] == 1);
7914 switch (d[0]) {
7915 case 0x00:
7916 PrintAndLogEx(NORMAL, "MIFARE Classic mode");
7917 break;
7918 case 0x01:
7919 PrintAndLogEx(NORMAL, "MIFARE Ultralight/NTAG mode");
7920 break;
7921 default:
7922 PrintAndLogEx(NORMAL, _RED_("unknown"));
7923 break;
7926 PrintAndLogEx(INFO, "..%02X............ UID " NOLF, d[1]);
7928 switch (d[1]) {
7929 case 0x00:
7930 PrintAndLogEx(NORMAL, _GREEN_("4") " byte");
7931 break;
7932 case 0x01:
7933 PrintAndLogEx(NORMAL, _GREEN_("7") " byte");
7934 break;
7935 case 0x02:
7936 PrintAndLogEx(NORMAL, _GREEN_("10") " byte");
7937 break;
7938 default:
7939 PrintAndLogEx(NORMAL, _RED_("unknown"));
7940 break;
7943 PrintAndLogEx(INFO, "...." _YELLOW_("%s") ".... " _YELLOW_("Password"), sprint_hex_inrow(&d[2], 4));
7944 PrintAndLogEx(INFO, "............%02X.. GTU mode " NOLF, d[6]);
7945 switch (d[6]) {
7946 case 0x00:
7947 PrintAndLogEx(NORMAL, _GREEN_("pre-write") " - shadow data can be written");
7948 break;
7949 case 0x01:
7950 PrintAndLogEx(NORMAL, _GREEN_("restore mode"));
7951 break;
7952 case 0x02:
7953 PrintAndLogEx(NORMAL, "disabled");
7954 break;
7955 case 0x03:
7956 PrintAndLogEx(NORMAL, "disabled, high speed R/W mode for Ultralight ?");
7957 break;
7958 default:
7959 PrintAndLogEx(NORMAL, _RED_("unknown"));
7960 break;
7963 uint8_t atslen = d[7];
7964 if (atslen == 0) {
7965 PrintAndLogEx(INFO, ".............. ATS length %u bytes ( %s )", atslen, _YELLOW_("zero"));
7966 } else if (atslen <= 16) {
7967 PrintAndLogEx(INFO, ".............. ATS length %u bytes ( %s )", atslen, _GREEN_("ok"));
7968 } else {
7969 PrintAndLogEx(INFO, ".............. ATS length %u bytes ( %s )", atslen, _RED_("fail"));
7970 atslen = 0;
7973 PrintAndLogEx(INFO, "");
7975 // ATS seems to have 16 bytes reserved
7976 PrintAndLogEx(INFO, _CYAN_("Config 2 - ATS"));
7977 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d + 8, 16));
7978 if (atslen <= 16) {
7979 PrintAndLogEx(INFO, "%s.............. ATS ( %d bytes )", sprint_hex_inrow(&d[8], d[7]), d[7]);
7980 PrintAndLogEx(INFO, "..................%s Reserved for ATS", sprint_hex_inrow(d + 8 + d[7], 16 - d[7]));
7981 } else {
7982 PrintAndLogEx(INFO, "%s.............. %u Reserved for ATS", sprint_hex_inrow(&d[8], 16), 16);
7985 PrintAndLogEx(INFO, "");
7986 PrintAndLogEx(INFO, _CYAN_("Config 3 - Limits"));
7987 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d + 24, (n - 24)));
7988 PrintAndLogEx(INFO, "%02X%02X............ ATQA", d[24], d[25]);
7989 PrintAndLogEx(INFO, "....%02X.......... SAK", d[26]);
7990 PrintAndLogEx(INFO, "......%02X........ " NOLF, d[27]);
7991 switch (d[27]) {
7992 case 0x00:
7993 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("Ultralight EV1") : "Ultralight Ev1");
7994 break;
7995 case 0x01:
7996 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("NTAG") : "NTAG");
7997 break;
7998 case 0x02:
7999 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("Ultralight C") : "Ultralight C");
8000 break;
8001 case 0x03:
8002 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("Ultralight") : "Ultralight");
8003 break;
8004 default:
8005 PrintAndLogEx(NORMAL, _RED_("unknown"));
8006 break;
8009 PrintAndLogEx(INFO, "........%02X...... Max R/W sectors", d[28]);
8010 PrintAndLogEx(INFO, "..........%02X.... " NOLF, d[29]);
8011 switch (d[29]) {
8012 case 0x00:
8013 PrintAndLogEx(NORMAL, _GREEN_("CUID enabled"));
8014 break;
8015 case 0x01:
8016 PrintAndLogEx(NORMAL, "CUID disabled");
8017 break;
8018 case 0x02:
8019 PrintAndLogEx(NORMAL, "Default value. Same behaviour as 00?");
8020 break;
8021 default:
8022 PrintAndLogEx(NORMAL, _RED_("unknown"));
8023 break;
8025 PrintAndLogEx(INFO, "............%s unknown", sprint_hex_inrow(d + 30, n - 30));
8026 PrintAndLogEx(INFO, "");
8027 return PM3_SUCCESS;
8030 // info about Gen4 GTU card
8031 static int CmdHF14AGen4Info(const char *cmd) {
8032 CLIParserContext *ctx;
8033 CLIParserInit(&ctx, "hf mf ginfo",
8034 "Read info about magic gen4 GTU card.",
8035 "hf mf ginfo --> get info with default password 00000000\n"
8036 "hf mf ginfo --pwd 01020304 --> get info with password\n"
8037 "hf mf ginfo -d 00000000000002090978009102BDAC19131011121314151604001800FF0002FD -v --> decode config block"
8039 void *argtable[] = {
8040 arg_param_begin,
8041 arg_lit0("v", "verbose", "verbose output"),
8042 arg_str0("p", "pwd", "<hex>", "password 4 bytes"),
8043 arg_str0("d", "data", "<hex>", "config bytes 32 bytes"),
8044 arg_param_end
8046 CLIExecWithReturn(ctx, cmd, argtable, true);
8047 bool verbose = arg_get_lit(ctx, 1);
8049 int pwd_len = 0;
8050 uint8_t pwd[4] = {0};
8051 CLIGetHexWithReturn(ctx, 2, pwd, &pwd_len);
8053 int dlen = 0;
8054 uint8_t data[32] = {0};
8055 CLIGetHexWithReturn(ctx, 3, data, &dlen);
8056 CLIParserFree(ctx);
8058 if (pwd_len != 0 && pwd_len != 4) {
8059 PrintAndLogEx(FAILED, "Password must be 4 bytes length, got " _YELLOW_("%u"), pwd_len);
8060 return PM3_EINVARG;
8063 uint8_t resp[40] = {0};
8064 size_t resplen = 0;
8065 int res = 0;
8067 if (dlen != 32) {
8068 res = mfG4GetConfig(pwd, resp, &resplen, verbose);
8069 if (res != PM3_SUCCESS || resplen == 0) {
8070 if (res == PM3_ETIMEOUT)
8071 PrintAndLogEx(ERR, "No card in the field or card command timeout.");
8072 else
8073 PrintAndLogEx(ERR, "Error get config. Maybe not a Gen4 card?. error=%d rlen=%zu", res, resplen);
8074 return PM3_ESOFT;
8076 } else {
8077 memcpy(resp, data, dlen);
8078 resplen = 32;
8081 parse_gtu_cfg(resp, resplen);
8083 uint8_t uid_len = resp[1];
8085 res = mfG4GetFactoryTest(pwd, resp, &resplen, false);
8086 if (res == PM3_SUCCESS && resplen > 2) {
8087 PrintAndLogEx(INFO, "");
8088 PrintAndLogEx(INFO, _CYAN_("Factory test"));
8089 if (verbose) {
8090 PrintAndLogEx(INFO, "Raw......... %s", sprint_hex_inrow(resp, resplen));
8093 if (memcmp(resp + resplen - 2, "\x66\x66", 2) == 0) {
8094 PrintAndLogEx(INFO, "Card type... Generic");
8096 } else if (memcmp(resp + resplen - 2, "\x02\xAA", 2) == 0) {
8097 PrintAndLogEx(INFO, "Card type... " _RED_("Limited functionality"));
8099 } else if (memcmp(resp + resplen - 2, "\x03\xA0", 2) == 0) {
8100 PrintAndLogEx(INFO, "Card type... Old card version");
8102 } else if (memcmp(resp + resplen - 2, "\x06\xA0", 2) == 0) {
8103 PrintAndLogEx(INFO, "Card type... " _GREEN_("New card version"));
8105 } else {
8106 PrintAndLogEx(INFO, "Card type... " _RED_("unknown %02X%02X"), resp[resplen - 2], resp[resplen - 1]);
8110 // read block 0
8111 res = mfG4GetBlock(pwd, 0, resp, MAGIC_INIT | MAGIC_OFF);
8112 if (res == PM3_SUCCESS) {
8113 PrintAndLogEx(INFO, "");
8114 PrintAndLogEx(INFO, _CYAN_("Block 0 test"));
8115 PrintAndLogEx(INFO, "Block 0..... %s", sprint_hex_inrow(resp, 16));
8117 switch (uid_len) {
8118 case 0x00:
8119 PrintAndLogEx(INFO, "UID [4]..... %s", sprint_hex_inrow(resp, 4));
8120 break;
8121 case 0x01:
8122 PrintAndLogEx(INFO, "UID [7]..... %s", sprint_hex_inrow(resp, 7));
8123 break;
8124 case 0x02:
8125 PrintAndLogEx(INFO, "UID [10..... %s", sprint_hex_inrow(resp, 10));
8126 break;
8127 default:
8128 break;
8132 PrintAndLogEx(NORMAL, "");
8133 return PM3_SUCCESS;
8136 // Read block from Gen4 GTU card
8137 static int CmdHF14AGen4GetBlk(const char *cmd) {
8138 CLIParserContext *ctx;
8139 CLIParserInit(&ctx, "hf mf ggetblk",
8140 "Get block data from magic gen4 GTU card.",
8141 "hf mf ggetblk --blk 0 --> get block 0 (manufacturer)\n"
8142 "hf mf ggetblk --blk 3 -v --> get block 3, decode sector trailer\n"
8144 void *argtable[] = {
8145 arg_param_begin,
8146 arg_int1("b", "blk", "<dec>", "block number"),
8147 arg_lit0("v", "verbose", "verbose output"),
8148 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8149 arg_param_end
8151 CLIExecWithReturn(ctx, cmd, argtable, false);
8152 int b = arg_get_int_def(ctx, 1, 0);
8153 bool verbose = arg_get_lit(ctx, 2);
8155 int pwd_len = 0;
8156 uint8_t pwd[4] = {0};
8157 CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
8158 CLIParserFree(ctx);
8160 //validate args
8161 if (b > MIFARE_4K_MAXBLOCK) {
8162 return PM3_EINVARG;
8165 if (pwd_len != 4 && pwd_len != 0) {
8166 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8167 return PM3_EINVARG;
8170 uint8_t blockno = (uint8_t)b;
8171 uint8_t data[16] = {0};
8173 PrintAndLogEx(NORMAL, "Block: %x", blockno) ;
8175 int res = mfG4GetBlock(pwd, blockno, data, MAGIC_INIT | MAGIC_OFF);
8176 if (res) {
8177 PrintAndLogEx(ERR, "Can't read block. error=%d", res);
8178 return PM3_ESOFT;
8181 uint8_t sector = mfSectorNum(blockno);
8182 mf_print_sector_hdr(sector);
8183 mf_print_block_one(blockno, data, verbose);
8185 if (verbose) {
8186 decode_print_st(blockno, data);
8187 } else {
8188 PrintAndLogEx(NORMAL, "");
8191 return PM3_SUCCESS;
8194 // Load dump to Gen4 GTU card
8195 static int CmdHF14AGen4Load(const char *cmd) {
8197 CLIParserContext *ctx;
8198 CLIParserInit(&ctx, "hf mf gload",
8199 "Load magic gen4 gtu card with data from (bin/eml/json) dump file\n"
8200 "or from emulator memory.",
8201 "hf mf gload --emu\n"
8202 "hf mf gload -f hf-mf-01020304.eml\n"
8203 "hf mf gload -p AABBCCDD --4k -v -f hf-mf-01020304-dump.bin\n"
8204 "\n"
8205 "Card must be configured beforehand with `script run hf_mf_ultimatecard`.\n"
8206 "Blocks are 16 bytes long."
8208 void *argtable[] = {
8209 arg_param_begin,
8210 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
8211 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
8212 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
8213 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
8214 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8215 arg_lit0("v", "verbose", "verbose output"),
8216 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
8217 arg_lit0(NULL, "emu", "from emulator memory"),
8218 arg_int0(NULL, "start", "<dec>", "index of block to start writing (default 0)"),
8219 arg_int0(NULL, "end", "<dec>", "index of block to end writing (default last block)"),
8220 arg_param_end
8223 CLIExecWithReturn(ctx, cmd, argtable, false);
8224 bool m0 = arg_get_lit(ctx, 1);
8225 bool m1 = arg_get_lit(ctx, 2);
8226 bool m2 = arg_get_lit(ctx, 3);
8227 bool m4 = arg_get_lit(ctx, 4);
8229 int pwd_len = 0;
8230 uint8_t pwd[4] = {0};
8231 CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
8233 bool verbose = arg_get_lit(ctx, 6);
8235 int fnlen = 0;
8236 char filename[FILE_PATH_SIZE] = {0};
8237 CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
8239 bool fill_from_emulator = arg_get_lit(ctx, 8);
8241 int start = arg_get_int_def(ctx, 9, 0);
8242 int end = arg_get_int_def(ctx, 10, -1);
8244 CLIParserFree(ctx);
8246 // validations
8247 if (pwd_len != 4 && pwd_len != 0) {
8248 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8249 return PM3_EINVARG;
8252 if ((m0 + m1 + m2 + m4) > 1) {
8253 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
8254 return PM3_EINVARG;
8255 } else if ((m0 + m1 + m2 + m4) == 0) {
8256 m1 = true;
8259 char s[6];
8260 memset(s, 0, sizeof(s));
8261 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
8262 if (m0) {
8263 block_cnt = MIFARE_MINI_MAXBLOCK;
8264 strncpy(s, "Mini", 5);
8265 } else if (m1) {
8266 block_cnt = MIFARE_1K_MAXBLOCK;
8267 strncpy(s, "1K", 3);
8268 } else if (m2) {
8269 block_cnt = MIFARE_2K_MAXBLOCK;
8270 strncpy(s, "2K", 3);
8271 } else if (m4) {
8272 block_cnt = MIFARE_4K_MAXBLOCK;
8273 strncpy(s, "4K", 3);
8274 } else {
8275 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
8276 return PM3_EINVARG;
8279 if (fill_from_emulator && (fnlen != 0)) {
8280 PrintAndLogEx(WARNING, "Please specify file or emulator memory, but not both");
8281 return PM3_EINVARG;
8284 if (!fill_from_emulator && (fnlen == 0)) {
8285 PrintAndLogEx(WARNING, "Please specify file or emulator memory");
8286 return PM3_EINVARG;
8289 if (end == -1) {
8290 end = block_cnt - 1;
8293 if (start < 0 || end < 0) {
8294 PrintAndLogEx(WARNING, "start and end must be positive integers");
8295 return PM3_EINVARG ;
8298 if (start > end) {
8299 PrintAndLogEx(WARNING, "start cannot be more than end");
8300 return PM3_EINVARG ;
8303 if (start >= block_cnt) {
8304 PrintAndLogEx(WARNING, "Last block for Mifare %s is %d. Start is too high.", s, block_cnt - 1) ;
8305 return PM3_EINVARG ;
8308 if (end >= block_cnt) {
8309 PrintAndLogEx(WARNING, "Last block for Mifare %s is %d. End is too high.", s, block_cnt - 1) ;
8310 return PM3_EINVARG ;
8313 uint8_t *data = NULL;
8314 size_t bytes_read = 0;
8316 if (fill_from_emulator) {
8317 data = calloc(block_cnt * MFBLOCK_SIZE, sizeof(uint8_t));
8318 if (data == NULL) {
8319 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
8320 return PM3_EMALLOC;
8323 PrintAndLogEx(INFO, "downloading emulator memory");
8324 if (GetFromDevice(BIG_BUF_EML, data, block_cnt * MFBLOCK_SIZE, 0, NULL, 0, NULL, 2500, false) == false) {
8325 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
8326 free(data);
8327 return PM3_ETIMEOUT;
8330 } else {
8331 // read from file
8332 int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
8333 if (res != PM3_SUCCESS) {
8334 return res;
8337 // check file size corresponds to card size.
8338 if (bytes_read != (block_cnt * MFBLOCK_SIZE)) {
8339 PrintAndLogEx(ERR, "File content error. Read %zu bytes, expected %i", bytes_read, block_cnt * MFBLOCK_SIZE);
8340 if (data != NULL) free(data);
8341 return PM3_EFILE;
8345 if (verbose) {
8346 if (fnlen != 0) {
8347 PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
8348 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
8349 } else {
8350 PrintAndLogEx(INFO, "Read %d blocks from emulator memory", block_cnt);
8354 PrintAndLogEx(INFO, "Copying to magic gen4 GTU MIFARE Classic " _GREEN_("%s"), s);
8355 PrintAndLogEx(INFO, "Starting block: %d. Ending block: %d.", start, end);
8357 // copy to card
8358 for (uint16_t blockno = start; blockno <= end; blockno++) {
8360 // 4k writes can be long, so we split status each 64 block boundary.
8361 if (blockno % 64 == 0 || blockno == start) {
8362 PrintAndLogEx(NORMAL, "");
8363 PrintAndLogEx(INFO, "" NOLF) ;
8365 PrintAndLogEx(NORMAL, "." NOLF);
8366 fflush(stdout);
8368 // write block
8369 uint8_t flags = 0 ;
8370 if (blockno == start) flags |= MAGIC_INIT ;
8371 if (blockno == end) flags |= MAGIC_OFF ;
8373 int res = mfG4SetBlock(pwd, blockno, data + (blockno * MFBLOCK_SIZE), flags);
8374 if (res != PM3_SUCCESS) {
8375 PrintAndLogEx(WARNING, "Can't set magic card block: %d. error=%d", blockno, res);
8376 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
8377 free(data);
8378 return PM3_ESOFT;
8381 PrintAndLogEx(NORMAL, "\n");
8383 if (data != NULL) free(data);
8385 PrintAndLogEx(SUCCESS, "Card loaded " _YELLOW_("%d") " blocks from %s", end - start + 1,
8386 (fill_from_emulator ? "emulator memory" : "file"));
8387 PrintAndLogEx(INFO, "Done!");
8388 return PM3_SUCCESS;
8391 // Write block to Gen4 GTU card
8392 static int CmdHF14AGen4SetBlk(const char *cmd) {
8393 CLIParserContext *ctx;
8394 CLIParserInit(&ctx, "hf mf gsetblk",
8395 "Set block data on a magic gen4 GTU card",
8396 "hf mf gsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
8398 void *argtable[] = {
8399 arg_param_begin,
8400 arg_int1("b", "blk", "<dec>", "block number"),
8401 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
8402 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8403 arg_param_end
8405 CLIExecWithReturn(ctx, cmd, argtable, false);
8407 int b = arg_get_int_def(ctx, 1, -1);
8409 uint8_t data[MFBLOCK_SIZE] = {0x00};
8410 int datalen = 0;
8411 CLIGetHexWithReturn(ctx, 2, data, &datalen);
8413 int pwd_len = 0;
8414 uint8_t pwd[4] = {0};
8415 CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
8417 CLIParserFree(ctx);
8419 // validations
8420 if (pwd_len != 4 && pwd_len != 0) {
8421 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8422 return PM3_EINVARG;
8425 CLIParserFree(ctx);
8427 if (b < 0 || b >= MIFARE_4K_MAXBLOCK) {
8428 PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
8429 return PM3_EINVARG;
8432 if (datalen != MFBLOCK_SIZE) {
8433 PrintAndLogEx(FAILED, "expected 16 bytes data, got %i", datalen);
8434 return PM3_EINVARG;
8437 // write block
8438 PrintAndLogEx(INFO, "Writing block number:%2d data:%s", b, sprint_hex_inrow(data, sizeof(data)));
8440 uint8_t blockno = (uint8_t)b;
8441 int res = mfG4SetBlock(pwd, blockno, data, MAGIC_INIT | MAGIC_OFF);
8442 if (res) {
8443 PrintAndLogEx(ERR, "Can't write block. error=%d", res);
8444 return PM3_ESOFT;
8447 return PM3_SUCCESS;
8450 static int CmdHF14AGen4View(const char *Cmd) {
8452 CLIParserContext *ctx;
8453 CLIParserInit(&ctx, "hf mf gview",
8454 "View `magic gen4 gtu` card memory",
8455 "hf mf gview\n"
8456 "hf mf gview --4k"
8458 void *argtable[] = {
8459 arg_param_begin,
8460 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
8461 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
8462 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
8463 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
8464 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8465 arg_lit0("v", "verbose", "verbose output"),
8466 arg_param_end
8468 CLIExecWithReturn(ctx, Cmd, argtable, true);
8469 bool m0 = arg_get_lit(ctx, 1);
8470 bool m1 = arg_get_lit(ctx, 2);
8471 bool m2 = arg_get_lit(ctx, 3);
8472 bool m4 = arg_get_lit(ctx, 4);
8474 int pwd_len = 0;
8475 uint8_t pwd[4] = {0};
8476 CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
8478 bool verbose = arg_get_lit(ctx, 6);
8479 CLIParserFree(ctx);
8481 // validations
8482 if (pwd_len != 4 && pwd_len != 0) {
8483 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8484 return PM3_EINVARG;
8487 if ((m0 + m1 + m2 + m4) > 1) {
8488 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
8489 return PM3_EINVARG;
8490 } else if ((m0 + m1 + m2 + m4) == 0) {
8491 m1 = true;
8494 char s[6];
8495 memset(s, 0, sizeof(s));
8496 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
8497 if (m0) {
8498 block_cnt = MIFARE_MINI_MAXBLOCK;
8499 strncpy(s, "Mini", 5);
8500 } else if (m1) {
8501 block_cnt = MIFARE_1K_MAXBLOCK;
8502 strncpy(s, "1K", 3);
8503 } else if (m2) {
8504 block_cnt = MIFARE_2K_MAXBLOCK;
8505 strncpy(s, "2K", 3);
8506 } else if (m4) {
8507 block_cnt = MIFARE_4K_MAXBLOCK;
8508 strncpy(s, "4K", 3);
8509 } else {
8510 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
8511 return PM3_EINVARG;
8513 PrintAndLogEx(SUCCESS, "View magic gen4 GTU MIFARE Classic " _GREEN_("%s"), s);
8515 // reserve memory
8516 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
8517 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
8518 if (dump == NULL) {
8519 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
8520 return PM3_EMALLOC;
8523 for (uint16_t i = 0; i < block_cnt; i++) {
8525 uint8_t flags = 0 ;
8526 if (i == 0) flags |= MAGIC_INIT ;
8527 if (i + 1 == block_cnt) flags |= MAGIC_OFF ;
8529 int res = mfG4GetBlock(pwd, i, dump + (i * MFBLOCK_SIZE), flags);
8530 if (res != PM3_SUCCESS) {
8531 PrintAndLogEx(WARNING, "Can't get magic card block: %u. error=%d", i, res);
8532 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
8533 free(dump);
8534 return PM3_ESOFT;
8537 PrintAndLogEx(NORMAL, "." NOLF);
8538 fflush(stdout);
8539 // 4k READs can be long, so we split status each 64 blocks.
8540 if (i % 64 == 0) {
8541 PrintAndLogEx(NORMAL, "");
8542 PrintAndLogEx(INFO, "" NOLF) ;
8546 PrintAndLogEx(NORMAL, "");
8547 mf_print_blocks(block_cnt, dump, verbose);
8549 if (verbose) {
8550 mf_print_keys(block_cnt, dump);
8553 free(dump);
8554 return PM3_SUCCESS;
8557 // save contents of Gent4 GTU card to file / emulator
8558 static int CmdHF14AGen4Save(const char *Cmd) {
8560 CLIParserContext *ctx;
8561 CLIParserInit(&ctx, "hf mf gsave",
8562 "Save `magic gen4 gtu` card memory to file (bin/json)"
8563 "or into emulator memory",
8564 "hf mf gsave\n"
8565 "hf mf gsave --4k\n"
8566 "hf mf gsave -p DEADBEEF -f hf-mf-01020304.json"
8568 void *argtable[] = {
8569 arg_param_begin,
8570 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
8571 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
8572 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
8573 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
8574 arg_str0("p", "pwd", "<hex>", "password 4 bytes"),
8575 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
8576 arg_lit0(NULL, "emu", "to emulator memory"),
8577 arg_param_end
8579 CLIExecWithReturn(ctx, Cmd, argtable, true);
8580 bool m0 = arg_get_lit(ctx, 1);
8581 bool m1 = arg_get_lit(ctx, 2);
8582 bool m2 = arg_get_lit(ctx, 3);
8583 bool m4 = arg_get_lit(ctx, 4);
8585 int pwd_len = 0;
8586 uint8_t pwd[4] = {0};
8587 CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
8589 int fnlen = 0;
8590 char filename[FILE_PATH_SIZE];
8591 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
8593 bool fill_emulator = arg_get_lit(ctx, 7);
8594 CLIParserFree(ctx);
8596 // ICEMAN: bug. if device has been using ICLASS commands,
8597 // the device needs to load the HF fpga image. It takes 1.5 second.
8598 set_fpga_mode(FPGA_BITSTREAM_HF);
8600 // validations
8601 if (pwd_len != 4 && pwd_len != 0) {
8602 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8603 return PM3_EINVARG;
8606 if ((m0 + m1 + m2 + m4) > 1) {
8607 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
8608 return PM3_EINVARG;
8609 } else if ((m0 + m1 + m2 + m4) == 0) {
8610 m1 = true;
8613 char s[6];
8614 memset(s, 0, sizeof(s));
8615 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
8616 if (m0) {
8617 block_cnt = MIFARE_MINI_MAXBLOCK;
8618 strncpy(s, "Mini", 5);
8619 } else if (m1) {
8620 block_cnt = MIFARE_1K_MAXBLOCK;
8621 strncpy(s, "1K", 3);
8622 } else if (m2) {
8623 block_cnt = MIFARE_2K_MAXBLOCK;
8624 strncpy(s, "2K", 3);
8625 } else if (m4) {
8626 block_cnt = MIFARE_4K_MAXBLOCK;
8627 strncpy(s, "4K", 3);
8628 } else {
8629 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
8630 return PM3_EINVARG;
8633 // Select card to get UID/UIDLEN information
8634 clearCommandBuffer();
8635 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
8636 PacketResponseNG resp;
8637 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
8638 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
8639 return PM3_ETIMEOUT;
8643 0: couldn't read
8644 1: OK, with ATS
8645 2: OK, no ATS
8646 3: proprietary Anticollision
8648 uint64_t select_status = resp.oldarg[0];
8649 if (select_status == 0) {
8650 PrintAndLogEx(DEBUG, "iso14443a card select failed");
8651 return PM3_SUCCESS;
8654 // store card info
8655 iso14a_card_select_t card;
8656 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
8658 // reserve memory
8659 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
8660 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
8661 if (dump == NULL) {
8662 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
8663 return PM3_EMALLOC;
8666 PrintAndLogEx(SUCCESS, "Dumping magic gen4 GTU MIFARE Classic " _GREEN_("%s") " card memory", s);
8667 PrintAndLogEx(INFO, "." NOLF);
8669 for (uint16_t i = 0; i < block_cnt; i++) {
8670 uint8_t flags = 0 ;
8671 if (i == 0) {
8672 flags |= MAGIC_INIT;
8674 if (i + 1 == block_cnt) {
8675 flags |= MAGIC_OFF;
8678 int res = mfG4GetBlock(pwd, i, dump + (i * MFBLOCK_SIZE), flags);
8679 if (res != PM3_SUCCESS) {
8680 PrintAndLogEx(NORMAL, "");
8681 PrintAndLogEx(WARNING, "Can't get magic card block: %u. error=%d", i, res);
8682 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
8683 free(dump);
8684 return PM3_ESOFT;
8688 PrintAndLogEx(NORMAL, "." NOLF);
8689 fflush(stdout);
8690 // 4k READs can be long, so we split status each 64 blocks.
8691 if (i % 64 == 0 && i != 0) {
8692 PrintAndLogEx(NORMAL, "");
8693 PrintAndLogEx(INFO, "" NOLF) ;
8697 PrintAndLogEx(NORMAL, "");
8699 if (fill_emulator) {
8700 PrintAndLogEx(INFO, "uploading to emulator memory");
8701 PrintAndLogEx(INFO, "." NOLF);
8702 // fast push mode
8703 g_conn.block_after_ACK = true;
8705 size_t offset = 0;
8706 int cnt = 0;
8707 uint16_t bytes_left = bytes ;
8709 // 12 is the size of the struct the fct mf_eml_set_mem_xt uses to transfer to device
8710 uint16_t max_avail_blocks = ((PM3_CMD_DATA_SIZE - 12) / MFBLOCK_SIZE) * MFBLOCK_SIZE;
8712 while (bytes_left > 0 && cnt < block_cnt) {
8713 if (bytes_left == MFBLOCK_SIZE) {
8714 // Disable fast mode on last packet
8715 g_conn.block_after_ACK = false;
8718 uint16_t chunk_size = MIN(max_avail_blocks, bytes_left);
8719 uint16_t blocks_to_send = chunk_size / MFBLOCK_SIZE;
8721 if (mf_eml_set_mem_xt(dump + offset, cnt, blocks_to_send, MFBLOCK_SIZE) != PM3_SUCCESS) {
8722 PrintAndLogEx(FAILED, "Can't set emulator mem at block: %3d", cnt);
8723 free(dump);
8724 return PM3_ESOFT;
8727 cnt += blocks_to_send;
8728 offset += chunk_size;
8729 bytes_left -= chunk_size;
8730 PrintAndLogEx(NORMAL, "." NOLF);
8731 fflush(stdout);
8734 PrintAndLogEx(NORMAL, "");
8735 PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", bytes);
8738 // user supplied filename?
8739 if (fnlen < 1) {
8740 char *fptr = filename;
8741 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
8742 FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
8745 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
8746 free(dump);
8747 return PM3_SUCCESS;
8750 // change Gent4 GTU card access password
8751 static int CmdHF14AGen4ChangePwd(const char *Cmd) {
8753 CLIParserContext *ctx;
8754 CLIParserInit(&ctx, "hf mf gchpwd",
8755 "Change access password for Gen4 GTU card. WARNING! If you dont KNOW the password - you CAN'T access it!!!",
8756 "hf mf gchpwd --pwd 00000000 --newpwd 01020304"
8758 void *argtable[] = {
8759 arg_param_begin,
8760 arg_str0("p", "pwd", "<hex>", "password 4 bytes"),
8761 arg_str0("n", "newpwd", "<hex>", "new password 4 bytes"),
8762 arg_lit0("v", "verbose", "verbose output"),
8763 arg_param_end
8765 CLIExecWithReturn(ctx, Cmd, argtable, false);
8767 int pwd_len = 0;
8768 uint8_t pwd[4] = {0};
8769 CLIGetHexWithReturn(ctx, 1, pwd, &pwd_len);
8771 int new_pwd_len = 0;
8772 uint8_t new_pwd[4] = {0};
8773 CLIGetHexWithReturn(ctx, 2, new_pwd, &new_pwd_len);
8775 bool verbose = arg_get_lit(ctx, 3);
8777 CLIParserFree(ctx);
8779 if (pwd_len != 4) {
8780 PrintAndLogEx(FAILED, "Old password must be 4 bytes long, got " _YELLOW_("%u"), pwd_len);
8781 return PM3_EINVARG;
8784 if (new_pwd_len != 4) {
8785 PrintAndLogEx(FAILED, "New password must be 4 bytes long, got " _YELLOW_("%u"), new_pwd_len);
8786 return PM3_EINVARG;
8789 int res = mfG4ChangePassword(pwd, new_pwd, verbose);
8790 if (res != PM3_SUCCESS) {
8791 PrintAndLogEx(ERR, "Change password error");
8792 return res;
8795 PrintAndLogEx(SUCCESS, "Change password ( " _GREEN_("ok") " )");
8796 return PM3_SUCCESS;
8799 static void parse_gdm_cfg(const uint8_t *d) {
8800 PrintAndLogEx(NORMAL, "");
8801 PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("GDM Gen4 Configuration") " -----------------------------------------");
8802 PrintAndLogEx(SUCCESS, _YELLOW_("%s"), sprint_hex_inrow(d, MFBLOCK_SIZE));
8803 PrintAndLogEx(SUCCESS, _YELLOW_("%02X%02X") "............................ %s %s"
8804 , d[0]
8805 , d[1]
8806 , (d[0] == 0x85 && d[1] == 0x00) ? "Magic wakeup disabled" : _GREEN_("Magic wakeup enabled")
8807 , (d[0] == 0x85 && d[1] == 0x00) ? "" : ((d[0] == 0x7A && d[1] == 0xFF) ? _GREEN_("with GDM cfg block access") : _RED_(", no GDM cfg block access"))
8809 PrintAndLogEx(SUCCESS, "...." _YELLOW_("%02X") ".......................... Magic wakeup style " _YELLOW_("%s"), d[2], ((d[2] == 0x85) ? "GDM 20(7)/23" : "Gen1a 40(7)/43"));
8810 PrintAndLogEx(SUCCESS, "......" _YELLOW_("%02X%02X%02X") ".................... unknown", d[3], d[4], d[5]);
8811 PrintAndLogEx(SUCCESS, "............" _YELLOW_("%02X") ".................. %s", d[6], (d[6] == 0x5A) ? "Key B use blocked when readable by ACL" : "Key B use allowed when readable by ACL");
8812 PrintAndLogEx(SUCCESS, ".............." _YELLOW_("%02X") "................ %s", d[7], (d[7] == 0x5A) ? _GREEN_("CUID enabled") : "CUID Disabled");
8813 PrintAndLogEx(SUCCESS, "................" _YELLOW_("%02X") ".............. n/a", d[8]);
8815 const char *pers;
8816 switch (d[9]) {
8817 case 0x5A:
8818 pers = _YELLOW_("Unfused");
8819 break;
8820 case 0xC3:
8821 pers = _CYAN_("UIDFO, double size UID");
8822 break;
8823 case 0xA5:
8824 pers = _CYAN_("UIDF1, double size UID, optional usage of selection process shortcut");
8825 break;
8826 case 0x87:
8827 pers = _GREEN_("UIDF2, single size random ID");
8828 break;
8829 case 0x69:
8830 pers = _GREEN_("UIDF3, single size NUID");
8831 break;
8832 default:
8833 pers = "4B UID from Block 0";
8834 break;
8836 PrintAndLogEx(SUCCESS, ".................." _YELLOW_("%02X") "............ MFC EV1 perso. " _YELLOW_("%s"), d[9], pers);
8837 PrintAndLogEx(SUCCESS, "...................." _YELLOW_("%02X") ".......... %s", d[10], (d[10] == 0x5A) ? _GREEN_("Shadow mode enabled") : "Shadow mode disabled");
8838 PrintAndLogEx(SUCCESS, "......................" _YELLOW_("%02X") "........ %s", d[11], (d[11] == 0x5A) ? _GREEN_("Magic auth enabled") : "Magic auth disabled");
8839 PrintAndLogEx(SUCCESS, "........................" _YELLOW_("%02X") "...... %s", d[12], (d[12] == 0x5A) ? _GREEN_("Static encrypted nonce enabled") : "Static encrypted nonce disabled");
8840 PrintAndLogEx(SUCCESS, ".........................." _YELLOW_("%02X") ".... %s", d[13], (d[13] == 0x5A) ? _GREEN_("MFC EV1 signature enabled") : "MFC EV1 signature disabled");
8841 PrintAndLogEx(SUCCESS, "............................" _YELLOW_("%02X") ".. n/a", d[14]);
8842 PrintAndLogEx(SUCCESS, ".............................." _YELLOW_("%02X") " SAK", d[15]);
8843 PrintAndLogEx(NORMAL, "");
8846 static int CmdHF14AGen4_GDM_ParseCfg(const char *Cmd) {
8847 CLIParserContext *ctx;
8848 CLIParserInit(&ctx, "hf mf gdmparsecfg",
8849 "Parse configuration data on a magic gen4 GDM card",
8850 "hf mf gdmparsecfg -d 850000000000000000005A5A00000008"
8852 void *argtable[] = {
8853 arg_param_begin,
8854 arg_str1("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
8855 arg_param_end
8857 CLIExecWithReturn(ctx, Cmd, argtable, false);
8859 uint8_t block[MFBLOCK_SIZE] = {0x00};
8860 int blen = 0;
8861 CLIGetHexWithReturn(ctx, 1, block, &blen);
8862 CLIParserFree(ctx);
8864 if (blen != MFBLOCK_SIZE) {
8865 PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
8866 return PM3_EINVARG;
8869 parse_gdm_cfg(block);
8871 return PM3_SUCCESS;
8874 static int CmdHF14AGen4_GDM_Cfg(const char *Cmd) {
8875 CLIParserContext *ctx;
8876 CLIParserInit(&ctx, "hf mf gdmcfg",
8877 "Get configuration data from magic gen4 GDM card.",
8878 "hf mf gdmcfg\n"
8880 void *argtable[] = {
8881 arg_param_begin,
8882 arg_str0("k", "key", "<hex>", "key 6 bytes (only for regular wakeup)"),
8883 arg_lit0(NULL, "gen1a", "use gen1a (40/43) magic wakeup"),
8884 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
8885 arg_param_end
8887 CLIExecWithReturn(ctx, Cmd, argtable, true);
8889 int keylen = 0;
8890 uint8_t key[6] = {0};
8891 CLIGetHexWithReturn(ctx, 1, key, &keylen);
8892 bool gen1a = arg_get_lit(ctx, 2);
8893 bool gdm = arg_get_lit(ctx, 3);
8894 CLIParserFree(ctx);
8896 // validate args
8897 if (keylen != 6 && keylen != 0) {
8898 PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
8899 return PM3_EINVARG;
8902 if (gen1a && gdm) {
8903 PrintAndLogEx(FAILED, "Can only specify a single magic wakeup command");
8904 return PM3_EINVARG;
8907 if ((gen1a || gdm) && keylen != 0) {
8908 PrintAndLogEx(FAILED, "Cannot use a key in combination with a magic wakeup");
8909 return PM3_EINVARG;
8912 mf_readblock_ex_t payload = {
8913 .read_cmd = MIFARE_MAGIC_GDM_READ_CFG,
8914 .block_no = 0,
8916 memcpy(payload.key, key, sizeof(payload.key));
8918 if (gen1a) {
8919 payload.wakeup = MF_WAKE_GEN1A;
8920 payload.auth_cmd = 0;
8921 } else if (gdm) {
8922 payload.wakeup = MF_WAKE_GDM_ALT;
8923 payload.auth_cmd = 0;
8924 } else {
8925 payload.wakeup = MF_WAKE_WUPA;
8926 payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
8929 clearCommandBuffer();
8930 SendCommandNG(CMD_HF_MIFARE_READBL_EX, (uint8_t *)&payload, sizeof(payload));
8931 PacketResponseNG resp;
8932 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL_EX, &resp, 1500) == false) {
8933 PrintAndLogEx(WARNING, "command execution time out");
8934 return PM3_ETIMEOUT;
8937 if (resp.status == PM3_SUCCESS && resp.length == MFBLOCK_SIZE) {
8938 parse_gdm_cfg(resp.data.asBytes);
8940 PrintAndLogEx(NORMAL, "");
8943 return resp.status;
8946 static int CmdHF14AGen4_GDM_SetCfg(const char *Cmd) {
8947 CLIParserContext *ctx;
8948 CLIParserInit(&ctx, "hf mf gdmsetcfg",
8949 "Set configuration data on a magic gen4 GDM card",
8950 "hf mf gdmsetcfg -d 850000000000000000005A5A00000008"
8952 void *argtable[] = {
8953 arg_param_begin,
8954 arg_str1("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
8955 arg_str0("k", "key", "<hex>", "key 6 bytes (only for regular wakeup)"),
8956 arg_lit0(NULL, "gen1a", "use gen1a (40/43) magic wakeup"),
8957 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
8958 arg_param_end
8960 CLIExecWithReturn(ctx, Cmd, argtable, false);
8962 uint8_t block[MFBLOCK_SIZE] = {0x00};
8963 int blen = 0;
8964 CLIGetHexWithReturn(ctx, 1, block, &blen);
8965 int keylen = 0;
8966 uint8_t key[6] = {0};
8967 CLIGetHexWithReturn(ctx, 2, key, &keylen);
8968 bool gen1a = arg_get_lit(ctx, 3);
8969 bool gdm = arg_get_lit(ctx, 4);
8970 CLIParserFree(ctx);
8972 if (blen != MFBLOCK_SIZE) {
8973 PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
8974 return PM3_EINVARG;
8977 if (keylen != 6 && keylen != 0) {
8978 PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
8979 return PM3_EINVARG;
8982 if (gen1a && gdm) {
8983 PrintAndLogEx(FAILED, "Can only specify a single magic wakeup command");
8984 return PM3_EINVARG;
8987 if ((gen1a || gdm) && keylen != 0) {
8988 PrintAndLogEx(FAILED, "Cannot use a key in combination with a magic wakeup");
8989 return PM3_EINVARG;
8992 mf_writeblock_ex_t payload = {
8993 .write_cmd = MIFARE_MAGIC_GDM_WRITE_CFG,
8994 .block_no = 0,
8996 memcpy(payload.block_data, block, sizeof(payload.block_data));
8997 memcpy(payload.key, key, sizeof(payload.key));
8999 if (gen1a) {
9000 payload.wakeup = MF_WAKE_GEN1A;
9001 payload.auth_cmd = 0;
9002 } else if (gdm) {
9003 payload.wakeup = MF_WAKE_GDM_ALT;
9004 payload.auth_cmd = 0;
9005 } else {
9006 payload.wakeup = MF_WAKE_WUPA;
9007 payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
9010 clearCommandBuffer();
9011 SendCommandNG(CMD_HF_MIFARE_WRITEBL_EX, (uint8_t *)&payload, sizeof(payload));
9012 PacketResponseNG resp;
9013 if (WaitForResponseTimeout(CMD_HF_MIFARE_WRITEBL_EX, &resp, 1500) == false) {
9014 PrintAndLogEx(WARNING, "command execution time out");
9015 return PM3_ETIMEOUT;
9018 if (resp.status == PM3_SUCCESS) {
9019 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
9020 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf gdmcfg") "` to verify");
9021 } else {
9022 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
9024 return PM3_SUCCESS;
9027 static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
9029 CLIParserContext *ctx;
9030 CLIParserInit(&ctx, "hf mf gdmsetblk",
9031 "Set block data on a magic gen4 GDM card\n"
9032 "`--force` param is used to override warnings like bad ACL writes.\n"
9033 " if not specified, it will exit if detected",
9034 "hf mf gdmsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
9036 void *argtable[] = {
9037 arg_param_begin,
9038 arg_int1(NULL, "blk", "<dec>", "block number"),
9039 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
9040 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9041 arg_lit0(NULL, "force", "override warnings"),
9042 arg_param_end
9044 CLIExecWithReturn(ctx, Cmd, argtable, false);
9046 int b = arg_get_int_def(ctx, 1, 1);
9048 uint8_t block[MFBLOCK_SIZE] = {0x00};
9049 int blen = 0;
9050 CLIGetHexWithReturn(ctx, 2, block, &blen);
9052 int keylen = 0;
9053 uint8_t key[6] = {0};
9054 CLIGetHexWithReturn(ctx, 3, key, &keylen);
9056 bool force = arg_get_lit(ctx, 4);
9057 CLIParserFree(ctx);
9059 if (blen != MFBLOCK_SIZE) {
9060 PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
9061 return PM3_EINVARG;
9064 if (b < 0 || b >= MIFARE_4K_MAXBLOCK) {
9065 PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
9066 return PM3_EINVARG;
9069 if (keylen != 6 && keylen != 0) {
9070 PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
9071 return PM3_EINVARG;
9074 uint8_t blockno = (uint8_t)b;
9076 if (mf_analyse_st_block(blockno, block, force) != PM3_SUCCESS) {
9077 return PM3_EINVARG;
9080 PrintAndLogEx(INFO, "Writing block no %d, key %s", blockno, sprint_hex_inrow(key, sizeof(key)));
9081 PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block)));
9083 struct p {
9084 uint8_t blockno;
9085 uint8_t key[6];
9086 uint8_t data[MFBLOCK_SIZE]; // data to be written
9087 } PACKED payload;
9089 payload.blockno = blockno;
9090 memcpy(payload.key, key, sizeof(payload.key));
9091 memcpy(payload.data, block, sizeof(payload.data));
9093 clearCommandBuffer();
9094 SendCommandNG(CMD_HF_MIFARE_G4_GDM_WRBL, (uint8_t *)&payload, sizeof(payload));
9095 PacketResponseNG resp;
9096 if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_WRBL, &resp, 1500) == false) {
9097 PrintAndLogEx(WARNING, "command execution time out");
9098 return PM3_ETIMEOUT;
9101 if (resp.status == PM3_SUCCESS) {
9102 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
9103 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf rdbl") "` to verify");
9104 } else if (resp.status == PM3_ETEAROFF) {
9105 PrintAndLogEx(INFO, "Tear off triggered");
9106 return resp.status;
9107 } else {
9108 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
9110 return PM3_SUCCESS;
9113 static int CmdHF14AMfValue(const char *Cmd) {
9115 CLIParserContext *ctx;
9116 CLIParserInit(&ctx, "hf mf value",
9117 "MIFARE Classic value data commands\n",
9118 "hf mf value --blk 16 -k FFFFFFFFFFFF --set 1000\n"
9119 "hf mf value --blk 16 -k FFFFFFFFFFFF --inc 10\n"
9120 "hf mf value --blk 16 -k FFFFFFFFFFFF -b --dec 10\n"
9121 "hf mf value --blk 16 -k FFFFFFFFFFFF -b --get\n"
9122 "hf mf value --blk 16 -k FFFFFFFFFFFF --res --transfer 30 --tk FFFFFFFFFFFF --> transfer block 16 value to block 30 (even if block can't be incremented by ACL)\n"
9123 "hf mf value --get -d 87D612007829EDFF87D6120011EE11EE\n"
9125 void *argtable[] = {
9126 arg_param_begin,
9127 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9128 arg_lit0("a", NULL, "input key type is key A (def)"),
9129 arg_lit0("b", NULL, "input key type is key B"),
9130 arg_u64_0(NULL, "inc", "<dec>", "Increment value by X (0 - 2147483647)"),
9131 arg_u64_0(NULL, "dec", "<dec>", "Decrement value by X (0 - 2147483647)"),
9132 arg_u64_0(NULL, "set", "<dec>", "Set value to X (-2147483647 - 2147483647)"),
9133 arg_u64_0(NULL, "transfer", "<dec>", "Transfer value to other block (after inc/dec/restore)"),
9134 arg_str0(NULL, "tkey", "<hex>", "transfer key, 6 hex bytes (if transfer is preformed to other sector)"),
9135 arg_lit0(NULL, "ta", "transfer key type is key A (def)"),
9136 arg_lit0(NULL, "tb", "transfer key type is key B"),
9137 arg_lit0(NULL, "get", "Get value from block"),
9138 arg_lit0(NULL, "res", "Restore (copy value to card buffer, should be used with --transfer)"),
9139 arg_int0(NULL, "blk", "<dec>", "block number"),
9140 arg_str0("d", "data", "<hex>", "block data to extract values from (16 hex bytes)"),
9141 arg_param_end
9143 CLIExecWithReturn(ctx, Cmd, argtable, false);
9145 uint8_t blockno = (uint8_t)arg_get_int_def(ctx, 13, 1);
9147 uint8_t keytype = MF_KEY_A;
9148 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
9149 CLIParserFree(ctx);
9150 PrintAndLogEx(WARNING, "Choose one single input key type");
9151 return PM3_EINVARG;
9152 } else if (arg_get_lit(ctx, 3)) {
9153 keytype = MF_KEY_B;
9156 uint8_t transferkeytype = MF_KEY_A;
9157 if (arg_get_lit(ctx, 9) && arg_get_lit(ctx, 10)) {
9158 CLIParserFree(ctx);
9159 PrintAndLogEx(WARNING, "Choose one single transfer key type");
9160 return PM3_EINVARG;
9161 } else if (arg_get_lit(ctx, 10)) {
9162 transferkeytype = MF_KEY_B;
9165 int keylen = 0;
9166 uint8_t key[6] = {0};
9167 CLIGetHexWithReturn(ctx, 1, key, &keylen);
9169 int transferkeylen = 0;
9170 uint8_t transferkey[6] = {0};
9171 CLIGetHexWithReturn(ctx, 8, transferkey, &transferkeylen);
9174 Value /Value Value BLK /BLK BLK /BLK
9175 00000000 FFFFFFFF 00000000 10 EF 10 EF
9176 BLK is used to reference where the backup come from, I suspect it's just the current block for the actual value ?
9177 increment and decrement are an unsigned value
9178 set value is a signed value
9180 We are getting signed and/or bigger values to allow a default to be set meaning users did not supply that option.
9182 int64_t incval = (int64_t)arg_get_u64_def(ctx, 4, -1); // Inc by -1 is invalid, so not set.
9183 int64_t decval = (int64_t)arg_get_u64_def(ctx, 5, -1); // Dec by -1 is invalid, so not set.
9184 int64_t setval = (int64_t)arg_get_u64_def(ctx, 6, 0x7FFFFFFFFFFFFFFF); // out of bounds (for int32) so not set
9185 int64_t trnval = (int64_t)arg_get_u64_def(ctx, 7, -1); // block to transfer to
9186 bool getval = arg_get_lit(ctx, 11);
9187 bool resval = arg_get_lit(ctx, 12);
9188 int dlen = 0;
9189 uint8_t data[16] = {0};
9190 CLIGetHexWithReturn(ctx, 14, data, &dlen);
9191 CLIParserFree(ctx);
9193 // sanity checks
9196 // Action: 0 Increment, 1 - Decrement, 2 - Restore, 3 - Set, 4 - Get, 5 - Decode from data
9197 // iceman: TODO - should be enum
9198 uint8_t action = 4;
9199 uint32_t value = 0;
9201 // Need to check we only have 1 of inc/dec/set and get the value from the selected option
9202 int optionsprovided = 0;
9204 if (incval != -1) {
9205 optionsprovided++;
9206 action = 0;
9207 if ((incval <= 0) || (incval > 2147483647)) {
9208 PrintAndLogEx(WARNING, "increment value must be between 1 and 2147483647. Got %lli", incval);
9209 return PM3_EINVARG;
9210 } else
9211 value = (uint32_t)incval;
9214 if (decval != -1) {
9215 optionsprovided++;
9216 action = 1;
9217 if ((decval <= 0) || (decval > 2147483647)) {
9218 PrintAndLogEx(WARNING, "decrement value must be between 1 and 2147483647. Got %lli", decval);
9219 return PM3_EINVARG;
9220 } else
9221 value = (uint32_t)decval;
9224 if (setval != 0x7FFFFFFFFFFFFFFF) {
9225 optionsprovided++;
9226 action = 3;
9227 if ((setval < -2147483647) || (setval > 2147483647)) {
9228 PrintAndLogEx(WARNING, "set value must be between -2147483647 and 2147483647. Got %lli", setval);
9229 return PM3_EINVARG;
9230 } else
9231 value = (uint32_t)setval;
9234 if (resval) {
9235 if (trnval == -1) {
9236 PrintAndLogEx(WARNING, "You can't use restore without using transfer");
9237 return PM3_EINVARG;
9240 optionsprovided++;
9241 action = 2;
9244 if (dlen != 0) {
9245 optionsprovided++;
9246 action = 5;
9247 if (dlen != 16) {
9248 PrintAndLogEx(WARNING, "date length must be 16 hex bytes long, got %d", dlen);
9249 return PM3_EINVARG;
9253 if (optionsprovided > 1) {
9254 PrintAndLogEx(WARNING, "must have one and only one of --inc, --dec, --set or --data");
9255 return PM3_EINVARG;
9258 if (trnval != -1 && action > 2) {
9259 PrintAndLogEx(WARNING, "You can't use transfer without using --inc, --dec or --res");
9260 return PM3_EINVARG;
9263 if (trnval != -1 && transferkeylen == 0 && mfSectorNum(trnval) != mfSectorNum(blockno)) {
9264 PrintAndLogEx(WARNING, "Transfer is preformed to other sector, but no key for new sector provided");
9265 return PM3_EINVARG;
9268 // don't want to write value data and break something
9269 if ((blockno == 0) ||
9270 (mfIsSectorTrailer(blockno)) ||
9271 (trnval == 0) ||
9272 (trnval != -1 && mfIsSectorTrailer(trnval))) {
9273 PrintAndLogEx(WARNING, "invalid block number, should be a data block");
9274 return PM3_EINVARG;
9277 if (action < 4) {
9279 uint8_t isok = true;
9280 if (g_session.pm3_present == false)
9281 return PM3_ENOTTY;
9283 // 0 Increment, 1 - Decrement, 2 - Restore, 3 - Set, 4 - Get, 5 - Decode from data
9284 if (action <= 2) {
9286 uint8_t block[MFBLOCK_SIZE] = {0x00};
9287 memcpy(block, (uint8_t *)&value, 4);
9289 uint8_t cmddata[34];
9290 memcpy(cmddata, key, sizeof(key));
9291 // Key == 6 data went to 10, so lets offset 9 for inc/dec
9293 if (action == 0) {
9294 PrintAndLogEx(INFO, "Value incremented by : %d", (int32_t)value);
9296 if (action == 1) {
9297 PrintAndLogEx(INFO, "Value decremented by : %d", (int32_t)value);
9300 // 00 if increment, 01 if decrement, 02 if restore
9301 cmddata[9] = action;
9303 if (trnval != -1) {
9305 // transfer to block
9306 cmddata[10] = trnval;
9308 memcpy(cmddata + 27, transferkey, sizeof(transferkey));
9309 if (mfSectorNum(trnval) != mfSectorNum(blockno)) {
9310 cmddata[33] = 1; // should send nested auth
9312 PrintAndLogEx(INFO, "Transfer block no %u to block %" PRId64, blockno, trnval);
9314 } else {
9315 cmddata[10] = 0;
9316 if (keytype < 2) {
9317 PrintAndLogEx(INFO, "Writing block no %u, key type:%c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
9318 } else {
9319 PrintAndLogEx(INFO, "Writing block no %u, key type:%02x - %s", blockno, MIFARE_AUTH_KEYA + keytype, sprint_hex_inrow(key, sizeof(key)));
9323 memcpy(cmddata + 11, block, sizeof(block));
9325 clearCommandBuffer();
9326 SendCommandMIX(CMD_HF_MIFARE_VALUE, blockno, keytype, transferkeytype, cmddata, sizeof(cmddata));
9328 PacketResponseNG resp;
9329 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
9330 PrintAndLogEx(FAILED, "command execution time out");
9331 return PM3_ETIMEOUT;
9333 isok = resp.oldarg[0] & 0xff;
9334 } else { // set value
9335 // To set a value block (or setup) we can use the normal mifare classic write block
9336 // So build the command options can call CMD_HF_MIFARE_WRITEBL
9337 PrintAndLogEx(INFO, "set value to : %d", (int32_t)value);
9339 uint8_t writedata[26] = {0x00};
9340 int32_t invertvalue = value ^ 0xFFFFFFFF;
9341 memcpy(writedata, key, sizeof(key));
9342 memcpy(writedata + 10, (uint8_t *)&value, 4);
9343 memcpy(writedata + 14, (uint8_t *)&invertvalue, 4);
9344 memcpy(writedata + 18, (uint8_t *)&value, 4);
9345 writedata[22] = blockno;
9346 writedata[23] = (blockno ^ 0xFF);
9347 writedata[24] = blockno;
9348 writedata[25] = (blockno ^ 0xFF);
9350 clearCommandBuffer();
9351 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, keytype, 0, writedata, sizeof(writedata));
9353 PacketResponseNG resp;
9354 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
9355 PrintAndLogEx(FAILED, "command execution time out");
9356 return PM3_ETIMEOUT;
9359 isok = resp.oldarg[0] & 0xff;
9362 if (isok) {
9363 PrintAndLogEx(SUCCESS, "Update ... : " _GREEN_("success"));
9364 getval = true;
9365 // all ok so set flag to read current value
9366 } else {
9367 PrintAndLogEx(FAILED, "Update ... : " _RED_("failed"));
9371 // If all went well getval will be true, so read the current value and display
9372 if (getval) {
9373 int32_t readvalue;
9374 int res = -1;
9376 if (action == 5) {
9377 res = PM3_SUCCESS;
9378 // already have data from command line
9379 } else {
9380 if (trnval == -1) {
9381 res = mf_read_block(blockno, keytype, key, data);
9382 } else {
9383 if (mfSectorNum(trnval) != mfSectorNum(blockno))
9384 res = mf_read_block(trnval, transferkeytype, transferkey, data);
9385 else
9386 res = mf_read_block(trnval, keytype, key, data);
9390 if (res == PM3_SUCCESS) {
9391 if (mfc_value(data, &readvalue)) {
9392 PrintAndLogEx(SUCCESS, "Dec ...... : " _YELLOW_("%" PRIi32), readvalue);
9393 PrintAndLogEx(SUCCESS, "Hex ...... : " _YELLOW_("0x%" PRIX32), readvalue);
9394 } else {
9395 PrintAndLogEx(FAILED, "No value block detected");
9397 } else {
9398 PrintAndLogEx(FAILED, "failed to read value block");
9402 return PM3_SUCCESS;
9405 static int CmdHFMFHidEncode(const char *Cmd) {
9406 CLIParserContext *ctx;
9407 CLIParserInit(&ctx, "hf mf encodehid",
9408 "Encode binary wiegand to card\n"
9409 "Use either --bin or --wiegand/--fc/--cn",
9410 "hf mf encodehid --bin 10001111100000001010100011 -> FC 31 CN 337 (H10301)\n"
9411 "hf mf encodehid -w H10301 --fc 31 --cn 337\n"
9414 void *argtable[] = {
9415 arg_param_begin,
9416 arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
9417 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
9418 arg_u64_0(NULL, "cn", "<dec>", "card number"),
9419 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
9420 arg_lit0("v", "verbose", "verbose output"),
9421 arg_param_end
9423 CLIExecWithReturn(ctx, Cmd, argtable, false);
9425 uint8_t bin[121] = {0};
9426 int bin_len = sizeof(bin) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated
9427 CLIGetStrWithReturn(ctx, 1, bin, &bin_len);
9429 wiegand_card_t card;
9430 memset(&card, 0, sizeof(wiegand_card_t));
9431 card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
9432 card.CardNumber = arg_get_u32_def(ctx, 3, 0);
9434 char format[16] = {0};
9435 int format_len = 0;
9436 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)format, sizeof(format), &format_len);
9438 bool verbose = arg_get_lit(ctx, 5);
9439 CLIParserFree(ctx);
9441 // santity checks
9442 if (bin_len > 120) {
9443 PrintAndLogEx(ERR, "Binary wiegand string must be less than 120 bits");
9444 return PM3_EINVARG;
9447 if (bin_len == 0 && card.FacilityCode == 0 && card.CardNumber == 0) {
9448 PrintAndLogEx(ERR, "Must provide either --cn/--fc or --bin");
9449 return PM3_EINVARG;
9452 uint8_t blocks[] = {
9453 0x1B, 0x01, 0x4D, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9455 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A,
9456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9457 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9459 0x48, 0x49, 0x44, 0x20, 0x49, 0x53, 0x78, 0x77, 0x88, 0xAA, 0x20, 0x47, 0x52, 0x45, 0x41, 0x54,
9462 if (bin_len) {
9463 char mfcbin[121] = {0};
9464 mfcbin[0] = '1';
9465 memcpy(mfcbin + 1, bin, bin_len);
9467 size_t hexlen = 0;
9468 uint8_t hex[15] = {0};
9469 binstr_2_bytes(hex, &hexlen, mfcbin);
9471 memcpy(blocks + (MFBLOCK_SIZE * 4) + 1 + (15 - hexlen), hex, hexlen);
9472 } else {
9473 wiegand_message_t packed;
9474 memset(&packed, 0, sizeof(wiegand_message_t));
9476 int format_idx = HIDFindCardFormat(format);
9477 if (format_idx == -1) {
9478 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
9479 return PM3_EINVARG;
9482 if (HIDPack(format_idx, &card, &packed, false) == false) {
9483 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
9484 return PM3_ESOFT;
9487 // iceman: only for formats w length smaller than 37.
9488 // Needs a check.
9490 // increase length to allow setting bit just above real data
9491 packed.Length++;
9492 // Set sentinel bit
9493 set_bit_by_position(&packed, true, 0);
9495 #ifdef HOST_LITTLE_ENDIAN
9496 packed.Mid = BSWAP_32(packed.Mid);
9497 packed.Bot = BSWAP_32(packed.Bot);
9498 #endif
9500 memcpy(blocks + (MFBLOCK_SIZE * 4) + 8, &packed.Mid, sizeof(packed.Mid));
9501 memcpy(blocks + (MFBLOCK_SIZE * 4) + 12, &packed.Bot, sizeof(packed.Bot));
9504 uint8_t empty[MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
9505 bool res = true;
9506 for (uint8_t i = 0; i < (sizeof(blocks) / MFBLOCK_SIZE); i++) {
9508 if (verbose) {
9509 PrintAndLogEx(INFO, "Writing %u - %s", (i + 1), sprint_hex_inrow(blocks + (i * MFBLOCK_SIZE), MFBLOCK_SIZE));
9512 if (mf_write_block((i + 1), MF_KEY_A, empty, blocks + (i * MFBLOCK_SIZE)) == PM3_EFAILED) {
9513 if (mf_write_block((i + 1), MF_KEY_B, empty, blocks + (i * MFBLOCK_SIZE)) == PM3_EFAILED) {
9514 PrintAndLogEx(WARNING, "failed writing block %d using default empty key", (i + 1));
9515 res = false;
9516 break;
9520 if (res == false) {
9521 PrintAndLogEx(WARNING, "Make sure card is wiped before running this command");
9523 PrintAndLogEx(NORMAL, "");
9524 return PM3_SUCCESS;
9527 static int CmdHF14AMfInfo(const char *Cmd) {
9528 CLIParserContext *ctx;
9529 CLIParserInit(&ctx, "hf mf info",
9530 "Information and check vulnerabilities in a MIFARE Classic card\n"
9531 "Some cards in order to extract information you need to specify key\n"
9532 "and/or specific keys in the command line",
9533 "hf mf info\n"
9534 "hf mf info -k FFFFFFFFFFFF -n -v\n"
9537 void *argtable[] = {
9538 arg_param_begin,
9539 arg_int0(NULL, "blk", "<dec>", "block number"),
9540 arg_lit0("a", NULL, "input key type is key A (def)"),
9541 arg_lit0("b", NULL, "input key type is key B"),
9542 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9543 arg_lit0("n", "nack", "do nack test"),
9544 arg_lit0("v", "verbose", "verbose output"),
9545 arg_param_end
9547 CLIExecWithReturn(ctx, Cmd, argtable, true);
9549 int blockn = arg_get_int_def(ctx, 1, 0);
9551 uint8_t keytype = MF_KEY_A;
9552 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
9553 CLIParserFree(ctx);
9554 PrintAndLogEx(WARNING, "Choose one single input key type");
9555 return PM3_EINVARG;
9556 } else if (arg_get_lit(ctx, 3)) {
9557 keytype = MF_KEY_B;
9560 int keylen = 0;
9561 uint8_t key[100 * MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
9562 CLIGetHexWithReturn(ctx, 4, key, &keylen);
9564 bool do_nack_test = arg_get_lit(ctx, 5);
9565 bool verbose = arg_get_lit(ctx, 6);
9566 CLIParserFree(ctx);
9568 uint8_t dbg_curr = DBG_NONE;
9569 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
9570 return PM3_EFAILED;
9573 if (keylen != 0 && keylen != MIFARE_KEY_SIZE) {
9574 PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE);
9575 return PM3_EINVARG;
9578 clearCommandBuffer();
9579 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
9580 PacketResponseNG resp;
9581 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
9582 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
9583 return 0;
9586 iso14a_card_select_t card;
9587 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
9590 0: couldn't read
9591 1: OK, with ATS
9592 2: OK, no ATS
9593 3: proprietary Anticollision
9595 uint64_t select_status = resp.oldarg[0];
9597 if (select_status == 0) {
9598 PrintAndLogEx(DEBUG, "iso14443a card select failed");
9599 return select_status;
9602 if (select_status == 3) {
9603 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
9605 if (verbose) {
9606 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
9608 return select_status;
9611 PrintAndLogEx(NORMAL, "");
9612 PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " ---------------------");
9613 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
9614 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
9615 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
9617 if (setDeviceDebugLevel(verbose ? MAX(dbg_curr, DBG_INFO) : DBG_NONE, false) != PM3_SUCCESS) {
9618 return PM3_EFAILED;
9621 uint8_t signature[32] = {0};
9622 int res = read_mfc_ev1_signature(signature);
9623 if (res == PM3_SUCCESS) {
9624 mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
9627 PrintAndLogEx(NORMAL, "");
9628 PrintAndLogEx(INFO, "--- " _CYAN_("Keys Information"));
9630 uint8_t fkey[MIFARE_KEY_SIZE] = {0};
9631 uint8_t fKeyType = 0xFF;
9633 uint64_t tmpkey = 0;
9634 mfc_algo_saflok_one(card.uid, 0, MF_KEY_A, &tmpkey);
9635 num_to_bytes(tmpkey, MIFARE_KEY_SIZE, key + MIFARE_KEY_SIZE);
9637 int sectorsCnt = 2;
9638 uint8_t *keyBlock = NULL;
9639 uint32_t keycnt = 0;
9640 res = mf_load_keys(&keyBlock, &keycnt, key, MIFARE_KEY_SIZE * 2, NULL, 0, true);
9641 if (res != PM3_SUCCESS) {
9642 return res;
9645 // create/initialize key storage structure
9646 sector_t *e_sector = NULL;
9647 if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
9648 free(keyBlock);
9649 return PM3_EMALLOC;
9652 uint8_t blockdata[MFBLOCK_SIZE] = {0};
9653 res = mf_check_keys_fast(sectorsCnt, true, true, 1, keycnt, keyBlock, e_sector, false, verbose);
9654 if (res == PM3_SUCCESS || res == PM3_EPARTIAL) {
9656 if (e_sector[0].foundKey[MF_KEY_A]) {
9657 PrintAndLogEx(SUCCESS, "Sector 0 key A... " _GREEN_("%012" PRIX64), e_sector[0].Key[MF_KEY_A]);
9659 num_to_bytes(e_sector[0].Key[MF_KEY_A], MIFARE_KEY_SIZE, fkey);
9660 if (mf_read_block(0, MF_KEY_A, key, blockdata) == PM3_SUCCESS) {
9661 fKeyType = MF_KEY_A;
9665 if (e_sector[0].foundKey[MF_KEY_B]) {
9666 PrintAndLogEx(SUCCESS, "Sector 0 key B... " _GREEN_("%012" PRIX64), e_sector[0].Key[MF_KEY_B]);
9668 if (fKeyType == 0xFF) {
9669 num_to_bytes(e_sector[0].Key[MF_KEY_B], MIFARE_KEY_SIZE, fkey);
9670 if (mf_read_block(0, MF_KEY_B, key, blockdata) == PM3_SUCCESS) {
9671 fKeyType = MF_KEY_B;
9676 if (e_sector[1].foundKey[MF_KEY_A]) {
9677 PrintAndLogEx(SUCCESS, "Sector 1 key A... " _GREEN_("%012" PRIX64), e_sector[1].Key[MF_KEY_A]);
9681 uint8_t k08s[6] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
9682 uint8_t k08[6] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
9683 uint8_t k32[6] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60};
9684 if (mf_read_block(0, 4, k08s, blockdata) == PM3_SUCCESS) {
9685 PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s)));
9686 fKeyType = MF_KEY_BD;
9687 memcpy(fkey, k08s, sizeof(fkey));
9689 } else if (mf_read_block(0, 4, k08, blockdata) == PM3_SUCCESS) {
9690 PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08, sizeof(k08)));
9691 fKeyType = MF_KEY_BD;
9692 memcpy(fkey, k08, sizeof(fkey));
9693 } else if (mf_read_block(0, 4, k32, blockdata) == PM3_SUCCESS) {
9694 PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k32, sizeof(k32)));
9695 fKeyType = MF_KEY_BD;
9696 memcpy(fkey, k32, sizeof(fkey));
9699 if (fKeyType != 0xFF) {
9700 PrintAndLogEx(SUCCESS, "Block 0.... %s | " NOLF, sprint_hex_inrow(blockdata, MFBLOCK_SIZE));
9701 PrintAndLogEx(NORMAL, "%s", sprint_ascii(blockdata + 8, 8));
9704 PrintAndLogEx(NORMAL, "");
9705 PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
9707 if (fKeyType != 0xFF) {
9708 // cards with known backdoor
9709 if (card.sak != 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) {
9710 // backdoor might be present, or just a clone reusing Fudan MF data...
9711 PrintAndLogEx(SUCCESS, "Fudan based card");
9712 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0
9713 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
9714 && (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x90) {
9715 PrintAndLogEx(SUCCESS, "Fudan FM11RF08S");
9716 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08s, sizeof(fkey)) == 0
9717 && card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x03\x00\x10", 4) == 0
9718 && blockdata[15] == 0x90) {
9719 PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B");
9720 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9721 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
9722 && blockdata[15] == 0x98) {
9723 PrintAndLogEx(SUCCESS, "Fudan FM11RF08S **98");
9724 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9725 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
9726 && (blockdata[8] >= 0x01 && blockdata[8] <= 0x03) && blockdata[15] == 0x1D) {
9727 PrintAndLogEx(SUCCESS, "Fudan FM11RF08");
9728 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k32, sizeof(fkey)) == 0
9729 && card.sak == 0x18 && memcmp(blockdata + 5, "\x18\x02\x00\x46\x44\x53\x37\x30\x56\x30\x31", 11) == 0) {
9730 PrintAndLogEx(SUCCESS, "Fudan FM11RF32");
9731 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9732 && card.sak == 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) {
9733 PrintAndLogEx(SUCCESS, "Fudan FM11RF32 (SAK=20)");
9734 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9735 && card.sak == 0x28 && (
9736 (memcmp(blockdata + 5, "\x28\x04\x00\x90\x10\x15\x01\x00\x00\x00\x00", 11) == 0) ||
9737 (memcmp(blockdata + 5, "\x28\x04\x00\x90\x11\x15\x01\x00\x00\x00\x00", 11) == 0))) {
9738 // Note: it also has ATS =
9739 // 10 78 80 90 02 20 90 00 00 00 00 00 + UID + CRC
9740 PrintAndLogEx(SUCCESS, "Fudan FM1208-10");
9741 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9742 && card.sak == 0x28 && memcmp(blockdata + 5, "\x28\x04\x00\x90\x53\xB7\x0C\x00\x00\x00\x00", 11) == 0) {
9743 // Note: it also has ATS =
9744 // 10 78 80 B0 02 20 90 00 00 00 00 00 + UID + CRC
9745 PrintAndLogEx(SUCCESS, "Fudan FM1216-137");
9746 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9747 && card.sak == 0x88 && memcmp(blockdata + 5, "\x88\x04\x00\x43", 4) == 0) {
9748 PrintAndLogEx(SUCCESS, "Infineon SLE66R35");
9749 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9750 && card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x44", 4) == 0) {
9751 PrintAndLogEx(SUCCESS, "NXP MF1ICS5003");
9752 } else if (fKeyType == MF_KEY_BD && memcmp(fkey, k08, sizeof(fkey)) == 0
9753 && card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x45", 4) == 0) {
9754 PrintAndLogEx(SUCCESS, "NXP MF1ICS5004");
9755 } else if (fKeyType == MF_KEY_BD) {
9756 PrintAndLogEx(SUCCESS, _RED_("Unknown card with backdoor, please report details!"));
9757 } else
9758 // other cards
9759 if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x46", 4) == 0) {
9760 PrintAndLogEx(SUCCESS, "NXP MF1ICS5005");
9761 } else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x47", 4) == 0) {
9762 PrintAndLogEx(SUCCESS, "NXP MF1ICS5006");
9763 } else if (card.sak == 0x09 && memcmp(blockdata + 5, "\x89\x04\x00\x47", 4) == 0) {
9764 PrintAndLogEx(SUCCESS, "NXP MF1ICS2006");
9765 } else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x48", 4) == 0) {
9766 PrintAndLogEx(SUCCESS, "NXP MF1ICS5007");
9767 } else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\xc0", 4) == 0) {
9768 PrintAndLogEx(SUCCESS, "NXP MF1ICS5035");
9769 } else {
9770 PrintAndLogEx(SUCCESS, "unknown");
9773 if (e_sector[1].foundKey[MF_KEY_A] && (e_sector[1].Key[MF_KEY_A] == 0x2A2C13CC242A)) {
9774 PrintAndLogEx(SUCCESS, "Dorma Kaba SAFLOK detected");
9777 } else {
9778 PrintAndLogEx(INFO, "<n/a>");
9781 PrintAndLogEx(NORMAL, "");
9782 PrintAndLogEx(INFO, "--- " _CYAN_("Magic Tag Information"));
9783 if (detect_mf_magic(true, MF_KEY_B, e_sector[0].Key[MF_KEY_B]) == MAGIC_FLAG_NONE) {
9784 if (detect_mf_magic(true, MF_KEY_A, e_sector[0].Key[MF_KEY_A]) == MAGIC_FLAG_NONE) {
9785 PrintAndLogEx(INFO, "<n/a>");
9789 free(keyBlock);
9790 free(e_sector);
9792 PrintAndLogEx(NORMAL, "");
9793 PrintAndLogEx(INFO, "--- " _CYAN_("PRNG Information"));
9795 res = detect_classic_static_nonce();
9796 if (res == NONCE_STATIC) {
9797 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
9801 if (res == NONCE_NORMAL) {
9802 // not static
9803 res = detect_classic_prng();
9804 if (res == 1) {
9805 PrintAndLogEx(SUCCESS, "Prng....... " _GREEN_("weak"));
9806 } else if (res == 0) {
9807 PrintAndLogEx(SUCCESS, "Prng....... " _YELLOW_("hard"));
9808 } else {
9809 PrintAndLogEx(FAILED, "Prng........ " _RED_("fail"));
9812 // detect static encrypted nonce
9813 if (keylen == MIFARE_KEY_SIZE) {
9814 res = detect_classic_static_encrypted_nonce(blockn, keytype, key);
9815 if (res == NONCE_STATIC) {
9816 PrintAndLogEx(SUCCESS, "Static nonce... " _YELLOW_("yes"));
9817 fKeyType = 0xFF; // dont detect twice
9818 } else if (res == NONCE_SUPERSTATIC) {
9819 PrintAndLogEx(SUCCESS, "Static nonce... " _YELLOW_("yes, even when nested"));
9820 fKeyType = 0xFF; // dont detect twice
9821 } else if (res == NONCE_STATIC_ENC) {
9822 PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes"));
9823 fKeyType = 0xFF; // dont detect twice
9827 if (fKeyType != 0xFF) {
9828 res = detect_classic_static_encrypted_nonce(0, fKeyType, fkey);
9829 if (res == NONCE_STATIC) {
9830 PrintAndLogEx(SUCCESS, "Static nonce... " _YELLOW_("yes"));
9831 } else if (res == NONCE_SUPERSTATIC) {
9832 PrintAndLogEx(SUCCESS, "Static nonce... " _YELLOW_("yes, even when nested"));
9833 } else if (res == NONCE_STATIC_ENC) {
9834 PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes"));
9838 if (do_nack_test) {
9839 detect_classic_nackbug(verbose);
9843 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
9844 return PM3_EFAILED;
9847 PrintAndLogEx(NORMAL, "");
9848 return PM3_SUCCESS;
9851 static int CmdHF14AMfISEN(const char *Cmd) {
9852 CLIParserContext *ctx;
9853 CLIParserInit(&ctx, "hf mf isen",
9854 "Information about Static Encrypted Nonce properties in a MIFARE Classic card",
9855 "hf mf isen\n"
9856 "Default behavior:\n"
9857 "auth(blk)-auth(blk2)-auth(blk2)-...\n"
9858 "Default behavior when wrong key2:\n"
9859 "auth(blk)-auth(blk2) auth(blk)-auth(blk2) ...\n"
9862 void *argtable[] = {
9863 arg_param_begin,
9864 arg_int0(NULL, "blk", "<dec>", "block number"),
9865 arg_lit0("a", NULL, "input key type is key A (def)"),
9866 arg_lit0("b", NULL, "input key type is key B"),
9867 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
9868 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9869 arg_int0(NULL, "blk2", "<dec>", "nested block number (default=same)"),
9870 arg_lit0(NULL, "a2", "nested input key type is key A (default=same)"),
9871 arg_lit0(NULL, "b2", "nested input key type is key B (default=same)"),
9872 arg_int0(NULL, "c2", "<dec>", "nested input key type is key A + offset"),
9873 arg_str0(NULL, "key2", "<hex>", "nested key, 6 hex bytes (default=same)"),
9874 arg_int0("n", NULL, "<dec>", "number of nonces (default=2)"),
9875 arg_lit0(NULL, "reset", "reset between attempts, even if auth was successful"),
9876 arg_lit0(NULL, "hardreset", "hard reset (RF off/on) between attempts, even if auth was successful"),
9877 arg_lit0(NULL, "addread", "auth(blk)-read(blk)-auth(blk2)"),
9878 arg_lit0(NULL, "addauth", "auth(blk)-auth(blk)-auth(blk2)"),
9879 arg_lit0(NULL, "incblk2", "auth(blk)-auth(blk2)-auth(blk2+4)-..."),
9880 arg_lit0(NULL, "corruptnrar", "corrupt {nR}{aR}, but with correct parity"),
9881 arg_lit0(NULL, "corruptnrarparity", "correct {nR}{aR}, but with corrupted parity"),
9882 arg_rem("", ""),
9883 arg_rem("FM11RF08S specific options:", "Incompatible with above options, except -k; output in JSON"),
9884 arg_lit0(NULL, "collect_fm11rf08s", "collect all nT/{nT}/par_err."),
9885 arg_lit0(NULL, "collect_fm11rf08s_with_data", "collect all nT/{nT}/par_err and data blocks."),
9886 arg_str0("f", "file", "<fn>", "Specify a filename for collected data"),
9887 arg_param_end
9889 CLIExecWithReturn(ctx, Cmd, argtable, true);
9891 int blockn = arg_get_int_def(ctx, 1, 0);
9893 uint8_t keytype = MF_KEY_A;
9894 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
9895 CLIParserFree(ctx);
9896 PrintAndLogEx(WARNING, "Choose one single input key type");
9897 return PM3_EINVARG;
9898 } else if (arg_get_lit(ctx, 3)) {
9899 keytype = MF_KEY_B;
9901 uint8_t prev_keytype = keytype;
9902 keytype = arg_get_int_def(ctx, 4, keytype);
9903 if ((arg_get_lit(ctx, 2) || arg_get_lit(ctx, 3)) && (keytype != prev_keytype)) {
9904 CLIParserFree(ctx);
9905 PrintAndLogEx(WARNING, "Choose one single input key type");
9906 return PM3_EINVARG;
9909 int keylen = 0;
9910 uint8_t key[MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
9911 CLIGetHexWithReturn(ctx, 5, key, &keylen);
9913 int blockn_nested = arg_get_int_def(ctx, 6, blockn);
9915 uint8_t keytype_nested = keytype;
9916 if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) {
9917 CLIParserFree(ctx);
9918 PrintAndLogEx(WARNING, "Choose one single nested input key type");
9919 return PM3_EINVARG;
9920 } else if (arg_get_lit(ctx, 7)) {
9921 keytype_nested = MF_KEY_A;
9922 } else if (arg_get_lit(ctx, 8)) {
9923 keytype_nested = MF_KEY_B;
9925 uint8_t prev_keytype_nested = keytype_nested;
9926 keytype_nested = arg_get_int_def(ctx, 9, keytype_nested);
9927 if ((arg_get_lit(ctx, 7) || arg_get_lit(ctx, 8)) && (keytype_nested != prev_keytype_nested)) {
9928 CLIParserFree(ctx);
9929 PrintAndLogEx(WARNING, "Choose one single nested input key type");
9930 return PM3_EINVARG;
9933 int keylen_nested = 0;
9934 uint8_t key_nested[MIFARE_KEY_SIZE];
9935 memcpy(key_nested, key, MIFARE_KEY_SIZE);
9936 CLIGetHexWithReturn(ctx, 10, key_nested, &keylen_nested);
9938 int nr_nested = arg_get_int_def(ctx, 11, 2);
9940 bool reset = arg_get_lit(ctx, 12);
9941 bool hardreset = arg_get_lit(ctx, 13);
9942 if (reset && hardreset) {
9943 CLIParserFree(ctx);
9944 PrintAndLogEx(WARNING, "Choose one single type of reset");
9945 return PM3_EINVARG;
9947 bool addread = arg_get_lit(ctx, 14);
9948 bool addauth = arg_get_lit(ctx, 15);
9949 bool incblk2 = arg_get_lit(ctx, 16);
9950 bool corruptnrar = arg_get_lit(ctx, 17);
9951 bool corruptnrarparity = arg_get_lit(ctx, 18);
9952 bool collect_fm11rf08s = arg_get_lit(ctx, 21);
9953 bool collect_fm11rf08s_with_data = arg_get_lit(ctx, 22);
9954 if (collect_fm11rf08s_with_data) {
9955 collect_fm11rf08s = 1;
9957 int fnlen = 0;
9958 char filename[FILE_PATH_SIZE] = {0};
9959 CLIParamStrToBuf(arg_get_str(ctx, 23), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
9961 CLIParserFree(ctx);
9963 uint8_t dbg_curr = DBG_NONE;
9964 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
9965 return PM3_EFAILED;
9968 if (keylen != 0 && keylen != MIFARE_KEY_SIZE) {
9969 PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE);
9970 return PM3_EINVARG;
9973 if (keylen_nested != 0 && keylen_nested != MIFARE_KEY_SIZE) {
9974 PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE);
9975 return PM3_EINVARG;
9978 clearCommandBuffer();
9979 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
9980 PacketResponseNG resp;
9981 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
9982 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
9983 return 0;
9986 iso14a_card_select_t card;
9987 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
9990 0: couldn't read
9991 1: OK, with ATS
9992 2: OK, no ATS
9993 3: proprietary Anticollision
9995 uint64_t select_status = resp.oldarg[0];
9997 if (select_status == 0) {
9998 PrintAndLogEx(DEBUG, "iso14443a card select failed");
9999 return select_status;
10002 if (select_status == 3) {
10003 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
10006 if (collect_fm11rf08s) {
10007 uint64_t t1 = msclock();
10008 uint32_t flags = collect_fm11rf08s_with_data;
10009 SendCommandMIX(CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES, flags, 0, 0, key, sizeof(key));
10010 if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) {
10011 if (resp.status == PM3_ESOFT) {
10012 return NONCE_FAIL;
10015 uint8_t num_sectors = MIFARE_1K_MAXSECTOR + 1;
10016 iso14a_fm11rf08s_nonces_with_data_t nonces_dump = {0};
10017 for (uint8_t sec = 0; sec < num_sectors; sec++) {
10018 // reconstruct full nt
10019 uint32_t nt;
10020 nt = bytes_to_num(resp.data.asBytes + ((sec * 2) * 8), 2);
10021 nt = nt << 16 | prng_successor(nt, 16);
10022 num_to_bytes(nt, 4, nonces_dump.nt[sec][0]);
10023 nt = bytes_to_num(resp.data.asBytes + (((sec * 2) + 1) * 8), 2);
10024 nt = nt << 16 | prng_successor(nt, 16);
10025 num_to_bytes(nt, 4, nonces_dump.nt[sec][1]);
10027 for (uint8_t sec = 0; sec < num_sectors; sec++) {
10028 memcpy(nonces_dump.nt_enc[sec][0], resp.data.asBytes + ((sec * 2) * 8) + 4, 4);
10029 memcpy(nonces_dump.nt_enc[sec][1], resp.data.asBytes + (((sec * 2) + 1) * 8) + 4, 4);
10031 for (uint8_t sec = 0; sec < num_sectors; sec++) {
10032 nonces_dump.par_err[sec][0] = resp.data.asBytes[((sec * 2) * 8) + 2];
10033 nonces_dump.par_err[sec][1] = resp.data.asBytes[(((sec * 2) + 1) * 8) + 2];
10035 if (collect_fm11rf08s_with_data) {
10036 int bytes = MIFARE_1K_MAXBLOCK * MFBLOCK_SIZE;
10038 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
10039 if (dump == NULL) {
10040 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
10041 return PM3_EFAILED;
10043 if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
10044 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
10045 free(dump);
10046 return PM3_ETIMEOUT;
10048 for (uint8_t blk = 0; blk < MIFARE_1K_MAXBLOCK; blk++) {
10049 memcpy(nonces_dump.blocks[blk], dump + blk * MFBLOCK_SIZE, MFBLOCK_SIZE);
10051 free(dump);
10053 t1 = msclock() - t1;
10054 PrintAndLogEx(SUCCESS, "time: " _YELLOW_("%" PRIu64) " ms", t1);
10056 if (fnlen == 0) {
10057 snprintf(filename, sizeof(filename), "hf-mf-%s-nonces%s", sprint_hex_inrow(card.uid, card.uidlen), collect_fm11rf08s_with_data ? "_with_data" : "");
10059 if (pm3_save_fm11rf08s_nonces(filename, &nonces_dump, collect_fm11rf08s_with_data) != PM3_SUCCESS) {
10060 return PM3_EFAILED;
10062 return PM3_SUCCESS;
10065 PrintAndLogEx(NORMAL, "");
10066 PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " ---------------------");
10067 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
10068 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
10069 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
10071 // if (setDeviceDebugLevel(DBG_DEBUG, false) != PM3_SUCCESS) {
10072 if (setDeviceDebugLevel(DBG_EXTENDED, false) != PM3_SUCCESS) {
10073 return PM3_EFAILED;
10076 int res = detect_classic_static_encrypted_nonce_ex(blockn, keytype, key, blockn_nested, keytype_nested, key_nested, nr_nested, reset, hardreset, addread, addauth, incblk2, corruptnrar, corruptnrarparity, true);
10077 if (res == NONCE_STATIC) {
10078 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
10079 } else if (res == NONCE_SUPERSTATIC) {
10080 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes, even when nested"));
10081 } else if (res == NONCE_STATIC_ENC) {
10082 PrintAndLogEx(SUCCESS, "Static enc nonce..... " _RED_("yes"));
10084 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
10085 return PM3_EFAILED;
10088 PrintAndLogEx(NORMAL, "");
10089 return PM3_SUCCESS;
10092 static command_t CommandTable[] = {
10093 {"help", CmdHelp, AlwaysAvailable, "This help"},
10094 {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
10095 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -----------------------"},
10096 {"info", CmdHF14AMfInfo, IfPm3Iso14443a, "mfc card Info"},
10097 {"isen", CmdHF14AMfISEN, IfPm3Iso14443a, "mfc card Info Static Encrypted Nonces"},
10098 {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"},
10099 {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"},
10100 {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"},
10101 {"staticnested", CmdHF14AMfNestedStatic, IfPm3Iso14443a, "Nested attack against static nonce MIFARE Classic cards"},
10102 {"brute", CmdHF14AMfSmartBrute, IfPm3Iso14443a, "Smart bruteforce to exploit weak key generators"},
10103 {"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"},
10104 // {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"},
10105 {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"},
10106 {"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"},
10107 {"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"},
10108 {"decrypt", CmdHf14AMfDecryptBytes, AlwaysAvailable, "Decrypt Crypto1 data from sniff or trace"},
10109 {"supercard", CmdHf14AMfSuperCard, IfPm3Iso14443a, "Extract info from a `super card`"},
10110 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
10111 {"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"},
10112 {"acl", CmdHF14AMfAcl, AlwaysAvailable, "Decode and print MIFARE Classic access rights bytes"},
10113 {"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE Classic tag to binary file"},
10114 {"mad", CmdHF14AMfMAD, AlwaysAvailable, "Checks and prints MAD"},
10115 {"personalize", CmdHFMFPersonalize, IfPm3Iso14443a, "Personalize UID (MIFARE Classic EV1 only)"},
10116 {"rdbl", CmdHF14AMfRdBl, IfPm3Iso14443a, "Read MIFARE Classic block"},
10117 {"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"},
10118 {"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to tag"},
10119 {"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"},
10120 {"value", CmdHF14AMfValue, AlwaysAvailable, "Value blocks"},
10121 {"view", CmdHF14AMfView, AlwaysAvailable, "Display content from tag dump file"},
10122 {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"},
10123 {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"},
10124 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
10125 {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"},
10126 {"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill emulator memory with help of keys from emulator"},
10127 {"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear emulator memory"},
10128 {"egetblk", CmdHF14AMfEGetBlk, IfPm3Iso14443a, "Get emulator memory block"},
10129 {"egetsc", CmdHF14AMfEGetSc, IfPm3Iso14443a, "Get emulator memory sector"},
10130 {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from emulator memory"},
10131 {"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Upload file into emulator memory"},
10132 {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save emulator memory to file"},
10133 {"esetblk", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"},
10134 {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emulator memory"},
10135 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"},
10136 {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block from card"},
10137 {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector from card"},
10138 {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump to card"},
10139 {"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from card into file or emulator"},
10140 {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block to card"},
10141 {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID on card"},
10142 {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "View card"},
10143 {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"},
10144 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"},
10145 {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"},
10146 {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"},
10147 {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"},
10148 {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"},
10149 {"ginfo", CmdHF14AGen4Info, IfPm3Iso14443a, "Info about configuration of the card"},
10150 {"ggetblk", CmdHF14AGen4GetBlk, IfPm3Iso14443a, "Read block from card"},
10151 {"gload", CmdHF14AGen4Load, IfPm3Iso14443a, "Load dump to card"},
10152 {"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"},
10153 {"gsetblk", CmdHF14AGen4SetBlk, IfPm3Iso14443a, "Write block to card"},
10154 {"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"},
10155 {"gchpwd", CmdHF14AGen4ChangePwd, IfPm3Iso14443a, "Change card access password. Warning!"},
10156 {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GDM") " --------------------------"},
10157 {"gdmcfg", CmdHF14AGen4_GDM_Cfg, IfPm3Iso14443a, "Read config block from card"},
10158 {"gdmsetcfg", CmdHF14AGen4_GDM_SetCfg, IfPm3Iso14443a, "Write config block to card"},
10159 {"gdmparsecfg", CmdHF14AGen4_GDM_ParseCfg, AlwaysAvailable, "Parse config block to card"},
10160 {"gdmsetblk", CmdHF14AGen4_GDM_SetBlk, IfPm3Iso14443a, "Write block to card"},
10161 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"},
10162 // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
10163 {"ndefformat", CmdHFMFNDEFFormat, IfPm3Iso14443a, "Format MIFARE Classic Tag as NFC Tag"},
10164 {"ndefread", CmdHFMFNDEFRead, IfPm3Iso14443a, "Read and print NDEF records from card"},
10165 {"ndefwrite", CmdHFMFNDEFWrite, IfPm3Iso14443a, "Write NDEF records to card"},
10166 {"encodehid", CmdHFMFHidEncode, IfPm3Iso14443a, "Encode a HID Credential / NDEF record to card"},
10167 {NULL, NULL, NULL, NULL}
10171 static int CmdHelp(const char *Cmd) {
10172 (void)Cmd; // Cmd is not used so far
10173 CmdsHelp(CommandTable);
10174 return PM3_SUCCESS;
10177 int CmdHFMF(const char *Cmd) {
10178 clearCommandBuffer();
10179 return CmdsParse(CommandTable, Cmd);