From 36f689beaa0445d21f70eb105476048a5200db00 Mon Sep 17 00:00:00 2001 From: Matthew Carroll Date: Sat, 12 Sep 2026 10:38:52 -0700 Subject: [PATCH] lf idteck demod: report only what the tag actually holds Three ways this command reported a credential that was not on the tag. CmdIdteckDemod always passed its local raw[8] to demodIdteck, never NULL, so without --raw the command decoded a zeroed stack array rather than the graphbuffer and reported card id 0 every time. The help's own first example, plain `lf idteck demod`, has been doing that since --raw was added. It now passes NULL when no --raw is given, which is the signal path demodIdteck already has and lf idteck reader already uses. A raw frame whose first word is not 4944544B printed "No genuine IDTECK found" and then fell through and announced a tag anyway, with a card id read out of whatever was passed in. It now stops there. The signal path cannot reach this: detectIdteck matches the full 32 bit preamble, so lf search and lf idteck reader are unaffected. Finally the Idteck card id was packed into a 26 bit wiegand_message_t and run through HIDUnpack, which prints an HID H10301 line with a facility code and card number. That is not a decode of anything - the id is 24 bits, byte reversed off the wire, and Unpack_H10301 returns true for any 26 bit message, so the parity flag is the only hint and it reads ok for 25% of card ids by chance. Both committed Idteck traces show it: 4944544B351FBE4B prints FC: 37 CN: 57103 parity ( ok ), AC40E069 prints FC: 52 CN: 61472 parity ( fail ). Dropped, with the wiegand_formats.h include that came in with it. Added five offline regression tests. Three fail without this change, one per defect; lf search over every committed lf trace is byte identical before and after apart from the two removed H10301 lines. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 3 +++ client/src/cmdlfidteck.c | 18 ++++++------------ tools/pm3_tests.sh | 6 ++++++ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d460646fc..3e5233a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Fixed `lf idteck demod` - without `--raw` it decoded a zeroed stack buffer instead of the graphbuffer, always reporting card id 0 (@mfcarroll) +- Fixed `lf idteck demod` - a raw frame without the Idteck preamble printed `No genuine IDTECK found` and then announced a tag anyway (@mfcarroll) +- Changed `lf idteck demod` - no longer prints an HID H10301 credential built from the Idteck card id (@mfcarroll) - Added `trace clear` - clears the tracebuffer (@iceman1001) - Changed `trace save -1` - now downloads from device by default (@iceman1001) - Added `hf 14a antifuzz --coll` - the UID collides from the 9th bit (@iceman1001) diff --git a/client/src/cmdlfidteck.c b/client/src/cmdlfidteck.c index 9fbe6a490..c697cbe75 100644 --- a/client/src/cmdlfidteck.c +++ b/client/src/cmdlfidteck.c @@ -33,7 +33,6 @@ #include "protocols.h" // T55x7 defines #include "cmdlft55xx.h" // verifywrite #include "generator.h" -#include "wiegand_formats.h" static int CmdHelp(const char *Cmd); @@ -104,13 +103,14 @@ int demodIdteck(uint8_t *raw, bool verbose) { raw2 = bytes_to_num(raw + 4, 4); } - // got a good demod - uint32_t id = 0; - if (raw1 != 0x4944544B) { PrintAndLogEx(FAILED, "No genuine IDTECK found"); + return PM3_ESOFT; } + // got a good demod + uint32_t id = 0; + // parity check (TBD) uint32_t tmp = raw2; @@ -135,13 +135,6 @@ int demodIdteck(uint8_t *raw, bool verbose) { (chksum == calc) ? _GREEN_("ok") : _RED_("fail") ); - wiegand_message_t packed = { - .Bot = id, - .Mid = 0, - .Top = 0, - .Length = 26 - }; - HIDUnpack(0, &packed); return PM3_SUCCESS; } @@ -163,7 +156,8 @@ static int CmdIdteckDemod(const char *Cmd) { uint8_t raw[8] = {0}; CLIGetHexWithReturn(ctx, 1, raw, &raw_len); CLIParserFree(ctx); - return demodIdteck(raw, true); + // no --raw given, demod the graphbuffer instead + return demodIdteck((raw_len == 0) ? NULL : raw, true); } static int CmdIdteckClone(const char *Cmd) { diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index b0f257ab6..c56c66023 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -539,6 +539,12 @@ while true; do if ! CheckExecute "lf GPROXII test" "$CLIENTBIN -c 'data load -f traces/lf_GProx_36_30_14489.pm3; lf search -1'" "Guardall G-Prox II ID found"; then break; fi if ! CheckExecute "lf HID Prox test" "$CLIENTBIN -c 'data load -f traces/lf_HID-proxCardII-05512-11432784-1.pm3;lf search -1'" "HID Prox ID found"; then break; fi if ! CheckExecute "lf IDTECK test" "$CLIENTBIN -c 'data load -f traces/lf_IDTECK_4944544BAC40E069.pm3; lf search -1'" "Idteck ID found"; then break; fi + if ! CheckExecute "lf IDTECK test 2" "$CLIENTBIN -c 'data load -f traces/lf_IDTECK_4944544BAC40E069.pm3; lf idteck demod'" \ + "Card ID 6938688 \( 0x69E040 \) Raw: 4944544BAC40E069"; then break; fi + if ! CheckExecute "lf IDTECK raw test" "$CLIENTBIN -c 'lf idteck demod --raw 4944544B351FBE4B'" \ + "Card ID 4963871 \( 0x4BBE1F \) Raw: 4944544B351FBE4B"; then break; fi + if ! CheckExecute "lf IDTECK reject test" "if ! $CLIENTBIN -c 'lf idteck demod --raw DEADBEEFDEADBEEF' 2>&1 | grep -q 'IDTECK Tag Found'; then echo OK; fi" "OK"; then break; fi + if ! CheckExecute "lf IDTECK no wiegand test" "if ! $CLIENTBIN -c 'lf idteck demod --raw 4944544B351FBE4B' 2>&1 | grep -q 'H10301'; then echo OK; fi" "OK"; then break; fi if ! CheckExecute "lf INDALA test" "$CLIENTBIN -c 'data load -f traces/lf_Indala-504278295.pm3;lf search -1'" "Indala ID found"; then break; fi if ! CheckExecute "lf KERI test" "$CLIENTBIN -c 'data load -f traces/lf_Keri.pm3;lf search -1'" "Pyramid ID found"; then break; fi if ! CheckExecute "lf NEXWATCH test" "$CLIENTBIN -c 'data load -f traces/lf_NEXWATCH_Quadrakey-521512301.pm3;lf search -1 '" "NexWatch ID found"; then break; fi