fix one too small
[RRG-proxmark3.git] / client / src / cmdlfhid.c
blobab41f3798e323ea16c9744f7ce8034eb6a01cd71
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))
62 return PM3_ETIMEOUT;
63 return PM3_SUCCESS;
65 static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, bool verbose) {
67 wiegand_message_t packed;
68 memset(&packed, 0, sizeof(wiegand_message_t));
70 if (HIDPack(format_idx, card, &packed, true) == false) {
71 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
72 return PM3_ESOFT;
75 if (verbose) {
76 PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%"PRIu64) " Issue level: " _YELLOW_("%u") " OEM: " _YELLOW_("%u")
77 , card->FacilityCode
78 , card->CardNumber
79 , card->IssueLevel
80 , card->OEM
84 lf_hidsim_t payload = {
85 .EM = false,
86 .Q5 = false,
87 .hi2 = packed.Top,
88 .hi = packed.Mid,
89 .lo = packed.Bot,
90 .longFMT = (packed.Mid > 0xFFF)
93 clearCommandBuffer();
95 SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
97 PacketResponseNG resp;
98 WaitForResponse(CMD_LF_HID_SIMULATE, &resp);
99 if (resp.status == PM3_EOPABORTED)
100 return resp.status;
102 msleep(delay);
103 return sendPing();
106 //by marshmellow (based on existing demod + holiman's refactor)
107 //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
108 //print full HID Prox ID and some bit format details if found
109 int demodHID(bool verbose) {
110 (void) verbose; // unused so far
112 // HID simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
113 if (isGraphBitstream()) {
114 convertGraphFromBitstream();
117 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
118 uint32_t hi2 = 0, hi = 0, lo = 0;
120 uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
121 if (bits == NULL) {
122 PrintAndLogEx(FAILED, "failed to allocate memory");
123 return PM3_EMALLOC;
125 size_t size = getFromGraphBuffer(bits);
126 if (size == 0) {
127 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
128 free(bits);
129 return PM3_ESOFT;
131 //get binary from fsk wave
132 int waveIdx = 0;
133 int idx = HIDdemodFSK(bits, &size, &hi2, &hi, &lo, &waveIdx);
134 if (idx < 0) {
136 if (idx == -1)
137 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
138 else if (idx == -2)
139 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID just noise detected"));
140 else if (idx == -3)
141 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID problem during FSK demod"));
142 else if (idx == -4)
143 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID preamble not found"));
144 else if (idx == -5)
145 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu"), size);
146 else
147 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx);
149 free(bits);
150 return PM3_ESOFT;
153 setDemodBuff(bits, size, idx);
154 setClockGrid(50, waveIdx + (idx * 50));
155 free(bits);
157 if (hi2 == 0 && hi == 0 && lo == 0) {
158 PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found"));
159 return PM3_ESOFT;
162 wiegand_message_t packed = initialize_message_object(hi2, hi, lo, 0);
163 if (HIDTryUnpack(&packed) == false) {
164 printDemodBuff(0, false, false, true);
166 PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
168 PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing DemodBuffer: ", idx, size);
169 if (g_debugMode) {
170 PrintAndLogEx(DEBUG, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
172 printDemodBuff(0, false, false, false);
175 return PM3_SUCCESS;
178 static int CmdHIDDemod(const char *Cmd) {
179 CLIParserContext *ctx;
180 CLIParserInit(&ctx, "lf hid demod",
181 "Try to find HID Prox preamble, if found decode / descramble data",
182 "lf hid demod"
185 void *argtable[] = {
186 arg_param_begin,
187 arg_param_end
189 CLIExecWithReturn(ctx, Cmd, argtable, true);
190 CLIParserFree(ctx);
191 return demodHID(true);
194 // this read is the "normal" read, which download lf signal and tries to demod here.
195 static int CmdHIDReader(const char *Cmd) {
196 CLIParserContext *ctx;
197 CLIParserInit(&ctx, "lf hid reader",
198 "read a HID Prox tag",
199 "lf hid reader -@ -> continuous reader mode"
202 void *argtable[] = {
203 arg_param_begin,
204 arg_lit0("@", NULL, "optional - continuous reader mode"),
205 arg_param_end
207 CLIExecWithReturn(ctx, Cmd, argtable, true);
208 bool cm = arg_get_lit(ctx, 1);
209 CLIParserFree(ctx);
211 if (cm) {
212 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
215 do {
216 lf_read(false, 16000);
217 demodHID(!cm);
218 } while (cm && !kbd_enter_pressed());
220 return PM3_SUCCESS;
223 // this read loops on device side.
224 // uses the demod in lfops.c
225 static int CmdHIDWatch(const char *Cmd) {
226 CLIParserContext *ctx;
228 CLIParserInit(&ctx, "lf hid watch",
229 "Enables HID compatible reader mode printing details.\n"
230 "By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
231 "lf hid watch"
234 void *argtable[] = {
235 arg_param_begin,
236 arg_param_end
238 CLIExecWithReturn(ctx, Cmd, argtable, true);
239 CLIParserFree(ctx);
241 PrintAndLogEx(SUCCESS, "Watching for HID Prox cards - place tag on antenna");
242 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to stop reading cards");
243 clearCommandBuffer();
244 SendCommandNG(CMD_LF_HID_WATCH, NULL, 0);
245 return lfsim_wait_check(CMD_LF_HID_WATCH);
248 static int CmdHIDSim(const char *Cmd) {
250 CLIParserContext *ctx;
251 CLIParserInit(&ctx, "lf hid sim",
252 "Enables simulation of HID card with card number.\n"
253 "Simulation runs until the button is pressed or another USB command is issued.",
254 "lf hid sim -r 2006ec0c86 -> HID 10301 26 bit\n"
255 "lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit\n"
256 "lf hid sim -r 01f0760643c3 -> HID P10001 40 bit\n"
257 "lf hid sim -r 01400076000c86 -> HID Corporate 48 bit\n"
258 "lf hid sim -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n"
261 void *argtable[] = {
262 arg_param_begin,
263 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
264 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
265 arg_u64_0(NULL, "cn", "<dec>", "card number"),
266 arg_u64_0("i", NULL, "<dec>", "issue level"),
267 arg_u64_0("o", "oem", "<dec>", "OEM code"),
268 arg_str0("r", "raw", "<hex>", "raw bytes"),
269 arg_param_end
271 CLIExecWithReturn(ctx, Cmd, argtable, false);
273 char format[16] = {0};
274 int format_len = 0;
275 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
277 wiegand_card_t card;
278 memset(&card, 0, sizeof(wiegand_card_t));
279 card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
280 card.CardNumber = arg_get_u32_def(ctx, 3, 0);
281 card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
282 card.OEM = arg_get_u32_def(ctx, 5, 0);
284 int raw_len = 0;
285 char raw[40] = {0};
286 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
287 CLIParserFree(ctx);
289 wiegand_message_t packed;
290 memset(&packed, 0, sizeof(wiegand_message_t));
292 // format validation
293 int format_idx = HIDFindCardFormat(format);
294 if (format_idx == -1 && raw_len == 0) {
295 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
296 return PM3_EINVARG;
299 if (raw_len) {
300 uint32_t top = 0, mid = 0, bot = 0;
301 hexstring_to_u96(&top, &mid, &bot, raw);
302 packed.Top = top;
303 packed.Mid = mid;
304 packed.Bot = bot;
305 } else {
306 if (HIDPack(format_idx, &card, &packed, true) == false) {
307 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
308 return PM3_ESOFT;
312 if (raw_len == 0) {
313 PrintAndLogEx(INFO, "Simulating HID tag");
314 HIDTryUnpack(&packed);
315 } else {
316 PrintAndLogEx(INFO, "Simulating HID tag using raw " _GREEN_("%s"), raw);
319 lf_hidsim_t payload;
320 payload.hi2 = packed.Top;
321 payload.hi = packed.Mid;
322 payload.lo = packed.Bot;
323 payload.longFMT = (packed.Mid > 0xFFF);
325 clearCommandBuffer();
326 SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
327 return lfsim_wait_check(CMD_LF_HID_SIMULATE);
330 static int CmdHIDClone(const char *Cmd) {
332 CLIParserContext *ctx;
333 CLIParserInit(&ctx, "lf hid clone",
334 "clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
335 "Tag must be on the antenna when issuing this command.",
336 "lf hid clone -r 2006ec0c86 -> write raw value for T55x7 tag (HID 10301 26 bit)\n"
337 "lf hid clone -r 2e0ec00c87 -> write raw value for T55x7 tag (HID Corporate 35 bit)\n"
338 "lf hid clone -r 01f0760643c3 -> write raw value for T55x7 tag (HID P10001 40 bit)\n"
339 "lf hid clone -r 01400076000c86 -> write raw value for T55x7 tag (HID Corporate 48 bit)\n"
340 "lf hid clone -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit, encode for T55x7 tag\n"
341 "lf hid clone -w H10301 --fc 118 --cn 1603 --q5 -> HID 10301 26 bit, encode for Q5/T5555 tag\n"
342 "lf hid clone -w H10301 --fc 118 --cn 1603 --em -> HID 10301 26 bit, encode for EM4305/4469"
345 void *argtable[] = {
346 arg_param_begin,
347 arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
348 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
349 arg_u64_0(NULL, "cn", "<dec>", "card number"),
350 arg_int0("i", NULL, "<dec>", "issue level"),
351 arg_int0("o", "oem", "<dec>", "OEM code"),
352 arg_str0("r", "raw", "<hex>", "raw bytes"),
353 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
354 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
355 arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
356 arg_param_end
358 CLIExecWithReturn(ctx, Cmd, argtable, false);
360 char format[16] = {0};
361 int format_len = 0;
362 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
364 wiegand_card_t card;
365 memset(&card, 0, sizeof(wiegand_card_t));
366 card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
367 card.CardNumber = arg_get_u32_def(ctx, 3, 0);
368 card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
369 card.OEM = arg_get_u32_def(ctx, 5, 0);
371 int raw_len = 0;
372 char raw[40] = {0};
373 CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
375 bool q5 = arg_get_lit(ctx, 7);
376 bool em = arg_get_lit(ctx, 8);
378 // TODO: very confusing sizes... buf of 70, parser len to 63 instead of 70-1, tests for len > 127, loop with 96...
379 int bin_len = 63;
380 uint8_t bin[70] = {0};
381 CLIGetStrWithReturn(ctx, 9, bin, &bin_len);
382 CLIParserFree(ctx);
384 if (q5 && em) {
385 PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
386 return PM3_EINVARG;
389 if (bin_len > 127) {
390 PrintAndLogEx(ERR, "Binary wiegand string must be less than 128 bits");
391 return PM3_EINVARG;
394 wiegand_message_t packed;
395 memset(&packed, 0, sizeof(wiegand_message_t));
397 // format validation
398 int format_idx = HIDFindCardFormat(format);
399 if (format_idx == -1 && raw_len == 0) {
400 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
401 return PM3_EINVARG;
404 uint32_t top = 0, mid = 0, bot = 0;
405 if (raw_len) {
406 hexstring_to_u96(&top, &mid, &bot, raw);
407 packed.Top = top;
408 packed.Mid = mid;
409 packed.Bot = bot;
410 } else if (bin_len) {
412 uint8_t hex[12];
413 memset(hex, 0, sizeof(hex));
414 BitstreamOut_t bout = {hex, 0, 0 };
416 for (int i = 0; i < 96 - bin_len - 1; i++) {
417 pushBit(&bout, 0);
419 // add binary sentinel bit.
420 pushBit(&bout, 1);
422 // convert binary string to hex bytes
423 for (int i = 0; i < bin_len; i++) {
424 char c = bin[i];
425 if (c == '1')
426 pushBit(&bout, 1);
427 else if (c == '0')
428 pushBit(&bout, 0);
431 packed.Length = bin_len;
432 packed.Top = bytes_to_num(hex, 4);
433 packed.Mid = bytes_to_num(hex + 4, 4);
434 packed.Bot = bytes_to_num(hex + 8, 4);
435 add_HID_header(&packed);
437 } else {
438 if (HIDPack(format_idx, &card, &packed, true) == false) {
439 PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
440 return PM3_ESOFT;
444 char cardtype[16] = {"T55x7"};
445 // Q5
446 if (q5) {
447 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
450 // EM4305
451 if (em) {
452 PrintAndLogEx(WARNING, "Beware some EM4305 tags don't support FSK and datarate = RF/50, check your tag copy!");
453 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
456 if (raw_len == 0) {
457 PrintAndLogEx(INFO, "Preparing to clone HID tag");
458 HIDUnpack(format_idx, &packed);
459 } else {
460 PrintAndLogEx(INFO, "Preparing to clone HID tag using raw " _YELLOW_("%s"), raw);
463 lf_hidsim_t payload;
464 payload.hi2 = packed.Top;
465 payload.hi = packed.Mid;
466 payload.lo = packed.Bot;
467 payload.longFMT = (packed.Mid > 0xFFF);
468 payload.Q5 = q5;
469 payload.EM = em;
471 clearCommandBuffer();
472 SendCommandNG(CMD_LF_HID_CLONE, (uint8_t *)&payload, sizeof(payload));
474 PacketResponseNG resp;
475 WaitForResponse(CMD_LF_HID_CLONE, &resp);
476 if (resp.status == PM3_SUCCESS) {
477 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid reader`") " to verify");
478 PrintAndLogEx(INFO, "Done!");
479 } else {
480 PrintAndLogEx(FAILED, "cloning ( " _RED_("fail") " )");
483 return resp.status;
487 PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted");
488 PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------");
489 PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64,
490 fmtlen[i],
491 oem,
493 cardnum,
494 wiegand,
495 blocks
498 PrintAndLogEx(NORMAL, "----+-----+-----+-------+-----------+--------------------");
501 static int CmdHIDBrute(const char *Cmd) {
502 CLIParserContext *ctx;
503 CLIParserInit(&ctx, "lf hid brute",
504 "Enables bruteforce of HID readers with specified facility code or card number. This is an attack against the reader.\n"
505 "If the field being bruteforced is provided, it starts with it and goes up / down one step while maintaining other supplied values.\n"
506 "If the field being bruteforced is not provided, it will iterate through the full range while maintaining other supplied values.",
507 "lf hid brute -w H10301 --field fc --fc 224 --cn 6278\n"
508 "lf hid brute -w H10301 --field cn --fc 21 -d 2000\n"
509 "lf hid brute -v -w H10301 --field cn --fc 21 --cn 200 -d 2000\n"
510 "lf hid brute -v -w H10301 --field fc --fc 21 --cn 200 -d 2000 --up\n"
513 void *argtable[] = {
514 arg_param_begin,
515 arg_lit0("v", "verbose", "verbose output"),
516 arg_str1("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
517 arg_str1(NULL, "field", "<fc|cn>", "field to bruteforce"),
518 arg_u64_0(NULL, "fc", "<dec>", "facility code"),
519 arg_u64_0(NULL, "cn", "<dec>", "card number"),
520 arg_u64_0("i", "issue", "<dec>", "issue level"),
521 arg_u64_0("o", "oem", "<dec>", "OEM code"),
522 arg_u64_0("d", "delay", "<dec>", "delay betweens attempts in ms. (def is 1000)"),
523 arg_lit0(NULL, "up", "direction to increment field value. (def is both directions)"),
524 arg_lit0(NULL, "down", "direction to decrement field value. (def is both directions)"),
525 arg_param_end
527 CLIExecWithReturn(ctx, Cmd, argtable, false);
529 bool verbose = arg_get_lit(ctx, 1);
531 char format[16] = {0};
532 int format_len = 0;
533 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)format, sizeof(format), &format_len);
535 int format_idx = HIDFindCardFormat(format);
536 if (format_idx == -1) {
537 PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
538 CLIParserFree(ctx);
539 return PM3_EINVARG;
542 wiegand_card_t card_hi, card_low;
543 memset(&card_hi, 0, sizeof(wiegand_card_t));
545 char field[3] = {0};
546 int field_len = 0;
547 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)field, sizeof(field), &field_len);
549 card_hi.FacilityCode = arg_get_u32_def(ctx, 4, 0);
550 card_hi.CardNumber = arg_get_u32_def(ctx, 5, 0);
551 card_hi.IssueLevel = arg_get_u32_def(ctx, 6, 0);
552 card_hi.OEM = arg_get_u32_def(ctx, 7, 0);
554 uint32_t delay = arg_get_u32_def(ctx, 8, 1000);
556 int direction = 0;
557 if (arg_get_lit(ctx, 9) && arg_get_lit(ctx, 10)) {
558 direction = 0;
559 } else if (arg_get_lit(ctx, 9)) {
560 direction = 1;
561 } else if (arg_get_lit(ctx, 10)) {
562 direction = 2;
565 CLIParserFree(ctx);
567 if (verbose) {
568 PrintAndLogEx(INFO, "Wiegand format... %i", format_idx);
569 PrintAndLogEx(INFO, "OEM.............. %u", card_hi.OEM);
570 PrintAndLogEx(INFO, "ISSUE............ %u", card_hi.IssueLevel);
571 PrintAndLogEx(INFO, "Facility code.... %u", card_hi.FacilityCode);
572 PrintAndLogEx(INFO, "Card number...... %" PRIu64, card_hi.CardNumber);
573 PrintAndLogEx(INFO, "Delay............ " _YELLOW_("%d"), delay);
574 if (strcmp(field, "fc") == 0) {
575 PrintAndLogEx(INFO, "Field............ " _YELLOW_("fc"));
576 } else if (strcmp(field, "cn") == 0) {
577 PrintAndLogEx(INFO, "Field............ " _YELLOW_("cn"));
579 switch (direction) {
580 case 0:
581 PrintAndLogEx(INFO, "Direction........ " _YELLOW_("both"));
582 break;
583 case 1:
584 PrintAndLogEx(INFO, "Direction........ " _YELLOW_("up"));
585 break;
586 case 2:
587 PrintAndLogEx(INFO, "Direction........ " _YELLOW_("down"));
588 break;
589 default:
590 break;
593 PrintAndLogEx(NORMAL, "");
594 PrintAndLogEx(INFO, "Started bruteforcing HID Prox reader");
595 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or " _GREEN_("<Enter>") " to abort simulation");
596 PrintAndLogEx(NORMAL, "");
597 // copy values to low.
598 card_low = card_hi;
600 // main loop
601 bool exitloop = false;
602 bool fin_hi, fin_low;
603 fin_hi = fin_low = false;
604 do {
606 if (g_session.pm3_present == false) {
607 PrintAndLogEx(WARNING, "Device offline\n");
608 return PM3_ENODATA;
611 if (kbd_enter_pressed()) {
612 PrintAndLogEx(WARNING, "aborted via keyboard!");
613 return sendPing();
616 // do one up
617 if (direction != 2 && fin_hi != true) {
618 if (sendTry(format_idx, &card_hi, delay, verbose) != PM3_SUCCESS) {
619 return PM3_ESOFT;
621 if (strcmp(field, "fc") == 0) {
622 if (card_hi.FacilityCode < 0xFF) {
623 card_hi.FacilityCode++;
624 } else {
625 fin_hi = true;
627 } else if (strcmp(field, "cn") == 0) {
628 if (card_hi.CardNumber < 0xFFFF) {
629 card_hi.CardNumber++;
630 } else {
631 fin_hi = true;
636 // do one down
637 if (direction != 1 && fin_low != true) {
638 if (sendTry(format_idx, &card_low, delay, verbose) != PM3_SUCCESS) {
639 return PM3_ESOFT;
641 if (strcmp(field, "fc") == 0) {
642 if (card_low.FacilityCode > 0) {
643 card_low.FacilityCode--;
644 } else {
645 fin_low = true;
647 } else if (strcmp(field, "cn") == 0) {
648 if (card_low.CardNumber > 0) {
649 card_low.CardNumber--;
650 } else {
651 fin_low = true;
656 switch (direction) {
657 case 0:
658 if (fin_hi && fin_low) {
659 exitloop = true;
661 break;
662 case 1:
663 exitloop = fin_hi;
664 break;
665 case 2:
666 exitloop = fin_low;
667 break;
668 default:
669 break;
672 } while (exitloop == false);
674 PrintAndLogEx(NORMAL, "");
675 PrintAndLogEx(INFO, "Bruteforcing finished");
676 return PM3_SUCCESS;
679 static command_t CommandTable[] = {
680 {"help", CmdHelp, AlwaysAvailable, "this help"},
681 {"demod", CmdHIDDemod, AlwaysAvailable, "demodulate HID Prox tag from the GraphBuffer"},
682 {"reader", CmdHIDReader, IfPm3Lf, "attempt to read and extract tag data"},
683 {"clone", CmdHIDClone, IfPm3Lf, "clone HID tag to T55x7, Q5/T5555 or EM4305/4469"},
684 {"sim", CmdHIDSim, IfPm3Lf, "simulate HID tag"},
685 {"brute", CmdHIDBrute, IfPm3Lf, "bruteforce facility code or card number against reader"},
686 {"watch", CmdHIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
687 {NULL, NULL, NULL, NULL}
690 static int CmdHelp(const char *Cmd) {
691 (void)Cmd; // Cmd is not used so far
692 CmdsHelp(CommandTable);
693 return PM3_SUCCESS;
696 int CmdLFHID(const char *Cmd) {
697 clearCommandBuffer();
698 return CmdsParse(CommandTable, Cmd);