fix incorrect HID bitlen calculations and wiegand format display

This commit is contained in:
Donny 2025-02-15 21:56:19 -08:00
parent 430ef1f273
commit 3f794818f0
8 changed files with 69 additions and 40 deletions

@ -1316,10 +1316,6 @@ int lf_hid_watch(int findone, uint32_t *high, uint32_t *low, bool ledcontrol) {
cardnum = (lo >> 1) & 0xFFFF;
fac = (lo >> 17) & 0xFF;
}
if (bitlen == 37) {
cardnum = (lo >> 1) & 0x7FFFF;
fac = ((hi & 0xF) << 12) | (lo >> 20);
}
if (bitlen == 34) {
cardnum = (lo >> 1) & 0xFFFF;
fac = ((hi & 1) << 15) | (lo >> 17);

@ -1451,8 +1451,7 @@ static int iclass_decode_credentials_new_pacs(uint8_t *d) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
HIDTryUnpack(&packed);
decode_wiegand(top, mid, bot, 0);
return PM3_SUCCESS;
}
@ -1492,8 +1491,7 @@ static void iclass_decode_credentials(uint8_t *data) {
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), pbin);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
HIDTryUnpack(&packed);
decode_wiegand(top, mid, bot, 0);
}
} else {
@ -2916,8 +2914,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
PrintAndLogEx(SUCCESS, " bin : %s", pbin);
PrintAndLogEx(INFO, "");
PrintAndLogEx(INFO, "------------------------------ " _CYAN_("Wiegand") " -------------------------------");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
HIDTryUnpack(&packed);
decode_wiegand(top, mid, bot, 0);
}
} else {
PrintAndLogEx(INFO, "no credential found");

@ -6293,8 +6293,7 @@ static int CmdHF14AMfMAD(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Binary... " _GREEN_("%s"), pbin);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
HIDTryUnpack(&packed);
decode_wiegand(top, mid, bot, 0);
}
}

@ -160,8 +160,7 @@ int demodHID(bool verbose) {
return PM3_ESOFT;
}
wiegand_message_t packed = initialize_message_object(hi2, hi, lo, 0);
if (HIDTryUnpack(&packed) == false) {
if (!decode_wiegand(hi2, hi, lo, 0)) { // if failed to unpack wiegand
printDemodBuff(0, false, false, true);
}
PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
@ -214,8 +213,8 @@ static int CmdHIDReader(const char *Cmd) {
}
do {
lf_read(false, 16000);
demodHID(!cm);
lf_read(false, 16000); // get data of 16000 samples from proxmark device
demodHID(!cm); // demod data and print results if found
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;

@ -160,8 +160,7 @@ int CmdWiegandDecode(const char *Cmd) {
return PM3_EINVARG;
}
wiegand_message_t packed = initialize_message_object(top, mid, bot, blen);
HIDTryUnpack(&packed);
decode_wiegand(top, mid, bot, blen);
return PM3_SUCCESS;
}

@ -1534,18 +1534,18 @@ bool HIDTryUnpack(wiegand_message_t *packed) {
found_cnt++;
hid_print_card(&card, FormatTable[i]);
if (FormatTable[i].Fields.hasParity || card.ParityValid == false)
// if fields has parity AND card parity is false
if (FormatTable[i].Fields.hasParity && (card.ParityValid == false))
found_invalid_par++;
}
++i;
}
if (found_cnt) {
PrintAndLogEx(INFO, "found %u matching format%c", found_cnt, (found_cnt > 1) ? 's' : ' ');
PrintAndLogEx(INFO, "found %u matching format%c with bit len %d", found_cnt, (found_cnt > 1) ? 's' : ' ', packed->Length);
}
if (packed->Length && found_invalid_par == 0) {
if (packed->Length && ((found_cnt - found_invalid_par) == 0)) { // if length > 0 and no valid parity matches
PrintAndLogEx(WARNING, "Wiegand unknown bit len %d", packed->Length);
PrintAndLogEx(HINT, "Try 0xFFFF's http://cardinfo.barkweb.com.au/");
}
@ -1561,6 +1561,31 @@ void HIDUnpack(int idx, wiegand_message_t *packed) {
}
}
// decode wiegand format using HIDTryUnpack
// return true if at least one valid matching formats found
bool decode_wiegand(uint32_t top, uint32_t mid, uint32_t bot, int n) {
bool decode_result;
if (top == 0 && mid == 0 && bot == 0) {
decode_result = false;
} else if ((n > 0) || ((mid & 0xFFFFFFC0) > 0)) { // if n > 0 or there's more than 38 bits
wiegand_message_t packed = initialize_message_object(top, mid, bot, n);
decode_result = HIDTryUnpack(&packed);
} else { // n <= 0 and 39-64 bits are all 0, try two possible bitlens
wiegand_message_t packed1 = initialize_message_object(top, mid, bot, n); // 26-37 bits
wiegand_message_t packed2 = initialize_message_object(top, mid, bot, 38); // 38 bits
bool packed1_result = HIDTryUnpack(&packed1);
bool packed2_result = HIDTryUnpack(&packed2);
decode_result = (packed1_result || packed2_result);
}
if (decode_result == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found"));
}
return decode_result;
}
int HIDDumpPACSBits(const uint8_t *const data, const uint8_t length, bool verbose) {
uint8_t n = length - 1;
uint8_t pad = data[0];

@ -58,6 +58,7 @@ bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bo
bool HIDTryUnpack(wiegand_message_t *packed);
void HIDPackTryAll(wiegand_card_t *card, bool preamble);
void HIDUnpack(int idx, wiegand_message_t *packed);
bool decode_wiegand(uint32_t top, uint32_t mid, uint32_t bot, int n);
int HIDDumpPACSBits(const uint8_t *const data, const uint8_t length, bool verbose);
void print_wiegand_code(wiegand_message_t *packed);
void print_desc_wiegand(cardformat_t *fmt, wiegand_message_t *packed);

@ -132,7 +132,23 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
/**
* detect if message has "preamble" / "sentinel bit"
* Right now we just calculate the highest bit set
* 37 bit formats is hard to detect since it doesnt have a sentinel bit
* 38 bits format is handled by directly setting n=38 in initialize_message_object()
* since it's hard to distinguish 38 bits with formats with preamble bit (26-36 bits)
*
* (from http://www.proxmark.org/forum/viewtopic.php?pid=5368#p5368)
* 0000 0010 0000 0000 01xx xxxx xxxx xxxx xxxx xxxx xxxx 26-bit
* 0000 0010 0000 0000 1xxx xxxx xxxx xxxx xxxx xxxx xxxx 27-bit
* 0000 0010 0000 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx 28-bit
* 0000 0010 0000 001x xxxx xxxx xxxx xxxx xxxx xxxx xxxx 29-bit
* 0000 0010 0000 01xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 30-bit
* 0000 0010 0000 1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 31-bit
* 0000 0010 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 32-bit
* 0000 0010 001x xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 33-bit
* 0000 0010 01xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 34-bit
* 0000 0010 1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 35-bit
* 0000 0011 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 36-bit
* 0000 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 37-bit
* 0000 00xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 38-bit
*/
uint8_t len = 0;
uint32_t hfmt = 0; // for calculating card length
@ -140,26 +156,23 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
if ((data->Top & 0x000FFFFF) > 0) { // > 64 bits
hfmt = data->Top & 0x000FFFFF;
len = 64;
} else if (data->Mid > 0) { // < 63-32 bits
} else if (data->Mid > 0) {
// detect HID format b38 set
if (data->Mid & 0xFFFFFFC0) {
if (data->Mid & 0xFFFFFFC0) { // 39-64 bits
hfmt = data->Mid;
len = 32;
} else {
len = 31; // remove leading 1 (preamble) in 39-64 bits format
} else { // detect card format 26-37 bits using "preamble" / "sentinel bit"
PrintAndLogEx(DEBUG, "hid preamble detected");
len = 32;
if ((data->Mid ^ 0x20) == 0) { hfmt = data->Bot; len = 0; }
else if ((data->Mid & 0x10) == 0) { hfmt = data->Mid & 0x1F; }
else if ((data->Mid & 0x08) == 0) { hfmt = data->Mid & 0x0F; }
else if ((data->Mid & 0x04) == 0) { hfmt = data->Mid & 0x07; }
else if ((data->Mid & 0x02) == 0) { hfmt = data->Mid & 0x03; }
else if ((data->Mid & 0x01) == 0) { hfmt = data->Mid & 0x01; }
else { hfmt = data->Mid & 0x3F;}
}
// if bit 38 is set: => 26-36 bits
if (((data->Mid >> 5) & 1) == 1) {
hfmt = (((data->Mid & 31) << 12) | (data->Bot >> 26)); //get bits 27-37 to check for format len bit
len = 19;
} else { // if bit 38 is not set => 37 bits
hfmt = 0;
len = 37;
}
}
} else {
hfmt = data->Bot;
len = 0;