diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 90a667105..7206b735c 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -281,7 +281,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ } break; - // Received RWD authentication challenge and respnse + // Received RWD authentication challenge and response case 64: { // Store the authentication attempt if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { @@ -891,7 +891,7 @@ static bool hitag2_test_auth_attempts(uint8_t *rx, const size_t rxlen, uint8_t * if (bCrypto) { Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]); - // Removing failed entry from authentiations table + // Removing failed entry from authentications table memcpy(auth_table + auth_table_pos, auth_table + auth_table_pos + 8, 8); auth_table_len -= 8; diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 8cd28b842..74c77b8f9 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -224,11 +224,11 @@ static int CmdLFHitagEload(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "Specfiy dump filename"), - arg_lit0("1", NULL, "Card type Hitag1"), - arg_lit0("2", NULL, "Card type Hitag2"), - arg_lit0("s", NULL, "Card type HitagS"), - arg_lit0("m", NULL, "Card type HitagM"), + arg_str1("f", "file", "", "Specify dump filename"), + arg_lit0("1", NULL, "Card type Hitag 1"), + arg_lit0("2", NULL, "Card type Hitag 2"), + arg_lit0("s", NULL, "Card type Hitag S"), + arg_lit0("m", NULL, "Card type Hitag M"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -243,9 +243,12 @@ static int CmdLFHitagEload(const char *Cmd) { bool use_htm = arg_get_lit(ctx, 5); CLIParserFree(ctx); - uint8_t n = (use_ht1 + use_ht2 + use_hts + use_htm); - if (n != 1) { - PrintAndLogEx(ERR, "error, only specify one Hitag type"); + if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) { + PrintAndLogEx(ERR, "error, specify only one Hitag type"); + return PM3_EINVARG; + } + if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) { + PrintAndLogEx(ERR, "error, specify one Hitag type"); return PM3_EINVARG; } @@ -288,16 +291,16 @@ static int CmdLFHitagEload(const char *Cmd) { static int CmdLFHitagSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf hitag sim", - "Simulate Hitag2 / HitagS transponder\n" + "Simulate Hitag transponder\n" "You need to `lf hitag eload` first", "lf hitag sim -2" ); void *argtable[] = { arg_param_begin, - arg_lit0("1", NULL, "simulate Hitag1"), - arg_lit0("2", NULL, "simulate Hitag2"), - arg_lit0("s", NULL, "simulate HitagS"), + arg_lit0("1", "ht1", "simulate Hitag 1"), + arg_lit0("2", "ht2", "simulate Hitag 2"), + arg_lit0("s", "hts", "simulate Hitag S"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -305,10 +308,15 @@ static int CmdLFHitagSim(const char *Cmd) { bool use_ht1 = arg_get_lit(ctx, 1); bool use_ht2 = arg_get_lit(ctx, 2); bool use_hts = arg_get_lit(ctx, 3); + bool use_htm = false; // not implemented yet CLIParserFree(ctx); - if ((use_ht1 + use_ht2 + use_hts) > 1) { - PrintAndLogEx(ERR, "error, Only specify one Hitag type"); + if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) { + PrintAndLogEx(ERR, "error, specify only one Hitag type"); + return PM3_EINVARG; + } + if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) { + PrintAndLogEx(ERR, "error, specify one Hitag type"); return PM3_EINVARG; } @@ -523,67 +531,85 @@ static int CmdLFHitagInfo(const char *Cmd) { return PM3_SUCCESS; } -// TODO: iceman -// Hitag2 reader, problem is that this command mixes up stuff. So 26 give uid. 21 etc will also give you a memory dump !? -// static int CmdLFHitagReader(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf hitag reader", - "Act like a Hitag Reader", - "Hitag S\n" - " lf hitag reader --01 --nrar 0102030411223344\n" - " lf hitag reader --02 -k 4F4E4D494B52\n" - "Hitag 2\n" - " lf hitag reader --21 -k 4D494B52\n" - " lf hitag reader --22 --nrar 0102030411223344\n" - " lf hitag reader --23 -k 4F4E4D494B52\n" - " lf hitag reader --26\n" + CLIParserInit(&ctx, "lf hitag read", + "Read Hitag memory\n" + "Crypto mode key format: ISK high + ISK low", + "Hitag S, plain mode\n" + " lf hitag read --hts\n" + "Hitag S, challenge mode\n" + " lf hitag read --hts --nrar 0102030411223344\n" + "Hitag S, crypto mode => use default key 4F4E4D494B52 (ONMIKR)\n" + " lf hitag read --hts --crypto\n" + "Hitag S, long key = crypto mode\n" + " lf hitag read --hts -k 4F4E4D494B52\n\n" + + "Hitag 2, password mode => use default key 4D494B52 (MIKR)\n" + " lf hitag read --ht2 --pwd\n" + "Hitag 2, providing a short key = password mode\n" + " lf hitag read --ht2 -k 4D494B52\n" + "Hitag 2, challenge mode\n" + " lf hitag read --ht2 --nrar 0102030411223344\n" + "Hitag 2, crypto mode => use default key 4F4E4D494B52 (ONMIKR)\n" + " lf hitag read --ht2 --crypto\n" + "Hitag 2, providing a long key = crypto mode\n" + " lf hitag read --ht2 -k 4F4E4D494B52\n" ); void *argtable[] = { arg_param_begin, - arg_lit0(NULL, "01", "HitagS, read all pages, challenge mode"), - arg_lit0(NULL, "02", "HitagS, read all pages, crypto mode. Set key=0 for no auth"), - arg_lit0(NULL, "21", "Hitag2, read all pages, password mode. def 4D494B52 (MIKR)"), - arg_lit0(NULL, "22", "Hitag2, read all pages, challenge mode"), - arg_lit0(NULL, "23", "Hitag2, read all pages, crypto mode. Key ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"), - arg_lit0(NULL, "25", "Hitag2, test recorded authentications (replay?)"), - arg_lit0(NULL, "26", "Hitag2, read UID"), + arg_lit0(NULL, "hts", "Hitag S"), + arg_lit0(NULL, "ht2", "Hitag 2"), + arg_lit0(NULL, "pwd", "password mode"), + arg_str0(NULL, "nrar", "", "nonce / answer writer, 8 hex bytes"), + arg_lit0(NULL, "crypto", "crypto mode"), arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), - arg_str0(NULL, "nrar", "", "nonce / answer reader, 8 hex bytes"), +// currently pm3 fw reads all the memory anyway +// arg_int1("p", "page", "", "page address to write to"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - // Hitag S - bool s01 = arg_get_lit(ctx, 1); - bool s02 = arg_get_lit(ctx, 2); + bool use_ht1 = false; // not yet implemented + bool use_hts = arg_get_lit(ctx, 1); + bool use_ht2 = arg_get_lit(ctx, 2); + bool use_htm = false; // not yet implemented - // Hitag 2 - bool h21 = arg_get_lit(ctx, 3); - bool h22 = arg_get_lit(ctx, 4); - bool h23 = arg_get_lit(ctx, 5); - bool h25 = arg_get_lit(ctx, 6); - bool h26 = arg_get_lit(ctx, 7); - - uint8_t key[6]; - int keylen = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 8), key, sizeof(key), &keylen); + bool use_plain = false; + bool use_pwd = arg_get_lit(ctx, 3); + uint8_t nrar[8]; + int nalen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 4), nrar, sizeof(nrar), &nalen); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; } + bool use_nrar = nalen > 0; + bool use_crypto = arg_get_lit(ctx, 5); - uint8_t nrar[8]; - int nalen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 9), nrar, sizeof(nrar), &nalen); - CLIParserFree(ctx); + uint8_t key[6]; + int keylen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 6), key, sizeof(key), &keylen); if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } +// uint32_t page = arg_get_u32_def(ctx, 6, 0); + + CLIParserFree(ctx); + + // sanity checks + if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) { + PrintAndLogEx(ERR, "error, specify only one Hitag type"); + return PM3_EINVARG; + } + if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) { + PrintAndLogEx(ERR, "error, specify one Hitag type"); return PM3_EINVARG; } - // sanity checks if (keylen != 0 && keylen != 4 && keylen != 6) { PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen); return PM3_EINVARG; @@ -594,48 +620,73 @@ static int CmdLFHitagReader(const char *Cmd) { return PM3_EINVARG; } - uint8_t foo = (s01 + s02 + h21 + h22 + h23 + h25 + h26); + // complete options + if (keylen == 4) { + use_pwd = true; + } + if (keylen == 6) { + use_crypto = true; + } + if ((keylen == 0) && use_pwd) { + memcpy(key, "MIKR", 4); + keylen = 4; + } + if ((keylen == 0) && use_crypto) { + memcpy(key, "ONMIKR", 6); + keylen = 6; + } + + // check coherence + uint8_t foo = (use_plain + use_pwd + use_nrar + use_crypto); if (foo > 1) { - PrintAndLogEx(WARNING, "Only specify one HITAG reader cmd"); + PrintAndLogEx(WARNING, "Specify only one authentication mode"); return PM3_EINVARG; } else if (foo == 0) { - PrintAndLogEx(WARNING, "Specify one HITAG reader cms"); + if (use_hts) { + use_plain = true; + } else { + PrintAndLogEx(WARNING, "Specify one authentication mode"); + return PM3_EINVARG; + } + } + + if (use_hts && use_pwd) { // not sure for the other types... + PrintAndLogEx(WARNING, "Chosen Hitag type does not have Password mode"); + return PM3_EINVARG; + } + + if (use_ht2 && use_plain) { // not sure for the other types... + PrintAndLogEx(WARNING, "Chosen Hitag type does not have Plain mode"); return PM3_EINVARG; } hitag_function htf; hitag_data htd; memset(&htd, 0, sizeof(htd)); - - - uint16_t cmd = CMD_LF_HITAG_READER; - if (s01) { + uint16_t cmd; + if (use_hts && use_nrar) { cmd = CMD_LF_HITAGS_READ; htf = RHTSF_CHALLENGE; memcpy(htd.auth.NrAr, nrar, sizeof(htd.auth.NrAr)); - } - if (s02) { + } else if (use_hts && use_crypto) { cmd = CMD_LF_HITAGS_READ; htf = RHTSF_KEY; memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); - } - if (h21) { + } else if (use_ht2 && use_pwd) { + cmd = CMD_LF_HITAG_READER; htf = RHT2F_PASSWORD; memcpy(htd.pwd.password, key, sizeof(htd.pwd.password)); - } - if (h22) { + } else if (use_ht2 && use_nrar) { + cmd = CMD_LF_HITAG_READER; htf = RHT2F_AUTHENTICATE; memcpy(htd.auth.NrAr, nrar, sizeof(htd.auth.NrAr)); - } - if (h23) { + } else if (use_ht2 && use_crypto) { htf = RHT2F_CRYPTO; + cmd = CMD_LF_HITAG_READER; memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); - } - if (h25) { - htf = RHT2F_TEST_AUTH_ATTEMPTS; - } - if (h26) { - htf = RHT2F_UID_ONLY; + } else { + PrintAndLogEx(WARNING, "Sorry, not yet implemented"); + return PM3_ENOTIMPL; } clearCommandBuffer(); @@ -653,21 +704,13 @@ static int CmdLFHitagReader(const char *Cmd) { uint32_t id = bytes_to_num(resp.data.asBytes, 4); uint8_t *data = resp.data.asBytes; PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); - - if (htf != RHT2F_UID_ONLY) { - - // block3, 1 byte - printHitag2Configuration(data[4 * 3]); - - // print data - print_hex_break(data, 48, 4); - - printHitag2PaxtonDowngrade(data); - } + printHitag2Configuration(data[4 * 3]); + print_hex_break(data, 48, 4); + printHitag2PaxtonDowngrade(data); return PM3_SUCCESS; } -static int CmdLFHitagCheckChallenges(const char *Cmd) { +static int CmdLFHitagSCheckChallenges(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf hitag cc", @@ -708,92 +751,169 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { return PM3_SUCCESS; } +static int CmdLFHitag2CheckChallenges(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag ta", + "Test recorded authentications (replay?)", + "lf hitag ta" + ); + + clearCommandBuffer(); + SendCommandMIX(CMD_LF_HITAG_READER, RHT2F_TEST_AUTH_ATTEMPTS, 0, 0, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + if (resp.oldarg[0] == false) { + PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed"); + return PM3_ESOFT; + } + + // FIXME: doegox: not sure what this fct does and what it returns... + return PM3_SUCCESS; +} + + static int CmdLFHitagWriter(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf hitag writer", - "Act like a Hitag writer" - "In password mode the default key is 4D494B52 (MIKR)\n" - "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.", - "Hitag S\n" - " lf hitag writer --03 --nrar 0102030411223344 -p 3 -d 01020304\n" - " lf hitag writer --04 -k 4F4E4D494B52 -p 3 -d 01020304\n" - "Hitag 2\n" - " lf hitag writer --24 -k 4F4E4D494B52 -p 3 -d 01020304\n" - " lf hitag writer --27 -k 4D494B52 -p 3 -d 01020304\n" + CLIParserInit(&ctx, "lf hitag wrbl", + "Write a page in Hitag memory\n" + "Crypto mode key format: ISK high + ISK low", + "Hitag S, plain mode\n" + " lf hitag wrbl --hts -p 6 -d 01020304\n" + "Hitag S, challenge mode\n" + " lf hitag wrbl --hts --nrar 0102030411223344 -p 6 -d 01020304\n" + "Hitag S, crypto mode => use default key 4F4E4D494B52 (ONMIKR)\n" + " lf hitag wrbl --hts --crypto -p 6 -d 01020304\n" + "Hitag S, long key = crypto mode\n" + " lf hitag wrbl --hts -k 4F4E4D494B52 -p 6 -d 01020304\n\n" + + "Hitag 2, password mode => use default key 4D494B52 (MIKR)\n" + " lf hitag wrbl --ht2 --pwd -p 6 -d 01020304\n" + "Hitag 2, providing a short key = password mode\n" + " lf hitag wrbl --ht2 -k 4D494B52 -p 6 -d 01020304\n" + "Hitag 2, challenge mode\n" + " lf hitag wrbl --ht2 --nrar 0102030411223344 -p 6 -d 01020304\n" + "Hitag 2, crypto mode => use default key 4F4E4D494B52 (ONMIKR)\n" + " lf hitag wrbl --ht2 --crypto -p 6 -d 01020304\n" + "Hitag 2, providing a long key = crypto mode\n" + " lf hitag wrbl --ht2 -k 4F4E4D494B52 -p 6 -d 01020304\n" ); void *argtable[] = { arg_param_begin, - arg_lit0(NULL, "03", "HitagS, write page, challenge mode"), - arg_lit0(NULL, "04", "HitagS, write page, crypto mode. Set key=0 for no auth"), - arg_lit0(NULL, "24", "Hitag2, write page, crypto mode."), - arg_lit0(NULL, "27", "Hitag2, write page, password mode"), - arg_int1("p", "page", "", "page address to write to"), - arg_str0("d", "data", "", "data, 4 hex bytes"), - arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_lit0(NULL, "hts", "Hitag S"), + arg_lit0(NULL, "ht2", "Hitag 2"), + arg_lit0(NULL, "pwd", "password mode"), arg_str0(NULL, "nrar", "", "nonce / answer writer, 8 hex bytes"), + arg_lit0(NULL, "crypto", "crypto mode"), + arg_str0("k", "key", "", "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 }; CLIExecWithReturn(ctx, Cmd, argtable, false); - // Hitag S - bool s03 = arg_get_lit(ctx, 1); - bool s04 = arg_get_lit(ctx, 2); + bool use_ht1 = false; // not yet implemented + bool use_hts = arg_get_lit(ctx, 1); + bool use_ht2 = arg_get_lit(ctx, 2); + bool use_htm = false; // not yet implemented - // Hitag 2 - bool h24 = arg_get_lit(ctx, 3); - bool h27 = arg_get_lit(ctx, 4); - - uint32_t page = arg_get_u32_def(ctx, 5, 0); - - uint8_t data[4]; - int dlen = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, sizeof(data), &dlen); + bool use_plain = false; + bool use_pwd = arg_get_lit(ctx, 3); + uint8_t nrar[8]; + int nalen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 4), nrar, sizeof(nrar), &nalen); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; } + bool use_nrar = nalen > 0; + bool use_crypto = arg_get_lit(ctx, 5); uint8_t key[6]; int keylen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 7), key, sizeof(key), &keylen); + res = CLIParamHexToBuf(arg_get_str(ctx, 6), key, sizeof(key), &keylen); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; } - uint8_t nrar[8]; - int nalen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 8), nrar, sizeof(nrar), &nalen); + uint32_t page = arg_get_u32_def(ctx, 7, 0); + + uint8_t data[4]; + int dlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 8), data, sizeof(data), &dlen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } CLIParserFree(ctx); - if (res != 0) { + // sanity checks + if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) { + PrintAndLogEx(ERR, "error, specify only one Hitag type"); + return PM3_EINVARG; + } + if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) { + PrintAndLogEx(ERR, "error, specify one Hitag type"); + return PM3_EINVARG; + } + + if (keylen != 0 && keylen != 4 && keylen != 6) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen); return PM3_EINVARG; } - // sanity checks if (dlen != sizeof(data)) { PrintAndLogEx(WARNING, "Wrong DATA len expected 4, got %d", dlen); return PM3_EINVARG; } - if (keylen != 0 && keylen != 6 && keylen != 4) { - PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen); - return PM3_EINVARG; - } - if (nalen != 0 && nalen != 8) { PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen); return PM3_EINVARG; } - uint8_t foo = (s03 + s04 + h24 + h27); + // complete options + if (keylen == 4) { + use_pwd = true; + } + if (keylen == 6) { + use_crypto = true; + } + if ((keylen == 0) && use_pwd) { + memcpy(key, "MIKR", 4); + keylen = 4; + } + if ((keylen == 0) && use_crypto) { + memcpy(key, "ONMIKR", 6); + keylen = 6; + } + + // check coherence + uint8_t foo = (use_plain + use_pwd + use_nrar + use_crypto); if (foo > 1) { - PrintAndLogEx(WARNING, "Only specify one HITAG write cmd"); + PrintAndLogEx(WARNING, "Specify only one authentication mode"); return PM3_EINVARG; } else if (foo == 0) { - PrintAndLogEx(WARNING, "Specify one HITAG write cmd"); + if (use_hts) { + use_plain = true; + } else { + PrintAndLogEx(WARNING, "Specify one authentication mode"); + return PM3_EINVARG; + } + } + + if (use_hts && use_pwd) { // not sure for the other types... + PrintAndLogEx(WARNING, "Chosen Hitag type does not have Password mode"); + return PM3_EINVARG; + } + + if (use_ht2 && use_plain) { // not sure for the other types... + PrintAndLogEx(WARNING, "Chosen Hitag type does not have Plain mode"); return PM3_EINVARG; } @@ -801,29 +921,33 @@ static int CmdLFHitagWriter(const char *Cmd) { hitag_data htd; memset(&htd, 0, sizeof(htd)); - if (s03) { + if (use_hts && use_nrar) { htf = WHTSF_CHALLENGE; memcpy(htd.auth.NrAr, nrar, sizeof(htd.auth.NrAr)); memcpy(htd.auth.data, data, sizeof(data)); - } - if (s04) { + PrintAndLogEx(INFO, "Authenticating to Hitag S in Challenge mode"); + } else if (use_hts && use_crypto) { htf = WHTSF_KEY; memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); memcpy(htd.crypto.data, data, sizeof(data)); - } - if (h24) { - htf = WHT2F_CRYPTO; - memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); - memcpy(htd.crypto.data, data, sizeof(data)); - } - if (h27) { + PrintAndLogEx(INFO, "Authenticating to Hitag S in Crypto mode"); + } else if (use_ht2 && use_pwd) { htf = WHT2F_PASSWORD; memcpy(htd.pwd.password, key, sizeof(htd.pwd.password)); memcpy(htd.crypto.data, data, sizeof(data)); + PrintAndLogEx(INFO, "Authenticating to Hitag 2 in Password mode"); + } else if (use_ht2 && use_crypto) { + htf = WHT2F_CRYPTO; + memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); + memcpy(htd.crypto.data, data, sizeof(data)); + PrintAndLogEx(INFO, "Authenticating to Hitag 2 in Crypto mode"); + } else { + PrintAndLogEx(WARNING, "Sorry, not yet implemented"); + return PM3_ENOTIMPL; } - + uint16_t cmd = CMD_LF_HITAGS_WRITE; clearCommandBuffer(); - SendCommandMIX(CMD_LF_HITAGS_WRITE, htf, 0, page, &htd, sizeof(htd)); + SendCommandMIX(cmd, htf, 0, page, &htd, sizeof(htd)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 4000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); @@ -841,56 +965,132 @@ static int CmdLFHitag2Dump(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf hitag dump", - "Read all card memory and save to file" - "In password mode the default key is 4D494B52 (MIKR)\n" - "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.", - "lf hitag dump -k 4F4E4D494B52\n" - "lf hitag dump -k 4D494B52\n" + "Read all Hitag 2 card memory and save to file\n" + "Crypto mode key format: ISK high + ISK low", + "Password mode => use default key 4D494B52 (MIKR)\n" + " lf hitag dump --pwd\n" + "Short key = password mode\n" + " lf hitag dump -k 4D494B52\n" + "Challenge mode\n" + " lf hitag dump --nrar 0102030411223344\n" + "Crypto mode => use default key 4F4E4D494B52 (ONMIKR)\n" + " lf hitag dump --crypto\n" + "Long key = crypto mode\n" + " lf hitag dump -k 4F4E4D494B52\n" ); void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "specify file name"), - arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_lit0(NULL, "pwd", "password mode"), arg_str0(NULL, "nrar", "", "nonce / answer reader, 8 hex bytes"), + arg_lit0(NULL, "crypto", "crypto mode"), + arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_str0("f", "file", "", "specify file name"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - int fnlen = 0; - char filename[FILE_PATH_SIZE] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool use_ht1 = false; // not yet implemented + bool use_hts = false; // not yet implemented + bool use_ht2 = true; + bool use_htm = false; // not yet implemented + + bool use_plain = false; + bool use_pwd = arg_get_lit(ctx, 1); + uint8_t nrar[8]; + int nalen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 2), nrar, sizeof(nrar), &nalen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + bool use_nrar = nalen > 0; + bool use_crypto = arg_get_lit(ctx, 3); uint8_t key[6]; int keylen = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 2), key, sizeof(key), &keylen); + res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &keylen); if (res != 0) { CLIParserFree(ctx); return PM3_EINVARG; } - uint8_t nrar[8]; - int nalen = 0; - res = CLIParamHexToBuf(arg_get_str(ctx, 3), nrar, sizeof(nrar), &nalen); + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + CLIParserFree(ctx); - if (res != 0) { + + // sanity checks + if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) { + PrintAndLogEx(ERR, "error, specify only one Hitag type"); + return PM3_EINVARG; + } + if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) { + PrintAndLogEx(ERR, "error, specify one Hitag type"); + return PM3_EINVARG; + } + + if (keylen != 0 && keylen != 4 && keylen != 6) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen); + return PM3_EINVARG; + } + + // complete options + if (keylen == 4) { + use_pwd = true; + } + if (keylen == 6) { + use_crypto = true; + } + if ((keylen == 0) && use_pwd) { + memcpy(key, "MIKR", 4); + keylen = 4; + } + if ((keylen == 0) && use_crypto) { + memcpy(key, "ONMIKR", 6); + keylen = 6; + } + + // check coherence + uint8_t foo = (use_plain + use_pwd + use_nrar + use_crypto); + if (foo > 1) { + PrintAndLogEx(WARNING, "Specify only one authentication mode"); + return PM3_EINVARG; + } else if (foo == 0) { + if (use_hts) { + use_plain = true; + } else { + PrintAndLogEx(WARNING, "Specify one authentication mode"); + return PM3_EINVARG; + } + } + + if (use_hts && use_pwd) { // not sure for the other types... + PrintAndLogEx(WARNING, "Chosen Hitag type does not have Password mode"); + return PM3_EINVARG; + } + + if (use_ht2 && use_plain) { // not sure for the other types... + PrintAndLogEx(WARNING, "Chosen Hitag type does not have Plain mode"); return PM3_EINVARG; } hitag_function htf; hitag_data htd; memset(&htd, 0, sizeof(htd)); - - if (keylen == 6) { - htf = RHT2F_CRYPTO; - memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); - PrintAndLogEx(INFO, "Authenticating in crypto mode"); - } else { + if (use_ht2 && use_pwd) { htf = RHT2F_PASSWORD; memcpy(htd.pwd.password, key, sizeof(htd.pwd.password)); - PrintAndLogEx(INFO, "Authenticating in password mode"); + PrintAndLogEx(INFO, "Authenticating to Hitag 2 in Password mode"); + } else if (use_ht2 && use_crypto) { + htf = RHT2F_CRYPTO; + memcpy(htd.crypto.key, key, sizeof(htd.crypto.key)); + PrintAndLogEx(INFO, "Authenticating to Hitag 2 in Crypto mode"); + } else { + PrintAndLogEx(WARNING, "Sorry, not yet implemented"); + return PM3_ENOTIMPL; } - uint16_t cmd = CMD_LF_HITAG_READER; clearCommandBuffer(); SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd)); @@ -909,7 +1109,8 @@ static int CmdLFHitag2Dump(const char *Cmd) { if (data == NULL) return PM3_ESOFT; - PrintAndLogEx(SUCCESS, "Dumping tag memory..."); + uint32_t id = bytes_to_num(resp.data.asBytes, 4); + PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); if (fnlen < 1) { char *fptr = filename; @@ -917,8 +1118,16 @@ static int CmdLFHitag2Dump(const char *Cmd) { FillFileNameByUID(fptr, data, "-dump", 4); } + // block3, 1 byte + printHitag2Configuration(data[4 * 3]); + + // print data print_hex_break(data, 48, 4); + printHitag2PaxtonDowngrade(data); + + PrintAndLogEx(SUCCESS, "Dumping tag memory..."); + pm3_save_dump(filename, data, 48, jsfHitag, 4); return PM3_SUCCESS; } @@ -982,16 +1191,20 @@ void annotateHitagS(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, } static command_t CommandTable[] = { + {"-----------", CmdHelp, IfPm3Hitag, "------------------------ " _CYAN_("General") " ------------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"eload", CmdLFHitagEload, IfPm3Hitag, "Load Hitag dump file into emulator memory"}, {"list", CmdLFHitagList, AlwaysAvailable, "List Hitag trace history"}, - {"info", CmdLFHitagInfo, IfPm3Hitag, "Hitag2 tag information"}, - {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag reader"}, - {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder"}, + {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("operations") " -----------------------"}, + {"info", CmdLFHitagInfo, IfPm3Hitag, "Hitag 2 tag information"}, + {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag 2 tag"}, + {"read", CmdLFHitagReader, IfPm3Hitag, "Read Hitag memory"}, + {"wrbl", CmdLFHitagWriter, IfPm3Hitag, "Write a block (page) in Hitag memory"}, {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication"}, - {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag writer"}, - {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag2 tag"}, - {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges"}, + {"cc", CmdLFHitagSCheckChallenges, IfPm3Hitag, "Hitag S: test all provided challenges"}, + {"ta", CmdLFHitag2CheckChallenges, IfPm3Hitag, "Hitag 2: test all recorded authentications"}, + {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("simulation") " -----------------------"}, + {"eload", CmdLFHitagEload, IfPm3Hitag, "Load Hitag dump file into emulator memory"}, + {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder"}, { NULL, NULL, 0, NULL } };