Merge pull request #1174 from McEloff/trace_list_mf_dict

`trace list -t mf` - now can use external dictionary keys file
This commit is contained in:
Iceman 2021-01-27 12:49:06 +01:00 committed by GitHub
commit 375909653d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 13 deletions

View file

@ -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... 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] ## [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) - Added support for bidirectional communication for `lf em 4x50 sim` (@tharexde)
- Change `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001) - Change `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001)
- Added `tools/hitag2crack/crack5opencl`, an optimized version of `crack5gpu` (@matrix) - Added `tools/hitag2crack/crack5opencl`, an optimized version of `crack5gpu` (@matrix)

View file

@ -17,7 +17,6 @@
#include "commonutil.h" // ARRAYLEN #include "commonutil.h" // ARRAYLEN
#include "mifare/mifarehost.h" #include "mifare/mifarehost.h"
#include "mifare/mifaredefault.h"
#include "parity.h" // oddparity #include "parity.h" // oddparity
#include "ui.h" #include "ui.h"
#include "crc16.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; static struct Crypto1State *traceCrypto1;
*mfDataLen = 0; *mfDataLen = 0;
@ -1383,12 +1382,12 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes
} }
// check default keys // check default keys
if (!traceCrypto1) { if (!traceCrypto1 && dicKeys != NULL && dicKeysCount > 0) {
for (int i = 0; i < ARRAYLEN(g_mifare_default_keys); i++) { for (int i = 0; i < dicKeysCount; i++) {
if (NestedCheckKey(g_mifare_default_keys[i], &AuthData, cmd, cmdsize, parity)) { if (NestedCheckKey(dicKeys[i], &AuthData, cmd, cmdsize, parity)) {
PrintAndLogEx(NORMAL, " | | * |%61s " _GREEN_("%012" PRIX64) "| |", "key", g_mifare_default_keys[i]); 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); traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3);
break; break;
}; };

View file

@ -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 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); 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 NTParityChk(TAuthData *ad, uint32_t ntx);
bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); 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); bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc);

View file

@ -15,6 +15,8 @@
#include "protocols.h" #include "protocols.h"
#include "parity.h" // oddparity #include "parity.h" // oddparity
#include "cmdhflist.h" // annotations #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 "comms.h" // for sending cmds to device. GetFromBigBuf
#include "fileutils.h" // for saveFile #include "fileutils.h" // for saveFile
#include "cmdlfhitag.h" // annotate hitag #include "cmdlfhitag.h" // annotate hitag
@ -131,7 +133,8 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac
return ret; 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 // sanity check
if (is_last_record(tracepos, traceLen)) { if (is_last_record(tracepos, traceLen)) {
PrintAndLogEx(DEBUG, "last record triggered. t-pos: %u t-len %u", 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 (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)); memset(explanation, 0x00, sizeof(explanation));
if (hdr->isResponse == false) { if (hdr->isResponse == false) {
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen); annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen);
@ -612,6 +615,7 @@ int CmdTraceList(const char *Cmd) {
"trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n" "trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n"
"trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " 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 cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n"
"trace list -t mf --dict <mfc_default_keys> -> use dictionary keys file\n"
"trace list -t 14a -f -> show frame delay times\n" "trace list -t 14a -f -> show frame delay times\n"
"trace list -t 14a -1 -> use trace buffer " "trace list -t 14a -1 -> use trace buffer "
); );
@ -626,6 +630,7 @@ int CmdTraceList(const char *Cmd) {
arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n" arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n"
" or to import into Wireshark using encapsulation type \"ISO 14443\""), " or to import into Wireshark using encapsulation type \"ISO 14443\""),
arg_strx0("t", "type", NULL, "protocol to annotate the trace"), arg_strx0("t", "type", NULL, "protocol to annotate the trace"),
arg_strx0(NULL, "dict", "<file>", "use dictionary keys file"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -642,6 +647,13 @@ int CmdTraceList(const char *Cmd) {
CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)type, sizeof(type), &tlen); CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)type, sizeof(type), &tlen);
str_lower(type); str_lower(type);
int diclen = 0;
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); CLIParserFree(ctx);
clearCommandBuffer(); clearCommandBuffer();
@ -742,6 +754,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, ""); PrintAndLogEx(NORMAL, "");
if (use_relative) { if (use_relative) {
PrintAndLogEx(NORMAL, " Gap | Duration | Src | Data (! denotes parity error, ' denotes short bytes) | CRC | Annotation"); PrintAndLogEx(NORMAL, " Gap | Duration | Src | Data (! denotes parity error, ' denotes short bytes) | CRC | Annotation");
@ -761,11 +801,14 @@ int CmdTraceList(const char *Cmd) {
} }
while (tracepos < g_traceLen) { 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()) if (kbd_enter_pressed())
break; break;
} }
if (dictionaryLoad)
free((void *) dicKeys);
} }
if (show_hex) if (show_hex)