From 11b94e7748ac561cea9844bfadcf4f9ab18d7ffe Mon Sep 17 00:00:00 2001 From: McEloff Date: Wed, 27 Jan 2021 01:14:20 +0300 Subject: [PATCH 1/2] `trace list -t mf` - now can use external dictionary keys file --- CHANGELOG.md | 1 + client/src/cmdhflist.c | 13 +++++------ client/src/cmdhflist.h | 2 +- client/src/cmdtrace.c | 50 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 868fe6877..ffd6aa4cc 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 `trace list -t mf` - now can use external dictionary keys file - Added support for bidirectional communication for `lf em 4x50 sim` (@tharexde) - Change `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001) - Added `tools/hitag2crack/crack5opencl`, an optimized version of `crack5gpu` (@matrix) diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index 945edda06..dbe80ef5a 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -17,7 +17,6 @@ #include "commonutil.h" // ARRAYLEN #include "mifare/mifarehost.h" -#include "mifare/mifaredefault.h" #include "parity.h" // oddparity #include "ui.h" #include "crc16.h" @@ -1335,7 +1334,7 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8 } -bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { +bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen, const uint64_t *dicKeys, uint32_t dicKeysCount) { static struct Crypto1State *traceCrypto1; *mfDataLen = 0; @@ -1383,12 +1382,12 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes } // check default keys - if (!traceCrypto1) { - for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { - if (NestedCheckKey(g_mifare_default_keys[i], &AuthData, cmd, cmdsize, parity)) { - PrintAndLogEx(NORMAL, " | | * |%61s " _GREEN_("%012" PRIX64) "| |", "key", g_mifare_default_keys[i]); + if (!traceCrypto1 && dicKeys != NULL && dicKeysCount > 0) { + for (int i = 0; i < dicKeysCount; i++) { + if (NestedCheckKey(dicKeys[i], &AuthData, cmd, cmdsize, parity)) { + PrintAndLogEx(NORMAL, " | | * |%60s " _GREEN_("%012" PRIX64) "| |", "key", dicKeys[i]); - mfLastKey = g_mifare_default_keys[i]; + mfLastKey = dicKeys[i]; traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; }; diff --git a/client/src/cmdhflist.h b/client/src/cmdhflist.h index f12f2a61d..ff7f7f799 100644 --- a/client/src/cmdhflist.h +++ b/client/src/cmdhflist.h @@ -51,7 +51,7 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8 void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateCryptoRF(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); +bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen, const uint64_t *dicKeys, uint32_t dicKeysCount); bool NTParityChk(TAuthData *ad, uint32_t ntx); bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc); diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index f934caebe..d53f47883 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -15,6 +15,8 @@ #include "protocols.h" #include "parity.h" // oddparity #include "cmdhflist.h" // annotations +#include "commonutil.h" // ARRAYLEN +#include "mifare/mifaredefault.h" // mifare default key array #include "comms.h" // for sending cmds to device. GetFromBigBuf #include "fileutils.h" // for saveFile #include "cmdlfhitag.h" // annotate hitag @@ -131,7 +133,8 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac return ret; } -static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes, uint32_t *prev_eot, bool use_us) { +static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes, uint32_t *prev_eot, bool use_us, + const uint64_t *mfDicKeys, uint32_t mfDicKeysCount) { // sanity check if (is_last_record(tracepos, traceLen)) { PrintAndLogEx(DEBUG, "last record triggered. t-pos: %u t-len %u", tracepos, traceLen); @@ -428,7 +431,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr } if (protocol == PROTO_MIFARE) { - if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen)) { + if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen, mfDicKeys, mfDicKeysCount)) { memset(explanation, 0x00, sizeof(explanation)); if (hdr->isResponse == false) { annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen); @@ -612,8 +615,9 @@ int CmdTraceList(const char *Cmd) { "trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n" "trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " communications\n" "trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n" - "trace list -t 14a -f -> show frame delay times\n" - "trace list -t 14a -1 -> use trace buffer " + "trace list -t mf -d -> use dictionary keys file\n" + "trace list -t 14a -f -> show frame delay times\n" + "trace list -t 14a -1 -> use trace buffer " ); void *argtable[] = { @@ -626,6 +630,7 @@ int CmdTraceList(const char *Cmd) { arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n" " or to import into Wireshark using encapsulation type \"ISO 14443\""), arg_strx0("t", "type", NULL, "protocol to annotate the trace"), + arg_strx0("d", "dict", NULL, "use dictionary keys file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -642,6 +647,10 @@ int CmdTraceList(const char *Cmd) { CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)type, sizeof(type), &tlen); str_lower(type); + int diclen = 0; + char dictionary[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 8), (uint8_t *)dictionary, sizeof(dictionary), &diclen); + CLIParserFree(ctx); clearCommandBuffer(); @@ -742,6 +751,34 @@ int CmdTraceList(const char *Cmd) { } + const uint64_t *dicKeys = NULL; + uint32_t dicKeysCount = 0; + bool dictionaryLoad = false; + + if (protocol == PROTO_MIFARE) { + if (diclen > 0) { + uint8_t *keyBlock = NULL; + int res = loadFileDICTIONARY_safe(dictionary, (void **) &keyBlock, 6, &dicKeysCount); + if (res != PM3_SUCCESS || dicKeysCount == 0 || keyBlock == NULL) { + PrintAndLogEx(FAILED, "An error occurred while loading the dictionary! (we will use the default keys now)"); + } else { + dicKeys = calloc(dicKeysCount, sizeof(uint64_t)); + for (int i = 0; i < dicKeysCount; i++) { + uint64_t key = bytes_to_num(keyBlock + i * 6, 6); + memcpy((uint8_t *) &dicKeys[i], &key, sizeof(uint64_t)); + } + dictionaryLoad = true; + } + if (keyBlock != NULL) { + free(keyBlock); + } + } + if (dicKeys == NULL) { + dicKeys = g_mifare_default_keys; + dicKeysCount = ARRAYLEN(g_mifare_default_keys); + } + } + PrintAndLogEx(NORMAL, ""); if (use_relative) { PrintAndLogEx(NORMAL, " Gap | Duration | Src | Data (! denotes parity error, ' denotes short bytes) | CRC | Annotation"); @@ -761,11 +798,14 @@ int CmdTraceList(const char *Cmd) { } while (tracepos < g_traceLen) { - tracepos = printTraceLine(tracepos, g_traceLen, g_trace, protocol, show_wait_cycles, mark_crc, prev_EOT, use_us); + tracepos = printTraceLine(tracepos, g_traceLen, g_trace, protocol, show_wait_cycles, mark_crc, prev_EOT, use_us, dicKeys, dicKeysCount); if (kbd_enter_pressed()) break; } + + if (dictionaryLoad) + free((void *) dicKeys); } if (show_hex) From 2218b4e7db5ecc06b266ee27e033e56daa937f73 Mon Sep 17 00:00:00 2001 From: Eloff Date: Wed, 27 Jan 2021 14:43:50 +0300 Subject: [PATCH 2/2] minor fix --- client/src/cmdtrace.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index d53f47883..a95503813 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -615,7 +615,7 @@ int CmdTraceList(const char *Cmd) { "trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n" "trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " communications\n" "trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n" - "trace list -t mf -d -> use dictionary keys file\n" + "trace list -t mf --dict -> use dictionary keys file\n" "trace list -t 14a -f -> show frame delay times\n" "trace list -t 14a -1 -> use trace buffer " ); @@ -630,7 +630,7 @@ int CmdTraceList(const char *Cmd) { arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n" " or to import into Wireshark using encapsulation type \"ISO 14443\""), arg_strx0("t", "type", NULL, "protocol to annotate the trace"), - arg_strx0("d", "dict", NULL, "use dictionary keys file"), + arg_strx0(NULL, "dict", "", "use dictionary keys file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -648,8 +648,11 @@ int CmdTraceList(const char *Cmd) { str_lower(type); int diclen = 0; - char dictionary[FILE_PATH_SIZE] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 8), (uint8_t *)dictionary, sizeof(dictionary), &diclen); + char dictionary[FILE_PATH_SIZE + 2] = {0}; + if (CLIParamStrToBuf(arg_get_str(ctx, 8), (uint8_t *)dictionary, FILE_PATH_SIZE, &diclen)) { + PrintAndLogEx(FAILED, "Dictionary file name too long or invalid."); + diclen = 0; + } CLIParserFree(ctx);