hf mf sim: add nested reader attack (needs data & rf08s nonces)
[RRG-proxmark3.git] / client / src / cmdhfmf.c
blob8b7e218b06597fde5730f2bbae97eaeecff6e7c9
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"
49 static int CmdHelp(const char *Cmd);
52 static int usage_hf14_keybrute(void) {
53 PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery");
54 PrintAndLogEx(NORMAL, "You have a known 4 last bytes of a key recovered with mf_nonce_brute tool.");
55 PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced");
56 PrintAndLogEx(NORMAL, "");
57 PrintAndLogEx(NORMAL, " ---[ This attack is obsolete, try hardnested instead ]---");
58 PrintAndLogEx(NORMAL, "Options:");
59 PrintAndLogEx(NORMAL, " h this help");
60 PrintAndLogEx(NORMAL, " <block number> target block number");
61 PrintAndLogEx(NORMAL, " <A|B> target key type");
62 PrintAndLogEx(NORMAL, " <key> candidate key from mf_nonce_brute tool");
63 PrintAndLogEx(NORMAL, "Examples:");
64 PrintAndLogEx(NORMAL, _YELLOW_(" hf mf keybrute --blk 1 -k 000011223344"));
65 return 0;
69 int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
71 // ref: MIFARE Classic EV1 Originality Signature Validation
72 #define PUBLIC_MFCEV1_ECDA_KEYLEN 33
73 const ecdsa_publickey_t nxp_mfc_public_keys[] = {
74 {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
75 {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
76 {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
77 {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
78 {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
79 {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
80 {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
81 {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
82 {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
83 {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
86 uint8_t i;
87 bool is_valid = false;
89 for (i = 0; i < ARRAYLEN(nxp_mfc_public_keys); i++) {
91 int dl = 0;
92 uint8_t key[PUBLIC_MFCEV1_ECDA_KEYLEN];
93 param_gethex_to_eol(nxp_mfc_public_keys[i].value, 0, key, PUBLIC_MFCEV1_ECDA_KEYLEN, &dl);
95 int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, uidlen, signature, signature_len, false);
96 is_valid = (res == 0);
97 if (is_valid)
98 break;
101 PrintAndLogEx(INFO, "");
102 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
103 if (is_valid == false || i == ARRAYLEN(nxp_mfc_public_keys)) {
104 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
105 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
106 PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
107 return PM3_ESOFT;
110 PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfc_public_keys[i].desc);
111 PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfc_public_keys[i].value);
112 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
113 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
114 PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
115 return PM3_SUCCESS;
118 static int mf_read_uid(uint8_t *uid, int *uidlen, int *nxptype) {
119 clearCommandBuffer();
120 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
121 PacketResponseNG resp;
122 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
123 PrintAndLogEx(DEBUG, "iso14443a card select failed");
124 DropField();
125 return PM3_ERFTRANS;
128 iso14a_card_select_t card;
129 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
131 if (nxptype) {
132 uint64_t select_status = resp.oldarg[0];
133 *nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
136 memcpy(uid, card.uid, card.uidlen * sizeof(uint8_t));
137 *uidlen = card.uidlen;
138 return PM3_SUCCESS;
141 static char *GenerateFilename(const char *prefix, const char *suffix) {
142 if (! IfPm3Iso14443a()) {
143 return NULL;
145 uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
146 int uidlen = 0;
147 char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid) * 2 + 1, sizeof(uint8_t));
149 int res = mf_read_uid(uid, &uidlen, NULL);
150 if (res != PM3_SUCCESS || !uidlen) {
151 PrintAndLogEx(WARNING, "No tag found.");
152 free(fptr);
153 return NULL;
156 strcpy(fptr, prefix);
157 FillFileNameByUID(fptr, uid, suffix, uidlen);
158 return fptr;
161 static int initSectorTable(sector_t **src, size_t items) {
163 (*src) = calloc(items, sizeof(sector_t));
164 if (*src == NULL)
165 return PM3_EMALLOC;
167 // empty e_sector
168 for (size_t i = 0; i < items; i++) {
169 for (uint8_t j = 0; j < 2; j++) {
170 (*src)[i].Key[j] = 0xffffffffffff;
171 (*src)[i].foundKey[j] = 0;
174 return PM3_SUCCESS;
177 static void decode_print_st(uint16_t blockno, uint8_t *data) {
178 if (mfIsSectorTrailer(blockno)) {
179 PrintAndLogEx(NORMAL, "");
180 PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Sector trailer decoder") " --------------------------");
181 PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6));
182 PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3));
183 PrintAndLogEx(INFO, "user / gpb... " _GREEN_("%02x"), data[9]);
184 PrintAndLogEx(INFO, "key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6));
185 PrintAndLogEx(INFO, "");
186 PrintAndLogEx(INFO, " # | access rights");
187 PrintAndLogEx(INFO, "----+-----------------------------------------------------------------------");
189 if (mfValidateAccessConditions(&data[6]) == false) {
190 PrintAndLogEx(WARNING, _RED_("Invalid Access Conditions"));
194 int bln = mfFirstBlockOfSector(mfSectorNum(blockno));
195 int blinc = (mfNumBlocksPerSector(mfSectorNum(blockno)) > 4) ? 5 : 1;
196 for (int i = 0; i < 4; i++) {
197 PrintAndLogEx(INFO, "%3d%c| " _YELLOW_("%s"), bln, ((blinc > 1) && (i < 3) ? '+' : ' '), mfGetAccessConditionsDesc(i, &data[6]));
198 bln += blinc;
200 if (i == 3) {
201 uint8_t cond = mf_get_accesscondition(i, &data[6]);
202 if (cond == 0 || cond == 1 || cond == 2) {
203 PrintAndLogEx(INFO, "");
204 PrintAndLogEx(INFO, "OBS! Key B is readable, it SHALL NOT be able to authenticate on original MFC");
210 PrintAndLogEx(INFO, "----------------------------------------------------------------------------");
211 PrintAndLogEx(NORMAL, "");
215 static uint8_t NumOfSectors(char card) {
216 switch (card) {
217 case '0' :
218 return MIFARE_MINI_MAXSECTOR;
219 case '1' :
220 return MIFARE_1K_MAXSECTOR;
221 case '2' :
222 return MIFARE_2K_MAXSECTOR;
223 case '4' :
224 return MIFARE_4K_MAXSECTOR;
225 default :
226 return 0;
230 static char GetFormatFromSector(uint8_t sectors) {
231 switch (sectors) {
232 case MIFARE_MINI_MAXSECTOR:
233 return '0';
234 case MIFARE_1K_MAXSECTOR:
235 return '1';
236 case MIFARE_2K_MAXSECTOR:
237 return '2';
238 case MIFARE_4K_MAXSECTOR:
239 return '4';
240 default :
241 return ' ';
245 bool mfc_value(const uint8_t *d, int32_t *val) {
246 // values
247 int32_t a = (int32_t)MemLeToUint4byte(d);
248 uint32_t a_inv = MemLeToUint4byte(d + 4);
249 uint32_t b = MemLeToUint4byte(d + 8);
251 int val_checks = (
252 (a == b) && (a == ~a_inv) &&
253 (d[12] == (~d[13] & 0xFF)) &&
254 (d[14] == (~d[15] & 0xFF))
257 if (val) {
258 *val = a;
260 return val_checks;
263 void mf_print_block_one(uint8_t blockno, uint8_t *d, bool verbose) {
265 if (blockno == 0) {
266 char ascii[24] = {0};
267 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
268 PrintAndLogEx(INFO, "%3d | " _RED_("%s") "| " _RED_("%s"),
269 blockno,
270 sprint_hex(d, MFBLOCK_SIZE),
271 ascii
273 } else if (mfIsSectorTrailer(blockno)) {
275 char keya[26] = {0};
276 hex_to_buffer((uint8_t *)keya, d, MIFARE_KEY_SIZE, sizeof(keya) - 1, 0, 1, true);
278 char acl[20] = {0};
279 hex_to_buffer((uint8_t *)acl, d + MIFARE_KEY_SIZE, 3, sizeof(acl) - 1, 0, 1, true);
281 char keyb[26] = {0};
282 hex_to_buffer((uint8_t *)keyb, d + 10, MIFARE_KEY_SIZE, sizeof(keyb) - 1, 0, 1, true);
284 char ascii[24] = {0};
285 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
287 PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
288 blockno,
289 keya,
290 acl,
291 d[9],
292 keyb,
293 ascii
296 } else {
297 int32_t value = 0;
298 if (verbose && mfc_value(d, &value)) {
299 PrintAndLogEx(INFO, "%3d | " _CYAN_("%s") " %"PRIi32, blockno, sprint_hex_ascii(d, MFBLOCK_SIZE), value);
300 } else {
301 PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
306 static void mf_print_block(uint8_t blockno, uint8_t *d, bool verbose) {
307 uint8_t sectorno = mfSectorNum(blockno);
309 char secstr[6] = " ";
310 if (mfFirstBlockOfSector(sectorno) == blockno) {
311 sprintf(secstr, " %3d ", sectorno);
314 if (blockno == 0) {
315 char ascii[24] = {0};
316 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
317 PrintAndLogEx(INFO, "%s| %3d | " _RED_("%s") "| " _RED_("%s"),
318 secstr,
319 blockno,
320 sprint_hex(d, MFBLOCK_SIZE),
321 ascii
324 } else if (mfIsSectorTrailer(blockno)) {
326 char keya[26] = {0};
327 hex_to_buffer((uint8_t *)keya, d, MIFARE_KEY_SIZE, sizeof(keya) - 1, 0, 1, true);
329 char acl[20] = {0};
330 hex_to_buffer((uint8_t *)acl, d + MIFARE_KEY_SIZE, 3, sizeof(acl) - 1, 0, 1, true);
332 char keyb[26] = {0};
333 hex_to_buffer((uint8_t *)keyb, d + 10, MIFARE_KEY_SIZE, sizeof(keyb) - 1, 0, 1, true);
335 char ascii[24] = {0};
336 ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
338 PrintAndLogEx(INFO, "%s| %3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
339 secstr,
340 blockno,
341 keya,
342 acl,
343 d[9],
344 keyb,
345 ascii
347 } else {
348 int32_t value = 0;
349 if (verbose && mfc_value(d, &value)) {
350 PrintAndLogEx(INFO, "%s| %3d | " _CYAN_("%s") " %"PRIi32, secstr, blockno, sprint_hex_ascii(d, MFBLOCK_SIZE), value);
351 } else {
352 PrintAndLogEx(INFO, "%s| %3d | %s ", secstr, blockno, sprint_hex_ascii(d, MFBLOCK_SIZE));
357 static void mf_print_blocks(uint16_t n, uint8_t *d, bool verbose) {
358 PrintAndLogEx(NORMAL, "");
359 PrintAndLogEx(INFO, "-----+-----+-------------------------------------------------+-----------------");
360 PrintAndLogEx(INFO, " sec | blk | data | ascii");
361 PrintAndLogEx(INFO, "-----+-----+-------------------------------------------------+-----------------");
362 for (uint16_t i = 0; i < n; i++) {
363 mf_print_block(i, d + (i * MFBLOCK_SIZE), verbose);
365 PrintAndLogEx(INFO, "-----+-----+-------------------------------------------------+-----------------");
366 if (verbose) {
367 PrintAndLogEx(HINT, _CYAN_("cyan") " = value block with decoded value");
370 // MAD detection
371 if (HasMADKey(d)) {
372 PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
374 PrintAndLogEx(NORMAL, "");
377 // assumes n is in number of blocks 0..255
378 static int mf_print_keys(uint16_t n, uint8_t *d) {
379 uint8_t sectors = 0;
380 switch (n) {
381 case MIFARE_MINI_MAXBLOCK:
382 sectors = MIFARE_MINI_MAXSECTOR;
383 break;
384 case MIFARE_2K_MAXBLOCK:
385 sectors = MIFARE_2K_MAXSECTOR;
386 break;
387 case MIFARE_4K_MAXBLOCK:
388 sectors = MIFARE_4K_MAXSECTOR;
389 break;
390 case MIFARE_1K_MAXBLOCK:
391 sectors = MIFARE_1K_MAXSECTOR;
392 break;
393 default:
394 sectors = MIFARE_1K_MAXSECTOR;
395 n = MIFARE_1K_MAXBLOCK;
396 break;
399 sector_t *e_sector = calloc(sectors, sizeof(sector_t));
400 if (e_sector == NULL) {
401 return PM3_EMALLOC;
404 for (uint16_t i = 0; i < n; i++) {
405 if (mfIsSectorTrailer(i) == false) {
406 continue;
408 // zero based index...
409 uint8_t lookup = mfSectorNum(i);
410 uint8_t sec = MIN(sectors - 1, lookup);
411 e_sector[sec].foundKey[0] = 1;
412 e_sector[sec].Key[0] = bytes_to_num(d + (i * MFBLOCK_SIZE), MIFARE_KEY_SIZE);
413 e_sector[sec].foundKey[1] = 1;
414 e_sector[sec].Key[1] = bytes_to_num(d + (i * MFBLOCK_SIZE) + 10, MIFARE_KEY_SIZE);
416 printKeyTable(sectors, e_sector);
417 free(e_sector);
418 return PM3_SUCCESS;
421 // MFC dump , extract and save the keys to key file
422 // assumes n is in number of blocks 0..255
423 static int mf_save_keys_from_arr(uint16_t n, uint8_t *d) {
424 uint8_t sectors = 0;
425 switch (n) {
426 case MIFARE_MINI_MAXBLOCK:
427 sectors = MIFARE_MINI_MAXSECTOR;
428 break;
429 case MIFARE_2K_MAXBLOCK:
430 sectors = MIFARE_2K_MAXSECTOR;
431 break;
432 case MIFARE_4K_MAXBLOCK:
433 sectors = MIFARE_4K_MAXSECTOR;
434 break;
435 case MIFARE_1K_MAXBLOCK:
436 default:
437 sectors = MIFARE_1K_MAXSECTOR;
438 break;
441 uint16_t keysize = 2 * MIFARE_KEY_SIZE * sectors;
443 uint8_t *keys = calloc(keysize, sizeof(uint8_t));
444 if (keys == NULL) {
445 return PM3_EMALLOC;
448 uint8_t sector = 0;
449 for (uint16_t i = 0; i < n; i++) {
450 if (mfIsSectorTrailer(i)) {
451 // key A offset in ST block
452 memcpy(keys + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE), MIFARE_KEY_SIZE);
454 // key B offset in ST block
455 memcpy(keys + (MIFARE_KEY_SIZE * sectors) + (MIFARE_KEY_SIZE * sector), d + (i * MFBLOCK_SIZE) + 10, MIFARE_KEY_SIZE);
457 sector++;
461 char fn[FILE_PATH_SIZE] = {0};
462 snprintf(fn, sizeof(fn), "hf-mf-%s-key", sprint_hex_inrow(d, 4));
463 saveFileEx(fn, ".bin", keys, keysize, spDump);
464 free(keys);
465 return PM3_SUCCESS;
469 static void mf_print_values(uint16_t n, uint8_t *d) {
471 PrintAndLogEx(NORMAL, "");
472 PrintAndLogEx(INFO, "Looking for value blocks...");
473 PrintAndLogEx(NORMAL, "");
474 uint8_t cnt = 0;
475 int32_t value = 0;
476 for (uint16_t i = 0; i < n; i++) {
478 if (mfc_value(d + (i * MFBLOCK_SIZE), &value)) {
479 PrintAndLogEx(INFO, "%03d | " _YELLOW_("%" PRIi32) " " _YELLOW_("0x%" PRIX32), i, value, value);
480 ++cnt;
484 if (cnt) {
485 PrintAndLogEx(INFO, "Found %u value blocks in file", cnt);
486 PrintAndLogEx(NORMAL, "");
491 void mf_print_sector_hdr(uint8_t sector) {
492 PrintAndLogEx(NORMAL, "");
493 PrintAndLogEx(INFO, " # | sector " _GREEN_("%02d") " / " _GREEN_("0x%02X") " | ascii", sector, sector);
494 PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------");
497 static bool mf_write_block(const uint8_t *key, uint8_t keytype, uint8_t blockno, uint8_t *block) {
499 uint8_t data[26];
500 memcpy(data, key, MIFARE_KEY_SIZE);
501 memcpy(data + 10, block, MFBLOCK_SIZE);
503 clearCommandBuffer();
504 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, keytype, 0, data, sizeof(data));
505 PacketResponseNG resp;
506 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
507 PrintAndLogEx(FAILED, "command execution time out");
508 return false;
511 return ((resp.oldarg[0] & 0xff) == 1);
514 // assumes n is in number of blocks 0..255
515 static void mf_analyse_acl(uint16_t n, uint8_t *d) {
517 for (uint16_t b = 3; b < n; b++) {
518 if (mfIsSectorTrailer(b) == false) {
519 continue;
522 uint8_t block[MFBLOCK_SIZE] = {0x00};
523 memcpy(block, d + (b * MFBLOCK_SIZE), MFBLOCK_SIZE);
525 // ensure access right isn't messed up.
526 if (mfValidateAccessConditions(&block[6]) == false) {
527 PrintAndLogEx(WARNING, "Invalid Access Conditions on sector " _YELLOW_("%u"), mfSectorNum(b));
530 // Warn if ACL is strict read-only
531 uint8_t bar = mfNumBlocksPerSector(mfSectorNum(b));
532 for (uint8_t foo = 0; foo < bar; foo++) {
533 if (mfReadOnlyAccessConditions(foo, &block[6])) {
534 PrintAndLogEx(WARNING, _YELLOW_("s%u / b%u") " - Strict ReadOnly Access Conditions detected", mfSectorNum(b), b - bar + 1 + foo);
541 Sector trailer sanity checks.
542 Warn if ACL is strict read-only, or invalid ACL.
544 static int mf_analyse_st_block(uint8_t blockno, uint8_t *block, bool force) {
546 if (mfIsSectorTrailer(blockno) == false) {
547 return PM3_SUCCESS;
550 PrintAndLogEx(INFO, "Sector trailer (ST) write detected");
552 // ensure access right isn't messed up.
553 if (mfValidateAccessConditions(&block[6]) == false) {
554 PrintAndLogEx(WARNING, "Invalid Access Conditions detected, replacing with default values");
555 memcpy(block + 6, "\xFF\x07\x80\x69", 4);
558 bool ro_detected = false;
559 uint8_t bar = mfNumBlocksPerSector(mfSectorNum(blockno));
560 for (uint8_t foo = 0; foo < bar; foo++) {
561 if (mfReadOnlyAccessConditions(foo, &block[6])) {
562 PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", blockno - bar + 1 + foo);
563 ro_detected = true;
566 if (ro_detected) {
567 if (force) {
568 PrintAndLogEx(WARNING, " --force override, continuing...");
569 } else {
570 PrintAndLogEx(INFO, "Exiting, please run `" _YELLOW_("hf mf acl -d %s") "` to understand", sprint_hex_inrow(&block[6], 3));
571 PrintAndLogEx(INFO, "Use `" _YELLOW_("--force") "` to override and write this data");
572 return PM3_EINVARG;
574 } else {
575 PrintAndLogEx(SUCCESS, "ST checks ( " _GREEN_("ok") " )");
578 return PM3_SUCCESS;
581 /* Reads data from tag
582 * @param card: (output) card info
583 * @param carddata: (output) card data
584 * @param numSectors: size of the card
585 * @param keyFileName: filename containing keys or NULL.
587 static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t numSectors, char *keyfn) {
589 // Select card to get UID/UIDLEN/ATQA/SAK information
590 clearCommandBuffer();
591 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
592 PacketResponseNG resp;
593 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
594 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
595 return PM3_ETIMEOUT;
598 uint64_t select_status = resp.oldarg[0];
599 if (select_status == 0) {
600 PrintAndLogEx(DEBUG, "iso14443a card select failed");
601 return PM3_ESOFT;
604 // store card info
605 memcpy(card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
607 char *fptr = NULL;
608 if (keyfn == NULL || keyfn[0] == '\0') {
609 fptr = GenerateFilename("hf-mf-", "-key.bin");
610 if (fptr == NULL)
611 return PM3_ESOFT;
613 keyfn = fptr ;
616 PrintAndLogEx(INFO, "Using... %s", keyfn);
618 size_t alen = 0, blen = 0;
619 uint8_t *keyA, *keyB;
620 if (loadFileBinaryKey(keyfn, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) {
621 free(fptr);
622 return PM3_ESOFT;
625 PrintAndLogEx(INFO, "Reading sector access bits...");
626 PrintAndLogEx(INFO, "." NOLF);
628 uint8_t rights[40][4] = {0};
630 mf_readblock_t payload;
631 uint8_t current_key;
632 for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) {
633 current_key = MF_KEY_A;
634 for (uint8_t tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
635 PrintAndLogEx(NORMAL, "." NOLF);
636 fflush(stdout);
638 if (kbd_enter_pressed()) {
639 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
640 free(fptr);
641 free(keyA);
642 free(keyB);
643 return PM3_EOPABORTED;
646 payload.blockno = mfFirstBlockOfSector(sectorNo) + mfNumBlocksPerSector(sectorNo) - 1;
647 payload.keytype = current_key;
649 memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
651 clearCommandBuffer();
652 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
654 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) {
656 uint8_t *data = resp.data.asBytes;
657 if (resp.status == PM3_SUCCESS) {
658 rights[sectorNo][0] = ((data[7] & 0x10) >> 2) | ((data[8] & 0x1) << 1) | ((data[8] & 0x10) >> 4); // C1C2C3 for data area 0
659 rights[sectorNo][1] = ((data[7] & 0x20) >> 3) | ((data[8] & 0x2) << 0) | ((data[8] & 0x20) >> 5); // C1C2C3 for data area 1
660 rights[sectorNo][2] = ((data[7] & 0x40) >> 4) | ((data[8] & 0x4) >> 1) | ((data[8] & 0x40) >> 6); // C1C2C3 for data area 2
661 rights[sectorNo][3] = ((data[7] & 0x80) >> 5) | ((data[8] & 0x8) >> 2) | ((data[8] & 0x80) >> 7); // C1C2C3 for sector trailer
662 break;
663 } else if (tries == (MIFARE_SECTOR_RETRY / 2)) { // after half unsuccessful tries, give key B a go
664 PrintAndLogEx(WARNING, "\nTrying with " _YELLOW_("key B") " instead...");
665 current_key = MF_KEY_B;
666 PrintAndLogEx(INFO, "." NOLF);
667 } else if (tries == (MIFARE_SECTOR_RETRY - 1)) { // on last try set defaults
668 PrintAndLogEx(FAILED, "\nFailed to read access rights for sector %2d ( fallback to default )", sectorNo);
669 rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00;
670 rights[sectorNo][3] = 0x01;
672 } else {
673 PrintAndLogEx(FAILED, "\nTimeout reading access rights for sector... %2d ( fallback to default )", sectorNo);
674 rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00;
675 rights[sectorNo][3] = 0x01;
680 PrintAndLogEx(NORMAL, "");
681 PrintAndLogEx(SUCCESS, "Finished reading sector access bits");
682 PrintAndLogEx(INFO, "Dumping all blocks from card...");
684 for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) {
685 for (uint8_t blockNo = 0; blockNo < mfNumBlocksPerSector(sectorNo); blockNo++) {
686 bool received = false;
687 current_key = MF_KEY_A;
688 uint8_t data_area = (sectorNo < 32) ? blockNo : blockNo / 5;
689 if (rights[sectorNo][data_area] == 0x07) { // no key would work
690 PrintAndLogEx(WARNING, "Access rights prevent reading sector... " _YELLOW_("%2d") " block... " _YELLOW_("%3d") " ( skip )", sectorNo, blockNo);
691 continue;
694 for (uint8_t tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) {
696 if (mfIsSectorTrailerBasedOnBlocks(sectorNo, blockNo)) {
698 // sector trailer. At least the Access Conditions can always be read with key A.
699 payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
700 payload.keytype = current_key;
701 memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
703 clearCommandBuffer();
704 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
705 received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
706 } else {
707 // data block. Check if it can be read with key A or key B
708 if ((rights[sectorNo][data_area] == 0x03) || (rights[sectorNo][data_area] == 0x05)) {
709 // only key B would work
710 payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
711 payload.keytype = MF_KEY_B;
712 memcpy(payload.key, keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
714 clearCommandBuffer();
715 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
716 received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
717 } else {
718 // key A would work
719 payload.blockno = mfFirstBlockOfSector(sectorNo) + blockNo;
720 payload.keytype = current_key;
721 memcpy(payload.key, (current_key == MF_KEY_A) ? keyA + (sectorNo * MIFARE_KEY_SIZE) : keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
723 clearCommandBuffer();
724 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
725 received = WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500);
729 if (received) {
730 if (resp.status == PM3_SUCCESS) {
731 // break the re-try loop
732 break;
734 if ((current_key == MF_KEY_A) && (tries == (MIFARE_SECTOR_RETRY / 2))) {
735 // Half the tries failed with key A. Swap for key B
736 current_key = MF_KEY_B;
738 // clear out keyA since it failed.
739 memset(keyA + (sectorNo * MIFARE_KEY_SIZE), 0x00, MIFARE_KEY_SIZE);
744 if (received) {
746 if (resp.status == PM3_SUCCESS) {
748 uint8_t *data = resp.data.asBytes;
750 if (mfIsSectorTrailerBasedOnBlocks(sectorNo, blockNo)) {
751 // sector trailer. Fill in the keys.
752 memcpy(data, keyA + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
753 memcpy(data + 10, keyB + (sectorNo * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
756 memcpy(carddata + (MFBLOCK_SIZE * (mfFirstBlockOfSector(sectorNo) + blockNo)), data, MFBLOCK_SIZE);
757 PrintAndLogEx(INPLACE, "Sector... " _YELLOW_("%2d") " block..." _YELLOW_("%2d") " ( " _GREEN_("ok") " )", sectorNo, blockNo);
758 } else {
759 PrintAndLogEx(FAILED, "\nSector... %2d Block... %2d ( " _RED_("fail") " )", sectorNo, blockNo);
761 } else {
762 PrintAndLogEx(WARNING, "Timeout reading sector... %2d block... %2d", sectorNo, blockNo);
767 free(fptr);
768 free(keyA);
769 free(keyB);
770 PrintAndLogEx(SUCCESS, "\nSucceeded in dumping all blocks");
771 return PM3_SUCCESS ;
774 static int mf_load_keys(uint8_t **pkeyBlock, uint32_t *pkeycnt, uint8_t *userkey, int userkeylen, const char *filename, int fnlen, bool load_default) {
775 // Handle Keys
776 *pkeycnt = 0;
777 *pkeyBlock = NULL;
778 uint8_t *p;
779 // Handle user supplied key
780 // (it considers *pkeycnt and *pkeyBlock as possibly non-null so logic can be easily reordered)
781 if (userkeylen >= MIFARE_KEY_SIZE) {
782 int numKeys = userkeylen / MIFARE_KEY_SIZE;
783 p = realloc(*pkeyBlock, numKeys * MIFARE_KEY_SIZE);
784 if (!p) {
785 PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
786 free(*pkeyBlock);
787 return PM3_EMALLOC;
789 *pkeyBlock = p;
791 memcpy(*pkeyBlock, userkey, numKeys * MIFARE_KEY_SIZE);
793 for (int i = 0; i < numKeys; i++) {
794 PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", i, sprint_hex(*pkeyBlock + i * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE));
796 *pkeycnt += numKeys;
797 PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " user keys", numKeys);
800 if (load_default) {
801 // Handle default keys
802 p = realloc(*pkeyBlock, (*pkeycnt + ARRAYLEN(g_mifare_default_keys)) * MIFARE_KEY_SIZE);
803 if (!p) {
804 PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
805 free(*pkeyBlock);
806 return PM3_EMALLOC;
808 *pkeyBlock = p;
809 // Copy default keys to list
810 for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) {
811 num_to_bytes(g_mifare_default_keys[i], MIFARE_KEY_SIZE, (uint8_t *)(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE));
812 PrintAndLogEx(DEBUG, _YELLOW_("%2d") " - %s", *pkeycnt + i, sprint_hex(*pkeyBlock + (*pkeycnt + i) * MIFARE_KEY_SIZE, MIFARE_KEY_SIZE));
814 *pkeycnt += ARRAYLEN(g_mifare_default_keys);
815 PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%zu") " keys from hardcoded default array", ARRAYLEN(g_mifare_default_keys));
818 // Handle user supplied dictionary file
819 if (fnlen > 0) {
820 uint32_t loaded_numKeys = 0;
821 uint8_t *keyBlock_tmp = NULL;
822 int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock_tmp, MIFARE_KEY_SIZE, &loaded_numKeys);
823 if (res != PM3_SUCCESS || loaded_numKeys == 0 || keyBlock_tmp == NULL) {
824 PrintAndLogEx(FAILED, "An error occurred while loading the dictionary!");
825 free(keyBlock_tmp);
826 free(*pkeyBlock);
827 return PM3_EFILE;
828 } else {
829 p = realloc(*pkeyBlock, (*pkeycnt + loaded_numKeys) * MIFARE_KEY_SIZE);
830 if (!p) {
831 PrintAndLogEx(FAILED, "cannot allocate memory for Keys");
832 free(keyBlock_tmp);
833 free(*pkeyBlock);
834 return PM3_EMALLOC;
836 *pkeyBlock = p;
837 memcpy(*pkeyBlock + *pkeycnt * MIFARE_KEY_SIZE, keyBlock_tmp, loaded_numKeys * MIFARE_KEY_SIZE);
838 *pkeycnt += loaded_numKeys;
839 free(keyBlock_tmp);
842 return PM3_SUCCESS;
845 static int CmdHF14AMfAcl(const char *Cmd) {
846 CLIParserContext *ctx;
847 CLIParserInit(&ctx, "hf mf acl",
848 "Print decoded MIFARE access rights (ACL), \n"
849 " A = key A\n"
850 " B = key B\n"
851 " AB = both key A and B\n"
852 " ACCESS = access bytes inside sector trailer block\n"
853 " Increment, decrement, transfer, restore is for value blocks",
854 "hf mf acl\n"
855 "hf mf acl -d FF0780\n");
857 void *argtable[] = {
858 arg_param_begin,
859 arg_str1("d", "data", "<hex>", "ACL bytes specified as 3 hex bytes"),
860 arg_param_end
862 CLIExecWithReturn(ctx, Cmd, argtable, true);
864 int acllen = 0;
865 uint8_t acl[3] = {0};
866 CLIGetHexWithReturn(ctx, 1, acl, &acllen);
868 CLIParserFree(ctx);
870 PrintAndLogEx(NORMAL, "");
872 // look up common default ACL bytes and print a fingerprint line about it.
873 if (memcmp(acl, "\xFF\x07\x80", 3) == 0) {
874 PrintAndLogEx(INFO, "ACL... " _GREEN_("%s") " (transport configuration)", sprint_hex(acl, sizeof(acl)));
876 if (mfValidateAccessConditions(acl) == false) {
877 PrintAndLogEx(ERR, _RED_("Invalid Access Conditions, NEVER write these on a card!"));
879 PrintAndLogEx(NORMAL, "");
880 PrintAndLogEx(INFO, " # | Access rights");
881 PrintAndLogEx(INFO, "----+-----------------------------------------------------------------");
882 for (int i = 0; i < 4; i++) {
883 PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), i, mfGetAccessConditionsDesc(i, acl));
885 PrintAndLogEx(NORMAL, "");
886 return PM3_SUCCESS;
889 static int CmdHF14AMfDarkside(const char *Cmd) {
890 CLIParserContext *ctx;
891 CLIParserInit(&ctx, "hf mf darkside",
892 "Darkside attack",
893 "hf mf darkside\n"
894 "hf mf darkside --blk 16\n"
895 "hf mf darkside --blk 16 -b\n");
897 void *argtable[] = {
898 arg_param_begin,
899 arg_int0(NULL, "blk", "<dec> ", "Target block"),
900 arg_lit0("b", NULL, "Target key B instead of default key A"),
901 arg_int0("c", NULL, "<dec>", "Target Auth 6x"),
902 arg_param_end
904 CLIExecWithReturn(ctx, Cmd, argtable, true);
906 uint8_t blockno = arg_get_u32_def(ctx, 1, 0) & 0xFF;
907 uint8_t key_type = MIFARE_AUTH_KEYA;
909 if (arg_get_lit(ctx, 2)) {
910 PrintAndLogEx(INFO, "Targeting key B");
911 key_type = MIFARE_AUTH_KEYB;
914 uint8_t ctype = arg_get_u32_def(ctx, 3, 0) & 0xFF;
915 if ((ctype & 0x60) == 0x60) {
916 key_type = ctype;
919 CLIParserFree(ctx);
921 uint64_t key = 0;
922 uint64_t t1 = msclock();
923 int ret = mfDarkside(blockno, key_type, &key);
924 t1 = msclock() - t1;
926 if (ret != PM3_SUCCESS) return ret;
928 PrintAndLogEx(SUCCESS, "found valid key: " _GREEN_("%012" PRIx64), key);
929 PrintAndLogEx(SUCCESS, "time in darkside " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
930 return PM3_SUCCESS;
933 static int CmdHF14AMfWrBl(const char *Cmd) {
935 CLIParserContext *ctx;
936 CLIParserInit(&ctx, "hf mf wrbl",
937 "Write MIFARE Classic block with 16 hex bytes of data\n"
938 " \n"
939 "Sector 0 / Block 0 - Manufacturer block\n"
940 "When writing to block 0 you must use a VALID block 0 data (UID, BCC, SAK, ATQA)\n"
941 "Writing an invalid block 0 means rendering your Magic GEN2 card undetectable. \n"
942 "Look in the magic_cards_notes.md file for help to resolve it.\n"
943 " \n"
944 "`--force` param is used to override warnings like bad ACL and BLOCK 0 writes.\n"
945 " if not specified, it will exit if detected",
946 "hf mf wrbl --blk 1 -d 000102030405060708090a0b0c0d0e0f\n"
947 "hf mf wrbl --blk 1 -k A0A1A2A3A4A5 -d 000102030405060708090a0b0c0d0e0f\n"
949 void *argtable[] = {
950 arg_param_begin,
951 arg_int1(NULL, "blk", "<dec>", "block number"),
952 arg_lit0("a", NULL, "input key type is key A (def)"),
953 arg_lit0("b", NULL, "input key type is key B"),
954 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
955 arg_lit0(NULL, "force", "override warnings"),
956 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
957 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
958 arg_param_end
960 CLIExecWithReturn(ctx, Cmd, argtable, false);
962 int b = arg_get_int_def(ctx, 1, 1);
964 uint8_t keytype = MF_KEY_A;
965 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
966 CLIParserFree(ctx);
967 PrintAndLogEx(WARNING, "Choose one single input key type");
968 return PM3_EINVARG;
969 } else if (arg_get_lit(ctx, 3)) {
970 keytype = MF_KEY_B;
972 uint8_t prev_keytype = keytype;
973 keytype = arg_get_int_def(ctx, 4, keytype);
974 if ((arg_get_lit(ctx, 2) || arg_get_lit(ctx, 3)) && (keytype != prev_keytype)) {
975 CLIParserFree(ctx);
976 PrintAndLogEx(WARNING, "Choose one single input key type");
977 return PM3_EINVARG;
979 bool force = arg_get_lit(ctx, 5);
981 int keylen = 0;
982 uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
983 CLIGetHexWithReturn(ctx, 6, key, &keylen);
985 uint8_t block[MFBLOCK_SIZE] = {0x00};
986 int blen = 0;
987 CLIGetHexWithReturn(ctx, 7, block, &blen);
988 CLIParserFree(ctx);
990 if (keylen && keylen != 6) {
991 PrintAndLogEx(WARNING, "Key must be 12 hex digits. Got %d", keylen);
992 return PM3_EINVARG;
995 if (blen != MFBLOCK_SIZE) {
996 PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", blen);
997 return PM3_EINVARG;
1000 if (b > 255) {
1001 return PM3_EINVARG;
1004 // BLOCK 0 detection
1005 if (b == 0 && force == false) {
1006 PrintAndLogEx(NORMAL, "");
1007 PrintAndLogEx(INFO, "Targeting Sector 0 / Block 0 - Manufacturer block");
1008 PrintAndLogEx(INFO, "Read the helptext for details before writing to this block");
1009 PrintAndLogEx(INFO, "You must use param `" _YELLOW_("--force") "` to write to this block");
1010 PrintAndLogEx(NORMAL, "");
1011 return PM3_EINVARG;
1014 uint8_t blockno = (uint8_t)b;
1016 if (mf_analyse_st_block(blockno, block, force) != PM3_SUCCESS) {
1017 return PM3_EINVARG;
1020 PrintAndLogEx(INFO, "Writing block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
1021 PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block)));
1023 uint8_t data[26];
1024 memcpy(data, key, sizeof(key));
1025 memcpy(data + 10, block, sizeof(block));
1026 clearCommandBuffer();
1027 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, keytype, 0, data, sizeof(data));
1029 PacketResponseNG resp;
1030 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1031 PrintAndLogEx(FAILED, "command execution time out");
1032 return PM3_ETIMEOUT;
1035 int status = resp.oldarg[0];
1036 if (status > 0) {
1037 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
1038 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf rdbl") "` to verify");
1039 } else if (status == PM3_ETEAROFF) {
1040 return status;
1041 } else {
1042 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
1043 // suggest the opposite keytype than what was used.
1044 PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype `" _YELLOW_("hf mf wrbl -%c ...") "` instead", (keytype == MF_KEY_A) ? 'b' : 'a');
1046 return PM3_SUCCESS;
1049 static int CmdHF14AMfRdBl(const char *Cmd) {
1050 CLIParserContext *ctx;
1051 CLIParserInit(&ctx, "hf mf rdbl",
1052 "Read MIFARE Classic block",
1053 "hf mf rdbl --blk 0\n"
1054 "hf mf rdbl --blk 0 -k A0A1A2A3A4A5\n"
1055 "hf mf rdbl --blk 3 -v -> get block 3, decode sector trailer\n"
1057 void *argtable[] = {
1058 arg_param_begin,
1059 arg_int1(NULL, "blk", "<dec>", "block number"),
1060 arg_lit0("a", NULL, "input key type is key A (def)"),
1061 arg_lit0("b", NULL, "input key type is key B"),
1062 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
1063 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
1064 arg_lit0("v", "verbose", "verbose output"),
1065 arg_param_end
1067 CLIExecWithReturn(ctx, Cmd, argtable, false);
1068 int b = arg_get_int_def(ctx, 1, 0);
1070 uint8_t keytype = MF_KEY_A;
1071 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
1072 CLIParserFree(ctx);
1073 PrintAndLogEx(WARNING, "Choose one single input key type");
1074 return PM3_EINVARG;
1075 } else if (arg_get_lit(ctx, 3)) {
1076 keytype = MF_KEY_B;
1078 keytype = arg_get_int_def(ctx, 4, keytype);
1079 uint8_t prev_keytype = keytype;
1080 keytype = arg_get_int_def(ctx, 4, keytype);
1081 if ((arg_get_lit(ctx, 2) || arg_get_lit(ctx, 3)) && (keytype != prev_keytype)) {
1082 CLIParserFree(ctx);
1083 PrintAndLogEx(WARNING, "Choose one single input key type");
1084 return PM3_EINVARG;
1087 int keylen = 0;
1088 uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1089 CLIGetHexWithReturn(ctx, 5, key, &keylen);
1090 bool verbose = arg_get_lit(ctx, 6);
1091 CLIParserFree(ctx);
1093 if (keylen && keylen != 6) {
1094 PrintAndLogEx(WARNING, "Key must be 12 hex digits. Got %d", keylen);
1095 return PM3_EINVARG;
1098 if (b > 255) {
1099 return PM3_EINVARG;
1101 uint8_t blockno = (uint8_t)b;
1103 uint8_t data[16] = {0};
1104 int res = mfReadBlock(blockno, keytype, key, data);
1105 if (res == PM3_SUCCESS) {
1107 uint8_t sector = mfSectorNum(blockno);
1108 mf_print_sector_hdr(sector);
1109 mf_print_block_one(blockno, data, verbose);
1110 if (verbose) {
1111 decode_print_st(blockno, data);
1114 PrintAndLogEx(NORMAL, "");
1115 return res;
1118 static int CmdHF14AMfRdSc(const char *Cmd) {
1120 CLIParserContext *ctx;
1121 CLIParserInit(&ctx, "hf mf rdsc",
1122 "Read MIFARE Classic sector",
1123 "hf mf rdsc -s 0\n"
1124 "hf mf rdsc -s 0 -k A0A1A2A3A4A5\n"
1126 void *argtable[] = {
1127 arg_param_begin,
1128 arg_lit0("a", NULL, "input key specified is A key (def)"),
1129 arg_lit0("b", NULL, "input key specified is B key"),
1130 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
1131 arg_str0("k", "key", "<hex>", "key specified as 6 hex bytes"),
1132 arg_int1("s", "sec", "<dec>", "sector number"),
1133 arg_lit0("v", "verbose", "verbose output"),
1134 arg_param_end
1136 CLIExecWithReturn(ctx, Cmd, argtable, false);
1137 uint8_t keytype = MF_KEY_A;
1138 if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) {
1139 CLIParserFree(ctx);
1140 PrintAndLogEx(WARNING, "Choose one single input key type");
1141 return PM3_EINVARG;
1142 } else if (arg_get_lit(ctx, 2)) {
1143 keytype = MF_KEY_B;
1145 uint8_t prev_keytype = keytype;
1146 keytype = arg_get_int_def(ctx, 3, keytype);
1147 if ((arg_get_lit(ctx, 1) || arg_get_lit(ctx, 2)) && (keytype != prev_keytype)) {
1148 CLIParserFree(ctx);
1149 PrintAndLogEx(WARNING, "Choose one single input key type");
1150 return PM3_EINVARG;
1153 int keylen = 0;
1154 uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1155 CLIGetHexWithReturn(ctx, 4, key, &keylen);
1157 int s = arg_get_int_def(ctx, 5, 0);
1158 bool verbose = arg_get_lit(ctx, 6);
1159 CLIParserFree(ctx);
1161 if (keylen && keylen != 6) {
1162 PrintAndLogEx(WARNING, "Key must be 12 hex digits. Got %d", keylen);
1163 return PM3_EINVARG;
1166 if (s >= MIFARE_4K_MAXSECTOR) {
1167 PrintAndLogEx(WARNING, "Sector number must be less then 40");
1168 return PM3_EINVARG;
1171 uint8_t sector = (uint8_t)s;
1172 uint16_t sc_size = mfNumBlocksPerSector(sector) * MFBLOCK_SIZE;
1174 uint8_t *data = calloc(sc_size, sizeof(uint8_t));
1175 if (data == NULL) {
1176 PrintAndLogEx(ERR, "failed to allocate memory");
1177 return PM3_EMALLOC;
1180 int res = mfReadSector(sector, keytype, key, data);
1181 if (res == PM3_SUCCESS) {
1183 uint8_t blocks = mfNumBlocksPerSector(sector);
1184 uint8_t start = mfFirstBlockOfSector(sector);
1186 mf_print_sector_hdr(sector);
1187 for (int i = 0; i < blocks; i++) {
1188 mf_print_block_one(start + i, data + (i * MFBLOCK_SIZE), verbose);
1191 if (verbose) {
1192 decode_print_st(start + blocks - 1, data + ((blocks - 1) * MFBLOCK_SIZE));
1195 free(data);
1196 PrintAndLogEx(NORMAL, "");
1197 return PM3_SUCCESS;
1200 static int FastDumpWithEcFill(uint8_t numsectors) {
1202 uint8_t dbg_curr = DBG_NONE;
1203 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
1204 return PM3_EFAILED;
1208 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
1209 return PM3_EFAILED;
1213 mfc_eload_t payload;
1214 payload.sectorcnt = numsectors;
1215 payload.keytype = MF_KEY_A;
1217 // ecfill key A
1218 clearCommandBuffer();
1219 SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
1221 PacketResponseNG resp;
1222 bool res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2500);
1223 if (res == false) {
1224 PrintAndLogEx(WARNING, "command execution time out");
1225 return PM3_ETIMEOUT;
1228 if (resp.status != PM3_SUCCESS) {
1229 PrintAndLogEx(FAILED, "fast dump reported back failure w KEY A, swapping to KEY B");
1231 // ecfill key B
1232 payload.keytype = MF_KEY_B;
1234 clearCommandBuffer();
1235 SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
1236 res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2500);
1237 if (res == false) {
1238 PrintAndLogEx(WARNING, "command execution time out");
1239 setDeviceDebugLevel(dbg_curr, false);
1240 return PM3_ETIMEOUT;
1243 if (resp.status != PM3_SUCCESS) {
1244 PrintAndLogEx(FAILED, "fast dump reported back failure w KEY B");
1245 PrintAndLogEx(FAILED, "Dump file is " _RED_("PARTIAL") " complete");
1249 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
1250 return PM3_EFAILED;
1253 return PM3_SUCCESS;
1256 static int CmdHF14AMfDump(const char *Cmd) {
1257 CLIParserContext *ctx;
1258 CLIParserInit(&ctx, "hf mf dump",
1259 "Dump MIFARE Classic tag to file (bin/json)\n"
1260 "If no <name> given, UID will be used as filename",
1261 "hf mf dump --mini --> MIFARE Mini\n"
1262 "hf mf dump --1k --> MIFARE Classic 1k\n"
1263 "hf mf dump --2k --> MIFARE 2k\n"
1264 "hf mf dump --4k --> MIFARE 4k\n"
1265 "hf mf dump --keys hf-mf-066C8B78-key.bin --> MIFARE 1k with keys from specified file\n");
1267 void *argtable[] = {
1268 arg_param_begin,
1269 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
1270 arg_str0("k", "keys", "<fn>", "filename of keys"),
1271 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
1272 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
1273 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
1274 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
1275 arg_lit0(NULL, "ns", "no save to file"),
1276 arg_lit0("v", "verbose", "verbose output"),
1277 arg_param_end
1279 CLIExecWithReturn(ctx, Cmd, argtable, true);
1281 int datafnlen = 0;
1282 char dataFilename[FILE_PATH_SIZE] = {0};
1283 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)dataFilename, FILE_PATH_SIZE, &datafnlen);
1285 int keyfnlen = 0;
1286 char keyFilename[FILE_PATH_SIZE] = {0};
1287 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
1289 bool m0 = arg_get_lit(ctx, 3);
1290 bool m1 = arg_get_lit(ctx, 4);
1291 bool m2 = arg_get_lit(ctx, 5);
1292 bool m4 = arg_get_lit(ctx, 6);
1293 bool nosave = arg_get_lit(ctx, 7);
1294 bool verbose = arg_get_lit(ctx, 8);
1295 CLIParserFree(ctx);
1297 uint64_t t1 = msclock();
1299 // validations
1300 if ((m0 + m1 + m2 + m4) > 1) {
1301 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
1302 return PM3_EINVARG;
1303 } else if ((m0 + m1 + m2 + m4) == 0) {
1304 m1 = true;
1307 uint8_t numSectors = MIFARE_1K_MAXSECTOR;
1308 uint16_t bytes = MIFARE_1K_MAX_BYTES;
1309 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
1311 if (m0) {
1312 numSectors = MIFARE_MINI_MAXSECTOR;
1313 bytes = MIFARE_MINI_MAX_BYTES;
1314 block_cnt = MIFARE_MINI_MAXBLOCK;
1315 } else if (m1) {
1316 numSectors = MIFARE_1K_MAXSECTOR;
1317 bytes = MIFARE_1K_MAX_BYTES;
1318 block_cnt = MIFARE_1K_MAXBLOCK;
1319 } else if (m2) {
1320 numSectors = MIFARE_2K_MAXSECTOR;
1321 bytes = MIFARE_2K_MAX_BYTES;
1322 block_cnt = MIFARE_2K_MAXBLOCK;
1323 } else if (m4) {
1324 numSectors = MIFARE_4K_MAXSECTOR;
1325 bytes = MIFARE_4K_MAX_BYTES;
1326 block_cnt = MIFARE_4K_MAXBLOCK;
1327 } else {
1328 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
1329 return PM3_EINVARG;
1332 // read card
1333 iso14a_card_select_t card ;
1334 uint8_t *mem = calloc(MIFARE_4K_MAX_BYTES, sizeof(uint8_t));
1335 if (mem == NULL) {
1336 PrintAndLogEx(ERR, "failed to allocate memory");
1337 return PM3_EMALLOC;
1339 int res = mfc_read_tag(&card, mem, numSectors, keyFilename);
1340 if (res != PM3_SUCCESS) {
1341 free(mem);
1342 return res;
1345 PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock() - t1) / 1000);
1347 mf_print_blocks(block_cnt, mem, verbose);
1349 if (verbose) {
1350 mf_print_keys(block_cnt, mem);
1351 mf_analyse_acl(block_cnt, mem);
1354 // Skip saving card data to file
1355 if (nosave) {
1356 PrintAndLogEx(INFO, "Called with no save option");
1357 free(mem);
1358 return PM3_SUCCESS;
1361 // Save to file
1362 if (strlen(dataFilename) < 1) {
1363 char *fptr = GenerateFilename("hf-mf-", "-dump");
1364 if (fptr == NULL) {
1365 free(mem);
1366 return PM3_ESOFT;
1369 strcpy(dataFilename, fptr);
1370 free(fptr);
1373 pm3_save_mf_dump(dataFilename, mem, bytes, jsfCardMemory);
1374 free(mem);
1375 return PM3_SUCCESS;
1378 static int CmdHF14AMfRestore(const char *Cmd) {
1380 CLIParserContext *ctx;
1381 CLIParserInit(&ctx, "hf mf restore",
1382 "Restore MIFARE Classic dump file to tag.\n"
1383 "\n"
1384 "The key file and dump file will program the card sector trailers.\n"
1385 "By default we authenticate to card with key 0xFFFFFFFFFFFF.\n"
1386 "If access rights in dump file is all zeros, it will be replaced with default values\n"
1387 "\n"
1388 "`--uid` param is used for filename templates `hf-mf-<uid>-dump.bin` and `hf-mf-<uid>-key.bin.\n"
1389 " if not specified, it will read the card uid instead.\n"
1390 " `--ka` param you can indicate that the key file should be used for authentication instead.\n"
1391 " if so we also try both B/A keys\n"
1392 "`--force` param is used to override warnings and allow bad ACL block writes.\n"
1393 " if not specified, it will skip blocks with bad ACL.\n",
1394 "hf mf restore\n"
1395 "hf mf restore --1k --uid 04010203\n"
1396 "hf mf restore --1k --uid 04010203 -k hf-mf-AABBCCDD-key.bin\n"
1397 "hf mf restore --4k"
1400 void *argtable[] = {
1401 arg_param_begin,
1402 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
1403 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
1404 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
1405 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
1406 arg_str0("u", "uid", "<hex>", "uid, (4|7|10 hex bytes)"),
1407 arg_str0("f", "file", "<fn>", "specify a filename for dump file"),
1408 arg_str0("k", "kfn", "<fn>", "key filename"),
1409 arg_lit0(NULL, "ka", "use specified keyfile to authenticate"),
1410 arg_lit0(NULL, "force", "override warnings"),
1411 arg_param_end
1413 CLIExecWithReturn(ctx, Cmd, argtable, true);
1415 bool m0 = arg_get_lit(ctx, 1);
1416 bool m1 = arg_get_lit(ctx, 2);
1417 bool m2 = arg_get_lit(ctx, 3);
1418 bool m4 = arg_get_lit(ctx, 4);
1420 int uidlen = 0;
1421 char uid[20] = {0};
1422 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)uid, sizeof(uid), &uidlen);
1424 int datafnlen = 0;
1425 char datafilename[FILE_PATH_SIZE] = {0};
1426 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)datafilename, FILE_PATH_SIZE, &datafnlen);
1428 int keyfnlen = 0;
1429 char keyfilename[FILE_PATH_SIZE] = {0};
1430 CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)keyfilename, FILE_PATH_SIZE, &keyfnlen);
1432 bool use_keyfile_for_auth = arg_get_lit(ctx, 8);
1433 bool force = arg_get_lit(ctx, 9);
1435 CLIParserFree(ctx);
1437 // validations
1438 if ((m0 + m1 + m2 + m4) > 1) {
1439 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
1440 return PM3_EINVARG;
1441 } else if ((m0 + m1 + m2 + m4) == 0) {
1442 m1 = true;
1445 uint8_t sectors = MIFARE_1K_MAXSECTOR;
1447 if (m0) {
1448 sectors = MIFARE_MINI_MAXSECTOR;
1449 } else if (m1) {
1450 sectors = MIFARE_1K_MAXSECTOR;
1451 } else if (m2) {
1452 sectors = MIFARE_2K_MAXSECTOR;
1453 } else if (m4) {
1454 sectors = MIFARE_4K_MAXSECTOR;
1455 } else {
1456 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
1457 return PM3_EINVARG;
1460 // if user specified UID, use it in file templates
1461 if (uidlen) {
1463 if (keyfnlen == 0) {
1464 snprintf(keyfilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", uid);
1465 keyfnlen = strlen(keyfilename);
1468 if (datafnlen == 0) {
1469 snprintf(datafilename, FILE_PATH_SIZE, "hf-mf-%s-dump.bin", uid);
1470 datafnlen = strlen(datafilename);
1474 // try reading card uid and create filename
1475 if (keyfnlen == 0) {
1476 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
1477 if (fptr == NULL)
1478 return PM3_ESOFT;
1480 strncpy(keyfilename, fptr, sizeof(keyfilename) - 1);
1481 free(fptr);
1485 size_t alen = 0, blen = 0;
1486 uint8_t *keyA, *keyB;
1487 if (loadFileBinaryKey(keyfilename, "", (void **)&keyA, (void **)&keyB, &alen, &blen) != PM3_SUCCESS) {
1488 return PM3_ESOFT;
1491 PrintAndLogEx(INFO, "Using key file `" _YELLOW_("%s") "`", keyfilename);
1493 // try reading card uid and create filename
1494 if (datafnlen == 0) {
1495 char *fptr = GenerateFilename("hf-mf-", "-dump.bin");
1496 if (fptr == NULL) {
1497 if (keyA) {
1498 free(keyA);
1500 if (keyB) {
1501 free(keyB);
1503 return PM3_ESOFT;
1505 strcpy(datafilename, fptr);
1506 free(fptr);
1509 // read dump file
1510 uint8_t *dump = NULL;
1511 size_t bytes_read = 0;
1512 int res = pm3_load_dump(datafilename, (void **)&dump, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
1513 if (res != PM3_SUCCESS) {
1514 free(keyA);
1515 free(keyB);
1516 return res;
1519 // default authentication key
1520 uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1522 PrintAndLogEx(NORMAL, "");
1523 PrintAndLogEx(INFO, " blk | data | status");
1524 PrintAndLogEx(INFO, "-----+-------------------------------------------------+----------------");
1526 // main loop for restoring.
1527 // a bit more complicated than needed
1528 // this is because of two things.
1529 // 1. we are setting keys from a key file or using the existing ones in the dump
1530 // 2. we need to authenticate against a card which might not have default keys.
1531 uint8_t *ref_dump = dump;
1532 for (uint8_t s = 0; s < sectors; s++) {
1533 for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) {
1535 uint8_t bldata[MFBLOCK_SIZE] = {0x00};
1536 memcpy(bldata, dump, MFBLOCK_SIZE);
1538 bool skip = false;
1539 // if sector trailer
1540 if (mfIsSectorTrailerBasedOnBlocks(s, b)) {
1541 // keep the current keys on the card
1542 if (use_keyfile_for_auth == false) {
1543 // replace KEY A
1544 memcpy(bldata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1546 // replace KEY B
1547 memcpy(bldata + 10, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1550 // ensure access right isn't messed up.
1551 if (mfValidateAccessConditions(&bldata[6]) == false) {
1552 PrintAndLogEx(WARNING, "Invalid Access Conditions on sector %i, replacing with default values", s);
1553 memcpy(bldata + 6, "\xFF\x07\x80\x69", 4);
1556 // Warn if ACL is strict read-only
1557 for (uint8_t foo = 0; foo < mfNumBlocksPerSector(s); foo++) {
1558 if (mfReadOnlyAccessConditions(foo, &bldata[6])) {
1559 PrintAndLogEx(WARNING, "Strict ReadOnly Access Conditions on block " _YELLOW_("%u") " detected", foo);
1561 // if --force isn't used, skip writing this block
1562 if (force == false) {
1563 PrintAndLogEx(INFO, "Skipping, use `" _YELLOW_("--force") "` to override and write this data");
1564 skip = true;
1570 if (bytes_read) {
1571 dump += MFBLOCK_SIZE;
1572 bytes_read -= MFBLOCK_SIZE;
1574 if (skip) {
1575 continue;
1578 uint8_t wdata[26];
1579 memcpy(wdata + 10, bldata, sizeof(bldata));
1581 for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
1582 if (use_keyfile_for_auth) {
1584 if (kt == MF_KEY_A) {
1585 memcpy(wdata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1586 } else {
1587 memcpy(wdata, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
1590 } else {
1591 // use default key to authenticate for the write command
1592 memcpy(wdata, default_key, MIFARE_KEY_SIZE);
1595 uint16_t blockno = (mfFirstBlockOfSector(s) + b);
1597 clearCommandBuffer();
1598 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, kt, 0, wdata, sizeof(wdata));
1599 PacketResponseNG resp;
1600 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1601 PrintAndLogEx(WARNING, "command execution time out");
1602 continue;
1605 int isOK = resp.oldarg[0] & 0xff;
1606 if (isOK == 1) {
1607 // if success, skip to next block
1608 PrintAndLogEx(INFO, " %3d | %s| ( " _GREEN_("ok") " )", blockno, sprint_hex(bldata, sizeof(bldata)));
1609 break;
1611 // write somehow failed. Lets determine why.
1612 if (isOK == PM3_ETEAROFF) {
1613 PrintAndLogEx(INFO, "Tear off triggered. Recommendation is not to use tear-off with restore command");
1614 goto out;
1617 PrintAndLogEx(INFO, " %3d | %s| ( " _RED_("fail") " ) key " _YELLOW_("%c"),
1618 blockno,
1619 sprint_hex(bldata, sizeof(bldata)),
1620 (kt == MF_KEY_A) ? 'A' : 'B'
1622 } // end loop key types
1623 } // end loop B
1624 } // end loop S
1626 out:
1627 free(ref_dump);
1628 free(keyA);
1629 free(keyB);
1630 PrintAndLogEx(INFO, "-----+-------------------------------------------------+----------------");
1631 PrintAndLogEx(NORMAL, "");
1632 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf dump --ns") "` to verify");
1633 PrintAndLogEx(INFO, "Done!");
1634 return PM3_SUCCESS;
1637 static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't find keys...
1638 CLIParserContext *ctx;
1639 CLIParserInit(&ctx, "hf mf nested",
1640 "Execute Nested attack against MIFARE Classic card for key recovery",
1641 "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"
1642 "hf mf nested --mini --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n"
1643 "hf mf nested --1k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n"
1644 "hf mf nested --2k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n"
1645 "hf mf nested --4k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k");
1647 void *argtable[] = {
1648 arg_param_begin,
1649 arg_str0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
1650 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
1651 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
1652 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
1653 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
1654 arg_int0(NULL, "blk", "<dec>", "Input block number"),
1655 arg_lit0("a", NULL, "Input key specified is A key (default)"),
1656 arg_lit0("b", NULL, "Input key specified is B key"),
1657 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
1658 arg_int0(NULL, "tblk", "<dec>", "Target block number"),
1659 arg_lit0(NULL, "ta", "Target A key (default)"),
1660 arg_lit0(NULL, "tb", "Target B key"),
1661 arg_int0(NULL, "tc", "<dec>", "Nested input key type is key A + offset (you must specify a single block as well!)"),
1662 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
1663 arg_lit0(NULL, "dump", "Dump found keys to file"),
1664 arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
1665 arg_lit0("i", NULL, "Ignore static encrypted nonces"),
1666 arg_param_end
1668 CLIExecWithReturn(ctx, Cmd, argtable, false);
1670 int keylen = 0;
1671 uint8_t key[6] = {0};
1672 CLIGetHexWithReturn(ctx, 1, key, &keylen);
1674 bool m0 = arg_get_lit(ctx, 2);
1675 bool m1 = arg_get_lit(ctx, 3);
1676 bool m2 = arg_get_lit(ctx, 4);
1677 bool m4 = arg_get_lit(ctx, 5);
1679 uint8_t blockNo = arg_get_u32_def(ctx, 6, 0);
1681 uint8_t keyType = MF_KEY_A;
1683 if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) {
1684 CLIParserFree(ctx);
1685 PrintAndLogEx(WARNING, "Choose one single input key type");
1686 return PM3_EINVARG;
1687 } else if (arg_get_lit(ctx, 8)) {
1688 keyType = MF_KEY_B;
1690 uint8_t prev_keytype = keyType;
1691 keyType = arg_get_int_def(ctx, 9, keyType);
1692 if ((arg_get_lit(ctx, 7) || arg_get_lit(ctx, 8)) && (keyType != prev_keytype)) {
1693 CLIParserFree(ctx);
1694 PrintAndLogEx(WARNING, "Choose one single input key type");
1695 return PM3_EINVARG;
1698 int trgBlockNo = arg_get_int_def(ctx, 10, -1);
1700 uint8_t trgKeyType = MF_KEY_A;
1702 if (arg_get_lit(ctx, 11) && arg_get_lit(ctx, 12)) {
1703 CLIParserFree(ctx);
1704 PrintAndLogEx(WARNING, "Choose one single target key type");
1705 return PM3_EINVARG;
1706 } else if (arg_get_lit(ctx, 12)) {
1707 trgKeyType = MF_KEY_B;
1709 uint8_t prev_trgkeytype = trgKeyType;
1710 trgKeyType = arg_get_int_def(ctx, 13, trgKeyType);
1711 if ((arg_get_lit(ctx, 11) || arg_get_lit(ctx, 12)) && (trgKeyType != prev_trgkeytype)) {
1712 CLIParserFree(ctx);
1713 PrintAndLogEx(WARNING, "Choose one single target key type");
1714 return PM3_EINVARG;
1716 bool transferToEml = arg_get_lit(ctx, 14);
1717 bool createDumpFile = arg_get_lit(ctx, 15);
1718 bool singleSector = trgBlockNo > -1;
1719 bool use_flashmemory = arg_get_lit(ctx, 16);
1720 bool ignore_static_encrypted = arg_get_lit(ctx, 17);
1722 CLIParserFree(ctx);
1724 //validations
1725 if ((m0 + m1 + m2 + m4) > 1) {
1726 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
1727 return PM3_EINVARG;
1730 uint8_t SectorsCnt = 1;
1731 if (m0) {
1732 SectorsCnt = MIFARE_MINI_MAXSECTOR;
1733 } else if (m1) {
1734 SectorsCnt = MIFARE_1K_MAXSECTOR;
1735 } else if (m2) {
1736 SectorsCnt = MIFARE_2K_MAXSECTOR;
1737 } else if (m4) {
1738 SectorsCnt = MIFARE_4K_MAXSECTOR;
1741 if (singleSector) {
1742 uint8_t MinSectorsCnt = 0;
1743 // find a MIFARE type that can accommodate the provided block number
1744 uint8_t s = MAX(mfSectorNum(trgBlockNo), mfSectorNum(blockNo));
1745 if (s < MIFARE_MINI_MAXSECTOR) {
1746 MinSectorsCnt = MIFARE_MINI_MAXSECTOR;
1747 } else if (s < MIFARE_1K_MAXSECTOR) {
1748 MinSectorsCnt = MIFARE_1K_MAXSECTOR;
1749 } else if (s < MIFARE_2K_MAXSECTOR) {
1750 MinSectorsCnt = MIFARE_2K_MAXSECTOR;
1751 } else if (s < MIFARE_4K_MAXSECTOR) {
1752 MinSectorsCnt = MIFARE_4K_MAXSECTOR;
1753 } else {
1754 PrintAndLogEx(WARNING, "Provided block out of possible MIFARE Type memory map");
1755 return PM3_EINVARG;
1757 if (SectorsCnt == 1) {
1758 SectorsCnt = MinSectorsCnt;
1759 } else if (SectorsCnt < MinSectorsCnt) {
1760 PrintAndLogEx(WARNING, "Provided block out of provided MIFARE Type memory map");
1761 return PM3_EINVARG;
1764 if (SectorsCnt == 1) {
1765 SectorsCnt = MIFARE_1K_MAXSECTOR;
1768 if (keylen != 6) {
1769 PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols");
1770 return PM3_EINVARG;
1773 sector_t *e_sector = NULL;
1774 uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6];
1775 uint64_t key64 = 0;
1777 // check if tag doesn't have static nonce
1778 if (detect_classic_static_nonce() == NONCE_STATIC) {
1779 PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
1780 PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf staticnested`"));
1781 return PM3_EOPABORTED;
1784 // check if we can authenticate to sector
1785 if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) {
1786 if (keyType < 2) {
1787 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
1788 } else {
1789 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockNo, MIFARE_AUTH_KEYA + keyType);
1791 return PM3_EOPABORTED;
1794 if (singleSector) {
1795 int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, !ignore_static_encrypted);
1796 switch (isOK) {
1797 case PM3_ETIMEOUT:
1798 PrintAndLogEx(ERR, "command execution time out\n");
1799 break;
1800 case PM3_EOPABORTED:
1801 PrintAndLogEx(WARNING, "Button pressed. Aborted\n");
1802 break;
1803 case PM3_EFAILED:
1804 PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable).\n");
1805 break;
1806 case PM3_ESOFT:
1807 PrintAndLogEx(FAILED, "No valid key found");
1808 break;
1809 case PM3_ESTATIC_NONCE:
1810 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
1811 break;
1812 case PM3_SUCCESS:
1813 key64 = bytes_to_num(keyBlock, 6);
1815 // transfer key to the emulator
1816 if (transferToEml) {
1817 uint8_t sectortrailer;
1819 if (trgBlockNo < 32 * 4) { // 4 block sector
1820 sectortrailer = trgBlockNo | 0x03;
1821 } else { // 16 block sector
1822 sectortrailer = trgBlockNo | 0x0f;
1824 mfEmlGetMem(keyBlock, sectortrailer, 1);
1826 if (trgKeyType == MF_KEY_A)
1827 num_to_bytes(key64, 6, keyBlock);
1828 else
1829 num_to_bytes(key64, 6, &keyBlock[10]);
1831 mfEmlSetMem(keyBlock, sectortrailer, 1);
1832 PrintAndLogEx(SUCCESS, "Key transferred to emulator memory.");
1834 return PM3_SUCCESS;
1835 default :
1836 PrintAndLogEx(ERR, "Unknown error\n");
1838 return PM3_SUCCESS;
1840 } else { // ------------------------------------ multiple sectors working
1841 uint64_t t1 = msclock();
1843 e_sector = calloc(SectorsCnt, sizeof(sector_t));
1844 if (e_sector == NULL) return PM3_EMALLOC;
1846 // add our known key
1847 e_sector[mfSectorNum(blockNo)].foundKey[keyType] = 1;
1848 e_sector[mfSectorNum(blockNo)].Key[keyType] = key64;
1850 //test current key and additional standard keys first
1851 // add parameter key
1852 memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6);
1854 for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) {
1855 num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
1858 PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt);
1859 int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, use_flashmemory, false);
1860 if (res == PM3_SUCCESS) {
1861 PrintAndLogEx(SUCCESS, "Fast check found all keys");
1862 goto jumptoend;
1865 uint64_t t2 = msclock() - t1;
1866 PrintAndLogEx(SUCCESS, "Time to check " _YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0);
1867 PrintAndLogEx(SUCCESS, "enter nested key recovery");
1869 // nested sectors
1870 bool calibrate = !ignore_static_encrypted;
1872 for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) {
1873 for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) {
1874 for (int i = 0; i < MIFARE_SECTOR_RETRY; i++) {
1876 if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
1878 int16_t isOK = mfnested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
1879 switch (isOK) {
1880 case PM3_ETIMEOUT:
1881 PrintAndLogEx(ERR, "command execution time out\n");
1882 break;
1883 case PM3_EOPABORTED:
1884 PrintAndLogEx(WARNING, "button pressed. Aborted\n");
1885 break;
1886 case PM3_EFAILED :
1887 PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable)\n");
1888 break;
1889 case PM3_ESOFT:
1890 //key not found
1891 calibrate = false;
1892 continue;
1893 case PM3_ESTATIC_NONCE:
1894 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
1895 break;
1896 case PM3_SUCCESS:
1897 calibrate = false;
1898 e_sector[sectorNo].foundKey[trgKeyType] = 1;
1899 e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
1901 mfCheckKeys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false);
1902 continue;
1903 default :
1904 PrintAndLogEx(ERR, "Unknown error\n");
1906 free(e_sector);
1907 return PM3_ESOFT;
1912 t1 = msclock() - t1;
1913 PrintAndLogEx(SUCCESS, "time in nested " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
1916 // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
1917 PrintAndLogEx(INFO, "trying to read key B...");
1918 for (int i = 0; i < SectorsCnt; i++) {
1919 // KEY A but not KEY B
1920 if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
1922 uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
1924 PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
1926 mf_readblock_t payload;
1927 payload.blockno = sectrail;
1928 payload.keytype = MF_KEY_A;
1930 num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
1932 clearCommandBuffer();
1933 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
1935 PacketResponseNG resp;
1936 if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
1938 if (resp.status != PM3_SUCCESS) continue;
1940 uint8_t *data = resp.data.asBytes;
1941 key64 = bytes_to_num(data + 10, 6);
1942 if (key64) {
1943 PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6));
1944 e_sector[i].foundKey[1] = true;
1945 e_sector[i].Key[1] = key64;
1950 jumptoend:
1952 PrintAndLogEx(NORMAL, "");
1953 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
1955 //print them
1956 printKeyTable(SectorsCnt, e_sector);
1958 // transfer them to the emulator
1959 if (transferToEml) {
1960 // fast push mode
1961 g_conn.block_after_ACK = true;
1962 for (int i = 0; i < SectorsCnt; i++) {
1963 mfEmlGetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
1965 if (e_sector[i].foundKey[0])
1966 num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
1968 if (e_sector[i].foundKey[1])
1969 num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
1971 if (i == SectorsCnt - 1) {
1972 // Disable fast mode on last packet
1973 g_conn.block_after_ACK = false;
1975 mfEmlSetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
1977 PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
1980 // Create dump file
1981 if (createDumpFile) {
1982 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
1983 if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
1984 PrintAndLogEx(ERR, "Failed to save keys to file");
1985 free(e_sector);
1986 free(fptr);
1987 return PM3_EFILE;
1989 free(fptr);
1991 free(e_sector);
1993 return PM3_SUCCESS;
1996 static int CmdHF14AMfNestedStatic(const char *Cmd) {
1997 CLIParserContext *ctx;
1998 CLIParserInit(&ctx, "hf mf staticnested",
1999 "Execute static nested attack against MIFARE Classic card with static nonce for key recovery.\n"
2000 "Supply a known key from one block to recover all keys",
2001 "hf mf staticnested --mini --blk 0 -a -k FFFFFFFFFFFF\n"
2002 "hf mf staticnested --1k --blk 0 -a -k FFFFFFFFFFFF\n"
2003 "hf mf staticnested --2k --blk 0 -a -k FFFFFFFFFFFF\n"
2004 "hf mf staticnested --4k --blk 0 -a -k FFFFFFFFFFFF\n");
2006 void *argtable[] = {
2007 arg_param_begin,
2008 arg_str0("k", "key", "<hex>", "Known key (12 hex symbols)"),
2009 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
2010 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
2011 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
2012 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
2013 arg_int0(NULL, "blk", "<dec>", "Input block number"),
2014 arg_lit0("a", NULL, "Input key specified is keyA (def)"),
2015 arg_lit0("b", NULL, "Input key specified is keyB"),
2016 arg_lit0("e", "emukeys", "Fill simulator keys from found keys"),
2017 arg_lit0(NULL, "dumpkeys", "Dump found keys to file"),
2018 arg_param_end
2020 CLIExecWithReturn(ctx, Cmd, argtable, false);
2022 int keylen = 0;
2023 uint8_t key[6] = {0};
2024 CLIGetHexWithReturn(ctx, 1, key, &keylen);
2026 bool m0 = arg_get_lit(ctx, 2);
2027 bool m1 = arg_get_lit(ctx, 3);
2028 bool m2 = arg_get_lit(ctx, 4);
2029 bool m4 = arg_get_lit(ctx, 5);
2031 uint8_t blockNo = arg_get_u32_def(ctx, 6, 0);
2033 uint8_t keyType = MF_KEY_A;
2035 if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) {
2036 CLIParserFree(ctx);
2037 PrintAndLogEx(WARNING, "Choose one single input key type");
2038 return PM3_EINVARG;
2039 } else if (arg_get_lit(ctx, 8)) {
2040 keyType = MF_KEY_B;
2043 bool transferToEml = arg_get_lit(ctx, 9);
2044 bool createDumpFile = arg_get_lit(ctx, 10);
2045 CLIParserFree(ctx);
2047 //validations
2048 if ((m0 + m1 + m2 + m4) > 1) {
2049 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
2050 return PM3_EINVARG;
2053 uint8_t SectorsCnt = 1;
2054 if (m0) {
2055 SectorsCnt = MIFARE_MINI_MAXSECTOR;
2056 } else if (m1) {
2057 SectorsCnt = MIFARE_1K_MAXSECTOR;
2058 } else if (m2) {
2059 SectorsCnt = MIFARE_2K_MAXSECTOR;
2060 } else if (m4) {
2061 SectorsCnt = MIFARE_4K_MAXSECTOR;
2062 } else {
2063 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
2064 return PM3_EINVARG;
2067 if (keylen != 6) {
2068 PrintAndLogEx(WARNING, "Input key must include 12 HEX symbols");
2069 return PM3_EINVARG;
2072 sector_t *e_sector = NULL;
2074 uint8_t trgKeyType = MF_KEY_A;
2076 uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6];
2077 uint64_t key64 = 0;
2079 // check if tag have static nonce
2080 if (detect_classic_static_nonce() != NONCE_STATIC) {
2081 PrintAndLogEx(WARNING, "Normal nonce detected, or failed read of card. Quitting...");
2082 PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf nested`"));
2083 return PM3_EOPABORTED;
2086 // check if we can authenticate to sector
2087 if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) {
2088 if (keyType < 2) {
2089 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A');
2090 } else {
2091 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockNo, MIFARE_AUTH_KEYA + keyType);
2093 return PM3_EOPABORTED;
2096 if (IfPm3Flash()) {
2097 PrintAndLogEx(INFO, "RDV4 with flashmemory supported detected.");
2100 uint64_t t1 = msclock();
2102 e_sector = calloc(SectorsCnt, sizeof(sector_t));
2103 if (e_sector == NULL)
2104 return PM3_EMALLOC;
2106 // add our known key
2107 e_sector[mfSectorNum(blockNo)].foundKey[keyType] = 1;
2108 e_sector[mfSectorNum(blockNo)].Key[keyType] = key64;
2110 //test current key and additional standard keys first
2111 // add parameter key
2112 memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6);
2114 for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) {
2115 num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6));
2118 PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt);
2119 int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false, false);
2120 if (res == PM3_SUCCESS) {
2121 // all keys found
2122 PrintAndLogEx(SUCCESS, "Fast check found all keys");
2123 goto jumptoend;
2126 uint64_t t2 = msclock() - t1;
2127 PrintAndLogEx(SUCCESS, "Time to check "_YELLOW_("%zu") " known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0);
2128 PrintAndLogEx(SUCCESS, "enter static nested key recovery");
2130 // nested sectors
2131 for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) {
2132 for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) {
2134 for (int i = 0; i < 1; i++) {
2136 if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
2138 int16_t isOK = mfStaticNested(blockNo, keyType, key, mfFirstBlockOfSector(sectorNo), trgKeyType, keyBlock);
2139 switch (isOK) {
2140 case PM3_ETIMEOUT :
2141 PrintAndLogEx(ERR, "command execution time out");
2142 break;
2143 case PM3_EOPABORTED :
2144 PrintAndLogEx(WARNING, "aborted via keyboard.");
2145 break;
2146 case PM3_ESOFT :
2147 continue;
2148 case PM3_SUCCESS :
2149 e_sector[sectorNo].foundKey[trgKeyType] = 1;
2150 e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
2152 // mfCheckKeys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false);
2153 continue;
2154 default :
2155 PrintAndLogEx(ERR, "unknown error.\n");
2157 free(e_sector);
2158 return PM3_ESOFT;
2163 t1 = msclock() - t1;
2164 PrintAndLogEx(SUCCESS, "time in static nested " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
2167 // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
2168 PrintAndLogEx(INFO, "trying to read key B...");
2169 for (int i = 0; i < SectorsCnt; i++) {
2170 // KEY A but not KEY B
2171 if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
2173 uint8_t sectrail = (mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
2175 PrintAndLogEx(SUCCESS, "reading block %d", sectrail);
2177 mf_readblock_t payload;
2178 payload.blockno = sectrail;
2179 payload.keytype = MF_KEY_A;
2181 num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A
2183 clearCommandBuffer();
2184 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
2186 PacketResponseNG resp;
2187 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) {
2188 continue;
2191 if (resp.status != PM3_SUCCESS) continue;
2193 uint8_t *data = resp.data.asBytes;
2194 key64 = bytes_to_num(data + 10, 6);
2195 if (key64) {
2196 PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6));
2197 e_sector[i].foundKey[1] = true;
2198 e_sector[i].Key[1] = key64;
2203 jumptoend:
2205 PrintAndLogEx(NORMAL, "");
2206 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
2208 //print them
2209 printKeyTable(SectorsCnt, e_sector);
2211 // transfer them to the emulator
2212 if (transferToEml) {
2213 // fast push mode
2214 g_conn.block_after_ACK = true;
2215 for (int i = 0; i < SectorsCnt; i++) {
2216 mfEmlGetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
2218 if (e_sector[i].foundKey[0])
2219 num_to_bytes(e_sector[i].Key[0], 6, keyBlock);
2221 if (e_sector[i].foundKey[1])
2222 num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]);
2224 if (i == SectorsCnt - 1) {
2225 // Disable fast mode on last packet
2226 g_conn.block_after_ACK = false;
2228 mfEmlSetMem(keyBlock, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1);
2230 PrintAndLogEx(SUCCESS, "keys transferred to emulator memory.");
2233 // Create dump file
2234 if (createDumpFile) {
2235 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
2236 if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) {
2237 PrintAndLogEx(ERR, "Failed to save keys to file");
2238 free(e_sector);
2239 free(fptr);
2240 return PM3_EFILE;
2242 free(fptr);
2244 free(e_sector);
2246 return PM3_SUCCESS;
2249 static int CmdHF14AMfNestedHard(const char *Cmd) {
2251 CLIParserContext *ctx;
2252 CLIParserInit(&ctx, "hf mf hardnested",
2253 "Nested attack for hardened MIFARE Classic cards.\n"
2254 "if card is EV1, command can detect and use known key see example below\n"
2255 " \n"
2256 "`--i<X>` set type of SIMD instructions. Without this flag programs autodetect it.\n"
2257 " or \n"
2258 " hf mf hardnested -r --tk [known target key]\n"
2259 "Add the known target key to check if it is present in the remaining key space\n"
2260 " hf mf hardnested --blk 0 -a -k A0A1A2A3A4A5 --tblk 4 --ta --tk FFFFFFFFFFFF\n"
2262 "hf mf hardnested --tblk 4 --ta --> works for MFC EV1\n"
2263 "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta\n"
2264 "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -w\n"
2265 "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -f nonces.bin -w -s\n"
2266 "hf mf hardnested -r\n"
2267 "hf mf hardnested -r --tk a0a1a2a3a4a5\n"
2268 "hf mf hardnested -t --tk a0a1a2a3a4a5\n"
2269 "hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk FFFFFFFFFFFF\n"
2272 void *argtable[] = {
2273 arg_param_begin,
2274 arg_str0("k", "key", "<hex>", "Key, 12 hex bytes"), // 1
2275 arg_int0(NULL, "blk", "<dec>", "Input block number"), // 2
2276 arg_lit0("a", NULL, "Input key A (def)"), // 3
2277 arg_lit0("b", NULL, "Input key B"),
2278 arg_int0(NULL, "tblk", "<dec>", "Target block number"),
2279 arg_lit0(NULL, "ta", "Target key A"),
2280 arg_lit0(NULL, "tb", "Target key B"),
2281 arg_str0(NULL, "tk", "<hex>", "Target key, 12 hex bytes"), // 8
2282 arg_str0("u", "uid", "<hex>", "R/W `hf-mf-<UID>-nonces.bin` instead of default name"),
2283 arg_str0("f", "file", "<fn>", "R/W <name> instead of default name"),
2284 arg_lit0("r", "read", "Read `hf-mf-<UID>-nonces.bin` if tag present, otherwise `nonces.bin`, and start attack"),
2285 arg_lit0("s", "slow", "Slower acquisition (required by some non standard cards)"),
2286 arg_lit0("t", "tests", "Run tests"),
2287 arg_lit0("w", "wr", "Acquire nonces and UID, and write them to file `hf-mf-<UID>-nonces.bin`"),
2289 arg_lit0(NULL, "in", "None (use CPU regular instruction set)"),
2290 #if defined(COMPILER_HAS_SIMD_X86)
2291 arg_lit0(NULL, "im", "MMX"),
2292 arg_lit0(NULL, "is", "SSE2"),
2293 arg_lit0(NULL, "ia", "AVX"),
2294 arg_lit0(NULL, "i2", "AVX2"),
2295 #endif
2296 #if defined(COMPILER_HAS_SIMD_AVX512)
2297 arg_lit0(NULL, "i5", "AVX512"),
2298 #endif
2299 #if defined(COMPILER_HAS_SIMD_NEON)
2300 arg_lit0(NULL, "ie", "NEON"),
2301 #endif
2302 arg_param_end
2304 CLIExecWithReturn(ctx, Cmd, argtable, false);
2306 int keylen = 0;
2307 uint8_t key[6] = {0};
2308 CLIGetHexWithReturn(ctx, 1, key, &keylen);
2310 uint8_t blockno = arg_get_u32_def(ctx, 2, 0);
2312 uint8_t keytype = MF_KEY_A;
2313 if (arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) {
2314 CLIParserFree(ctx);
2315 PrintAndLogEx(WARNING, "Choose one single input key type");
2316 return PM3_EINVARG;
2317 } else if (arg_get_lit(ctx, 4)) {
2318 keytype = MF_KEY_B;
2321 uint8_t trg_blockno = arg_get_u32_def(ctx, 5, 0);
2323 uint8_t trg_keytype = MF_KEY_A;
2324 if (arg_get_lit(ctx, 6) && arg_get_lit(ctx, 7)) {
2325 CLIParserFree(ctx);
2326 PrintAndLogEx(WARNING, "Choose one single target key type");
2327 return PM3_EINVARG;
2328 } else if (arg_get_lit(ctx, 7)) {
2329 trg_keytype = MF_KEY_B;
2332 int trg_keylen = 0;
2333 uint8_t trg_key[6] = {0};
2334 CLIGetHexWithReturn(ctx, 8, trg_key, &trg_keylen);
2336 int uidlen = 0;
2337 char uid[14] = {0};
2338 CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)uid, sizeof(uid), &uidlen);
2340 int fnlen = 0;
2341 char filename[FILE_PATH_SIZE] = {0};
2342 CLIParamStrToBuf(arg_get_str(ctx, 10), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2344 bool nonce_file_read = arg_get_lit(ctx, 11);
2345 bool slow = arg_get_lit(ctx, 12);
2346 bool tests = arg_get_lit(ctx, 13);
2347 bool nonce_file_write = arg_get_lit(ctx, 14);
2349 bool in = arg_get_lit(ctx, 15);
2350 #if defined(COMPILER_HAS_SIMD_X86)
2351 bool im = arg_get_lit(ctx, 16);
2352 bool is = arg_get_lit(ctx, 17);
2353 bool ia = arg_get_lit(ctx, 18);
2354 bool i2 = arg_get_lit(ctx, 19);
2355 #endif
2356 #if defined(COMPILER_HAS_SIMD_AVX512)
2357 bool i5 = arg_get_lit(ctx, 20);
2358 #endif
2359 #if defined(COMPILER_HAS_SIMD_NEON)
2360 bool ie = arg_get_lit(ctx, 16);
2361 #endif
2362 CLIParserFree(ctx);
2364 // set SIM instructions
2365 SetSIMDInstr(SIMD_AUTO);
2367 #if defined(COMPILER_HAS_SIMD_AVX512)
2368 if (i5)
2369 SetSIMDInstr(SIMD_AVX512);
2370 #endif
2372 #if defined(COMPILER_HAS_SIMD_X86)
2373 if (i2)
2374 SetSIMDInstr(SIMD_AVX2);
2375 if (ia)
2376 SetSIMDInstr(SIMD_AVX);
2377 if (is)
2378 SetSIMDInstr(SIMD_SSE2);
2379 if (im)
2380 SetSIMDInstr(SIMD_MMX);
2381 #endif
2383 #if defined(COMPILER_HAS_SIMD_NEON)
2384 if (ie)
2385 SetSIMDInstr(SIMD_NEON);
2386 #endif
2388 if (in)
2389 SetSIMDInstr(SIMD_NONE);
2392 bool known_target_key = (trg_keylen);
2394 if (nonce_file_read) {
2395 char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
2396 if (fptr == NULL)
2397 strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1);
2398 else
2399 strncpy(filename, fptr, FILE_PATH_SIZE - 1);
2400 free(fptr);
2403 if (nonce_file_write) {
2404 char *fptr = GenerateFilename("hf-mf-", "-nonces.bin");
2405 if (fptr == NULL) {
2406 return PM3_EFILE;
2408 strncpy(filename, fptr, FILE_PATH_SIZE - 1);
2409 free(fptr);
2412 if (uidlen) {
2413 snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid);
2416 if (g_session.pm3_present && !tests) {
2417 // detect MFC EV1 Signature
2418 if (detect_mfc_ev1_signature() && keylen == 0) {
2419 PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
2420 blockno = 69;
2421 keytype = MF_KEY_B;
2422 memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
2425 if (known_target_key == false && nonce_file_read == false) {
2426 // check if tag doesn't have static nonce
2427 if (detect_classic_static_nonce() == NONCE_STATIC) {
2428 PrintAndLogEx(WARNING, "Static nonce detected. Quitting...");
2429 PrintAndLogEx(HINT, "\tTry use `" _YELLOW_("hf mf staticnested") "`");
2430 return PM3_EOPABORTED;
2433 uint64_t key64 = 0;
2434 // check if we can authenticate to sector
2435 if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) {
2436 if (keytype < 2) {
2437 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockno, keytype ? 'B' : 'A');
2438 } else {
2439 PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%02x", blockno, MIFARE_AUTH_KEYA + keytype);
2441 return PM3_EWRONGANSWER;
2446 PrintAndLogEx(INFO, "Target block no " _YELLOW_("%3d") ", target key type: " _YELLOW_("%c") ", known target key: " _YELLOW_("%02x%02x%02x%02x%02x%02x%s"),
2447 trg_blockno,
2448 (trg_keytype == MF_KEY_B) ? 'B' : 'A',
2449 trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5],
2450 known_target_key ? "" : " (not set)"
2452 PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") ", Slow: " _YELLOW_("%s") ", Tests: " _YELLOW_("%d"),
2453 nonce_file_write ? "write" : nonce_file_read ? "read" : "none",
2454 slow ? "Yes" : "No",
2455 tests);
2457 uint64_t foundkey = 0;
2458 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);
2459 switch (isOK) {
2460 case PM3_ETIMEOUT :
2461 PrintAndLogEx(ERR, "Error: No response from Proxmark3\n");
2462 break;
2463 case PM3_EOPABORTED:
2464 PrintAndLogEx(WARNING, "Button pressed. Aborted\n");
2465 break;
2466 case PM3_ESTATIC_NONCE:
2467 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
2468 break;
2469 case PM3_EFAILED: {
2470 PrintAndLogEx(FAILED, "\nFailed to recover a key...");
2471 break;
2473 default :
2474 break;
2477 if ((tests == 0) && IfPm3Iso14443a()) {
2478 DropField();
2480 return isOK;
2483 static int CmdHF14AMfAutoPWN(const char *Cmd) {
2485 CLIParserContext *ctx;
2486 CLIParserInit(&ctx, "hf mf autopwn",
2487 "This command automates the key recovery process on MIFARE Classic cards.\n"
2488 "It uses the fchk, chk, darkside, nested, hardnested and staticnested to recover keys.\n"
2489 "If all keys are found, it try dumping card content both to file and emulator memory.",
2490 "hf mf autopwn\n"
2491 "hf mf autopwn -s 0 -a -k FFFFFFFFFFFF --> target MFC 1K card, Sector 0 with known key A 'FFFFFFFFFFFF'\n"
2492 "hf mf autopwn --1k -f mfc_default_keys --> target MFC 1K card, default dictionary\n"
2493 "hf mf autopwn --1k -s 0 -a -k FFFFFFFFFFFF -f mfc_default_keys --> combo of the two above samples\n"
2494 "hf mf autopwn --1k -s 0 -a -k FFFFFFFFFFFF -k a0a1a2a3a4a5 --> multiple user supplied keys"
2497 void *argtable[] = {
2498 arg_param_begin,
2499 arg_strx0("k", "key", "<hex>", "Known key, 12 hex bytes"),
2500 arg_int0("s", "sector", "<dec>", "Input sector number"),
2501 arg_lit0("a", NULL, "Input key A (def)"),
2502 arg_lit0("b", NULL, "Input key B"),
2503 arg_str0("f", "file", "<fn>", "filename of dictionary"),
2504 arg_lit0(NULL, "slow", "Slower acquisition (required by some non standard cards)"),
2505 arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"),
2506 arg_lit0("v", "verbose", "verbose output"),
2508 arg_lit0(NULL, "ns", "No save to file"),
2510 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
2511 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
2512 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
2513 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
2515 arg_lit0(NULL, "in", "None (use CPU regular instruction set)"),
2516 #if defined(COMPILER_HAS_SIMD_X86)
2517 arg_lit0(NULL, "im", "MMX"),
2518 arg_lit0(NULL, "is", "SSE2"),
2519 arg_lit0(NULL, "ia", "AVX"),
2520 arg_lit0(NULL, "i2", "AVX2"),
2521 #endif
2522 #if defined(COMPILER_HAS_SIMD_AVX512)
2523 arg_lit0(NULL, "i5", "AVX512"),
2524 #endif
2525 #if defined(COMPILER_HAS_SIMD_NEON)
2526 arg_lit0(NULL, "ie", "NEON"),
2527 #endif
2528 arg_param_end
2530 CLIExecWithReturn(ctx, Cmd, argtable, true);
2532 int in_keys_len = 0;
2533 uint8_t in_keys[100 * MIFARE_KEY_SIZE] = {0};
2534 CLIGetHexWithReturn(ctx, 1, in_keys, &in_keys_len);
2536 uint8_t sectorno = arg_get_u32_def(ctx, 2, 0);
2538 uint8_t keytype = MF_KEY_A;
2539 if (arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) {
2540 CLIParserFree(ctx);
2541 PrintAndLogEx(WARNING, "Choose one single input key type");
2542 return PM3_EINVARG;
2543 } else if (arg_get_lit(ctx, 4)) {
2544 keytype = MF_KEY_B;
2547 int fnlen = 0;
2548 char filename[FILE_PATH_SIZE] = {0};
2549 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2551 bool slow = arg_get_lit(ctx, 6);
2552 bool legacy_mfchk = arg_get_lit(ctx, 7);
2553 bool verbose = arg_get_lit(ctx, 8);
2555 bool no_save = arg_get_lit(ctx, 9);
2557 bool m0 = arg_get_lit(ctx, 10);
2558 bool m1 = arg_get_lit(ctx, 11);
2559 bool m2 = arg_get_lit(ctx, 12);
2560 bool m4 = arg_get_lit(ctx, 13);
2562 bool in = arg_get_lit(ctx, 14);
2563 #if defined(COMPILER_HAS_SIMD_X86)
2564 bool im = arg_get_lit(ctx, 15);
2565 bool is = arg_get_lit(ctx, 16);
2566 bool ia = arg_get_lit(ctx, 17);
2567 bool i2 = arg_get_lit(ctx, 18);
2568 #endif
2569 #if defined(COMPILER_HAS_SIMD_AVX512)
2570 bool i5 = arg_get_lit(ctx, 19);
2571 #endif
2572 #if defined(COMPILER_HAS_SIMD_NEON)
2573 bool ie = arg_get_lit(ctx, 15);
2574 #endif
2576 CLIParserFree(ctx);
2578 //validations
2579 if ((m0 + m1 + m2 + m4) > 1) {
2580 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
2581 return PM3_EINVARG;
2582 } else if ((m0 + m1 + m2 + m4) == 0) {
2583 m1 = true;
2586 uint8_t sector_cnt = MIFARE_1K_MAXSECTOR;
2587 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
2589 if (m0) {
2590 sector_cnt = MIFARE_MINI_MAXSECTOR;
2591 block_cnt = MIFARE_MINI_MAXBLOCK;
2592 } else if (m1) {
2593 sector_cnt = MIFARE_1K_MAXSECTOR;
2594 block_cnt = MIFARE_1K_MAXBLOCK;
2595 } else if (m2) {
2596 sector_cnt = MIFARE_2K_MAXSECTOR;
2597 block_cnt = MIFARE_2K_MAXBLOCK;
2598 } else if (m4) {
2599 sector_cnt = MIFARE_4K_MAXSECTOR;
2600 block_cnt = MIFARE_4K_MAXBLOCK;
2601 } else {
2602 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
2603 return PM3_EINVARG;
2607 // set SIM instructions
2608 SetSIMDInstr(SIMD_AUTO);
2610 #if defined(COMPILER_HAS_SIMD_AVX512)
2611 if (i5)
2612 SetSIMDInstr(SIMD_AVX512);
2613 #endif
2615 #if defined(COMPILER_HAS_SIMD_X86)
2616 if (i2)
2617 SetSIMDInstr(SIMD_AVX2);
2618 if (ia)
2619 SetSIMDInstr(SIMD_AVX);
2620 if (is)
2621 SetSIMDInstr(SIMD_SSE2);
2622 if (im)
2623 SetSIMDInstr(SIMD_MMX);
2624 #endif
2626 #if defined(COMPILER_HAS_SIMD_NEON)
2627 if (ie)
2628 SetSIMDInstr(SIMD_NEON);
2629 #endif
2631 if (in) {
2632 SetSIMDInstr(SIMD_NONE);
2635 // Nested and Hardnested parameter
2636 uint64_t key64 = 0;
2637 bool calibrate = true;
2639 // Attack key storage variables
2640 uint8_t *keyBlock = NULL;
2641 uint32_t key_cnt = 0;
2642 uint8_t tmp_key[MIFARE_KEY_SIZE] = {0};
2644 // Nested and Hardnested returned status
2645 uint64_t foundkey = 0;
2646 int current_sector_i = 0, current_key_type_i = 0;
2648 // Dumping and transfere to simulater memory
2649 uint8_t block[MFBLOCK_SIZE] = {0x00};
2650 int bytes;
2652 // Settings
2653 int prng_type = PM3_EUNDEF;
2654 int isOK = 0;
2655 // ------------------------------
2657 uint64_t tagT = GetHF14AMfU_Type();
2658 if (tagT != MFU_TT_UL_ERROR) {
2659 PrintAndLogEx(ERR, "Detected a MIFARE Ultralight/C/NTAG Compatible card.");
2660 PrintAndLogEx(ERR, "This command targets " _YELLOW_("MIFARE Classic"));
2661 return PM3_ESOFT;
2664 // Select card to get UID/UIDLEN/ATQA/SAK information
2665 clearCommandBuffer();
2666 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
2667 PacketResponseNG resp;
2668 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
2669 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
2670 return PM3_ETIMEOUT;
2673 uint64_t select_status = resp.oldarg[0];
2674 if (select_status == 0) {
2675 // iso14443a card select failed
2676 PrintAndLogEx(FAILED, "No tag detected or other tag communication error");
2677 PrintAndLogEx(HINT, "Hint: Try some distance or position of the card");
2678 return PM3_ECARDEXCHANGE;
2681 // store card info
2682 iso14a_card_select_t card;
2683 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
2685 bool known_key = (in_keys_len > 5);
2686 uint8_t key[MIFARE_KEY_SIZE] = {0};
2687 if (known_key) {
2688 memcpy(key, in_keys, sizeof(key));
2691 // Add KDF keys...
2692 uint16_t key1_offset = in_keys_len;
2693 uint64_t key1 = 0;
2695 // iceman: todo, need to add all generated keys
2696 mfc_algo_mizip_one(card.uid, 0, MF_KEY_A, &key1);
2697 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (0 * MIFARE_KEY_SIZE));
2699 mfc_algo_di_one(card.uid, 0, MF_KEY_A, &key1);
2700 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (1 * MIFARE_KEY_SIZE));
2702 mfc_algo_sky_one(card.uid, 15, MF_KEY_A, &key1);
2703 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (2 * MIFARE_KEY_SIZE));
2705 // one key
2706 mfc_algo_saflok_one(card.uid, 0, MF_KEY_A, &key1);
2707 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (3 * MIFARE_KEY_SIZE));
2709 mfc_algo_touch_one(card.uid, 0, MF_KEY_A, &key1);
2710 num_to_bytes(key1, MIFARE_KEY_SIZE, in_keys + key1_offset + (4 * MIFARE_KEY_SIZE));
2712 in_keys_len += (MIFARE_KEY_SIZE * 5);
2714 // detect MFC EV1 Signature
2715 bool is_ev1 = detect_mfc_ev1_signature();
2716 if (is_ev1) {
2717 // hidden sectors on MFC EV1
2718 sector_cnt += 2;
2721 // create/initialize key storage structure
2722 sector_t *e_sector = NULL;
2723 size_t e_sector_cnt = (sector_cnt > sectorno) ? sector_cnt : sectorno + 1;
2724 if (initSectorTable(&e_sector, e_sector_cnt) != PM3_SUCCESS) {
2725 return PM3_EMALLOC;
2728 if (is_ev1) {
2729 PrintAndLogEx(INFO, "MIFARE Classic EV1 card detected");
2731 // use found key if not supplied
2732 if (known_key == false) {
2733 known_key = true;
2734 sectorno = 17;
2735 keytype = MF_KEY_B;
2736 memcpy(key, g_mifare_signature_key_b, sizeof(g_mifare_signature_key_b));
2740 // read uid to generate a filename for the key file
2741 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
2743 // check if tag doesn't have static nonce
2744 int has_staticnonce = detect_classic_static_nonce();
2746 // card prng type (weak=1 / hard=0 / select/card comm error = negative value)
2747 if (has_staticnonce == NONCE_NORMAL) {
2748 prng_type = detect_classic_prng();
2749 if (prng_type < 0) {
2750 PrintAndLogEx(FAILED, "\nNo tag detected or other tag communication error (%i)", prng_type);
2751 free(e_sector);
2752 free(fptr);
2753 return PM3_ESOFT;
2757 // print parameters
2758 if (verbose) {
2759 PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " =======================");
2760 PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sector_cnt);
2761 PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), known_key ? "True" : "False");
2762 PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), sectorno);
2763 PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A');
2764 PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex_inrow(key, sizeof(key)));
2766 if (has_staticnonce == NONCE_STATIC)
2767 PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("STATIC"));
2768 else if (has_staticnonce == NONCE_NORMAL)
2769 PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("%s"), prng_type ? "WEAK" : "HARD");
2770 else
2771 PrintAndLogEx(INFO, " card PRNG ..... " _YELLOW_("Could not determine PRNG,") " " _RED_("read failed."));
2773 PrintAndLogEx(INFO, " dictionary .... " _YELLOW_("%s"), strlen(filename) ? filename : "NONE");
2774 PrintAndLogEx(INFO, " legacy mode ... " _YELLOW_("%s"), legacy_mfchk ? "True" : "False");
2776 PrintAndLogEx(INFO, "========================================================================");
2779 // check the user supplied key
2780 if (known_key == false) {
2781 PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail");
2784 // Start the timer
2785 uint64_t t1 = msclock();
2787 int ret = mf_load_keys(&keyBlock, &key_cnt, in_keys, in_keys_len, filename, fnlen, true);
2788 if (ret != PM3_SUCCESS) {
2789 free(e_sector);
2790 return ret;
2793 int32_t res = PM3_SUCCESS;
2795 // Use the dictionary to find sector keys on the card
2796 if (verbose) PrintAndLogEx(INFO, "======================= " _YELLOW_("START DICTIONARY ATTACK") " =======================");
2798 if (legacy_mfchk) {
2799 PrintAndLogEx(INFO, "." NOLF);
2800 // Check all the sectors
2801 for (int i = 0; i < sector_cnt; i++) {
2802 for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
2803 // Check if the key is known
2804 if (e_sector[i].foundKey[j] == 0) {
2805 for (uint32_t k = 0; k < key_cnt; k++) {
2806 PrintAndLogEx(NORMAL, "." NOLF);
2807 fflush(stdout);
2809 if (mfCheckKeys(mfFirstBlockOfSector(i), j, true, 1, (keyBlock + (MIFARE_KEY_SIZE * k)), &key64) == PM3_SUCCESS) {
2810 e_sector[i].Key[j] = bytes_to_num((keyBlock + (MIFARE_KEY_SIZE * k)), MIFARE_KEY_SIZE);
2811 e_sector[i].foundKey[j] = 'D';
2812 break;
2818 PrintAndLogEx(NORMAL, "");
2819 } else {
2821 uint32_t chunksize = key_cnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : key_cnt;
2822 bool firstChunk = true, lastChunk = false;
2824 for (uint8_t strategy = 1; strategy < 3; strategy++) {
2825 PrintAndLogEx(INFO, "running strategy %u", strategy);
2826 // main keychunk loop
2827 for (uint32_t i = 0; i < key_cnt; i += chunksize) {
2829 if (kbd_enter_pressed()) {
2830 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
2831 i = key_cnt;
2832 strategy = 3;
2833 break; // Exit the loop
2835 uint32_t size = ((key_cnt - i) > chunksize) ? chunksize : key_cnt - i;
2836 // last chunk?
2837 if (size == key_cnt - i) {
2838 lastChunk = true;
2841 res = mfCheckKeys_fast(sector_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, verbose);
2842 if (firstChunk) {
2843 firstChunk = false;
2845 // all keys, aborted
2846 if (res == PM3_SUCCESS) {
2847 i = key_cnt;
2848 strategy = 3;
2849 break; // Exit the loop
2851 } // end chunks of keys
2852 firstChunk = true;
2853 lastChunk = false;
2854 } // end strategy
2857 // Analyse the dictionary attack
2858 uint8_t num_found_keys = 0;
2859 for (int i = 0; i < sector_cnt; i++) {
2860 for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
2861 if (e_sector[i].foundKey[j] != 1) {
2862 continue;
2865 ++num_found_keys;
2867 e_sector[i].foundKey[j] = 'D';
2868 num_to_bytes(e_sector[i].Key[j], MIFARE_KEY_SIZE, tmp_key);
2870 // Store valid credentials for the nested / hardnested attack if none exist
2871 if (known_key == false) {
2872 num_to_bytes(e_sector[i].Key[j], MIFARE_KEY_SIZE, key);
2873 known_key = true;
2874 sectorno = i;
2875 keytype = j;
2876 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)",
2878 (j == MF_KEY_B) ? 'B' : 'A',
2879 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
2881 } else {
2882 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
2884 (j == MF_KEY_B) ? 'B' : 'A',
2885 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
2891 if (num_found_keys == sector_cnt * 2) {
2892 goto all_found;
2895 // Check if at least one sector key was found
2896 if (known_key == false) {
2898 // Check if the darkside attack can be used
2899 if (prng_type && has_staticnonce != NONCE_STATIC) {
2900 if (verbose) {
2901 PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " =======================");
2904 PrintAndLogEx(NORMAL, "");
2906 isOK = mfDarkside(mfFirstBlockOfSector(sectorno), MIFARE_AUTH_KEYA + keytype, &key64);
2908 if (isOK != PM3_SUCCESS)
2909 goto noValidKeyFound;
2911 PrintAndLogEx(SUCCESS, "Found valid key [ " _GREEN_("%012" PRIx64) " ]\n", key64);
2913 // Store the keys
2914 num_to_bytes(key64, MIFARE_KEY_SIZE, key);
2915 e_sector[sectorno].Key[keytype] = key64;
2916 e_sector[sectorno].foundKey[keytype] = 'S';
2917 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%012" PRIx64) " ] (used for nested / hardnested attack)",
2918 sectorno,
2919 (keytype == MF_KEY_B) ? 'B' : 'A',
2920 key64
2922 } else {
2924 noValidKeyFound:
2925 PrintAndLogEx(FAILED, "No usable key was found!");
2926 free(keyBlock);
2927 free(e_sector);
2928 free(fptr);
2929 return PM3_ESOFT;
2933 free(keyBlock);
2934 // Clear the needed variables
2935 num_to_bytes(0, MIFARE_KEY_SIZE, tmp_key);
2936 bool nested_failed = false;
2938 // Iterate over each sector and key(A/B)
2939 for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) {
2941 for (current_key_type_i = MF_KEY_A; current_key_type_i <= MF_KEY_B; current_key_type_i++) {
2943 // If the key is already known, just skip it
2944 if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
2946 if (has_staticnonce == NONCE_STATIC)
2947 goto tryStaticnested;
2949 // Try the found keys are reused
2950 if (bytes_to_num(tmp_key, MIFARE_KEY_SIZE) != 0) {
2951 // <!> The fast check --> mfCheckKeys_fast(sector_cnt, true, true, 2, 1, tmp_key, e_sector, false, verbose);
2952 // <!> Returns false keys, so we just stick to the slower mfchk.
2953 for (int i = 0; i < sector_cnt; i++) {
2954 for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
2955 // Check if the sector key is already broken
2956 if (e_sector[i].foundKey[j])
2957 continue;
2959 // Check if the key works
2960 if (mfCheckKeys(mfFirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) {
2961 e_sector[i].Key[j] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE);
2962 e_sector[i].foundKey[j] = 'R';
2963 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
2965 (j == MF_KEY_B) ? 'B' : 'A',
2966 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
2972 // Clear the last found key
2973 num_to_bytes(0, MIFARE_KEY_SIZE, tmp_key);
2975 if (current_key_type_i == MF_KEY_B) {
2976 if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) {
2977 if (verbose) {
2978 PrintAndLogEx(INFO, "======================= " _YELLOW_("START READ B KEY ATTACK") " =======================");
2979 PrintAndLogEx(INFO, "reading B key of sector %3d with key type %c",
2980 current_sector_i,
2981 (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
2983 uint8_t sectrail = (mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1);
2985 mf_readblock_t payload;
2986 payload.blockno = sectrail;
2987 payload.keytype = MF_KEY_A;
2989 num_to_bytes(e_sector[current_sector_i].Key[0], MIFARE_KEY_SIZE, payload.key); // KEY A
2991 clearCommandBuffer();
2992 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
2994 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) goto skipReadBKey;
2996 if (resp.status != PM3_SUCCESS) goto skipReadBKey;
2998 uint8_t *data = resp.data.asBytes;
2999 key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE);
3000 if (key64) {
3001 e_sector[current_sector_i].foundKey[current_key_type_i] = 'A';
3002 e_sector[current_sector_i].Key[current_key_type_i] = key64;
3003 num_to_bytes(key64, MIFARE_KEY_SIZE, tmp_key);
3004 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
3005 current_sector_i,
3006 (current_key_type_i == MF_KEY_B) ? 'B' : 'A',
3007 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
3009 } else {
3010 if (verbose) {
3011 PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c",
3012 current_sector_i,
3013 (current_key_type_i == MF_KEY_B) ? 'B' : 'A'
3015 PrintAndLogEx(INFO, " -- reading the B key was not possible, maybe due to access rights?");
3023 // Use the nested / hardnested attack
3024 skipReadBKey:
3025 if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
3027 if (has_staticnonce == NONCE_STATIC)
3028 goto tryStaticnested;
3030 if (prng_type && (nested_failed == false)) {
3031 uint8_t retries = 0;
3032 if (verbose) {
3033 PrintAndLogEx(INFO, "======================= " _YELLOW_("START NESTED ATTACK") " =======================");
3034 PrintAndLogEx(INFO, "sector no %3d, target key type %c",
3035 current_sector_i,
3036 (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
3038 tryNested:
3039 isOK = mfnested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate);
3041 switch (isOK) {
3042 case PM3_ETIMEOUT: {
3043 PrintAndLogEx(ERR, "\nError: No response from Proxmark3.");
3044 free(e_sector);
3045 free(fptr);
3046 return isOK;
3048 case PM3_EOPABORTED: {
3049 PrintAndLogEx(WARNING, "\nButton pressed. Aborted.");
3050 free(e_sector);
3051 free(fptr);
3052 return isOK;
3054 case PM3_EFAILED: {
3055 PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is probably not predictable).");
3056 PrintAndLogEx(FAILED, "Nested attack failed --> try hardnested");
3057 goto tryHardnested;
3059 case PM3_ESOFT: {
3060 // key not found
3061 calibrate = false;
3062 // this can happen on some old cards, it's worth trying some more before switching to slower hardnested
3063 if (retries++ < MIFARE_SECTOR_RETRY) {
3064 PrintAndLogEx(FAILED, "Nested attack failed, trying again (%i/%i)", retries, MIFARE_SECTOR_RETRY);
3065 goto tryNested;
3066 } else {
3067 PrintAndLogEx(FAILED, "Nested attack failed, moving to hardnested");
3068 nested_failed = true;
3069 goto tryHardnested;
3071 break;
3073 case PM3_ESTATIC_NONCE: {
3074 PrintAndLogEx(ERR, "Error: Static encrypted nonce detected. Aborted\n");
3076 e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;
3077 e_sector[current_sector_i].foundKey[current_key_type_i] = false;
3078 // Show the results to the user
3079 PrintAndLogEx(NORMAL, "");
3080 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3081 printKeyTable(sector_cnt, e_sector);
3082 PrintAndLogEx(NORMAL, "");
3083 free(e_sector);
3084 free(fptr);
3085 return isOK;
3087 case PM3_SUCCESS: {
3088 calibrate = false;
3089 e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE);
3090 e_sector[current_sector_i].foundKey[current_key_type_i] = 'N';
3091 break;
3093 default: {
3094 PrintAndLogEx(ERR, "unknown Error.\n");
3095 free(e_sector);
3096 free(fptr);
3097 return isOK;
3101 } else {
3102 tryHardnested: // If the nested attack fails then we try the hardnested attack
3103 if (verbose) {
3104 PrintAndLogEx(INFO, "======================= " _YELLOW_("START HARDNESTED ATTACK") " =======================");
3105 PrintAndLogEx(INFO, "sector no %3d, target key type %c, Slow %s",
3106 current_sector_i,
3107 (current_key_type_i == MF_KEY_B) ? 'B' : 'A',
3108 slow ? "Yes" : "No");
3111 foundkey = 0;
3112 isOK = mfnestedhard(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL);
3113 DropField();
3114 if (isOK != PM3_SUCCESS) {
3115 switch (isOK) {
3116 case PM3_ETIMEOUT: {
3117 PrintAndLogEx(ERR, "\nError: No response from Proxmark3");
3118 break;
3120 case PM3_EOPABORTED: {
3121 PrintAndLogEx(NORMAL, "\nButton pressed, user aborted");
3122 break;
3124 case PM3_ESTATIC_NONCE: {
3125 PrintAndLogEx(ERR, "\nError: Static encrypted nonce detected. Aborted\n");
3127 e_sector[current_sector_i].Key[current_key_type_i] = 0xffffffffffff;
3128 e_sector[current_sector_i].foundKey[current_key_type_i] = false;
3130 // Show the results to the user
3131 PrintAndLogEx(NORMAL, "");
3132 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3133 printKeyTable(sector_cnt, e_sector);
3134 PrintAndLogEx(NORMAL, "");
3135 break;
3137 case PM3_EFAILED: {
3138 PrintAndLogEx(FAILED, "\nFailed to recover a key...");
3139 continue;
3141 default: {
3142 break;
3145 free(e_sector);
3146 free(fptr);
3147 return PM3_ESOFT;
3150 // Copy the found key to the tmp_key variale (for the following print statement, and the mfCheckKeys above)
3151 num_to_bytes(foundkey, MIFARE_KEY_SIZE, tmp_key);
3152 e_sector[current_sector_i].Key[current_key_type_i] = foundkey;
3153 e_sector[current_sector_i].foundKey[current_key_type_i] = 'H';
3156 if (has_staticnonce == NONCE_STATIC) {
3157 tryStaticnested:
3158 if (verbose) {
3159 PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " =======================");
3160 PrintAndLogEx(INFO, "sector no %3d, target key type %c",
3161 current_sector_i,
3162 (current_key_type_i == MF_KEY_B) ? 'B' : 'A');
3165 isOK = mfStaticNested(mfFirstBlockOfSector(sectorno), keytype, key, mfFirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key);
3166 DropField();
3167 switch (isOK) {
3168 case PM3_ETIMEOUT: {
3169 PrintAndLogEx(ERR, "\nError: No response from Proxmark3");
3170 free(e_sector);
3171 free(fptr);
3172 return isOK;
3174 case PM3_EOPABORTED: {
3175 PrintAndLogEx(WARNING, "\nButton pressed, user aborted");
3176 free(e_sector);
3177 free(fptr);
3178 return isOK;
3180 case PM3_SUCCESS: {
3181 e_sector[current_sector_i].Key[current_key_type_i] = bytes_to_num(tmp_key, MIFARE_KEY_SIZE);
3182 e_sector[current_sector_i].foundKey[current_key_type_i] = 'C';
3183 break;
3185 default: {
3186 break;
3191 // Check if the key was found
3192 if (e_sector[current_sector_i].foundKey[current_key_type_i]) {
3193 PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]",
3194 current_sector_i,
3195 (current_key_type_i == MF_KEY_B) ? 'B' : 'A',
3196 sprint_hex_inrow(tmp_key, sizeof(tmp_key))
3204 all_found:
3206 // Show the results to the user
3207 PrintAndLogEx(NORMAL, "");
3208 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3210 printKeyTable(sector_cnt, e_sector);
3212 if (no_save == false) {
3214 // Dump the keys
3215 PrintAndLogEx(NORMAL, "");
3216 if (createMfcKeyDump(fptr, sector_cnt, e_sector) != PM3_SUCCESS) {
3217 PrintAndLogEx(ERR, "Failed to save keys to file");
3221 // clear emulator mem
3222 clearCommandBuffer();
3223 SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0);
3225 PrintAndLogEx(INFO, "transferring keys to simulator memory " NOLF);
3227 bool transfer_status = true;
3228 for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) {
3229 mfEmlGetMem(block, current_sector_i, 1);
3230 if (e_sector[current_sector_i].foundKey[0])
3231 num_to_bytes(e_sector[current_sector_i].Key[0], MIFARE_KEY_SIZE, block);
3232 if (e_sector[current_sector_i].foundKey[1])
3233 num_to_bytes(e_sector[current_sector_i].Key[1], MIFARE_KEY_SIZE, block + 10);
3235 transfer_status |= mfEmlSetMem(block, mfFirstBlockOfSector(current_sector_i) + mfNumBlocksPerSector(current_sector_i) - 1, 1);
3237 PrintAndLogEx(NORMAL, "( %s )", (transfer_status) ? _GREEN_("ok") : _RED_("fail"));
3239 PrintAndLogEx(INFO, "dumping card content to emulator memory (Cmd Error: 04 can occur)");
3241 // use ecfill trick
3242 FastDumpWithEcFill(sector_cnt);
3244 if (no_save) {
3245 PrintAndLogEx(INFO, "Called with no save option");
3246 PrintAndLogEx(NORMAL, "");
3247 goto out;
3250 bytes = block_cnt * MFBLOCK_SIZE;
3251 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
3252 if (dump == NULL) {
3253 PrintAndLogEx(ERR, "Fail, cannot allocate memory");
3254 free(e_sector);
3255 free(fptr);
3256 return PM3_EMALLOC;
3259 PrintAndLogEx(INFO, "downloading card content from emulator memory");
3260 if (GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false) == false) {
3261 PrintAndLogEx(ERR, "Fail, transfer from device time-out");
3262 free(e_sector);
3263 free(dump);
3264 free(fptr);
3265 return PM3_ETIMEOUT;
3268 free(fptr);
3269 fptr = GenerateFilename("hf-mf-", "-dump");
3270 if (fptr == NULL) {
3271 free(dump);
3272 free(e_sector);
3273 free(fptr);
3274 return PM3_ESOFT;
3277 strncpy(filename, fptr, sizeof(filename) - 1);
3278 free(fptr);
3280 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
3281 free(dump);
3283 out:
3284 // Generate and show statistics
3285 t1 = msclock() - t1;
3286 PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0);
3288 free(e_sector);
3289 return PM3_SUCCESS;
3292 static int CmdHF14AMfChk_fast(const char *Cmd) {
3293 CLIParserContext *ctx;
3294 CLIParserInit(&ctx, "hf mf fchk",
3295 "This is a improved checkkeys method speedwise. It checks MIFARE Classic tags sector keys against a dictionary file with keys",
3296 "hf mf fchk --mini -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n"
3297 "hf mf fchk --1k -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n"
3298 "hf mf fchk --2k -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n"
3299 "hf mf fchk --4k -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k\n"
3300 "hf mf fchk --1k -f mfc_default_keys.dic --> Target 1K using default dictionary file\n"
3301 "hf mf fchk --1k --emu --> Target 1K, write keys to emulator memory\n"
3302 "hf mf fchk --1k --dump --> Target 1K, write keys to file\n"
3303 "hf mf fchk --1k --mem --> Target 1K, use dictionary from flash memory");
3305 void *argtable[] = {
3306 arg_param_begin,
3307 arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
3308 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
3309 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
3310 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
3311 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
3312 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
3313 arg_lit0(NULL, "dump", "Dump found keys to binary file"),
3314 arg_lit0(NULL, "mem", "Use dictionary from flashmemory"),
3315 arg_str0("f", "file", "<fn>", "filename of dictionary"),
3316 arg_int0(NULL, "blk", "<dec>", "block number (single block recovery mode)"),
3317 arg_lit0("a", NULL, "single block recovery key A"),
3318 arg_lit0("b", NULL, "single block recovery key B"),
3319 arg_lit0(NULL, "no-default", "Skip check default keys"),
3320 arg_param_end
3322 CLIExecWithReturn(ctx, Cmd, argtable, true);
3324 int keylen = 0;
3325 uint8_t key[100 * MIFARE_KEY_SIZE] = {0};
3326 CLIGetHexWithReturn(ctx, 1, key, &keylen);
3328 bool m0 = arg_get_lit(ctx, 2);
3329 bool m1 = arg_get_lit(ctx, 3);
3330 bool m2 = arg_get_lit(ctx, 4);
3331 bool m4 = arg_get_lit(ctx, 5);
3333 bool transferToEml = arg_get_lit(ctx, 6);
3334 bool createDumpFile = arg_get_lit(ctx, 7);
3335 bool use_flashmemory = arg_get_lit(ctx, 8);
3337 int fnlen = 0;
3338 char filename[FILE_PATH_SIZE] = {0};
3339 CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3341 int blockn = arg_get_int_def(ctx, 10, -1);
3342 uint8_t keytype = MF_KEY_A;
3343 if (arg_get_lit(ctx, 11) && arg_get_lit(ctx, 12)) {
3344 CLIParserFree(ctx);
3345 PrintAndLogEx(WARNING, "Choose one single input key type");
3346 return PM3_EINVARG;
3347 } else if (arg_get_lit(ctx, 12)) {
3348 keytype = MF_KEY_B;
3350 bool load_default = ! arg_get_lit(ctx, 13);
3352 CLIParserFree(ctx);
3354 //validations
3356 if ((m0 + m1 + m2 + m4) > 1) {
3357 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
3358 return PM3_EINVARG;
3359 } else if ((m0 + m1 + m2 + m4) == 0) {
3360 m1 = true;
3363 uint8_t sectorsCnt = MIFARE_1K_MAXSECTOR;
3364 if (m0) {
3365 sectorsCnt = MIFARE_MINI_MAXSECTOR;
3366 } else if (m1) {
3367 sectorsCnt = MIFARE_1K_MAXSECTOR;
3368 } else if (m2) {
3369 sectorsCnt = MIFARE_2K_MAXSECTOR;
3370 } else if (m4) {
3371 sectorsCnt = MIFARE_4K_MAXSECTOR;
3372 } else {
3373 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
3374 return PM3_EINVARG;
3377 uint8_t *keyBlock = NULL;
3378 uint32_t keycnt = 0;
3379 int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default);
3380 if (ret != PM3_SUCCESS) {
3381 return ret;
3384 // create/initialize key storage structure
3385 sector_t *e_sector = NULL;
3386 if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
3387 free(keyBlock);
3388 return PM3_EMALLOC;
3391 uint32_t chunksize = keycnt > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : keycnt;
3392 bool firstChunk = true, lastChunk = false;
3394 int i = 0;
3396 // time
3397 uint64_t t1 = msclock();
3399 uint16_t singleSectorParams = 0;
3400 if (blockn != -1) {
3401 singleSectorParams = (blockn & 0xFF) | keytype << 8 | 1 << 15;
3403 if (use_flashmemory) {
3404 PrintAndLogEx(SUCCESS, "Using dictionary in flash memory");
3405 mfCheckKeys_fast_ex(sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory, false, false, singleSectorParams);
3406 } else {
3408 // strategies. 1= deep first on sector 0 AB, 2= width first on all sectors
3409 for (uint8_t strategy = 1; strategy < 3; strategy++) {
3410 PrintAndLogEx(INFO, "Running strategy %u", strategy);
3412 // main keychunk loop
3413 for (i = 0; i < keycnt; i += chunksize) {
3415 if (kbd_enter_pressed()) {
3416 PrintAndLogEx(NORMAL, "");
3417 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
3418 // field is still ON if not on last chunk
3419 clearCommandBuffer();
3420 SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0);
3421 // TODO: we're missing these cleanups on arm side, not sure if it's important...
3422 // set_tracing(false);
3423 // BigBuf_free();
3424 // BigBuf_Clear_ext(false);
3425 goto out;
3427 PrintAndLogEx(INPLACE, "Testing %5i/%5i %02.1f%%", i, keycnt, (float)i * 100 / keycnt);
3428 uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i;
3430 // last chunk?
3431 if (size == keycnt - i)
3432 lastChunk = true;
3434 int res = mfCheckKeys_fast_ex(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * MIFARE_KEY_SIZE), e_sector, false, false, true, singleSectorParams);
3435 if (firstChunk)
3436 firstChunk = false;
3438 // all keys, aborted
3439 if (res == PM3_SUCCESS || res == 2) {
3440 PrintAndLogEx(NORMAL, "");
3441 goto out;
3443 } // end chunks of keys
3444 PrintAndLogEx(INPLACE, "Testing %5i/%5i 100.00%%", keycnt, keycnt);
3445 PrintAndLogEx(NORMAL, "");
3446 firstChunk = true;
3447 lastChunk = false;
3448 if (blockn != -1) break;
3449 } // end strategy
3451 out:
3452 t1 = msclock() - t1;
3453 PrintAndLogEx(INFO, "Time in checkkeys (fast) " _YELLOW_("%.1fs") "\n", (float)(t1 / 1000.0));
3455 if (blockn != -1) {
3456 goto out2;
3459 // check..
3460 uint8_t found_keys = 0;
3461 for (i = 0; i < sectorsCnt; ++i) {
3463 if (e_sector[i].foundKey[0])
3464 found_keys++;
3466 if (e_sector[i].foundKey[1])
3467 found_keys++;
3470 if (found_keys == 0) {
3471 PrintAndLogEx(WARNING, "No keys found");
3472 } else {
3474 PrintAndLogEx(NORMAL, "");
3475 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3477 printKeyTable(sectorsCnt, e_sector);
3479 if (use_flashmemory && found_keys == (sectorsCnt << 1)) {
3480 PrintAndLogEx(SUCCESS, "Card dumped as well. run " _YELLOW_("`%s %c`"),
3481 "hf mf esave",
3482 GetFormatFromSector(sectorsCnt)
3486 if (transferToEml) {
3487 // fast push mode
3488 g_conn.block_after_ACK = true;
3489 uint8_t block[MFBLOCK_SIZE] = {0x00};
3490 for (i = 0; i < sectorsCnt; ++i) {
3491 uint8_t b = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
3492 mfEmlGetMem(block, b, 1);
3494 if (e_sector[i].foundKey[0])
3495 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block);
3497 if (e_sector[i].foundKey[1])
3498 num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10);
3500 if (i == sectorsCnt - 1) {
3501 // Disable fast mode on last packet
3502 g_conn.block_after_ACK = false;
3504 mfEmlSetMem(block, b, 1);
3506 PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
3508 if (found_keys == (sectorsCnt << 1)) {
3509 FastDumpWithEcFill(sectorsCnt);
3513 if (createDumpFile) {
3515 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
3516 if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) {
3517 PrintAndLogEx(ERR, "Failed to save keys to file");
3519 free(fptr);
3522 out2:
3523 free(keyBlock);
3524 free(e_sector);
3525 PrintAndLogEx(NORMAL, "");
3526 return PM3_SUCCESS;
3529 static int CmdHF14AMfSmartBrute(const char *Cmd) {
3530 CLIParserContext *ctx;
3531 CLIParserInit(&ctx, "hf mf brute",
3532 "This is a smart bruteforce, exploiting common patterns, bugs and bad designs in key generators.",
3533 "hf mf brute --mini --> Key recovery against MIFARE Mini\n"
3534 "hf mf brute --1k --> Key recovery against MIFARE Classic 1k\n"
3535 "hf mf brute --2k --> Key recovery against MIFARE 2k\n"
3536 "hf mf brute --4k --> Key recovery against MIFARE 4k\n"
3537 "hf mf brute --1k --emu --> Target 1K, write keys to emulator memory\n"
3538 "hf mf brute --1k --dump --> Target 1K, write keys to file\n");
3540 void *argtable[] = {
3541 arg_param_begin,
3542 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
3543 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
3544 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
3545 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
3546 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
3547 arg_lit0(NULL, "dump", "Dump found keys to binary file"),
3548 arg_param_end
3550 CLIExecWithReturn(ctx, Cmd, argtable, true);
3553 bool m0 = arg_get_lit(ctx, 2);
3554 bool m1 = arg_get_lit(ctx, 3);
3555 bool m2 = arg_get_lit(ctx, 4);
3556 bool m4 = arg_get_lit(ctx, 5);
3558 bool transferToEml = arg_get_lit(ctx, 6);
3559 bool createDumpFile = arg_get_lit(ctx, 7);
3561 CLIParserFree(ctx);
3563 //validations
3565 if ((m0 + m1 + m2 + m4) > 1) {
3566 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
3567 return PM3_EINVARG;
3568 } else if ((m0 + m1 + m2 + m4) == 0) {
3569 m1 = true;
3572 uint8_t sectorsCnt = MIFARE_1K_MAXSECTOR;
3573 if (m0) {
3574 sectorsCnt = MIFARE_MINI_MAXSECTOR;
3575 } else if (m1) {
3576 sectorsCnt = MIFARE_1K_MAXSECTOR;
3577 } else if (m2) {
3578 sectorsCnt = MIFARE_2K_MAXSECTOR;
3579 } else if (m4) {
3580 sectorsCnt = MIFARE_4K_MAXSECTOR;
3581 } else {
3582 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
3583 return PM3_EINVARG;
3586 uint32_t chunksize = 100 > (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) ? (PM3_CMD_DATA_SIZE / MIFARE_KEY_SIZE) : 100;
3587 uint8_t *keyBlock = calloc(MIFARE_KEY_SIZE, chunksize);
3589 if (keyBlock == NULL)
3590 return PM3_EMALLOC;
3592 // create/initialize key storage structure
3593 sector_t *e_sector = NULL;
3594 if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
3595 free(keyBlock);
3596 return PM3_EMALLOC;
3599 // initialize bruteforce engine
3600 generator_context_t bctx;
3601 bf_generator_init(&bctx, BF_MODE_SMART, BF_KEY_SIZE_48);
3603 int i = 0, ret;
3604 int smart_mode_stage = -1;
3605 uint64_t generator_key;
3607 // time
3608 uint64_t t0 = msclock();
3609 uint64_t t1 = msclock();
3610 uint64_t keys_checked = 0;
3611 uint64_t total_keys_checked = 0;
3613 uint32_t keycnt = 0;
3614 bool firstChunk = true, lastChunk = false;
3616 while (!lastChunk) {
3617 keycnt = 0;
3619 // generate block of keys from generator
3620 memset(keyBlock, 0, MIFARE_KEY_SIZE * chunksize);
3622 for (i = 0; i < chunksize; i++) {
3624 ret = bf_generate(&bctx);
3626 if (ret == BF_GENERATOR_ERROR) {
3627 PrintAndLogEx(ERR, "Internal bruteforce generator error");
3628 free(keyBlock);
3629 free(e_sector);
3630 return PM3_EFAILED;
3632 } else if (ret == BF_GENERATOR_END) {
3634 lastChunk = true;
3635 break;
3637 } else if (ret == BF_GENERATOR_NEXT) {
3639 generator_key = bf_get_key48(&bctx);
3640 num_to_bytes(generator_key, MIFARE_KEY_SIZE, keyBlock + (i * MIFARE_KEY_SIZE));
3641 keycnt++;
3643 if (smart_mode_stage != bctx.smart_mode_stage) {
3645 smart_mode_stage = bctx.smart_mode_stage;
3646 PrintAndLogEx(INFO, "Running bruteforce stage %d", smart_mode_stage);
3648 if (keys_checked) {
3650 PrintAndLogEx(INFO, "Current cracking speed (keys/s): %lu",
3651 keys_checked / ((msclock() - t1) / 1000)
3654 t1 = msclock();
3655 keys_checked = 0;
3661 int strategy = 2; // width first on all sectors
3662 ret = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, keycnt, keyBlock, e_sector, false, false);
3664 keys_checked += keycnt;
3665 total_keys_checked += keycnt;
3667 if (firstChunk)
3668 firstChunk = false;
3670 if (ret == PM3_SUCCESS || ret == 2)
3671 goto out;
3675 out:
3676 PrintAndLogEx(INFO, "Time in brute mode: " _YELLOW_("%.1fs") "\n", (float)((msclock() - t0) / 1000.0));
3677 PrintAndLogEx(INFO, "Total keys checked: " _YELLOW_("%lu") "\n", total_keys_checked);
3678 // check..
3679 uint8_t found_keys = 0;
3680 for (i = 0; i < sectorsCnt; ++i) {
3682 if (e_sector[i].foundKey[0]) {
3683 found_keys++;
3686 if (e_sector[i].foundKey[1]) {
3687 found_keys++;
3691 if (found_keys == 0) {
3692 PrintAndLogEx(WARNING, "No keys found");
3693 } else {
3695 PrintAndLogEx(NORMAL, "");
3696 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3698 printKeyTable(sectorsCnt, e_sector);
3700 if (transferToEml) {
3701 // fast push mode
3702 g_conn.block_after_ACK = true;
3703 uint8_t block[MFBLOCK_SIZE] = {0x00};
3704 for (i = 0; i < sectorsCnt; ++i) {
3705 uint8_t b = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
3706 mfEmlGetMem(block, b, 1);
3708 if (e_sector[i].foundKey[0])
3709 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block);
3711 if (e_sector[i].foundKey[1])
3712 num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10);
3714 if (i == sectorsCnt - 1) {
3715 // Disable fast mode on last packet
3716 g_conn.block_after_ACK = false;
3718 mfEmlSetMem(block, b, 1);
3720 PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
3722 if (found_keys == (sectorsCnt << 1)) {
3723 FastDumpWithEcFill(sectorsCnt);
3727 if (createDumpFile) {
3729 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
3730 if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) {
3731 PrintAndLogEx(ERR, "Failed to save keys to file");
3733 free(fptr);
3738 free(keyBlock);
3739 free(e_sector);
3740 PrintAndLogEx(NORMAL, "");
3741 return PM3_SUCCESS;
3744 static int CmdHF14AMfChk(const char *Cmd) {
3745 CLIParserContext *ctx;
3746 CLIParserInit(&ctx, "hf mf chk",
3747 "Check keys on MIFARE Classic card",
3748 "hf mf chk --mini -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE Mini\n"
3749 "hf mf chk --1k -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE Classic 1k\n"
3750 "hf mf chk --2k -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE 2k\n"
3751 "hf mf chk --4k -k FFFFFFFFFFFF --> Check all sectors, all keys against MIFARE 4k\n"
3752 "hf mf chk --1k --emu --> Check all sectors, all keys, 1K, and write to emulator memory\n"
3753 "hf mf chk --1k --dump --> Check all sectors, all keys, 1K, and write to file\n"
3754 "hf mf chk -a --tblk 0 -f mfc_default_keys.dic --> Check dictionary against block 0, key A");
3756 void *argtable[] = {
3757 arg_param_begin,
3758 arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
3759 arg_int0(NULL, "tblk", "<dec>", "Target block number"),
3760 arg_lit0("a", NULL, "Target Key A"),
3761 arg_lit0("b", NULL, "Target Key B"),
3762 arg_lit0("*", "all", "Target both key A & B (default)"),
3763 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
3764 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
3765 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
3766 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
3767 arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
3768 arg_lit0(NULL, "dump", "Dump found keys to binary file"),
3769 arg_str0("f", "file", "<fn>", "Filename of dictionary"),
3770 arg_lit0(NULL, "no-default", "Skip check default keys"),
3771 arg_param_end
3773 CLIExecWithReturn(ctx, Cmd, argtable, true);
3775 int keylen = 0;
3776 uint8_t key[100 * MIFARE_KEY_SIZE] = {0};
3777 CLIGetHexWithReturn(ctx, 1, key, &keylen);
3779 int blockNo = arg_get_int_def(ctx, 2, -1);
3781 uint8_t keyType = 2;
3783 if ((arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) || arg_get_lit(ctx, 5)) {
3784 keyType = 2;
3785 } else if (arg_get_lit(ctx, 3)) {
3786 keyType = MF_KEY_A;
3787 } else if (arg_get_lit(ctx, 4)) {
3788 keyType = MF_KEY_B;
3791 bool m0 = arg_get_lit(ctx, 6);
3792 bool m1 = arg_get_lit(ctx, 7);
3793 bool m2 = arg_get_lit(ctx, 8);
3794 bool m4 = arg_get_lit(ctx, 9);
3796 bool transferToEml = arg_get_lit(ctx, 10);
3797 bool createDumpFile = arg_get_lit(ctx, 11);
3799 int fnlen = 0;
3800 char filename[FILE_PATH_SIZE] = {0};
3801 CLIParamStrToBuf(arg_get_str(ctx, 12), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3802 bool load_default = ! arg_get_lit(ctx, 13);
3804 CLIParserFree(ctx);
3806 bool singleSector = (blockNo > -1);
3807 if (singleSector == false) {
3808 // start from first trailer block
3809 blockNo = 3;
3812 //validations
3813 if ((m0 + m1 + m2 + m4) > 1) {
3814 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
3815 return PM3_EINVARG;
3818 size_t sectors_cnt = 1;
3819 if (m0) {
3820 sectors_cnt = MIFARE_MINI_MAXSECTOR;
3821 } else if (m1) {
3822 sectors_cnt = MIFARE_1K_MAXSECTOR;
3823 } else if (m2) {
3824 sectors_cnt = MIFARE_2K_MAXSECTOR;
3825 } else if (m4) {
3826 sectors_cnt = MIFARE_4K_MAXSECTOR;
3829 if (singleSector) {
3831 // find a MIFARE type that can accommodate the provided block number
3832 size_t min_sectors_cnt = 0;
3833 uint8_t s = mfSectorNum(blockNo);
3835 if (s < MIFARE_MINI_MAXSECTOR) {
3836 min_sectors_cnt = MIFARE_MINI_MAXSECTOR;
3837 } else if (s < MIFARE_1K_MAXSECTOR) {
3838 min_sectors_cnt = MIFARE_1K_MAXSECTOR;
3839 } else if (s < MIFARE_2K_MAXSECTOR) {
3840 min_sectors_cnt = MIFARE_2K_MAXSECTOR;
3841 } else if (s < MIFARE_4K_MAXSECTOR) {
3842 min_sectors_cnt = MIFARE_4K_MAXSECTOR;
3843 } else {
3844 PrintAndLogEx(WARNING, "Provided block out of possible MIFARE Type memory map");
3845 return PM3_EINVARG;
3848 if (sectors_cnt == 1) {
3849 sectors_cnt = min_sectors_cnt;
3850 } else if (sectors_cnt < min_sectors_cnt) {
3851 PrintAndLogEx(WARNING, "Provided block out of provided MIFARE Type memory map");
3852 return PM3_EINVARG;
3856 if (sectors_cnt == 1) {
3857 sectors_cnt = MIFARE_1K_MAXSECTOR;
3860 uint8_t *keyBlock = NULL;
3861 uint32_t keycnt = 0;
3862 int ret = mf_load_keys(&keyBlock, &keycnt, key, keylen, filename, fnlen, load_default);
3863 if (ret != PM3_SUCCESS) {
3864 return ret;
3867 uint64_t key64 = 0;
3869 // create/initialize key storage structure
3870 sector_t *e_sector = NULL;
3871 if (initSectorTable(&e_sector, sectors_cnt) != PM3_SUCCESS) {
3872 free(keyBlock);
3873 return PM3_EMALLOC;
3876 uint8_t trgKeyType = MF_KEY_A;
3877 uint16_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
3879 PrintAndLogEx(INFO, "Start check for keys...");
3880 PrintAndLogEx(INFO, "." NOLF);
3882 // fast push mode
3883 g_conn.block_after_ACK = true;
3885 // clear trace log by first check keys call only
3886 bool clearLog = true;
3888 // time
3889 uint64_t t1 = msclock();
3891 // check keys.
3892 for (trgKeyType = (keyType == 2) ? 0 : keyType; trgKeyType < 2; (keyType == 2) ? (++trgKeyType) : (trgKeyType = 2)) {
3894 // loop sectors but block is used as to keep track of from which blocks to test
3895 int b = blockNo;
3896 for (int i = mfSectorNum(b); i < sectors_cnt; ++i) {
3898 // skip already found keys.
3899 if (e_sector[i].foundKey[trgKeyType]) continue;
3901 for (uint32_t c = 0; c < keycnt; c += max_keys) {
3903 PrintAndLogEx(NORMAL, "." NOLF);
3904 fflush(stdout);
3906 if (kbd_enter_pressed()) {
3907 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
3908 goto out;
3911 uint32_t size = keycnt - c > max_keys ? max_keys : keycnt - c;
3913 if (mfCheckKeys(b, trgKeyType, clearLog, size, &keyBlock[MIFARE_KEY_SIZE * c], &key64) == PM3_SUCCESS) {
3914 e_sector[i].Key[trgKeyType] = key64;
3915 e_sector[i].foundKey[trgKeyType] = true;
3916 clearLog = false;
3917 break;
3919 clearLog = false;
3921 if (singleSector)
3922 break;
3924 b < 127 ? (b += 4) : (b += 16);
3927 t1 = msclock() - t1;
3928 PrintAndLogEx(INFO, "\ntime in checkkeys " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
3930 // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag?
3931 if (keyType != MF_KEY_B) {
3932 PrintAndLogEx(INFO, "testing to read key B...");
3934 // loop sectors but block is used as to keep track of from which blocks to test
3935 int b = blockNo;
3936 for (int i = mfSectorNum(b); i < sectors_cnt; i++) {
3938 // KEY A but not KEY B
3939 if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) {
3941 uint8_t sectrail = mfSectorTrailerOfSector(i);
3942 PrintAndLogEx(INFO, "Sector: %u, First block: %u, Last block: %u, Num of blocks: %u", i, mfFirstBlockOfSector(i), sectrail, mfNumBlocksPerSector(i));
3943 PrintAndLogEx(INFO, "Reading sector trailer");
3945 mf_readblock_t payload;
3946 payload.blockno = sectrail;
3947 payload.keytype = MF_KEY_A;
3949 // Use key A
3950 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, payload.key);
3952 clearCommandBuffer();
3953 SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
3955 PacketResponseNG resp;
3956 if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
3958 if (resp.status != PM3_SUCCESS) continue;
3960 uint8_t *data = resp.data.asBytes;
3961 key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE);
3962 if (key64) {
3963 PrintAndLogEx(NORMAL, "Data:%s", sprint_hex(data + 10, MIFARE_KEY_SIZE));
3964 e_sector[i].foundKey[1] = 1;
3965 e_sector[i].Key[1] = key64;
3968 if (singleSector)
3969 break;
3970 b < 127 ? (b += 4) : (b += 16);
3974 out:
3975 PrintAndLogEx(NORMAL, "");
3976 PrintAndLogEx(SUCCESS, _GREEN_("found keys:"));
3978 //print keys
3979 // if (singleSector)
3980 // printKeyTableEx(1, e_sector, mfSectorNum(blockNo));
3981 // else
3982 printKeyTable(sectors_cnt, e_sector);
3984 if (transferToEml) {
3985 // fast push mode
3986 g_conn.block_after_ACK = true;
3987 uint8_t block[MFBLOCK_SIZE] = {0x00};
3988 for (int i = 0; i < sectors_cnt; ++i) {
3989 uint8_t blockno = mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1;
3990 mfEmlGetMem(block, blockno, 1);
3992 if (e_sector[i].foundKey[0])
3993 num_to_bytes(e_sector[i].Key[0], MIFARE_KEY_SIZE, block);
3995 if (e_sector[i].foundKey[1])
3996 num_to_bytes(e_sector[i].Key[1], MIFARE_KEY_SIZE, block + 10);
3998 if (i == sectors_cnt - 1) {
3999 // Disable fast mode on last packet
4000 g_conn.block_after_ACK = false;
4002 mfEmlSetMem(block, blockno, 1);
4004 PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
4007 if (createDumpFile) {
4008 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
4009 if (createMfcKeyDump(fptr, sectors_cnt, e_sector) != PM3_SUCCESS) {
4010 PrintAndLogEx(ERR, "Failed to save keys to file");
4012 free(fptr);
4015 free(keyBlock);
4016 free(e_sector);
4018 // Disable fast mode and send a dummy command to make it effective
4019 g_conn.block_after_ACK = false;
4020 SendCommandNG(CMD_PING, NULL, 0);
4021 if (!WaitForResponseTimeout(CMD_PING, NULL, 1000)) {
4022 PrintAndLogEx(WARNING, "command execution time out");
4023 return PM3_ETIMEOUT;
4026 PrintAndLogEx(NORMAL, "");
4027 return PM3_SUCCESS;
4030 void showSectorTable(sector_t *k_sector, size_t k_sectors_cnt) {
4031 if (k_sector != NULL) {
4032 printKeyTable(k_sectors_cnt, k_sector);
4033 free(k_sector);
4037 void readerAttack(sector_t *k_sector, size_t k_sectors_cnt, nonces_t data, bool setEmulatorMem, bool verbose) {
4039 // init if needed
4040 if (k_sector == NULL) {
4041 if (initSectorTable(&k_sector, k_sectors_cnt) != PM3_SUCCESS) {
4042 return;
4046 uint64_t key = 0;
4047 bool found = false;
4048 if ((nonce_state)data.state == SECOND) {
4049 found = mfkey32_moebius(&data, &key);
4050 } else if ((nonce_state)data.state == NESTED) {
4051 found = mfkey32_nested(&data, &key);
4053 if (found) {
4054 uint8_t sector = data.sector;
4055 uint8_t keytype = data.keytype;
4057 PrintAndLogEx(INFO, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]"
4058 , (keytype == MF_KEY_B) ? "B" : "A"
4059 , sector
4060 , key
4063 k_sector[sector].Key[keytype] = key;
4064 k_sector[sector].foundKey[keytype] = true;
4066 //set emulator memory for keys
4067 if (setEmulatorMem) {
4068 uint8_t memBlock[16];
4069 mfEmlGetMem(memBlock, (sector * 4) + 3, 1);
4070 if ((memBlock[6]==0) && (memBlock[7]==0) && (memBlock[8]==0)) {
4071 // ACL not yet set?
4072 memBlock[6] = 0xFF;
4073 memBlock[7] = 0x07;
4074 memBlock[8] = 0x80;
4076 num_to_bytes(k_sector[sector].Key[keytype], 6, memBlock + ((keytype == MF_KEY_B) ? 10 : 0));
4077 //iceman, guessing this will not work so well for 4K tags.
4078 PrintAndLogEx(INFO, "Setting Emulator Memory Block %02d: [%s]"
4079 , (sector * 4) + 3
4080 , sprint_hex(memBlock, sizeof(memBlock))
4082 mfEmlSetMem(memBlock, (sector * 4) + 3, 1);
4086 free(k_sector);
4089 static int CmdHF14AMfSim(const char *Cmd) {
4090 CLIParserContext *ctx;
4091 CLIParserInit(&ctx, "hf mf sim",
4092 "Simulate MIFARE Classic family type based upon\n"
4093 "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
4094 "from emulator memory. See `hf mf eload` first.\n"
4095 "The UID from emulator memory will be used if not specified.",
4096 "hf mf sim --mini --> MIFARE Mini\n"
4097 "hf mf sim --1k --> MIFARE Classic 1k (default)\n"
4098 "hf mf sim --1k -u 0a0a0a0a --> MIFARE Classic 1k with 4b UID\n"
4099 "hf mf sim --1k -u 11223344556677 --> MIFARE Classic 1k with 7b UID\n"
4100 "hf mf sim --1k -u 11223344 -i -x --> Perform reader attack in interactive mode\n"
4101 "hf mf sim --2k --> MIFARE 2k\n"
4102 "hf mf sim --4k --> MIFARE 4k"
4103 "hf mf sim --1k -x -e --> Keep simulation running and populate with found reader keys\n"
4106 void *argtable[] = {
4107 arg_param_begin,
4108 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
4109 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4110 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50"),
4111 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4112 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4113 arg_str0(NULL, "atqa", "<hex>", "Provide explicit ATQA (2 bytes, overrides option t)"),
4114 arg_str0(NULL, "sak", "<hex>", "Provide explicit SAK (1 bytes, overrides option t)"),
4115 arg_int0("n", "num", "<dec> ", "Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
4116 arg_lit0("i", "interactive", "Console will not be returned until simulation finishes or is aborted"),
4117 arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader."),
4118 arg_lit0("y", NULL, "Performs the nested 'reader attack'. This requires preloading nt & nt_enc in emulator memory. Implies -x."),
4119 arg_lit0("e", "emukeys", "Fill simulator keys from found keys. Requires -x or -y. Implies -i. Simulation will restart automatically."),
4120 arg_lit0("v", "verbose", "verbose output"),
4121 arg_lit0(NULL, "cve", "trigger CVE 2021_0430"),
4122 arg_param_end
4124 CLIExecWithReturn(ctx, Cmd, argtable, true);
4126 uint16_t flags = 0;
4128 int uidlen = 0;
4129 uint8_t uid[10] = {0};
4130 CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
4132 char uidsize[8] = {0};
4133 if (uidlen > 0) {
4134 switch (uidlen) {
4135 case 10:
4136 flags |= FLAG_10B_UID_IN_DATA;
4137 snprintf(uidsize, sizeof(uidsize), "10 byte");
4138 break;
4139 case 7:
4140 flags |= FLAG_7B_UID_IN_DATA;
4141 snprintf(uidsize, sizeof(uidsize), "7 byte");
4142 break;
4143 case 4:
4144 flags |= FLAG_4B_UID_IN_DATA;
4145 snprintf(uidsize, sizeof(uidsize), "4 byte");
4146 break;
4147 default:
4148 PrintAndLogEx(WARNING, "Invalid parameter for UID");
4149 CLIParserFree(ctx);
4150 return PM3_EINVARG;
4154 bool m0 = arg_get_lit(ctx, 2);
4155 bool m1 = arg_get_lit(ctx, 3);
4156 bool m2 = arg_get_lit(ctx, 4);
4157 bool m4 = arg_get_lit(ctx, 5);
4159 int atqalen = 0;
4160 uint8_t atqa[2] = {0};
4161 CLIGetHexWithReturn(ctx, 6, atqa, &atqalen);
4163 int saklen = 0;
4164 uint8_t sak[1] = {0};
4165 CLIGetHexWithReturn(ctx, 7, sak, &saklen);
4167 uint8_t exitAfterNReads = arg_get_u32_def(ctx, 8, 0);
4169 if (arg_get_lit(ctx, 9)) {
4170 flags |= FLAG_INTERACTIVE;
4173 if (arg_get_lit(ctx, 10)) {
4174 flags |= FLAG_NR_AR_ATTACK;
4177 if (arg_get_lit(ctx, 11)) {
4178 flags |= FLAG_NESTED_AUTH_ATTACK;
4181 bool setEmulatorMem = arg_get_lit(ctx, 12);
4183 bool verbose = arg_get_lit(ctx, 13);
4185 if (arg_get_lit(ctx, 14)) {
4186 flags |= FLAG_CVE21_0430;
4188 CLIParserFree(ctx);
4190 //Validations
4191 if (atqalen > 0) {
4192 if (atqalen != 2) {
4193 PrintAndLogEx(WARNING, "Wrong ATQA length");
4194 return PM3_EINVARG;
4196 flags |= FLAG_FORCED_ATQA;
4199 if (saklen > 0) {
4200 if (saklen != 1) {
4201 PrintAndLogEx(WARNING, "Wrong SAK length");
4202 return PM3_EINVARG;
4204 flags |= FLAG_FORCED_SAK;
4207 // Use UID, SAK, ATQA from EMUL, if uid not defined
4208 if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
4209 flags |= FLAG_UID_IN_EMUL;
4212 size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
4213 char csize[13] = { 0 };
4215 if ((m0 + m1 + m2 + m4) > 1) {
4216 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4217 return PM3_EINVARG;
4220 if (m0) {
4221 flags |= FLAG_MF_MINI;
4222 snprintf(csize, sizeof(csize), "MINI");
4223 k_sectors_cnt = MIFARE_MINI_MAXSECTOR;
4224 } else if (m1) {
4225 flags |= FLAG_MF_1K;
4226 snprintf(csize, sizeof(csize), "1K");
4227 k_sectors_cnt = MIFARE_1K_MAXSECTOR;
4228 } else if (m2) {
4229 flags |= FLAG_MF_2K;
4230 snprintf(csize, sizeof(csize), "2K with RATS");
4231 k_sectors_cnt = MIFARE_2K_MAXSECTOR;
4232 } else if (m4) {
4233 flags |= FLAG_MF_4K;
4234 snprintf(csize, sizeof(csize), "4K");
4235 k_sectors_cnt = MIFARE_4K_MAXSECTOR;
4236 } else {
4237 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
4238 return PM3_EINVARG;
4241 if ((flags & FLAG_NESTED_AUTH_ATTACK) == FLAG_NESTED_AUTH_ATTACK) {
4242 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
4243 PrintAndLogEx(INFO, "Note: option -y implies -x");
4244 flags |= FLAG_NR_AR_ATTACK;
4248 if (setEmulatorMem) {
4249 if ((flags & FLAG_INTERACTIVE) != FLAG_INTERACTIVE) {
4250 PrintAndLogEx(INFO, "Note: option -e implies -i");
4251 flags |= FLAG_INTERACTIVE;
4253 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
4254 PrintAndLogEx(WARNING, "Option -e requires -x or -y");
4255 return PM3_EINVARG;
4259 PrintAndLogEx(INFO, _YELLOW_("MIFARE %s") " | %s UID " _YELLOW_("%s") ""
4260 , csize
4261 , uidsize
4262 , (uidlen == 0) ? "n/a" : sprint_hex(uid, uidlen)
4265 PrintAndLogEx(INFO, "Options [ numreads: %d, flags: %d (0x%02x) ]"
4266 , exitAfterNReads
4267 , flags
4268 , flags);
4270 struct {
4271 uint16_t flags;
4272 uint8_t exitAfter;
4273 uint8_t uid[10];
4274 uint16_t atqa;
4275 uint8_t sak;
4276 } PACKED payload;
4278 payload.flags = flags;
4279 payload.exitAfter = exitAfterNReads;
4280 memcpy(payload.uid, uid, uidlen);
4281 payload.atqa = (atqa[1] << 8) | atqa[0];
4282 payload.sak = sak[0];
4284 clearCommandBuffer();
4286 if (flags & FLAG_INTERACTIVE) {
4287 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or a key to abort simulation");
4288 } else {
4289 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
4291 bool cont;
4292 do {
4293 cont = false;
4294 SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
4295 if (flags & FLAG_INTERACTIVE) {
4296 PacketResponseNG resp;
4297 sector_t *k_sector = NULL;
4299 bool keypress = kbd_enter_pressed();
4300 while (keypress == false) {
4302 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
4303 keypress = kbd_enter_pressed();
4304 continue;
4307 if (resp.status != PM3_SUCCESS)
4308 break;
4310 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
4311 break;
4313 const nonces_t *data = (nonces_t *)resp.data.asBytes;
4314 readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
4315 if (setEmulatorMem) {
4316 cont = true;
4318 break;
4320 if (keypress) {
4321 if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
4322 // inform device to break the sim loop since client has exited
4323 PrintAndLogEx(INFO, "Key pressed, please wait a few seconds for the pm3 to stop...");
4324 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
4329 } while (cont);
4330 return PM3_SUCCESS;
4334 static int CmdHF14AMfKeyBrute(const char *Cmd) {
4336 uint8_t blockNo = 0, keytype = MF_KEY_A;
4337 uint8_t key[6] = {0, 0, 0, 0, 0, 0};
4338 uint64_t foundkey = 0;
4340 char cmdp = tolower(param_getchar(Cmd, 0));
4341 if (cmdp == 'h') return usage_hf14_keybrute();
4343 // block number
4344 blockNo = param_get8(Cmd, 0);
4346 // keytype
4347 cmdp = tolower(param_getchar(Cmd, 1));
4348 if (cmdp == 'b') keytype = MF_KEY_B;
4350 // key
4351 int keylen = 0;
4352 if (param_gethex_ex(Cmd, 2, key, &keylen) && (keylen != 12)) {
4353 return usage_hf14_keybrute();
4356 uint64_t t1 = msclock();
4358 if (mfKeyBrute(blockNo, keytype, key, &foundkey))
4359 PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 " \n", foundkey);
4360 else
4361 PrintAndLogEx(FAILED, "key not found");
4363 t1 = msclock() - t1;
4364 PrintAndLogEx(SUCCESS, "\ntime in keybrute " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
4365 return PM3_SUCCESS;
4369 void printKeyTable(size_t sectorscnt, sector_t *e_sector) {
4370 printKeyTableEx(sectorscnt, e_sector, 0);
4373 void printKeyTableEx(size_t sectorscnt, sector_t *e_sector, uint8_t start_sector) {
4374 char strA[26 + 1] = {0};
4375 char strB[26 + 1] = {0};
4376 char resA[20 + 1] = {0};
4377 char resB[20 + 1] = {0};
4379 uint64_t ndef_key = 0xD3F7D3F7D3F7;
4380 bool has_ndef_key = false;
4381 bool extended_legend = false;
4383 PrintAndLogEx(NORMAL, "");
4384 PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
4385 PrintAndLogEx(SUCCESS, " Sec | Blk | key A |res| key B |res");
4386 PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
4388 for (size_t i = 0; i < sectorscnt; i++) {
4390 if ((e_sector[i].foundKey[0] > 1) || (e_sector[i].foundKey[1] > 1)) {
4391 extended_legend = true;
4394 if (e_sector[i].Key[0] == ndef_key || e_sector[i].Key[1] == ndef_key) {
4395 has_ndef_key = true;
4398 if (e_sector[i].foundKey[0]) {
4399 snprintf(strA, sizeof(strA), _GREEN_("%012" PRIX64), e_sector[i].Key[0]);
4400 if (extended_legend) {
4401 snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[0]);
4402 } else {
4403 snprintf(resA, sizeof(resA), _BRIGHT_GREEN_("%d"), e_sector[i].foundKey[0]);
4405 } else {
4406 snprintf(strA, sizeof(strA), _RED_("%s"), "------------");
4407 snprintf(resA, sizeof(resA), _RED_("0"));
4410 if (e_sector[i].foundKey[1]) {
4411 snprintf(strB, sizeof(strB), _GREEN_("%012" PRIX64), e_sector[i].Key[1]);
4412 if (extended_legend) {
4413 snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%c"), e_sector[i].foundKey[1]);
4414 } else {
4415 snprintf(resB, sizeof(resB), _BRIGHT_GREEN_("%d"), e_sector[i].foundKey[1]);
4417 } else {
4418 snprintf(strB, sizeof(strB), _RED_("%s"), "------------");
4419 snprintf(resB, sizeof(resB), _RED_("0"));
4422 // keep track if we use start_sector or i
4423 // show one sector or all.
4424 uint8_t s = start_sector;
4425 if (start_sector == 0) {
4426 s = i;
4429 char extra[24] = {0x00};
4430 if (sectorscnt == 18 && i > 15) {
4431 strcat(extra, "( " _MAGENTA_("*") " )");
4434 PrintAndLogEx(SUCCESS, " " _YELLOW_("%03d") " | %03d | %s | %s | %s | %s %s"
4436 , mfSectorTrailerOfSector(s)
4437 , strA, resA
4438 , strB, resB
4439 , extra
4443 PrintAndLogEx(SUCCESS, "-----+-----+--------------+---+--------------+----");
4445 if (extended_legend) {
4446 PrintAndLogEx(INFO, "( "
4447 _YELLOW_("D") ":Dictionary / "
4448 _YELLOW_("S") ":darkSide / "
4449 _YELLOW_("U") ":User / "
4450 _YELLOW_("R") ":Reused / "
4451 _YELLOW_("N") ":Nested / "
4452 _YELLOW_("H") ":Hardnested / "
4453 _YELLOW_("C") ":statiCnested / "
4454 _YELLOW_("A") ":keyA "
4455 " )"
4457 if (sectorscnt == 18) {
4458 PrintAndLogEx(INFO, "( " _MAGENTA_("*") " ) These sectors used for signature. Lays outside of user memory");
4461 } else {
4462 PrintAndLogEx(SUCCESS, "( " _RED_("0") ":Failed / " _GREEN_("1") ":Success )");
4465 // MAD detection
4466 if (e_sector[MF_MAD1_SECTOR].foundKey[0] && e_sector[MF_MAD1_SECTOR].Key[0] == 0xA0A1A2A3A4A5) {
4467 PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
4469 // NDEF detection
4470 if (has_ndef_key) {
4471 PrintAndLogEx(HINT, "NDEF key detected. Try " _YELLOW_("`hf mf ndefread`") " for more details");
4473 PrintAndLogEx(NORMAL, "");
4477 // EMULATOR COMMANDS
4478 static int CmdHF14AMfEGetBlk(const char *Cmd) {
4479 CLIParserContext *ctx;
4480 CLIParserInit(&ctx, "hf mf egetblk",
4481 "Get emulator memory block",
4482 "hf mf egetblk --blk 0 -> get block 0 (manufacturer)\n"
4483 "hf mf egetblk --blk 3 -v -> get block 3, decode sector trailer\n"
4485 void *argtable[] = {
4486 arg_param_begin,
4487 arg_int1("b", "blk", "<dec>", "block number"),
4488 arg_lit0("v", "verbose", "verbose output"),
4489 arg_param_end
4491 CLIExecWithReturn(ctx, Cmd, argtable, false);
4492 int b = arg_get_int_def(ctx, 1, 0);
4493 bool verbose = arg_get_lit(ctx, 2);
4494 CLIParserFree(ctx);
4496 if (b > 255) {
4497 return PM3_EINVARG;
4499 uint8_t blockno = (uint8_t)b;
4501 uint8_t data[16] = {0x00};
4502 if (mfEmlGetMem(data, blockno, 1) == PM3_SUCCESS) {
4504 uint8_t sector = mfSectorNum(blockno);
4505 mf_print_sector_hdr(sector);
4506 mf_print_block_one(blockno, data, verbose);
4508 if (verbose) {
4509 decode_print_st(blockno, data);
4510 } else {
4511 PrintAndLogEx(NORMAL, "");
4513 return PM3_SUCCESS;
4516 static int CmdHF14AMfEGetSc(const char *Cmd) {
4517 CLIParserContext *ctx;
4518 CLIParserInit(&ctx, "hf mf egetsc",
4519 "Get emulator memory sector",
4520 "hf mf egetsc -s 0"
4522 void *argtable[] = {
4523 arg_param_begin,
4524 arg_int1("s", "sec", "<dec>", "sector number"),
4525 arg_lit0("v", "verbose", "verbose output"),
4526 arg_param_end
4528 CLIExecWithReturn(ctx, Cmd, argtable, false);
4529 int s = arg_get_int_def(ctx, 1, 0);
4530 bool verbose = arg_get_lit(ctx, 2);
4531 CLIParserFree(ctx);
4533 if (s >= MIFARE_4K_MAXSECTOR) {
4534 PrintAndLogEx(WARNING, "Sector number must be less then 40");
4535 return PM3_EINVARG;
4538 uint8_t sector = (uint8_t)s;
4539 mf_print_sector_hdr(sector);
4541 uint8_t blocks = mfNumBlocksPerSector(sector);
4542 uint8_t start = mfFirstBlockOfSector(sector);
4544 uint8_t data[16] = {0};
4545 for (int i = 0; i < blocks; i++) {
4546 int res = mfEmlGetMem(data, start + i, 1);
4547 if (res == PM3_SUCCESS) {
4548 mf_print_block_one(start + i, data, verbose);
4551 if (verbose) {
4552 decode_print_st(start + blocks - 1, data);
4553 } else {
4554 PrintAndLogEx(NORMAL, "");
4556 return PM3_SUCCESS;
4559 static int CmdHF14AMfEClear(const char *Cmd) {
4560 CLIParserContext *ctx;
4561 CLIParserInit(&ctx, "hf mf eclr",
4562 "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF",
4563 "hf mf eclr"
4565 void *argtable[] = {
4566 arg_param_begin,
4567 arg_param_end
4569 CLIExecWithReturn(ctx, Cmd, argtable, true);
4570 CLIParserFree(ctx);
4571 clearCommandBuffer();
4572 SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0);
4573 return PM3_SUCCESS;
4576 static int CmdHF14AMfESet(const char *Cmd) {
4578 CLIParserContext *ctx;
4579 CLIParserInit(&ctx, "hf mf esetblk",
4580 "Set emulator memory block",
4581 "hf mf esetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
4583 void *argtable[] = {
4584 arg_param_begin,
4585 arg_int1("b", "blk", "<dec>", "block number"),
4586 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
4587 arg_param_end
4589 CLIExecWithReturn(ctx, Cmd, argtable, false);
4591 int b = arg_get_int_def(ctx, 1, 0);
4593 uint8_t data[16] = {0x00};
4594 int datalen = 0;
4595 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &datalen);
4596 CLIParserFree(ctx);
4597 if (res) {
4598 PrintAndLogEx(FAILED, "Error parsing bytes");
4599 return PM3_EINVARG;
4602 if (b > 255) {
4603 return PM3_EINVARG;
4606 if (datalen != sizeof(data)) {
4607 PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", datalen);
4608 return PM3_EINVARG;
4611 // 1 - blocks count
4612 return mfEmlSetMem(data, b, 1);
4615 int CmdHF14AMfELoad(const char *Cmd) {
4617 CLIParserContext *ctx;
4618 CLIParserInit(&ctx, "hf mf eload",
4619 "Load emulator memory with data from (bin/eml/json) dump file",
4620 "hf mf eload -f hf-mf-01020304.bin\n"
4621 "hf mf eload --4k -f hf-mf-01020304.eml\n"
4623 void *argtable[] = {
4624 arg_param_begin,
4625 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
4626 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4627 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4628 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4629 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4630 arg_lit0(NULL, "ul", "MIFARE Ultralight family"),
4631 arg_lit0("m", "mem", "use RDV4 spiffs"),
4632 arg_int0("q", "qty", "<dec>", "manually set number of blocks (overrides)"),
4633 arg_lit0("v", "verbose", "verbose output"),
4634 arg_param_end
4636 CLIExecWithReturn(ctx, Cmd, argtable, false);
4638 int fnlen = 0;
4639 char filename[FILE_PATH_SIZE];
4640 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
4642 bool m0 = arg_get_lit(ctx, 2);
4643 bool m1 = arg_get_lit(ctx, 3);
4644 bool m2 = arg_get_lit(ctx, 4);
4645 bool m4 = arg_get_lit(ctx, 5);
4646 bool mu = arg_get_lit(ctx, 6);
4648 bool use_spiffs = arg_get_lit(ctx, 7);
4649 int numblks = arg_get_int_def(ctx, 8, -1);
4650 bool verbose = arg_get_lit(ctx, 9);
4651 CLIParserFree(ctx);
4653 // validations
4654 if ((m0 + m1 + m2 + m4 + mu) > 1) {
4655 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4656 return PM3_EINVARG;
4657 } else if ((m0 + m1 + m2 + m4 + mu) == 0) {
4658 m1 = true;
4661 uint8_t block_width = 16;
4662 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
4663 uint8_t hdr_len = 0;
4665 if (m0) {
4666 block_cnt = MIFARE_MINI_MAXBLOCK;
4667 } else if (m1) {
4668 block_cnt = MIFARE_1K_MAXBLOCK;
4669 } else if (m2) {
4670 block_cnt = MIFARE_2K_MAXBLOCK;
4671 } else if (m4) {
4672 block_cnt = MIFARE_4K_MAXBLOCK;
4673 } else if (mu) {
4674 block_cnt = MFU_MAX_BLOCKS;
4675 block_width = MFU_BLOCK_SIZE;
4676 hdr_len = MFU_DUMP_PREFIX_LENGTH;
4677 } else {
4678 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
4679 return PM3_EINVARG;
4682 PrintAndLogEx(INFO, "Upload " _YELLOW_("%u") " blocks " _YELLOW_("%u") " bytes", block_cnt, block_cnt * block_width);
4684 if (numblks > 0) {
4685 block_cnt = MIN(numblks, block_cnt);
4686 PrintAndLogEx(INFO, "overriding number of blocks, will use " _YELLOW_("%u") " blocks " _YELLOW_("%u") " bytes", block_cnt, block_cnt * block_width);
4689 // ICEMAN: bug. if device has been using ICLASS commands,
4690 // the device needs to load the HF fpga image. It takes 1.5 second.
4691 set_fpga_mode(FPGA_BITSTREAM_HF);
4693 // use RDV4 spiffs
4694 if (use_spiffs && IfPm3Flash() == false) {
4695 PrintAndLogEx(WARNING, "Device not compiled to support spiffs");
4696 return PM3_EINVARG;
4699 if (use_spiffs) {
4701 if (fnlen > 32) {
4702 PrintAndLogEx(WARNING, "filename too long for spiffs, expected 32, got %u", fnlen);
4703 return PM3_EINVARG;
4706 clearCommandBuffer();
4707 SendCommandNG(CMD_SPIFFS_ELOAD, (uint8_t *)filename, fnlen);
4708 PacketResponseNG resp;
4709 if (WaitForResponseTimeout(CMD_SPIFFS_ELOAD, &resp, 2000) == false) {
4710 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
4711 return PM3_ETIMEOUT;
4714 if (resp.status != PM3_SUCCESS) {
4715 PrintAndLogEx(FAILED, "Loading file from spiffs to emulator memory failed");
4716 return PM3_EFLASH;
4719 PrintAndLogEx(SUCCESS, "File transfered from spiffs to device emulator memory");
4720 return PM3_SUCCESS;
4723 uint8_t *data = NULL;
4724 size_t bytes_read = 0;
4725 int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (block_width * block_cnt + hdr_len));
4726 if (res != PM3_SUCCESS) {
4727 return res;
4730 // 64 or 256 blocks.
4731 if ((bytes_read % block_width) != 0) {
4732 PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth ");
4733 free(data);
4734 return PM3_ESOFT;
4737 // convert plain or old mfu format to new format
4738 if (block_width == MFU_BLOCK_SIZE) {
4739 res = convert_mfu_dump_format(&data, &bytes_read, true);
4740 if (res != PM3_SUCCESS) {
4741 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
4742 free(data);
4743 return res;
4746 if (verbose) {
4747 mfu_dump_t *mfu_dump = (mfu_dump_t *)data;
4748 mfu_print_dump(mfu_dump, mfu_dump->pages + 1, 0, false);
4751 // update expected blocks to match converted data.
4752 block_cnt = bytes_read / MFU_BLOCK_SIZE;
4753 PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width);
4756 PrintAndLogEx(INFO, "Uploading to emulator memory");
4757 PrintAndLogEx(INFO, "." NOLF);
4759 // fast push mode
4760 g_conn.block_after_ACK = true;
4762 size_t offset = 0;
4763 int cnt = 0;
4765 // 12 is the size of the struct the fct mfEmlSetMem_xt uses to transfer to device
4766 uint16_t max_avail_blocks = ((PM3_CMD_DATA_SIZE - 12) / block_width) * block_width;
4768 while (bytes_read && cnt < block_cnt) {
4769 if (bytes_read == block_width) {
4770 // Disable fast mode on last packet
4771 g_conn.block_after_ACK = false;
4774 uint16_t chunk_size = MIN(max_avail_blocks, bytes_read);
4775 uint16_t blocks_to_send = chunk_size / block_width;
4777 if (mfEmlSetMem_xt(data + offset, cnt, blocks_to_send, block_width) != PM3_SUCCESS) {
4778 PrintAndLogEx(FAILED, "Can't set emulator mem at block: %3d", cnt);
4779 free(data);
4780 return PM3_ESOFT;
4782 cnt += blocks_to_send;
4783 offset += chunk_size;
4784 bytes_read -= chunk_size;
4785 PrintAndLogEx(NORMAL, "." NOLF);
4786 fflush(stdout);
4788 free(data);
4789 PrintAndLogEx(NORMAL, "");
4791 if (block_width == MFU_BLOCK_SIZE) {
4792 PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim -h`"));
4793 // MFU / NTAG
4794 if ((cnt != block_cnt)) {
4795 PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", cnt, block_cnt);
4796 return PM3_SUCCESS;
4798 } else {
4799 PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim -h`"));
4800 // MFC
4801 if ((cnt != block_cnt)) {
4802 PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", cnt, block_cnt);
4803 return PM3_SUCCESS;
4805 PrintAndLogEx(INFO, "Done!");
4807 return PM3_SUCCESS;
4810 static int CmdHF14AMfESave(const char *Cmd) {
4812 CLIParserContext *ctx;
4813 CLIParserInit(&ctx, "hf mf esave",
4814 "Save emulator memory to file (bin/json) ",
4815 "hf mf esave\n"
4816 "hf mf esave --4k\n"
4817 "hf mf esave --4k -f hf-mf-01020304.eml"
4819 void *argtable[] = {
4820 arg_param_begin,
4821 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
4822 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4823 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4824 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4825 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4826 arg_param_end
4828 CLIExecWithReturn(ctx, Cmd, argtable, true);
4830 int fnlen = 0;
4831 char filename[FILE_PATH_SIZE];
4832 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
4834 bool m0 = arg_get_lit(ctx, 2);
4835 bool m1 = arg_get_lit(ctx, 3);
4836 bool m2 = arg_get_lit(ctx, 4);
4837 bool m4 = arg_get_lit(ctx, 5);
4838 CLIParserFree(ctx);
4840 // validations
4841 if ((m0 + m1 + m2 + m4) > 1) {
4842 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4843 return PM3_EINVARG;
4844 } else if ((m0 + m1 + m2 + m4) == 0) {
4845 m1 = true;
4848 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
4850 if (m0) {
4851 block_cnt = MIFARE_MINI_MAXBLOCK;
4852 } else if (m1) {
4853 block_cnt = MIFARE_1K_MAXBLOCK;
4854 } else if (m2) {
4855 block_cnt = MIFARE_2K_MAXBLOCK;
4856 } else if (m4) {
4857 block_cnt = MIFARE_4K_MAXBLOCK;
4860 int bytes = block_cnt * MFBLOCK_SIZE;
4862 // reserv memory
4863 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
4864 if (dump == NULL) {
4865 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
4866 return PM3_EMALLOC;
4868 memset(dump, 0, bytes);
4870 PrintAndLogEx(INFO, "downloading %u bytes from emulator memory", bytes);
4871 if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
4872 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
4873 free(dump);
4874 return PM3_ETIMEOUT;
4877 // user supplied filename?
4878 if (fnlen < 1) {
4879 char *fptr = filename;
4880 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
4881 FillFileNameByUID(fptr, dump, "-dump", 4);
4884 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
4885 free(dump);
4886 return PM3_SUCCESS;
4889 static int CmdHF14AMfEView(const char *Cmd) {
4891 CLIParserContext *ctx;
4892 CLIParserInit(&ctx, "hf mf eview",
4893 "It displays emulator memory",
4894 "hf mf eview\n"
4895 "hf mf eview --4k"
4897 void *argtable[] = {
4898 arg_param_begin,
4899 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4900 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4901 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4902 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4903 arg_lit0("v", "verbose", "verbose output"),
4904 arg_lit0(NULL, "sk", "Save extracted keys to binary file"),
4905 arg_param_end
4907 CLIExecWithReturn(ctx, Cmd, argtable, true);
4908 bool m0 = arg_get_lit(ctx, 1);
4909 bool m1 = arg_get_lit(ctx, 2);
4910 bool m2 = arg_get_lit(ctx, 3);
4911 bool m4 = arg_get_lit(ctx, 4);
4912 bool verbose = arg_get_lit(ctx, 5);
4913 bool save_keys = arg_get_lit(ctx, 6);
4914 CLIParserFree(ctx);
4916 // validations
4917 if ((m0 + m1 + m2 + m4) > 1) {
4918 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
4919 return PM3_EINVARG;
4920 } else if ((m0 + m1 + m2 + m4) == 0) {
4921 m1 = true;
4924 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
4926 if (m0) {
4927 block_cnt = MIFARE_MINI_MAXBLOCK;
4928 } else if (m1) {
4929 block_cnt = MIFARE_1K_MAXBLOCK;
4930 } else if (m2) {
4931 block_cnt = MIFARE_2K_MAXBLOCK;
4932 } else if (m4) {
4933 block_cnt = MIFARE_4K_MAXBLOCK;
4934 } else {
4935 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
4936 return PM3_EINVARG;
4939 int bytes = block_cnt * MFBLOCK_SIZE;
4941 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
4942 if (dump == NULL) {
4943 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
4944 return PM3_EMALLOC;
4947 PrintAndLogEx(INFO, "downloading emulator memory");
4948 if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
4949 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
4950 free(dump);
4951 return PM3_ETIMEOUT;
4954 mf_print_blocks(block_cnt, dump, verbose);
4956 if (verbose) {
4957 mf_print_keys(block_cnt, dump);
4960 if (save_keys) {
4961 mf_save_keys_from_arr(block_cnt, dump);
4964 free(dump);
4965 return PM3_SUCCESS;
4968 static int CmdHF14AMfECFill(const char *Cmd) {
4970 CLIParserContext *ctx;
4971 CLIParserInit(&ctx, "hf mf ecfill",
4972 "Dump card and transfer the data to emulator memory.\n"
4973 "Keys must be in the emulator memory",
4974 "hf mf ecfill --> use key type A\n"
4975 "hf mf ecfill --4k -b --> target 4K card with key type B"
4977 void *argtable[] = {
4978 arg_param_begin,
4979 arg_lit0("a", NULL, "input key type is key A(def)"),
4980 arg_lit0("b", NULL, "input key type is key B"),
4981 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
4982 arg_str0("k", "key", "<hex>", "key, 6 hex bytes, only for option -c"),
4983 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
4984 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
4985 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
4986 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
4987 arg_param_end
4989 CLIExecWithReturn(ctx, Cmd, argtable, true);
4990 uint8_t keytype = MF_KEY_A;
4991 if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) {
4992 CLIParserFree(ctx);
4993 PrintAndLogEx(WARNING, "Choose one single input key type");
4994 return PM3_EINVARG;
4995 } else if (arg_get_lit(ctx, 2)) {
4996 keytype = MF_KEY_B;
4998 uint8_t prev_keytype = keytype;
4999 keytype = arg_get_int_def(ctx, 3, keytype);
5000 if ((arg_get_lit(ctx, 1) || arg_get_lit(ctx, 2)) && (keytype != prev_keytype)) {
5001 CLIParserFree(ctx);
5002 PrintAndLogEx(WARNING, "Choose one single input key type");
5003 return PM3_EINVARG;
5005 int keylen = 0;
5006 uint8_t key[6] = {0};
5007 CLIGetHexWithReturn(ctx, 4, key, &keylen);
5008 if ((keytype > MF_KEY_B) && (keylen != 6)) {
5009 PrintAndLogEx(WARNING, "Missing key");
5010 return PM3_EINVARG;
5012 if ((keytype <= MF_KEY_B) && (keylen > 0)) {
5013 PrintAndLogEx(WARNING, "Ignoring provided key");
5016 bool m0 = arg_get_lit(ctx, 5);
5017 bool m1 = arg_get_lit(ctx, 6);
5018 bool m2 = arg_get_lit(ctx, 7);
5019 bool m4 = arg_get_lit(ctx, 8);
5020 CLIParserFree(ctx);
5022 // validations
5023 if ((m0 + m1 + m2 + m4) > 1) {
5024 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5025 return PM3_EINVARG;
5026 } else if ((m0 + m1 + m2 + m4) == 0) {
5027 m1 = true;
5030 uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR;
5032 if (m0) {
5033 sectors_cnt = MIFARE_MINI_MAXSECTOR;
5034 } else if (m1) {
5035 sectors_cnt = MIFARE_1K_MAXSECTOR;
5036 } else if (m2) {
5037 sectors_cnt = MIFARE_2K_MAXSECTOR;
5038 } else if (m4) {
5039 sectors_cnt = MIFARE_4K_MAXSECTOR;
5040 } else {
5041 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5042 return PM3_EINVARG;
5045 mfc_eload_t payload = {
5046 .sectorcnt = sectors_cnt,
5047 .keytype = keytype
5049 memcpy(payload.key, key, sizeof(payload.key));
5051 clearCommandBuffer();
5052 SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
5054 PacketResponseNG resp;
5055 if (WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 1500) == false) {
5056 PrintAndLogEx(WARNING, "command execution time out");
5057 return PM3_ETIMEOUT;
5060 if (resp.status == PM3_SUCCESS)
5061 PrintAndLogEx(SUCCESS, "Fill ( " _GREEN_("ok") " )");
5062 else
5063 PrintAndLogEx(FAILED, "Fill ( " _RED_("fail") " )");
5065 return resp.status;
5068 static int CmdHF14AMfEKeyPrn(const char *Cmd) {
5070 CLIParserContext *ctx;
5071 CLIParserInit(&ctx, "hf mf ekeyprn",
5072 "Download and print the keys from emulator memory",
5073 "hf mf ekeyprn --1k --> print MFC 1K keyset\n"
5074 "hf mf ekeyprn -w --> write keys to binary file"
5076 void *argtable[] = {
5077 arg_param_begin,
5078 arg_lit0("w", "write", "write keys to binary file `hf-mf-<UID>-key.bin`"),
5079 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5080 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5081 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5082 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5083 arg_param_end
5085 CLIExecWithReturn(ctx, Cmd, argtable, true);
5087 bool create_dumpfile = arg_get_lit(ctx, 1);
5088 bool m0 = arg_get_lit(ctx, 2);
5089 bool m1 = arg_get_lit(ctx, 3);
5090 bool m2 = arg_get_lit(ctx, 4);
5091 bool m4 = arg_get_lit(ctx, 5);
5092 CLIParserFree(ctx);
5094 // validations
5095 if ((m0 + m1 + m2 + m4) > 1) {
5096 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5097 return PM3_EINVARG;
5098 } else if ((m0 + m1 + m2 + m4) == 0) {
5099 m1 = true;
5102 size_t sectors_cnt = MIFARE_1K_MAXSECTOR;
5104 if (m0) {
5105 sectors_cnt = MIFARE_MINI_MAXSECTOR;
5106 } else if (m1) {
5107 sectors_cnt = MIFARE_1K_MAXSECTOR;
5108 } else if (m2) {
5109 sectors_cnt = MIFARE_2K_MAXSECTOR;
5110 } else if (m4) {
5111 sectors_cnt = MIFARE_4K_MAXSECTOR;
5112 } else {
5113 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5114 return PM3_EINVARG;
5117 // create/initialize key storage structure
5118 sector_t *e_sector = NULL;
5119 if (initSectorTable(&e_sector, sectors_cnt) != PM3_SUCCESS) {
5120 return PM3_EMALLOC;
5123 // read UID from EMUL
5124 uint8_t data[16];
5125 if (mfEmlGetMem(data, 0, 1) != PM3_SUCCESS) {
5126 PrintAndLogEx(WARNING, "error get block 0");
5127 free(e_sector);
5128 return PM3_ESOFT;
5131 // assuming 4byte UID.
5132 uint8_t uid[4];
5133 memcpy(uid, data, sizeof(uid));
5135 // download keys from EMUL
5136 for (int i = 0; i < sectors_cnt; i++) {
5138 if (mfEmlGetMem(data, mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1, 1) != PM3_SUCCESS) {
5139 PrintAndLogEx(WARNING, "error get block %d", mfFirstBlockOfSector(i) + mfNumBlocksPerSector(i) - 1);
5140 e_sector[i].foundKey[0] = false;
5141 e_sector[i].foundKey[1] = false;
5142 } else {
5143 e_sector[i].foundKey[0] = true;
5144 e_sector[i].Key[0] = bytes_to_num(data, 6);
5145 e_sector[i].foundKey[1] = true;
5146 e_sector[i].Key[1] = bytes_to_num(data + 10, 6);
5150 // print keys
5151 printKeyTable(sectors_cnt, e_sector);
5153 // dump the keys
5154 if (create_dumpfile) {
5156 char filename[FILE_PATH_SIZE] = {0};
5157 char *fptr = filename;
5158 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
5159 FillFileNameByUID(fptr + strlen(fptr), uid, "-key", sizeof(uid));
5160 createMfcKeyDump(filename, sectors_cnt, e_sector);
5163 free(e_sector);
5164 return PM3_SUCCESS;
5167 // CHINESE MAGIC COMMANDS
5168 static int CmdHF14AMfCSetUID(const char *Cmd) {
5170 CLIParserContext *ctx;
5171 CLIParserInit(&ctx, "hf mf csetuid",
5172 "Set UID, ATQA, and SAK for magic gen1a card",
5173 "hf mf csetuid -u 01020304\n"
5174 "hf mf csetuid -w -u 01020304 --atqa 0004 --sak 08"
5176 void *argtable[] = {
5177 arg_param_begin,
5178 arg_lit0("w", "wipe", "wipes card with backdoor cmd`"),
5179 arg_str0("u", "uid", "<hex>", "UID, 4/7 hex bytes"),
5180 arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
5181 arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
5182 arg_param_end
5184 CLIExecWithReturn(ctx, Cmd, argtable, true);
5186 uint8_t wipe_card = arg_get_lit(ctx, 1);
5188 int uidlen = 0;
5189 uint8_t uid[7] = {0x00};
5190 CLIGetHexWithReturn(ctx, 2, uid, &uidlen);
5192 int alen = 0;
5193 uint8_t atqa[2] = {0x00};
5194 CLIGetHexWithReturn(ctx, 3, atqa, &alen);
5196 int slen = 0;
5197 uint8_t sak[1] = {0x00};
5198 CLIGetHexWithReturn(ctx, 4, sak, &slen);
5199 CLIParserFree(ctx);
5201 // sanity checks
5202 if (uidlen != 4 && uidlen != 7) {
5203 PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen);
5204 return PM3_EINVARG;
5206 if (alen && alen != 2) {
5207 PrintAndLogEx(FAILED, "ATQA must be 2 hex bytes. Got %d", alen);
5208 return PM3_EINVARG;
5210 if (slen && slen != 1) {
5211 PrintAndLogEx(FAILED, "SAK must be 1 hex byte. Got %d", slen);
5212 return PM3_EINVARG;
5215 uint8_t old_uid[7] = {0};
5216 uint8_t verify_uid[7] = {0};
5218 int res = mfCSetUID(
5219 uid,
5220 uidlen,
5221 (alen) ? atqa : NULL,
5222 (slen) ? sak : NULL,
5223 old_uid,
5224 verify_uid,
5225 wipe_card
5228 if (res) {
5229 PrintAndLogEx(ERR, "Can't set UID. error %d", res);
5230 return PM3_ESOFT;
5233 res = memcmp(uid, verify_uid, uidlen);
5235 PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen));
5236 PrintAndLogEx(SUCCESS, "New UID... %s ( %s )",
5237 sprint_hex(verify_uid, uidlen),
5238 (res == 0) ? _GREEN_("verified") : _RED_("fail")
5240 return PM3_SUCCESS;
5243 static int CmdHF14AMfCWipe(const char *cmd) {
5244 CLIParserContext *ctx;
5245 CLIParserInit(&ctx, "hf mf cwipe",
5246 "Wipe gen1 magic chinese card.\n"
5247 "Set UID / ATQA / SAK / Data / Keys / Access to default values",
5248 "hf mf cwipe\n"
5249 "hf mf cwipe -u 09080706 -a 0004 -s 18 --> set UID, ATQA and SAK and wipe card");
5251 void *argtable[] = {
5252 arg_param_begin,
5253 arg_str0("u", "uid", "<hex>", "UID, 4 hex bytes"),
5254 arg_str0("a", "atqa", "<hex>", "ATQA, 2 hex bytes"),
5255 arg_str0("s", "sak", "<hex>", "SAK, 1 hex byte"),
5256 arg_param_end
5258 CLIExecWithReturn(ctx, cmd, argtable, true);
5260 int uidlen = 0;
5261 uint8_t uid[8] = {0x00};
5262 CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
5264 int alen = 0;
5265 uint8_t atqa[2] = {0x00};
5266 CLIGetHexWithReturn(ctx, 2, atqa, &alen);
5268 int slen = 0;
5269 uint8_t sak[1] = {0x00};
5270 CLIGetHexWithReturn(ctx, 3, sak, &slen);
5271 CLIParserFree(ctx);
5273 if (uidlen && uidlen != 4) {
5274 PrintAndLogEx(ERR, "UID length must be 4 bytes, got %d", uidlen);
5275 return PM3_EINVARG;
5277 if (alen && alen != 2) {
5278 PrintAndLogEx(ERR, "ATQA length must be 2 bytes, got %d", alen);
5279 return PM3_EINVARG;
5281 if (slen && slen != 1) {
5282 PrintAndLogEx(ERR, "SAK length must be 1 byte, got %d", slen);
5283 return PM3_EINVARG;
5286 int res = mfCWipe((uidlen) ? uid : NULL, (alen) ? atqa : NULL, (slen) ? sak : NULL);
5287 if (res) {
5288 PrintAndLogEx(ERR, "Can't wipe card. error %d", res);
5289 return PM3_ESOFT;
5292 PrintAndLogEx(SUCCESS, "Card wiped successfully");
5293 return PM3_SUCCESS;
5296 static int CmdHF14AMfCSetBlk(const char *Cmd) {
5298 CLIParserContext *ctx;
5299 CLIParserInit(&ctx, "hf mf csetblk",
5300 "Set block data on a magic gen1a card",
5301 "hf mf csetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
5303 void *argtable[] = {
5304 arg_param_begin,
5305 arg_int1("b", "blk", "<dec>", "block number"),
5306 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
5307 arg_lit0("w", "wipe", "wipes card with backdoor cmd before writing"),
5308 arg_param_end
5310 CLIExecWithReturn(ctx, Cmd, argtable, false);
5312 int b = arg_get_int_def(ctx, 1, -1);
5314 uint8_t data[MFBLOCK_SIZE] = {0x00};
5315 int datalen = 0;
5316 CLIGetHexWithReturn(ctx, 2, data, &datalen);
5318 uint8_t wipe_card = arg_get_lit(ctx, 3);
5319 CLIParserFree(ctx);
5321 if (b < 0 || b >= MIFARE_1K_MAXBLOCK) {
5322 PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
5323 return PM3_EINVARG;
5326 if (datalen != MFBLOCK_SIZE) {
5327 PrintAndLogEx(FAILED, "expected 16 bytes data, got %i", datalen);
5328 return PM3_EINVARG;
5331 uint8_t params = MAGIC_SINGLE;
5332 if (wipe_card) {
5333 params |= MAGIC_WIPE;
5336 PrintAndLogEx(INFO, "Writing block number:%2d data:%s", b, sprint_hex_inrow(data, sizeof(data)));
5338 int res = mfCSetBlock(b, data, NULL, params);
5339 if (res) {
5340 PrintAndLogEx(ERR, "Can't write block. error=%d", res);
5341 return PM3_ESOFT;
5343 return PM3_SUCCESS;
5346 static int CmdHF14AMfCLoad(const char *Cmd) {
5348 CLIParserContext *ctx;
5349 CLIParserInit(&ctx, "hf mf cload",
5350 "Load magic gen1a card with data from (bin/eml/json) dump file\n"
5351 "or from emulator memory.",
5352 "hf mf cload --emu\n"
5353 "hf mf cload -f hf-mf-01020304.eml\n"
5355 void *argtable[] = {
5356 arg_param_begin,
5357 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5358 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5359 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5360 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5361 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5362 arg_lit0(NULL, "emu", "from emulator memory"),
5363 arg_param_end
5365 CLIExecWithReturn(ctx, Cmd, argtable, false);
5367 int fnlen = 0;
5368 char filename[FILE_PATH_SIZE] = {0};
5369 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5371 bool m0 = arg_get_lit(ctx, 2);
5372 bool m1 = arg_get_lit(ctx, 3);
5373 bool m2 = arg_get_lit(ctx, 4);
5374 bool m4 = arg_get_lit(ctx, 5);
5375 bool fill_from_emulator = arg_get_lit(ctx, 6);
5377 CLIParserFree(ctx);
5379 if ((m0 + m1 + m2 + m4) > 1) {
5380 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5381 return PM3_EINVARG;
5382 } else if ((m0 + m1 + m2 + m4) == 0) {
5383 m1 = true;
5386 char s[6];
5387 memset(s, 0, sizeof(s));
5388 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
5389 if (m0) {
5390 block_cnt = MIFARE_MINI_MAXBLOCK;
5391 strncpy(s, "Mini", 5);
5392 } else if (m1) {
5393 block_cnt = MIFARE_1K_MAXBLOCK;
5394 strncpy(s, "1K", 3);
5395 } else if (m2) {
5396 block_cnt = MIFARE_2K_MAXBLOCK;
5397 strncpy(s, "2K", 3);
5398 } else if (m4) {
5399 block_cnt = MIFARE_4K_MAXBLOCK;
5400 strncpy(s, "4K", 3);
5401 } else {
5402 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5403 return PM3_EINVARG;
5407 if (fill_from_emulator) {
5409 PrintAndLogEx(INFO, "Start upload to emulator memory");
5410 PrintAndLogEx(INFO, "." NOLF);
5412 for (int b = 0; b < block_cnt; b++) {
5413 int flags = 0;
5414 uint8_t buf8[MFBLOCK_SIZE] = {0x00};
5416 // read from emul memory
5417 if (mfEmlGetMem(buf8, b, 1)) {
5418 PrintAndLogEx(WARNING, "Can't read from emul block: %d", b);
5419 return PM3_ESOFT;
5422 // switch on field and send magic sequence
5423 if (b == 0) {
5424 flags = MAGIC_INIT + MAGIC_WUPC;
5427 // just write
5428 if (b == 1) {
5429 flags = 0;
5432 // Done. Magic Halt and switch off field.
5433 if (b == (block_cnt - 1)) {
5434 flags = MAGIC_HALT + MAGIC_OFF;
5437 // write to card
5438 if (mfCSetBlock(b, buf8, NULL, flags)) {
5439 PrintAndLogEx(WARNING, "Can't set magic card block: %d", b);
5440 return PM3_ESOFT;
5442 PrintAndLogEx(NORMAL, "." NOLF);
5443 fflush(stdout);
5445 PrintAndLogEx(NORMAL, "");
5446 return PM3_SUCCESS;
5449 // reserve memory
5450 uint8_t *data = NULL;
5451 size_t bytes_read = 0;
5452 int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * block_cnt));
5453 if (res != PM3_SUCCESS) {
5454 return res;
5457 if (bytes_read != (block_cnt * MFBLOCK_SIZE)) {
5458 PrintAndLogEx(ERR, "File content error. Read %zu bytes", bytes_read);
5459 free(data);
5460 return PM3_EFILE;
5463 PrintAndLogEx(INFO, "Copying to magic gen1a card");
5464 PrintAndLogEx(INFO, "." NOLF);
5466 int blockno = 0;
5467 int flags = 0;
5468 while (bytes_read) {
5470 // switch on field and send magic sequence
5471 if (blockno == 0) {
5472 flags = MAGIC_INIT + MAGIC_WUPC;
5475 // write
5476 if (blockno == 1) {
5477 flags = 0;
5480 // switch off field
5481 if (blockno == (block_cnt - 1)) {
5482 flags = MAGIC_HALT + MAGIC_OFF;
5485 if (mfCSetBlock(blockno, data + (MFBLOCK_SIZE * blockno), NULL, flags)) {
5486 PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockno);
5487 free(data);
5488 return PM3_ESOFT;
5491 bytes_read -= MFBLOCK_SIZE;
5493 PrintAndLogEx(NORMAL, "." NOLF);
5494 fflush(stdout);
5496 blockno++;
5498 if (blockno >= block_cnt) break;
5500 PrintAndLogEx(NORMAL, "\n");
5502 free(data);
5504 // confirm number written blocks. Must be 20, 64 or 256 blocks
5505 if (blockno != block_cnt) {
5506 PrintAndLogEx(ERR, "File content error. There must be %d blocks", block_cnt);
5507 return PM3_EFILE;
5510 PrintAndLogEx(SUCCESS, "Card loaded " _YELLOW_("%d") " blocks from file", block_cnt);
5511 PrintAndLogEx(INFO, "Done!");
5512 return PM3_SUCCESS;
5515 static int CmdHF14AMfCGetBlk(const char *Cmd) {
5516 CLIParserContext *ctx;
5517 CLIParserInit(&ctx, "hf mf cgetblk",
5518 "Get block data from magic Chinese card.\n"
5519 "Only works with magic gen1a cards",
5520 "hf mf cgetblk --blk 0 --> get block 0 (manufacturer)\n"
5521 "hf mf cgetblk --blk 3 -v --> get block 3, decode sector trailer\n"
5523 void *argtable[] = {
5524 arg_param_begin,
5525 arg_int1("b", "blk", "<dec>", "block number"),
5526 arg_lit0("v", "verbose", "verbose output"),
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 CLIParserFree(ctx);
5534 if (b > 255) {
5535 return PM3_EINVARG;
5538 uint8_t blockno = (uint8_t)b;
5539 uint8_t data[16] = {0};
5540 int res = mfCGetBlock(blockno, data, MAGIC_SINGLE);
5541 if (res) {
5542 PrintAndLogEx(ERR, "Can't read block. error=%d", res);
5543 return PM3_ESOFT;
5546 uint8_t sector = mfSectorNum(blockno);
5547 mf_print_sector_hdr(sector);
5548 mf_print_block_one(blockno, data, verbose);
5550 if (verbose) {
5551 decode_print_st(blockno, data);
5552 } else {
5553 PrintAndLogEx(NORMAL, "");
5555 return PM3_SUCCESS;
5558 static int CmdHF14AMfCGetSc(const char *Cmd) {
5559 CLIParserContext *ctx;
5560 CLIParserInit(&ctx, "hf mf cgetsc",
5561 "Get sector data from magic Chinese card.\n"
5562 "Only works with magic gen1a cards",
5563 "hf mf cgetsc -s 0"
5565 void *argtable[] = {
5566 arg_param_begin,
5567 arg_int1("s", "sec", "<dec>", "sector number"),
5568 arg_lit0("v", "verbose", "verbose output"),
5569 arg_param_end
5571 CLIExecWithReturn(ctx, Cmd, argtable, false);
5572 int s = arg_get_int_def(ctx, 1, 0);
5573 bool verbose = arg_get_lit(ctx, 2);
5574 CLIParserFree(ctx);
5576 if (s >= MIFARE_4K_MAXSECTOR) {
5577 PrintAndLogEx(WARNING, "Sector number must be less then 40");
5578 return PM3_EINVARG;
5581 uint8_t sector = (uint8_t)s;
5582 mf_print_sector_hdr(sector);
5584 uint8_t blocks = 4;
5585 uint8_t start = sector * 4;
5586 if (sector >= 32) {
5587 blocks = 16;
5588 start = 128 + (sector - 32) * 16;
5591 int flags = MAGIC_INIT + MAGIC_WUPC;
5592 uint8_t data[16] = {0};
5593 for (int i = 0; i < blocks; i++) {
5594 if (i == 1) flags = 0;
5595 if (i == blocks - 1) flags = MAGIC_HALT + MAGIC_OFF;
5597 int res = mfCGetBlock(start + i, data, flags);
5598 if (res) {
5599 PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res);
5600 return PM3_ESOFT;
5602 mf_print_block_one(start + i, data, verbose);
5604 if (verbose) {
5605 decode_print_st(start + blocks - 1, data);
5606 } else {
5607 PrintAndLogEx(NORMAL, "");
5609 return PM3_SUCCESS;
5612 static int CmdHF14AMfCSave(const char *Cmd) {
5613 CLIParserContext *ctx;
5614 CLIParserInit(&ctx, "hf mf csave",
5615 "Save magic gen1a card memory to file (bin/json)"
5616 "or into emulator memory",
5617 "hf mf csave\n"
5618 "hf mf csave --4k"
5620 void *argtable[] = {
5621 arg_param_begin,
5622 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5623 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5624 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5625 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5626 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5627 arg_lit0(NULL, "emu", "to emulator memory"),
5628 arg_param_end
5630 CLIExecWithReturn(ctx, Cmd, argtable, true);
5632 int fnlen = 0;
5633 char filename[FILE_PATH_SIZE];
5634 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5636 bool m0 = arg_get_lit(ctx, 2);
5637 bool m1 = arg_get_lit(ctx, 3);
5638 bool m2 = arg_get_lit(ctx, 4);
5639 bool m4 = arg_get_lit(ctx, 5);
5640 bool fill_emulator = arg_get_lit(ctx, 6);
5641 CLIParserFree(ctx);
5643 // validations
5644 if ((m0 + m1 + m2 + m4) > 1) {
5645 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5646 return PM3_EINVARG;
5647 } else if ((m0 + m1 + m2 + m4) == 0) {
5648 m1 = true;
5651 char s[6];
5652 memset(s, 0, sizeof(s));
5653 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
5654 if (m0) {
5655 block_cnt = MIFARE_MINI_MAXBLOCK;
5656 strncpy(s, "Mini", 5);
5657 } else if (m1) {
5658 block_cnt = MIFARE_1K_MAXBLOCK;
5659 strncpy(s, "1K", 3);
5660 } else if (m2) {
5661 block_cnt = MIFARE_2K_MAXBLOCK;
5662 strncpy(s, "2K", 3);
5663 } else if (m4) {
5664 block_cnt = MIFARE_4K_MAXBLOCK;
5665 strncpy(s, "4K", 3);
5666 } else {
5667 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5668 return PM3_EINVARG;
5671 PrintAndLogEx(SUCCESS, "Dumping magic Gen1a MIFARE Classic " _GREEN_("%s") " card memory", s);
5672 PrintAndLogEx(INFO, "." NOLF);
5674 // Select card to get UID/UIDLEN information
5675 clearCommandBuffer();
5676 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
5677 PacketResponseNG resp;
5678 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
5679 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
5680 return PM3_ETIMEOUT;
5684 0: couldn't read
5685 1: OK, with ATS
5686 2: OK, no ATS
5687 3: proprietary Anticollision
5689 uint64_t select_status = resp.oldarg[0];
5690 if (select_status == 0) {
5691 PrintAndLogEx(DEBUG, "iso14443a card select failed");
5692 return PM3_SUCCESS;
5695 // store card info
5696 iso14a_card_select_t card;
5697 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
5699 // reserve memory
5700 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
5701 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
5702 if (dump == NULL) {
5703 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
5704 return PM3_EMALLOC;
5707 // switch on field and send magic sequence
5708 uint8_t flags = MAGIC_INIT + MAGIC_WUPC;
5709 for (uint16_t i = 0; i < block_cnt; i++) {
5711 // read
5712 if (i == 1) {
5713 flags = 0;
5715 // switch off field
5716 if (i == block_cnt - 1) {
5717 flags = MAGIC_HALT + MAGIC_OFF;
5720 if (mfCGetBlock(i, dump + (i * MFBLOCK_SIZE), flags)) {
5721 PrintAndLogEx(WARNING, "Can't get magic card block: %d", i);
5722 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
5723 free(dump);
5724 return PM3_ESOFT;
5726 PrintAndLogEx(NORMAL, "." NOLF);
5727 fflush(stdout);
5729 PrintAndLogEx(NORMAL, "");
5731 if (fill_emulator) {
5732 PrintAndLogEx(INFO, "uploading to emulator memory");
5733 PrintAndLogEx(INFO, "." NOLF);
5734 // fast push mode
5735 g_conn.block_after_ACK = true;
5736 for (int i = 0; i < block_cnt; i += 5) {
5737 if (i == block_cnt - 1) {
5738 // Disable fast mode on last packet
5739 g_conn.block_after_ACK = false;
5741 if (mfEmlSetMem(dump + (i * MFBLOCK_SIZE), i, 5) != PM3_SUCCESS) {
5742 PrintAndLogEx(WARNING, "Can't set emul block: " _YELLOW_("%d"), i);
5744 if (i % 64 == 0) {
5745 PrintAndLogEx(NORMAL, "");
5746 PrintAndLogEx(INFO, "" NOLF) ;
5748 PrintAndLogEx(NORMAL, "." NOLF);
5749 fflush(stdout);
5751 PrintAndLogEx(NORMAL, "");
5752 PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", bytes);
5755 // user supplied filename?
5756 if (fnlen < 1) {
5757 char *fptr = filename;
5758 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
5759 FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
5762 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
5763 free(dump);
5764 return PM3_SUCCESS;
5767 static int CmdHF14AMfCView(const char *Cmd) {
5769 CLIParserContext *ctx;
5770 CLIParserInit(&ctx, "hf mf cview",
5771 "View `magic gen1a` card memory",
5772 "hf mf cview\n"
5773 "hf mf cview --4k"
5775 void *argtable[] = {
5776 arg_param_begin,
5777 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
5778 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
5779 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
5780 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
5781 arg_lit0("v", "verbose", "verbose output"),
5782 arg_param_end
5784 CLIExecWithReturn(ctx, Cmd, argtable, true);
5785 bool m0 = arg_get_lit(ctx, 1);
5786 bool m1 = arg_get_lit(ctx, 2);
5787 bool m2 = arg_get_lit(ctx, 3);
5788 bool m4 = arg_get_lit(ctx, 4);
5789 bool verbose = arg_get_lit(ctx, 5);
5790 CLIParserFree(ctx);
5792 // validations
5793 if ((m0 + m1 + m2 + m4) > 1) {
5794 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
5795 return PM3_EINVARG;
5796 } else if ((m0 + m1 + m2 + m4) == 0) {
5797 m1 = true;
5800 char s[6];
5801 memset(s, 0, sizeof(s));
5802 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
5803 if (m0) {
5804 block_cnt = MIFARE_MINI_MAXBLOCK;
5805 strncpy(s, "Mini", 5);
5806 } else if (m1) {
5807 block_cnt = MIFARE_1K_MAXBLOCK;
5808 strncpy(s, "1K", 3);
5809 } else if (m2) {
5810 block_cnt = MIFARE_2K_MAXBLOCK;
5811 strncpy(s, "2K", 3);
5812 } else if (m4) {
5813 block_cnt = MIFARE_4K_MAXBLOCK;
5814 strncpy(s, "4K", 3);
5815 } else {
5816 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
5817 return PM3_EINVARG;
5819 PrintAndLogEx(SUCCESS, "View magic Gen1a MIFARE Classic " _GREEN_("%s"), s);
5820 PrintAndLogEx(INFO, "." NOLF);
5822 // Select card to get UID/UIDLEN information
5823 clearCommandBuffer();
5824 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
5825 PacketResponseNG resp;
5826 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
5827 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
5828 return PM3_ETIMEOUT;
5832 0: couldn't read
5833 1: OK, with ATS
5834 2: OK, no ATS
5835 3: proprietary Anticollision
5837 uint64_t select_status = resp.oldarg[0];
5839 if (select_status == 0) {
5840 PrintAndLogEx(DEBUG, "iso14443a card select failed");
5841 return PM3_ERFTRANS;
5844 iso14a_card_select_t card;
5845 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
5847 // reserve memory
5848 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
5849 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
5850 if (dump == NULL) {
5851 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
5852 return PM3_EMALLOC;
5855 // switch on field and send magic sequence
5856 uint8_t flags = MAGIC_INIT + MAGIC_WUPC;
5857 for (uint16_t i = 0; i < block_cnt; i++) {
5858 // read
5859 if (i == 1) {
5860 flags = 0;
5862 // switch off field
5863 if (i == block_cnt - 1) {
5864 flags = MAGIC_HALT + MAGIC_OFF;
5867 if (mfCGetBlock(i, dump + (i * MFBLOCK_SIZE), flags)) {
5868 PrintAndLogEx(WARNING, "Can't get magic card block: " _YELLOW_("%u"), i);
5869 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
5870 free(dump);
5871 return PM3_ESOFT;
5873 PrintAndLogEx(NORMAL, "." NOLF);
5874 fflush(stdout);
5877 PrintAndLogEx(NORMAL, "");
5878 mf_print_blocks(block_cnt, dump, verbose);
5880 if (verbose) {
5881 mf_print_keys(block_cnt, dump);
5884 free(dump);
5885 return PM3_SUCCESS;
5888 //needs nt, ar, at, Data to decrypt
5889 static int CmdHf14AMfDecryptBytes(const char *Cmd) {
5890 CLIParserContext *ctx;
5891 CLIParserInit(&ctx, "hf mf decrypt",
5892 "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values",
5893 "hf mf decrypt --nt b830049b --ar 9248314a --at 9280e203 -d 41e586f9\n"
5894 " -> 41e586f9 becomes 3003999a\n"
5895 " -> which annotates 30 03 [99 9a] read block 3 [crc]"
5897 void *argtable[] = {
5898 arg_param_begin,
5899 arg_str1(NULL, "nt", "<hex>", "tag nonce"),
5900 arg_str1(NULL, "ar", "<hex>", "ar_enc, encrypted reader response"),
5901 arg_str1(NULL, "at", "<hex>", "at_enc, encrypted tag response"),
5902 arg_str1("d", "data", "<hex>", "encrypted data, taken directly after at_enc and forward"),
5903 arg_param_end
5905 CLIExecWithReturn(ctx, Cmd, argtable, false);
5907 uint32_t nt = 0;
5908 int res = arg_get_u32_hexstr_def(ctx, 1, 0, &nt);
5909 if (res != 1) {
5910 CLIParserFree(ctx);
5911 PrintAndLogEx(WARNING, "check `nt` parameter");
5912 return PM3_EINVARG;
5915 uint32_t ar_enc = 0;
5916 res = arg_get_u32_hexstr_def(ctx, 2, 0, &ar_enc);
5917 if (res != 1) {
5918 CLIParserFree(ctx);
5919 PrintAndLogEx(WARNING, "check `ar` parameter");
5920 return PM3_EINVARG;
5923 uint32_t at_enc = 0;
5924 res = arg_get_u32_hexstr_def(ctx, 3, 0, &at_enc);
5925 if (res != 1) {
5926 CLIParserFree(ctx);
5927 PrintAndLogEx(WARNING, "check `at` parameter");
5928 return PM3_EINVARG;
5931 int datalen = 0;
5932 uint8_t data[512] = {0x00};
5933 CLIGetHexWithReturn(ctx, 4, data, &datalen);
5934 CLIParserFree(ctx);
5936 PrintAndLogEx(INFO, "nt....... %08X", nt);
5937 PrintAndLogEx(INFO, "ar enc... %08X", ar_enc);
5938 PrintAndLogEx(INFO, "at enc... %08X", at_enc);
5940 return tryDecryptWord(nt, ar_enc, at_enc, data, datalen);
5943 static int CmdHf14AMfSetMod(const char *Cmd) {
5945 CLIParserContext *ctx;
5946 CLIParserInit(&ctx, "hf mf setmod",
5947 "Sets the load modulation strength of a MIFARE Classic EV1 card",
5948 "hf mf setmod -k ffffffffffff -0"
5950 void *argtable[] = {
5951 arg_param_begin,
5952 arg_lit0("0", NULL, "normal modulation"),
5953 arg_lit0("1", NULL, "strong modulation (def)"),
5954 arg_str0("k", "key", "<hex>", "key A, Sector 0, 6 hex bytes"),
5955 arg_param_end
5957 CLIExecWithReturn(ctx, Cmd, argtable, true);
5958 bool m0 = arg_get_lit(ctx, 1);
5959 bool m1 = arg_get_lit(ctx, 2);
5961 int keylen = 0;
5962 uint8_t key[6] = {0};
5963 CLIGetHexWithReturn(ctx, 3, key, &keylen);
5964 CLIParserFree(ctx);
5966 if (m0 + m1 > 1) {
5967 PrintAndLogEx(WARNING, "please select one modulation");
5968 return PM3_EINVARG;
5971 uint8_t data[7] = {0};
5972 memcpy(data + 1, key, 6);
5974 if (m1) {
5975 data[0] = 1;
5976 } else {
5977 data[0] = 0;
5980 clearCommandBuffer();
5981 SendCommandNG(CMD_HF_MIFARE_SETMOD, data, sizeof(data));
5982 PacketResponseNG resp;
5983 if (WaitForResponseTimeout(CMD_HF_MIFARE_SETMOD, &resp, 1500) == false) {
5984 PrintAndLogEx(WARNING, "command execution time out");
5985 return PM3_ETIMEOUT;
5988 if (resp.status == PM3_SUCCESS)
5989 PrintAndLogEx(SUCCESS, "Change ( " _GREEN_("ok") " )");
5990 else
5991 PrintAndLogEx(FAILED, "Change ( " _RED_("fail") " )");
5993 return resp.status;
5996 // MIFARE NACK bug detection
5997 static int CmdHf14AMfNack(const char *Cmd) {
5998 CLIParserContext *ctx;
5999 CLIParserInit(&ctx, "hf mf nack",
6000 "Test a MIFARE Classic based card for the NACK bug",
6001 "hf mf nack"
6003 void *argtable[] = {
6004 arg_param_begin,
6005 arg_lit0("v", "verbose", "verbose output`"),
6006 arg_param_end
6008 CLIExecWithReturn(ctx, Cmd, argtable, true);
6009 bool verbose = arg_get_lit(ctx, 1);
6010 CLIParserFree(ctx);
6012 if (verbose)
6013 PrintAndLogEx(INFO, "Started testing card for NACK bug. Press Enter to abort");
6015 detect_classic_nackbug(verbose);
6016 return PM3_SUCCESS;
6020 static int CmdHF14AMfice(const char *Cmd) {
6021 CLIParserContext *ctx;
6022 CLIParserInit(&ctx, "hf mf ice",
6023 "Collect MIFARE Classic nonces to file",
6024 "hf mf ice\n"
6025 "hf mf ice -f nonces.bin");
6027 void *argtable[] = {
6028 arg_param_begin,
6029 arg_str0("f", "file", "<fn>", "filename of nonce dump"),
6030 arg_u64_0(NULL, "limit", "<dec>", "nonces to be collected"),
6031 arg_param_end
6033 CLIExecWithReturn(ctx, Cmd, argtable, true);
6035 int fnlen = 0;
6036 char filename[FILE_PATH_SIZE] = {0};
6037 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6039 uint32_t limit = arg_get_u32_def(ctx, 2, 50000);
6041 CLIParserFree(ctx);
6043 // Validations
6044 char *fptr;
6046 if (filename[0] == '\0') {
6047 fptr = GenerateFilename("hf-mf-", "-nonces.bin");
6048 if (fptr == NULL)
6049 return PM3_EFILE;
6050 strncpy(filename, fptr, sizeof(filename) - 1);
6051 free(fptr);
6054 uint8_t blockNo = 0;
6055 uint8_t keyType = MF_KEY_A;
6056 uint8_t trgBlockNo = 0;
6057 uint8_t trgKeyType = MF_KEY_B;
6058 bool slow = false;
6059 bool initialize = true;
6060 bool acquisition_completed = false;
6061 uint32_t total_num_nonces = 0;
6062 PacketResponseNG resp;
6064 uint32_t part_limit = 3000;
6066 PrintAndLogEx(NORMAL, "Collecting "_YELLOW_("%u")" nonces \n", limit);
6068 FILE *fnonces = NULL;
6069 if ((fnonces = fopen(filename, "wb")) == NULL) {
6070 PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), filename);
6071 return PM3_EFILE;
6074 clearCommandBuffer();
6076 uint64_t t1 = msclock();
6078 do {
6079 if (kbd_enter_pressed()) {
6080 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
6081 break;
6084 uint32_t flags = 0;
6085 flags |= initialize ? 0x0001 : 0;
6086 flags |= slow ? 0x0002 : 0;
6087 clearCommandBuffer();
6088 SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, NULL, 0);
6090 if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out;
6091 if (resp.oldarg[0]) goto out;
6093 uint32_t items = resp.oldarg[2];
6094 fwrite(resp.data.asBytes, 1, items * 4, fnonces);
6095 fflush(fnonces);
6097 total_num_nonces += items;
6098 if (total_num_nonces > part_limit) {
6099 PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces);
6100 part_limit += 3000;
6103 acquisition_completed = (total_num_nonces > limit);
6105 initialize = false;
6107 } while (!acquisition_completed);
6109 out:
6110 PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock() - t1) / 1000);
6112 if (fnonces) {
6113 fflush(fnonces);
6114 fclose(fnonces);
6117 clearCommandBuffer();
6118 SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, NULL, 0);
6119 return PM3_SUCCESS;
6123 static int CmdHF14AMfAuth4(const char *Cmd) {
6124 uint8_t keyn[20] = {0};
6125 int keynlen = 0;
6126 uint8_t key[16] = {0};
6127 int keylen = 0;
6129 CLIParserContext *ctx;
6130 CLIParserInit(&ctx, "hf mf auth4",
6131 "Executes AES authentication command in ISO14443-4",
6132 "hf mf auth4 -n 4000 -k 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
6133 "hf mf auth4 -n 9003 -k FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n");
6135 void *argtable[] = {
6136 arg_param_begin,
6137 arg_str1("n", NULL, "<hex>", "key num, 2 hex bytes"),
6138 arg_str1("k", "key", "<hex>", "key, 16 hex bytes"),
6139 arg_param_end
6141 CLIExecWithReturn(ctx, Cmd, argtable, true);
6142 CLIGetHexWithReturn(ctx, 1, keyn, &keynlen);
6143 CLIGetHexWithReturn(ctx, 2, key, &keylen);
6144 CLIParserFree(ctx);
6146 if (keynlen != 2) {
6147 PrintAndLogEx(ERR, "Key number must be 2 bytes. Got... %d", keynlen);
6148 return PM3_ESOFT;
6151 if (keylen != 16) {
6152 PrintAndLogEx(ERR, "Key must be 16 bytes. Got... %d", keylen);
6153 return PM3_ESOFT;
6156 return MifareAuth4(NULL, keyn, key, true, false, true, true, false);
6159 // https://www.nxp.com/docs/en/application-note/AN10787.pdf
6160 static int CmdHF14AMfMAD(const char *Cmd) {
6162 CLIParserContext *ctx;
6163 CLIParserInit(&ctx, "hf mf mad",
6164 "Checks and prints MIFARE Application Directory (MAD)",
6165 "hf mf mad -> shows MAD if exists\n"
6166 "hf mf mad --aid e103 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"
6167 "hf mf mad --dch -k ffffffffffff -> decode CardHolder information\n");
6169 void *argtable[] = {
6170 arg_param_begin,
6171 arg_lit0("v", "verbose", "verbose output"),
6172 arg_str0(NULL, "aid", "<hex>", "print all sectors with specified aid"),
6173 arg_str0("k", "key", "<hex>", "key for printing sectors"),
6174 arg_lit0("b", "keyb", "use key B for access printing sectors (by default: key A)"),
6175 arg_lit0(NULL, "be", "(optional, BigEndian)"),
6176 arg_lit0(NULL, "dch", "decode Card Holder information"),
6177 arg_str0("f", "file", "<fn>", "load dump file and decode MAD"),
6178 arg_param_end
6180 CLIExecWithReturn(ctx, Cmd, argtable, true);
6181 bool verbose = arg_get_lit(ctx, 1);
6182 uint8_t aid[2] = {0};
6183 int aidlen = 0;
6184 CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
6185 uint8_t userkey[6] = {0};
6186 int keylen = 0;
6187 CLIGetHexWithReturn(ctx, 3, userkey, &keylen);
6188 bool keyB = arg_get_lit(ctx, 4);
6189 bool swapmad = arg_get_lit(ctx, 5);
6190 bool decodeholder = arg_get_lit(ctx, 6);
6192 int fnlen = 0;
6193 char filename[FILE_PATH_SIZE] = {0};
6194 CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6195 CLIParserFree(ctx);
6197 if (fnlen > 0) {
6199 // read dump file
6200 uint8_t *dump = NULL;
6201 size_t bytes_read = 0;
6202 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, MIFARE_4K_MAX_BYTES);
6203 if (res != PM3_SUCCESS) {
6204 return res;
6207 uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE));
6208 if (bytes_read == MIFARE_MINI_MAX_BYTES)
6209 block_cnt = MIFARE_MINI_MAXBLOCK;
6210 else if (bytes_read == MIFARE_2K_MAX_BYTES)
6211 block_cnt = MIFARE_2K_MAXBLOCK;
6212 else if (bytes_read == MIFARE_4K_MAX_BYTES)
6213 block_cnt = MIFARE_4K_MAXBLOCK;
6215 if (verbose) {
6216 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
6219 // MAD detection
6220 if (HasMADKey(dump) == false) {
6221 PrintAndLogEx(FAILED, "No MAD key was detected in the dump file");
6222 free(dump);
6223 return PM3_ESOFT;
6226 MADPrintHeader();
6227 bool haveMAD2 = false;
6228 MAD1DecodeAndPrint(dump, swapmad, verbose, &haveMAD2);
6230 int sector = DetectHID(dump, 0x484d);
6231 if (sector > -1) {
6233 // decode it
6234 PrintAndLogEx(INFO, "");
6235 PrintAndLogEx(INFO, _CYAN_("HID PACS detected"));
6237 uint8_t pacs_sector[MFBLOCK_SIZE * 3] = {0};
6238 memcpy(pacs_sector, dump + (sector * 4 * 16), sizeof(pacs_sector));
6240 if (pacs_sector[16] == 0x02) {
6242 PrintAndLogEx(SUCCESS, "Raw...... " _GREEN_("%s"), sprint_hex_inrow(pacs_sector + 24, 8));
6244 //todo: remove preamble/sentinel
6245 uint32_t top = 0, mid = 0, bot = 0;
6246 char hexstr[16 + 1] = {0};
6247 hex_to_buffer((uint8_t *)hexstr, pacs_sector + 24, 8, sizeof(hexstr) - 1, 0, 0, true);
6248 hexstring_to_u96(&top, &mid, &bot, hexstr);
6250 char binstr[64 + 1];
6251 hextobinstring(binstr, hexstr);
6252 char *pbin = binstr;
6253 while (strlen(pbin) && *(++pbin) == '0');
6255 PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s"), pbin);
6257 PrintAndLogEx(INFO, "Wiegand decode");
6258 wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
6259 HIDTryUnpack(&packed);
6263 sector = DetectHID(dump, 0x4910);
6264 if (sector > -1) {
6265 // decode it
6266 PrintAndLogEx(INFO, "");
6267 PrintAndLogEx(INFO, _CYAN_("VIGIK PACS detected"));
6270 if (haveMAD2) {
6271 MAD2DecodeAndPrint(dump + (MIFARE_1K_MAXBLOCK * MF_MAD2_SECTOR), swapmad, verbose);
6274 if (aidlen == 2 || decodeholder) {
6275 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6276 size_t madlen = 0;
6277 if (MADDecode(dump, dump + (0x10 * MIFARE_1K_MAXBLOCK), mad, &madlen, swapmad)) {
6278 PrintAndLogEx(ERR, "can't decode MAD");
6279 free(dump);
6280 return PM3_ESOFT;
6283 uint16_t aaid = 0x0004;
6284 if (aidlen == 2) {
6285 aaid = (aid[0] << 8) + aid[1];
6288 PrintAndLogEx(NORMAL, "");
6289 PrintAndLogEx(INFO, "-------- " _CYAN_("Card Holder Info 0x%04x") " --------", aaid);
6291 MADCardHolderInfoDecode(dump, bytes_read, verbose);
6293 free(dump);
6294 return PM3_SUCCESS;
6297 if (g_session.pm3_present == false)
6298 return PM3_ENOTTY;
6301 uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
6302 uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
6304 bool got_first = true;
6305 if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0) != PM3_SUCCESS) {
6306 PrintAndLogEx(WARNING, "error, read sector 0. card doesn't have MAD or doesn't have MAD on default keys");
6307 got_first = false;
6308 } else {
6309 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6312 // User supplied key
6313 if (got_first == false && keylen == 6) {
6314 PrintAndLogEx(INFO, "Trying user specified key...");
6315 if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, userkey, sector0) != PM3_SUCCESS) {
6316 PrintAndLogEx(ERR, "error, read sector 0. card doesn't have MAD or the custom key is wrong");
6317 } else {
6318 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6319 got_first = true;
6323 // Both default and user supplied key failed
6324 if (got_first == false) {
6325 return PM3_ESOFT;
6328 got_first = true;
6329 if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10) != PM3_SUCCESS) {
6330 if (verbose) {
6331 PrintAndLogEx(ERR, "error, read sector 0x10. card doesn't have MAD 2 or doesn't have MAD 2 on default keys");
6333 got_first = false;
6334 } else {
6335 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6338 // User supplied key
6339 if (got_first == false && keylen == 6) {
6340 PrintAndLogEx(INFO, "Trying user specified key...");
6341 if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, userkey, sector10) != PM3_SUCCESS) {
6342 if (verbose) {
6343 PrintAndLogEx(ERR, "error, read sector 10. card doesn't have MAD 2 or the custom key is wrong");
6345 } else {
6346 PrintAndLogEx(INFO, "Authentication ( " _GREEN_("ok") " )");
6350 MADPrintHeader();
6352 bool haveMAD2 = false;
6353 MAD1DecodeAndPrint(sector0, swapmad, verbose, &haveMAD2);
6355 if (haveMAD2) {
6356 MAD2DecodeAndPrint(sector10, swapmad, verbose);
6359 if (aidlen == 2 || decodeholder) {
6360 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6361 size_t madlen = 0;
6362 if (MADDecode(sector0, sector10, mad, &madlen, swapmad)) {
6363 PrintAndLogEx(ERR, "can't decode MAD");
6364 return PM3_ESOFT;
6367 // copy default NDEF key
6368 uint8_t akey[6] = {0};
6369 memcpy(akey, g_mifare_ndef_key, 6);
6371 // user specified key
6372 if (keylen == 6) {
6373 memcpy(akey, userkey, sizeof(akey));
6376 uint16_t aaid = 0x0004;
6377 if (aidlen == 2) {
6379 aaid = (aid[0] << 8) + aid[1];
6381 PrintAndLogEx(NORMAL, "");
6382 PrintAndLogEx(INFO, "-------------- " _CYAN_("AID 0x%04x") " ---------------", aaid);
6384 for (int i = 0; i < madlen; i++) {
6385 if (aaid == mad[i]) {
6386 uint8_t vsector[MFBLOCK_SIZE * 4] = {0};
6387 if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
6388 PrintAndLogEx(NORMAL, "");
6389 PrintAndLogEx(ERR, "error, read sector %d", i + 1);
6390 return PM3_ESOFT;
6393 for (int j = 0; j < (verbose ? 4 : 3); j ++)
6394 PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * MFBLOCK_SIZE], MFBLOCK_SIZE));
6399 if (decodeholder) {
6401 PrintAndLogEx(NORMAL, "");
6402 PrintAndLogEx(INFO, "-------- " _CYAN_("Card Holder Info 0x%04x") " --------", aaid);
6404 uint8_t data[MIFARE_4K_MAX_BYTES] = {0};
6405 int datalen = 0;
6407 for (int i = 0; i < madlen; i++) {
6408 if (aaid == mad[i]) {
6410 uint8_t vsector[MFBLOCK_SIZE * 4] = {0};
6411 if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
6412 PrintAndLogEx(NORMAL, "");
6413 PrintAndLogEx(ERR, "error, read sector %d", i + 1);
6414 return PM3_ESOFT;
6417 // skip ST block hence only 3 blocks copy
6418 memcpy(&data[datalen], vsector, MFBLOCK_SIZE * 3);
6419 datalen += MFBLOCK_SIZE * 3;
6423 if (!datalen) {
6424 PrintAndLogEx(WARNING, "no Card Holder Info data");
6425 return PM3_SUCCESS;
6427 MADCardHolderInfoDecode(data, datalen, verbose);
6431 if (verbose) {
6432 PrintAndLogEx(NORMAL, "");
6433 PrintAndLogEx(INFO, "------------ " _CYAN_("MAD v1 sector raw") " -------------");
6434 for (int i = 0; i < 4; i ++) {
6435 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex(&sector0[i * MFBLOCK_SIZE], MFBLOCK_SIZE));
6438 PrintAndLogEx(NORMAL, "");
6439 PrintAndLogEx(INFO, "------------ " _CYAN_("MAD v2 sector raw") " -------------");
6440 for (int i = 0; i < 4; i ++) {
6441 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex(&sector10[i * MFBLOCK_SIZE], MFBLOCK_SIZE));
6445 return PM3_SUCCESS;
6448 int CmdHFMFNDEFRead(const char *Cmd) {
6450 CLIParserContext *ctx;
6451 CLIParserInit(&ctx, "hf mf ndefread",
6452 "Prints NFC Data Exchange Format (NDEF)",
6453 "hf mf ndefread -> shows NDEF parsed data\n"
6454 "hf mf ndefread -vv -> shows NDEF parsed and raw data\n"
6455 "hf mf ndefread --aid e103 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"
6456 "hf mf ndefread -f myfilename -> save raw NDEF to file"
6459 void *argtable[] = {
6460 arg_param_begin,
6461 arg_litn("v", "verbose", 0, 2, "Verbose output"),
6462 arg_str0(NULL, "aid", "<aid>", "replace default aid for NDEF"),
6463 arg_str0("k", "key", "<key>", "replace default key for NDEF"),
6464 arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"),
6465 arg_str0("f", "file", "<fn>", "save raw NDEF to file"),
6466 arg_param_end
6468 CLIExecWithReturn(ctx, Cmd, argtable, true);
6470 bool verbose = arg_get_lit(ctx, 1);
6471 bool verbose2 = arg_get_lit(ctx, 1) > 1;
6472 uint8_t aid[2] = {0};
6474 int aidlen;
6475 CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
6476 uint8_t key[6] = {0};
6478 int keylen;
6479 CLIGetHexWithReturn(ctx, 3, key, &keylen);
6480 bool keyB = arg_get_lit(ctx, 4);
6482 int fnlen = 0;
6483 char filename[FILE_PATH_SIZE] = {0};
6484 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6486 CLIParserFree(ctx);
6488 uint16_t ndef_aid = NDEF_MFC_AID;
6489 if (aidlen == 2) {
6490 ndef_aid = (aid[0] << 8) + aid[1];
6493 uint8_t ndefkey[6] = {0};
6494 memcpy(ndefkey, g_mifare_ndef_key, 6);
6495 if (keylen == 6) {
6496 memcpy(ndefkey, key, 6);
6499 uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
6500 uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
6501 uint8_t data[4096] = {0};
6502 int datalen = 0;
6504 if (verbose) {
6505 PrintAndLogEx(INFO, "reading MAD v1 sector");
6508 if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, g_mifare_mad_key, sector0)) {
6509 PrintAndLogEx(ERR, "error, read sector 0. card doesn't have MAD or doesn't have MAD on default keys");
6510 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -k `") " with your custom key");
6511 return PM3_ESOFT;
6514 if (verbose) {
6515 PrintAndLogEx(INFO, "reading MAD v2 sector");
6518 if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, g_mifare_mad_key, sector10)) {
6519 if (verbose) {
6520 PrintAndLogEx(ERR, "error, read sector 0x10. card doesn't have MAD 2 or doesn't have MAD 2 on default keys");
6521 PrintAndLogEx(INFO, "Skipping MAD 2");
6525 bool haveMAD2 = false;
6526 int res = MADCheck(sector0, sector10, verbose, &haveMAD2);
6527 if (res != PM3_SUCCESS) {
6528 PrintAndLogEx(ERR, "MAD error %d", res);
6529 return res;
6532 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6533 size_t madlen = 0;
6534 res = MADDecode(sector0, sector10, mad, &madlen, false);
6535 if (res != PM3_SUCCESS) {
6536 PrintAndLogEx(ERR, "can't decode MAD");
6537 return res;
6540 PrintAndLogEx(INFO, "reading data from tag");
6541 for (int i = 0; i < madlen; i++) {
6542 if (ndef_aid == mad[i]) {
6543 uint8_t vsector[MFBLOCK_SIZE * 4] = {0};
6544 if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) {
6545 PrintAndLogEx(ERR, "error, reading sector %d ", i + 1);
6546 return PM3_ESOFT;
6549 memcpy(&data[datalen], vsector, MFBLOCK_SIZE * 3);
6550 datalen += MFBLOCK_SIZE * 3;
6552 PrintAndLogEx(INPLACE, "%d", i);
6555 PrintAndLogEx(NORMAL, "");
6557 if (datalen == 0) {
6558 PrintAndLogEx(WARNING, "no NDEF data");
6559 return PM3_SUCCESS;
6562 if (verbose2) {
6563 PrintAndLogEx(NORMAL, "");
6564 PrintAndLogEx(INFO, "--- " _CYAN_("MFC NDEF raw") " ----------------");
6565 print_buffer(data, datalen, 1);
6568 res = NDEFDecodeAndPrint(data, datalen, verbose);
6569 if (res != PM3_SUCCESS) {
6570 PrintAndLogEx(INFO, "Trying to parse NDEF records w/o NDEF header");
6571 res = NDEFRecordsDecodeAndPrint(data, datalen, verbose);
6574 // if given a filename, save it
6575 if (fnlen) {
6576 // get total NDEF length before save. If fails, we save it all
6577 size_t n = 0;
6578 if (NDEFGetTotalLength(data, datalen, &n) != PM3_SUCCESS) {
6579 n = datalen;
6582 pm3_save_dump(filename, data, n, jsfNDEF);
6585 if (verbose == false) {
6586 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -v`") " for more details");
6587 } else {
6588 if (verbose2 == false) {
6589 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -vv`") " for more details");
6592 return PM3_SUCCESS;
6595 // https://www.nxp.com/docs/en/application-note/AN1305.pdf
6596 int CmdHFMFNDEFFormat(const char *Cmd) {
6598 CLIParserContext *ctx;
6599 CLIParserInit(&ctx, "hf mf ndefformat",
6600 "format MIFARE Classic Tag as a NFC tag with Data Exchange Format (NDEF)\n"
6601 "If no <name> given, UID will be used as filename. \n"
6602 "It will try default keys and MAD keys to detect if tag is already formatted in order to write.\n"
6603 "\n"
6604 "If not, it will try finding a key file based on your UID. ie, if you ran autopwn before",
6605 "hf mf ndefformat\n"
6606 // "hf mf ndefformat --mini --> MIFARE Mini\n"
6607 "hf mf ndefformat --1k --> MIFARE Classic 1k\n"
6608 // "hf mf ndefformat --2k --> MIFARE 2k\n"
6609 // "hf mf ndefformat --4k --> MIFARE 4k\n"
6610 "hf mf ndefformat --keys hf-mf-01020304-key.bin --> MIFARE 1k with keys from specified file\n"
6613 void *argtable[] = {
6614 arg_param_begin,
6615 arg_str0("k", "keys", "<fn>", "filename of keys"),
6616 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
6617 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
6618 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
6619 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
6620 arg_param_end
6622 CLIExecWithReturn(ctx, Cmd, argtable, true);
6624 int keyfnlen = 0;
6625 char keyFilename[FILE_PATH_SIZE] = {0};
6626 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
6628 bool m0 = arg_get_lit(ctx, 2);
6629 bool m1 = arg_get_lit(ctx, 3);
6630 bool m2 = arg_get_lit(ctx, 4);
6631 bool m4 = arg_get_lit(ctx, 5);
6633 CLIParserFree(ctx);
6635 // validations
6636 if ((m0 + m1 + m2 + m4) > 1) {
6637 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
6638 return PM3_EINVARG;
6639 } else if ((m0 + m1 + m2 + m4) == 0) {
6640 m1 = true;
6643 uint8_t numSectors = MIFARE_1K_MAXSECTOR;
6645 if (m0) {
6646 numSectors = MIFARE_MINI_MAXSECTOR;
6647 } else if (m1) {
6648 numSectors = MIFARE_1K_MAXSECTOR;
6649 } else if (m2) {
6650 numSectors = MIFARE_2K_MAXSECTOR;
6651 } else if (m4) {
6652 numSectors = MIFARE_4K_MAXSECTOR;
6653 } else {
6654 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
6655 return PM3_EINVARG;
6659 if (g_session.pm3_present == false)
6660 return PM3_ENOTTY;
6662 // Select card to get UID/UIDLEN/ATQA/SAK information
6663 clearCommandBuffer();
6664 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
6665 PacketResponseNG resp;
6666 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
6667 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
6668 return PM3_ETIMEOUT;
6671 uint64_t select_status = resp.oldarg[0];
6672 if (select_status == 0) {
6673 PrintAndLogEx(DEBUG, "iso14443a card select failed");
6674 return PM3_SUCCESS;
6677 DropField();
6680 // init keys to default key
6681 uint8_t keyA[MIFARE_4K_MAXSECTOR][MIFARE_KEY_SIZE];
6682 uint8_t keyB[MIFARE_4K_MAXSECTOR][MIFARE_KEY_SIZE];
6684 for (uint8_t i = 0; i < MIFARE_4K_MAXSECTOR; i++) {
6685 memcpy(keyA[i], g_mifare_default_key, sizeof(g_mifare_default_key));
6686 memcpy(keyB[i], g_mifare_default_key, sizeof(g_mifare_default_key));
6689 // test if MAD key is used
6690 uint64_t key64 = 0;
6692 // check if we can authenticate to sector
6693 if (mfCheckKeys(0, MF_KEY_A, true, 1, (uint8_t *)g_mifare_mad_key, &key64) == PM3_SUCCESS) {
6695 // if used, assume KEY A is MAD/NDEF set.
6696 memcpy(keyA[0], g_mifare_mad_key, sizeof(g_mifare_mad_key));
6697 memcpy(keyB[0], g_mifare_mad_key_b, sizeof(g_mifare_mad_key_b));
6698 for (uint8_t i = 1; i < MIFARE_4K_MAXSECTOR; i++) {
6699 memcpy(keyA[i], g_mifare_ndef_key, sizeof(g_mifare_ndef_key));
6703 // Do we have a keyfile based from UID?
6704 if (keyfnlen == 0) {
6705 char *fptr = GenerateFilename("hf-mf-", "-key.bin");
6706 if (fptr) {
6707 strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
6709 free(fptr);
6710 DropField();
6713 // load key file if exist
6714 if (strlen(keyFilename)) {
6716 size_t alen = 0, blen = 0;
6717 uint8_t *tmpA, *tmpB;
6718 if (loadFileBinaryKey(keyFilename, "", (void **)&tmpA, (void **)&tmpB, &alen, &blen) != PM3_SUCCESS) {
6719 goto skipfile;
6722 PrintAndLogEx(INFO, "Using `" _YELLOW_("%s") "`", keyFilename);
6724 for (int i = 0; i < numSectors; i++) {
6725 memcpy(keyA[i], tmpA + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
6726 memcpy(keyB[i], tmpB + (i * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
6728 free(tmpA);
6729 free(tmpB);
6732 skipfile:
6735 uint8_t firstblocks[8][16] = {
6736 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6737 { 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 },
6738 { 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1 },
6739 { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A },
6740 { 0x03, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6741 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6742 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
6743 { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
6746 // main loop
6747 for (int i = 0; i < numSectors; i++) {
6748 for (int j = 0; j < mfNumBlocksPerSector(j); j++) {
6750 uint8_t b = (mfFirstBlockOfSector(i) + j);
6751 uint8_t block[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
6753 switch (b) {
6754 case 0:
6755 continue;
6756 case 1:
6757 case 2:
6758 case 3:
6759 case 4:
6760 case 5:
6761 case 6:
6762 case 7:
6763 memcpy(block, firstblocks[b], MFBLOCK_SIZE);
6764 break;
6765 default: {
6766 if (mfIsSectorTrailerBasedOnBlocks(i, j)) {
6767 // ST NDEF
6768 memcpy(block, firstblocks[7], MFBLOCK_SIZE);
6770 break;
6774 // write to card, try B key first
6775 if (mf_write_block(keyB[i], MF_KEY_B, b, block) == 0) {
6776 // try A key,
6777 if (mf_write_block(keyA[i], MF_KEY_A, b, block) == 0) {
6778 return PM3_EFAILED;
6781 PrintAndLogEx(INPLACE, "Formatting block %u", b);
6785 PrintAndLogEx(NORMAL, "");
6786 return PM3_SUCCESS;
6789 int CmdHFMFNDEFWrite(const char *Cmd) {
6791 CLIParserContext *ctx;
6792 CLIParserInit(&ctx, "hf mf ndefwrite",
6793 "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n",
6794 "hf mf ndefwrite -d 0300FE -> write empty record to tag\n"
6795 "hf mf ndefwrite -f myfilename\n"
6796 "hf mf ndefwrite -d 033fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\n"
6799 void *argtable[] = {
6800 arg_param_begin,
6801 arg_str0("d", NULL, "<hex>", "raw NDEF hex bytes"),
6802 arg_str0("f", "file", "<fn>", "write raw NDEF file to tag"),
6803 arg_lit0("p", NULL, "fix NDEF record headers / terminator block if missing"),
6804 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
6805 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
6806 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
6807 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
6808 arg_lit0("v", "verbose", "verbose output"),
6809 arg_param_end
6811 CLIExecWithReturn(ctx, Cmd, argtable, false);
6813 uint8_t raw[4096] = {0};
6814 int rawlen;
6815 CLIGetHexWithReturn(ctx, 1, raw, &rawlen);
6817 int fnlen = 0;
6818 char filename[FILE_PATH_SIZE] = {0};
6819 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
6821 bool fix_msg = arg_get_lit(ctx, 3);
6823 bool m0 = arg_get_lit(ctx, 4);
6824 bool m1 = arg_get_lit(ctx, 5);
6825 bool m2 = arg_get_lit(ctx, 6);
6826 bool m4 = arg_get_lit(ctx, 7);
6827 bool verbose = arg_get_lit(ctx, 8);
6829 CLIParserFree(ctx);
6831 // validations
6832 if ((m0 + m1 + m2 + m4) > 1) {
6833 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
6834 return PM3_EINVARG;
6835 } else if ((m0 + m1 + m2 + m4) == 0) {
6836 m1 = true;
6839 uint8_t numSectors = MIFARE_1K_MAXSECTOR;
6841 if (m0) {
6842 numSectors = MIFARE_MINI_MAXSECTOR;
6843 } else if (m1) {
6844 numSectors = MIFARE_1K_MAXSECTOR;
6845 } else if (m2) {
6846 numSectors = MIFARE_2K_MAXSECTOR;
6847 } else if (m4) {
6848 numSectors = MIFARE_4K_MAXSECTOR;
6849 } else {
6850 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
6851 return PM3_EINVARG;
6854 if (verbose) {
6855 PrintAndLogEx(INFO, "Number of sectors selected: %u", numSectors);
6858 if (g_session.pm3_present == false) {
6859 PrintAndLogEx(FAILED, "No Proxmark3 device present");
6860 return PM3_ENOTTY;
6863 if ((rawlen && fnlen) || (rawlen == 0 && fnlen == 0)) {
6864 PrintAndLogEx(WARNING, "Please specify either raw hex or filename");
6865 return PM3_EINVARG;
6868 // test if MAD key is used
6869 uint64_t key64 = 0;
6871 // check if we can authenticate to sector
6872 int res = mfCheckKeys(0, MF_KEY_A, true, 1, (uint8_t *)g_mifare_mad_key, &key64);
6873 if (res != PM3_SUCCESS) {
6874 PrintAndLogEx(FAILED, "Sector 0 failed to authenticate with MAD default key");
6875 PrintAndLogEx(HINT, "Verify that the tag NDEF formatted");
6876 return res;
6879 // NDEF for MIFARE CLASSIC has different memory size available.
6881 int32_t bytes = rawlen;
6883 // read dump file
6884 if (fnlen) {
6885 uint8_t *dump = NULL;
6886 size_t bytes_read = 0;
6887 res = pm3_load_dump(filename, (void **)&dump, &bytes_read, sizeof(raw));
6888 if (res != PM3_SUCCESS) {
6889 return res;
6891 memcpy(raw, dump, bytes_read);
6892 bytes = bytes_read;
6893 free(dump);
6896 // Has raw bytes ndef message header?bytes
6897 switch (raw[0]) {
6898 case 0x00:
6899 case 0x01:
6900 case 0x02:
6901 case 0x03:
6902 case 0xFD:
6903 case 0xFE:
6904 break;
6905 default: {
6906 if (fix_msg == false) {
6907 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a proper header, continuing...");
6908 } else {
6909 if (bytes + 2 > sizeof(raw)) {
6910 PrintAndLogEx(WARNING, "no room for header, exiting...");
6911 return PM3_EMALLOC;
6913 uint8_t tmp_raw[4096];
6914 memcpy(tmp_raw, raw, sizeof(tmp_raw));
6915 raw[0] = 0x03;
6916 raw[1] = bytes;
6917 memcpy(raw + 2, tmp_raw, sizeof(raw) - 2);
6918 bytes += 2;
6919 PrintAndLogEx(SUCCESS, "Added generic message header (0x03)");
6924 // Has raw bytes ndef a terminator block?
6925 if (raw[bytes - 1] != 0xFE) {
6926 if (fix_msg == false) {
6927 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a terminator block, continuing...");
6928 } else {
6930 if (bytes + 1 > sizeof(raw)) {
6931 PrintAndLogEx(WARNING, "no room for terminator block, exiting...");
6932 return PM3_EMALLOC;
6934 raw[bytes] = 0xFE;
6935 bytes++;
6936 PrintAndLogEx(SUCCESS, "Added terminator block (0xFE)");
6940 if (verbose) {
6941 PrintAndLogEx(INFO, "Num of Bytes... %u", bytes);
6942 print_buffer(raw, bytes, 0);
6945 // read MAD Sector 0, block1,2
6946 uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
6947 if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, g_mifare_mad_key, sector0)) {
6948 PrintAndLogEx(ERR, "error, reading sector 0. Card doesn't have MAD or doesn't have MAD on default keys");
6949 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mf ndefread -k `") " with your custom key");
6950 return PM3_ESOFT;
6953 // read MAD Sector 10, block1,2
6954 uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
6955 if (m4) {
6956 if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, g_mifare_mad_key, sector10)) {
6957 PrintAndLogEx(ERR, "error, reading sector 10. 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;
6963 // decode MAD v1
6964 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
6965 size_t madlen = 0;
6966 res = MADDecode(sector0, sector10, mad, &madlen, false);
6967 if (res != PM3_SUCCESS) {
6968 PrintAndLogEx(ERR, "can't decode MAD");
6969 return res;
6972 // how much memory do I have available ?
6973 // Skip sector 0 since its used for MAD
6974 uint8_t freemem[MIFARE_4K_MAXSECTOR] = {0};
6975 uint16_t sum = 0;
6976 uint8_t block_no = 0;
6977 for (uint8_t i = 1; i < (madlen & 0xFF); i++) {
6979 freemem[i] = (mad[i] == NDEF_MFC_AID);
6981 if (freemem[i]) {
6983 if (block_no == 0) {
6984 block_no = mfFirstBlockOfSector(i);
6987 if (verbose) {
6988 PrintAndLogEx(INFO, "Sector %u is NDEF formatted", i);
6990 sum += (MFBLOCK_SIZE * 3);
6994 if (verbose) {
6995 PrintAndLogEx(INFO, "Total avail ndef mem... %u", sum);
6996 PrintAndLogEx(INFO, "First block............ %u", block_no);
6999 if (sum < bytes) {
7000 PrintAndLogEx(WARNING, "Raw NDEF message is larger than available NDEF formatted memory");
7001 return PM3_EINVARG;
7004 // main loop - write blocks
7005 uint8_t *ptr_raw = raw;
7006 while (bytes > 0) {
7008 uint8_t block[MFBLOCK_SIZE] = { 0x00 };
7010 if (bytes < MFBLOCK_SIZE) {
7011 memcpy(block, ptr_raw, bytes);
7012 } else {
7013 memcpy(block, ptr_raw, MFBLOCK_SIZE);
7014 ptr_raw += MFBLOCK_SIZE;
7017 // write to card, try B key first
7018 if (mf_write_block(g_mifare_default_key, MF_KEY_B, block_no, block) == 0) {
7020 // try A key,
7021 if (mf_write_block(g_mifare_ndef_key, MF_KEY_A, block_no, block) == 0) {
7022 return PM3_EFAILED;
7026 PrintAndLogEx(INPLACE, "%u", block_no);
7028 // find next available block
7029 block_no++;
7031 if (mfIsSectorTrailer(block_no)) {
7032 block_no++;
7033 // skip sectors which isn't ndef formatted
7034 while (freemem[mfSectorNum(block_no)] == 0) {
7035 block_no++;
7039 bytes -= MFBLOCK_SIZE;
7042 PrintAndLogEx(NORMAL, "");
7043 return PM3_SUCCESS;
7046 static int CmdHFMFPersonalize(const char *Cmd) {
7047 CLIParserContext *ctx;
7048 CLIParserInit(&ctx, "hf mf personalize",
7049 "Personalize the UID of a MIFARE Classic EV1 card. This is only possible \n"
7050 "if it is a 7Byte UID card and if it is not already personalized.",
7051 "hf mf personalize --f0 -> double size UID\n"
7052 "hf mf personalize --f1 -> double size UID, optional usage of selection process shortcut\n"
7053 "hf mf personalize --f2 -> single size random ID\n"
7054 "hf mf personalize --f3 -> single size NUID\n"
7055 "hf mf personalize -b -k B0B1B2B3B4B5 --f3 -> use key B = 0xB0B1B2B3B4B5"
7058 void *argtable[] = {
7059 arg_param_begin,
7060 arg_lit0("a", NULL, "use key A to authenticate sector 0 (def)"),
7061 arg_lit0("b", NULL, "use key B to authenticate sector 0"),
7062 arg_str0("k", "key", "<hex>", "key (def FFFFFFFFFFFF)"),
7063 arg_lit0(NULL, "f0", "UIDFO, double size UID"),
7064 arg_lit0(NULL, "f1", "UIDF1, double size UID, optional usage of selection process shortcut"),
7065 arg_lit0(NULL, "f2", "UIDF2, single size random ID"),
7066 arg_lit0(NULL, "f3", "UIDF3, single size NUID"),
7067 arg_param_end
7069 CLIExecWithReturn(ctx, Cmd, argtable, true);
7071 bool use_a = arg_get_lit(ctx, 1);
7072 bool use_b = arg_get_lit(ctx, 2);
7074 if (use_a + use_b > 1) {
7075 PrintAndLogEx(ERR, "error, use only one key type");
7076 CLIParserFree(ctx);
7077 return PM3_EINVARG;
7080 uint8_t keytype = 0;
7081 if (use_b) {
7082 keytype = 1;
7085 uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
7086 int key_len;
7087 int res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 6, &key_len);
7088 if (res || (!res && key_len && key_len != 6)) {
7089 PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits");
7090 CLIParserFree(ctx);
7091 return PM3_EINVARG;
7094 bool f0 = arg_get_lit(ctx, 4);
7095 bool f1 = arg_get_lit(ctx, 5);
7096 bool f2 = arg_get_lit(ctx, 6);
7097 bool f3 = arg_get_lit(ctx, 7);
7098 CLIParserFree(ctx);
7100 uint8_t tmp = f0 + f1 + f2 + f3;
7101 if (tmp > 1) {
7102 PrintAndLogEx(WARNING, "select only one key type");
7103 return PM3_EINVARG;
7105 if (tmp == 0) {
7106 PrintAndLogEx(WARNING, "select one key type");
7107 return PM3_EINVARG;
7110 uint8_t pers_option = MIFARE_EV1_UIDF3;
7111 if (f0) {
7112 pers_option = MIFARE_EV1_UIDF0;
7113 } else if (f1) {
7114 pers_option = MIFARE_EV1_UIDF1;
7115 } else if (f2) {
7116 pers_option = MIFARE_EV1_UIDF2;
7119 CLIParserFree(ctx);
7121 struct {
7122 uint8_t keytype;
7123 uint8_t pers_option;
7124 uint8_t key[6];
7125 } PACKED payload;
7126 payload.keytype = keytype;
7127 payload.pers_option = pers_option;
7128 memcpy(payload.key, key, sizeof(payload.key));
7130 clearCommandBuffer();
7131 SendCommandNG(CMD_HF_MIFARE_PERSONALIZE_UID, (uint8_t *)&payload, sizeof(payload));
7132 PacketResponseNG resp;
7133 if (WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500) == false) {
7134 return PM3_ETIMEOUT;
7137 if (resp.status == PM3_SUCCESS) {
7138 PrintAndLogEx(SUCCESS, "Personalization ( %s )", _GREEN_("ok"));
7139 } else {
7140 PrintAndLogEx(FAILED, "Personalization ( %s )", _RED_("fail"));
7142 return PM3_SUCCESS;
7145 static int CmdHF14AMfList(const char *Cmd) {
7146 return CmdTraceListAlias(Cmd, "hf mf", "mf -c");
7149 static int CmdHf14AGen3UID(const char *Cmd) {
7150 CLIParserContext *ctx;
7151 CLIParserInit(&ctx, "hf mf gen3uid",
7152 "Set UID for magic Gen3 card _without_ changes to manufacturer block 0",
7153 "hf mf gen3uid --uid 01020304 --> set 4 byte uid\n"
7154 "hf mf gen3uid --uid 01020304050607 --> set 7 byte uid"
7156 void *argtable[] = {
7157 arg_param_begin,
7158 arg_str0("u", "uid", "<hex>", "UID 4/7 hex bytes"),
7159 arg_param_end
7161 CLIExecWithReturn(ctx, Cmd, argtable, true);
7163 uint8_t uid[7] = {0};
7164 int uidlen = 0;
7165 CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
7166 CLIParserFree(ctx);
7168 // sanity checks
7169 if (uidlen != 4 && uidlen != 7) {
7170 PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen);
7171 return PM3_EINVARG;
7174 uint8_t old_uid[10] = {0};
7176 int res = mfGen3UID(uid, uidlen, old_uid);
7177 if (res != PM3_SUCCESS) {
7178 PrintAndLogEx(ERR, "Can't set UID");
7179 PrintAndLogEx(HINT, "Are you sure your card is a Gen3 ?");
7180 return PM3_ESOFT;
7183 PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen));
7184 PrintAndLogEx(SUCCESS, "New UID... %s", sprint_hex(uid, uidlen));
7185 return PM3_SUCCESS;
7188 static int CmdHf14AGen3Block(const char *Cmd) {
7189 CLIParserContext *ctx;
7190 CLIParserInit(&ctx, "hf mf gen3blk",
7191 "Overwrite full manufacturer block for magic Gen3 card\n"
7192 " - You can specify part of manufacturer block as\n"
7193 " 4/7-bytes for UID change only\n"
7194 "\n"
7195 "NOTE: BCC, SAK, ATQA will be calculated automatically"
7197 "hf mf gen3blk --> print current data\n"
7198 "hf mf gen3blk -d 01020304 --> set 4 byte uid\n"
7199 "hf mf gen3blk -d 01020304050607 --> set 7 byte uid \n"
7200 "hf mf gen3blk -d 01020304FFFFFFFF0102030405060708"
7203 void *argtable[] = {
7204 arg_param_begin,
7205 arg_str0("d", "data", "<hex>", "manufacturer block data up to 16 hex bytes"),
7206 arg_param_end
7208 CLIExecWithReturn(ctx, Cmd, argtable, true);
7210 uint8_t data[MFBLOCK_SIZE] = {0x00};
7211 int datalen = 0;
7212 CLIGetHexWithReturn(ctx, 1, data, &datalen);
7213 CLIParserFree(ctx);
7215 uint8_t new_block[MFBLOCK_SIZE] = {0x00};
7216 int res = mfGen3Block(data, datalen, new_block);
7217 if (res) {
7218 PrintAndLogEx(ERR, "Can't change manufacturer block data. error %d", res);
7219 return PM3_ESOFT;
7222 PrintAndLogEx(SUCCESS, "Current block... %s", sprint_hex_inrow(new_block, sizeof(new_block)));
7223 return PM3_SUCCESS;
7226 static int CmdHf14AGen3Freeze(const char *Cmd) {
7227 CLIParserContext *ctx;
7228 CLIParserInit(&ctx, "hf mf gen3freeze",
7229 "Perma lock further UID changes. No more UID changes available after operation completed\n"
7230 "\nNote: operation is " _RED_("! irreversible !"),
7232 "hf mf gen3freeze -y"
7234 void *argtable[] = {
7235 arg_param_begin,
7236 arg_lit1("y", "yes", "confirm UID lock operation"),
7237 arg_param_end
7239 CLIExecWithReturn(ctx, Cmd, argtable, false);
7240 bool confirm = arg_get_lit(ctx, 1);
7241 CLIParserFree(ctx);
7242 if (confirm == false) {
7243 PrintAndLogEx(INFO, "please confirm that you want to perma lock the card");
7244 return PM3_SUCCESS;
7247 int res = mfGen3Freeze();
7248 if (res != PM3_SUCCESS) {
7249 PrintAndLogEx(ERR, "Can't lock UID changes. error %d", res);
7250 } else {
7251 PrintAndLogEx(SUCCESS, "MFC Gen3 UID card is now perma-locked");
7253 return res;
7256 #define FURUI_MAX_TRACES 8
7257 static int mfc_furui_recovery(uint8_t items, uint8_t tracedata[FURUI_MAX_TRACES][18]) {
7258 // recover key from collected traces
7259 // outer loop
7260 for (uint8_t i = 0; i < items; i++) {
7262 // first
7263 nonces_t data;
7264 data.cuid = bytes_to_num(tracedata[i], 4);
7265 data.nonce = bytes_to_num(tracedata[i] + 6, 4);
7266 data.nr = bytes_to_num(tracedata[i] + 10, 4);
7267 data.ar = bytes_to_num(tracedata[i] + 14, 4);
7268 data.at = 0;
7270 // inner loop
7271 for (uint8_t j = i + 1; j < items; j++) {
7273 uint8_t *p = tracedata[j];
7274 PrintAndLogEx(INFO, "%u... %s", i, sprint_hex_inrow(p, 18));
7276 // since data stored as block number but its the same key for all blocks in one sector
7277 // we compare with sector number here
7278 uint8_t s = mfSectorNum(tracedata[i][4]);
7279 if (mfSectorNum(p[4]) == s) {
7281 data.nonce2 = bytes_to_num(p + 6, 4);
7282 data.nr2 = bytes_to_num(p + 10, 4);
7283 data.ar2 = bytes_to_num(p + 14, 4);
7284 data.sector = s;
7285 data.keytype = tracedata[i][5];
7286 data.state = FIRST;
7288 uint64_t key64 = -1;
7289 if (mfkey32_moebius(&data, &key64)) {
7290 PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ "_GREEN_("%012" PRIX64) " ]",
7291 sprint_hex_inrow(tracedata[i], 4),
7292 data.sector,
7293 (data.keytype == 0x60) ? 'A' : 'B',
7294 key64
7296 break;
7301 return PM3_SUCCESS;
7304 static int mfc_supercard_gen2_recovery(uint8_t items, uint8_t tracedata[FURUI_MAX_TRACES][18]) {
7305 for (uint8_t i = 0; i < items; i++) {
7306 uint8_t *tmp = tracedata[i];
7308 // first
7309 uint16_t NT0 = (tmp[6] << 8) | tmp[7];
7311 nonces_t data;
7312 data.cuid = bytes_to_num(tmp, 4);
7313 data.nonce = prng_successor(NT0, 31);
7314 data.nr = bytes_to_num(tmp + 8, 4);
7315 data.ar = bytes_to_num(tmp + 12, 4);
7316 data.at = 0;
7318 // second
7319 for (uint8_t j = i + 1; j < items; j++) {
7320 uint8_t *p = tracedata[j];
7322 // since data stored as block number but its the same key for all blocks in one sector
7323 // we compare with sector number here
7324 uint8_t s = mfSectorNum(tmp[5]);
7325 if (mfSectorNum(p[5]) == s) {
7327 NT0 = (p[6] << 8) | p[7];
7329 data.nonce2 = prng_successor(NT0, 31);
7330 data.nr2 = bytes_to_num(p + 8, 4);
7331 data.ar2 = bytes_to_num(p + 12, 4);
7332 data.sector = s;
7333 data.keytype = tmp[4];
7334 data.state = FIRST;
7336 uint64_t key64 = -1;
7337 if (mfkey32_moebius(&data, &key64)) {
7338 PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ "_GREEN_("%012" PRIX64) " ]",
7339 sprint_hex_inrow(tmp, 4),
7340 data.sector,
7341 (data.keytype == 0x60) ? 'A' : 'B',
7342 key64
7344 break;
7349 return PM3_SUCCESS;
7352 static int CmdHf14AMfSuperCard(const char *Cmd) {
7353 CLIParserContext *ctx;
7354 CLIParserInit(&ctx, "hf mf supercard",
7355 "Extract info from a `super card`",
7356 "hf mf supercard -> recover key\n"
7357 "hf mf supercard -r -> reset card\n"
7358 "hf mf supercard -u 11223344 -> change UID\n");
7360 void *argtable[] = {
7361 arg_param_begin,
7362 arg_lit0("r", "reset", "Reset card"),
7363 arg_str0("u", "uid", "<hex>", "New UID (4 hex bytes)"),
7364 arg_lit0(NULL, "furui", "Furui detection card"),
7365 arg_param_end
7367 CLIExecWithReturn(ctx, Cmd, argtable, true);
7368 bool reset_card = arg_get_lit(ctx, 1);
7369 uint8_t uid[4];
7370 int uidlen = 0;
7371 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), uid, sizeof(uid), &uidlen);
7372 bool is_furui = arg_get_lit(ctx, 3);
7374 CLIParserFree(ctx);
7376 // sanity checks
7377 if (res || (!res && uidlen && uidlen != sizeof(uid))) {
7378 PrintAndLogEx(ERR, "UID must include 4 hex bytes");
7379 return PM3_EINVARG;
7382 uint8_t tracedata[FURUI_MAX_TRACES][18];
7384 // Super card FURUI
7385 if (is_furui) {
7387 // no reset on super card FURUI
7388 if (uidlen || reset_card) {
7389 PrintAndLogEx(FAILED, "Not supported on this card");
7390 return PM3_SUCCESS;
7393 // read 8 traces
7394 uint8_t i;
7395 for (i = 0; i < FURUI_MAX_TRACES; i++) {
7397 uint8_t data[] = {0xAA, 0xA8, 0x00, i};
7398 uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
7399 clearCommandBuffer();
7400 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(data), 0, data, sizeof(data));
7401 if (WaitForResponseTimeout(CMD_ACK, NULL, 1500) == false) {
7402 break;
7405 PacketResponseNG resp;
7406 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
7407 break;
7410 uint16_t len = resp.oldarg[0] & 0xFFFF;
7411 if (len != 20) {
7412 break; // Not trace data
7415 PrintAndLogEx(DEBUG, ">>> %s", sprint_hex_inrow(resp.data.asBytes, len));
7416 memcpy(&tracedata[i], resp.data.asBytes, len - 2);
7419 return mfc_furui_recovery(i, tracedata);
7422 #define SUPER_MAX_TRACES 7
7424 // read 7 traces from super card generation 1,2
7425 uint8_t i = 0;
7426 for (i = 0; i < SUPER_MAX_TRACES; i++) {
7428 uint8_t data[] = {0x30, i};
7429 uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
7430 clearCommandBuffer();
7431 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(data), 0, data, sizeof(data));
7432 if (WaitForResponseTimeout(CMD_ACK, NULL, 1500) == false) {
7433 break;
7436 PacketResponseNG resp;
7437 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
7438 break;
7441 uint16_t len = resp.oldarg[0] & 0xFFFF;
7442 if (len != 18) {
7443 break; // Not trace data
7446 PrintAndLogEx(DEBUG, ">>> %s", sprint_hex_inrow(resp.data.asBytes, len));
7447 memcpy(&tracedata[i], resp.data.asBytes, len - 2);
7450 // Super card generation 2
7451 if (i == SUPER_MAX_TRACES) {
7453 // no reset on super card generation 2.
7454 if (uidlen || reset_card) {
7455 PrintAndLogEx(FAILED, "Not supported on this card");
7456 return PM3_SUCCESS;
7459 // recover key from collected traces
7460 return mfc_supercard_gen2_recovery(i, tracedata);
7463 // Super card generation 1
7465 // Commands:
7466 // a0 - set UID
7467 // b0 - read traces
7468 // c0 - clear card
7469 bool activate_field = true;
7470 bool keep_field_on = true;
7472 // change UID on a super card generation 1
7473 if (uidlen) {
7474 keep_field_on = false;
7475 uint8_t response[6];
7476 int resplen = 0;
7478 // --------------- CHANGE UID ----------------
7479 uint8_t aCHANGE[] = {0x00, 0xa6, 0xa0, 0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0x00};
7480 memcpy(aCHANGE + 5, uid, uidlen);
7481 res = ExchangeAPDU14a(
7482 aCHANGE, sizeof(aCHANGE),
7483 activate_field,
7484 keep_field_on,
7485 response, sizeof(response),
7486 &resplen
7489 if (res != PM3_SUCCESS) {
7490 PrintAndLogEx(FAILED, "Super card UID change [ " _RED_("fail") " ]");
7491 DropField();
7492 return res;
7495 PrintAndLogEx(SUCCESS, "Super card UID change ( " _GREEN_("ok") " )");
7496 return PM3_SUCCESS;
7499 // reset a super card generation 1
7500 if (reset_card) {
7501 keep_field_on = false;
7502 uint8_t response[6];
7503 int resplen = 0;
7505 // --------------- RESET CARD ----------------
7506 uint8_t aRESET[] = {0x00, 0xa6, 0xc0, 0x00};
7507 res = ExchangeAPDU14a(
7508 aRESET, sizeof(aRESET),
7509 activate_field,
7510 keep_field_on,
7511 response, sizeof(response),
7512 &resplen
7515 if (res != PM3_SUCCESS) {
7516 PrintAndLogEx(FAILED, "Super card reset [ " _RED_("fail") " ]");
7517 DropField();
7518 return res;
7520 PrintAndLogEx(SUCCESS, "Super card reset ( " _GREEN_("ok") " )");
7521 return PM3_SUCCESS;
7524 uint8_t responseA[22];
7525 uint8_t responseB[22];
7526 int respAlen = 0;
7527 int respBlen = 0;
7529 // --------------- First ----------------
7530 uint8_t aFIRST[] = {0x00, 0xa6, 0xb0, 0x00, 0x10};
7531 res = ExchangeAPDU14a(aFIRST, sizeof(aFIRST), activate_field, keep_field_on, responseA, sizeof(responseA), &respAlen);
7532 if (res != PM3_SUCCESS) {
7533 DropField();
7534 return res;
7537 // --------------- Second ----------------
7538 activate_field = false;
7539 keep_field_on = false;
7541 uint8_t aSECOND[] = {0x00, 0xa6, 0xb0, 0x01, 0x10};
7542 res = ExchangeAPDU14a(aSECOND, sizeof(aSECOND), activate_field, keep_field_on, responseB, sizeof(responseB), &respBlen);
7543 if (res != PM3_SUCCESS) {
7544 DropField();
7545 return res;
7548 uint8_t outA[16] = {0};
7549 uint8_t outB[16] = {0};
7551 uint8_t key[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
7552 for (i = 0; i < 16; i += 8) {
7553 des_decrypt(outA + i, responseA + i, key);
7554 des_decrypt(outB + i, responseB + i, key);
7557 PrintAndLogEx(DEBUG, " in : %s", sprint_hex_inrow(responseA, respAlen));
7558 PrintAndLogEx(DEBUG, "out : %s", sprint_hex_inrow(outA, sizeof(outA)));
7559 PrintAndLogEx(DEBUG, " in : %s", sprint_hex_inrow(responseB, respAlen));
7560 PrintAndLogEx(DEBUG, "out : %s", sprint_hex_inrow(outB, sizeof(outB)));
7562 if (memcmp(outA, "\x01\x01\x01\x01\x01\x01\x01\x01", 8) == 0) {
7563 PrintAndLogEx(INFO, "No trace recorded");
7564 return PM3_SUCCESS;
7567 // second trace?
7568 if (memcmp(outB, "\x01\x01\x01\x01\x01\x01\x01\x01", 8) == 0) {
7569 PrintAndLogEx(INFO, "Only one trace recorded");
7570 return PM3_SUCCESS;
7573 nonces_t data;
7575 // first
7576 uint16_t NT0 = (outA[6] << 8) | outA[7];
7577 data.cuid = bytes_to_num(outA, 4);
7578 data.nonce = prng_successor(NT0, 31);
7579 data.nr = bytes_to_num(outA + 8, 4);
7580 data.ar = bytes_to_num(outA + 12, 4);
7581 data.at = 0;
7583 // second
7584 NT0 = (outB[6] << 8) | outB[7];
7585 data.nonce2 = prng_successor(NT0, 31);
7586 data.nr2 = bytes_to_num(outB + 8, 4);
7587 data.ar2 = bytes_to_num(outB + 12, 4);
7588 data.sector = mfSectorNum(outA[5]);
7589 data.keytype = outA[4];
7590 data.state = FIRST;
7592 PrintAndLogEx(DEBUG, "A Sector %02x", data.sector);
7593 PrintAndLogEx(DEBUG, "A NT %08x", data.nonce);
7594 PrintAndLogEx(DEBUG, "A NR %08x", data.nr);
7595 PrintAndLogEx(DEBUG, "A AR %08x", data.ar);
7596 PrintAndLogEx(DEBUG, "");
7597 PrintAndLogEx(DEBUG, "B NT %08x", data.nonce2);
7598 PrintAndLogEx(DEBUG, "B NR %08x", data.nr2);
7599 PrintAndLogEx(DEBUG, "B AR %08x", data.ar2);
7601 uint64_t key64 = -1;
7602 if (mfkey32_moebius(&data, &key64)) {
7603 PrintAndLogEx(SUCCESS, "UID: %s Sector %02x key %c [ " _GREEN_("%012" PRIX64) " ]",
7604 sprint_hex_inrow(outA, 4),
7605 data.sector,
7606 (data.keytype == 0x60) ? 'A' : 'B',
7607 key64
7609 } else {
7610 PrintAndLogEx(FAILED, "failed to recover any key");
7612 return PM3_SUCCESS;
7615 static int CmdHF14AMfWipe(const char *Cmd) {
7616 CLIParserContext *ctx;
7617 CLIParserInit(&ctx, "hf mf wipe",
7618 "Wipe card to zeros and default keys/acc. This command takes a key file to wipe card\n"
7619 "Will use UID from card to generate keyfile name if not specified.\n"
7620 "New A/B keys..... FF FF FF FF FF FF\n"
7621 "New acc rights... FF 07 80\n"
7622 "New GPB.......... 69",
7623 "hf mf wipe --> reads card uid to generate file name\n"
7624 "hf mf wipe --gen2 --> force write to S0, B0 manufacture block\n"
7625 "hf mf wipe -f mykey.bin --> use mykey.bin\n"
7627 void *argtable[] = {
7628 arg_param_begin,
7629 arg_str0("f", "file", "<fn>", "key filename"),
7630 arg_lit0(NULL, "gen2", "force write to Sector 0, block 0 (GEN2)"),
7631 arg_param_end
7633 CLIExecWithReturn(ctx, Cmd, argtable, true);
7635 int keyfnlen = 0;
7636 char keyFilename[FILE_PATH_SIZE] = {0};
7637 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen);
7639 bool gen2 = arg_get_lit(ctx, 2);
7640 CLIParserFree(ctx);
7642 char *fptr;
7643 if (keyfnlen == 0) {
7644 fptr = GenerateFilename("hf-mf-", "-key.bin");
7645 if (fptr == NULL) {
7646 return PM3_ESOFT;
7648 strncpy(keyFilename, fptr, sizeof(keyFilename) - 1);
7649 free(fptr);
7652 uint8_t *keys;
7653 size_t keyslen = 0;
7654 if (loadFile_safeEx(keyFilename, ".bin", (void **)&keys, (size_t *)&keyslen, false) != PM3_SUCCESS) {
7655 PrintAndLogEx(FAILED, "failed to load key file");
7656 return PM3_ESOFT;
7659 uint8_t keyA[MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE];
7660 uint8_t keyB[MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE];
7661 uint8_t num_sectors = 0;
7663 uint8_t mf[MFBLOCK_SIZE];
7664 switch (keyslen) {
7665 case (MIFARE_MINI_MAX_KEY_SIZE): {
7666 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic Mini 320b");
7667 memcpy(keyA, keys, (MIFARE_MINI_MAXSECTOR * MIFARE_KEY_SIZE));
7668 memcpy(keyB, keys + (MIFARE_MINI_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_MINI_MAXSECTOR * MIFARE_KEY_SIZE));
7669 num_sectors = NumOfSectors('0');
7670 memcpy(mf, "\x11\x22\x33\x44\x44\x09\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7671 break;
7673 case (MIFARE_1K_EV1_MAX_KEY_SIZE): {
7674 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 1K Ev1");
7675 memcpy(keyA, keys, (MIFARE_1K_EV1_MAXSECTOR * MIFARE_KEY_SIZE));
7676 memcpy(keyB, keys + (MIFARE_1K_EV1_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_1K_EV1_MAXSECTOR * MIFARE_KEY_SIZE));
7677 num_sectors = NumOfSectors('1');
7678 memcpy(mf, "\x11\x22\x33\x44\x44\x08\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7679 break;
7681 case (MIFARE_1K_MAX_KEY_SIZE): {
7682 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 1K");
7683 memcpy(keyA, keys, (MIFARE_1K_MAXSECTOR * MIFARE_KEY_SIZE));
7684 memcpy(keyB, keys + (MIFARE_1K_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_1K_MAXSECTOR * MIFARE_KEY_SIZE));
7685 num_sectors = NumOfSectors('1');
7687 memcpy(mf, "\x11\x22\x33\x44\x44\x08\x04\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7688 break;
7690 case (MIFARE_4K_MAX_KEY_SIZE): {
7691 PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 4K");
7692 memcpy(keyA, keys, (MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE));
7693 memcpy(keyB, keys + (MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE), (MIFARE_4K_MAXSECTOR * MIFARE_KEY_SIZE));
7694 num_sectors = NumOfSectors('4');
7695 memcpy(mf, "\x11\x22\x33\x44\x44\x18\x02\x00\x62\x63\x64\x65\x66\x67\x68\x69", MFBLOCK_SIZE);
7696 break;
7698 default: {
7699 PrintAndLogEx(INFO, "wrong key file size. got %zu", keyslen);
7700 goto out;
7704 if (gen2)
7705 PrintAndLogEx(INFO, "Forcing overwrite of sector 0 / block 0 ");
7706 else
7707 PrintAndLogEx(INFO, "Skipping sector 0 / block 0");
7709 PrintAndLogEx(NORMAL, "");
7711 uint8_t zeros[MFBLOCK_SIZE] = {0};
7712 memset(zeros, 0x00, sizeof(zeros));
7713 uint8_t st[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
7715 PrintAndLogEx(INFO, " blk | ");
7716 PrintAndLogEx(INFO, "-----+------------------------------------------------------------");
7717 // time to wipe card
7718 for (uint8_t s = 0; s < num_sectors; s++) {
7720 for (uint8_t b = 0; b < mfNumBlocksPerSector(s); b++) {
7722 if (kbd_enter_pressed()) {
7723 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
7724 goto out;
7727 // Skip write to manufacture block if not enforced
7728 if (s == 0 && b == 0 && gen2 == false) {
7729 continue;
7732 uint8_t data[26];
7733 memset(data, 0, sizeof(data));
7734 if (mfIsSectorTrailerBasedOnBlocks(s, b)) {
7735 memcpy(data + 10, st, sizeof(st));
7736 } else {
7737 memcpy(data + 10, zeros, sizeof(zeros));
7740 // add correct manufacture block if UID Gen2
7741 if (s == 0 && b == 0 && gen2) {
7742 memcpy(data + 10, mf, sizeof(mf));
7745 // try both A/B keys, start with B key first
7746 for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
7748 if (kt == MF_KEY_A)
7749 memcpy(data, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
7750 else
7751 memcpy(data, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
7753 PrintAndLogEx(INFO, " %3d | %s" NOLF, mfFirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE));
7754 clearCommandBuffer();
7755 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, mfFirstBlockOfSector(s) + b, kt, 0, data, sizeof(data));
7756 PacketResponseNG resp;
7757 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
7758 int8_t isOK = resp.oldarg[0];
7759 if (isOK == 1) {
7760 PrintAndLogEx(NORMAL, "- key %c ( " _GREEN_("ok") " )", (kt == MF_KEY_A) ? 'A' : 'B');
7761 break;
7762 } else {
7763 PrintAndLogEx(NORMAL, "- key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B');
7765 } else {
7766 PrintAndLogEx(WARNING, "command execution time out");
7772 PrintAndLogEx(INFO, "-----+------------------------------------------------------------");
7773 PrintAndLogEx(NORMAL, "");
7774 PrintAndLogEx(INFO, "Done!");
7775 out:
7776 free(keys);
7777 return PM3_SUCCESS;
7780 static int CmdHF14AMfView(const char *Cmd) {
7782 CLIParserContext *ctx;
7783 CLIParserInit(&ctx, "hf mf view",
7784 "Print a MIFARE Classic dump file (bin/eml/json)",
7785 "hf mf view -f hf-mf-01020304-dump.bin"
7787 void *argtable[] = {
7788 arg_param_begin,
7789 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
7790 arg_lit0("v", "verbose", "verbose output"),
7791 arg_lit0(NULL, "sk", "Save extracted keys to binary file"),
7792 arg_param_end
7794 CLIExecWithReturn(ctx, Cmd, argtable, false);
7795 int fnlen = 0;
7796 char filename[FILE_PATH_SIZE];
7797 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
7798 bool verbose = arg_get_lit(ctx, 2);
7799 bool save_keys = arg_get_lit(ctx, 3);
7800 CLIParserFree(ctx);
7802 // read dump file
7803 uint8_t *dump = NULL;
7804 size_t bytes_read = 0;
7805 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, MIFARE_4K_MAX_BYTES);
7806 if (res != PM3_SUCCESS) {
7807 return res;
7810 uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE));
7811 if (bytes_read == MIFARE_MINI_MAX_BYTES)
7812 block_cnt = MIFARE_MINI_MAXBLOCK;
7813 else if (bytes_read == MIFARE_2K_MAX_BYTES)
7814 block_cnt = MIFARE_2K_MAXBLOCK;
7815 else if (bytes_read == MIFARE_4K_MAX_BYTES)
7816 block_cnt = MIFARE_4K_MAXBLOCK;
7818 if (verbose) {
7819 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
7822 mf_print_blocks(block_cnt, dump, verbose);
7824 if (verbose) {
7825 mf_print_keys(block_cnt, dump);
7826 mf_analyse_acl(block_cnt, dump);
7829 if (save_keys) {
7830 mf_save_keys_from_arr(block_cnt, dump);
7833 int sector = DetectHID(dump, 0x4910);
7834 if (sector > -1) {
7835 // decode it
7836 PrintAndLogEx(INFO, "");
7837 PrintAndLogEx(INFO, _CYAN_("VIGIK PACS detected"));
7839 // decode MAD v1
7840 uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
7841 size_t madlen = 0;
7842 res = MADDecode(dump, NULL, mad, &madlen, false);
7843 if (res != PM3_SUCCESS) {
7844 PrintAndLogEx(ERR, "can't decode MAD");
7845 return res;
7848 typedef union UDATA {
7849 uint8_t *bytes;
7850 mfc_vigik_t *vigik;
7851 } UDATA;
7852 // allocate memory
7853 UDATA d;
7854 d.bytes = calloc(bytes_read, sizeof(uint8_t));
7855 if (d.bytes == NULL) {
7856 return PM3_EMALLOC;
7858 uint16_t dlen = 0;
7860 // vigik struture sector 0
7861 uint8_t *pdump = dump;
7863 memcpy(d.bytes + dlen, pdump, MFBLOCK_SIZE * 3);
7864 dlen += MFBLOCK_SIZE * 3;
7865 pdump += (MFBLOCK_SIZE * 4); // skip sectortrailer
7867 // extract memory from MAD sectors
7868 for (int i = 0; i <= madlen; i++) {
7869 if (0x4910 == mad[i] || 0x4916 == mad[i]) {
7870 memcpy(d.bytes + dlen, pdump, MFBLOCK_SIZE * 3);
7871 dlen += MFBLOCK_SIZE * 3;
7874 pdump += (MFBLOCK_SIZE * 4); // skip sectortrailer
7877 // convert_mfc_2_arr(pdump, bytes_read, d, &dlen);
7878 vigik_annotate(d.vigik);
7879 free(d.bytes);
7882 free(dump);
7883 return PM3_SUCCESS;
7886 static int parse_gtu_cfg(uint8_t *d, size_t n) {
7888 PrintAndLogEx(NORMAL, "");
7889 PrintAndLogEx(INFO, "---------- " _CYAN_("GTU Gen4 Configuration") " -------------------------------------");
7890 if (n != 30 && n != 32) {
7891 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d, n));
7892 PrintAndLogEx(INFO, "%zu bytes", n);
7893 PrintAndLogEx(WARNING, "Unknown config format");
7894 return PM3_SUCCESS;
7897 PrintAndLogEx(INFO, _YELLOW_("%s"), sprint_hex_inrow(d, n));
7898 PrintAndLogEx(INFO, "%zu bytes", n);
7899 PrintAndLogEx(INFO, "");
7900 PrintAndLogEx(INFO, _CYAN_("Config 1 - UID & modes"));
7901 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d, 8));
7902 PrintAndLogEx(INFO, "%02X.............. " NOLF, d[0]);
7903 bool is_ul_enabled = (d[0] == 1);
7904 switch (d[0]) {
7905 case 0x00:
7906 PrintAndLogEx(NORMAL, "MIFARE Classic mode");
7907 break;
7908 case 0x01:
7909 PrintAndLogEx(NORMAL, "MIFARE Ultralight/NTAG mode");
7910 break;
7911 default:
7912 PrintAndLogEx(NORMAL, _RED_("unknown"));
7913 break;
7916 PrintAndLogEx(INFO, "..%02X............ UID " NOLF, d[1]);
7918 switch (d[1]) {
7919 case 0x00:
7920 PrintAndLogEx(NORMAL, _GREEN_("4") " byte");
7921 break;
7922 case 0x01:
7923 PrintAndLogEx(NORMAL, _GREEN_("7") " byte");
7924 break;
7925 case 0x02:
7926 PrintAndLogEx(NORMAL, _GREEN_("10") " byte");
7927 break;
7928 default:
7929 PrintAndLogEx(NORMAL, _RED_("unknown"));
7930 break;
7933 PrintAndLogEx(INFO, "...." _YELLOW_("%s") ".... " _YELLOW_("Password"), sprint_hex_inrow(&d[2], 4));
7934 PrintAndLogEx(INFO, "............%02X.. GTU mode " NOLF, d[6]);
7935 switch (d[6]) {
7936 case 0x00:
7937 PrintAndLogEx(NORMAL, _GREEN_("pre-write") " - shadow data can be written");
7938 break;
7939 case 0x01:
7940 PrintAndLogEx(NORMAL, _GREEN_("restore mode"));
7941 break;
7942 case 0x02:
7943 PrintAndLogEx(NORMAL, "disabled");
7944 break;
7945 case 0x03:
7946 PrintAndLogEx(NORMAL, "disabled, high speed R/W mode for Ultralight ?");
7947 break;
7948 default:
7949 PrintAndLogEx(NORMAL, _RED_("unknown"));
7950 break;
7953 uint8_t atslen = d[7];
7954 if (atslen == 0) {
7955 PrintAndLogEx(INFO, ".............. ATS length %u bytes ( %s )", atslen, _YELLOW_("zero"));
7956 } else if (atslen <= 16) {
7957 PrintAndLogEx(INFO, ".............. ATS length %u bytes ( %s )", atslen, _GREEN_("ok"));
7958 } else {
7959 PrintAndLogEx(INFO, ".............. ATS length %u bytes ( %s )", atslen, _RED_("fail"));
7960 atslen = 0;
7963 PrintAndLogEx(INFO, "");
7965 // ATS seems to have 16 bytes reserved
7966 PrintAndLogEx(INFO, _CYAN_("Config 2 - ATS"));
7967 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d + 8, 16));
7968 if (atslen <= 16) {
7969 PrintAndLogEx(INFO, "%s.............. ATS ( %d bytes )", sprint_hex_inrow(&d[8], d[7]), d[7]);
7970 PrintAndLogEx(INFO, "..................%s Reserved for ATS", sprint_hex_inrow(d + 8 + d[7], 16 - d[7]));
7971 } else {
7972 PrintAndLogEx(INFO, "%s.............. %u Reserved for ATS", sprint_hex_inrow(&d[8], 16), 16);
7975 PrintAndLogEx(INFO, "");
7976 PrintAndLogEx(INFO, _CYAN_("Config 3 - Limits"));
7977 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(d + 24, (n - 24)));
7978 PrintAndLogEx(INFO, "%02X%02X............ ATQA", d[24], d[25]);
7979 PrintAndLogEx(INFO, "....%02X.......... SAK", d[26]);
7980 PrintAndLogEx(INFO, "......%02X........ " NOLF, d[27]);
7981 switch (d[27]) {
7982 case 0x00:
7983 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("Ultralight EV1") : "Ultralight Ev1");
7984 break;
7985 case 0x01:
7986 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("NTAG") : "NTAG");
7987 break;
7988 case 0x02:
7989 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("Ultralight C") : "Ultralight C");
7990 break;
7991 case 0x03:
7992 PrintAndLogEx(NORMAL, "%s", (is_ul_enabled) ? _GREEN_("Ultralight") : "Ultralight");
7993 break;
7994 default:
7995 PrintAndLogEx(NORMAL, _RED_("unknown"));
7996 break;
7999 PrintAndLogEx(INFO, "........%02X...... Max R/W sectors", d[28]);
8000 PrintAndLogEx(INFO, "..........%02X.... " NOLF, d[29]);
8001 switch (d[29]) {
8002 case 0x00:
8003 PrintAndLogEx(NORMAL, _GREEN_("CUID enabled"));
8004 break;
8005 case 0x01:
8006 PrintAndLogEx(NORMAL, "CUID disabled");
8007 break;
8008 case 0x02:
8009 PrintAndLogEx(NORMAL, "Default value. Same behaviour as 00?");
8010 break;
8011 default:
8012 PrintAndLogEx(NORMAL, _RED_("unknown"));
8013 break;
8015 PrintAndLogEx(INFO, "............%s unknown", sprint_hex_inrow(d + 30, n - 30));
8016 PrintAndLogEx(INFO, "");
8017 return PM3_SUCCESS;
8020 // info about Gen4 GTU card
8021 static int CmdHF14AGen4Info(const char *cmd) {
8022 CLIParserContext *ctx;
8023 CLIParserInit(&ctx, "hf mf ginfo",
8024 "Read info about magic gen4 GTU card.",
8025 "hf mf ginfo --> get info with default password 00000000\n"
8026 "hf mf ginfo --pwd 01020304 --> get info with password\n"
8027 "hf mf ginfo -d 00000000000002090978009102BDAC19131011121314151604001800FF0002FD -v --> decode config block"
8029 void *argtable[] = {
8030 arg_param_begin,
8031 arg_lit0("v", "verbose", "verbose output"),
8032 arg_str0("p", "pwd", "<hex>", "password 4 bytes"),
8033 arg_str0("d", "data", "<hex>", "config bytes 32 bytes"),
8034 arg_param_end
8036 CLIExecWithReturn(ctx, cmd, argtable, true);
8037 bool verbose = arg_get_lit(ctx, 1);
8039 int pwd_len = 0;
8040 uint8_t pwd[4] = {0};
8041 CLIGetHexWithReturn(ctx, 2, pwd, &pwd_len);
8043 int dlen = 0;
8044 uint8_t data[32] = {0};
8045 CLIGetHexWithReturn(ctx, 3, data, &dlen);
8046 CLIParserFree(ctx);
8048 if (pwd_len != 0 && pwd_len != 4) {
8049 PrintAndLogEx(FAILED, "Password must be 4 bytes length, got " _YELLOW_("%u"), pwd_len);
8050 return PM3_EINVARG;
8053 uint8_t resp[40] = {0};
8054 size_t resplen = 0;
8055 int res = 0;
8057 if (dlen != 32) {
8058 res = mfG4GetConfig(pwd, resp, &resplen, verbose);
8059 if (res != PM3_SUCCESS || resplen == 0) {
8060 if (res == PM3_ETIMEOUT)
8061 PrintAndLogEx(ERR, "No card in the field or card command timeout.");
8062 else
8063 PrintAndLogEx(ERR, "Error get config. Maybe not a Gen4 card?. error=%d rlen=%zu", res, resplen);
8064 return PM3_ESOFT;
8066 } else {
8067 memcpy(resp, data, dlen);
8068 resplen = 32;
8071 parse_gtu_cfg(resp, resplen);
8073 uint8_t uid_len = resp[1];
8075 res = mfG4GetFactoryTest(pwd, resp, &resplen, false);
8076 if (res == PM3_SUCCESS && resplen > 2) {
8077 PrintAndLogEx(INFO, "");
8078 PrintAndLogEx(INFO, _CYAN_("Factory test"));
8079 if (verbose) {
8080 PrintAndLogEx(INFO, "Raw......... %s", sprint_hex_inrow(resp, resplen));
8083 if (memcmp(resp + resplen - 2, "\x66\x66", 2) == 0) {
8084 PrintAndLogEx(INFO, "Card type... Generic");
8086 } else if (memcmp(resp + resplen - 2, "\x02\xAA", 2) == 0) {
8087 PrintAndLogEx(INFO, "Card type... " _RED_("Limited functionality"));
8089 } else if (memcmp(resp + resplen - 2, "\x03\xA0", 2) == 0) {
8090 PrintAndLogEx(INFO, "Card type... Old card version");
8092 } else if (memcmp(resp + resplen - 2, "\x06\xA0", 2) == 0) {
8093 PrintAndLogEx(INFO, "Card type... " _GREEN_("New card version"));
8095 } else {
8096 PrintAndLogEx(INFO, "Card type... " _RED_("unknown %02X%02X"), resp[resplen - 2], resp[resplen - 1]);
8100 // read block 0
8101 res = mfG4GetBlock(pwd, 0, resp, MAGIC_INIT | MAGIC_OFF);
8102 if (res == PM3_SUCCESS) {
8103 PrintAndLogEx(INFO, "");
8104 PrintAndLogEx(INFO, _CYAN_("Block 0 test"));
8105 PrintAndLogEx(INFO, "Block 0..... %s", sprint_hex_inrow(resp, 16));
8107 switch (uid_len) {
8108 case 0x00:
8109 PrintAndLogEx(INFO, "UID [4]..... %s", sprint_hex_inrow(resp, 4));
8110 break;
8111 case 0x01:
8112 PrintAndLogEx(INFO, "UID [7]..... %s", sprint_hex_inrow(resp, 7));
8113 break;
8114 case 0x02:
8115 PrintAndLogEx(INFO, "UID [10..... %s", sprint_hex_inrow(resp, 10));
8116 break;
8117 default:
8118 break;
8122 PrintAndLogEx(NORMAL, "");
8123 return PM3_SUCCESS;
8126 // Read block from Gen4 GTU card
8127 static int CmdHF14AGen4GetBlk(const char *cmd) {
8128 CLIParserContext *ctx;
8129 CLIParserInit(&ctx, "hf mf ggetblk",
8130 "Get block data from magic gen4 GTU card.",
8131 "hf mf ggetblk --blk 0 --> get block 0 (manufacturer)\n"
8132 "hf mf ggetblk --blk 3 -v --> get block 3, decode sector trailer\n"
8134 void *argtable[] = {
8135 arg_param_begin,
8136 arg_int1("b", "blk", "<dec>", "block number"),
8137 arg_lit0("v", "verbose", "verbose output"),
8138 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8139 arg_param_end
8141 CLIExecWithReturn(ctx, cmd, argtable, false);
8142 int b = arg_get_int_def(ctx, 1, 0);
8143 bool verbose = arg_get_lit(ctx, 2);
8145 int pwd_len = 0;
8146 uint8_t pwd[4] = {0};
8147 CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
8148 CLIParserFree(ctx);
8150 //validate args
8151 if (b > MIFARE_4K_MAXBLOCK) {
8152 return PM3_EINVARG;
8155 if (pwd_len != 4 && pwd_len != 0) {
8156 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8157 return PM3_EINVARG;
8160 uint8_t blockno = (uint8_t)b;
8161 uint8_t data[16] = {0};
8163 PrintAndLogEx(NORMAL, "Block: %x", blockno) ;
8165 int res = mfG4GetBlock(pwd, blockno, data, MAGIC_INIT | MAGIC_OFF);
8166 if (res) {
8167 PrintAndLogEx(ERR, "Can't read block. error=%d", res);
8168 return PM3_ESOFT;
8171 uint8_t sector = mfSectorNum(blockno);
8172 mf_print_sector_hdr(sector);
8173 mf_print_block_one(blockno, data, verbose);
8175 if (verbose) {
8176 decode_print_st(blockno, data);
8177 } else {
8178 PrintAndLogEx(NORMAL, "");
8181 return PM3_SUCCESS;
8184 // Load dump to Gen4 GTU card
8185 static int CmdHF14AGen4Load(const char *cmd) {
8187 CLIParserContext *ctx;
8188 CLIParserInit(&ctx, "hf mf gload",
8189 "Load magic gen4 gtu card with data from (bin/eml/json) dump file\n"
8190 "or from emulator memory.",
8191 "hf mf gload --emu\n"
8192 "hf mf gload -f hf-mf-01020304.eml\n"
8193 "hf mf gload -p AABBCCDD --4k -v -f hf-mf-01020304-dump.bin\n"
8194 "\n"
8195 "Card must be configured beforehand with `script run hf_mf_ultimatecard`.\n"
8196 "Blocks are 16 bytes long."
8198 void *argtable[] = {
8199 arg_param_begin,
8200 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
8201 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
8202 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
8203 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
8204 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8205 arg_lit0("v", "verbose", "verbose output"),
8206 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
8207 arg_lit0(NULL, "emu", "from emulator memory"),
8208 arg_int0(NULL, "start", "<dec>", "index of block to start writing (default 0)"),
8209 arg_int0(NULL, "end", "<dec>", "index of block to end writing (default last block)"),
8210 arg_param_end
8213 CLIExecWithReturn(ctx, cmd, argtable, false);
8214 bool m0 = arg_get_lit(ctx, 1);
8215 bool m1 = arg_get_lit(ctx, 2);
8216 bool m2 = arg_get_lit(ctx, 3);
8217 bool m4 = arg_get_lit(ctx, 4);
8219 int pwd_len = 0;
8220 uint8_t pwd[4] = {0};
8221 CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
8223 bool verbose = arg_get_lit(ctx, 6);
8225 int fnlen = 0;
8226 char filename[FILE_PATH_SIZE] = {0};
8227 CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
8229 bool fill_from_emulator = arg_get_lit(ctx, 8);
8231 int start = arg_get_int_def(ctx, 9, 0);
8232 int end = arg_get_int_def(ctx, 10, -1);
8234 CLIParserFree(ctx);
8236 // validations
8237 if (pwd_len != 4 && pwd_len != 0) {
8238 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8239 return PM3_EINVARG;
8242 if ((m0 + m1 + m2 + m4) > 1) {
8243 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
8244 return PM3_EINVARG;
8245 } else if ((m0 + m1 + m2 + m4) == 0) {
8246 m1 = true;
8249 char s[6];
8250 memset(s, 0, sizeof(s));
8251 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
8252 if (m0) {
8253 block_cnt = MIFARE_MINI_MAXBLOCK;
8254 strncpy(s, "Mini", 5);
8255 } else if (m1) {
8256 block_cnt = MIFARE_1K_MAXBLOCK;
8257 strncpy(s, "1K", 3);
8258 } else if (m2) {
8259 block_cnt = MIFARE_2K_MAXBLOCK;
8260 strncpy(s, "2K", 3);
8261 } else if (m4) {
8262 block_cnt = MIFARE_4K_MAXBLOCK;
8263 strncpy(s, "4K", 3);
8264 } else {
8265 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
8266 return PM3_EINVARG;
8269 if (fill_from_emulator && (fnlen != 0)) {
8270 PrintAndLogEx(WARNING, "Please specify file or emulator memory, but not both");
8271 return PM3_EINVARG;
8274 if (!fill_from_emulator && (fnlen == 0)) {
8275 PrintAndLogEx(WARNING, "Please specify file or emulator memory");
8276 return PM3_EINVARG;
8279 if (end == -1) {
8280 end = block_cnt - 1;
8283 if (start < 0 || end < 0) {
8284 PrintAndLogEx(WARNING, "start and end must be positive integers");
8285 return PM3_EINVARG ;
8288 if (start > end) {
8289 PrintAndLogEx(WARNING, "start cannot be more than end");
8290 return PM3_EINVARG ;
8293 if (start >= block_cnt) {
8294 PrintAndLogEx(WARNING, "Last block for Mifare %s is %d. Start is too high.", s, block_cnt - 1) ;
8295 return PM3_EINVARG ;
8298 if (end >= block_cnt) {
8299 PrintAndLogEx(WARNING, "Last block for Mifare %s is %d. End is too high.", s, block_cnt - 1) ;
8300 return PM3_EINVARG ;
8303 uint8_t *data = NULL;
8304 size_t bytes_read = 0;
8306 if (fill_from_emulator) {
8307 data = calloc(block_cnt * MFBLOCK_SIZE, sizeof(uint8_t));
8308 if (data == NULL) {
8309 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
8310 return PM3_EMALLOC;
8313 PrintAndLogEx(INFO, "downloading emulator memory");
8314 if (GetFromDevice(BIG_BUF_EML, data, block_cnt * MFBLOCK_SIZE, 0, NULL, 0, NULL, 2500, false) == false) {
8315 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
8316 free(data);
8317 return PM3_ETIMEOUT;
8320 } else {
8321 // read from file
8322 int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
8323 if (res != PM3_SUCCESS) {
8324 return res;
8327 // check file size corresponds to card size.
8328 if (bytes_read != (block_cnt * MFBLOCK_SIZE)) {
8329 PrintAndLogEx(ERR, "File content error. Read %zu bytes, expected %i", bytes_read, block_cnt * MFBLOCK_SIZE);
8330 if (data != NULL) free(data);
8331 return PM3_EFILE;
8335 if (verbose) {
8336 if (fnlen != 0) {
8337 PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
8338 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
8339 } else {
8340 PrintAndLogEx(INFO, "Read %d blocks from emulator memory", block_cnt);
8344 PrintAndLogEx(INFO, "Copying to magic gen4 GTU MIFARE Classic " _GREEN_("%s"), s);
8345 PrintAndLogEx(INFO, "Starting block: %d. Ending block: %d.", start, end);
8347 // copy to card
8348 for (uint16_t blockno = start; blockno <= end; blockno++) {
8350 // 4k writes can be long, so we split status each 64 block boundary.
8351 if (blockno % 64 == 0 || blockno == start) {
8352 PrintAndLogEx(NORMAL, "");
8353 PrintAndLogEx(INFO, "" NOLF) ;
8355 PrintAndLogEx(NORMAL, "." NOLF);
8356 fflush(stdout);
8358 // write block
8359 uint8_t flags = 0 ;
8360 if (blockno == start) flags |= MAGIC_INIT ;
8361 if (blockno == end) flags |= MAGIC_OFF ;
8363 int res = mfG4SetBlock(pwd, blockno, data + (blockno * MFBLOCK_SIZE), flags);
8364 if (res != PM3_SUCCESS) {
8365 PrintAndLogEx(WARNING, "Can't set magic card block: %d. error=%d", blockno, res);
8366 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
8367 free(data);
8368 return PM3_ESOFT;
8371 PrintAndLogEx(NORMAL, "\n");
8373 if (data != NULL) free(data);
8375 PrintAndLogEx(SUCCESS, "Card loaded " _YELLOW_("%d") " blocks from %s", end - start + 1,
8376 (fill_from_emulator ? "emulator memory" : "file"));
8377 PrintAndLogEx(INFO, "Done!");
8378 return PM3_SUCCESS;
8381 // Write block to Gen4 GTU card
8382 static int CmdHF14AGen4SetBlk(const char *cmd) {
8383 CLIParserContext *ctx;
8384 CLIParserInit(&ctx, "hf mf gsetblk",
8385 "Set block data on a magic gen4 GTU card",
8386 "hf mf gsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
8388 void *argtable[] = {
8389 arg_param_begin,
8390 arg_int1("b", "blk", "<dec>", "block number"),
8391 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
8392 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8393 arg_param_end
8395 CLIExecWithReturn(ctx, cmd, argtable, false);
8397 int b = arg_get_int_def(ctx, 1, -1);
8399 uint8_t data[MFBLOCK_SIZE] = {0x00};
8400 int datalen = 0;
8401 CLIGetHexWithReturn(ctx, 2, data, &datalen);
8403 int pwd_len = 0;
8404 uint8_t pwd[4] = {0};
8405 CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
8407 CLIParserFree(ctx);
8409 // validations
8410 if (pwd_len != 4 && pwd_len != 0) {
8411 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8412 return PM3_EINVARG;
8415 CLIParserFree(ctx);
8417 if (b < 0 || b >= MIFARE_4K_MAXBLOCK) {
8418 PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
8419 return PM3_EINVARG;
8422 if (datalen != MFBLOCK_SIZE) {
8423 PrintAndLogEx(FAILED, "expected 16 bytes data, got %i", datalen);
8424 return PM3_EINVARG;
8427 // write block
8428 PrintAndLogEx(INFO, "Writing block number:%2d data:%s", b, sprint_hex_inrow(data, sizeof(data)));
8430 uint8_t blockno = (uint8_t)b;
8431 int res = mfG4SetBlock(pwd, blockno, data, MAGIC_INIT | MAGIC_OFF);
8432 if (res) {
8433 PrintAndLogEx(ERR, "Can't write block. error=%d", res);
8434 return PM3_ESOFT;
8437 return PM3_SUCCESS;
8440 static int CmdHF14AGen4View(const char *Cmd) {
8442 CLIParserContext *ctx;
8443 CLIParserInit(&ctx, "hf mf gview",
8444 "View `magic gen4 gtu` card memory",
8445 "hf mf gview\n"
8446 "hf mf gview --4k"
8448 void *argtable[] = {
8449 arg_param_begin,
8450 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
8451 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
8452 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
8453 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
8454 arg_str0("p", "pwd", "<hex>", "password 4bytes"),
8455 arg_lit0("v", "verbose", "verbose output"),
8456 arg_param_end
8458 CLIExecWithReturn(ctx, Cmd, argtable, true);
8459 bool m0 = arg_get_lit(ctx, 1);
8460 bool m1 = arg_get_lit(ctx, 2);
8461 bool m2 = arg_get_lit(ctx, 3);
8462 bool m4 = arg_get_lit(ctx, 4);
8464 int pwd_len = 0;
8465 uint8_t pwd[4] = {0};
8466 CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
8468 bool verbose = arg_get_lit(ctx, 6);
8469 CLIParserFree(ctx);
8471 // validations
8472 if (pwd_len != 4 && pwd_len != 0) {
8473 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8474 return PM3_EINVARG;
8477 if ((m0 + m1 + m2 + m4) > 1) {
8478 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
8479 return PM3_EINVARG;
8480 } else if ((m0 + m1 + m2 + m4) == 0) {
8481 m1 = true;
8484 char s[6];
8485 memset(s, 0, sizeof(s));
8486 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
8487 if (m0) {
8488 block_cnt = MIFARE_MINI_MAXBLOCK;
8489 strncpy(s, "Mini", 5);
8490 } else if (m1) {
8491 block_cnt = MIFARE_1K_MAXBLOCK;
8492 strncpy(s, "1K", 3);
8493 } else if (m2) {
8494 block_cnt = MIFARE_2K_MAXBLOCK;
8495 strncpy(s, "2K", 3);
8496 } else if (m4) {
8497 block_cnt = MIFARE_4K_MAXBLOCK;
8498 strncpy(s, "4K", 3);
8499 } else {
8500 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
8501 return PM3_EINVARG;
8503 PrintAndLogEx(SUCCESS, "View magic gen4 GTU MIFARE Classic " _GREEN_("%s"), s);
8505 // reserve memory
8506 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
8507 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
8508 if (dump == NULL) {
8509 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
8510 return PM3_EMALLOC;
8513 for (uint16_t i = 0; i < block_cnt; i++) {
8515 uint8_t flags = 0 ;
8516 if (i == 0) flags |= MAGIC_INIT ;
8517 if (i + 1 == block_cnt) flags |= MAGIC_OFF ;
8519 int res = mfG4GetBlock(pwd, i, dump + (i * MFBLOCK_SIZE), flags);
8520 if (res != PM3_SUCCESS) {
8521 PrintAndLogEx(WARNING, "Can't get magic card block: %u. error=%d", i, res);
8522 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
8523 free(dump);
8524 return PM3_ESOFT;
8527 PrintAndLogEx(NORMAL, "." NOLF);
8528 fflush(stdout);
8529 // 4k READs can be long, so we split status each 64 blocks.
8530 if (i % 64 == 0) {
8531 PrintAndLogEx(NORMAL, "");
8532 PrintAndLogEx(INFO, "" NOLF) ;
8536 PrintAndLogEx(NORMAL, "");
8537 mf_print_blocks(block_cnt, dump, verbose);
8539 if (verbose) {
8540 mf_print_keys(block_cnt, dump);
8543 free(dump);
8544 return PM3_SUCCESS;
8547 // save contents of Gent4 GTU card to file / emulator
8548 static int CmdHF14AGen4Save(const char *Cmd) {
8550 CLIParserContext *ctx;
8551 CLIParserInit(&ctx, "hf mf gsave",
8552 "Save `magic gen4 gtu` card memory to file (bin/json)"
8553 "or into emulator memory",
8554 "hf mf gsave\n"
8555 "hf mf gsave --4k\n"
8556 "hf mf gsave -p DEADBEEF -f hf-mf-01020304.json"
8558 void *argtable[] = {
8559 arg_param_begin,
8560 arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
8561 arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"),
8562 arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
8563 arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
8564 arg_str0("p", "pwd", "<hex>", "password 4 bytes"),
8565 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
8566 arg_lit0(NULL, "emu", "to emulator memory"),
8567 arg_param_end
8569 CLIExecWithReturn(ctx, Cmd, argtable, true);
8570 bool m0 = arg_get_lit(ctx, 1);
8571 bool m1 = arg_get_lit(ctx, 2);
8572 bool m2 = arg_get_lit(ctx, 3);
8573 bool m4 = arg_get_lit(ctx, 4);
8575 int pwd_len = 0;
8576 uint8_t pwd[4] = {0};
8577 CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len);
8579 int fnlen = 0;
8580 char filename[FILE_PATH_SIZE];
8581 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
8583 bool fill_emulator = arg_get_lit(ctx, 7);
8584 CLIParserFree(ctx);
8586 // ICEMAN: bug. if device has been using ICLASS commands,
8587 // the device needs to load the HF fpga image. It takes 1.5 second.
8588 set_fpga_mode(FPGA_BITSTREAM_HF);
8590 // validations
8591 if (pwd_len != 4 && pwd_len != 0) {
8592 PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);
8593 return PM3_EINVARG;
8596 if ((m0 + m1 + m2 + m4) > 1) {
8597 PrintAndLogEx(WARNING, "Only specify one MIFARE Type");
8598 return PM3_EINVARG;
8599 } else if ((m0 + m1 + m2 + m4) == 0) {
8600 m1 = true;
8603 char s[6];
8604 memset(s, 0, sizeof(s));
8605 uint16_t block_cnt = MIFARE_1K_MAXBLOCK;
8606 if (m0) {
8607 block_cnt = MIFARE_MINI_MAXBLOCK;
8608 strncpy(s, "Mini", 5);
8609 } else if (m1) {
8610 block_cnt = MIFARE_1K_MAXBLOCK;
8611 strncpy(s, "1K", 3);
8612 } else if (m2) {
8613 block_cnt = MIFARE_2K_MAXBLOCK;
8614 strncpy(s, "2K", 3);
8615 } else if (m4) {
8616 block_cnt = MIFARE_4K_MAXBLOCK;
8617 strncpy(s, "4K", 3);
8618 } else {
8619 PrintAndLogEx(WARNING, "Please specify a MIFARE Type");
8620 return PM3_EINVARG;
8623 // Select card to get UID/UIDLEN information
8624 clearCommandBuffer();
8625 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
8626 PacketResponseNG resp;
8627 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
8628 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
8629 return PM3_ETIMEOUT;
8633 0: couldn't read
8634 1: OK, with ATS
8635 2: OK, no ATS
8636 3: proprietary Anticollision
8638 uint64_t select_status = resp.oldarg[0];
8639 if (select_status == 0) {
8640 PrintAndLogEx(DEBUG, "iso14443a card select failed");
8641 return PM3_SUCCESS;
8644 // store card info
8645 iso14a_card_select_t card;
8646 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
8648 // reserve memory
8649 uint16_t bytes = block_cnt * MFBLOCK_SIZE;
8650 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
8651 if (dump == NULL) {
8652 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
8653 return PM3_EMALLOC;
8656 PrintAndLogEx(SUCCESS, "Dumping magic gen4 GTU MIFARE Classic " _GREEN_("%s") " card memory", s);
8657 PrintAndLogEx(INFO, "." NOLF);
8659 for (uint16_t i = 0; i < block_cnt; i++) {
8660 uint8_t flags = 0 ;
8661 if (i == 0) {
8662 flags |= MAGIC_INIT;
8664 if (i + 1 == block_cnt) {
8665 flags |= MAGIC_OFF;
8668 int res = mfG4GetBlock(pwd, i, dump + (i * MFBLOCK_SIZE), flags);
8669 if (res != PM3_SUCCESS) {
8670 PrintAndLogEx(NORMAL, "");
8671 PrintAndLogEx(WARNING, "Can't get magic card block: %u. error=%d", i, res);
8672 PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position");
8673 free(dump);
8674 return PM3_ESOFT;
8678 PrintAndLogEx(NORMAL, "." NOLF);
8679 fflush(stdout);
8680 // 4k READs can be long, so we split status each 64 blocks.
8681 if (i % 64 == 0 && i != 0) {
8682 PrintAndLogEx(NORMAL, "");
8683 PrintAndLogEx(INFO, "" NOLF) ;
8687 PrintAndLogEx(NORMAL, "");
8689 if (fill_emulator) {
8690 PrintAndLogEx(INFO, "uploading to emulator memory");
8691 PrintAndLogEx(INFO, "." NOLF);
8692 // fast push mode
8693 g_conn.block_after_ACK = true;
8695 size_t offset = 0;
8696 int cnt = 0;
8697 uint16_t bytes_left = bytes ;
8699 // 12 is the size of the struct the fct mfEmlSetMem_xt uses to transfer to device
8700 uint16_t max_avail_blocks = ((PM3_CMD_DATA_SIZE - 12) / MFBLOCK_SIZE) * MFBLOCK_SIZE;
8702 while (bytes_left > 0 && cnt < block_cnt) {
8703 if (bytes_left == MFBLOCK_SIZE) {
8704 // Disable fast mode on last packet
8705 g_conn.block_after_ACK = false;
8708 uint16_t chunk_size = MIN(max_avail_blocks, bytes_left);
8709 uint16_t blocks_to_send = chunk_size / MFBLOCK_SIZE;
8711 if (mfEmlSetMem_xt(dump + offset, cnt, blocks_to_send, MFBLOCK_SIZE) != PM3_SUCCESS) {
8712 PrintAndLogEx(FAILED, "Can't set emulator mem at block: %3d", cnt);
8713 free(dump);
8714 return PM3_ESOFT;
8717 cnt += blocks_to_send;
8718 offset += chunk_size;
8719 bytes_left -= chunk_size;
8720 PrintAndLogEx(NORMAL, "." NOLF);
8721 fflush(stdout);
8724 PrintAndLogEx(NORMAL, "");
8725 PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", bytes);
8728 // user supplied filename?
8729 if (fnlen < 1) {
8730 char *fptr = filename;
8731 fptr += snprintf(fptr, sizeof(filename), "hf-mf-");
8732 FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
8735 pm3_save_mf_dump(filename, dump, bytes, jsfCardMemory);
8736 free(dump);
8737 return PM3_SUCCESS;
8740 // change Gent4 GTU card access password
8741 static int CmdHF14AGen4ChangePwd(const char *Cmd) {
8743 CLIParserContext *ctx;
8744 CLIParserInit(&ctx, "hf mf gchpwd",
8745 "Change access password for Gen4 GTU card. WARNING! If you dont KNOW the password - you CAN'T access it!!!",
8746 "hf mf gchpwd --pwd 00000000 --newpwd 01020304"
8748 void *argtable[] = {
8749 arg_param_begin,
8750 arg_str0("p", "pwd", "<hex>", "password 4 bytes"),
8751 arg_str0("n", "newpwd", "<hex>", "new password 4 bytes"),
8752 arg_lit0("v", "verbose", "verbose output"),
8753 arg_param_end
8755 CLIExecWithReturn(ctx, Cmd, argtable, false);
8757 int pwd_len = 0;
8758 uint8_t pwd[4] = {0};
8759 CLIGetHexWithReturn(ctx, 1, pwd, &pwd_len);
8761 int new_pwd_len = 0;
8762 uint8_t new_pwd[4] = {0};
8763 CLIGetHexWithReturn(ctx, 2, new_pwd, &new_pwd_len);
8765 bool verbose = arg_get_lit(ctx, 3);
8767 CLIParserFree(ctx);
8769 if (pwd_len != 4) {
8770 PrintAndLogEx(FAILED, "Old password must be 4 bytes long, got " _YELLOW_("%u"), pwd_len);
8771 return PM3_EINVARG;
8774 if (new_pwd_len != 4) {
8775 PrintAndLogEx(FAILED, "New password must be 4 bytes long, got " _YELLOW_("%u"), new_pwd_len);
8776 return PM3_EINVARG;
8779 int res = mfG4ChangePassword(pwd, new_pwd, verbose);
8780 if (res != PM3_SUCCESS) {
8781 PrintAndLogEx(ERR, "Change password error");
8782 return res;
8785 PrintAndLogEx(SUCCESS, "Change password ( " _GREEN_("ok") " )");
8786 return PM3_SUCCESS;
8789 static void parse_gdm_cfg(const uint8_t *d) {
8790 PrintAndLogEx(NORMAL, "");
8791 PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("GDM Gen4 Configuration") " -----------------------------------------");
8792 PrintAndLogEx(SUCCESS, _YELLOW_("%s"), sprint_hex_inrow(d, MFBLOCK_SIZE));
8793 PrintAndLogEx(SUCCESS, _YELLOW_("%02X%02X") "............................ %s %s"
8794 , d[0]
8795 , d[1]
8796 , (d[0] == 0x85 && d[1] == 0x00) ? "Magic wakeup disabled" : _GREEN_("Magic wakeup enabled")
8797 , (d[0] == 0x85 && d[1] == 0x00) ? "" : ((d[0] == 0x7A && d[1] == 0xFF) ? _GREEN_("with GDM cfg block access") : _RED_(", no GDM cfg block access"))
8799 PrintAndLogEx(SUCCESS, "...." _YELLOW_("%02X") ".......................... Magic wakeup style " _YELLOW_("%s"), d[2], ((d[2] == 0x85) ? "GDM 20(7)/23" : "Gen1a 40(7)/43"));
8800 PrintAndLogEx(SUCCESS, "......" _YELLOW_("%02X%02X%02X") ".................... unknown", d[3], d[4], d[5]);
8801 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");
8802 PrintAndLogEx(SUCCESS, ".............." _YELLOW_("%02X") "................ %s", d[7], (d[7] == 0x5A) ? _GREEN_("CUID enabled") : "CUID Disabled");
8803 PrintAndLogEx(SUCCESS, "................" _YELLOW_("%02X") ".............. n/a", d[8]);
8805 const char *pers;
8806 switch (d[9]) {
8807 case 0x5A:
8808 pers = _YELLOW_("Unfused");
8809 break;
8810 case 0xC3:
8811 pers = _CYAN_("UIDFO, double size UID");
8812 break;
8813 case 0xA5:
8814 pers = _CYAN_("UIDF1, double size UID, optional usage of selection process shortcut");
8815 break;
8816 case 0x87:
8817 pers = _GREEN_("UIDF2, single size random ID");
8818 break;
8819 case 0x69:
8820 pers = _GREEN_("UIDF3, single size NUID");
8821 break;
8822 default:
8823 pers = "4B UID from Block 0";
8824 break;
8826 PrintAndLogEx(SUCCESS, ".................." _YELLOW_("%02X") "............ MFC EV1 perso. " _YELLOW_("%s"), d[9], pers);
8827 PrintAndLogEx(SUCCESS, "...................." _YELLOW_("%02X") ".......... %s", d[10], (d[10] == 0x5A) ? _GREEN_("Shadow mode enabled") : "Shadow mode disabled");
8828 PrintAndLogEx(SUCCESS, "......................" _YELLOW_("%02X") "........ %s", d[11], (d[11] == 0x5A) ? _GREEN_("Magic auth enabled") : "Magic auth disabled");
8829 PrintAndLogEx(SUCCESS, "........................" _YELLOW_("%02X") "...... %s", d[12], (d[12] == 0x5A) ? _GREEN_("Static encrypted nonce enabled") : "Static encrypted nonce disabled");
8830 PrintAndLogEx(SUCCESS, ".........................." _YELLOW_("%02X") ".... %s", d[13], (d[13] == 0x5A) ? _GREEN_("MFC EV1 signature enabled") : "MFC EV1 signature disabled");
8831 PrintAndLogEx(SUCCESS, "............................" _YELLOW_("%02X") ".. n/a", d[14]);
8832 PrintAndLogEx(SUCCESS, ".............................." _YELLOW_("%02X") " SAK", d[15]);
8833 PrintAndLogEx(NORMAL, "");
8836 static int CmdHF14AGen4_GDM_ParseCfg(const char *Cmd) {
8837 CLIParserContext *ctx;
8838 CLIParserInit(&ctx, "hf mf gdmparsecfg",
8839 "Parse configuration data on a magic gen4 GDM card",
8840 "hf mf gdmparsecfg -d 850000000000000000005A5A00000008"
8842 void *argtable[] = {
8843 arg_param_begin,
8844 arg_str1("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
8845 arg_param_end
8847 CLIExecWithReturn(ctx, Cmd, argtable, false);
8849 uint8_t block[MFBLOCK_SIZE] = {0x00};
8850 int blen = 0;
8851 CLIGetHexWithReturn(ctx, 1, block, &blen);
8852 CLIParserFree(ctx);
8854 if (blen != MFBLOCK_SIZE) {
8855 PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
8856 return PM3_EINVARG;
8859 parse_gdm_cfg(block);
8861 return PM3_SUCCESS;
8864 static int CmdHF14AGen4_GDM_Cfg(const char *Cmd) {
8865 CLIParserContext *ctx;
8866 CLIParserInit(&ctx, "hf mf gdmcfg",
8867 "Get configuration data from magic gen4 GDM card.",
8868 "hf mf gdmcfg\n"
8870 void *argtable[] = {
8871 arg_param_begin,
8872 arg_str0("k", "key", "<hex>", "key 6 bytes (only for regular wakeup)"),
8873 arg_lit0(NULL, "gen1a", "use gen1a (40/43) magic wakeup"),
8874 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
8875 arg_param_end
8877 CLIExecWithReturn(ctx, Cmd, argtable, true);
8879 int keylen = 0;
8880 uint8_t key[6] = {0};
8881 CLIGetHexWithReturn(ctx, 1, key, &keylen);
8882 bool gen1a = arg_get_lit(ctx, 2);
8883 bool gdm = arg_get_lit(ctx, 3);
8884 CLIParserFree(ctx);
8886 // validate args
8887 if (keylen != 6 && keylen != 0) {
8888 PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
8889 return PM3_EINVARG;
8892 if (gen1a && gdm) {
8893 PrintAndLogEx(FAILED, "Can only specify a single magic wakeup command");
8894 return PM3_EINVARG;
8897 if ((gen1a || gdm) && keylen != 0) {
8898 PrintAndLogEx(FAILED, "Cannot use a key in combination with a magic wakeup");
8899 return PM3_EINVARG;
8902 mf_readblock_ex_t payload = {
8903 .read_cmd = MIFARE_MAGIC_GDM_READ_CFG,
8904 .block_no = 0,
8906 memcpy(payload.key, key, sizeof(payload.key));
8908 if (gen1a) {
8909 payload.wakeup = MF_WAKE_GEN1A;
8910 payload.auth_cmd = 0;
8911 } else if (gdm) {
8912 payload.wakeup = MF_WAKE_GDM_ALT;
8913 payload.auth_cmd = 0;
8914 } else {
8915 payload.wakeup = MF_WAKE_WUPA;
8916 payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
8919 clearCommandBuffer();
8920 SendCommandNG(CMD_HF_MIFARE_READBL_EX, (uint8_t *)&payload, sizeof(payload));
8921 PacketResponseNG resp;
8922 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL_EX, &resp, 1500) == false) {
8923 PrintAndLogEx(WARNING, "command execution time out");
8924 return PM3_ETIMEOUT;
8927 if (resp.status == PM3_SUCCESS && resp.length == MFBLOCK_SIZE) {
8928 parse_gdm_cfg(resp.data.asBytes);
8930 PrintAndLogEx(NORMAL, "");
8933 return resp.status;
8936 static int CmdHF14AGen4_GDM_SetCfg(const char *Cmd) {
8937 CLIParserContext *ctx;
8938 CLIParserInit(&ctx, "hf mf gdmsetcfg",
8939 "Set configuration data on a magic gen4 GDM card",
8940 "hf mf gdmsetcfg -d 850000000000000000005A5A00000008"
8942 void *argtable[] = {
8943 arg_param_begin,
8944 arg_str1("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
8945 arg_str0("k", "key", "<hex>", "key 6 bytes (only for regular wakeup)"),
8946 arg_lit0(NULL, "gen1a", "use gen1a (40/43) magic wakeup"),
8947 arg_lit0(NULL, "gdm", "use gdm alt (20/23) magic wakeup"),
8948 arg_param_end
8950 CLIExecWithReturn(ctx, Cmd, argtable, false);
8952 uint8_t block[MFBLOCK_SIZE] = {0x00};
8953 int blen = 0;
8954 CLIGetHexWithReturn(ctx, 1, block, &blen);
8955 int keylen = 0;
8956 uint8_t key[6] = {0};
8957 CLIGetHexWithReturn(ctx, 2, key, &keylen);
8958 bool gen1a = arg_get_lit(ctx, 3);
8959 bool gdm = arg_get_lit(ctx, 4);
8960 CLIParserFree(ctx);
8962 if (blen != MFBLOCK_SIZE) {
8963 PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
8964 return PM3_EINVARG;
8967 if (keylen != 6 && keylen != 0) {
8968 PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
8969 return PM3_EINVARG;
8972 if (gen1a && gdm) {
8973 PrintAndLogEx(FAILED, "Can only specify a single magic wakeup command");
8974 return PM3_EINVARG;
8977 if ((gen1a || gdm) && keylen != 0) {
8978 PrintAndLogEx(FAILED, "Cannot use a key in combination with a magic wakeup");
8979 return PM3_EINVARG;
8982 mf_writeblock_ex_t payload = {
8983 .write_cmd = MIFARE_MAGIC_GDM_WRITE_CFG,
8984 .block_no = 0,
8986 memcpy(payload.block_data, block, sizeof(payload.block_data));
8987 memcpy(payload.key, key, sizeof(payload.key));
8989 if (gen1a) {
8990 payload.wakeup = MF_WAKE_GEN1A;
8991 payload.auth_cmd = 0;
8992 } else if (gdm) {
8993 payload.wakeup = MF_WAKE_GDM_ALT;
8994 payload.auth_cmd = 0;
8995 } else {
8996 payload.wakeup = MF_WAKE_WUPA;
8997 payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
9000 clearCommandBuffer();
9001 SendCommandNG(CMD_HF_MIFARE_WRITEBL_EX, (uint8_t *)&payload, sizeof(payload));
9002 PacketResponseNG resp;
9003 if (WaitForResponseTimeout(CMD_HF_MIFARE_WRITEBL_EX, &resp, 1500) == false) {
9004 PrintAndLogEx(WARNING, "command execution time out");
9005 return PM3_ETIMEOUT;
9008 if (resp.status == PM3_SUCCESS) {
9009 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
9010 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf gdmcfg") "` to verify");
9011 } else {
9012 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
9014 return PM3_SUCCESS;
9017 static int CmdHF14AGen4_GDM_SetBlk(const char *Cmd) {
9019 CLIParserContext *ctx;
9020 CLIParserInit(&ctx, "hf mf gdmsetblk",
9021 "Set block data on a magic gen4 GDM card\n"
9022 "`--force` param is used to override warnings like bad ACL writes.\n"
9023 " if not specified, it will exit if detected",
9024 "hf mf gdmsetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f"
9026 void *argtable[] = {
9027 arg_param_begin,
9028 arg_int1(NULL, "blk", "<dec>", "block number"),
9029 arg_str0("d", "data", "<hex>", "bytes to write, 16 hex bytes"),
9030 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9031 arg_lit0(NULL, "force", "override warnings"),
9032 arg_param_end
9034 CLIExecWithReturn(ctx, Cmd, argtable, false);
9036 int b = arg_get_int_def(ctx, 1, 1);
9038 uint8_t block[MFBLOCK_SIZE] = {0x00};
9039 int blen = 0;
9040 CLIGetHexWithReturn(ctx, 2, block, &blen);
9042 int keylen = 0;
9043 uint8_t key[6] = {0};
9044 CLIGetHexWithReturn(ctx, 3, key, &keylen);
9046 bool force = arg_get_lit(ctx, 4);
9047 CLIParserFree(ctx);
9049 if (blen != MFBLOCK_SIZE) {
9050 PrintAndLogEx(WARNING, "expected %u HEX bytes. got %i", MFBLOCK_SIZE, blen);
9051 return PM3_EINVARG;
9054 if (b < 0 || b >= MIFARE_4K_MAXBLOCK) {
9055 PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b);
9056 return PM3_EINVARG;
9059 if (keylen != 6 && keylen != 0) {
9060 PrintAndLogEx(FAILED, "Must specify 6 bytes, got " _YELLOW_("%u"), keylen);
9061 return PM3_EINVARG;
9064 uint8_t blockno = (uint8_t)b;
9066 if (mf_analyse_st_block(blockno, block, force) != PM3_SUCCESS) {
9067 return PM3_EINVARG;
9070 PrintAndLogEx(INFO, "Writing block no %d, key %s", blockno, sprint_hex_inrow(key, sizeof(key)));
9071 PrintAndLogEx(INFO, "data: %s", sprint_hex(block, sizeof(block)));
9073 struct p {
9074 uint8_t blockno;
9075 uint8_t key[6];
9076 uint8_t data[MFBLOCK_SIZE]; // data to be written
9077 } PACKED payload;
9079 payload.blockno = blockno;
9080 memcpy(payload.key, key, sizeof(payload.key));
9081 memcpy(payload.data, block, sizeof(payload.data));
9083 clearCommandBuffer();
9084 SendCommandNG(CMD_HF_MIFARE_G4_GDM_WRBL, (uint8_t *)&payload, sizeof(payload));
9085 PacketResponseNG resp;
9086 if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_GDM_WRBL, &resp, 1500) == false) {
9087 PrintAndLogEx(WARNING, "command execution time out");
9088 return PM3_ETIMEOUT;
9091 if (resp.status == PM3_SUCCESS) {
9092 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
9093 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf rdbl") "` to verify");
9094 } else if (resp.status == PM3_ETEAROFF) {
9095 PrintAndLogEx(INFO, "Tear off triggered");
9096 return resp.status;
9097 } else {
9098 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
9100 return PM3_SUCCESS;
9103 static int CmdHF14AMfValue(const char *Cmd) {
9105 CLIParserContext *ctx;
9106 CLIParserInit(&ctx, "hf mf value",
9107 "MIFARE Classic value data commands\n",
9108 "hf mf value --blk 16 -k FFFFFFFFFFFF --set 1000\n"
9109 "hf mf value --blk 16 -k FFFFFFFFFFFF --inc 10\n"
9110 "hf mf value --blk 16 -k FFFFFFFFFFFF -b --dec 10\n"
9111 "hf mf value --blk 16 -k FFFFFFFFFFFF -b --get\n"
9112 "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"
9113 "hf mf value --get -d 87D612007829EDFF87D6120011EE11EE\n"
9115 void *argtable[] = {
9116 arg_param_begin,
9117 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9118 arg_lit0("a", NULL, "input key type is key A (def)"),
9119 arg_lit0("b", NULL, "input key type is key B"),
9120 arg_u64_0(NULL, "inc", "<dec>", "Increment value by X (0 - 2147483647)"),
9121 arg_u64_0(NULL, "dec", "<dec>", "Decrement value by X (0 - 2147483647)"),
9122 arg_u64_0(NULL, "set", "<dec>", "Set value to X (-2147483647 - 2147483647)"),
9123 arg_u64_0(NULL, "transfer", "<dec>", "Transfer value to other block (after inc/dec/restore)"),
9124 arg_str0(NULL, "tkey", "<hex>", "transfer key, 6 hex bytes (if transfer is preformed to other sector)"),
9125 arg_lit0(NULL, "ta", "transfer key type is key A (def)"),
9126 arg_lit0(NULL, "tb", "transfer key type is key B"),
9127 arg_lit0(NULL, "get", "Get value from block"),
9128 arg_lit0(NULL, "res", "Restore (copy value to card buffer, should be used with --transfer)"),
9129 arg_int0(NULL, "blk", "<dec>", "block number"),
9130 arg_str0("d", "data", "<hex>", "block data to extract values from (16 hex bytes)"),
9131 arg_param_end
9133 CLIExecWithReturn(ctx, Cmd, argtable, false);
9135 uint8_t blockno = (uint8_t)arg_get_int_def(ctx, 13, 1);
9137 uint8_t keytype = MF_KEY_A;
9138 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
9139 CLIParserFree(ctx);
9140 PrintAndLogEx(WARNING, "Choose one single input key type");
9141 return PM3_EINVARG;
9142 } else if (arg_get_lit(ctx, 3)) {
9143 keytype = MF_KEY_B;
9146 uint8_t transferkeytype = MF_KEY_A;
9147 if (arg_get_lit(ctx, 9) && arg_get_lit(ctx, 10)) {
9148 CLIParserFree(ctx);
9149 PrintAndLogEx(WARNING, "Choose one single transfer key type");
9150 return PM3_EINVARG;
9151 } else if (arg_get_lit(ctx, 10)) {
9152 transferkeytype = MF_KEY_B;
9155 int keylen = 0;
9156 uint8_t key[6] = {0};
9157 CLIGetHexWithReturn(ctx, 1, key, &keylen);
9159 int transferkeylen = 0;
9160 uint8_t transferkey[6] = {0};
9161 CLIGetHexWithReturn(ctx, 8, transferkey, &transferkeylen);
9164 Value /Value Value BLK /BLK BLK /BLK
9165 00000000 FFFFFFFF 00000000 10 EF 10 EF
9166 BLK is used to reference where the backup come from, I suspect it's just the current block for the actual value ?
9167 increment and decrement are an unsigned value
9168 set value is a signed value
9170 We are getting signed and/or bigger values to allow a default to be set meaning users did not supply that option.
9172 int64_t incval = (int64_t)arg_get_u64_def(ctx, 4, -1); // Inc by -1 is invalid, so not set.
9173 int64_t decval = (int64_t)arg_get_u64_def(ctx, 5, -1); // Dec by -1 is invalid, so not set.
9174 int64_t setval = (int64_t)arg_get_u64_def(ctx, 6, 0x7FFFFFFFFFFFFFFF); // out of bounds (for int32) so not set
9175 int64_t trnval = (int64_t)arg_get_u64_def(ctx, 7, -1); // block to transfer to
9176 bool getval = arg_get_lit(ctx, 11);
9177 bool resval = arg_get_lit(ctx, 12);
9178 int dlen = 0;
9179 uint8_t data[16] = {0};
9180 CLIGetHexWithReturn(ctx, 14, data, &dlen);
9181 CLIParserFree(ctx);
9183 // sanity checks
9186 // Action: 0 Increment, 1 - Decrement, 2 - Restore, 3 - Set, 4 - Get, 5 - Decode from data
9187 // iceman: TODO - should be enum
9188 uint8_t action = 4;
9189 uint32_t value = 0;
9191 // Need to check we only have 1 of inc/dec/set and get the value from the selected option
9192 int optionsprovided = 0;
9194 if (incval != -1) {
9195 optionsprovided++;
9196 action = 0;
9197 if ((incval <= 0) || (incval > 2147483647)) {
9198 PrintAndLogEx(WARNING, "increment value must be between 1 and 2147483647. Got %lli", incval);
9199 return PM3_EINVARG;
9200 } else
9201 value = (uint32_t)incval;
9204 if (decval != -1) {
9205 optionsprovided++;
9206 action = 1;
9207 if ((decval <= 0) || (decval > 2147483647)) {
9208 PrintAndLogEx(WARNING, "decrement value must be between 1 and 2147483647. Got %lli", decval);
9209 return PM3_EINVARG;
9210 } else
9211 value = (uint32_t)decval;
9214 if (setval != 0x7FFFFFFFFFFFFFFF) {
9215 optionsprovided++;
9216 action = 3;
9217 if ((setval < -2147483647) || (setval > 2147483647)) {
9218 PrintAndLogEx(WARNING, "set value must be between -2147483647 and 2147483647. Got %lli", setval);
9219 return PM3_EINVARG;
9220 } else
9221 value = (uint32_t)setval;
9224 if (resval) {
9225 if (trnval == -1) {
9226 PrintAndLogEx(WARNING, "You can't use restore without using transfer");
9227 return PM3_EINVARG;
9230 optionsprovided++;
9231 action = 2;
9234 if (dlen != 0) {
9235 optionsprovided++;
9236 action = 5;
9237 if (dlen != 16) {
9238 PrintAndLogEx(WARNING, "date length must be 16 hex bytes long, got %d", dlen);
9239 return PM3_EINVARG;
9243 if (optionsprovided > 1) {
9244 PrintAndLogEx(WARNING, "must have one and only one of --inc, --dec, --set or --data");
9245 return PM3_EINVARG;
9248 if (trnval != -1 && action > 2) {
9249 PrintAndLogEx(WARNING, "You can't use transfer without using --inc, --dec or --res");
9250 return PM3_EINVARG;
9253 if (trnval != -1 && transferkeylen == 0 && mfSectorNum(trnval) != mfSectorNum(blockno)) {
9254 PrintAndLogEx(WARNING, "Transfer is preformed to other sector, but no key for new sector provided");
9255 return PM3_EINVARG;
9258 // don't want to write value data and break something
9259 if ((blockno == 0) ||
9260 (mfIsSectorTrailer(blockno)) ||
9261 (trnval == 0) ||
9262 (trnval != -1 && mfIsSectorTrailer(trnval))) {
9263 PrintAndLogEx(WARNING, "invalid block number, should be a data block");
9264 return PM3_EINVARG;
9267 if (action < 4) {
9269 uint8_t isok = true;
9270 if (g_session.pm3_present == false)
9271 return PM3_ENOTTY;
9273 // 0 Increment, 1 - Decrement, 2 - Restore, 3 - Set, 4 - Get, 5 - Decode from data
9274 if (action <= 2) {
9276 uint8_t block[MFBLOCK_SIZE] = {0x00};
9277 memcpy(block, (uint8_t *)&value, 4);
9279 uint8_t cmddata[34];
9280 memcpy(cmddata, key, sizeof(key));
9281 // Key == 6 data went to 10, so lets offset 9 for inc/dec
9283 if (action == 0) {
9284 PrintAndLogEx(INFO, "Value incremented by : %d", (int32_t)value);
9286 if (action == 1) {
9287 PrintAndLogEx(INFO, "Value decremented by : %d", (int32_t)value);
9290 // 00 if increment, 01 if decrement, 02 if restore
9291 cmddata[9] = action;
9293 if (trnval != -1) {
9295 // transfer to block
9296 cmddata[10] = trnval;
9298 memcpy(cmddata + 27, transferkey, sizeof(transferkey));
9299 if (mfSectorNum(trnval) != mfSectorNum(blockno)) {
9300 cmddata[33] = 1; // should send nested auth
9302 PrintAndLogEx(INFO, "Transfer block no %u to block %" PRId64, blockno, trnval);
9304 } else {
9305 cmddata[10] = 0;
9306 PrintAndLogEx(INFO, "Writing block no %u, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key)));
9309 memcpy(cmddata + 11, block, sizeof(block));
9311 clearCommandBuffer();
9312 SendCommandMIX(CMD_HF_MIFARE_VALUE, blockno, keytype, transferkeytype, cmddata, sizeof(cmddata));
9314 PacketResponseNG resp;
9315 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
9316 PrintAndLogEx(FAILED, "command execution time out");
9317 return PM3_ETIMEOUT;
9319 isok = resp.oldarg[0] & 0xff;
9320 } else { // set value
9321 // To set a value block (or setup) we can use the normal mifare classic write block
9322 // So build the command options can call CMD_HF_MIFARE_WRITEBL
9323 PrintAndLogEx(INFO, "set value to : %d", (int32_t)value);
9325 uint8_t writedata[26] = {0x00};
9326 int32_t invertvalue = value ^ 0xFFFFFFFF;
9327 memcpy(writedata, key, sizeof(key));
9328 memcpy(writedata + 10, (uint8_t *)&value, 4);
9329 memcpy(writedata + 14, (uint8_t *)&invertvalue, 4);
9330 memcpy(writedata + 18, (uint8_t *)&value, 4);
9331 writedata[22] = blockno;
9332 writedata[23] = (blockno ^ 0xFF);
9333 writedata[24] = blockno;
9334 writedata[25] = (blockno ^ 0xFF);
9336 clearCommandBuffer();
9337 SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, keytype, 0, writedata, sizeof(writedata));
9339 PacketResponseNG resp;
9340 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
9341 PrintAndLogEx(FAILED, "command execution time out");
9342 return PM3_ETIMEOUT;
9345 isok = resp.oldarg[0] & 0xff;
9348 if (isok) {
9349 PrintAndLogEx(SUCCESS, "Update ... : " _GREEN_("success"));
9350 getval = true;
9351 // all ok so set flag to read current value
9352 } else {
9353 PrintAndLogEx(FAILED, "Update ... : " _RED_("failed"));
9357 // If all went well getval will be true, so read the current value and display
9358 if (getval) {
9359 int32_t readvalue;
9360 int res = -1;
9362 if (action == 5) {
9363 res = PM3_SUCCESS;
9364 // already have data from command line
9365 } else {
9366 if (trnval == -1) {
9367 res = mfReadBlock(blockno, keytype, key, data);
9368 } else {
9369 if (mfSectorNum(trnval) != mfSectorNum(blockno))
9370 res = mfReadBlock(trnval, transferkeytype, transferkey, data);
9371 else
9372 res = mfReadBlock(trnval, keytype, key, data);
9376 if (res == PM3_SUCCESS) {
9377 if (mfc_value(data, &readvalue)) {
9378 PrintAndLogEx(SUCCESS, "Dec ...... : " _YELLOW_("%" PRIi32), readvalue);
9379 PrintAndLogEx(SUCCESS, "Hex ...... : " _YELLOW_("0x%" PRIX32), readvalue);
9380 } else {
9381 PrintAndLogEx(FAILED, "No value block detected");
9383 } else {
9384 PrintAndLogEx(FAILED, "failed to read value block");
9388 return PM3_SUCCESS;
9391 static int CmdHFMFHidEncode(const char *Cmd) {
9392 CLIParserContext *ctx;
9393 CLIParserInit(&ctx, "hf mf encodehid",
9394 "Encode binary wiegand to card\n"
9395 "Use either --bin or --wiegand/--fc/--cn",
9396 "hf mf encodehid --bin 10001111100000001010100011 -> FC 31 CN 337 (H10301)\n"
9397 "hf mf encodehid -w H10301 --fc 31 --cn 337\n"
9400 void *argtable[] = {
9401 arg_param_begin,
9402 arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
9403 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
9404 arg_u64_0(NULL, "cn", "<dec>", "card number"),
9405 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
9406 arg_lit0("v", "verbose", "verbose output"),
9407 arg_param_end
9409 CLIExecWithReturn(ctx, Cmd, argtable, false);
9411 uint8_t bin[121] = {0};
9412 int bin_len = sizeof(bin) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated
9413 CLIGetStrWithReturn(ctx, 1, bin, &bin_len);
9415 wiegand_card_t card;
9416 memset(&card, 0, sizeof(wiegand_card_t));
9417 card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
9418 card.CardNumber = arg_get_u32_def(ctx, 3, 0);
9420 char format[16] = {0};
9421 int format_len = 0;
9422 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)format, sizeof(format), &format_len);
9424 bool verbose = arg_get_lit(ctx, 5);
9425 CLIParserFree(ctx);
9427 // santity checks
9428 if (bin_len > 120) {
9429 PrintAndLogEx(ERR, "Binary wiegand string must be less than 120 bits");
9430 return PM3_EINVARG;
9433 if (bin_len == 0 && card.FacilityCode == 0 && card.CardNumber == 0) {
9434 PrintAndLogEx(ERR, "Must provide either --cn/--fc or --bin");
9435 return PM3_EINVARG;
9438 uint8_t blocks[] = {
9439 0x1B, 0x01, 0x4D, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9441 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0x89, 0xEC, 0xA9, 0x7F, 0x8C, 0x2A,
9442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9443 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9445 0x48, 0x49, 0x44, 0x20, 0x49, 0x53, 0x78, 0x77, 0x88, 0xAA, 0x20, 0x47, 0x52, 0x45, 0x41, 0x54,
9448 if (bin_len) {
9449 char mfcbin[121] = {0};
9450 mfcbin[0] = '1';
9451 memcpy(mfcbin + 1, bin, bin_len);
9453 size_t hexlen = 0;
9454 uint8_t hex[15] = {0};
9455 binstr_2_bytes(hex, &hexlen, mfcbin);
9457 memcpy(blocks + (MFBLOCK_SIZE * 4) + 1 + (15 - hexlen), hex, hexlen);
9458 } else {
9459 wiegand_message_t packed;
9460 memset(&packed, 0, sizeof(wiegand_message_t));
9462 int format_idx = HIDFindCardFormat(format);
9463 if (format_idx == -1) {
9464 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
9465 return PM3_EINVARG;
9468 if (HIDPack(format_idx, &card, &packed, false) == false) {
9469 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
9470 return PM3_ESOFT;
9473 // iceman: only for formats w length smaller than 37.
9474 // Needs a check.
9476 // increase length to allow setting bit just above real data
9477 packed.Length++;
9478 // Set sentinel bit
9479 set_bit_by_position(&packed, true, 0);
9481 #ifdef HOST_LITTLE_ENDIAN
9482 packed.Mid = BSWAP_32(packed.Mid);
9483 packed.Bot = BSWAP_32(packed.Bot);
9484 #endif
9486 memcpy(blocks + (MFBLOCK_SIZE * 4) + 8, &packed.Mid, sizeof(packed.Mid));
9487 memcpy(blocks + (MFBLOCK_SIZE * 4) + 12, &packed.Bot, sizeof(packed.Bot));
9490 uint8_t empty[MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
9491 bool res = true;
9492 for (uint8_t i = 0; i < (sizeof(blocks) / MFBLOCK_SIZE); i++) {
9494 if (verbose) {
9495 PrintAndLogEx(INFO, "Writing %u - %s", (i + 1), sprint_hex_inrow(blocks + (i * MFBLOCK_SIZE), MFBLOCK_SIZE));
9498 if (mf_write_block(empty, MF_KEY_A, (i + 1), blocks + (i * MFBLOCK_SIZE)) == false) {
9499 if (mf_write_block(empty, MF_KEY_B, (i + 1), blocks + (i * MFBLOCK_SIZE)) == false) {
9500 PrintAndLogEx(WARNING, "failed writing block %d using default empty key", (i + 1));
9501 res = false;
9502 break;
9506 if (res == false) {
9507 PrintAndLogEx(WARNING, "Make sure card is wiped before running this command");
9509 PrintAndLogEx(NORMAL, "");
9510 return PM3_SUCCESS;
9513 static int CmdHF14AMfInfo(const char *Cmd) {
9514 CLIParserContext *ctx;
9515 CLIParserInit(&ctx, "hf mf info",
9516 "Information and check vulnerabilities in a MIFARE Classic card\n"
9517 "Some cards in order to extract information you need to specify key\n"
9518 "and/or specific keys in the command line",
9519 "hf mf info\n"
9520 "hf mf info -k FFFFFFFFFFFF -n -v\n"
9523 void *argtable[] = {
9524 arg_param_begin,
9525 arg_int0(NULL, "blk", "<dec>", "block number"),
9526 arg_lit0("a", NULL, "input key type is key A (def)"),
9527 arg_lit0("b", NULL, "input key type is key B"),
9528 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9529 arg_lit0("n", "nack", "do nack test"),
9530 arg_lit0("v", "verbose", "verbose output"),
9531 arg_param_end
9533 CLIExecWithReturn(ctx, Cmd, argtable, true);
9535 int blockn = arg_get_int_def(ctx, 1, 0);
9537 uint8_t keytype = MF_KEY_A;
9538 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
9539 CLIParserFree(ctx);
9540 PrintAndLogEx(WARNING, "Choose one single input key type");
9541 return PM3_EINVARG;
9542 } else if (arg_get_lit(ctx, 3)) {
9543 keytype = MF_KEY_B;
9546 int keylen = 0;
9547 uint8_t key[100 * MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
9548 CLIGetHexWithReturn(ctx, 4, key, &keylen);
9550 bool do_nack_test = arg_get_lit(ctx, 5);
9551 bool verbose = arg_get_lit(ctx, 6);
9552 CLIParserFree(ctx);
9554 uint8_t dbg_curr = DBG_NONE;
9555 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
9556 return PM3_EFAILED;
9559 if (keylen != 0 && keylen != MIFARE_KEY_SIZE) {
9560 PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE);
9561 return PM3_EINVARG;
9564 clearCommandBuffer();
9565 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
9566 PacketResponseNG resp;
9567 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
9568 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
9569 return 0;
9572 iso14a_card_select_t card;
9573 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
9576 0: couldn't read
9577 1: OK, with ATS
9578 2: OK, no ATS
9579 3: proprietary Anticollision
9581 uint64_t select_status = resp.oldarg[0];
9583 if (select_status == 0) {
9584 PrintAndLogEx(DEBUG, "iso14443a card select failed");
9585 return select_status;
9588 if (select_status == 3) {
9589 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
9591 if (verbose) {
9592 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
9594 return select_status;
9597 PrintAndLogEx(NORMAL, "");
9598 PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " ---------------------");
9599 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
9600 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
9601 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
9603 if (setDeviceDebugLevel(verbose ? MAX(dbg_curr, DBG_INFO) : DBG_NONE, false) != PM3_SUCCESS) {
9604 return PM3_EFAILED;
9607 uint8_t signature[32] = {0};
9608 int res = read_mfc_ev1_signature(signature);
9609 if (res == PM3_SUCCESS) {
9610 mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
9613 PrintAndLogEx(NORMAL, "");
9614 PrintAndLogEx(INFO, "--- " _CYAN_("Keys Information"));
9616 uint8_t fkey[MIFARE_KEY_SIZE] = {0};
9617 uint8_t fKeyType = 0xff;
9619 uint64_t tmpkey = 0;
9620 mfc_algo_saflok_one(card.uid, 0, MF_KEY_A, &tmpkey);
9621 num_to_bytes(tmpkey, MIFARE_KEY_SIZE, key + MIFARE_KEY_SIZE);
9623 int sectorsCnt = 2;
9624 uint8_t *keyBlock = NULL;
9625 uint32_t keycnt = 0;
9626 res = mf_load_keys(&keyBlock, &keycnt, key, MIFARE_KEY_SIZE * 2, NULL, 0, true);
9627 if (res != PM3_SUCCESS) {
9628 return res;
9631 // create/initialize key storage structure
9632 sector_t *e_sector = NULL;
9633 if (initSectorTable(&e_sector, sectorsCnt) != PM3_SUCCESS) {
9634 free(keyBlock);
9635 return PM3_EMALLOC;
9638 uint8_t blockdata[MFBLOCK_SIZE] = {0};
9639 res = mfCheckKeys_fast(sectorsCnt, true, true, 1, keycnt, keyBlock, e_sector, false, verbose);
9640 if (res == PM3_SUCCESS || res == PM3_EPARTIAL) {
9642 if (e_sector[0].foundKey[MF_KEY_A]) {
9643 PrintAndLogEx(SUCCESS, "Sector 0 key A... " _GREEN_("%012" PRIX64), e_sector[0].Key[MF_KEY_A]);
9645 num_to_bytes(e_sector[0].Key[MF_KEY_A], MIFARE_KEY_SIZE, fkey);
9646 if (mfReadBlock(0, MF_KEY_A, key, blockdata) == PM3_SUCCESS) {
9647 fKeyType = MF_KEY_A;
9651 if (e_sector[0].foundKey[MF_KEY_B]) {
9652 PrintAndLogEx(SUCCESS, "Sector 0 key B... " _GREEN_("%012" PRIX64), e_sector[0].Key[MF_KEY_B]);
9654 if (fKeyType == 0xFF) {
9655 num_to_bytes(e_sector[0].Key[MF_KEY_B], MIFARE_KEY_SIZE, fkey);
9656 if (mfReadBlock(0, MF_KEY_B, key, blockdata) == PM3_SUCCESS) {
9657 fKeyType = MF_KEY_B;
9662 if (e_sector[1].foundKey[MF_KEY_A]) {
9663 PrintAndLogEx(SUCCESS, "Sector 1 key A... " _GREEN_("%012" PRIX64), e_sector[1].Key[MF_KEY_A]);
9667 uint8_t k08s[6] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
9668 uint8_t k08[6] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
9669 uint8_t k32[6] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60};
9670 if (mfReadBlock(0, 4, k08s, blockdata) == PM3_SUCCESS) {
9671 PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s)));
9672 fKeyType = MF_KEY_BD08S;
9673 } else if (mfReadBlock(0, 4, k08, blockdata) == PM3_SUCCESS) {
9674 PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08, sizeof(k08)));
9675 fKeyType = MF_KEY_BD08;
9676 } else if (mfReadBlock(0, 4, k32, blockdata) == PM3_SUCCESS) {
9677 PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k32, sizeof(k32)));
9678 fKeyType = MF_KEY_BD32;
9681 if (fKeyType != 0xFF) {
9682 PrintAndLogEx(SUCCESS, "Block 0.......... %s", sprint_hex_ascii(blockdata, MFBLOCK_SIZE));
9685 PrintAndLogEx(NORMAL, "");
9686 PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
9688 if (fKeyType != 0xFF) {
9689 // cards with known backdoor
9690 if (card.sak != 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) {
9691 // backdoor might be present, or just a clone reusing Fudan MF data...
9692 PrintAndLogEx(SUCCESS, "Fudan based card");
9693 } else if (fKeyType == MF_KEY_BD08S && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
9694 && (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x90) {
9695 PrintAndLogEx(SUCCESS, "Fudan FM11RF08S");
9696 } else if (fKeyType == MF_KEY_BD08S && card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x03\x00\x10", 4) == 0
9697 && blockdata[15] == 0x90) {
9698 PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B");
9699 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
9700 && blockdata[15] == 0x98) {
9701 PrintAndLogEx(SUCCESS, "Fudan FM11RF08S **98");
9702 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
9703 && (blockdata[8] >= 0x01 && blockdata[8] <= 0x03) && blockdata[15] == 0x1D) {
9704 PrintAndLogEx(SUCCESS, "Fudan FM11RF08");
9705 } else if (fKeyType == MF_KEY_BD32 && card.sak == 0x18 && memcmp(blockdata + 5, "\x18\x02\x00\x46\x44\x53\x37\x30\x56\x30\x31", 11) == 0) {
9706 PrintAndLogEx(SUCCESS, "Fudan FM11RF32");
9707 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x20 && memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) {
9708 PrintAndLogEx(SUCCESS, "Fudan FM11RF32 (SAK=20)");
9709 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x28 && memcmp(blockdata + 5, "\x28\x04\x00\x90\x10\x15\x01\x00\x00\x00\x00", 11) == 0) {
9710 // Note: it also has ATS =
9711 // 10 78 80 90 02 20 90 00 00 00 00 00 + UID + CRC
9712 PrintAndLogEx(SUCCESS, "Fudan FM1208-10");
9713 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x88 && memcmp(blockdata + 5, "\x88\x04\x00\x43", 4) == 0) {
9714 PrintAndLogEx(SUCCESS, "Infineon SLE66R35");
9715 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x44", 4) == 0) {
9716 PrintAndLogEx(SUCCESS, "NXP MF1ICS5003");
9717 } else if (fKeyType == MF_KEY_BD08 && card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x45", 4) == 0) {
9718 PrintAndLogEx(SUCCESS, "NXP MF1ICS5004");
9719 } else if (fKeyType == MF_KEY_BD08 || fKeyType == MF_KEY_BD08S || fKeyType == MF_KEY_BD32) {
9720 PrintAndLogEx(SUCCESS, _RED_("Unknown card with backdoor, please report details!"));
9721 } else
9722 // other cards
9723 if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x46", 4) == 0) {
9724 PrintAndLogEx(SUCCESS, "NXP MF1ICS5005");
9725 } else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x47", 4) == 0) {
9726 PrintAndLogEx(SUCCESS, "NXP MF1ICS5006");
9727 } else if (card.sak == 0x09 && memcmp(blockdata + 5, "\x89\x04\x00\x47", 4) == 0) {
9728 PrintAndLogEx(SUCCESS, "NXP MF1ICS2006");
9729 } else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x48", 4) == 0) {
9730 PrintAndLogEx(SUCCESS, "NXP MF1ICS5007");
9731 } else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\xc0", 4) == 0) {
9732 PrintAndLogEx(SUCCESS, "NXP MF1ICS5035");
9733 } else {
9734 PrintAndLogEx(SUCCESS, "unknown");
9737 if (e_sector[1].foundKey[MF_KEY_A] && (e_sector[1].Key[MF_KEY_A] == 0x2A2C13CC242A)) {
9738 PrintAndLogEx(SUCCESS, "Dorma Kaba SAFLOK detected");
9741 } else {
9742 PrintAndLogEx(INFO, "<n/a>");
9745 PrintAndLogEx(NORMAL, "");
9746 PrintAndLogEx(INFO, "--- " _CYAN_("Magic Tag Information"));
9747 if (detect_mf_magic(true, MF_KEY_B, e_sector[0].Key[MF_KEY_B]) == MAGIC_FLAG_NONE) {
9748 if (detect_mf_magic(true, MF_KEY_A, e_sector[0].Key[MF_KEY_A]) == MAGIC_FLAG_NONE) {
9749 PrintAndLogEx(INFO, "<n/a>");
9753 free(keyBlock);
9754 free(e_sector);
9756 PrintAndLogEx(NORMAL, "");
9757 PrintAndLogEx(INFO, "--- " _CYAN_("PRNG Information"));
9759 res = detect_classic_static_nonce();
9760 if (res == NONCE_STATIC) {
9761 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
9765 if (res == NONCE_NORMAL) {
9766 // not static
9767 res = detect_classic_prng();
9768 if (res == 1) {
9769 PrintAndLogEx(SUCCESS, "Prng....... " _GREEN_("weak"));
9770 } else if (res == 0) {
9771 PrintAndLogEx(SUCCESS, "Prng....... " _YELLOW_("hard"));
9772 } else {
9773 PrintAndLogEx(FAILED, "Prng........ " _RED_("fail"));
9776 // detect static encrypted nonce
9777 if (keylen == MIFARE_KEY_SIZE) {
9778 res = detect_classic_static_encrypted_nonce(blockn, keytype, key);
9779 if (res == NONCE_STATIC) {
9780 PrintAndLogEx(SUCCESS, "Static nonce... " _YELLOW_("yes"));
9781 fKeyType = 0xFF; // dont detect twice
9783 if (res == NONCE_STATIC_ENC) {
9784 PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes"));
9785 fKeyType = 0xFF; // dont detect twice
9789 if (fKeyType != 0xFF) {
9790 res = detect_classic_static_encrypted_nonce(0, fKeyType, fkey);
9791 if (res == NONCE_STATIC) {
9792 PrintAndLogEx(SUCCESS, "Static nonce... " _YELLOW_("yes"));
9795 if (res == NONCE_STATIC_ENC) {
9796 PrintAndLogEx(SUCCESS, "Static enc nonce... " _RED_("yes"));
9800 if (do_nack_test) {
9801 detect_classic_nackbug(verbose);
9805 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
9806 return PM3_EFAILED;
9809 PrintAndLogEx(NORMAL, "");
9810 return PM3_SUCCESS;
9813 static int CmdHF14AMfISEN(const char *Cmd) {
9814 CLIParserContext *ctx;
9815 CLIParserInit(&ctx, "hf mf isen",
9816 "Information about Static Encrypted Nonce properties in a MIFARE Classic card",
9817 "hf mf isen\n"
9818 "Default behavior:\n"
9819 "auth(blk)-auth(blk2)-auth(blk2)-...\n"
9820 "Default behavior when wrong key2:\n"
9821 "auth(blk)-auth(blk2) auth(blk)-auth(blk2) ...\n"
9824 void *argtable[] = {
9825 arg_param_begin,
9826 arg_int0(NULL, "blk", "<dec>", "block number"),
9827 arg_lit0("a", NULL, "input key type is key A (def)"),
9828 arg_lit0("b", NULL, "input key type is key B"),
9829 arg_int0("c", NULL, "<dec>", "input key type is key A + offset"),
9830 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
9831 arg_int0(NULL, "blk2", "<dec>", "nested block number (default=same)"),
9832 arg_lit0(NULL, "a2", "nested input key type is key A (default=same)"),
9833 arg_lit0(NULL, "b2", "nested input key type is key B (default=same)"),
9834 arg_int0(NULL, "c2", "<dec>", "nested input key type is key A + offset"),
9835 arg_str0(NULL, "key2", "<hex>", "nested key, 6 hex bytes (default=same)"),
9836 arg_int0("n", NULL, "<dec>", "number of nonces (default=2)"),
9837 arg_lit0(NULL, "reset", "reset between attempts, even if auth was successful"),
9838 arg_lit0(NULL, "hardreset", "hard reset (RF off/on) between attempts, even if auth was successful"),
9839 arg_lit0(NULL, "addread", "auth(blk)-read(blk)-auth(blk2)"),
9840 arg_lit0(NULL, "addauth", "auth(blk)-auth(blk)-auth(blk2)"),
9841 arg_lit0(NULL, "incblk2", "auth(blk)-auth(blk2)-auth(blk2+4)-..."),
9842 arg_lit0(NULL, "corruptnrar", "corrupt {nR}{aR}, but with correct parity"),
9843 arg_lit0(NULL, "corruptnrarparity", "correct {nR}{aR}, but with corrupted parity"),
9844 arg_rem("", ""),
9845 arg_rem("FM11RF08S specific options:", "Incompatible with above options, except -k; output in JSON"),
9846 arg_lit0(NULL, "collect_fm11rf08s", "collect all nT/{nT}/par_err."),
9847 arg_lit0(NULL, "collect_fm11rf08s_with_data", "collect all nT/{nT}/par_err and data blocks."),
9848 arg_str0("f", "file", "<fn>", "Specify a filename for collected data"),
9849 arg_param_end
9851 CLIExecWithReturn(ctx, Cmd, argtable, true);
9853 int blockn = arg_get_int_def(ctx, 1, 0);
9855 uint8_t keytype = MF_KEY_A;
9856 if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) {
9857 CLIParserFree(ctx);
9858 PrintAndLogEx(WARNING, "Choose one single input key type");
9859 return PM3_EINVARG;
9860 } else if (arg_get_lit(ctx, 3)) {
9861 keytype = MF_KEY_B;
9863 uint8_t prev_keytype = keytype;
9864 keytype = arg_get_int_def(ctx, 4, keytype);
9865 if ((arg_get_lit(ctx, 2) || arg_get_lit(ctx, 3)) && (keytype != prev_keytype)) {
9866 CLIParserFree(ctx);
9867 PrintAndLogEx(WARNING, "Choose one single input key type");
9868 return PM3_EINVARG;
9871 int keylen = 0;
9872 uint8_t key[MIFARE_KEY_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
9873 CLIGetHexWithReturn(ctx, 5, key, &keylen);
9875 int blockn_nested = arg_get_int_def(ctx, 6, blockn);
9877 uint8_t keytype_nested = keytype;
9878 if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) {
9879 CLIParserFree(ctx);
9880 PrintAndLogEx(WARNING, "Choose one single nested input key type");
9881 return PM3_EINVARG;
9882 } else if (arg_get_lit(ctx, 7)) {
9883 keytype_nested = MF_KEY_A;
9884 } else if (arg_get_lit(ctx, 8)) {
9885 keytype_nested = MF_KEY_B;
9887 uint8_t prev_keytype_nested = keytype_nested;
9888 keytype_nested = arg_get_int_def(ctx, 9, keytype_nested);
9889 if ((arg_get_lit(ctx, 7) || arg_get_lit(ctx, 8)) && (keytype_nested != prev_keytype_nested)) {
9890 CLIParserFree(ctx);
9891 PrintAndLogEx(WARNING, "Choose one single nested input key type");
9892 return PM3_EINVARG;
9895 int keylen_nested = 0;
9896 uint8_t key_nested[MIFARE_KEY_SIZE];
9897 memcpy(key_nested, key, MIFARE_KEY_SIZE);
9898 CLIGetHexWithReturn(ctx, 10, key_nested, &keylen_nested);
9900 int nr_nested = arg_get_int_def(ctx, 11, 2);
9902 bool reset = arg_get_lit(ctx, 12);
9903 bool hardreset = arg_get_lit(ctx, 13);
9904 if (reset && hardreset) {
9905 CLIParserFree(ctx);
9906 PrintAndLogEx(WARNING, "Choose one single type of reset");
9907 return PM3_EINVARG;
9909 bool addread = arg_get_lit(ctx, 14);
9910 bool addauth = arg_get_lit(ctx, 15);
9911 bool incblk2 = arg_get_lit(ctx, 16);
9912 bool corruptnrar = arg_get_lit(ctx, 17);
9913 bool corruptnrarparity = arg_get_lit(ctx, 18);
9914 bool collect_fm11rf08s = arg_get_lit(ctx, 21);
9915 bool collect_fm11rf08s_with_data = arg_get_lit(ctx, 22);
9916 if (collect_fm11rf08s_with_data) {
9917 collect_fm11rf08s = 1;
9919 int fnlen = 0;
9920 char filename[FILE_PATH_SIZE] = {0};
9921 CLIParamStrToBuf(arg_get_str(ctx, 23), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
9923 CLIParserFree(ctx);
9925 uint8_t dbg_curr = DBG_NONE;
9926 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
9927 return PM3_EFAILED;
9930 if (keylen != 0 && keylen != MIFARE_KEY_SIZE) {
9931 PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE);
9932 return PM3_EINVARG;
9935 if (keylen_nested != 0 && keylen_nested != MIFARE_KEY_SIZE) {
9936 PrintAndLogEx(ERR, "Key length must be %u bytes", MIFARE_KEY_SIZE);
9937 return PM3_EINVARG;
9940 clearCommandBuffer();
9941 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
9942 PacketResponseNG resp;
9943 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
9944 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
9945 return 0;
9948 iso14a_card_select_t card;
9949 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
9952 0: couldn't read
9953 1: OK, with ATS
9954 2: OK, no ATS
9955 3: proprietary Anticollision
9957 uint64_t select_status = resp.oldarg[0];
9959 if (select_status == 0) {
9960 PrintAndLogEx(DEBUG, "iso14443a card select failed");
9961 return select_status;
9964 if (select_status == 3) {
9965 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
9968 if (collect_fm11rf08s) {
9969 uint32_t flags = collect_fm11rf08s_with_data;
9970 SendCommandMIX(CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES, flags, 0, 0, key, sizeof(key));
9971 if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) {
9972 if (resp.status == PM3_ESOFT) {
9973 return NONCE_FAIL;
9976 uint8_t num_sectors = MIFARE_1K_MAXSECTOR + 1;
9977 iso14a_fm11rf08s_nonces_with_data_t nonces_dump = {0};
9978 for (uint8_t sec = 0; sec < num_sectors; sec++) {
9979 // reconstruct full nt
9980 uint32_t nt;
9981 nt = bytes_to_num(resp.data.asBytes + ((sec * 2) * 8), 2);
9982 nt = nt << 16 | prng_successor(nt, 16);
9983 num_to_bytes(nt, 4, nonces_dump.nt[sec][0]);
9984 nt = bytes_to_num(resp.data.asBytes + (((sec * 2) + 1) * 8), 2);
9985 nt = nt << 16 | prng_successor(nt, 16);
9986 num_to_bytes(nt, 4, nonces_dump.nt[sec][1]);
9988 for (uint8_t sec = 0; sec < num_sectors; sec++) {
9989 memcpy(nonces_dump.nt_enc[sec][0], resp.data.asBytes + ((sec * 2) * 8) + 4, 4);
9990 memcpy(nonces_dump.nt_enc[sec][1], resp.data.asBytes + (((sec * 2) + 1) * 8) + 4, 4);
9992 for (uint8_t sec = 0; sec < num_sectors; sec++) {
9993 nonces_dump.par_err[sec][0] = resp.data.asBytes[((sec * 2) * 8) + 2];
9994 nonces_dump.par_err[sec][1] = resp.data.asBytes[(((sec * 2) + 1) * 8) + 2];
9996 if (collect_fm11rf08s_with_data) {
9997 int bytes = MIFARE_1K_MAXBLOCK * MFBLOCK_SIZE;
9999 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
10000 if (dump == NULL) {
10001 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
10002 return PM3_EFAILED;
10004 if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
10005 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
10006 free(dump);
10007 return PM3_ETIMEOUT;
10009 for (uint8_t blk = 0; blk < MIFARE_1K_MAXBLOCK; blk++) {
10010 memcpy(nonces_dump.blocks[blk], dump + blk * MFBLOCK_SIZE, MFBLOCK_SIZE);
10012 free(dump);
10014 if (fnlen == 0) {
10015 snprintf(filename, sizeof(filename), "hf-mf-%s-nonces%s", sprint_hex_inrow(card.uid, card.uidlen), collect_fm11rf08s_with_data ? "_with_data" : "");
10017 if (pm3_save_fm11rf08s_nonces(filename, &nonces_dump, collect_fm11rf08s_with_data) != PM3_SUCCESS) {
10018 return PM3_EFAILED;
10020 return PM3_SUCCESS;
10023 PrintAndLogEx(NORMAL, "");
10024 PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") " ---------------------");
10025 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
10026 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
10027 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
10029 // if (setDeviceDebugLevel(DBG_DEBUG, false) != PM3_SUCCESS) {
10030 if (setDeviceDebugLevel(DBG_EXTENDED, false) != PM3_SUCCESS) {
10031 return PM3_EFAILED;
10034 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);
10035 if (res == NONCE_STATIC)
10036 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
10037 if (res == NONCE_STATIC_ENC)
10038 PrintAndLogEx(SUCCESS, "Static enc nonce..... " _RED_("yes"));
10040 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
10041 return PM3_EFAILED;
10044 PrintAndLogEx(NORMAL, "");
10045 return PM3_SUCCESS;
10048 static command_t CommandTable[] = {
10049 {"help", CmdHelp, AlwaysAvailable, "This help"},
10050 {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
10051 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -----------------------"},
10052 {"info", CmdHF14AMfInfo, IfPm3Iso14443a, "mfc card Info"},
10053 {"isen", CmdHF14AMfISEN, IfPm3Iso14443a, "mfc card Info Static Encrypted Nonces"},
10054 {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"},
10055 {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"},
10056 {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"},
10057 {"staticnested", CmdHF14AMfNestedStatic, IfPm3Iso14443a, "Nested attack against static nonce MIFARE Classic cards"},
10058 {"brute", CmdHF14AMfSmartBrute, IfPm3Iso14443a, "Smart bruteforce to exploit weak key generators"},
10059 {"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"},
10060 // {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"},
10061 {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"},
10062 {"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"},
10063 {"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"},
10064 {"decrypt", CmdHf14AMfDecryptBytes, AlwaysAvailable, "Decrypt Crypto1 data from sniff or trace"},
10065 {"supercard", CmdHf14AMfSuperCard, IfPm3Iso14443a, "Extract info from a `super card`"},
10066 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
10067 {"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"},
10068 {"acl", CmdHF14AMfAcl, AlwaysAvailable, "Decode and print MIFARE Classic access rights bytes"},
10069 {"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE Classic tag to binary file"},
10070 {"mad", CmdHF14AMfMAD, AlwaysAvailable, "Checks and prints MAD"},
10071 {"personalize", CmdHFMFPersonalize, IfPm3Iso14443a, "Personalize UID (MIFARE Classic EV1 only)"},
10072 {"rdbl", CmdHF14AMfRdBl, IfPm3Iso14443a, "Read MIFARE Classic block"},
10073 {"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"},
10074 {"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to tag"},
10075 {"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"},
10076 {"value", CmdHF14AMfValue, AlwaysAvailable, "Value blocks"},
10077 {"view", CmdHF14AMfView, AlwaysAvailable, "Display content from tag dump file"},
10078 {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"},
10079 {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"},
10080 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
10081 {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"},
10082 {"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill emulator memory with help of keys from emulator"},
10083 {"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear emulator memory"},
10084 {"egetblk", CmdHF14AMfEGetBlk, IfPm3Iso14443a, "Get emulator memory block"},
10085 {"egetsc", CmdHF14AMfEGetSc, IfPm3Iso14443a, "Get emulator memory sector"},
10086 {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from emulator memory"},
10087 {"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Upload file into emulator memory"},
10088 {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save emulator memory to file"},
10089 {"esetblk", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"},
10090 {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emulator memory"},
10091 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"},
10092 {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block from card"},
10093 {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector from card"},
10094 {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump to card"},
10095 {"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from card into file or emulator"},
10096 {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block to card"},
10097 {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID on card"},
10098 {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "View card"},
10099 {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"},
10100 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"},
10101 {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"},
10102 {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"},
10103 {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"},
10104 {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"},
10105 {"ginfo", CmdHF14AGen4Info, IfPm3Iso14443a, "Info about configuration of the card"},
10106 {"ggetblk", CmdHF14AGen4GetBlk, IfPm3Iso14443a, "Read block from card"},
10107 {"gload", CmdHF14AGen4Load, IfPm3Iso14443a, "Load dump to card"},
10108 {"gsave", CmdHF14AGen4Save, IfPm3Iso14443a, "Save dump from card into file or emulator"},
10109 {"gsetblk", CmdHF14AGen4SetBlk, IfPm3Iso14443a, "Write block to card"},
10110 {"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"},
10111 {"gchpwd", CmdHF14AGen4ChangePwd, IfPm3Iso14443a, "Change card access password. Warning!"},
10112 {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GDM") " --------------------------"},
10113 {"gdmcfg", CmdHF14AGen4_GDM_Cfg, IfPm3Iso14443a, "Read config block from card"},
10114 {"gdmsetcfg", CmdHF14AGen4_GDM_SetCfg, IfPm3Iso14443a, "Write config block to card"},
10115 {"gdmparsecfg", CmdHF14AGen4_GDM_ParseCfg, AlwaysAvailable, "Parse config block to card"},
10116 {"gdmsetblk", CmdHF14AGen4_GDM_SetBlk, IfPm3Iso14443a, "Write block to card"},
10117 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("ndef") " -----------------------"},
10118 // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"},
10119 {"ndefformat", CmdHFMFNDEFFormat, IfPm3Iso14443a, "Format MIFARE Classic Tag as NFC Tag"},
10120 {"ndefread", CmdHFMFNDEFRead, IfPm3Iso14443a, "Read and print NDEF records from card"},
10121 {"ndefwrite", CmdHFMFNDEFWrite, IfPm3Iso14443a, "Write NDEF records to card"},
10122 {"encodehid", CmdHFMFHidEncode, IfPm3Iso14443a, "Encode a HID Credential / NDEF record to card"},
10123 {NULL, NULL, NULL, NULL}
10127 static int CmdHelp(const char *Cmd) {
10128 (void)Cmd; // Cmd is not used so far
10129 CmdsHelp(CommandTable);
10130 return PM3_SUCCESS;
10133 int CmdHFMF(const char *Cmd) {
10134 clearCommandBuffer();
10135 return CmdsParse(CommandTable, Cmd);