more wiegand formats, and if binary is user supplied use that length, and ignore parity faults is removed since we wanna see all decodings anyway

This commit is contained in:
iceman1001 2021-04-27 15:19:34 +02:00
parent bbdb2d7c95
commit 10c9ea5f84
7 changed files with 213 additions and 116 deletions

View file

@ -1309,8 +1309,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), binstr + i);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, true);
wiegand_message_t packed = initialize_message_object(top, mid, bot, strlen(binstr + i));
HIDTryUnpack(&packed);
} else {
PrintAndLogEx(INFO, "No credential found");
@ -2335,8 +2335,8 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
PrintAndLogEx(SUCCESS, " bin : %s", binstr + i);
PrintAndLogEx(INFO, "");
PrintAndLogEx(INFO, "------------------------------ " _CYAN_("wiegand") " -------------------------------");
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, true);
wiegand_message_t packed = initialize_message_object(top, mid, bot, strlen(binstr + i));
HIDTryUnpack(&packed);
} else {
PrintAndLogEx(INFO, "no credential found");
}

View file

@ -140,8 +140,8 @@ int demodHID(bool verbose) {
return PM3_ESOFT;
}
wiegand_message_t packed = initialize_message_object(hi2, hi, lo);
if (HIDTryUnpack(&packed, false) == false) {
wiegand_message_t packed = initialize_message_object(hi2, hi, lo, 0);
if (HIDTryUnpack(&packed) == false) {
printDemodBuff(0, false, false, true);
}
PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo);
@ -292,7 +292,7 @@ static int CmdHIDSim(const char *Cmd) {
if (raw_len == 0) {
PrintAndLogEx(INFO, "Simulating HID tag");
HIDTryUnpack(&packed, false);
HIDTryUnpack(&packed);
} else {
PrintAndLogEx(INFO, "Simulating HID tag using raw " _GREEN_("%s"), raw);
}
@ -416,7 +416,7 @@ static int CmdHIDClone(const char *Cmd) {
if (raw_len == 0) {
PrintAndLogEx(INFO, "Preparing to clone HID tag");
HIDTryUnpack(&packed, false);
HIDTryUnpack(&packed);
} else {
PrintAndLogEx(INFO, "Preparing to clone HID tag using raw " _YELLOW_("%s"), raw);
}

View file

@ -107,27 +107,24 @@ int CmdWiegandDecode(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "wiegand decode",
"Decode raw hex to wiegand format",
"Decode raw hex or binary to wiegand format",
"wiegand decode --raw 2006f623ae"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("p", "parity", "ignore invalid parity"),
arg_strx0("r", "raw", "<hex>", "raw hex to be decoded"),
arg_str0("b", "bin", "<bin>", "binary string to be decoded"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool ignore_parity = arg_get_lit(ctx, 1);
CLIExecWithReturn(ctx, Cmd, argtable, true);
int hlen = 0;
char hex[40] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)hex, sizeof(hex), &hlen);
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)hex, sizeof(hex), &hlen);
int blen = 0;
uint8_t binarr[100] = {0x00};
int res = CLIParamBinToBuf(arg_get_str(ctx, 3), binarr, sizeof(binarr), &blen);
int res = CLIParamBinToBuf(arg_get_str(ctx, 2), binarr, sizeof(binarr), &blen);
CLIParserFree(ctx);
if (res) {
@ -144,7 +141,7 @@ int CmdWiegandDecode(const char *Cmd) {
return PM3_EINVARG;
}
} else if (blen) {
uint16_t n = binarray_to_u96(&top, &mid, &bot, binarr, blen);
int n = binarray_to_u96(&top, &mid, &bot, binarr, blen);
if (n != blen) {
PrintAndLogEx(ERR, "Binary string contains none <0|1> chars");
return PM3_EINVARG;
@ -153,8 +150,8 @@ int CmdWiegandDecode(const char *Cmd) {
PrintAndLogEx(ERR, "empty input");
return PM3_EINVARG;
}
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, ignore_parity);
wiegand_message_t packed = initialize_message_object(top, mid, bot, blen);
HIDTryUnpack(&packed);
return PM3_SUCCESS;
}

View file

@ -163,7 +163,6 @@ static bool Unpack_indasc27(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_2804W(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -293,6 +292,91 @@ static bool Unpack_ADT31(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
static bool Pack_hcp32(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0) return false; // Not used
if (card->CardNumber > 0x3FFF) return false; // 24 bits
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used
packed->Length = 32; // Set number of bits
set_linear_field(packed, card->CardNumber, 1, 24);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_hcp32(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 32) return false; // Wrong length? Stop here.
card->CardNumber = get_linear_field(packed, 1, 24);
return true;
}
static bool Pack_hpp32(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // 12 bits
if (card->CardNumber > 0x1FFFFFFF) return false; // 29 bits
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used
packed->Length = 32; // Set number of bits
set_linear_field(packed, card->FacilityCode, 1, 12);
set_linear_field(packed, card->CardNumber, 13, 29);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_hpp32(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 32) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 1, 12);
card->CardNumber = get_linear_field(packed, 13, 29);
return true;
}
static bool Pack_wie32(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // 12 bits
if (card->CardNumber > 0xFFFF) return false; // 16 bits
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used
packed->Length = 32; // Set number of bits
set_linear_field(packed, card->FacilityCode, 4, 12);
set_linear_field(packed, card->CardNumber, 16, 16);
if (preamble)
return add_HID_header(packed);
return true;
}
static bool Unpack_wie32(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 32) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 4, 12);
card->CardNumber = get_linear_field(packed, 16, 16);
return true;
}
static bool Pack_Kastle(wiegand_card_t *card, wiegand_message_t *packed, bool preamble) {
memset(packed, 0, sizeof(wiegand_message_t));
@ -1109,6 +1193,88 @@ static bool Unpack_pw39(wiegand_message_t *packed, wiegand_card_t *card) {
return true;
}
// ---------------------------------------------------------------------------------------------------
void print_desc_wiegand(cardformat_t *fmt, wiegand_message_t *packed) {
char *s = calloc(128, sizeof(uint8_t));
sprintf(s, _YELLOW_("%-10s")" %-30s", fmt->Name, fmt->Descrp);
if (packed->Top != 0) {
PrintAndLogEx(SUCCESS, "%s -> " _GREEN_("%X%08X%08X"),
s,
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
} else {
PrintAndLogEx(SUCCESS, "%s -> " _YELLOW_("%X%08X"),
s,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
}
free(s);
}
void print_wiegand_code(wiegand_message_t *packed) {
const char *s = "Wiegand: ";
if (packed->Top != 0) {
PrintAndLogEx(SUCCESS, "%s" _GREEN_("%X%08X%08X"),
s,
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
} else {
PrintAndLogEx(SUCCESS, "%s" _YELLOW_("%X%08X"),
s,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
}
}
static void hid_print_card(wiegand_card_t *card, const cardformat_t format) {
/*
PrintAndLogEx(SUCCESS, " Format: %s (%s)", format.Name, format.Descrp);
if (format.Fields.hasFacilityCode)
PrintAndLogEx(SUCCESS, "Facility Code: %d",card->FacilityCode);
if (format.Fields.hasCardNumber)
PrintAndLogEx(SUCCESS, " Card Number: %d",card->CardNumber);
if (format.Fields.hasIssueLevel)
PrintAndLogEx(SUCCESS, " Issue Level: %d",card->IssueLevel);
if (format.Fields.hasOEMCode)
PrintAndLogEx(SUCCESS, " OEM Code: %d",card->OEM);
if (format.Fields.hasParity)
PrintAndLogEx(SUCCESS, " Parity: %s",card->ParityValid ? "Valid" : "Invalid");
*/
char s[110] = {0};
if (format.Fields.hasFacilityCode)
snprintf(s, sizeof(s), "FC: " _GREEN_("%u"), card->FacilityCode);
if (format.Fields.hasCardNumber)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " CN: " _GREEN_("%"PRIu64), card->CardNumber);
if (format.Fields.hasIssueLevel)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " Issue: " _GREEN_("%u"), card->IssueLevel);
if (format.Fields.hasOEMCode)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " OEM: " _GREEN_("%u"), card->OEM);
if (format.Fields.hasParity)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " parity ( %s )", card->ParityValid ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(SUCCESS, "[%-8s] %-30s %s", format.Name, format.Descrp, s);
}
static const cardformat_t FormatTable[] = {
{"H10301", Pack_H10301, Unpack_H10301, "HID H10301 26-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"ind26", Pack_ind26, Unpack_ind26, "Indala 26-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
@ -1119,13 +1285,16 @@ static const cardformat_t FormatTable[] = {
{"ind29", Pack_ind29, Unpack_ind29, "Indala 29-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"ATSW30", Pack_ATSW30, Unpack_ATSW30, "ATS Wiegand 30-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"ADT31", Pack_ADT31, Unpack_ADT31, "HID ADT 31-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"HCP32", Pack_hcp32, Unpack_hcp32, "HID Check Point 32-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"HPP32", Pack_hpp32, Unpack_hpp32, "HID Hewlett-Packard 32-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"Kastle", Pack_Kastle, Unpack_Kastle, "Kastle 32-bit", {1, 1, 1, 0, 1}}, // from @xilni; PR #23 on RfidResearchGroup/proxmark3
{"Kantech", Pack_Kantech, Unpack_Kantech, "Indala/Kantech KFS 32-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"WIE32", Pack_wie32, Unpack_wie32, "Wiegand 32-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"D10202", Pack_D10202, Unpack_D10202, "HID D10202 33-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"N10002", Pack_N10002, Unpack_N10002, "HID N10002 34-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"Optus34", Pack_Optus, Unpack_Optus, "Indala Optus 34-bit", {1, 1, 0, 0, 0}}, // from cardinfo.barkweb.com.au
{"Smartpass", Pack_Smartpass, Unpack_Smartpass, "Cardkey Smartpass 34-bit", {1, 1, 1, 0, 0}}, // from cardinfo.barkweb.com.au
{"SMP34", Pack_Smartpass, Unpack_Smartpass, "Cardkey Smartpass 34-bit", {1, 1, 1, 0, 0}}, // from cardinfo.barkweb.com.au
{"BQT34", Pack_bqt34, Unpack_bqt34, "BQT 34-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit std", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"C15001", Pack_C15001, Unpack_C15001, "HID KeyScan 36-bit", {1, 1, 0, 1, 1}}, // from Proxmark forums
@ -1134,7 +1303,7 @@ static const cardformat_t FormatTable[] = {
{"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD", {1, 0, 0, 0, 1}}, // from Proxmark forums
{"H10302", Pack_H10302, Unpack_H10302, "HID H10302 37-bit huge ID", {1, 0, 0, 0, 1}}, // from Proxmark forums
{"H10304", Pack_H10304, Unpack_H10304, "HID H10304 37-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"HGeneric37", Pack_HGeneric37, Unpack_HGeneric37, "HID Generic 37-bit", {1, 0, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"HGen37", Pack_HGeneric37, Unpack_HGeneric37, "HID Generic 37-bit", {1, 0, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"MDI37", Pack_MDI37, Unpack_MDI37, "PointGuard MDI 37-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"BQT38", Pack_bqt38, Unpack_bqt38, "BQT 38-bit", {1, 1, 1, 0, 1}}, // from cardinfo.barkweb.com.au
{"ISCS", Pack_iscs38, Unpack_iscs38, "ISCS 38-bit", {1, 1, 0, 1, 1}}, // from cardinfo.barkweb.com.au
@ -1158,50 +1327,12 @@ void HIDListFormats(void) {
PrintAndLogEx(INFO, _YELLOW_("%-10s")" %-30s", FormatTable[i].Name, FormatTable[i].Descrp);
++i;
}
PrintAndLogEx(INFO, "------------------------------------------------------------");
PrintAndLogEx(INFO, "Available card formats: " _YELLOW_("%u"), ARRAYLEN(FormatTable));
PrintAndLogEx(NORMAL, "");
return;
}
void print_desc_wiegand(cardformat_t *fmt, wiegand_message_t *packed) {
char *s = calloc(128, sizeof(uint8_t));
sprintf(s, _YELLOW_("%-10s")" %-30s", fmt->Name, fmt->Descrp);
if (packed->Top != 0) {
PrintAndLogEx(SUCCESS, "%s --> " _GREEN_("%X%08X%08X"),
s,
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
} else {
PrintAndLogEx(SUCCESS, "%s --> " _YELLOW_("%X%08X"),
s,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
}
free(s);
}
void print_wiegand_code(wiegand_message_t *packed) {
const char *s = "Encoded wiegand: ";
if (packed->Top != 0) {
PrintAndLogEx(SUCCESS, "%s" _GREEN_("%X%08X%08X"),
s,
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
} else {
PrintAndLogEx(SUCCESS, "%s" _YELLOW_("%X%08X"),
s,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot
);
}
}
cardformat_t HIDGetCardFormat(int idx) {
return FormatTable[idx];
}
@ -1237,7 +1368,7 @@ bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bo
void HIDPackTryAll(wiegand_card_t *card, bool preamble) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "%-10s %-30s --> Encoded wiegand", "Name", "Description");
PrintAndLogEx(INFO, "%-10s %-30s -> wiegand", "Name", "Description");
PrintAndLogEx(INFO, "----------------------------------------------------------------------");
wiegand_message_t packed;
@ -1254,69 +1385,35 @@ void HIDPackTryAll(wiegand_card_t *card, bool preamble) {
PrintAndLogEx(NORMAL, "");
}
static void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t format) {
/*
PrintAndLogEx(SUCCESS, " Format: %s (%s)", format.Name, format.Descrp);
if (format.Fields.hasFacilityCode)
PrintAndLogEx(SUCCESS, "Facility Code: %d",card->FacilityCode);
if (format.Fields.hasCardNumber)
PrintAndLogEx(SUCCESS, " Card Number: %d",card->CardNumber);
if (format.Fields.hasIssueLevel)
PrintAndLogEx(SUCCESS, " Issue Level: %d",card->IssueLevel);
if (format.Fields.hasOEMCode)
PrintAndLogEx(SUCCESS, " OEM Code: %d",card->OEM);
if (format.Fields.hasParity)
PrintAndLogEx(SUCCESS, " Parity: %s",card->ParityValid ? "Valid" : "Invalid");
*/
char s[110] = {0};
if (format.Fields.hasFacilityCode)
snprintf(s, sizeof(s), "FC: " _GREEN_("%u"), card->FacilityCode);
if (format.Fields.hasCardNumber)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " CN: " _GREEN_("%"PRIu64), card->CardNumber);
if (format.Fields.hasIssueLevel)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " Issue: " _GREEN_("%u"), card->IssueLevel);
if (format.Fields.hasOEMCode)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " OEM: " _GREEN_("%u"), card->OEM);
if (format.Fields.hasParity)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " parity: %s", card->ParityValid ? _GREEN_("valid") : _RED_("invalid"));
PrintAndLogEx(SUCCESS, "[%s] - %s %s", format.Name, format.Descrp, s);
}
bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity) {
bool HIDTryUnpack(wiegand_message_t *packed) {
if (FormatTable[0].Name == NULL)
return false;
bool result = false;
int i = 0;
wiegand_card_t card;
memset(&card, 0, sizeof(wiegand_card_t));
uint8_t found_cnt = 0, found_invalid_par = 0;
while (FormatTable[i].Name) {
if (FormatTable[i].Unpack(packed, &card)) {
if (ignore_parity || !FormatTable[i].Fields.hasParity || card.ParityValid) {
result = true;
HIDDisplayUnpackedCard(&card, FormatTable[i]);
}
found_cnt++;
hid_print_card(&card, FormatTable[i]);
if (FormatTable[i].Fields.hasParity || card.ParityValid == false)
found_invalid_par++;
}
++i;
}
if (result == false && packed->Length) {
PrintAndLogEx(SUCCESS, "(wiegand unpack) unknown bit len %d", packed->Length);
if (found_cnt) {
PrintAndLogEx(INFO, "found %u matching format%c", found_cnt, (found_cnt > 1) ? 's' : ' ');
}
if (packed->Length && found_invalid_par == 0) {
PrintAndLogEx(WARNING, "Wiegand unknown bit len %d", packed->Length);
PrintAndLogEx(HINT, "Try 0xFFFF's http://cardinfo.barkweb.com.au/");
}
return result;
return ((found_cnt - found_invalid_par) > 0);
}

View file

@ -43,7 +43,7 @@ void HIDListFormats(void);
int HIDFindCardFormat(const char *format);
cardformat_t HIDGetCardFormat(int idx);
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble);
bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity);
bool HIDTryUnpack(wiegand_message_t *packed);
void HIDPackTryAll(wiegand_card_t *card, bool preamble);
void print_wiegand_code(wiegand_message_t *packed);
void print_desc_wiegand(cardformat_t *fmt, wiegand_message_t *packed);

View file

@ -156,14 +156,17 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
return len;
}
wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t bot) {
wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t bot, int n) {
wiegand_message_t result;
memset(&result, 0, sizeof(wiegand_message_t));
result.Top = top;
result.Mid = mid;
result.Bot = bot;
result.Length = get_length_from_header(&result);
if (n > 0)
result.Length = n;
else
result.Length = get_length_from_header(&result);
return result;
}

View file

@ -42,7 +42,7 @@ bool set_linear_field(wiegand_message_t *data, uint64_t value, uint8_t firstBit,
uint64_t get_nonlinear_field(wiegand_message_t *data, uint8_t numBits, uint8_t *bits);
bool set_nonlinear_field(wiegand_message_t *data, uint64_t value, uint8_t numBits, uint8_t *bits);
wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t bot);
wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t bot, int n);
bool add_HID_header(wiegand_message_t *data);