mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-12 12:41:49 +08:00
636 lines
22 KiB
C
636 lines
22 KiB
C
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
|
// 2016,2017, marshmellow, iceman
|
|
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
|
// at your option, any later version. See the LICENSE.txt file for the text of
|
|
// the license.
|
|
//-----------------------------------------------------------------------------
|
|
// Low frequency HID commands (known)
|
|
//
|
|
// Useful resources:
|
|
// RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding:
|
|
// http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf
|
|
//
|
|
// "Understanding Card Data Formats"
|
|
// https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf
|
|
//
|
|
// "What Format Do You Need?"
|
|
// https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "cmdlfhid.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <inttypes.h>
|
|
#include "cmdparser.h" // command_t
|
|
#include "comms.h"
|
|
#include "commonutil.h" // ARRAYLEN
|
|
#include "cliparser.h"
|
|
#include "ui.h"
|
|
#include "graph.h"
|
|
#include "cmddata.h" // g_debugMode, demodbuff cmds
|
|
#include "cmdlf.h" // lf_read, lfsim_wait_check
|
|
#include "util_posix.h"
|
|
#include "lfdemod.h"
|
|
#include "wiegand_formats.h"
|
|
#include "wiegand_formatutils.h"
|
|
#include "cmdlfem4x05.h" // EM defines
|
|
|
|
#ifndef BITS
|
|
# define BITS 96
|
|
#endif
|
|
|
|
static int CmdHelp(const char *Cmd);
|
|
|
|
// sending three times. Didn't seem to break the previous sim?
|
|
static int sendPing(void) {
|
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
|
SendCommandNG(CMD_PING, NULL, 0);
|
|
clearCommandBuffer();
|
|
PacketResponseNG resp;
|
|
if (!WaitForResponseTimeout(CMD_PING, &resp, 1000))
|
|
return PM3_ETIMEOUT;
|
|
return PM3_SUCCESS;
|
|
}
|
|
static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, bool verbose) {
|
|
|
|
wiegand_message_t packed;
|
|
memset(&packed, 0, sizeof(wiegand_message_t));
|
|
|
|
if (HIDPack(format_idx, card, &packed, true) == false) {
|
|
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
|
|
return PM3_ESOFT;
|
|
}
|
|
|
|
if (verbose) {
|
|
PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%"PRIu64) " Issue level: " _YELLOW_("%u") " OEM: " _YELLOW_("%u")
|
|
, card->FacilityCode
|
|
, card->CardNumber
|
|
, card->IssueLevel
|
|
, card->OEM
|
|
);
|
|
}
|
|
|
|
lf_hidsim_t payload;
|
|
payload.hi2 = packed.Top;
|
|
payload.hi = packed.Mid;
|
|
payload.lo = packed.Bot;
|
|
payload.longFMT = (packed.Mid > 0xFFF);
|
|
|
|
clearCommandBuffer();
|
|
|
|
SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
|
/*
|
|
PacketResponseNG resp;
|
|
WaitForResponse(CMD_LF_HID_SIMULATE, &resp);
|
|
if (resp.status == PM3_EOPABORTED)
|
|
return resp.status;
|
|
*/
|
|
msleep(delay);
|
|
return sendPing();
|
|
}
|
|
|
|
//by marshmellow (based on existing demod + holiman's refactor)
|
|
//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
|
|
//print full HID Prox ID and some bit format details if found
|
|
int demodHID(bool verbose) {
|
|
(void) verbose; // unused so far
|
|
|
|
// HID simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
|
|
if (isGraphBitstream()) {
|
|
convertGraphFromBitstream();
|
|
}
|
|
|
|
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
|
uint32_t hi2 = 0, hi = 0, lo = 0;
|
|
|
|
uint8_t bits[GraphTraceLen];
|
|
size_t size = getFromGraphBuf(bits);
|
|
if (size == 0) {
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
|
|
return PM3_ESOFT;
|
|
}
|
|
//get binary from fsk wave
|
|
int waveIdx = 0;
|
|
int idx = HIDdemodFSK(bits, &size, &hi2, &hi, &lo, &waveIdx);
|
|
if (idx < 0) {
|
|
|
|
if (idx == -1)
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
|
|
else if (idx == -2)
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID just noise detected"));
|
|
else if (idx == -3)
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID problem during FSK demod"));
|
|
else if (idx == -4)
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID preamble not found"));
|
|
else if (idx == -5)
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error in Manchester data, size %zu"), size);
|
|
else
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx);
|
|
|
|
return PM3_ESOFT;
|
|
}
|
|
|
|
setDemodBuff(bits, size, idx);
|
|
setClockGrid(50, waveIdx + (idx * 50));
|
|
|
|
if (hi2 == 0 && hi == 0 && lo == 0) {
|
|
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found"));
|
|
return PM3_ESOFT;
|
|
}
|
|
|
|
wiegand_message_t packed = initialize_message_object(hi2, hi, lo);
|
|
if (HIDTryUnpack(&packed, false) == false) {
|
|
printDemodBuff(0, false, false, true);
|
|
}
|
|
PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
|
|
|
|
PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer: ", idx, size);
|
|
if (g_debugMode) {
|
|
PrintAndLogEx(DEBUG, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
|
|
|
|
printDemodBuff(0, false, false, false);
|
|
}
|
|
|
|
return PM3_SUCCESS;
|
|
}
|
|
|
|
static int CmdHIDDemod(const char *Cmd) {
|
|
CLIParserContext *ctx;
|
|
CLIParserInit(&ctx, "lf hid demod",
|
|
"Try to find HID Prox preamble, if found decode / descramble data",
|
|
"lf hid demod"
|
|
);
|
|
|
|
void *argtable[] = {
|
|
arg_param_begin,
|
|
arg_param_end
|
|
};
|
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
|
CLIParserFree(ctx);
|
|
return demodHID(true);
|
|
}
|
|
|
|
// this read is the "normal" read, which download lf signal and tries to demod here.
|
|
static int CmdHIDReader(const char *Cmd) {
|
|
CLIParserContext *ctx;
|
|
CLIParserInit(&ctx, "lf hid reader",
|
|
"read a HID Prox tag",
|
|
"lf hid reader -@ -> continuous reader mode"
|
|
);
|
|
|
|
void *argtable[] = {
|
|
arg_param_begin,
|
|
arg_lit0("@", NULL, "optional - continuous reader mode"),
|
|
arg_param_end
|
|
};
|
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
|
bool cm = arg_get_lit(ctx, 1);
|
|
CLIParserFree(ctx);
|
|
|
|
if (cm) {
|
|
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
|
}
|
|
|
|
do {
|
|
lf_read(false, 16000);
|
|
demodHID(!cm);
|
|
} while (cm && !kbd_enter_pressed());
|
|
|
|
return PM3_SUCCESS;
|
|
}
|
|
|
|
// this read loops on device side.
|
|
// uses the demod in lfops.c
|
|
static int CmdHIDWatch(const char *Cmd) {
|
|
CLIParserContext *ctx;
|
|
|
|
CLIParserInit(&ctx, "lf hid watch",
|
|
"Enables HID compatible reader mode printing details.\n"
|
|
"By default, values are printed and logged until the button is pressed or another USB command is issued.\n",
|
|
"lf hid watch"
|
|
);
|
|
|
|
void *argtable[] = {
|
|
arg_param_begin,
|
|
arg_param_end
|
|
};
|
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
|
CLIParserFree(ctx);
|
|
|
|
PrintAndLogEx(SUCCESS, "Watching for HID Prox cards - place tag on antenna");
|
|
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
|
|
clearCommandBuffer();
|
|
SendCommandNG(CMD_LF_HID_WATCH, NULL, 0);
|
|
return lfsim_wait_check(CMD_LF_HID_WATCH);
|
|
}
|
|
|
|
static int CmdHIDSim(const char *Cmd) {
|
|
|
|
CLIParserContext *ctx;
|
|
CLIParserInit(&ctx, "lf hid sim",
|
|
"Enables simulation of HID card with card number.\n"
|
|
"Simulation runs until the button is pressed or another USB command is issued.",
|
|
"lf hid sim -r 2006ec0c86 -> HID 10301 26 bit\n"
|
|
"lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit\n"
|
|
"lf hid sim -r 01f0760643c3 -> HID P10001 40 bit\n"
|
|
"lf hid sim -r 01400076000c86 -> HID Corporate 48 bit\n"
|
|
"lf hid sim -w H10301 --fc 118 --cn 1603 -> HID 10301 26 bit\n"
|
|
);
|
|
|
|
void *argtable[] = {
|
|
arg_param_begin,
|
|
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
|
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
|
|
arg_u64_0(NULL, "cn", "<dec>", "card number"),
|
|
arg_u64_0("i", NULL, "<dec>", "issue level"),
|
|
arg_u64_0("o", "oem", "<dec>", "OEM code"),
|
|
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
|
arg_param_end
|
|
};
|
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
|
|
|
char format[16] = {0};
|
|
int format_len = 0;
|
|
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
|
|
|
|
wiegand_card_t card;
|
|
memset(&card, 0, sizeof(wiegand_card_t));
|
|
card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
|
|
card.CardNumber = arg_get_u32_def(ctx, 3, 0);
|
|
card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
|
|
card.OEM = arg_get_u32_def(ctx, 5, 0);
|
|
|
|
int raw_len = 0;
|
|
char raw[40] = {0};
|
|
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
|
|
CLIParserFree(ctx);
|
|
|
|
wiegand_message_t packed;
|
|
memset(&packed, 0, sizeof(wiegand_message_t));
|
|
|
|
// format validation
|
|
int format_idx = HIDFindCardFormat((char *)format);
|
|
if (format_idx == -1 && raw_len == 0) {
|
|
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
|
return PM3_EINVARG;
|
|
}
|
|
|
|
if (raw_len) {
|
|
uint32_t top = 0, mid = 0, bot = 0;
|
|
hexstring_to_u96(&top, &mid, &bot, raw);
|
|
packed.Top = top;
|
|
packed.Mid = mid;
|
|
packed.Bot = bot;
|
|
} else {
|
|
if (HIDPack(format_idx, &card, &packed, true) == false) {
|
|
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
|
|
return PM3_ESOFT;
|
|
}
|
|
}
|
|
|
|
if (raw_len == 0) {
|
|
PrintAndLogEx(INFO, "Simulating HID tag");
|
|
HIDTryUnpack(&packed, false);
|
|
} else {
|
|
PrintAndLogEx(INFO, "Simulating HID tag using raw " _GREEN_("%s"), raw);
|
|
}
|
|
|
|
lf_hidsim_t payload;
|
|
payload.hi2 = packed.Top;
|
|
payload.hi = packed.Mid;
|
|
payload.lo = packed.Bot;
|
|
payload.longFMT = (packed.Mid > 0xFFF);
|
|
|
|
clearCommandBuffer();
|
|
SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
|
return lfsim_wait_check(CMD_LF_HID_SIMULATE);
|
|
}
|
|
|
|
static int CmdHIDClone(const char *Cmd) {
|
|
|
|
CLIParserContext *ctx;
|
|
CLIParserInit(&ctx, "lf hid clone",
|
|
"clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
|
|
"Tag must be on the antenna when issuing this command.",
|
|
"lf hid clone -r 2006ec0c86 -> write raw value (HID 10301 26 bit)\n"
|
|
"lf hid clone -r 2e0ec00c87 -> write raw value (HID Corporate 35 bit)\n"
|
|
"lf hid clone -r 01f0760643c3 -> write raw value (HID P10001 40 bit)\n"
|
|
"lf hid clone -r 01400076000c86 -> write raw value (HID Corporate 48 bit)\n"
|
|
"lf hid clone -w H10301 --fc 118 --cn 1603 -> write raw value (HID 10301 26 bit)\n"
|
|
"lf hid clone -w H10301 --fc 118 --cn 1603 --q5 -> HID 10301 26 bit, encode for Q5/T5555 tag\n"
|
|
"lf hid clone -w H10301 --fc 118 --cn 1603 --em -> HID 10301 26 bit, encode for EM4305/4469"
|
|
);
|
|
|
|
void *argtable[] = {
|
|
arg_param_begin,
|
|
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
|
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
|
|
arg_u64_0(NULL, "cn", "<dec>", "card number"),
|
|
arg_int0("i", NULL, "<dec>", "issue level"),
|
|
arg_int0("o", "oem", "<dec>", "OEM code"),
|
|
arg_strx0("r", "raw", "<hex>", "raw bytes"),
|
|
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
|
|
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
|
|
arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
|
|
arg_param_end
|
|
};
|
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
|
|
|
char format[16] = {0};
|
|
int format_len = 0;
|
|
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &format_len);
|
|
|
|
wiegand_card_t card;
|
|
memset(&card, 0, sizeof(wiegand_card_t));
|
|
card.FacilityCode = arg_get_u32_def(ctx, 2, 0);
|
|
card.CardNumber = arg_get_u32_def(ctx, 3, 0);
|
|
card.IssueLevel = arg_get_u32_def(ctx, 4, 0);
|
|
card.OEM = arg_get_u32_def(ctx, 5, 0);
|
|
|
|
int raw_len = 0;
|
|
char raw[40] = {0};
|
|
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)raw, sizeof(raw), &raw_len);
|
|
|
|
bool q5 = arg_get_lit(ctx, 7);
|
|
bool em = arg_get_lit(ctx, 8);
|
|
|
|
int bin_len = 63;
|
|
uint8_t bin[70] = {0};
|
|
CLIGetStrWithReturn(ctx, 9, bin, &bin_len);
|
|
CLIParserFree(ctx);
|
|
|
|
if (q5 && em) {
|
|
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
|
|
return PM3_EINVARG;
|
|
}
|
|
|
|
if (bin_len > 127) {
|
|
PrintAndLogEx(ERR, "Binary wiegand string must be less than 128 bits");
|
|
return PM3_EINVARG;
|
|
}
|
|
|
|
wiegand_message_t packed;
|
|
memset(&packed, 0, sizeof(wiegand_message_t));
|
|
|
|
// format validation
|
|
int format_idx = HIDFindCardFormat((char *)format);
|
|
if (format_idx == -1 && raw_len == 0) {
|
|
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
|
return PM3_EINVARG;
|
|
}
|
|
|
|
uint32_t top = 0, mid = 0, bot = 0;
|
|
if (raw_len) {
|
|
hexstring_to_u96(&top, &mid, &bot, raw);
|
|
packed.Top = top;
|
|
packed.Mid = mid;
|
|
packed.Bot = bot;
|
|
} else if (bin_len) {
|
|
int res = binstring_to_u96(&top, &mid, &bot, (const char *)bin);
|
|
if (res != bin_len) {
|
|
PrintAndLogEx(ERR, "Binary string contains none <0|1> chars");
|
|
return PM3_EINVARG;
|
|
}
|
|
packed.Top = top;
|
|
packed.Mid = mid;
|
|
packed.Bot = bot;
|
|
} else {
|
|
if (HIDPack(format_idx, &card, &packed, true) == false) {
|
|
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
|
|
return PM3_ESOFT;
|
|
}
|
|
}
|
|
|
|
char cardtype[16] = {"T55x7"};
|
|
// Q5
|
|
if (q5) {
|
|
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
|
|
}
|
|
|
|
// EM4305
|
|
if (em) {
|
|
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
|
|
}
|
|
|
|
if (raw_len == 0) {
|
|
PrintAndLogEx(INFO, "Preparing to clone HID tag");
|
|
HIDTryUnpack(&packed, false);
|
|
} else {
|
|
PrintAndLogEx(INFO, "Preparing to clone HID tag using raw " _YELLOW_("%s"), raw);
|
|
}
|
|
|
|
lf_hidsim_t payload;
|
|
payload.hi2 = packed.Top;
|
|
payload.hi = packed.Mid;
|
|
payload.lo = packed.Bot;
|
|
payload.longFMT = (packed.Mid > 0xFFF);
|
|
payload.Q5 = q5;
|
|
payload.EM = em;
|
|
|
|
clearCommandBuffer();
|
|
SendCommandNG(CMD_LF_HID_CLONE, (uint8_t *)&payload, sizeof(payload));
|
|
|
|
PacketResponseNG resp;
|
|
WaitForResponse(CMD_LF_HID_CLONE, &resp);
|
|
if (resp.status == PM3_SUCCESS) {
|
|
PrintAndLogEx(INFO, "Done");
|
|
} else {
|
|
PrintAndLogEx(FAILED, "Failed cloning");
|
|
return resp.status;
|
|
}
|
|
|
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf hid reader`") " to verify");
|
|
return PM3_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted");
|
|
PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------");
|
|
PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64,
|
|
fmtlen[i],
|
|
oem,
|
|
fc,
|
|
cardnum,
|
|
wiegand,
|
|
blocks
|
|
);
|
|
}
|
|
PrintAndLogEx(NORMAL, "----+-----+-----+-------+-----------+--------------------");
|
|
*/
|
|
|
|
static int CmdHIDBrute(const char *Cmd) {
|
|
|
|
uint32_t delay = 1000;
|
|
int format_idx = -1;
|
|
int direction = 0;
|
|
uint8_t format[16] = {0};
|
|
int formatLen;
|
|
|
|
wiegand_card_t cn_hi, cn_low;
|
|
memset(&cn_hi, 0, sizeof(wiegand_card_t));
|
|
|
|
CLIParserContext *ctx;
|
|
CLIParserInit(&ctx, "lf hid brute",
|
|
"Enables bruteforce of HID readers with specified facility code.\n"
|
|
"This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step\n"
|
|
"if cardnumber is not given, it starts with 1 and goes up to 65535",
|
|
"lf hid brute -w H10301 --fc 224\n"
|
|
"lf hid brute -w H10301 --fc 21 -d 2000\n"
|
|
"lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000\n"
|
|
"lf hid brute -v -w H10301 --fc 21 --cn 200 -d 2000 --up\n"
|
|
);
|
|
|
|
void *argtable[] = {
|
|
arg_param_begin,
|
|
arg_lit0("v", "verbose", "verbose logging, show all tries"),
|
|
arg_str1("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
|
|
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
|
|
arg_u64_0(NULL, "cn", "<dec>", "card number to start with"),
|
|
arg_u64_0("i", "issue", "<dec>", "issue level"),
|
|
arg_u64_0("o", "oem", "<dec>", "OEM code"),
|
|
arg_u64_0("d", "delay", "<dec>", "delay betweens attempts in ms. Default 1000ms"),
|
|
arg_lit0(NULL, "up", "direction to increment card number. (default is both directions)"),
|
|
arg_lit0(NULL, "down", "direction to decrement card number. (default is both directions)"),
|
|
arg_param_end
|
|
};
|
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
|
|
|
bool verbose = arg_get_lit(ctx, 1);
|
|
formatLen = sizeof(format);
|
|
CLIGetStrWithReturn(ctx, 2, format, &formatLen);
|
|
|
|
format_idx = HIDFindCardFormat((char *) format);
|
|
if (format_idx == -1) {
|
|
PrintAndLogEx(WARNING, "Unknown format: " _YELLOW_("%s"), format);
|
|
CLIParserFree(ctx);
|
|
return PM3_EINVARG;
|
|
}
|
|
|
|
cn_hi.FacilityCode = arg_get_u32_def(ctx, 3, 0);
|
|
cn_hi.CardNumber = arg_get_u32_def(ctx, 4, 0);
|
|
cn_hi.IssueLevel = arg_get_u32_def(ctx, 5, 0);
|
|
cn_hi.OEM = arg_get_u32_def(ctx, 6, 0);
|
|
delay = arg_get_u32_def(ctx, 7, 1000);
|
|
|
|
if (arg_get_lit(ctx, 8) && arg_get_lit(ctx, 9)) {
|
|
direction = 0;
|
|
} else if (arg_get_lit(ctx, 8)) {
|
|
direction = 1;
|
|
} else if (arg_get_lit(ctx, 9)) {
|
|
direction = 2;
|
|
}
|
|
|
|
CLIParserFree(ctx);
|
|
|
|
if (verbose) {
|
|
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
|
|
PrintAndLogEx(INFO, "OEM#............. %u", cn_hi.OEM);
|
|
PrintAndLogEx(INFO, "ISSUE#........... %u", cn_hi.IssueLevel);
|
|
PrintAndLogEx(INFO, "Facility#........ %u", cn_hi.FacilityCode);
|
|
PrintAndLogEx(INFO, "Card#............ %" PRIu64, cn_hi.CardNumber);
|
|
switch (direction) {
|
|
case 0:
|
|
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH") " delay " _YELLOW_("%d"), delay);
|
|
break;
|
|
case 1:
|
|
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("UP") " delay " _YELLOW_("%d"), delay);
|
|
break;
|
|
case 2:
|
|
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN") " delay " _YELLOW_("%d"), delay);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
PrintAndLogEx(INFO, "Started brute-forcing HID Prox reader");
|
|
PrintAndLogEx(INFO, "Press pm3-button to abort simulation or press " _GREEN_("`<enter>`") " to exit");
|
|
|
|
// copy values to low.
|
|
cn_low = cn_hi;
|
|
|
|
// main loop
|
|
// iceman: could add options for bruteforcing OEM, ISSUE or FC as well..
|
|
bool exitloop = false;
|
|
bool fin_hi, fin_low;
|
|
fin_hi = fin_low = false;
|
|
do {
|
|
|
|
if (!session.pm3_present) {
|
|
PrintAndLogEx(WARNING, "Device offline\n");
|
|
return PM3_ENODATA;
|
|
}
|
|
|
|
if (kbd_enter_pressed()) {
|
|
PrintAndLogEx(INFO, "aborted via keyboard!");
|
|
return sendPing();
|
|
}
|
|
|
|
// do one up
|
|
if (direction != 2) {
|
|
if (cn_hi.CardNumber < 0xFFFF) {
|
|
cn_hi.CardNumber++;
|
|
if (sendTry(format_idx, &cn_hi, delay, verbose) != PM3_SUCCESS) {
|
|
return PM3_ESOFT;
|
|
}
|
|
} else {
|
|
fin_hi = true;
|
|
}
|
|
}
|
|
|
|
// do one down
|
|
if (direction != 1) {
|
|
if (cn_low.CardNumber > 0) {
|
|
cn_low.CardNumber--;
|
|
if (sendTry(format_idx, &cn_low, delay, verbose) != PM3_SUCCESS) {
|
|
return PM3_ESOFT;
|
|
}
|
|
} else {
|
|
fin_low = true;
|
|
}
|
|
}
|
|
|
|
switch (direction) {
|
|
case 0:
|
|
if (fin_hi && fin_low) {
|
|
exitloop = true;
|
|
}
|
|
break;
|
|
case 1:
|
|
exitloop = fin_hi;
|
|
break;
|
|
case 2:
|
|
exitloop = fin_low;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
} while (exitloop == false);
|
|
|
|
PrintAndLogEx(INFO, "Brute forcing finished");
|
|
return PM3_SUCCESS;
|
|
}
|
|
|
|
static command_t CommandTable[] = {
|
|
{"help", CmdHelp, AlwaysAvailable, "this help"},
|
|
{"demod", CmdHIDDemod, AlwaysAvailable, "demodulate HID Prox tag from the GraphBuffer"},
|
|
{"reader", CmdHIDReader, IfPm3Lf, "attempt to read and extract tag data"},
|
|
{"clone", CmdHIDClone, IfPm3Lf, "clone HID tag to T55x7"},
|
|
{"sim", CmdHIDSim, IfPm3Lf, "simulate HID tag"},
|
|
{"brute", CmdHIDBrute, IfPm3Lf, "bruteforce card number against reader"},
|
|
{"watch", CmdHIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
|
|
{NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
static int CmdHelp(const char *Cmd) {
|
|
(void)Cmd; // Cmd is not used so far
|
|
CmdsHelp(CommandTable);
|
|
return PM3_SUCCESS;
|
|
}
|
|
|
|
int CmdLFHID(const char *Cmd) {
|
|
clearCommandBuffer();
|
|
return CmdsParse(CommandTable, Cmd);
|
|
}
|