diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 0716efc60..e81d5570c 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -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); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 22b90834e..492403344 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -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"); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b80fb138e..b17e9caf8 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -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); } } diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index baed95b29..fb1eeb56e 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -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; diff --git a/client/src/cmdwiegand.c b/client/src/cmdwiegand.c index 9fc06b6f9..7853b71cd 100644 --- a/client/src/cmdwiegand.c +++ b/client/src/cmdwiegand.c @@ -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; } diff --git a/client/src/wiegand_formats.c b/client/src/wiegand_formats.c index 0b600f804..b64aa0e74 100644 --- a/client/src/wiegand_formats.c +++ b/client/src/wiegand_formats.c @@ -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]; diff --git a/client/src/wiegand_formats.h b/client/src/wiegand_formats.h index ff231f25f..503e85daf 100644 --- a/client/src/wiegand_formats.h +++ b/client/src/wiegand_formats.h @@ -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); diff --git a/client/src/wiegand_formatutils.c b/client/src/wiegand_formatutils.c index f77ab5bfe..fed31d9fb 100644 --- a/client/src/wiegand_formatutils.c +++ b/client/src/wiegand_formatutils.c @@ -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;