From 66390096811a09fc3672c354b5f8d89ffe090731 Mon Sep 17 00:00:00 2001 From: CinderSocket Date: Tue, 17 Mar 2026 08:42:37 -0700 Subject: [PATCH] client: document wiegand layer and improve online tests Add inline comments throughout wiegand_formatutils and callers to explain sentinel-bit stripping, HID transport framing, and the normalization contract between input modes and downstream consumers. Replace sim-only LF HID online tests with T55xx clone+readback flows and add a full encode/decode roundtrip harness for hf mf encodehid, including sector restore/cleanup and an optional --manual flag for external reader verification. --- client/src/cmdhfmf.c | 6 + client/src/cmdlfhid.c | 8 + client/src/wiegand_formatutils.c | 12 +- client/src/wiegand_formatutils.h | 26 +++- tools/pm3_online_tests.sh | 242 +++++++++++++++++++++++++++++-- 5 files changed, 276 insertions(+), 18 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 3d666fe23..547064b0c 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -10045,6 +10045,8 @@ static int CmdHF14AMfValue(const char *Cmd) { return PM3_SUCCESS; } +// Encode the normalized Wiegand payload into the sentinel-prefixed byte layout stored in +// the HID-specific MIFARE payload block. static int hfmf_encodehid_pack_block5(const char *binstr, uint8_t *block) { if (binstr == NULL || block == NULL) { return PM3_EINVARG; @@ -10057,6 +10059,8 @@ static int hfmf_encodehid_pack_block5(const char *binstr, uint8_t *block) { return PM3_EINVARG; } + // MIFARE block 5 stores the Wiegand payload with the same sentinel-prefixed layout + // expected by existing HID cards: one leading 1 followed by the logical payload bits. bits_with_sentinel[0] = '1'; memcpy(bits_with_sentinel + 1, binstr, binlen + 1); @@ -10182,6 +10186,8 @@ static int CmdHFMFHidEncode(const char *Cmd) { return res; } + // Unlike LF HID transport, block 5 only needs the normalized bitstring. Raw/new/formatted + // inputs all converge here after the shared Wiegand layer has stripped transport framing. if (hfmf_encodehid_pack_block5(input.binstr, card_blocks + (MFBLOCK_SIZE * 4)) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Encoded Wiegand payload is too large to fit in the MIFARE payload"); return PM3_EINVARG; diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index d29df06f7..c0454b5f0 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -59,7 +59,11 @@ typedef struct { int new_pacs_len; } lf_hid_cli_input_t; +// Enforce the narrower LF HID transport limits after the shared Wiegand layer has +// normalized whichever user-facing input mode was selected. static int lf_hid_validate_packed_transport(const wiegand_input_t *input, const char *command_name) { + // The shared Wiegand layer can normalize credentials that are wider than the LF HID + // transport. Reject only when this specific command needs a packed HID frame. if (input->packed_valid == false) { PrintAndLogEx(ERR, "Credential encoded successfully, but %" PRIuMAX "-bit Wiegand data cannot be represented as a packed HID credential", (uintmax_t)input->bin_len); PrintAndLogEx(ERR, "Packed HID encoding supports up to 84 Wiegand bits"); @@ -80,6 +84,8 @@ static int lf_hid_validate_packed_transport(const wiegand_input_t *input, const return PM3_SUCCESS; } +// Resolve the CLI's mutually exclusive HID input modes into one normalized representation +// that downstream sim/clone code can consume without caring about the original encoding. static int lf_hid_resolve_input(const lf_hid_cli_input_t *cli, wiegand_input_t *input, int *format_idx) { int input_modes = 0; input_modes += (cli->raw_len > 0); @@ -101,6 +107,8 @@ static int lf_hid_resolve_input(const lf_hid_cli_input_t *cli, wiegand_input_t * return PM3_EINVARG; } + // Normalize every accepted CLI form into the same wiegand_input_t so sim/clone can + // share validation and transport handling regardless of where the credential came from. if (cli->raw_len) { return wiegand_pack_from_raw_hid(cli->raw, cli->raw_len, input); } diff --git a/client/src/wiegand_formatutils.c b/client/src/wiegand_formatutils.c index a65939e94..ed63bc5dc 100644 --- a/client/src/wiegand_formatutils.c +++ b/client/src/wiegand_formatutils.c @@ -244,6 +244,8 @@ bool wiegand_raw_to_binstr(const uint8_t *raw, size_t raw_len, char *binstr, siz bytes_2_binstr(binstr, raw, raw_len); + // Raw HID transport embeds a leading sentinel/start bit before the actual Wiegand payload. + // Strip that prefix so every caller downstream sees only the logical payload bits. char *sentinel = strchr(binstr, '1'); if (sentinel == NULL || sentinel[1] == '\0') { return false; @@ -271,6 +273,7 @@ bool wiegand_new_pacs_to_binstr(const uint8_t *pacs, size_t pacs_len, char *bins bytes_2_binstr(binstr, pacs + 1, payload_len); + // The first PACS byte stores how many zero padding bits were added to the final octet. size_t trimmed_len = strlen(binstr); if (pacs[0] >= trimmed_len) { return false; @@ -289,6 +292,7 @@ int wiegand_pack_bin_with_hid_header(const char *binstr, wiegand_message_t *pack uint8_t hex[12] = {0}; BitstreamOut_t bout = {hex, 0, 0}; + // HID transport stores the payload right-aligned behind a sentinel bit inside a 96-bit frame. for (size_t i = 0; i < (96 - bin_len - 1); i++) { pushBit(&bout, 0); } @@ -359,6 +363,8 @@ int wiegand_pack_from_plain_bin(const char *binstr, wiegand_input_t *input) { return res; } + // Plain binary input is still useful to non-HID callers above 84 bits, even though it + // can no longer be repacked into the legacy HID transport words. if (input->bin_len > 84) { input->packed_valid = false; return PM3_SUCCESS; @@ -375,6 +381,7 @@ int wiegand_pack_from_new_pacs(const uint8_t *pacs, size_t pacs_len, wiegand_inp return res; } + // New PACS can represent longer credentials than packed HID transport can carry. if (input->bin_len > 84) { input->packed_valid = false; return PM3_SUCCESS; @@ -422,8 +429,9 @@ int wiegand_pack_from_raw_hid(const uint8_t *raw, size_t raw_len, wiegand_input_ memcpy(aligned + (sizeof(aligned) - raw_len), raw, raw_len); input->packed = initialize_message_object(bytes_to_num(aligned, 4), bytes_to_num(aligned + 4, 4), bytes_to_num(aligned + 8, 4), 0); - // Raw HID input preserves legacy behavior: transport words are populated, but - // packed Wiegand length is left unset because this path does not repack data. + // Raw HID input preserves legacy behavior by keeping the transport words exactly as + // provided. The packed length is then derived from the embedded HID header bits + // instead of being recomputed by repacking the normalized payload bitstring. input->packed_valid = true; return PM3_SUCCESS; } diff --git a/client/src/wiegand_formatutils.h b/client/src/wiegand_formatutils.h index c5d5fac69..046dbdd55 100644 --- a/client/src/wiegand_formatutils.h +++ b/client/src/wiegand_formatutils.h @@ -45,8 +45,8 @@ typedef struct { typedef struct { size_t bin_len; char binstr[145]; - bool packed_valid; - wiegand_message_t packed; + bool packed_valid; // False when the input has a valid bitstring but no packed HID transport form. + wiegand_message_t packed; // HID transport words used by LF/HID-oriented callers. } wiegand_input_t; uint8_t get_bit_by_position(const wiegand_message_t *data, uint8_t pos); @@ -62,16 +62,38 @@ wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t uint8_t get_length_from_header(const wiegand_message_t *data); bool add_HID_header(wiegand_message_t *data); + +// Render a packed Wiegand message as a plain payload bitstring without HID transport framing. bool wiegand_message_to_binstr(const wiegand_message_t *packed, char *binstr, size_t binstr_size); + +// Decode raw HID transport bytes into a plain Wiegand payload bitstring. bool wiegand_raw_to_binstr(const uint8_t *raw, size_t raw_len, char *binstr, size_t binstr_size); + +// Decode the ASN.1 PACS form emitted by `wiegand encode --new` into a plain payload bitstring. bool wiegand_new_pacs_to_binstr(const uint8_t *pacs, size_t pacs_len, char *binstr, size_t binstr_size); + +// Validate and store a caller-provided binary Wiegand payload without attempting transport packing. int wiegand_set_plain_binstr(const char *binstr, wiegand_input_t *input); + +// Decode ASN.1 PACS input into the normalized binary representation used by downstream callers. int wiegand_set_new_pacs_binstr(const uint8_t *pacs, size_t pacs_len, wiegand_input_t *input); + +// Build HID transport words from a plain Wiegand payload, including sentinel placement and headers. int wiegand_pack_bin_with_hid_header(const char *binstr, wiegand_message_t *packed); + +// Encode a card-format struct through the existing HID formatter and return packed transport words. int wiegand_pack_formatted(int format_idx, wiegand_card_t *card, bool preamble, wiegand_message_t *packed); + +// Normalize ASN.1 PACS input and, when possible, also derive HID transport words for LF/HID callers. int wiegand_pack_from_new_pacs(const uint8_t *pacs, size_t pacs_len, wiegand_input_t *input); + +// Normalize plain binary input and, when possible, also derive HID transport words for LF/HID callers. int wiegand_pack_from_plain_bin(const char *binstr, wiegand_input_t *input); + +// Normalize formatted card data into both payload bits and packed transport words. int wiegand_pack_from_formatted(int format_idx, wiegand_card_t *card, bool preamble, wiegand_input_t *input); + +// Preserve legacy raw HID transport input while also exposing the decoded payload bitstring. int wiegand_pack_from_raw_hid(const uint8_t *raw, size_t raw_len, wiegand_input_t *input); #endif diff --git a/tools/pm3_online_tests.sh b/tools/pm3_online_tests.sh index 802439957..e56b03003 100755 --- a/tools/pm3_online_tests.sh +++ b/tools/pm3_online_tests.sh @@ -11,6 +11,8 @@ TESTALL=false TESTDESFIREVALUE=false TESTHIDWIEGAND=false TESTMFHIDENCODE=false +NEED_MF_HID_ENCODE_WIPE=false +TESTMANUAL=false # https://medium.com/@Drew_Stokes/bash-argument-parsing-54f3b81a6a8f PARAMS="" @@ -20,8 +22,9 @@ while (( "$#" )); do echo """ Usage: $0 [--pm3bin /path/to/pm3] [desfire_value|hid_wiegand|mf_hid_encode] --pm3bin ...: Specify path to pm3 binary to test + --manual ...: Pause after successful online LF HID clone/read checks for external reader verification desfire_value: Test DESFire value operations with card - hid_wiegand: Test LF HID simulate/clone Wiegand flows + hid_wiegand: Test LF HID T55xx clone and PM3 readback flows mf_hid_encode: Test MIFARE Classic HID encoding flows You must specify a test target - no default 'all' for online tests """ @@ -36,6 +39,10 @@ Usage: $0 [--pm3bin /path/to/pm3] [desfire_value|hid_wiegand|mf_hid_encode] exit 1 fi ;; + --manual) + TESTMANUAL=true + shift + ;; desfire_value) TESTALL=false TESTDESFIREVALUE=true @@ -109,13 +116,218 @@ function CheckExecute() { return 1 } +function CheckLfHidCloneReadback() { + printf "%-40s" "$1 " + + start=$(date +%s) + TIMEINFO="" + RES=$($PM3BIN -c "lf hid clone $2; lf hid reader" 2>&1) + end=$(date +%s) + delta=$(expr $end - $start) + if [ $delta -gt 2 ]; then + TIMEINFO=" ($delta s)" + fi + + if echo "$RES" | grep -E -q "$3"; then + echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK} $TIMEINFO" + if $TESTMANUAL; then + echo " Manual check: $4" + WaitForEnter "PRESENT THE T55xx TAG TO ANOTHER READER AND CONFIRM: $4" + fi + return 0 + fi + + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Execution trace:" + echo "$RES" + return 1 +} + +function HexToBin() { + local hex="${1^^}" + local bin="" + local i ch + for ((i=0; i<${#hex}; i++)); do + ch="${hex:i:1}" + case "$ch" in + 0) bin+="0000" ;; + 1) bin+="0001" ;; + 2) bin+="0010" ;; + 3) bin+="0011" ;; + 4) bin+="0100" ;; + 5) bin+="0101" ;; + 6) bin+="0110" ;; + 7) bin+="0111" ;; + 8) bin+="1000" ;; + 9) bin+="1001" ;; + A) bin+="1010" ;; + B) bin+="1011" ;; + C) bin+="1100" ;; + D) bin+="1101" ;; + E) bin+="1110" ;; + F) bin+="1111" ;; + *) return 1 ;; + esac + done + printf "%s" "$bin" +} + +function RestoreMfHidEncodeSector0() { + $PM3BIN -c "hf mf wrbl --blk 3 -b -k 89ECA97F8C2A -d FFFFFFFFFFFFFF078069FFFFFFFFFFFF" >/dev/null 2>&1 || true + $PM3BIN -c "hf mf wrbl --blk 3 -k FFFFFFFFFFFF -d FFFFFFFFFFFFFF078069FFFFFFFFFFFF" >/dev/null 2>&1 || true + $PM3BIN -c "hf mf wrbl --blk 3 -k A0A1A2A3A4A5 -d FFFFFFFFFFFFFF078069FFFFFFFFFFFF" >/dev/null 2>&1 || true + $PM3BIN -c "hf mf wrbl --blk 2 -k FFFFFFFFFFFF -d 00000000000000000000000000000000; \ +hf mf wrbl --blk 1 -k FFFFFFFFFFFF -d 00000000000000000000000000000000" >/dev/null 2>&1 || return 1 +} + +function RestoreMfHidEncodeSector1() { + $PM3BIN -c "hf mf wrbl --blk 7 -b -k 204752454154 -d FFFFFFFFFFFFFF078069FFFFFFFFFFFF" >/dev/null 2>&1 || true + $PM3BIN -c "hf mf wrbl --blk 7 -k FFFFFFFFFFFF -d FFFFFFFFFFFFFF078069FFFFFFFFFFFF" >/dev/null 2>&1 || true + $PM3BIN -c "hf mf wrbl --blk 7 -k 484944204953 -d FFFFFFFFFFFFFF078069FFFFFFFFFFFF" >/dev/null 2>&1 || true + $PM3BIN -c "hf mf wrbl --blk 6 -k FFFFFFFFFFFF -d 00000000000000000000000000000000; \ +hf mf wrbl --blk 5 -k FFFFFFFFFFFF -d 00000000000000000000000000000000; \ +hf mf wrbl --blk 4 -k FFFFFFFFFFFF -d 00000000000000000000000000000000" >/dev/null 2>&1 || return 1 +} + +function RestoreMfHidEncodeCard() { + RestoreMfHidEncodeSector0 || return 1 + RestoreMfHidEncodeSector1 || return 1 + + local verify + verify=$($PM3BIN -c 'hf mf rdbl --blk 1 -k FFFFFFFFFFFF; hf mf rdbl --blk 2 -k FFFFFFFFFFFF; hf mf rdbl --blk 4 -k FFFFFFFFFFFF; hf mf rdbl --blk 5 -k FFFFFFFFFFFF; hf mf rdbl --blk 6 -k FFFFFFFFFFFF' 2>&1) || return 1 + echo "$verify" | grep -E -q " 1 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$verify" | grep -E -q " 2 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$verify" | grep -E -q " 4 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$verify" | grep -E -q " 5 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$verify" | grep -E -q " 6 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" +} + +function CleanupMfHidEncodeCard() { + if [ "$NEED_MF_HID_ENCODE_WIPE" != true ]; then + return 0 + fi + + echo "" + printf "%-40s" "hf mf encodehid cleanup " + if RestoreMfHidEncodeCard; then + echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK}" + else + echo -e "[ ${C_YELLOW}WARN${C_NC} ]" + echo "Cleanup could not restore sectors 0 and 1 to the default usable state." + fi +} + +function CheckMfHidEncodeRoundTrip() { + printf "%-40s" "$1 " + + start=$(date +%s) + TIMEINFO="" + if ! RestoreMfHidEncodeCard >/dev/null 2>&1; then + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL}" + echo "Execution trace:" + echo "Failed to restore sectors 0 and 1 to the default usable state before running the test." + return 1 + fi + + RES=$($PM3BIN -c "hf mf encodehid $2; hf mf rdbl --blk 5 -k 484944204953" 2>&1) + end=$(date +%s) + delta=$(expr $end - $start) + if [ $delta -gt 2 ]; then + TIMEINFO=" ($delta s)" + fi + + BLOCKHEX=$(printf "%s\n" "$RES" | LC_ALL=C grep -aoE '02( [0-9A-F]{2}){15}' | tail -n1 | tr -d ' ') + if [ -z "$BLOCKHEX" ]; then + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Execution trace:" + echo "$RES" + return 1 + fi + + if [[ "$BLOCKHEX" != 02* ]]; then + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Expected block 5 to start with the 0x02 HID marker." + echo "Actual block 5 data: $BLOCKHEX" + echo "Execution trace:" + echo "$RES" + return 1 + fi + + RAWPAYLOAD=${BLOCKHEX#02} + PAYLOADBIN=$(HexToBin "$RAWPAYLOAD") || { + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Execution trace:" + echo "$RES" + return 1 + } + + while [[ "$PAYLOADBIN" == 0* ]]; do + PAYLOADBIN=${PAYLOADBIN#0} + done + + if [[ "$PAYLOADBIN" != 1* ]]; then + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Expected a sentinel-prefixed Wiegand payload in block 5." + echo "Actual payload bits: $PAYLOADBIN" + echo "Execution trace:" + echo "$RES" + return 1 + fi + + RECOVERED_BIN=${PAYLOADBIN#1} + if [ "$RECOVERED_BIN" != "$3" ]; then + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Expected Wiegand bits: $3" + echo "Actual Wiegand bits: $RECOVERED_BIN" + echo "Execution trace:" + echo "$RES" + return 1 + fi + + DECODE_RES=$($PM3BIN -c "wiegand decode --bin $RECOVERED_BIN" 2>&1) + if echo "$DECODE_RES" | grep -E -q "$4"; then + echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK} $TIMEINFO" + return 0 + fi + + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL} $TIMEINFO" + echo "Decode trace:" + echo "$DECODE_RES" + return 1 +} + +function CheckMfHidEncodeCleanup() { + printf "%-40s" "$1 " + RES=$($PM3BIN -c 'hf mf rdbl --blk 1 -k FFFFFFFFFFFF; hf mf rdbl --blk 2 -k FFFFFFFFFFFF; hf mf rdbl --blk 4 -k FFFFFFFFFFFF; hf mf rdbl --blk 5 -k FFFFFFFFFFFF; hf mf rdbl --blk 6 -k FFFFFFFFFFFF' 2>&1) + if echo "$RES" | grep -E -q " 1 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$RES" | grep -E -q " 2 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$RES" | grep -E -q " 4 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$RES" | grep -E -q " 5 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" \ + && echo "$RES" | grep -E -q " 6 \| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"; then + echo -e "[ ${C_GREEN}OK${C_NC} ] ${C_OK}" + return 0 + fi + + echo -e "[ ${C_RED}FAIL${C_NC} ] ${C_FAIL}" + echo "Execution trace:" + echo "$RES" + return 1 +} + function WaitForEnter() { echo "" echo "$1" echo "Press Enter when ready, or Ctrl-C to abort." - read -r + if [ -r /dev/tty ]; then + stty sane < /dev/tty 2>/dev/null || true + IFS= read -r < /dev/tty + else + read -r + fi } +trap CleanupMfHidEncodeCard EXIT + echo -e "${C_BLUE}Iceman Proxmark3 online test tool${C_NC}" echo "" echo "work directory: $(pwd)" @@ -161,19 +373,17 @@ while true; do fi if $TESTHIDWIEGAND; then - echo -e "\n${C_BLUE}Testing LF HID Wiegand flows${C_NC} ${PM3BIN:=./pm3}" + echo -e "\n${C_BLUE}Testing LF HID T55xx clone flows${C_NC} ${PM3BIN:=./pm3}" if ! CheckFileExist "pm3 exists" "$PM3BIN"; then break; fi - if ! CheckExecute "lf hid sim 26-bit bin" "$PM3BIN -c 'lf hid sim --bin 10001111100000001010100011'" "Simulating HID tag"; then break; fi - if ! CheckExecute "lf hid sim raw oversize" "$PM3BIN -c 'lf hid sim -r 01400076000c86' 2>&1" "LF HID simulation supports only packed credentials up to 37 bits"; then break; fi - if ! CheckExecute "lf hid sim bin oversize" "PAT=\$(printf '01%.0s' {1..48}); $PM3BIN -c \"lf hid sim --bin \$PAT\" 2>&1" "LF HID simulation supports only packed credentials up to 37 bits"; then break; fi - if ! CheckExecute "lf hid sim new oversize" "$PM3BIN -c 'lf hid sim --new 0000A4550148AB' 2>&1" "LF HID simulation supports only packed credentials up to 37 bits"; then break; fi + if ! CheckExecute "lf hid clone raw oversize" "$PM3BIN -c 'lf hid clone -r 01400076000c86' 2>&1" "LF HID clone supports only packed credentials up to 37 bits"; then break; fi + if ! CheckExecute "lf hid clone bin oversize" "PAT=\$(printf '01%.0s' {1..48}); $PM3BIN -c \"lf hid clone --bin \$PAT\" 2>&1" "Packed HID encoding supports up to 84 Wiegand bits"; then break; fi + if ! CheckExecute "lf hid clone new oversize" "$PM3BIN -c 'lf hid clone --new 0000A4550148AB' 2>&1" "LF HID clone supports only packed credentials up to 37 bits"; then break; fi WaitForEnter "PLACE A REWRITABLE T55xx TAG ON THE PM3 NOW" - if ! CheckExecute "lf hid clone 26-bit bin" "$PM3BIN -c 'lf hid clone --bin 10001111100000001010100011'" "Done!"; then break; fi - if ! CheckExecute "lf hid clone raw oversize" "$PM3BIN -c 'lf hid clone -r 01400076000c86' 2>&1" "LF HID clone supports only packed credentials up to 37 bits"; then break; fi - if ! CheckExecute "lf hid clone bin oversize" "PAT=\$(printf '01%.0s' {1..48}); $PM3BIN -c \"lf hid clone --bin \$PAT\" 2>&1" "LF HID clone supports only packed credentials up to 37 bits"; then break; fi - if ! CheckExecute "lf hid clone new oversize" "$PM3BIN -c 'lf hid clone --new 0000A4550148AB' 2>&1" "LF HID clone supports only packed credentials up to 37 bits"; then break; fi + if ! CheckLfHidCloneReadback "lf hid clone H10301 26-bit" "-w H10301 --fc 118 --cn 1603" "H10301.*FC: 118.*CN: 1603" "H10301 26-bit, FC 118, CN 1603"; then break; fi + if ! CheckLfHidCloneReadback "lf hid clone C1k35s 35-bit" "-w C1k35s --fc 118 --cn 1603" "C1k35s.*FC: 118.*CN: 1603" "C1k35s 35-bit, FC 118, CN 1603"; then break; fi + if ! CheckLfHidCloneReadback "lf hid clone H10304 37-bit" "-w H10304 --fc 118 --cn 1603" "H10304.*FC: 118.*CN: 1603" "H10304 37-bit, FC 118, CN 1603"; then break; fi fi if $TESTMFHIDENCODE; then @@ -181,9 +391,13 @@ while true; do if ! CheckFileExist "pm3 exists" "$PM3BIN"; then break; fi WaitForEnter "PLACE A BLANK MIFARE CLASSIC 1K CARD ON THE PM3 NOW" - if ! CheckExecute "hf mf encodehid bin" "$PM3BIN -c 'hf mf encodehid --bin 10001111100000001010100011; hf mf rdbl --blk 5 -k FFFFFFFFFFFF'" "023E02A3"; then break; fi - if ! CheckExecute "hf mf encodehid raw" "$PM3BIN -c 'hf mf encodehid --raw 023E02A3; hf mf rdbl --blk 5 -k FFFFFFFFFFFF'" "023E02A3"; then break; fi - if ! CheckExecute "hf mf encodehid new" "$PM3BIN -c 'hf mf encodehid --new 068F80A8C0; hf mf rdbl --blk 5 -k FFFFFFFFFFFF'" "023E02A3"; then break; fi + NEED_MF_HID_ENCODE_WIPE=true + if ! CheckMfHidEncodeRoundTrip "hf mf encodehid bin roundtrip" "--bin 10001111100000001010100011" "10001111100000001010100011" "H10301.*FC: 31.*CN: 337"; then break; fi + if ! CheckMfHidEncodeRoundTrip "hf mf encodehid raw roundtrip" "--raw 063E02A3" "10001111100000001010100011" "H10301.*FC: 31.*CN: 337"; then break; fi + if ! CheckMfHidEncodeRoundTrip "hf mf encodehid new roundtrip" "--new 068F80A8C0" "10001111100000001010100011" "H10301.*FC: 31.*CN: 337"; then break; fi + if ! CheckMfHidEncodeRoundTrip "hf mf encodehid format roundtrip" "-w H10301 --fc 31 --cn 337" "10001111100000001010100011" "H10301.*FC: 31.*CN: 337"; then break; fi + if ! RestoreMfHidEncodeCard; then break; fi + if ! CheckMfHidEncodeCleanup "hf mf encodehid cleanup verify"; then break; fi fi echo -e "\n------------------------------------------------------------"