1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // 2016,2017, marshmellow, iceman
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 HID commands (known)
11 // RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding:
12 // http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf
14 // "Understanding Card Data Formats"
15 // https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf
17 // "What Format Do You Need?"
18 // https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf
19 //-----------------------------------------------------------------------------
26 #include "cmdparser.h" // command_t
28 #include "commonutil.h" // ARRAYLEN
29 #include "cliparser.h"
32 #include "cmddata.h" // g_debugMode, demodbuff cmds
33 #include "cmdlf.h" // lf_read, lfsim_wait_check
34 #include "util_posix.h"
36 #include "wiegand_formats.h"
37 #include "wiegand_formatutils.h"
38 #include "cmdlfem4x05.h" // EM defines
44 static int CmdHelp(const char *Cmd
);
46 // sending three times. Didn't seem to break the previous sim?
47 static int sendPing(void) {
48 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
49 SendCommandNG(CMD_PING
, NULL
, 0);
51 PacketResponseNG resp
;
52 if (!WaitForResponseTimeout(CMD_PING
, &resp
, 1000))
56 static int sendTry(uint8_t format_idx
, wiegand_card_t
*card
, uint32_t delay
, bool verbose
) {
58 wiegand_message_t packed
;
59 memset(&packed
, 0, sizeof(wiegand_message_t
));
61 if (HIDPack(format_idx
, card
, &packed
, true) == false) {
62 PrintAndLogEx(WARNING
, "The card data could not be encoded in the selected format.");
67 PrintAndLogEx(INFO
, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%"PRIu64
) " Issue level: " _YELLOW_("%u") " OEM: " _YELLOW_("%u")
76 payload
.hi2
= packed
.Top
;
77 payload
.hi
= packed
.Mid
;
78 payload
.lo
= packed
.Bot
;
79 payload
.longFMT
= (packed
.Mid
> 0xFFF);
83 SendCommandNG(CMD_LF_HID_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
85 PacketResponseNG resp;
86 WaitForResponse(CMD_LF_HID_SIMULATE, &resp);
87 if (resp.status == PM3_EOPABORTED)
94 //by marshmellow (based on existing demod + holiman's refactor)
95 //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
96 //print full HID Prox ID and some bit format details if found
97 int demodHID(bool verbose
) {
98 (void) verbose
; // unused so far
100 // HID simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
101 if (isGraphBitstream()) {
102 convertGraphFromBitstream();
105 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
106 uint32_t hi2
= 0, hi
= 0, lo
= 0;
108 uint8_t bits
[GraphTraceLen
];
109 size_t size
= getFromGraphBuf(bits
);
111 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID not enough samples"));
114 //get binary from fsk wave
116 int idx
= HIDdemodFSK(bits
, &size
, &hi2
, &hi
, &lo
, &waveIdx
);
120 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID not enough samples"));
122 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID just noise detected"));
124 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID problem during FSK demod"));
126 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID preamble not found"));
128 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu"), size
);
130 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx
);
135 setDemodBuff(bits
, size
, idx
);
136 setClockGrid(50, waveIdx
+ (idx
* 50));
138 if (hi2
== 0 && hi
== 0 && lo
== 0) {
139 PrintAndLogEx(DEBUG
, "DEBUG: Error - " _RED_("HID no values found"));
143 wiegand_message_t packed
= initialize_message_object(hi2
, hi
, lo
, 0);
144 if (HIDTryUnpack(&packed
) == false) {
145 printDemodBuff(0, false, false, true);
147 PrintAndLogEx(INFO
, "raw: " _GREEN_("%08x%08x%08x"), hi2
, hi
, lo
);
149 PrintAndLogEx(DEBUG
, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer: ", idx
, size
);
151 PrintAndLogEx(DEBUG
, "raw: " _GREEN_("%08x%08x%08x"), hi2
, hi
, lo
);
153 printDemodBuff(0, false, false, false);
159 static int CmdHIDDemod(const char *Cmd
) {
160 CLIParserContext
*ctx
;
161 CLIParserInit(&ctx
, "lf hid demod",
162 "Try to find HID Prox preamble, if found decode / descramble data",
170 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
172 return demodHID(true);
175 // this read is the "normal" read, which download lf signal and tries to demod here.
176 static int CmdHIDReader(const char *Cmd
) {
177 CLIParserContext
*ctx
;
178 CLIParserInit(&ctx
, "lf hid reader",
179 "read a HID Prox tag",
180 "lf hid reader -@ -> continuous reader mode"
185 arg_lit0("@", NULL
, "optional - continuous reader mode"),
188 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
189 bool cm
= arg_get_lit(ctx
, 1);
193 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
197 lf_read(false, 16000);
199 } while (cm
&& !kbd_enter_pressed());
204 // this read loops on device side.
205 // uses the demod in lfops.c
206 static int CmdHIDWatch(const char *Cmd
) {
207 CLIParserContext
*ctx
;
209 CLIParserInit(&ctx
, "lf hid watch",
210 "Enables HID compatible reader mode printing details.\n"
211 "By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
219 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
222 PrintAndLogEx(SUCCESS
, "Watching for HID Prox cards - place tag on antenna");
223 PrintAndLogEx(INFO
, "Press pm3-button to stop reading cards");
224 clearCommandBuffer();
225 SendCommandNG(CMD_LF_HID_WATCH
, NULL
, 0);
226 return lfsim_wait_check(CMD_LF_HID_WATCH
);
229 static int CmdHIDSim(const char *Cmd
) {
231 CLIParserContext
*ctx
;
232 CLIParserInit(&ctx
, "lf hid sim",
233 "Enables simulation of HID card with card number.\n"
234 "Simulation runs until the button is pressed or another USB command is issued.",
235 "lf hid sim -r 2006ec0c86 -> HID 10301 26 bit\n"
236 "lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit\n"
237 "lf hid sim -r 01f0760643c3 -> HID P10001 40 bit\n"
238 "lf hid sim -r 01400076000c86 -> HID Corporate 48 bit\n"
239 "lf hid sim -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n"
244 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
245 arg_u64_0(NULL
, "fc", "<dec>", "facility code"),
246 arg_u64_0(NULL
, "cn", "<dec>", "card number"),
247 arg_u64_0("i", NULL
, "<dec>", "issue level"),
248 arg_u64_0("o", "oem", "<dec>", "OEM code"),
249 arg_strx0("r", "raw", "<hex>", "raw bytes"),
252 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
254 char format
[16] = {0};
256 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)format
, sizeof(format
), &format_len
);
259 memset(&card
, 0, sizeof(wiegand_card_t
));
260 card
.FacilityCode
= arg_get_u32_def(ctx
, 2, 0);
261 card
.CardNumber
= arg_get_u32_def(ctx
, 3, 0);
262 card
.IssueLevel
= arg_get_u32_def(ctx
, 4, 0);
263 card
.OEM
= arg_get_u32_def(ctx
, 5, 0);
267 CLIParamStrToBuf(arg_get_str(ctx
, 6), (uint8_t *)raw
, sizeof(raw
), &raw_len
);
270 wiegand_message_t packed
;
271 memset(&packed
, 0, sizeof(wiegand_message_t
));
274 int format_idx
= HIDFindCardFormat((char *)format
);
275 if (format_idx
== -1 && raw_len
== 0) {
276 PrintAndLogEx(WARNING
, "Unknown format: " _YELLOW_("%s"), format
);
281 uint32_t top
= 0, mid
= 0, bot
= 0;
282 hexstring_to_u96(&top
, &mid
, &bot
, raw
);
287 if (HIDPack(format_idx
, &card
, &packed
, true) == false) {
288 PrintAndLogEx(WARNING
, "The card data could not be encoded in the selected format.");
294 PrintAndLogEx(INFO
, "Simulating HID tag");
295 HIDTryUnpack(&packed
);
297 PrintAndLogEx(INFO
, "Simulating HID tag using raw " _GREEN_("%s"), raw
);
301 payload
.hi2
= packed
.Top
;
302 payload
.hi
= packed
.Mid
;
303 payload
.lo
= packed
.Bot
;
304 payload
.longFMT
= (packed
.Mid
> 0xFFF);
306 clearCommandBuffer();
307 SendCommandNG(CMD_LF_HID_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
308 return lfsim_wait_check(CMD_LF_HID_SIMULATE
);
311 static int CmdHIDClone(const char *Cmd
) {
313 CLIParserContext
*ctx
;
314 CLIParserInit(&ctx
, "lf hid clone",
315 "clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
316 "Tag must be on the antenna when issuing this command.",
317 "lf hid clone -r 2006ec0c86 -> write raw value (HID 10301 26 bit)\n"
318 "lf hid clone -r 2e0ec00c87 -> write raw value (HID Corporate 35 bit)\n"
319 "lf hid clone -r 01f0760643c3 -> write raw value (HID P10001 40 bit)\n"
320 "lf hid clone -r 01400076000c86 -> write raw value (HID Corporate 48 bit)\n"
321 "lf hid clone -w H10301 --fc 118 --cn 1603 -> write raw value (HID 10301 26 bit)\n"
322 "lf hid clone -w H10301 --fc 118 --cn 1603 --q5 -> HID 10301 26 bit, encode for Q5/T5555 tag\n"
323 "lf hid clone -w H10301 --fc 118 --cn 1603 --em -> HID 10301 26 bit, encode for EM4305/4469"
328 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
329 arg_u64_0(NULL
, "fc", "<dec>", "facility code"),
330 arg_u64_0(NULL
, "cn", "<dec>", "card number"),
331 arg_int0("i", NULL
, "<dec>", "issue level"),
332 arg_int0("o", "oem", "<dec>", "OEM code"),
333 arg_strx0("r", "raw", "<hex>", "raw bytes"),
334 arg_lit0(NULL
, "q5", "optional - specify writing to Q5/T5555 tag"),
335 arg_lit0(NULL
, "em", "optional - specify writing to EM4305/4469 tag"),
336 arg_str0(NULL
, "bin", "<bin>", "Binary string i.e 0001001001"),
339 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
341 char format
[16] = {0};
343 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)format
, sizeof(format
), &format_len
);
346 memset(&card
, 0, sizeof(wiegand_card_t
));
347 card
.FacilityCode
= arg_get_u32_def(ctx
, 2, 0);
348 card
.CardNumber
= arg_get_u32_def(ctx
, 3, 0);
349 card
.IssueLevel
= arg_get_u32_def(ctx
, 4, 0);
350 card
.OEM
= arg_get_u32_def(ctx
, 5, 0);
354 CLIParamStrToBuf(arg_get_str(ctx
, 6), (uint8_t *)raw
, sizeof(raw
), &raw_len
);
356 bool q5
= arg_get_lit(ctx
, 7);
357 bool em
= arg_get_lit(ctx
, 8);
360 uint8_t bin
[70] = {0};
361 CLIGetStrWithReturn(ctx
, 9, bin
, &bin_len
);
365 PrintAndLogEx(FAILED
, "Can't specify both Q5 and EM4305 at the same time");
370 PrintAndLogEx(ERR
, "Binary wiegand string must be less than 128 bits");
374 wiegand_message_t packed
;
375 memset(&packed
, 0, sizeof(wiegand_message_t
));
378 int format_idx
= HIDFindCardFormat((char *)format
);
379 if (format_idx
== -1 && raw_len
== 0) {
380 PrintAndLogEx(WARNING
, "Unknown format: " _YELLOW_("%s"), format
);
384 uint32_t top
= 0, mid
= 0, bot
= 0;
386 hexstring_to_u96(&top
, &mid
, &bot
, raw
);
390 } else if (bin_len
) {
391 int res
= binstring_to_u96(&top
, &mid
, &bot
, (const char *)bin
);
392 if (res
!= bin_len
) {
393 PrintAndLogEx(ERR
, "Binary string contains none <0|1> chars");
400 if (HIDPack(format_idx
, &card
, &packed
, true) == false) {
401 PrintAndLogEx(WARNING
, "The card data could not be encoded in the selected format.");
406 char cardtype
[16] = {"T55x7"};
409 snprintf(cardtype
, sizeof(cardtype
), "Q5/T5555");
414 snprintf(cardtype
, sizeof(cardtype
), "EM4305/4469");
418 PrintAndLogEx(INFO
, "Preparing to clone HID tag");
419 HIDUnpack(format_idx
, &packed
);
421 PrintAndLogEx(INFO
, "Preparing to clone HID tag using raw " _YELLOW_("%s"), raw
);
425 payload
.hi2
= packed
.Top
;
426 payload
.hi
= packed
.Mid
;
427 payload
.lo
= packed
.Bot
;
428 payload
.longFMT
= (packed
.Mid
> 0xFFF);
432 clearCommandBuffer();
433 SendCommandNG(CMD_LF_HID_CLONE
, (uint8_t *)&payload
, sizeof(payload
));
435 PacketResponseNG resp
;
436 WaitForResponse(CMD_LF_HID_CLONE
, &resp
);
437 if (resp
.status
== PM3_SUCCESS
) {
438 PrintAndLogEx(INFO
, "Done");
440 PrintAndLogEx(FAILED
, "Failed cloning");
444 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf hid reader`") " to verify");
449 PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted");
450 PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------");
451 PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64,
460 PrintAndLogEx(NORMAL, "----+-----+-----+-------+-----------+--------------------");
463 static int CmdHIDBrute(const char *Cmd
) {
465 uint32_t delay
= 1000;
468 uint8_t format
[16] = {0};
471 wiegand_card_t cn_hi
, cn_low
;
472 memset(&cn_hi
, 0, sizeof(wiegand_card_t
));
474 CLIParserContext
*ctx
;
475 CLIParserInit(&ctx
, "lf hid brute",
476 "Enables bruteforce of HID readers with specified facility code.\n"
477 "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step\n"
478 "if cardnumber is not given, it starts with 1 and goes up to 65535",
479 "lf hid brute -w H10301 --fc 224\n"
480 "lf hid brute -w H10301 --fc 21 -d 2000\n"
481 "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000\n"
482 "lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000 --up\n"
487 arg_lit0("v", "verbose", "verbose logging, show all tries"),
488 arg_str1("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
489 arg_u64_0(NULL
, "fc", "<dec>", "facility code"),
490 arg_u64_0(NULL
, "cn", "<dec>", "card number to start with"),
491 arg_u64_0("i", "issue", "<dec>", "issue level"),
492 arg_u64_0("o", "oem", "<dec>", "OEM code"),
493 arg_u64_0("d", "delay", "<dec>", "delay betweens attempts in ms. Default 1000ms"),
494 arg_lit0(NULL
, "up", "direction to increment card number. (default is both directions)"),
495 arg_lit0(NULL
, "down", "direction to decrement card number. (default is both directions)"),
498 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
500 bool verbose
= arg_get_lit(ctx
, 1);
501 formatLen
= sizeof(format
);
502 CLIGetStrWithReturn(ctx
, 2, format
, &formatLen
);
504 format_idx
= HIDFindCardFormat((char *) format
);
505 if (format_idx
== -1) {
506 PrintAndLogEx(WARNING
, "Unknown format: " _YELLOW_("%s"), format
);
511 cn_hi
.FacilityCode
= arg_get_u32_def(ctx
, 3, 0);
512 cn_hi
.CardNumber
= arg_get_u32_def(ctx
, 4, 0);
513 cn_hi
.IssueLevel
= arg_get_u32_def(ctx
, 5, 0);
514 cn_hi
.OEM
= arg_get_u32_def(ctx
, 6, 0);
515 delay
= arg_get_u32_def(ctx
, 7, 1000);
517 if (arg_get_lit(ctx
, 8) && arg_get_lit(ctx
, 9)) {
519 } else if (arg_get_lit(ctx
, 8)) {
521 } else if (arg_get_lit(ctx
, 9)) {
528 PrintAndLogEx(INFO
, "Wiegand format#.. %i", format_idx
);
529 PrintAndLogEx(INFO
, "OEM#............. %u", cn_hi
.OEM
);
530 PrintAndLogEx(INFO
, "ISSUE#........... %u", cn_hi
.IssueLevel
);
531 PrintAndLogEx(INFO
, "Facility#........ %u", cn_hi
.FacilityCode
);
532 PrintAndLogEx(INFO
, "Card#............ %" PRIu64
, cn_hi
.CardNumber
);
535 PrintAndLogEx(INFO
, "Brute-forcing direction: " _YELLOW_("BOTH") " delay " _YELLOW_("%d"), delay
);
538 PrintAndLogEx(INFO
, "Brute-forcing direction: " _YELLOW_("UP") " delay " _YELLOW_("%d"), delay
);
541 PrintAndLogEx(INFO
, "Brute-forcing direction: " _YELLOW_("DOWN") " delay " _YELLOW_("%d"), delay
);
547 PrintAndLogEx(INFO
, "Started brute-forcing HID Prox reader");
548 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " or pm3-button to abort simulation");
549 // copy values to low.
553 // iceman: could add options for bruteforcing OEM, ISSUE or FC as well..
554 bool exitloop
= false;
555 bool fin_hi
, fin_low
;
556 fin_hi
= fin_low
= false;
559 if (!session
.pm3_present
) {
560 PrintAndLogEx(WARNING
, "Device offline\n");
564 if (kbd_enter_pressed()) {
565 PrintAndLogEx(WARNING
, "aborted via keyboard!");
570 if (direction
!= 2) {
571 if (cn_hi
.CardNumber
< 0xFFFF) {
573 if (sendTry(format_idx
, &cn_hi
, delay
, verbose
) != PM3_SUCCESS
) {
582 if (direction
!= 1) {
583 if (cn_low
.CardNumber
> 0) {
585 if (sendTry(format_idx
, &cn_low
, delay
, verbose
) != PM3_SUCCESS
) {
595 if (fin_hi
&& fin_low
) {
609 } while (exitloop
== false);
611 PrintAndLogEx(INFO
, "Brute forcing finished");
615 static command_t CommandTable
[] = {
616 {"help", CmdHelp
, AlwaysAvailable
, "this help"},
617 {"demod", CmdHIDDemod
, AlwaysAvailable
, "demodulate HID Prox tag from the GraphBuffer"},
618 {"reader", CmdHIDReader
, IfPm3Lf
, "attempt to read and extract tag data"},
619 {"clone", CmdHIDClone
, IfPm3Lf
, "clone HID tag to T55x7"},
620 {"sim", CmdHIDSim
, IfPm3Lf
, "simulate HID tag"},
621 {"brute", CmdHIDBrute
, IfPm3Lf
, "bruteforce card number against reader"},
622 {"watch", CmdHIDWatch
, IfPm3Lf
, "continuously watch for cards. Reader mode"},
623 {NULL
, NULL
, NULL
, NULL
}
626 static int CmdHelp(const char *Cmd
) {
627 (void)Cmd
; // Cmd is not used so far
628 CmdsHelp(CommandTable
);
632 int CmdLFHID(const char *Cmd
) {
633 clearCommandBuffer();
634 return CmdsParse(CommandTable
, Cmd
);