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 -2 -f lf-hitag-11223344-dump.bin\n");
217 arg_str1("f", "file", "<filename>", "filename of dump"),
218 arg_lit0("1", NULL
, "Card type Hitag1"),
219 arg_lit0("2", NULL
, "Card type Hitag2"),
220 arg_lit0("s", NULL
, "Card type HitagS"),
221 arg_lit0("m", NULL
, "Card type HitagM"),
224 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
227 char filename
[FILE_PATH_SIZE
] = {0};
228 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
230 bool use_ht1
= arg_get_lit(ctx
, 2);
231 bool use_ht2
= arg_get_lit(ctx
, 3);
232 bool use_hts
= arg_get_lit(ctx
, 4);
233 bool use_htm
= arg_get_lit(ctx
, 5);
236 uint8_t n
= (use_ht1
+ use_ht2
+ use_hts
+ use_htm
);
238 PrintAndLogEx(ERR
, "error, only specify one Hitag type");
242 DumpFileType_t dftype
= getfiletype(filename
);
244 uint8_t *dump
= NULL
;
248 res
= loadFile_safe(filename
, ".bin", (void **)&dump
, &dumplen
);
252 res
= loadFileEML_safe(filename
, (void **)&dump
, &dumplen
);
257 dump
= calloc(dumplen
, sizeof(uint8_t));
259 PrintAndLogEx(ERR
, "error, cannot allocate memory");
262 res
= loadFileJSON(filename
, (void *)dump
, dumplen
, &dumplen
, NULL
);
266 PrintAndLogEx(ERR
, "error, only BIN/JSON/EML formats allowed");
271 if (res
!= PM3_SUCCESS
) {
272 PrintAndLogEx(ERR
, "error, something went wrong when loading file");
278 if (dumplen
== 48 || dumplen
== 4 * 64) {
280 lf_hitag_t
*payload
= calloc(1, sizeof(lf_hitag_t
) + dumplen
);
291 payload
->len
= dumplen
;
292 memcpy(payload
->data
, dump
, dumplen
);
294 clearCommandBuffer();
295 SendCommandNG(CMD_LF_HITAG_ELOAD
, (uint8_t *)payload
, 3 + dumplen
);
298 PrintAndLogEx(ERR
, "error, wrong dump file size. got %zu", dumplen
);
305 static int CmdLFHitagSim(const char *Cmd
) {
306 CLIParserContext
*ctx
;
307 CLIParserInit(&ctx
, "lf hitag sim",
308 "Simulate Hitag2 / HitagS transponder\n"
309 "You need to `lf hitag eload` first",
315 arg_lit0("1", NULL
, "simulate Hitag1"),
316 arg_lit0("2", NULL
, "simulate Hitag2"),
317 arg_lit0("s", NULL
, "simulate HitagS"),
320 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
322 bool use_ht1
= arg_get_lit(ctx
, 1);
323 bool use_ht2
= arg_get_lit(ctx
, 2);
324 bool use_hts
= arg_get_lit(ctx
, 3);
327 if ((use_ht1
+ use_ht2
+ use_hts
) > 1) {
328 PrintAndLogEx(ERR
, "error, Only specify one Hitag type");
332 uint16_t cmd
= CMD_LF_HITAG_SIMULATE
;
334 // cmd = CMD_LF_HITAG1_SIMULATE;
337 cmd
= CMD_LF_HITAGS_SIMULATE
;
339 clearCommandBuffer();
340 SendCommandMIX(cmd
, 0, 0, 0, NULL
, 0);
344 static void printHitagConfiguration(uint8_t config
) {
347 memset(msg
, 0, sizeof(msg
));
351 for (uint8_t i
= 0 ; i
< 8 ; i
++) {
352 snprintf(bs
, sizeof(bits
) - i
, "%1d", (config
>> (7 - i
)) & 1);
356 PrintAndLogEx(INFO
, "\n\nHitag2 tag information ");
357 PrintAndLogEx(INFO
, "------------------------------------");
360 PrintAndLogEx(SUCCESS
, "Config byte : 0x%02X [ %s ]", config
, bits
);
363 strcat(msg
, "Encoding : ");
365 strcat(msg
+ strlen(msg
), _YELLOW_("Biphase"));
367 strcat(msg
+ strlen(msg
), _YELLOW_("Manchester"));
369 PrintAndLogEx(SUCCESS
, "%s", msg
);
370 memset(msg
, 0, sizeof(msg
));
373 strcat(msg
, "Coding in HITAG 2 operation: %s");
374 uint8_t foo
= (config
& 0x6) >> 1;
377 PrintAndLogEx(SUCCESS
, "Version : public mode B, Coding: biphase");
378 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
381 PrintAndLogEx(SUCCESS
, "Version : public mode A, Coding: manchester");
382 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
385 PrintAndLogEx(SUCCESS
, "Version : public mode C, Coding: biphase");
386 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
389 PrintAndLogEx(SUCCESS
, "Version : Hitag2");
390 PrintAndLogEx(SUCCESS
, msg
, (config
& 0x1) ? "biphase" : "manchester");
393 memset(msg
, 0, sizeof(msg
));
396 strcat(msg
, "Tag is in : ");
398 strcat(msg
+ strlen(msg
), _YELLOW_("Crypto mode"));
400 strcat(msg
+ strlen(msg
), _YELLOW_("Password mode"));
402 PrintAndLogEx(SUCCESS
, "%s", msg
);
403 memset(msg
, 0, sizeof(msg
));
406 strcat(msg
, "Page 6,7 : ");
408 strcat(msg
+ strlen(msg
), "read only");
410 strcat(msg
+ strlen(msg
), _GREEN_("RW"));
412 PrintAndLogEx(SUCCESS
, "%s", msg
);
413 memset(msg
, 0, sizeof(msg
));
416 strcat(msg
, "Page 4,5 : ");
418 strcat(msg
+ strlen(msg
), "read only");
420 strcat(msg
+ strlen(msg
), _GREEN_("RW"));
422 PrintAndLogEx(SUCCESS
, "%s", msg
);
423 memset(msg
, 0, sizeof(msg
));
426 strcat(msg
, "Page 3 : ");
428 strcat(msg
+ strlen(msg
), "read only. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE"));
430 strcat(msg
+ strlen(msg
), _GREEN_("RW"));
432 PrintAndLogEx(SUCCESS
, "%s", msg
);
433 memset(msg
, 0, sizeof(msg
));
437 strcat(msg
, "Page 1 : " _RED_("locked") "\n");
439 strcat(msg
+ strlen(msg
), "Page 2 : ");
441 strcat(msg
+ strlen(msg
), _RED_("locked"));
443 strcat(msg
+ strlen(msg
), "read only");
446 strcat(msg
, "Page 1,2 : " _GREEN_("RW"));
448 PrintAndLogEx(SUCCESS
, "%s", msg
);
449 PrintAndLogEx(INFO
, "------------------------------------");
452 static bool getHitagUid(uint32_t *uid
) {
454 memset(&htd
, 0, sizeof(htd
));
455 clearCommandBuffer();
456 SendCommandMIX(CMD_LF_HITAG_READER
, RHT2F_UID_ONLY
, 0, 0, &htd
, sizeof(htd
));
457 PacketResponseNG resp
;
458 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
459 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
463 if (resp
.oldarg
[0] == false) {
464 PrintAndLogEx(DEBUG
, "DEBUG: Error - failed getting UID");
469 *uid
= bytes_to_num(resp
.data
.asBytes
, 4);
474 static int CmdLFHitagInfo(const char *Cmd
) {
475 CLIParserContext
*ctx
;
476 CLIParserInit(&ctx
, "lf hitag info",
477 "Sniff traffic between Hitag reader and tag.",
485 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
490 if (getHitagUid(&uid
) == false)
493 PrintAndLogEx(NORMAL
, "");
494 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " ---------------------------");
495 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
496 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%08X"), uid
);
497 PrintAndLogEx(SUCCESS
, " TYPE: " _GREEN_("%s"), getHitagTypeStr(uid
));
499 // how to detemine Hitag types?
500 // read block3, get configuration byte.
502 // common configurations.
503 // printHitagConfiguration(0x06);
504 //printHitagConfiguration( 0x0E );
505 //printHitagConfiguration( 0x02 );
506 //printHitagConfiguration( 0x00 );
507 //printHitagConfiguration( 0x04 );
508 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
513 // Hitag2 reader, problem is that this command mixes up stuff. So 26 give uid. 21 etc will also give you a memory dump !?
515 static int CmdLFHitagReader(const char *Cmd
) {
517 CLIParserContext
*ctx
;
518 CLIParserInit(&ctx
, "lf hitag reader",
519 "Act like a Hitag Reader",
521 " lf hitag reader --01 --nrar 0102030411223344\n"
522 " lf hitag reader --02 -k 4F4E4D494B52\n"
524 " lf hitag reader --21 -k 4D494B52\n"
525 " lf hitag reader --22 --nrar 0102030411223344\n"
526 " lf hitag reader --23 -k 4F4E4D494B52\n"
527 " lf hitag reader --26\n"
532 arg_lit0(NULL
, "01", "HitagS, read all pages, challenge mode"),
533 arg_lit0(NULL
, "02", "HitagS, read all pages, crypto mode. Set key=0 for no auth"),
534 arg_lit0(NULL
, "21", "Hitag2, read all pages, password mode. def 4D494B52 (MIKR)"),
535 arg_lit0(NULL
, "22", "Hitag2, read all pages, challenge mode"),
536 arg_lit0(NULL
, "23", "Hitag2, read all pages, crypto mode. Key ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"),
537 arg_lit0(NULL
, "25", "Hitag2, test recorded authentications (replay?)"),
538 arg_lit0(NULL
, "26", "Hitag2, read UID"),
539 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
540 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer reader, 8 hex bytes"),
543 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
546 bool s01
= arg_get_lit(ctx
, 1);
547 bool s02
= arg_get_lit(ctx
, 2);
550 bool h21
= arg_get_lit(ctx
, 3);
551 bool h22
= arg_get_lit(ctx
, 4);
552 bool h23
= arg_get_lit(ctx
, 5);
553 bool h25
= arg_get_lit(ctx
, 6);
554 bool h26
= arg_get_lit(ctx
, 7);
558 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 8), key
, sizeof(key
), &keylen
);
566 res
= CLIParamHexToBuf(arg_get_str(ctx
, 9), nrar
, sizeof(nrar
), &nalen
);
573 if (keylen
!= 0 && keylen
!= 4) {
574 PrintAndLogEx(WARNING
, "Wrong KEY len expected 0 or 4, got %d", keylen
);
578 if (nalen
!= 0 && nalen
!= 6) {
579 PrintAndLogEx(WARNING
, "Wrong NR/AR len expected 0 or 6, got %d", nalen
);
583 uint8_t foo
= (s01
+ s02
+ h21
+ h22
+ h23
+ h25
+ h26
);
585 PrintAndLogEx(WARNING
, "Only specify one HITAG reader cmd");
587 } else if (foo
== 0) {
588 PrintAndLogEx(WARNING
, "Specify one HITAG reader cms");
594 uint16_t cmd
= CMD_LF_HITAG_READER
;
596 cmd
= CMD_LF_HITAGS_READ
;
597 htf
= RHTSF_CHALLENGE
;
598 memcpy(htd
.auth
.NrAr
, nrar
, sizeof(nrar
));
601 cmd
= CMD_LF_HITAGS_READ
;
603 memcpy(htd
.crypto
.key
, key
, sizeof(key
));
606 htf
= RHT2F_PASSWORD
;
607 memcpy(htd
.pwd
.password
, key
, 4);
610 htf
= RHT2F_AUTHENTICATE
;
611 memcpy(htd
.auth
.NrAr
, nrar
, sizeof(nrar
));
615 memcpy(htd
.crypto
.key
, key
, sizeof(key
));
618 htf
= RHT2F_TEST_AUTH_ATTEMPTS
;
621 htf
= RHT2F_UID_ONLY
;
624 clearCommandBuffer();
625 SendCommandMIX(cmd
, htf
, 0, 0, &htd
, sizeof(htd
));
626 PacketResponseNG resp
;
627 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
628 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
632 if (resp
.oldarg
[0] == false) {
633 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag failed");
637 uint32_t id
= bytes_to_num(resp
.data
.asBytes
, 4);
638 uint8_t *data
= resp
.data
.asBytes
;
639 PrintAndLogEx(SUCCESS
, " UID: " _YELLOW_("%08x"), id
);
641 if (htf
!= RHT2F_UID_ONLY
) {
644 printHitagConfiguration(data
[4 * 3]);
649 static int CmdLFHitagCheckChallenges(const char *Cmd
) {
651 CLIParserContext
*ctx
;
652 CLIParserInit(&ctx
, "lf hitag cc",
653 "Check challenges, load a file with saved hitag crypto challenges and test them all.\n"
654 "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`") " ",
655 "lf hitag cc -f my_hitag_challenges"
660 arg_str0("f", "filename", "<fn w/o ext>", "filename to load from"),
663 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
666 char filename
[FILE_PATH_SIZE
] = {0};
667 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
671 clearCommandBuffer();
674 uint8_t *data
= NULL
;
676 int res
= loadFile_safe(filename
, ".cc", (void **)&data
, &datalen
);
677 if (res
== PM3_SUCCESS
) {
678 if (datalen
== (8 * 60)) {
679 SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES
, 1, 0, 0, data
, datalen
);
681 PrintAndLogEx(ERR
, "Error, file length mismatch. Expected %d, got %zu", 8 * 60, datalen
);
688 SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES
, 0, 0, 0, NULL
, 0);
694 static int CmdLFHitagWriter(const char *Cmd
) {
695 CLIParserContext
*ctx
;
696 CLIParserInit(&ctx
, "lf hitag writer",
697 "Act like a Hitag writer"
698 "In password mode the default key is 4D494B52 (MIKR)\n"
699 "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.",
701 " lf hitag writer --03 --nrar 0102030411223344 -p 3 -d 01020304\n"
702 " lf hitag writer --04 -k 4F4E4D494B52 -p 3 -d 01020304\n"
704 " lf hitag writer --24 -k 4F4E4D494B52 -p 3 -d 01020304\n"
705 " lf hitag writer --27 -k 4D494B52 -p 3 -d 01020304\n"
710 arg_lit0(NULL
, "03", "HitagS, write page, challenge mode"),
711 arg_lit0(NULL
, "04", "HitagS, write page, crypto mode. Set key=0 for no auth"),
712 arg_lit0(NULL
, "24", "Hitag2, write page, crypto mode."),
713 arg_lit0(NULL
, "27", "Hitag2, write page, password mode"),
714 arg_int1("p", "page", "<dec>", "page address to write to"),
715 arg_str0("d", "data", "<hex>", "data, 4 hex bytes"),
716 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
717 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
720 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
723 bool s03
= arg_get_lit(ctx
, 1);
724 bool s04
= arg_get_lit(ctx
, 2);
727 bool h24
= arg_get_lit(ctx
, 3);
728 bool h27
= arg_get_lit(ctx
, 4);
730 uint32_t page
= arg_get_u32_def(ctx
, 5, 0);
734 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 6), data
, sizeof(data
), &dlen
);
742 res
= CLIParamHexToBuf(arg_get_str(ctx
, 7), key
, sizeof(key
), &keylen
);
750 res
= CLIParamHexToBuf(arg_get_str(ctx
, 8), nrar
, sizeof(nrar
), &nalen
);
759 if (dlen
!= sizeof(data
)) {
760 PrintAndLogEx(WARNING
, "Wrong DATA len expected 4, got %d", dlen
);
764 if (keylen
!= 0 && keylen
!= 6 && keylen
!= 4) {
765 PrintAndLogEx(WARNING
, "Wrong KEY len expected 0, 4 or 6, got %d", keylen
);
769 if (nalen
!= 0 && nalen
!= 8) {
770 PrintAndLogEx(WARNING
, "Wrong NR/AR len expected 0 or 8, got %d", nalen
);
774 uint8_t foo
= (s03
+ s04
+ h24
+ h27
);
776 PrintAndLogEx(WARNING
, "Only specify one HITAG write cmd");
778 } else if (foo
== 0) {
779 PrintAndLogEx(WARNING
, "Specify one HITAG write cmd");
786 htf
= WHTSF_CHALLENGE
;
787 memcpy(htd
.auth
.NrAr
, nrar
, sizeof(nrar
));
788 memcpy(htd
.auth
.data
, data
, sizeof(data
));
792 memcpy(htd
.crypto
.key
, key
, sizeof(key
));
793 memcpy(htd
.crypto
.data
, data
, sizeof(data
));
797 memcpy(htd
.pwd
.password
, key
, 4);
798 memcpy(htd
.crypto
.data
, data
, sizeof(data
));
801 htf
= WHT2F_PASSWORD
;
802 memcpy(htd
.pwd
.password
, key
, 4);
803 memcpy(htd
.crypto
.data
, data
, sizeof(data
));
806 clearCommandBuffer();
807 SendCommandMIX(CMD_LF_HITAGS_WRITE
, htf
, 0, page
, &htd
, sizeof(htd
));
808 PacketResponseNG resp
;
809 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 4000) == false) {
810 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
814 if (resp
.oldarg
[0] == false) {
815 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag write failed");
821 static int CmdLFHitag2Dump(const char *Cmd
) {
823 CLIParserContext
*ctx
;
824 CLIParserInit(&ctx
, "lf hitag dump",
825 "Read all card memory and save to file"
826 "In password mode the default key is 4D494B52 (MIKR)\n"
827 "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.",
828 "lf hitag dump -k 4F4E4D494B52\n"
829 "lf hitag dump -k 4D494B52\n"
834 arg_str0("f", "file", "<fn>", "file name"),
835 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
836 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer reader, 8 hex bytes"),
839 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
840 uint8_t filename
[FILE_PATH_SIZE
] = {0};
842 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), filename
, sizeof(filename
), &fnlen
);
850 res
= CLIParamHexToBuf(arg_get_str(ctx
, 2), key
, sizeof(key
), &keylen
);
858 res
= CLIParamHexToBuf(arg_get_str(ctx
, 3), nrar
, sizeof(nrar
), &nalen
);
864 PrintAndLogEx(WARNING
, "to be implememted...");
867 PrintAndLogEx(SUCCESS, "Dumping tag memory...");
869 clearCommandBuffer();
870 //SendCommandNG(CMD_LF_HITAG_DUMP, &htd, sizeof(htd));
871 PacketResponseNG resp;
872 uint8_t *data = resp.data.asBytes;
874 char *fptr = filename;
875 fptr += sprintf(fptr, "lf-hitag-");
876 FillFileNameByUID(fptr, data, "-dump", 4);
879 saveFile(filename, ".bin", data, 48);
880 saveFileEML(filename, data, 48, 4);
881 saveFileJSON(filename, jsfHitag, data, 48, NULL);
887 // Annotate HITAG protocol
888 void annotateHitag1(char *exp
, size_t size
, uint8_t *cmd
, uint8_t cmdsize
, bool is_response
) {
891 void annotateHitag2(char *exp
, size_t size
, uint8_t *cmd
, uint8_t cmdsize
, bool is_response
) {
893 // iceman: live decrypt of trace?
897 uint8_t cmdbits
= (cmd
[0] & 0xC0) >> 6;
900 if (cmdbits
== HITAG2_START_AUTH
) {
901 snprintf(exp
, size
, "START AUTH");
904 if (cmdbits
== HITAG2_HALT
) {
905 snprintf(exp
, size
, "HALT");
911 if (cmdbits
== HITAG2_START_AUTH
) {
913 // 1100 0 00 1 1100 000
914 uint8_t page
= (cmd
[0] & 0x38) >> 3;
915 uint8_t inv_page
= ((cmd
[0] & 0x1) << 2) | ((cmd
[1] & 0xC0) >> 6);
916 snprintf(exp
, size
, "READ page(%x) %x", page
, inv_page
);
919 if (cmdbits
== HITAG2_WRITE_PAGE
) {
920 uint8_t page
= (cmd
[0] & 0x38) >> 3;
921 uint8_t inv_page
= ((cmd
[0] & 0x1) << 2) | ((cmd
[1] & 0xC0) >> 6);
922 snprintf(exp
, size
, "WRITE page(%x) %x", page
, inv_page
);
928 snprintf(exp
, size
, "Nr Ar Is response");
934 snprintf(exp
, size
, "Nr Ar");
942 void annotateHitagS(char *exp
, size_t size
, uint8_t *cmd
, uint8_t cmdsize
, bool is_response
) {
945 static command_t CommandTable
[] = {
946 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
947 {"eload", CmdLFHitagEload
, IfPm3Hitag
, "Load Hitag dump file into emulator memory"},
948 {"list", CmdLFHitagList
, AlwaysAvailable
, "List Hitag trace history"},
949 {"info", CmdLFHitagInfo
, IfPm3Hitag
, "Tag information"},
950 {"reader", CmdLFHitagReader
, IfPm3Hitag
, "Act like a Hitag reader"},
951 {"sim", CmdLFHitagSim
, IfPm3Hitag
, "Simulate Hitag transponder"},
952 {"sniff", CmdLFHitagSniff
, IfPm3Hitag
, "Eavesdrop Hitag communication"},
953 {"writer", CmdLFHitagWriter
, IfPm3Hitag
, "Act like a Hitag writer"},
954 {"dump", CmdLFHitag2Dump
, IfPm3Hitag
, "Dump Hitag2 tag"},
955 {"cc", CmdLFHitagCheckChallenges
, IfPm3Hitag
, "Test all challenges"},
956 { NULL
, NULL
, 0, NULL
}
959 static int CmdHelp(const char *Cmd
) {
960 (void)Cmd
; // Cmd is not used so far
961 CmdsHelp(CommandTable
);
965 int CmdLFHitag(const char *Cmd
) {
966 clearCommandBuffer();
967 return CmdsParse(CommandTable
, Cmd
);
970 int readHitagUid(void) {
971 return (CmdLFHitagReader("--26") == PM3_SUCCESS
);