1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2012 Roel Verdult
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // Low frequency Hitag support
9 //-----------------------------------------------------------------------------
10 #include "cmdlfhitag.h"
12 #include "cmdparser.h" // command_t
15 #include "commonutil.h"
17 #include "fileutils.h" // savefile
18 #include "protocols.h" // defines
19 #include "cliparser.h"
21 static int CmdHelp(const char *Cmd
);
23 static const char *getHitagTypeStr(uint32_t uid
) {
25 uint8_t type
= (uid
>> 4) & 0xF;
49 static size_t nbytes(size_t nbits) {
50 return (nbits / 8) + ((nbits % 8) > 0);
54 static int CmdLFHitagList(const char *Cmd
) {
55 return CmdTraceListAlias(Cmd
, "lf hitag", "hitag2");
59 uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
61 PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
65 // Query for the actual size of the trace
66 PacketResponseNG response;
67 if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 2500, false)) {
68 PrintAndLogEx(WARNING, "command execution time out");
73 uint16_t traceLen = response.arg[2];
74 if (traceLen > PM3_CMD_DATA_SIZE) {
75 uint8_t *p = realloc(got, traceLen);
77 PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
82 if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) {
83 PrintAndLogEx(WARNING, "command execution time out");
89 PrintAndLogEx(NORMAL, "recorded activity (TraceLen = %d bytes):");
90 PrintAndLogEx(NORMAL, " ETU :nbits: who bytes");
91 PrintAndLogEx(NORMAL, "---------+-----+----+-----------");
95 int len = strlen(Cmd);
97 char filename[FILE_PATH_SIZE] = { 0x00 };
100 if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
102 memcpy(filename, Cmd, len);
104 if (strlen(filename) > 0) {
105 f = fopen(filename, "wb");
107 PrintAndLogEx(ERR, "Error: Could not open file [%s]", filename);
114 if (i >= traceLen) { break; }
117 int timestamp = *((uint32_t *)(got + i));
118 if (timestamp & 0x80000000) {
119 timestamp &= 0x7fffffff;
125 int parityBits = *((uint32_t *)(got + i + 4));
126 // 4 bytes of additional information...
127 // maximum of 32 additional parity bit information
130 // at each quarter bit period we can send power level (16 levels)
131 // or each half bit period in 256 levels.
133 int bits = got[i + 8];
134 int len = nbytes(got[i + 8]);
139 if (i + len > traceLen) { break;}
141 uint8_t *frame = (got + i + 9);
143 // Break and stick with current result if buffer was not completely full
144 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
146 char line[1000] = "";
148 for (j = 0; j < len; j++) {
150 //if((parityBits >> (len - j - 1)) & 0x01) {
151 if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
152 sprintf(line + (j * 4), "%02x! ", frame[j]);
154 sprintf(line + (j * 4), "%02x ", frame[j]);
158 PrintAndLogEx(NORMAL, " +%7d: %3d: %s %s",
159 (prev < 0 ? 0 : (timestamp - prev)),
161 (isResponse ? "TAG" : " "),
165 fprintf(f, " +%7d: %3d: %s %s\n",
166 (prev < 0 ? 0 : (timestamp - prev)),
168 (isResponse ? "TAG" : " "),
178 PrintAndLogEx(NORMAL, "Recorded activity successfully written to file: %s", filename);
186 static int CmdLFHitagSniff(const char *Cmd
) {
187 CLIParserContext
*ctx
;
188 CLIParserInit(&ctx
, "lf hitag sniff",
189 "Sniff traffic between Hitag reader and tag.\n"
190 "Use " _YELLOW_("`lf hitag list`")" to view collected data.",
198 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
201 clearCommandBuffer();
202 SendCommandNG(CMD_LF_HITAG_SNIFF
, NULL
, 0);
203 PrintAndLogEx(HINT
, "HINT: Try " _YELLOW_("`lf hitag list`")" to view collected data");
208 // eload , to be implemented
209 static int CmdLFHitagEload(const char *Cmd
) {
210 CLIParserContext
*ctx
;
211 CLIParserInit(&ctx
, "lf hitag eload",
212 "Loads hitag tag dump into emulator memory on device",
213 "lf hitag eload -f lf-hitag-11223344-dump.bin\n");
217 arg_str1("f", "file", "<filename>", "filename of dump"),
218 arg_lit0("1", NULL
, "simulate Hitag1"),
219 arg_lit0("2", NULL
, "simulate Hitag2"),
220 arg_lit0("s", NULL
, "simulate HitagS"),
223 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
226 char filename
[FILE_PATH_SIZE
] = {0};
227 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
229 bool use_ht1
= arg_get_lit(ctx
, 2);
230 bool use_ht2
= arg_get_lit(ctx
, 3);
231 bool use_hts
= arg_get_lit(ctx
, 4);
234 uint8_t n
= (use_ht1
+ use_ht2
+ use_hts
);
236 PrintAndLogEx(ERR
, "error, only specify one Hitag type");
240 DumpFileType_t dftype
= getfiletype(filename
);
242 uint8_t *dump
= NULL
;
246 res
= loadFile_safe(filename
, ".bin", (void **)&dump
, &dumplen
);
250 res
= loadFileEML_safe(filename
, (void **)&dump
, &dumplen
);
255 dump
= calloc(dumplen
, sizeof(uint8_t));
257 PrintAndLogEx(ERR
, "error, cannot allocate memory");
260 res
= loadFileJSON(filename
, (void *)dump
, dumplen
, &dumplen
, NULL
);
264 PrintAndLogEx(ERR
, "error, only BIN/JSON/EML formats allowed");
269 if (res
!= PM3_SUCCESS
) {
270 PrintAndLogEx(ERR
, "error, something went wrong when loading file");
276 if (dumplen
== 48 || dumplen
== 4 * 64) {
281 payload
.len
= dumplen
;
282 memcpy(payload
.data
, dump
, dumplen
);
284 clearCommandBuffer();
285 SendCommandNG(CMD_LF_HITAG_ELOAD
, (uint8_t *)&payload
, 2 + dumplen
);
287 PrintAndLogEx(ERR
, "error, wrong dump file size. got %zu", dumplen
);
294 static int CmdLFHitagSim(const char *Cmd
) {
295 CLIParserContext
*ctx
;
296 CLIParserInit(&ctx
, "lf hitag sim",
297 "Simulate Hitag2 / HitagS transponder\n"
298 "You need to `lf hitag eload` first",
304 arg_lit0("1", NULL
, "simulate Hitag1"),
305 arg_lit0("2", NULL
, "simulate Hitag2"),
306 arg_lit0("s", NULL
, "simulate HitagS"),
309 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
311 bool use_ht1
= arg_get_lit(ctx
, 1);
312 bool use_ht2
= arg_get_lit(ctx
, 2);
313 bool use_hts
= arg_get_lit(ctx
, 3);
316 if ((use_ht1
+ use_ht2
+ use_hts
) > 1) {
317 PrintAndLogEx(ERR
, "error, Only specify one Hitag type");
321 uint16_t cmd
= CMD_LF_HITAG_SIMULATE
;
323 // cmd = CMD_LF_HITAG1_SIMULATE;
326 cmd
= CMD_LF_HITAGS_SIMULATE
;
328 clearCommandBuffer();
329 SendCommandMIX(cmd
, 0, 0, 0, NULL
, 0);
333 static void printHitagConfiguration(uint8_t config
) {
336 memset(msg
, 0, sizeof(msg
));
340 for (uint8_t i
= 0 ; i
< 8 ; i
++) {
341 snprintf(bs
, sizeof(bits
) - i
, "%1d", (config
>> (7 - i
)) & 1);
345 PrintAndLogEx(INFO
, "\n\nHitag2 tag information ");
346 PrintAndLogEx(INFO
, "------------------------------------");
349 PrintAndLogEx(SUCCESS
, "Config byte : 0x%02X [ %s ]", config
, bits
);
352 strcat(msg
, "Encoding : ");
354 strcat(msg
+ strlen(msg
), _YELLOW_("Biphase"));
356 strcat(msg
+ strlen(msg
), _YELLOW_("Manchester"));
358 PrintAndLogEx(SUCCESS
, "%s", msg
);
359 memset(msg
, 0, sizeof(msg
));
362 strcat(msg
, "Coding in HITAG 2 operation: %s");
363 uint8_t foo
= (config
& 0x6) >> 1;
366 PrintAndLogEx(SUCCESS
, "Version : public mode B, Coding: biphase");
367 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
370 PrintAndLogEx(SUCCESS
, "Version : public mode A, Coding: manchester");
371 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
374 PrintAndLogEx(SUCCESS
, "Version : public mode C, Coding: biphase");
375 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
378 PrintAndLogEx(SUCCESS
, "Version : Hitag2");
379 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
382 memset(msg
, 0, sizeof(msg
));
385 strcat(msg
, "Tag is in : ");
387 strcat(msg
+ strlen(msg
), _YELLOW_("Crypto mode"));
389 strcat(msg
+ strlen(msg
), _YELLOW_("Password mode"));
391 PrintAndLogEx(SUCCESS
, "%s", msg
);
392 memset(msg
, 0, sizeof(msg
));
395 strcat(msg
, "Page 6,7 : ");
397 strcat(msg
+ strlen(msg
), "read only");
399 strcat(msg
+ strlen(msg
), _GREEN_("RW"));
401 PrintAndLogEx(SUCCESS
, "%s", msg
);
402 memset(msg
, 0, sizeof(msg
));
405 strcat(msg
, "Page 4,5 : ");
407 strcat(msg
+ strlen(msg
), "read only");
409 strcat(msg
+ strlen(msg
), _GREEN_("RW"));
411 PrintAndLogEx(SUCCESS
, "%s", msg
);
412 memset(msg
, 0, sizeof(msg
));
415 strcat(msg
, "Page 3 : ");
417 strcat(msg
+ strlen(msg
), "read only. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE"));
419 strcat(msg
+ strlen(msg
), _GREEN_("RW"));
421 PrintAndLogEx(SUCCESS
, "%s", msg
);
422 memset(msg
, 0, sizeof(msg
));
426 strcat(msg
, "Page 1 : " _RED_("locked") "\n");
428 strcat(msg
+ strlen(msg
), "Page 2 : ");
430 strcat(msg
+ strlen(msg
), _RED_("locked"));
432 strcat(msg
+ strlen(msg
), "read only");
435 strcat(msg
, "Page 1,2 : " _GREEN_("RW"));
437 PrintAndLogEx(SUCCESS
, "%s", msg
);
438 PrintAndLogEx(INFO
, "------------------------------------");
441 static bool getHitagUid(uint32_t *uid
) {
443 memset(&htd
, 0, sizeof(htd
));
444 clearCommandBuffer();
445 SendCommandMIX(CMD_LF_HITAG_READER
, RHT2F_UID_ONLY
, 0, 0, &htd
, sizeof(htd
));
446 PacketResponseNG resp
;
447 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
448 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
452 if (resp
.oldarg
[0] == false) {
453 PrintAndLogEx(DEBUG
, "DEBUG: Error - failed getting UID");
458 *uid
= bytes_to_num(resp
.data
.asBytes
, 4);
463 static int CmdLFHitagInfo(const char *Cmd
) {
464 CLIParserContext
*ctx
;
465 CLIParserInit(&ctx
, "lf hitag info",
466 "Sniff traffic between Hitag reader and tag.",
474 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
479 if (getHitagUid(&uid
) == false)
482 PrintAndLogEx(NORMAL
, "");
483 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " ---------------------------");
484 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
485 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%08X"), uid
);
486 PrintAndLogEx(SUCCESS
, " TYPE: " _GREEN_("%s"), getHitagTypeStr(uid
));
488 // how to detemine Hitag types?
489 // read block3, get configuration byte.
491 // common configurations.
492 // printHitagConfiguration(0x06);
493 //printHitagConfiguration( 0x0E );
494 //printHitagConfiguration( 0x02 );
495 //printHitagConfiguration( 0x00 );
496 //printHitagConfiguration( 0x04 );
497 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
502 // Hitag2 reader, problem is that this command mixes up stuff. So 26 give uid. 21 etc will also give you a memory dump !?
504 static int CmdLFHitagReader(const char *Cmd
) {
506 CLIParserContext
*ctx
;
507 CLIParserInit(&ctx
, "lf hitag reader",
508 "Act like a Hitag Reader",
510 " lf hitag reader --01 --nrar 0102030411223344\n"
511 " lf hitag reader --02 -k 4F4E4D494B52\n"
513 " lf hitag reader --21 -k 4D494B52\n"
514 " lf hitag reader --22 --nrar 0102030411223344\n"
515 " lf hitag reader --23 -k 4F4E4D494B52\n"
516 " lf hitag reader --26\n"
521 arg_lit0(NULL
, "01", "HitagS, read all pages, challenge mode"),
522 arg_lit0(NULL
, "02", "HitagS, read all pages, crypto mode. Set key=0 for no auth"),
523 arg_lit0(NULL
, "21", "Hitag2, read all pages, password mode. def 4D494B52 (MIKR)"),
524 arg_lit0(NULL
, "22", "Hitag2, read all pages, challenge mode"),
525 arg_lit0(NULL
, "23", "Hitag2, read all pages, crypto mode. Key ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"),
526 arg_lit0(NULL
, "25", "Hitag2, test recorded authentications (replay?)"),
527 arg_lit0(NULL
, "26", "Hitag2, read UID"),
528 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
529 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer reader, 8 hex bytes"),
532 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
535 bool s01
= arg_get_lit(ctx
, 1);
536 bool s02
= arg_get_lit(ctx
, 2);
539 bool h21
= arg_get_lit(ctx
, 3);
540 bool h22
= arg_get_lit(ctx
, 4);
541 bool h23
= arg_get_lit(ctx
, 5);
542 bool h25
= arg_get_lit(ctx
, 6);
543 bool h26
= arg_get_lit(ctx
, 7);
547 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 8), key
, sizeof(key
), &keylen
);
555 res
= CLIParamHexToBuf(arg_get_str(ctx
, 9), nrar
, sizeof(nrar
), &nalen
);
562 if (keylen
!= 0 && keylen
!= 4) {
563 PrintAndLogEx(WARNING
, "Wrong KEY len expected 0 or 4, got %d", keylen
);
567 if (nalen
!= 0 && nalen
!= 6) {
568 PrintAndLogEx(WARNING
, "Wrong NR/AR len expected 0 or 6, got %d", nalen
);
572 uint8_t foo
= (s01
+ s02
+ h21
+ h22
+ h23
+ h25
+ h26
);
574 PrintAndLogEx(WARNING
, "Only specify one HITAG reader cmd");
576 } else if (foo
== 0) {
577 PrintAndLogEx(WARNING
, "Specify one HITAG reader cms");
583 uint16_t cmd
= CMD_LF_HITAG_READER
;
585 cmd
= CMD_LF_HITAGS_READ
;
586 htf
= RHTSF_CHALLENGE
;
587 memcpy(htd
.auth
.NrAr
, nrar
, sizeof(nrar
));
590 cmd
= CMD_LF_HITAGS_READ
;
592 memcpy(htd
.crypto
.key
, key
, sizeof(key
));
595 htf
= RHT2F_PASSWORD
;
596 memcpy(htd
.pwd
.password
, key
, 4);
599 htf
= RHT2F_AUTHENTICATE
;
600 memcpy(htd
.auth
.NrAr
, nrar
, sizeof(nrar
));
604 memcpy(htd
.crypto
.key
, key
, sizeof(key
));
607 htf
= RHT2F_TEST_AUTH_ATTEMPTS
;
610 htf
= RHT2F_UID_ONLY
;
613 clearCommandBuffer();
614 SendCommandMIX(cmd
, htf
, 0, 0, &htd
, sizeof(htd
));
615 PacketResponseNG resp
;
616 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
617 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
621 if (resp
.oldarg
[0] == false) {
622 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag failed");
626 uint32_t id
= bytes_to_num(resp
.data
.asBytes
, 4);
627 uint8_t *data
= resp
.data
.asBytes
;
628 PrintAndLogEx(SUCCESS
, " UID: " _YELLOW_("%08x"), id
);
630 if (htf
!= RHT2F_UID_ONLY
) {
633 printHitagConfiguration(data
[4 * 3]);
638 static int CmdLFHitagCheckChallenges(const char *Cmd
) {
640 CLIParserContext
*ctx
;
641 CLIParserInit(&ctx
, "lf hitag cc",
642 "Check challenges, load a file with saved hitag crypto challenges and test them all.\n"
643 "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`") " ",
644 "lf hitag cc -f my_hitag_challenges"
649 arg_str0("f", "filename", "<fn w/o ext>", "filename to load from"),
652 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
655 char filename
[FILE_PATH_SIZE
] = {0};
656 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
660 clearCommandBuffer();
663 uint8_t *data
= NULL
;
665 int res
= loadFile_safe(filename
, ".cc", (void **)&data
, &datalen
);
666 if (res
== PM3_SUCCESS
) {
667 if (datalen
== (8 * 60)) {
668 SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES
, 1, 0, 0, data
, datalen
);
670 PrintAndLogEx(ERR
, "Error, file length mismatch. Expected %d, got %zu", 8 * 60, datalen
);
677 SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES
, 0, 0, 0, NULL
, 0);
683 static int CmdLFHitagWriter(const char *Cmd
) {
684 CLIParserContext
*ctx
;
685 CLIParserInit(&ctx
, "lf hitag writer",
686 "Act like a Hitag writer"
687 "In password mode the default key is 4D494B52 (MIKR)\n"
688 "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.",
690 " lf hitag writer --03 --nrar 0102030411223344 -p 3 -d 01020304\n"
691 " lf hitag writer --04 -k 4F4E4D494B52 -p 3 -d 01020304\n"
693 " lf hitag writer --24 -k 4F4E4D494B52 -p 3 -d 01020304\n"
694 " lf hitag writer --27 -k 4D494B52 -p 3 -d 01020304\n"
699 arg_lit0(NULL
, "03", "HitagS, write page, challenge mode"),
700 arg_lit0(NULL
, "04", "HitagS, write page, crypto mode. Set key=0 for no auth"),
701 arg_lit0(NULL
, "24", "Hitag2, write page, crypto mode."),
702 arg_lit0(NULL
, "27", "Hitag2, write page, password mode"),
703 arg_int1("p", "page", "<dec>", "page address to write to"),
704 arg_str0("d", "data", "<hex>", "data, 4 hex bytes"),
705 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
706 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
709 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
712 bool s03
= arg_get_lit(ctx
, 1);
713 bool s04
= arg_get_lit(ctx
, 2);
716 bool h24
= arg_get_lit(ctx
, 3);
717 bool h27
= arg_get_lit(ctx
, 4);
719 uint32_t page
= arg_get_u32_def(ctx
, 5, 0);
723 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 6), data
, sizeof(data
), &dlen
);
731 res
= CLIParamHexToBuf(arg_get_str(ctx
, 7), key
, sizeof(key
), &keylen
);
739 res
= CLIParamHexToBuf(arg_get_str(ctx
, 8), nrar
, sizeof(nrar
), &nalen
);
748 if (dlen
!= sizeof(data
)) {
749 PrintAndLogEx(WARNING
, "Wrong DATA len expected 4, got %d", dlen
);
753 if (keylen
!= 0 && keylen
!= 6 && keylen
!= 4) {
754 PrintAndLogEx(WARNING
, "Wrong KEY len expected 0, 4 or 6, got %d", keylen
);
758 if (nalen
!= 0 && nalen
!= 8) {
759 PrintAndLogEx(WARNING
, "Wrong NR/AR len expected 0 or 8, got %d", nalen
);
763 uint8_t foo
= (s03
+ s04
+ h24
+ h27
);
765 PrintAndLogEx(WARNING
, "Only specify one HITAG write cmd");
767 } else if (foo
== 0) {
768 PrintAndLogEx(WARNING
, "Specify one HITAG write cmd");
775 htf
= WHTSF_CHALLENGE
;
776 memcpy(htd
.auth
.NrAr
, nrar
, sizeof(nrar
));
777 memcpy(htd
.auth
.data
, data
, sizeof(data
));
781 memcpy(htd
.crypto
.key
, key
, sizeof(key
));
782 memcpy(htd
.crypto
.data
, data
, sizeof(data
));
786 memcpy(htd
.pwd
.password
, key
, 4);
787 memcpy(htd
.crypto
.data
, data
, sizeof(data
));
790 htf
= WHT2F_PASSWORD
;
791 memcpy(htd
.pwd
.password
, key
, 4);
792 memcpy(htd
.crypto
.data
, data
, sizeof(data
));
795 clearCommandBuffer();
796 SendCommandMIX(CMD_LF_HITAGS_WRITE
, htf
, 0, page
, &htd
, sizeof(htd
));
797 PacketResponseNG resp
;
798 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 4000) == false) {
799 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
803 if (resp
.oldarg
[0] == false) {
804 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag write failed");
810 static int CmdLFHitag2Dump(const char *Cmd
) {
812 CLIParserContext
*ctx
;
813 CLIParserInit(&ctx
, "lf hitag dump",
814 "Read all card memory and save to file"
815 "In password mode the default key is 4D494B52 (MIKR)\n"
816 "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.",
817 "lf hitag dump -k 4F4E4D494B52\n"
818 "lf hitag dump -k 4D494B52\n"
823 arg_str0("f", "file", "<fn>", "file name"),
824 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
825 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer reader, 8 hex bytes"),
828 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
829 uint8_t filename
[FILE_PATH_SIZE
] = {0};
831 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), filename
, sizeof(filename
), &fnlen
);
839 res
= CLIParamHexToBuf(arg_get_str(ctx
, 2), key
, sizeof(key
), &keylen
);
847 res
= CLIParamHexToBuf(arg_get_str(ctx
, 3), nrar
, sizeof(nrar
), &nalen
);
853 PrintAndLogEx(WARNING
, "to be implememted...");
856 PrintAndLogEx(SUCCESS, "Dumping tag memory...");
858 clearCommandBuffer();
859 //SendCommandNG(CMD_LF_HITAG_DUMP, &htd, sizeof(htd));
860 PacketResponseNG resp;
861 uint8_t *data = resp.data.asBytes;
863 char *fptr = filename;
864 fptr += sprintf(fptr, "lf-hitag-");
865 FillFileNameByUID(fptr, data, "-dump", 4);
868 saveFile(filename, ".bin", data, 48);
869 saveFileEML(filename, data, 48, 4);
870 saveFileJSON(filename, jsfHitag, data, 48, NULL);
876 // Annotate HITAG protocol
877 void annotateHitag1(char *exp
, size_t size
, uint8_t *cmd
, uint8_t cmdsize
, bool is_response
) {
880 void annotateHitag2(char *exp
, size_t size
, uint8_t *cmd
, uint8_t cmdsize
, bool is_response
) {
882 // iceman: live decrypt of trace?
886 uint8_t cmdbits
= (cmd
[0] & 0xC0) >> 6;
889 if (cmdbits
== HITAG2_START_AUTH
) {
890 snprintf(exp
, size
, "START AUTH");
893 if (cmdbits
== HITAG2_HALT
) {
894 snprintf(exp
, size
, "HALT");
900 if (cmdbits
== HITAG2_START_AUTH
) {
902 // 1100 0 00 1 1100 000
903 uint8_t page
= (cmd
[0] & 0x38) >> 3;
904 uint8_t inv_page
= ((cmd
[0] & 0x1) << 2) | ((cmd
[1] & 0xC0) >> 6);
905 snprintf(exp
, size
, "READ page(%x) %x", page
, inv_page
);
908 if (cmdbits
== HITAG2_WRITE_PAGE
) {
909 uint8_t page
= (cmd
[0] & 0x38) >> 3;
910 uint8_t inv_page
= ((cmd
[0] & 0x1) << 2) | ((cmd
[1] & 0xC0) >> 6);
911 snprintf(exp
, size
, "WRITE page(%x) %x", page
, inv_page
);
917 snprintf(exp
, size
, "Nr Ar Is response");
923 snprintf(exp
, size
, "Nr Ar");
931 void annotateHitagS(char *exp
, size_t size
, uint8_t *cmd
, uint8_t cmdsize
, bool is_response
) {
934 static command_t CommandTable
[] = {
935 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
936 {"eload", CmdLFHitagEload
, IfPm3Hitag
, "Load Hitag dump file into emulator memory"},
937 {"list", CmdLFHitagList
, AlwaysAvailable
, "List Hitag trace history"},
938 {"info", CmdLFHitagInfo
, IfPm3Hitag
, "Tag information"},
939 {"reader", CmdLFHitagReader
, IfPm3Hitag
, "Act like a Hitag reader"},
940 {"sim", CmdLFHitagSim
, IfPm3Hitag
, "Simulate Hitag transponder"},
941 {"sniff", CmdLFHitagSniff
, IfPm3Hitag
, "Eavesdrop Hitag communication"},
942 {"writer", CmdLFHitagWriter
, IfPm3Hitag
, "Act like a Hitag writer"},
943 {"dump", CmdLFHitag2Dump
, IfPm3Hitag
, "Dump Hitag2 tag"},
944 {"cc", CmdLFHitagCheckChallenges
, IfPm3Hitag
, "Test all challenges"},
945 { NULL
, NULL
, 0, NULL
}
948 static int CmdHelp(const char *Cmd
) {
949 (void)Cmd
; // Cmd is not used so far
950 CmdsHelp(CommandTable
);
954 int CmdLFHitag(const char *Cmd
) {
955 clearCommandBuffer();
956 return CmdsParse(CommandTable
, Cmd
);
959 int readHitagUid(void) {
960 return (CmdLFHitagReader("--26") == PM3_SUCCESS
);