From 3860942e55b58d79cc881fafaa5d44fcffc54adc Mon Sep 17 00:00:00 2001 From: douniwan5788 Date: Fri, 13 Sep 2024 16:54:07 +0800 Subject: [PATCH 1/2] feat: Added support for 8268/8310 --- CHANGELOG.md | 1 + armsrc/hitagS.c | 66 +++++++++++++++++++++++----- client/src/cmdlfhitaghts.c | 89 +++++++++++++++++++++++++++----------- include/hitag.h | 2 + 4 files changed, 122 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7265cb7750..4256b4e8f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 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] +- Added support for 8268/8310 (@douniwan5788) - Changed scripting string params to accept 1024 chars, Thanks @evildaemond! (@iceman1001) - Added detection for FM11NT021 (@iceman1001) - Added detection of a magic NTAG 215 (@iceman1001) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 05255b19ec..ed5595be7b 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -37,7 +37,19 @@ #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D -static struct hitagS_tag tag; +static struct hitagS_tag tag = { + .pages = + { + // Plain mode: | Authentication mode: + [0] = {0x88, 0xcd, 0x6d, 0xf3}, // UID | UID + [1] = {0xca, 0x24, 0x00, 0x00}, // CON0 CON1 CON2 Reserved | CON0 CON1 CON2 PWDH0 + [2] = {0xaa, 0xaa, 0xaa, 0xaa}, // Data | PWDL0 PWDL1 KEYH0 KEYH1 + [3] = {0x55, 0x55, 0x55, 0x55}, // Data | KEYL0 KEYL1 KEYL2 KEYL3 + [4] = {0xff, 0x80, 0x00, 0x00}, // Data + [5] = {0x00, 0x00, 0x00, 0x00}, // Data + // up to index 63 for HITAG S2048 public data + }, +}; static uint8_t page_to_be_written = 0; static int block_data_left = 0; @@ -1360,6 +1372,40 @@ static int selectHitagS(const lf_hitag_data_t *packet, uint8_t *tx, size_t sizeo tx[i] = ((NrAr >> (56 - (i * 8))) & 0xFF); } + } else if (packet->cmd == RHTSF_82xx || packet->cmd == WHTSF_82xx) { + // 8268/8310 Authentication by writing password to block 64 + + //send write page request + txlen = 0; + cmd = HITAGS_WRITE_PAGE; + txlen = concatbits(tx, txlen, &cmd, 0, 4); + + uint8_t addr = 64; + txlen = concatbits(tx, txlen, &addr, 0, 8); + + crc = CRC8Hitag1Bits(tx, txlen); + txlen = concatbits(tx, txlen, &crc, 0, 8); + + sendReceiveHitagS(tx, txlen, rx, sizeofrx, &rxlen, HITAG_T_WAIT_SC, ledcontrol, false); + + if ((rxlen != 2) || (rx[0] >> (8 - 2) != 0x01)) { + Dbprintf("no write access on page " _YELLOW_("64") ". not 82xx?"); + return -1; + } + + txlen = 0; + txlen = concatbits(tx, txlen, packet->pwd, 0, 32); + crc = CRC8Hitag1Bits(tx, txlen); + txlen = concatbits(tx, txlen, &crc, 0, 8); + + sendReceiveHitagS(tx, txlen, rx, sizeofrx, &rxlen, HITAG_T_WAIT_SC, ledcontrol, false); + + if ((rxlen != 2) || (rx[0] >> (8 - 2) != 0x01)) { + Dbprintf("write to page " _YELLOW_("64") " failed! wrong password?"); + return -1; + } + + return 0; } else if (packet->cmd == RHTSF_PLAIN || packet->cmd == WHTSF_PLAIN) { Dbprintf("Error, " _YELLOW_("AUT=1") " This tag is configured in Authentication Mode"); return -1; @@ -1413,19 +1459,15 @@ static int selectHitagS(const lf_hitag_data_t *packet, uint8_t *tx, size_t sizeo * Reads every page of a hitag S transpoder. */ void ReadHitagS(const lf_hitag_data_t *payload, bool ledcontrol) { - + int status = PM3_SUCCESS; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t tx[HITAG_FRAME_LEN]; if (selectHitagS(payload, tx, ARRAYLEN(tx), rx, ARRAYLEN(rx), HITAG_T_WAIT_FIRST, ledcontrol) == -1) { - - hitagS_stop_clock(); - set_tracing(false); - lf_finalize(ledcontrol); - reply_ng(CMD_LF_HITAGS_READ, PM3_ERFTRANS, NULL, 0); - return; + status = PM3_ERFTRANS; + goto read_end; } int pageNum = 0; @@ -1445,9 +1487,10 @@ void ReadHitagS(const lf_hitag_data_t *payload, bool ledcontrol) { sendReceiveHitagS(tx, txlen, rx, ARRAYLEN(rx), &rxlen, HITAG_T_WAIT_SC, ledcontrol, false); - if (rxlen == 0) { + if (rxlen != 40) { Dbprintf("Read page failed!"); - break; + status = PM3_ERFTRANS; + goto read_end; } //save received data - 40 bits @@ -1499,10 +1542,11 @@ void ReadHitagS(const lf_hitag_data_t *payload, bool ledcontrol) { } } +read_end: hitagS_stop_clock(); set_tracing(false); lf_finalize(ledcontrol); - reply_ng(CMD_LF_HITAGS_READ, PM3_SUCCESS, (uint8_t *)tag.pages, sizeof(tag.pages)); + reply_ng(CMD_LF_HITAGS_READ, status, (uint8_t *)tag.pages, sizeof(tag.pages)); } /* diff --git a/client/src/cmdlfhitaghts.c b/client/src/cmdlfhitaghts.c index a55a46255d..01f368bd30 100644 --- a/client/src/cmdlfhitaghts.c +++ b/client/src/cmdlfhitaghts.c @@ -43,8 +43,11 @@ static int CmdLFHitagSRead(const char *Cmd) { "Read Hitag S memory.\n\n" " Crypto mode: \n" " - key format ISK high + ISK low\n" - " - default key 4F4E4D494B52 (ONMIKR)\n", - " lf hitag hts read -> Hitag S, plain mode\n" + " - default key 4F4E4D494B52 (ONMIKR)\n\n" + " 8268/8310 password mode: \n" + " - default password BBDD3399\n", + " lf hitag hts read -> Hitag S/8211, plain mode\n" + " lf hitag hts read --8 -k BBDD3399 -> 8268/8310, password mode\n" " lf hitag hts read --nrar 0102030411223344 -> Hitag S, challenge mode\n" " lf hitag hts read --crypto -> Hitag S, crypto mode, def key\n" " lf hitag hts read -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n" @@ -53,8 +56,9 @@ static int CmdLFHitagSRead(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0(NULL, "nrar", "", "nonce / answer writer, 8 hex bytes"), + arg_lit0(NULL, "8", "8268/8310 mode"), arg_lit0(NULL, "crypto", "crypto mode"), - arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_str0("k", "key", "", "pwd or key, 4 or 6 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -71,12 +75,13 @@ static int CmdLFHitagSRead(const char *Cmd) { } bool use_nrar = nrar_len > 0; - bool use_crypto = arg_get_lit(ctx, 2); + bool use_82xx = arg_get_lit(ctx, 2); + bool use_crypto = arg_get_lit(ctx, 3); uint8_t key[6]; int key_len = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, sizeof(key), &key_len); + res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &key_len); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; @@ -84,8 +89,8 @@ static int CmdLFHitagSRead(const char *Cmd) { CLIParserFree(ctx); - if (key_len && key_len != HITAGS_CRYPTOKEY_SIZE) { - PrintAndLogEx(WARNING, "Wrong KEY len expected %d, got %d", HITAGS_CRYPTOKEY_SIZE, key_len); + if (key_len != 0 && key_len != 4 && key_len != 6) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", key_len); return PM3_EINVARG; } @@ -94,13 +99,24 @@ static int CmdLFHitagSRead(const char *Cmd) { return PM3_EINVARG; } - if (!key_len && use_crypto) { + // complete options + if (key_len == 4) { + use_82xx = true; + } + if (key_len == 6) { + use_crypto = true; + } + if ((key_len == 0) && use_82xx) { + memcpy(key, (uint8_t[]){0xBB, 0xDD, 0x33, 0x99}, 4); + key_len = 4; + } + if ((key_len == 0) && use_crypto) { memcpy(key, "ONMIKR", 6); key_len = 6; } // check coherence - uint8_t auth_methods = (use_plain + use_nrar + use_crypto); + uint8_t auth_methods = (use_plain + use_nrar + use_82xx + use_crypto); if (auth_methods > 1) { PrintAndLogEx(WARNING, "Specify only one authentication mode"); return PM3_EINVARG; @@ -118,6 +134,11 @@ static int CmdLFHitagSRead(const char *Cmd) { memcpy(packet.NrAr, nrar, sizeof(packet.NrAr)); } + if (use_82xx) { + packet.cmd = RHTSF_82xx; + memcpy(packet.pwd, key, sizeof(packet.pwd)); + } + if (use_crypto) { packet.cmd = RHTSF_KEY; memcpy(packet.key, key, sizeof(packet.key)); @@ -168,8 +189,11 @@ static int CmdLFHitagSWrite(const char *Cmd) { "Write a page in Hitag S memory.\n" " Crypto mode: \n" " - key format ISK high + ISK low\n" - " - default key 4F4E4D494B52 (ONMIKR)\n", - " lf hitag hts write -p 6 -d 01020304 -> Hitag S, plain mode\n" + " - default key 4F4E4D494B52 (ONMIKR)\n\n" + " 8268/8310 password mode: \n" + " - default password BBDD3399\n", + " lf hitag hts write -p 6 -d 01020304 -> Hitag S/8211, plain mode\n" + " lf hitag hts write -p 6 -d 01020304 --8 -k BBDD3399 -> 8268/8310, password mode\n" " lf hitag hts write -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag S, challenge mode\n" " lf hitag hts write -p 6 -d 01020304 --crypto -> Hitag S, crypto mode, default key\n" " lf hitag hts write -p 6 -d 01020304 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n" @@ -178,8 +202,9 @@ static int CmdLFHitagSWrite(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0(NULL, "nrar", "", "nonce / answer writer, 8 hex bytes"), + arg_lit0(NULL, "8", "8268/8310 mode"), arg_lit0(NULL, "crypto", "crypto mode"), - arg_str0("k", "key", "", "key, 6 hex bytes"), + arg_str0("k", "key", "", "pwd or key, 4 or 6 hex bytes"), arg_int1("p", "page", "", "page address to write to"), arg_str1("d", "data", "", "data, 4 hex bytes"), arg_param_end @@ -198,23 +223,24 @@ static int CmdLFHitagSWrite(const char *Cmd) { } bool use_nrar = nrar_len > 0; - bool use_crypto = arg_get_lit(ctx, 2); + bool use_82xx = arg_get_lit(ctx, 2); + bool use_crypto = arg_get_lit(ctx, 3); uint8_t key[6]; int key_len = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, sizeof(key), &key_len); + res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &key_len); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; } - int page = arg_get_int_def(ctx, 4, 0); + int page = arg_get_int_def(ctx, 5, 0); uint8_t data[4]; int data_len = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 5), data, sizeof(data), &data_len); + res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, sizeof(data), &data_len); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; @@ -222,8 +248,8 @@ static int CmdLFHitagSWrite(const char *Cmd) { CLIParserFree(ctx); - if (key_len && key_len != HITAGS_CRYPTOKEY_SIZE) { - PrintAndLogEx(WARNING, "Wrong KEY len expected %d, got %d", HITAGS_CRYPTOKEY_SIZE, key_len); + if (key_len != 0 && key_len != 4 && key_len != 6) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", key_len); return PM3_EINVARG; } @@ -232,13 +258,24 @@ static int CmdLFHitagSWrite(const char *Cmd) { return PM3_EINVARG; } - if (!key_len && use_crypto) { + // complete options + if (key_len == 4) { + use_82xx = true; + } + if (key_len == 6) { + use_crypto = true; + } + if ((key_len == 0) && use_82xx) { + memcpy(key, (uint8_t[]){0xBB, 0xDD, 0x33, 0x99}, 4); + key_len = 4; + } + if ((key_len == 0) && use_crypto) { memcpy(key, "ONMIKR", 6); key_len = 6; } // check coherence - uint8_t auth_methods = (use_plain + use_nrar + use_crypto); + uint8_t auth_methods = (use_plain + use_nrar + use_82xx + use_crypto); if (auth_methods > 1) { PrintAndLogEx(WARNING, "Specify only one authentication mode"); return PM3_EINVARG; @@ -257,6 +294,11 @@ static int CmdLFHitagSWrite(const char *Cmd) { memcpy(packet.NrAr, nrar, sizeof(packet.NrAr)); } + if (use_82xx) { + packet.cmd = WHTSF_82xx; + memcpy(packet.pwd, key, sizeof(packet.pwd)); + } + if (use_crypto) { packet.cmd = WHTSF_KEY; memcpy(packet.key, key, sizeof(packet.key)); @@ -292,13 +334,10 @@ static int CmdLFHitagSList(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdLFHitagSList, AlwaysAvailable, "List Hitag S trace history"}, - { - "-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_( - "General") " ------------------------" - }, + {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("General") " ------------------------"}, {"read", CmdLFHitagSRead, IfPm3Hitag, "Read Hitag S memory"}, {"write", CmdLFHitagSWrite, IfPm3Hitag, "Write Hitag S page"}, - {NULL, NULL, 0, NULL} + {NULL, NULL, 0, NULL} }; static int CmdHelp(const char *Cmd) { diff --git a/include/hitag.h b/include/hitag.h index aa8ad7c9cf..48a0030f30 100644 --- a/include/hitag.h +++ b/include/hitag.h @@ -48,6 +48,8 @@ typedef enum { RHTSF_PLAIN, WHTSF_PLAIN, + RHTSF_82xx, + WHTSF_82xx, RHTSF_CHALLENGE, WHTSF_CHALLENGE, RHTSF_KEY, From 0c7964084c61a7dd5d720ac9248b65bbdc709270 Mon Sep 17 00:00:00 2001 From: douniwan5788 Date: Fri, 13 Sep 2024 16:57:16 +0800 Subject: [PATCH 2/2] feat: Added `lf em 410x clone --hts` clone EM410x ID to 8268/8310 --- client/src/cmdlfem410x.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/client/src/cmdlfem410x.c b/client/src/cmdlfem410x.c index 67c53972e5..9355479cba 100644 --- a/client/src/cmdlfem410x.c +++ b/client/src/cmdlfem410x.c @@ -676,11 +676,11 @@ static size_t concatbits(uint8_t *dst, size_t dstskip, const uint8_t *src, size_ static int CmdEM410xClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 410x clone", - "clone a EM410x ID to a T55x7, Q5/T5555, EM4305/4469 or Hitag S/8211 tag.", + "clone a EM410x ID to a T55x7, Q5/T5555, EM4305/4469 or Hitag S/8211/8268/8310 tag.", "lf em 410x clone --id 0F0368568B -> encode for T55x7 tag\n" "lf em 410x clone --id 0F0368568B --q5 -> encode for Q5/T5555 tag\n" "lf em 410x clone --id 0F0368568B --em -> encode for EM4305/4469\n" - "lf em 410x clone --id 0F0368568B --hs -> encode for Hitag S/8211" + "lf em 410x clone --id 0F0368568B --hts -> encode for Hitag S/8211/8268/8310" ); void *argtable[] = { @@ -689,7 +689,7 @@ static int CmdEM410xClone(const char *Cmd) { arg_str1(NULL, "id", "", "EM Tag ID number (5 hex bytes)"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), - arg_lit0(NULL, "hs", "optional - specify writing to Hitag S/8211 tag"), + arg_lit0(NULL, "hts", "optional - specify writing to Hitag S/8211/8268/8310 tag"), arg_lit0(NULL, "electra", "optional - add Electra blocks to tag"), arg_param_end }; @@ -702,16 +702,16 @@ static int CmdEM410xClone(const char *Cmd) { CLIGetHexWithReturn(ctx, 2, uid, &uid_len); bool q5 = arg_get_lit(ctx, 3); bool em = arg_get_lit(ctx, 4); - bool hs = arg_get_lit(ctx, 5); + bool hts = arg_get_lit(ctx, 5); bool add_electra = arg_get_lit(ctx, 6); CLIParserFree(ctx); - if (q5 + em + hs > 1) { + if (q5 + em + hts > 1) { PrintAndLogEx(FAILED, "Only specify one tag Type"); return PM3_EINVARG; } - if (hs) { + if (hts) { if (IfPm3Hitag() == false) { PrintAndLogEx(FAILED, "Device not compiled to support Hitag"); return PM3_EINVARG; @@ -730,7 +730,7 @@ static int CmdEM410xClone(const char *Cmd) { uint64_t id = bytes_to_num(uid, uid_len); PrintAndLogEx(SUCCESS, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with EM Tag ID " _GREEN_("%010" PRIX64) " (RF/%d)", - q5 ? "Q5/T5555" : (em ? "EM4305/4469" : (hs ? "Hitag S/8211" : "T55x7")), id, clk); + q5 ? "Q5/T5555" : (em ? "EM4305/4469" : (hts ? "Hitag S/82xx" : "T55x7")), id, clk); uint8_t data[HITAG_BLOCK_SIZE * 2] = {0xFF, 0x80}; // EM410X_HEADER 9 bits of one uint32_t databits = 9; @@ -754,7 +754,7 @@ static int CmdEM410xClone(const char *Cmd) { clearCommandBuffer(); PacketResponseNG resp; - if (hs) { + if (hts) { lf_hitag_data_t packet; memset(&packet, 0, sizeof(packet)); @@ -791,7 +791,8 @@ static int CmdEM410xClone(const char *Cmd) { break; } - packet.cmd = WHTSF_PLAIN; + packet.cmd = WHTSF_82xx; + memcpy(packet.pwd, (uint8_t[]){0xBB, 0xDD, 0x33, 0x99}, 4); SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *)&packet, sizeof(packet)); if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 4000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply.");