From ad3885a9bb56b15b4b73c6ad679743c5598e3044 Mon Sep 17 00:00:00 2001 From: jof Lassoff Date: Tue, 10 Mar 2026 15:49:39 +0000 Subject: [PATCH] Add Vanderbilt ACT pattern-based key generation to hf mf keygen - Implements mfc_algo_vanderbilt_one() and mfc_algo_vanderbilt_all() - Generates keys using 'Acces' + block ID pattern (416363657300-4163636573FF) - Supports all 40 sectors for 4K cards - Eliminates need for 256+ keys in dictionary file - Keys generated dynamically on-demand --- common/generator.c | 37 +++++++++++++++++++++++++++++++++++++ common/generator.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/common/generator.c b/common/generator.c index 62512c103..ce39a1824 100644 --- a/common/generator.c +++ b/common/generator.c @@ -620,6 +620,42 @@ int mfc_algo_snapmaker_all(uint8_t *uid, uint8_t *keys) { return PM3_SUCCESS; } +// Vanderbilt ACT pattern-based key generation +// Generates keys by appending block ID to "Acces" (0x4163636573) +// Pattern: 416363657300, 416363657301, ..., 4163636573FF +int mfc_algo_vanderbilt_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { + if (key == NULL) return PM3_EINVARG; + if (sector > 39) return PM3_EINVARG; + + // Base pattern: "Acces" in ASCII = 0x4163636573 + // For each sector, we generate keys for all 4 blocks (or 16 for sector 32+) + // Key format: 41 63 63 65 73 XX where XX is the block number + + uint8_t first_block = (sector < 32) ? (sector * 4) : (128 + (sector - 32) * 16); + uint8_t block_id = first_block + 3; // Use sector trailer block ID + + // Both key A and B use the same pattern with block ID + uint8_t key_bytes[6] = {0x41, 0x63, 0x63, 0x65, 0x73, block_id}; + *key = bytes_to_num(key_bytes, 6); + + return PM3_SUCCESS; +} + +int mfc_algo_vanderbilt_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + + // Generate keys for all sectors (40 sectors for 4K card) + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 40; sector++) { + uint64_t key = 0; + mfc_algo_vanderbilt_one(uid, sector, keytype, &key); + num_to_bytes(key, 6, keys + (keytype * 40 * 6) + (sector * 6)); + } + } + + return PM3_SUCCESS; +} + static kdf_t KDFTable[] = { {"Saflok / Maid", 16, mfc_algo_saflok_all, 4}, {"MIZIP", 5, mfc_algo_mizip_all, 4}, @@ -627,6 +663,7 @@ static kdf_t KDFTable[] = { {"Skylanders", 16, mfc_algo_sky_all, 4}, {"Bambu Lab Filament Spool", 16, mfc_algo_bambu_all, 4}, {"Snapmaker Filament Spool", 16, mfc_algo_snapmaker_all, 4}, + {"Vanderbilt ACT", 40, mfc_algo_vanderbilt_all, 0}, // {"Vinglock", 16, mfc_algo_ving_all, 4}, // not implemented // {"Yale Doorman", 16, mfc_algo_yale_all, 4}, // not implemented }; diff --git a/common/generator.h b/common/generator.h index d0dc0a8e9..0cd10b8ce 100644 --- a/common/generator.h +++ b/common/generator.h @@ -79,6 +79,9 @@ int mfc_algo_bambu_all(uint8_t *uid, uint8_t *keys); int mfc_algo_snapmaker_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_snapmaker_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_vanderbilt_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); +int mfc_algo_vanderbilt_all(uint8_t *uid, uint8_t *keys); + uint32_t lf_t55xx_white_pwdgen(uint32_t id); int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen);