From 42c8699abc827f78ec8822d1a39c87f6c93a8e5b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Mar 2026 08:30:31 +0700 Subject: [PATCH] simplify --- armsrc/mifareutil.c | 8 ++- client/dictionaries/ht2_default.dic | 5 +- client/dictionaries/iclass_default_keys.dic | 16 +++++ client/src/cmdhfmfhard.c | 43 +++++++++-- common/generator.c | 80 ++++++++++++++++++--- common/generator.h | 3 + 6 files changed, 136 insertions(+), 19 deletions(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index bcb0dfe76..8abe836bc 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -92,6 +92,7 @@ uint16_t mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t * uint8_t dcmd[32 + 3]; dcmd[0] = cmd; + if (data_size > 0) { memcpy(dcmd + 1, data, data_size); } @@ -122,15 +123,16 @@ uint16_t mifare_sendcmd_schann(uint8_t *data, uint8_t data_size, uint8_t *answer return 0; } - uint8_t dcmd[16 + 2]; - memset(dcmd, 0, sizeof(dcmd)); + uint8_t dcmd[16 + 2] = {0}; if (data_size > 0) { memcpy(dcmd, data, data_size); } AddCrc14A(dcmd, data_size); + data_size += 2; + ReaderTransmit(dcmd, data_size, timing); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred @@ -146,10 +148,12 @@ uint16_t mifare_sendcmd_schann(uint8_t *data, uint8_t data_size, uint8_t *answer // send 2 byte commands uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint16_t answer_len, uint8_t *answer_parity, uint32_t *timing) { + uint16_t pos; uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t par[MAX_MIFARE_PARITY_SIZE] = {0x00}; // used for cmd and answer + AddCrc14A(dcmd, 2); memcpy(ecmd, dcmd, sizeof(dcmd)); diff --git a/client/dictionaries/ht2_default.dic b/client/dictionaries/ht2_default.dic index 43120be3b..9326a6bf7 100644 --- a/client/dictionaries/ht2_default.dic +++ b/client/dictionaries/ht2_default.dic @@ -22,4 +22,7 @@ BDF5E846 # TSPL 5453504C 05040202 -25293C2F \ No newline at end of file +25293C2F +# +# Tecom +7A7A7A7B diff --git a/client/dictionaries/iclass_default_keys.dic b/client/dictionaries/iclass_default_keys.dic index d1d76d2b1..c6ed4c33f 100644 --- a/client/dictionaries/iclass_default_keys.dic +++ b/client/dictionaries/iclass_default_keys.dic @@ -6,11 +6,27 @@ AEA684A6DAB23278 # AA1 7665544332211000 # key1/Kc from PicoPass 2k documentation 0123456789ABCDEF # SAGEM +# +# KeyNo 14 X-reader 5b7c62c491c11b39 # from loclass demo file. +# KeyNo 13 X-reader +FEB475FABF65BE43 +# KeyNo 12 X-reader +B58EA6E835FFC090 +# KeyNo 460F1F15 X-reader +976CE582C3263457 +# F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation 5CBCF1DA45D5FB4F # PicoPass Default Exchange Key 31ad7ebd2f282168 # From HID multiclassSE reader # +0102030405060708 # default HID 3DES +5CBCF1DA45D5FB5F # picopass? +E0D1629F4DAEF400 # unkn +69434C694D414944 # iCLiMAID +# +E9924C13F4BFA82C # custom key +# # From pastebin: https://pastebin.com/uHqpjiuU 6EFD46EFCBB3C875 E033CA419AEE43F9 diff --git a/client/src/cmdhfmfhard.c b/client/src/cmdhfmfhard.c index 885162437..793b5f983 100644 --- a/client/src/cmdhfmfhard.c +++ b/client/src/cmdhfmfhard.c @@ -737,6 +737,7 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) { if (p2 == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); + return PM3_EMALLOC; } } else if ((p1->nonce_enc & 0x00ff0000) != (nonce_enc & 0x00ff0000)) { // found distinct 2nd byte. Need to insert. @@ -748,6 +749,7 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) { if (p2 == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); + return PM3_EMALLOC; } } else { // we have seen this 2nd byte before. Nothing to add or insert. @@ -1267,8 +1269,17 @@ static int read_nonce_file(char *filename) { uint32_t nt_enc1 = bytes_to_num(read_buf, 4); uint32_t nt_enc2 = bytes_to_num(read_buf + 4, 4); uint8_t par_enc = bytes_to_num(read_buf + 8, 1); - add_nonce(nt_enc1, par_enc >> 4); - add_nonce(nt_enc2, par_enc & 0x0f); + + int add_res = add_nonce(nt_enc1, par_enc >> 4); + if (add_res == PM3_EMALLOC) { + return add_res; + } + + add_res = add_nonce(nt_enc2, par_enc & 0x0f); + if (add_res == PM3_EMALLOC) { + return add_res; + } + num_acquired_nonces += 2; bytes_read = fread(read_buf, 1, 9, fnonces); } @@ -1528,7 +1539,12 @@ static int simulate_acquire_nonces(void) { for (uint16_t i = 0; i < 113; i++) { simulate_MFplus_RNG(cuid, known_target_key, &nt_enc, &par_enc); - num_acquired_nonces += add_nonce(nt_enc, par_enc); + + int add_res = add_nonce(nt_enc, par_enc); + if ( add_res == PM3_EMALLOC) { + return add_res; + } + num_acquired_nonces += add_res; total_num_nonces++; } @@ -1663,10 +1679,23 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ uint32_t nt_enc2 = bytes_to_num(bufp + 4, 4); uint8_t par_enc = bytes_to_num(bufp + 8, 1); - //PrintAndLogEx(INFO, "Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc1, par_enc >> 4); - num_acquired_nonces += add_nonce(nt_enc1, par_enc >> 4); - //PrintAndLogEx(INFO, "Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc2, par_enc & 0x0f); - num_acquired_nonces += add_nonce(nt_enc2, par_enc & 0x0f); + + // PrintAndLogEx(INFO, "Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc1, par_enc >> 4); + int add_res = add_nonce(nt_enc1, par_enc >> 4); + if (add_res == PM3_EMALLOC) { + DropField(); + return add_res; + } + + num_acquired_nonces += add_res; + + // PrintAndLogEx(INFO, "Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc2, par_enc & 0x0f); + add_res = add_nonce(nt_enc2, par_enc & 0x0f); + if (add_res == PM3_EMALLOC) { + DropField(); + return add_res; + } + num_acquired_nonces += add_res; if (nonce_file_write) { fwrite(bufp, 1, 9, fnonces); diff --git a/common/generator.c b/common/generator.c index ce39a1824..da0cf3d2b 100644 --- a/common/generator.c +++ b/common/generator.c @@ -44,6 +44,8 @@ # define prnt Dbprintf #endif +#define MIFARE_KEY_SIZE 6 + // Implementation tips: // For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travis CI / Appveyor runs. // See special note for MFC based algos. @@ -386,15 +388,16 @@ int mfc_algo_mizip_one(const uint8_t *uid, uint8_t sector, uint8_t keytype, uint if (keytype > 2) return PM3_EINVARG; if (sector == 0) { - // A - if (keytype == 0) - *key = 0xA0A1A2A3A4A5U; - else // B - *key = 0xB4C132439eef; + + if (keytype == 0) { + *key = 0xA0A1A2A3A4A5U; // A + } else { + *key = 0xB4C132439eefU; // B + } } else { - uint8_t txor[6]; + uint8_t txor[MIFARE_KEY_SIZE]; if (keytype == 0) { @@ -405,7 +408,7 @@ int mfc_algo_mizip_one(const uint8_t *uid, uint8_t sector, uint8_t keytype, uint 0x317AB72F4490, }; - num_to_bytes(xor_tbl_a[sector - 1], 6, txor); + num_to_bytes(xor_tbl_a[sector - 1], MIFARE_KEY_SIZE, txor); *key = (uint64_t)(uid[0] ^ txor[0]) << 40 | @@ -425,7 +428,7 @@ int mfc_algo_mizip_one(const uint8_t *uid, uint8_t sector, uint8_t keytype, uint }; // B - num_to_bytes(xor_tbl_b[sector - 1], 6, txor); + num_to_bytes(xor_tbl_b[sector - 1], MIFARE_KEY_SIZE, txor); *key = (uint64_t)(uid[2] ^ txor[0]) << 40 | @@ -449,7 +452,7 @@ int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { for (int sector = 0; sector < 5; sector++) { uint64_t key = 0; mfc_algo_mizip_one(uid, sector, keytype, &key); - num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6)); + num_to_bytes(key, MIFARE_KEY_SIZE, keys + (keytype * 5 * MIFARE_KEY_SIZE) + (sector * MIFARE_KEY_SIZE)); } } return PM3_SUCCESS; @@ -656,6 +659,64 @@ int mfc_algo_vanderbilt_all(uint8_t *uid, uint8_t *keys) { return PM3_SUCCESS; } +// Kale +int mfc_algo_kale_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { + if (uid == NULL) return PM3_EINVARG; + if (sector > 16) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + + *key = 0xFFFFFFFFFFFF; + + uint8_t tmp[MIFARE_KEY_SIZE] = {0}; + + if ( sector == 11 ) { + + + tmp[4] = uid[1] + 0x2A; + tmp[5] = uid[3] ^ 0x67; + + if ((uid[2] & 0x02) == 0x02) { + tmp[5] ^= (uid[1] ^ 0xFF); + } + + tmp[0] = tmp[5] ^ (uid[3] ^ 0xFF); + tmp[1] = tmp[5] + (uid[0] ^ 0xFF); + tmp[2] = tmp[4] ^ (uid[1] ^ 0xFF); + tmp[3] = tmp[1] + (uid[2] ^ 0xFF); + tmp[4] = tmp[4] + (tmp[0] ^ uid[0]); + tmp[5] = tmp[5] ^ (tmp[2] & uid[2]); + + *key = bytes_to_num(tmp, MIFARE_KEY_SIZE); + } + if ( sector == 1 ) { + + tmp[0] = uid[2] ^ 0x52 ^ uid[3] ^ 0xFF; + tmp[1] = (uid[2] ^ 0x52) + (uid[0] ^ 0xFF); + tmp[2] = (uid[1] + 0x1c) ^ uid[1] ^ 0xFF; + tmp[3] = tmp[1] + (uid[2] ^ 0xFF); + tmp[4] = (uid[0] ^ tmp[0]) + uid[1] + 0x1C; + tmp[5] = (uid[2] & tmp[2]) ^ uid[2] ^ 0x52; + + *key = bytes_to_num(tmp, MIFARE_KEY_SIZE); + } + + return PM3_SUCCESS; +} + +int mfc_algo_kale_all(uint8_t *uid, uint8_t *keys) { + if (uid == NULL) return PM3_EINVARG; + if (keys == NULL) return PM3_EINVARG; + + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 16; sector++) { + uint64_t key = 0; + mfc_algo_kale_one(uid, sector, keytype, &key); + num_to_bytes(key, 6, keys + (keytype * 16 * 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}, @@ -664,6 +725,7 @@ static kdf_t KDFTable[] = { {"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}, + {"Kale", 16, mfc_algo_kale_all, 4}, // {"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 0cd10b8ce..0839fd67b 100644 --- a/common/generator.h +++ b/common/generator.h @@ -82,6 +82,9 @@ 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); +int mfc_algo_kale_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); +int mfc_algo_kale_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);