recover_pk.py: replace secp192r1 by prime192v1
[RRG-proxmark3.git] / client / src / cmdlfhid.c
blob4ad3cbc6667629bf1424a0c02b722d69f36159cf
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 // Low frequency HID commands (known)
18 // Useful resources:
19 // RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding:
20 // http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf
22 // "Understanding Card Data Formats"
23 // https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf
25 // "What Format Do You Need?"
26 // https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf
27 //-----------------------------------------------------------------------------
29 #include "cmdlfhid.h"
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <inttypes.h>
34 #include "cmdparser.h" // command_t
35 #include "comms.h"
36 #include "commonutil.h" // ARRAYLEN
37 #include "cliparser.h"
38 #include "ui.h"
39 #include "graph.h"
40 #include "cmddata.h" // g_debugMode, demodbuff cmds
41 #include "cmdlf.h" // lf_read, lfsim_wait_check
42 #include "util_posix.h"
43 #include "lfdemod.h"
44 #include "wiegand_formats.h"
45 #include "wiegand_formatutils.h"
46 #include "cmdlfem4x05.h" // EM defines
47 #include "loclass/cipherutils.h" // bitstreamout
49 #ifndef BITS
50 # define BITS 96
51 #endif
53 static int CmdHelp(const char *Cmd);
55 // sending three times. Didn't seem to break the previous sim?
56 static int sendPing(void) {
57 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
58 SendCommandNG(CMD_PING, NULL, 0);
59 clearCommandBuffer();
60 PacketResponseNG resp;
61 if (WaitForResponseTimeout(CMD_PING, &resp, 1000) == false) {
62 return PM3_ETIMEOUT;
64 return PM3_SUCCESS;
66 static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, bool verbose) {
68 wiegand_message_t packed;
69 memset(&packed, 0, sizeof(wiegand_message_t));
71 if (HIDPack(format_idx, card, &packed, true) == false) {
72 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
73 return PM3_ESOFT;
76 if (verbose) {
77 PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%"PRIu64) " Issue level: " _YELLOW_("%u") " OEM: " _YELLOW_("%u")
78 , card->FacilityCode
79 , card->CardNumber
80 , card->IssueLevel
81 , card->OEM
85 lf_hidsim_t payload = {
86 .EM = false,
87 .Q5 = false,
88 .hi2 = packed.Top,
89 .hi = packed.Mid,
90 .lo = packed.Bot,
91 .longFMT = (packed.Mid > 0xFFF)
94 clearCommandBuffer();
96 SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
98 PacketResponseNG resp;
99 WaitForResponse(CMD_LF_HID_SIMULATE, &resp);
100 if (resp.status == PM3_EOPABORTED)
101 return resp.status;
103 msleep(delay);
104 return sendPing();
107 //by marshmellow (based on existing demod + holiman's refactor)
108 //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
109 //print full HID Prox ID and some bit format details if found
110 int demodHID(bool verbose) {
111 (void) verbose; // unused so far
113 // HID simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
114 if (isGraphBitstream()) {
115 convertGraphFromBitstream();
118 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
119 uint32_t hi2 = 0, hi = 0, lo = 0;
121 uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
122 if (bits == NULL) {
123 PrintAndLogEx(FAILED, "failed to allocate memory");
124 return PM3_EMALLOC;
126 size_t size = getFromGraphBuffer(bits);
127 if (size == 0) {
128 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
129 free(bits);
130 return PM3_ESOFT;
132 //get binary from fsk wave
133 int waveIdx = 0;
134 int idx = HIDdemodFSK(bits, &size, &hi2, &hi, &lo, &waveIdx);
135 if (idx < 0) {
137 if (idx == -1)
138 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
139 else if (idx == -2)
140 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID just noise detected"));
141 else if (idx == -3)
142 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID problem during FSK demod"));
143 else if (idx == -4)
144 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID preamble not found"));
145 else if (idx == -5)
146 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu"), size);
147 else
148 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx);
150 free(bits);
151 return PM3_ESOFT;
154 setDemodBuff(bits, size, idx);
155 setClockGrid(50, waveIdx + (idx * 50));
156 free(bits);
158 if (hi2 == 0 && hi == 0 && lo == 0) {
159 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found"));
160 return PM3_ESOFT;
163 wiegand_message_t packed = initialize_message_object(hi2, hi, lo, 0);
164 if (HIDTryUnpack(&packed) == false) {
165 printDemodBuff(0, false, false, true);
167 PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
169 PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing DemodBuffer: ", idx, size);
170 if (g_debugMode) {
171 PrintAndLogEx(DEBUG, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
173 printDemodBuff(0, false, false, false);
176 return PM3_SUCCESS;
179 static int CmdHIDDemod(const char *Cmd) {
180 CLIParserContext *ctx;
181 CLIParserInit(&ctx, "lf hid demod",
182 "Try to find HID Prox preamble, if found decode / descramble data",
183 "lf hid demod"
186 void *argtable[] = {
187 arg_param_begin,
188 arg_param_end
190 CLIExecWithReturn(ctx, Cmd, argtable, true);
191 CLIParserFree(ctx);
192 return demodHID(true);
195 // this read is the "normal" read, which download lf signal and tries to demod here.
196 static int CmdHIDReader(const char *Cmd) {
197 CLIParserContext *ctx;
198 CLIParserInit(&ctx, "lf hid reader",
199 "read a HID Prox tag",
200 "lf hid reader -@ -> continuous reader mode"
203 void *argtable[] = {
204 arg_param_begin,
205 arg_lit0("@", NULL, "optional - continuous reader mode"),
206 arg_param_end
208 CLIExecWithReturn(ctx, Cmd, argtable, true);
209 bool cm = arg_get_lit(ctx, 1);
210 CLIParserFree(ctx);
212 if (cm) {
213 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
216 do {
217 lf_read(false, 16000);
218 demodHID(!cm);
219 } while (cm && !kbd_enter_pressed());
221 return PM3_SUCCESS;
224 // this read loops on device side.
225 // uses the demod in lfops.c
226 static int CmdHIDWatch(const char *Cmd) {
227 CLIParserContext *ctx;
229 CLIParserInit(&ctx, "lf hid watch",
230 "Enables HID compatible reader mode printing details.\n"
231 "By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
232 "lf hid watch"
235 void *argtable[] = {
236 arg_param_begin,
237 arg_param_end
239 CLIExecWithReturn(ctx, Cmd, argtable, true);
240 CLIParserFree(ctx);
242 PrintAndLogEx(SUCCESS, "Watching for HID Prox cards - place tag on antenna");
243 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to stop reading cards");
244 clearCommandBuffer();
245 SendCommandNG(CMD_LF_HID_WATCH, NULL, 0);
246 return lfsim_wait_check(CMD_LF_HID_WATCH);
249 static int CmdHIDSim(const char *Cmd) {
251 CLIParserContext *ctx;
252 CLIParserInit(&ctx, "lf hid sim",
253 "Enables simulation of HID card with card number.\n"
254 "Simulation runs until the button is pressed or another USB command is issued.",
255 "lf hid sim -r 2006ec0c86 -> HID 10301 26 bit\n"
256 "lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit\n"
257 "lf hid sim -r 01f0760643c3 -> HID P10001 40 bit\n"
258 "lf hid sim -r 01400076000c86 -> HID Corporate 48 bit\n"
259 "lf hid sim -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n"
262 void *argtable[] = {
263 arg_param_begin,
264 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
265 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
266 arg_u64_0(NULL, "cn", "<dec>", "card number"),
267 arg_u64_0("i", NULL, "<dec>", "issue level"),
268 arg_u64_0("o", "oem", "<dec>", "OEM code"),
269 arg_str0("r", "raw", "<hex>", "raw bytes"),
270 arg_param_end
272 CLIExecWithReturn(ctx, Cmd, argtable, false);
274 char format[16] = {0};
275 int format_len = 0;
276 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
278 wiegand_card_t card;
279 memset(&card, 0, sizeof(wiegand_card_t));
280 card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
281 card.CardNumber = arg_get_u32_def(ctx, 3, 0);
282 card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
283 card.OEM = arg_get_u32_def(ctx, 5, 0);
285 int raw_len = 0;
286 char raw[40] = {0};
287 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
288 CLIParserFree(ctx);
290 wiegand_message_t packed;
291 memset(&packed, 0, sizeof(wiegand_message_t));
293 // format validation
294 int format_idx = HIDFindCardFormat(format);
295 if (format_idx == -1 && raw_len == 0) {
296 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
297 return PM3_EINVARG;
300 if (raw_len) {
301 uint32_t top = 0, mid = 0, bot = 0;
302 hexstring_to_u96(&top, &mid, &bot, raw);
303 packed.Top = top;
304 packed.Mid = mid;
305 packed.Bot = bot;
306 } else {
307 if (HIDPack(format_idx, &card, &packed, true) == false) {
308 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
309 return PM3_ESOFT;
313 if (raw_len == 0) {
314 PrintAndLogEx(INFO, "Simulating HID tag");
315 HIDTryUnpack(&packed);
316 } else {
317 PrintAndLogEx(INFO, "Simulating HID tag using raw " _GREEN_("%s"), raw);
320 lf_hidsim_t payload;
321 payload.hi2 = packed.Top;
322 payload.hi = packed.Mid;
323 payload.lo = packed.Bot;
324 payload.longFMT = (packed.Mid > 0xFFF);
326 clearCommandBuffer();
327 SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
328 return lfsim_wait_check(CMD_LF_HID_SIMULATE);
331 static int CmdHIDClone(const char *Cmd) {
333 CLIParserContext *ctx;
334 CLIParserInit(&ctx, "lf hid clone",
335 "clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
336 "Tag must be on the antenna when issuing this command.",
337 "lf hid clone -r 2006ec0c86 -> write raw value for T55x7 tag (HID 10301 26 bit)\n"
338 "lf hid clone -r 2e0ec00c87 -> write raw value for T55x7 tag (HID Corporate 35 bit)\n"
339 "lf hid clone -r 01f0760643c3 -> write raw value for T55x7 tag (HID P10001 40 bit)\n"
340 "lf hid clone -r 01400076000c86 -> write raw value for T55x7 tag (HID Corporate 48 bit)\n"
341 "lf hid clone -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit, encode for T55x7 tag\n"
342 "lf hid clone -w H10301 --fc 118 --cn 1603 --q5 -> HID 10301 26 bit, encode for Q5/T5555 tag\n"
343 "lf hid clone -w H10301 --fc 118 --cn 1603 --em -> HID 10301 26 bit, encode for EM4305/4469"
346 void *argtable[] = {
347 arg_param_begin,
348 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
349 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
350 arg_u64_0(NULL, "cn", "<dec>", "card number"),
351 arg_int0("i", NULL, "<dec>", "issue level"),
352 arg_int0("o", "oem", "<dec>", "OEM code"),
353 arg_str0("r", "raw", "<hex>", "raw bytes"),
354 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
355 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
356 arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
357 arg_param_end
359 CLIExecWithReturn(ctx, Cmd, argtable, false);
361 char format[16] = {0};
362 int format_len = 0;
363 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
365 wiegand_card_t card;
366 memset(&card, 0, sizeof(wiegand_card_t));
367 card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
368 card.CardNumber = arg_get_u32_def(ctx, 3, 0);
369 card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
370 card.OEM = arg_get_u32_def(ctx, 5, 0);
372 int raw_len = 0;
373 char raw[40] = {0};
374 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
376 bool q5 = arg_get_lit(ctx, 7);
377 bool em = arg_get_lit(ctx, 8);
379 // t5577 can do 6 blocks with 32bits == 192 bits, HID is manchester encoded and doubles in length.
380 // With parity, manchester and preamble we have about 3 blocks to play with. Ie: 96 bits
381 uint8_t bin[97] = {0};
382 int bin_len = sizeof(bin) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated
383 CLIGetStrWithReturn(ctx, 9, bin, &bin_len);
384 CLIParserFree(ctx);
386 if (q5 && em) {
387 PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
388 return PM3_EINVARG;
391 if (bin_len > 96) {
392 PrintAndLogEx(ERR, "Binary wiegand string must be less than 96 bits");
393 return PM3_EINVARG;
396 wiegand_message_t packed;
397 memset(&packed, 0, sizeof(wiegand_message_t));
399 // format validation
400 int format_idx = HIDFindCardFormat(format);
401 if (format_idx == -1 && raw_len == 0) {
402 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
403 return PM3_EINVARG;
406 uint32_t top = 0, mid = 0, bot = 0;
407 if (raw_len) {
408 hexstring_to_u96(&top, &mid, &bot, raw);
409 packed.Top = top;
410 packed.Mid = mid;
411 packed.Bot = bot;
412 } else if (bin_len) {
414 uint8_t hex[12];
415 memset(hex, 0, sizeof(hex));
416 BitstreamOut_t bout = {hex, 0, 0 };
418 for (int i = 0; i < 96 - bin_len - 1; i++) {
419 pushBit(&bout, 0);
421 // add binary sentinel bit.
422 pushBit(&bout, 1);
424 // convert binary string to hex bytes
425 for (int i = 0; i < bin_len; i++) {
426 char c = bin[i];
427 if (c == '1')
428 pushBit(&bout, 1);
429 else if (c == '0')
430 pushBit(&bout, 0);
433 packed.Length = bin_len;
434 packed.Top = bytes_to_num(hex, 4);
435 packed.Mid = bytes_to_num(hex + 4, 4);
436 packed.Bot = bytes_to_num(hex + 8, 4);
437 add_HID_header(&packed);
439 } else {
440 if (HIDPack(format_idx, &card, &packed, true) == false) {
441 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
442 return PM3_ESOFT;
446 char cardtype[16] = {"T55x7"};
447 // Q5
448 if (q5) {
449 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
452 // EM4305
453 if (em) {
454 PrintAndLogEx(WARNING, "Beware some EM4305 tags don't support FSK and datarate = RF/50, check your tag copy!");
455 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
458 if (raw_len == 0) {
459 PrintAndLogEx(INFO, "Preparing to clone HID tag");
460 HIDUnpack(format_idx, &packed);
461 } else {
462 PrintAndLogEx(INFO, "Preparing to clone HID tag using raw " _YELLOW_("%s"), raw);
465 lf_hidsim_t payload;
466 payload.hi2 = packed.Top;
467 payload.hi = packed.Mid;
468 payload.lo = packed.Bot;
469 payload.longFMT = (packed.Mid > 0xFFF);
470 payload.Q5 = q5;
471 payload.EM = em;
473 clearCommandBuffer();
474 SendCommandNG(CMD_LF_HID_CLONE, (uint8_t *)&payload, sizeof(payload));
475 PacketResponseNG resp;
476 if (WaitForResponseTimeout(CMD_LF_HID_CLONE, &resp, 2000) == false) {
477 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
478 return PM3_ETIMEOUT;
481 if (resp.status == PM3_SUCCESS) {
482 PrintAndLogEx(SUCCESS, "Done!");
483 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid reader`") " to verify");
484 } else {
485 PrintAndLogEx(FAILED, "cloning ( " _RED_("fail") " )");
487 return resp.status;
491 PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted");
492 PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------");
493 PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64,
494 fmtlen[i],
495 oem,
497 cardnum,
498 wiegand,
499 blocks
502 PrintAndLogEx(NORMAL, "----+-----+-----+-------+-----------+--------------------");
505 static int CmdHIDBrute(const char *Cmd) {
506 CLIParserContext *ctx;
507 CLIParserInit(&ctx, "lf hid brute",
508 "Enables bruteforce of HID readers with specified facility code or card number. This is an attack against the reader.\n"
509 "If the field being bruteforced is provided, it starts with it and goes up / down one step while maintaining other supplied values.\n"
510 "If the field being bruteforced is not provided, it will iterate through the full range while maintaining other supplied values.",
511 "lf hid brute -w H10301 --field fc --fc 224 --cn 6278\n"
512 "lf hid brute -w H10301 --field cn --fc 21 -d 2000\n"
513 "lf hid brute -v -w H10301 --field cn --fc 21 --cn 200 -d 2000\n"
514 "lf hid brute -v -w H10301 --field fc --fc 21 --cn 200 -d 2000 --up\n"
517 void *argtable[] = {
518 arg_param_begin,
519 arg_lit0("v", "verbose", "verbose output"),
520 arg_str1("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
521 arg_str1(NULL, "field", "<fc|cn>", "field to bruteforce"),
522 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
523 arg_u64_0(NULL, "cn", "<dec>", "card number"),
524 arg_u64_0("i", "issue", "<dec>", "issue level"),
525 arg_u64_0("o", "oem", "<dec>", "OEM code"),
526 arg_u64_0("d", "delay", "<dec>", "delay betweens attempts in ms. (def is 1000)"),
527 arg_lit0(NULL, "up", "direction to increment field value. (def is both directions)"),
528 arg_lit0(NULL, "down", "direction to decrement field value. (def is both directions)"),
529 arg_param_end
531 CLIExecWithReturn(ctx, Cmd, argtable, false);
533 bool verbose = arg_get_lit(ctx, 1);
535 char format[16] = {0};
536 int format_len = 0;
537 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)format, sizeof(format), &format_len);
539 int format_idx = HIDFindCardFormat(format);
540 if (format_idx == -1) {
541 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
542 CLIParserFree(ctx);
543 return PM3_EINVARG;
546 wiegand_card_t card_hi, card_low;
547 memset(&card_hi, 0, sizeof(wiegand_card_t));
549 char field[3] = {0};
550 int field_len = 0;
551 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)field, sizeof(field), &field_len);
553 card_hi.FacilityCode = arg_get_u32_def(ctx, 4, 0);
554 card_hi.CardNumber = arg_get_u32_def(ctx, 5, 0);
555 card_hi.IssueLevel = arg_get_u32_def(ctx, 6, 0);
556 card_hi.OEM = arg_get_u32_def(ctx, 7, 0);
558 uint32_t delay = arg_get_u32_def(ctx, 8, 1000);
560 int direction = 0;
561 if (arg_get_lit(ctx, 9) && arg_get_lit(ctx, 10)) {
562 direction = 0;
563 } else if (arg_get_lit(ctx, 9)) {
564 direction = 1;
565 } else if (arg_get_lit(ctx, 10)) {
566 direction = 2;
569 CLIParserFree(ctx);
571 if (verbose) {
572 PrintAndLogEx(INFO, "Wiegand format... %i", format_idx);
573 PrintAndLogEx(INFO, "OEM.............. %u", card_hi.OEM);
574 PrintAndLogEx(INFO, "ISSUE............ %u", card_hi.IssueLevel);
575 PrintAndLogEx(INFO, "Facility code.... %u", card_hi.FacilityCode);
576 PrintAndLogEx(INFO, "Card number...... %" PRIu64, card_hi.CardNumber);
577 PrintAndLogEx(INFO, "Delay............ " _YELLOW_("%d"), delay);
578 if (strcmp(field, "fc") == 0) {
579 PrintAndLogEx(INFO, "Field............ " _YELLOW_("fc"));
580 } else if (strcmp(field, "cn") == 0) {
581 PrintAndLogEx(INFO, "Field............ " _YELLOW_("cn"));
583 switch (direction) {
584 case 0:
585 PrintAndLogEx(INFO, "Direction........ " _YELLOW_("both"));
586 break;
587 case 1:
588 PrintAndLogEx(INFO, "Direction........ " _YELLOW_("up"));
589 break;
590 case 2:
591 PrintAndLogEx(INFO, "Direction........ " _YELLOW_("down"));
592 break;
593 default:
594 break;
597 PrintAndLogEx(NORMAL, "");
598 PrintAndLogEx(INFO, "Started bruteforcing HID Prox reader");
599 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or " _GREEN_("<Enter>") " to abort simulation");
600 PrintAndLogEx(NORMAL, "");
601 // copy values to low.
602 card_low = card_hi;
604 // main loop
605 bool exitloop = false;
606 bool fin_hi, fin_low;
607 fin_hi = fin_low = false;
608 do {
610 if (g_session.pm3_present == false) {
611 PrintAndLogEx(WARNING, "Device offline\n");
612 return PM3_ENODATA;
615 if (kbd_enter_pressed()) {
616 PrintAndLogEx(WARNING, "aborted via keyboard!");
617 return sendPing();
620 // do one up
621 if (direction != 2 && fin_hi != true) {
622 if (sendTry(format_idx, &card_hi, delay, verbose) != PM3_SUCCESS) {
623 return PM3_ESOFT;
625 if (strcmp(field, "fc") == 0) {
626 if (card_hi.FacilityCode < 0xFF) {
627 card_hi.FacilityCode++;
628 } else {
629 fin_hi = true;
631 } else if (strcmp(field, "cn") == 0) {
632 if (card_hi.CardNumber < 0xFFFF) {
633 card_hi.CardNumber++;
634 } else {
635 fin_hi = true;
640 // do one down
641 if (direction != 1 && fin_low != true) {
642 if (sendTry(format_idx, &card_low, delay, verbose) != PM3_SUCCESS) {
643 return PM3_ESOFT;
645 if (strcmp(field, "fc") == 0) {
646 if (card_low.FacilityCode > 0) {
647 card_low.FacilityCode--;
648 } else {
649 fin_low = true;
651 } else if (strcmp(field, "cn") == 0) {
652 if (card_low.CardNumber > 0) {
653 card_low.CardNumber--;
654 } else {
655 fin_low = true;
660 switch (direction) {
661 case 0:
662 if (fin_hi && fin_low) {
663 exitloop = true;
665 break;
666 case 1:
667 exitloop = fin_hi;
668 break;
669 case 2:
670 exitloop = fin_low;
671 break;
672 default:
673 break;
676 } while (exitloop == false);
678 PrintAndLogEx(NORMAL, "");
679 PrintAndLogEx(INFO, "Bruteforcing finished");
680 return PM3_SUCCESS;
683 static command_t CommandTable[] = {
684 {"help", CmdHelp, AlwaysAvailable, "this help"},
685 {"demod", CmdHIDDemod, AlwaysAvailable, "demodulate HID Prox tag from the GraphBuffer"},
686 {"reader", CmdHIDReader, IfPm3Lf, "attempt to read and extract tag data"},
687 {"clone", CmdHIDClone, IfPm3Lf, "clone HID tag to T55x7, Q5/T5555 or EM4305/4469"},
688 {"sim", CmdHIDSim, IfPm3Lf, "simulate HID tag"},
689 {"brute", CmdHIDBrute, IfPm3Lf, "bruteforce facility code or card number against reader"},
690 {"watch", CmdHIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
691 {NULL, NULL, NULL, NULL}
694 static int CmdHelp(const char *Cmd) {
695 (void)Cmd; // Cmd is not used so far
696 CmdsHelp(CommandTable);
697 return PM3_SUCCESS;
700 int CmdLFHID(const char *Cmd) {
701 clearCommandBuffer();
702 return CmdsParse(CommandTable, Cmd);