1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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 //-----------------------------------------------------------------------------
17 //-----------------------------------------------------------------------------
20 #include "cliparser.h"
22 #include "cmdparser.h"
28 #include "cmdhfst25ta.h"
29 #include "cmdhfthinfilm.h"
30 #include "cmdhftopaz.h"
32 #include "fileutils.h"
33 #include "mifare/mifaredefault.h"
34 #include "mifare/mad.h"
36 void print_type4_cc_info(uint8_t *d
, uint8_t n
) {
38 PrintAndLogEx(WARNING
, "Not enough bytes read from CC file");
42 PrintAndLogEx(NORMAL
, "");
43 PrintAndLogEx(SUCCESS
, "------------ " _CYAN_("Capability Container file") " ------------");
44 PrintAndLogEx(SUCCESS
, " Version... %s ( " _GREEN_("0x%02X") " )", (d
[2] == 0x20) ? "v2.0" : "v1.0", d
[2]);
45 PrintAndLogEx(SUCCESS
, " Len....... %u bytes ( " _GREEN_("0x%02X") " )", d
[1], d
[1]);
46 uint16_t maxr
= (d
[3] << 8 | d
[4]);
47 PrintAndLogEx(SUCCESS
, " Max bytes read %u bytes ( 0x%04X )", maxr
, maxr
);
48 uint16_t maxw
= (d
[5] << 8 | d
[6]);
49 PrintAndLogEx(SUCCESS
, " Max bytes write %u bytes ( 0x%04X )", maxw
, maxw
);
50 PrintAndLogEx(NORMAL
, "");
51 PrintAndLogEx(SUCCESS
, " NDEF file control TLV");
52 PrintAndLogEx(SUCCESS
, " (t) type of file.... %02X", d
[7]);
53 PrintAndLogEx(SUCCESS
, " (v) ................ %02X", d
[8]);
54 PrintAndLogEx(SUCCESS
, " file id............. %02X%02X", d
[9], d
[10]);
56 uint16_t maxndef
= (d
[11] << 8 | d
[12]);
57 PrintAndLogEx(SUCCESS
, " Max NDEF filesize... %u bytes ( 0x%04X )", maxndef
, maxndef
);
58 PrintAndLogEx(SUCCESS
, " " _CYAN_("Access rights"));
59 PrintAndLogEx(SUCCESS
, " read ( %02X ) protection: %s", d
[13], ((d
[13] & 0x80) == 0x80) ? _RED_("enabled") : _GREEN_("disabled"));
60 PrintAndLogEx(SUCCESS
, " write ( %02X ) protection: %s", d
[14], ((d
[14] & 0x80) == 0x80) ? _RED_("enabled") : _GREEN_("disabled"));
61 PrintAndLogEx(SUCCESS
, "");
62 PrintAndLogEx(SUCCESS
, "----------------- " _CYAN_("raw") " -----------------");
63 PrintAndLogEx(SUCCESS
, "%s", sprint_hex_inrow(d
, n
));
64 PrintAndLogEx(NORMAL
, "");
67 static int CmdNfcDecode(const char *Cmd
) {
70 #define MAX_NDEF_LEN 2048
73 CLIParserContext
*ctx
;
74 CLIParserInit(&ctx
, "nfc decode",
75 "Decode and print NFC Data Exchange Format (NDEF)\n"
76 "You must provide either data in hex or a filename, but not both",
77 "nfc decode -d 9101085402656e48656c6c6f5101085402656e576f726c64\n"
78 "nfc decode -d 0103d020240203e02c040300fe\n"
79 "nfc decode -f myfilename"
84 arg_str0("d", "data", "<hex>", "NDEF data to decode"),
85 arg_str0("f", "file", "<fn>", "file to load"),
86 arg_lit0("v", "verbose", "verbose output"),
89 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
92 uint8_t data
[MAX_NDEF_LEN
] = {0};
93 CLIGetHexWithReturn(ctx
, 1, data
, &datalen
);
96 char filename
[FILE_PATH_SIZE
] = {0};
97 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
99 bool verbose
= arg_get_lit(ctx
, 3);
101 if (((datalen
!= 0) && (fnlen
!= 0)) || ((datalen
== 0) && (fnlen
== 0))) {
102 PrintAndLogEx(ERR
, "You must provide either data in hex or a filename");
105 int res
= PM3_SUCCESS
;
109 uint8_t *dump
= NULL
;
110 size_t bytes_read
= 4096;
111 res
= pm3_load_dump(filename
, (void **)&dump
, &bytes_read
, 4096);
112 if (res
!= PM3_SUCCESS
|| dump
== NULL
|| bytes_read
> 4096) {
118 // if not MIFARE Classic default sizes, assume its Ultralight/NTAG
119 if (bytes_read
!= MIFARE_4K_MAX_BYTES
120 && bytes_read
!= MIFARE_2K_MAX_BYTES
121 && bytes_read
!= MIFARE_1K_MAX_BYTES
122 && bytes_read
!= MIFARE_MINI_MAX_BYTES
) {
125 mfu_df_e df
= detect_mfu_dump_format(pd
, verbose
);
126 if (df
== MFU_DF_OLDBIN
) {
127 tmp
+= OLD_MFU_DUMP_PREFIX_LENGTH
+ (4 * 4);
128 bytes_read
-= OLD_MFU_DUMP_PREFIX_LENGTH
+ (4 * 4);
129 } else if (df
== MFU_DF_NEWBIN
) {
130 tmp
+= MFU_DUMP_PREFIX_LENGTH
+ (4 * 4);
131 bytes_read
-= MFU_DUMP_PREFIX_LENGTH
+ (4 * 4);
137 // convert from MFC dump file to a pure NDEF byte array
138 if (HasMADKey(tmp
)) {
139 PrintAndLogEx(SUCCESS
, "MFC dump file detected. Converting...");
140 uint8_t ndef
[4096] = {0};
141 uint16_t ndeflen
= 0;
143 if (convert_mad_to_arr(tmp
, bytes_read
, ndef
, &ndeflen
) != PM3_SUCCESS
) {
144 PrintAndLogEx(FAILED
, "Failed converting, aborting...");
149 memcpy(tmp
, ndef
, ndeflen
);
150 bytes_read
= ndeflen
;
154 res
= NDEFDecodeAndPrint(tmp
, bytes_read
, verbose
);
155 if (res
!= PM3_SUCCESS
) {
156 PrintAndLogEx(INFO
, "Trying to parse NDEF records w/o NDEF header");
157 res
= NDEFRecordsDecodeAndPrint(tmp
, bytes_read
, verbose
);
163 res
= NDEFDecodeAndPrint(data
, datalen
, verbose
);
164 if (res
!= PM3_SUCCESS
) {
165 PrintAndLogEx(INFO
, "Trying to parse NDEF records w/o NDEF header");
166 res
= NDEFRecordsDecodeAndPrint(data
, datalen
, verbose
);
172 static int CmdNFCType1Read(const char *Cmd
) {
173 return CmdHFTopazInfo(Cmd
);
176 static int CmdNFCType1Help(const char *Cmd
);
178 static command_t CommandNFCType1Table
[] = {
180 {"--------", CmdNFCType1Help
, AlwaysAvailable
, "-------------- " _CYAN_("NFC Forum Tag Type 1") " ---------------"},
181 // {"format", CmdNFCType1Format, IfPm3Iso14443a, "format ISO-14443-a tag as NFC Tag"},
182 {"read", CmdNFCType1Read
, IfPm3Iso14443a
, "read NFC Forum Tag Type 1"},
183 // {"write", CmdNFCType1Write, IfPm3Iso14443a, "write NFC Forum Tag Type 1"},
184 {"--------", CmdNFCType1Help
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
185 {"help", CmdNFCType1Help
, AlwaysAvailable
, "This help"},
186 {NULL
, NULL
, NULL
, NULL
}
189 static int CmdNFCType1(const char *Cmd
) {
190 clearCommandBuffer();
191 return CmdsParse(CommandNFCType1Table
, Cmd
);
194 static int CmdNFCType1Help(const char *Cmd
) {
195 (void)Cmd
; // Cmd is not used so far
196 CmdsHelp(CommandNFCType1Table
);
200 static int CmdNFCType2Read(const char *Cmd
) {
201 return CmdHF14MfuNDEFRead(Cmd
);
204 static int CmdNFCType2Help(const char *Cmd
);
206 static command_t CommandNFCType2Table
[] = {
208 {"--------", CmdNFCType2Help
, AlwaysAvailable
, "-------------- " _CYAN_("NFC Forum Tag Type 2") " ---------------"},
209 // {"format", CmdNFCType2Format, IfPm3Iso14443a, "format ISO-14443-a tag as NFC Tag"},
210 {"read", CmdNFCType2Read
, IfPm3Iso14443a
, "read NFC Forum Tag Type 2"},
211 // {"write", CmdNFCType2Write, IfPm3Iso14443a, "write NFC Forum Tag Type 2"},
212 {"--------", CmdNFCType2Help
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
213 {"help", CmdNFCType2Help
, AlwaysAvailable
, "This help"},
214 {NULL
, NULL
, NULL
, NULL
}
217 static int CmdNFCType2(const char *Cmd
) {
218 clearCommandBuffer();
219 return CmdsParse(CommandNFCType2Table
, Cmd
);
222 static int CmdNFCType2Help(const char *Cmd
) {
223 (void)Cmd
; // Cmd is not used so far
224 CmdsHelp(CommandNFCType2Table
);
229 static int CmdNFCType3Read(const char *Cmd) {
230 return CmdHFFelicaXXX(Cmd);
233 static int CmdNFCType3Help(const char *Cmd);
235 static command_t CommandNFCType3Table[] = {
237 {"--------", CmdNFCType3Help, AlwaysAvailable, "-------------- " _CYAN_("NFC Forum Tag Type 3") " ---------------"},
238 // {"format", CmdNFCType3Format, IfPm3Felica, "format FeliCa tag as NFC Tag"},
239 {"read", CmdNFCType3Read, IfPm3Felica, "read NFC Forum Tag Type 3"},
240 // {"write", CmdNFCType3Write, IfPm3Felica, "write NFC Forum Tag Type 3"},
241 {"--------", CmdNFCType3Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
242 {"help", CmdNFCType3Help, AlwaysAvailable, "This help"},
243 {NULL, NULL, NULL, NULL}
246 static int CmdNFCType3(const char *Cmd) {
247 clearCommandBuffer();
248 return CmdsParse(CommandNFCType3Table, Cmd);
251 static int CmdNFCType3Help(const char *Cmd) {
252 (void)Cmd; // Cmd is not used so far
253 CmdsHelp(CommandNFCType3Table);
258 static int CmdNFCType4ARead(const char *Cmd
) {
259 return CmdHF14ANdefRead(Cmd
);
262 static int CmdNFCST25TARead(const char *Cmd
) {
263 return CmdHFST25TANdefRead(Cmd
);
266 static int CmdNFCType4AFormat(const char *Cmd
) {
267 return CmdHF14ANdefFormat(Cmd
);
270 static int CmdNFCType4AWrite(const char *Cmd
) {
271 return CmdHF14ANdefWrite(Cmd
);
274 static int CmdNFCType4AHelp(const char *Cmd
);
276 static command_t CommandNFCType4ATable
[] = {
278 {"--------", CmdNFCType4AHelp
, AlwaysAvailable
, "--------- " _CYAN_("NFC Forum Tag Type 4 ISO14443A") " ----------"},
279 {"format", CmdNFCType4AFormat
, IfPm3Iso14443a
, "format ISO-14443-a tag as NFC Tag"},
280 {"read", CmdNFCType4ARead
, IfPm3Iso14443a
, "read NFC Forum Tag Type 4 A"},
281 {"write", CmdNFCType4AWrite
, IfPm3Iso14443a
, "write NFC Forum Tag Type 4 A"},
282 // {"mfdesread", CmdNFCMFDESRead, IfPm3Iso14443a, "read NDEF from MIFARE DESfire"}, // hf mfdes ndefread
283 // {"mfdesformat", CmdNFCMFDESFormat, IfPm3Iso14443a, "format MIFARE DESfire as NFC Forum Tag Type 4"},
284 {"st25taread", CmdNFCST25TARead
, IfPm3Iso14443a
, "read ST25TA as NFC Forum Tag Type 4"},
286 {"--------", CmdNFCType4AHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
287 {"help", CmdNFCType4AHelp
, AlwaysAvailable
, "This help"},
288 {NULL
, NULL
, NULL
, NULL
}
291 static int CmdNFCType4A(const char *Cmd
) {
292 clearCommandBuffer();
293 return CmdsParse(CommandNFCType4ATable
, Cmd
);
296 static int CmdNFCType4AHelp(const char *Cmd
) {
297 (void)Cmd
; // Cmd is not used so far
298 CmdsHelp(CommandNFCType4ATable
);
302 static int CmdNFCType4BRead(const char *Cmd
) {
303 return CmdHF14BNdefRead(Cmd
);
306 static int CmdNFCType4BHelp(const char *Cmd
);
308 static command_t CommandNFCType4BTable
[] = {
310 {"--------", CmdNFCType4BHelp
, AlwaysAvailable
, "--------- " _CYAN_("NFC Forum Tag Type 4 ISO14443B") " -------------"},
311 // {"format", CmdNFCType4BFormat, IfPm3Iso14443b, "format ISO-14443-b tag as NFC Tag"},
312 {"read", CmdNFCType4BRead
, IfPm3Iso14443b
, "read NFC Forum Tag Type 4 B"},
313 // {"write", CmdNFCType4BWrite, IfPm3Iso14443b, "write NFC Forum Tag Type 4 B"},
314 {"--------", CmdNFCType4BHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
315 {"help", CmdNFCType4BHelp
, AlwaysAvailable
, "This help"},
316 {NULL
, NULL
, NULL
, NULL
}
319 static int CmdNFCType4B(const char *Cmd
) {
320 clearCommandBuffer();
321 return CmdsParse(CommandNFCType4BTable
, Cmd
);
324 static int CmdNFCType4BHelp(const char *Cmd
) {
325 (void)Cmd
; // Cmd is not used so far
326 CmdsHelp(CommandNFCType4BTable
);
331 static int CmdNFCType5Read(const char *Cmd) {
332 return CmdHF15XXX(Cmd);
335 static int CmdNFCType5Help(const char *Cmd);
337 static command_t CommandNFCType5Table[] = {
339 {"--------", CmdNFCType5Help, AlwaysAvailable, "-------------- " _CYAN_("NFC Forum Tag Type 5") " ---------------"},
340 // {"format", CmdNFCType5Format, IfPm3Iso15693, "format ISO-15693 tag as NFC Tag"},
341 {"read", CmdNFCType5Read, IfPm3Iso15693, "read NFC Forum Tag Type 5"},
342 // {"write", CmdNFCType5Write, IfPm3Iso15693, "write NFC Forum Tag Type 5"},
343 {"--------", CmdNFCType5Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
344 {"help", CmdNFCType5Help, AlwaysAvailable, "This help"},
345 {NULL, NULL, NULL, NULL}
348 static int CmdNFCType5(const char *Cmd) {
349 clearCommandBuffer();
350 return CmdsParse(CommandNFCType5Table, Cmd);
353 static int CmdNFCType5Help(const char *Cmd) {
354 (void)Cmd; // Cmd is not used so far
355 CmdsHelp(CommandNFCType5Table);
360 static int CmdNFCMFCRead(const char *Cmd
) {
361 return CmdHFMFNDEFRead(Cmd
);
364 static int CmdNFCMFCFormat(const char *Cmd
) {
365 return CmdHFMFNDEFFormat(Cmd
);
368 static int CmdNFCMFCWrite(const char *Cmd
) {
369 return CmdHFMFNDEFWrite(Cmd
);
373 static int CmdNFCMFPRead(const char *Cmd
) {
374 return CmdHFMFPNDEFRead(Cmd
);
377 static int CmdNFCMFHelp(const char *Cmd
);
379 static command_t CommandMFTable
[] = {
381 {"--------", CmdNFCMFHelp
, AlwaysAvailable
, "--------- " _CYAN_("NFC Type MIFARE Classic/Plus Tag") " --------"},
382 {"cformat", CmdNFCMFCFormat
, IfPm3Iso14443a
, "format MIFARE Classic Tag as NFC Tag"},
383 {"cread", CmdNFCMFCRead
, IfPm3Iso14443a
, "read NFC Type MIFARE Classic Tag"},
384 {"cwrite", CmdNFCMFCWrite
, IfPm3Iso14443a
, "write NFC Type MIFARE Classic Tag"},
385 {"pread", CmdNFCMFPRead
, IfPm3Iso14443a
, "read NFC Type MIFARE Plus Tag"},
386 {"--------", CmdNFCMFHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
387 {"help", CmdNFCMFHelp
, AlwaysAvailable
, "This help"},
388 {NULL
, NULL
, NULL
, NULL
}
391 static int CmdNFCMF(const char *Cmd
) {
392 clearCommandBuffer();
393 return CmdsParse(CommandMFTable
, Cmd
);
396 static int CmdNFCMFHelp(const char *Cmd
) {
397 (void)Cmd
; // Cmd is not used so far
398 CmdsHelp(CommandMFTable
);
402 static int CmdNFCBarcodeRead(const char *Cmd
) {
403 return CmdHfThinFilmInfo(Cmd
);
406 static int CmdNFCBarcodeSim(const char *Cmd
) {
407 return CmdHfThinFilmSim(Cmd
);
410 static int CmdNFCBarcodeHelp(const char *Cmd
);
412 static command_t CommandBarcodeTable
[] = {
414 {"--------", CmdNFCBarcodeHelp
, AlwaysAvailable
, "------------------ " _CYAN_("NFC Barcode") " --------------------"},
415 {"read", CmdNFCBarcodeRead
, IfPm3Iso14443a
, "read NFC Barcode"},
416 {"sim", CmdNFCBarcodeSim
, IfPm3Iso14443a
, "simulate NFC Barcode"},
417 {"--------", CmdNFCBarcodeHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
418 {"help", CmdNFCBarcodeHelp
, AlwaysAvailable
, "This help"},
419 {NULL
, NULL
, NULL
, NULL
}
422 static int CmdNFCBarcode(const char *Cmd
) {
423 clearCommandBuffer();
424 return CmdsParse(CommandBarcodeTable
, Cmd
);
427 static int CmdNFCBarcodeHelp(const char *Cmd
) {
428 (void)Cmd
; // Cmd is not used so far
429 CmdsHelp(CommandBarcodeTable
);
433 static int CmdHelp(const char *Cmd
);
435 static command_t CommandTable
[] = {
437 {"--------", CmdHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("NFC Tags") " --------------------"},
438 {"type1", CmdNFCType1
, AlwaysAvailable
, "{ NFC Forum Tag Type 1... }"},
439 {"type2", CmdNFCType2
, AlwaysAvailable
, "{ NFC Forum Tag Type 2... }"},
440 // {"type3", CmdNFCType3, AlwaysAvailable, "{ NFC Forum Tag Type 3... }"},
441 {"type4a", CmdNFCType4A
, AlwaysAvailable
, "{ NFC Forum Tag Type 4 ISO14443A... }"},
442 {"type4b", CmdNFCType4B
, AlwaysAvailable
, "{ NFC Forum Tag Type 4 ISO14443B... }"},
443 // {"type5", CmdNFCType5, AlwaysAvailable, "{ NFC Forum Tag Type 5... }"},
444 {"mf", CmdNFCMF
, AlwaysAvailable
, "{ NFC Type MIFARE Classic/Plus Tag... }"},
445 {"barcode", CmdNFCBarcode
, AlwaysAvailable
, "{ NFC Barcode Tag... }"},
446 // {"--------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("NFC peer-to-peer") " ------------"},
447 // {"isodep", CmdISODEP, AlwaysAvailable, "{ ISO-DEP protocol... }"},
448 // {"llcp", CmdNFCLLCP, AlwaysAvailable, "{ Logical Link Control Protocol... }"},
449 // {"snep", CmdNFCSNEP, AlwaysAvailable, "{ Simple NDEF Exchange Protocol... }"},
450 {"--------", CmdHelp
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
451 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
452 {"decode", CmdNfcDecode
, AlwaysAvailable
, "Decode NDEF records"},
453 // {"encode", CmdNfcEncode, AlwaysAvailable, "Encode NDEF records"},
454 {NULL
, NULL
, NULL
, NULL
}
457 int CmdNFC(const char *Cmd
) {
458 clearCommandBuffer();
459 return CmdsParse(CommandTable
, Cmd
);
462 int CmdHelp(const char *Cmd
) {
463 (void)Cmd
; // Cmd is not used so far
464 CmdsHelp(CommandTable
);