From 728e6d27c79847b1903dfaff73a403c17512bb05 Mon Sep 17 00:00:00 2001 From: nvx Date: Sat, 23 Jul 2022 12:37:07 +1000 Subject: [PATCH] add preference for dense output option and -z cmd flag --- client/src/cmdhficlass.c | 23 ++++++++---- client/src/cmdhficlass.h | 2 +- client/src/preferences.c | 75 +++++++++++++++++++++++++++++++++++++++- client/src/ui.h | 1 + 4 files changed, 92 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index f687807c4..f1bb638f4 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -38,6 +38,7 @@ #include "proxendian.h" #include "iclass_cmd.h" #include "crypto/asn1utils.h" // ASN1 decoder +#include "preferences.h" #define PICOPASS_BLOCK_SIZE 8 @@ -1100,6 +1101,7 @@ static int CmdHFiClassEView(const char *Cmd) { arg_param_begin, arg_int0("s", "size", "<256|2048>", "number of bytes to save (default 256)"), arg_lit0("v", "verbose", "verbose output"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1107,6 +1109,7 @@ static int CmdHFiClassEView(const char *Cmd) { uint16_t blocks = 32; uint16_t bytes = arg_get_int_def(ctx, 1, 256); bool verbose = arg_get_lit(ctx, 2); + bool dense_output = g_session.dense_output || arg_get_lit(ctx, 3); blocks = bytes / 8; CLIParserFree(ctx); @@ -1141,7 +1144,7 @@ static int CmdHFiClassEView(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - printIclassDumpContents(dump, 1, blocks, bytes); + printIclassDumpContents(dump, 1, blocks, bytes, dense_output); if (verbose) { printIclassSIO(dump); @@ -1174,6 +1177,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { arg_str0("k", "key", "", "3DES transport key"), arg_lit0("v", "verbose", "verbose output"), arg_lit0(NULL, "d6", "decode as block 6"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(clictx, Cmd, argtable, false); @@ -1197,6 +1201,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { bool verbose = arg_get_lit(clictx, 4); bool use_decode6 = arg_get_lit(clictx, 5); + bool dense_output = g_session.dense_output || arg_get_lit(clictx, 6); CLIParserFree(clictx); // sanity checks @@ -1334,7 +1339,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { pm3_save_dump(fptr, decrypted, decryptedlen, jsfIclass, PICOPASS_BLOCK_SIZE); - printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); + printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen, dense_output); if (verbose) { printIclassSIO(decrypted); @@ -1561,6 +1566,7 @@ static int CmdHFiClassDump(const char *Cmd) { arg_lit0(NULL, "elite", "elite computations applied to key"), arg_lit0(NULL, "raw", "raw, the key is interpreted as raw block 3/4"), arg_lit0(NULL, "nr", "replay of NR/MAC"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1644,6 +1650,7 @@ static int CmdHFiClassDump(const char *Cmd) { bool elite = arg_get_lit(ctx, 6); bool rawkey = arg_get_lit(ctx, 7); bool use_replay = arg_get_lit(ctx, 8); + bool dense_output = g_session.dense_output || arg_get_lit(ctx, 9); CLIParserFree(ctx); @@ -1876,7 +1883,7 @@ write_dump: PrintAndLogEx(INFO, "Reading AA2 failed. dumping AA1 data to file"); // print the dump - printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got); + printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got, dense_output); // use CSN as filename if (filename[0] == 0) { @@ -2494,7 +2501,7 @@ static void printIclassSIO(uint8_t *iclass_dump) { } } -void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) { +void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize, bool dense_output) { picopass_hdr_t *hdr = (picopass_hdr_t *)iclass_dump; // picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)iclass_dump; @@ -2649,8 +2656,8 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e if (regular_print_block) { // suppress repeating blocks, truncate as such that the first and last block with the same data is shown - // but the blocks in between are replaced with a single line of "*" - if (i > 6 && i < (endblock - 1) && !in_repeated_block && !memcmp(blk, blk - 8, 8) && + // but the blocks in between are replaced with a single line of "*" if dense_output is enabled + if (dense_output && i > 6 && i < (endblock - 1) && !in_repeated_block && !memcmp(blk, blk - 8, 8) && !memcmp(blk, blk + 8, 8) && !memcmp(blk, blk + 16, 8)) { // we're in a user block that isn't the first user block nor last two user blocks, // and the current block data is the same as the previous and next two block @@ -2699,6 +2706,7 @@ static int CmdHFiClassView(const char *Cmd) { arg_int0(NULL, "first", "", "Begin printing from this block (default block 6)"), arg_int0(NULL, "last", "", "End printing at this block (default 0, ALL)"), arg_lit0("v", "verbose", "verbose output"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2710,6 +2718,7 @@ static int CmdHFiClassView(const char *Cmd) { int startblock = arg_get_int_def(ctx, 2, 0); int endblock = arg_get_int_def(ctx, 3, 0); bool verbose = arg_get_lit(ctx, 4); + bool dense_output = g_session.dense_output || arg_get_lit(ctx, 5); CLIParserFree(ctx); @@ -2730,7 +2739,7 @@ static int CmdHFiClassView(const char *Cmd) { PrintAndLogEx(NORMAL, ""); print_picopass_header((picopass_hdr_t *) dump); print_picopass_info((picopass_hdr_t *) dump); - printIclassDumpContents(dump, startblock, endblock, bytes_read); + printIclassDumpContents(dump, startblock, endblock, bytes_read, dense_output); if (verbose) { printIclassSIO(dump); diff --git a/client/src/cmdhficlass.h b/client/src/cmdhficlass.h index f66a09a5e..a4d545a05 100644 --- a/client/src/cmdhficlass.h +++ b/client/src/cmdhficlass.h @@ -26,7 +26,7 @@ int CmdHFiClass(const char *Cmd); int info_iclass(void); int read_iclass_csn(bool loop, bool verbose); -void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); +void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize, bool dense_output); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite); void GenerateMacFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, uint32_t keycnt, iclass_premac_t *list); diff --git a/client/src/preferences.c b/client/src/preferences.c index 7195b2393..28ae4d44f 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -63,6 +63,7 @@ int preferences_load(void) { g_session.overlay.w = g_session.plot.w; g_session.overlay_sliders = true; g_session.show_hints = true; + g_session.dense_output = false; g_session.bar_mode = STYLE_VALUE; setDefaultPath(spDefault, ""); @@ -185,6 +186,8 @@ void preferences_save_callback(json_t *root) { JsonSaveBoolean(root, "show.hints", g_session.show_hints); + JsonSaveBoolean(root, "output.dense", g_session.dense_output); + JsonSaveBoolean(root, "os.supports.colors", g_session.supports_colors); JsonSaveStr(root, "file.default.savepath", g_session.defaultPaths[spDefault]); @@ -319,6 +322,9 @@ void preferences_load_callback(json_t *root) { if (json_unpack_ex(root, &up_error, 0, "{s:b}", "show.hints", &b1) == 0) g_session.show_hints = (bool)b1; + if (json_unpack_ex(root, &up_error, 0, "{s:b}", "output.dense", &b1) == 0) + g_session.dense_output = (bool)b1; + if (json_unpack_ex(root, &up_error, 0, "{s:b}", "os.supports.colors", &b1) == 0) g_session.supports_colors = (bool)b1; @@ -517,6 +523,11 @@ static void showBarModeState(prefShowOpt_t opt) { } } +static void showOutputState(prefShowOpt_t opt) { + PrintAndLogEx(INFO, " %s output................. %s", prefShowMsg(opt), + g_session.dense_output ? _GREEN_("dense") : _WHITE_("normal")); +} + static void showClientExeDelayState(void) { PrintAndLogEx(INFO, " Cmd execution delay.... "_GREEN_("%u"), g_session.client_exe_delay); } @@ -738,6 +749,49 @@ static int setCmdDeviceDebug (const char *Cmd) } */ +static int setCmdOutput(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "prefs set output", + "Set dump output style to condense consecutive repeated data", + "prefs set output --normal --> sets the output style to normal\n" + "prefs set output --dense --> sets the output style to dense" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "normal", "normal output"), + arg_lit0(NULL, "dense", "dense output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool use_off = arg_get_lit(ctx, 1); + bool use_on = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if ((use_off + use_on) > 1) { + PrintAndLogEx(FAILED, "Can only set one option"); + return PM3_EINVARG; + } + + bool new_value = g_session.dense_output; + if (use_off) { + new_value = false; + } + if (use_on) { + new_value = true; + } + + if (g_session.dense_output != new_value) { + showOutputState(prefShowOLD); + g_session.dense_output = new_value; + showOutputState(prefShowNEW); + preferences_save(); + } else { + showOutputState(prefShowNone); + } + + return PM3_SUCCESS; +} static int setCmdExeDelay(const char *Cmd) { CLIParserContext *ctx; @@ -1044,6 +1098,22 @@ static int getCmdDebug(const char *Cmd) { return PM3_SUCCESS; } +static int getCmdOutput(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "prefs get output", + "Get preference of dump output style", + "prefs get output" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + showOutputState(prefShowNone); + return PM3_SUCCESS; +} + static int getCmdPlotSlider(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "prefs get plotsliders", @@ -1119,6 +1189,7 @@ static command_t CommandTableGet[] = { // {"devicedebug", getCmdDeviceDebug, AlwaysAvailable, "Get device debug level"}, {"emoji", getCmdEmoji, AlwaysAvailable, "Get emoji display preference"}, {"hints", getCmdHint, AlwaysAvailable, "Get hint display preference"}, + {"output", getCmdOutput, AlwaysAvailable, "Get dump output style preference"}, {"plotsliders", getCmdPlotSlider, AlwaysAvailable, "Get plot slider display preference"}, {NULL, NULL, NULL, NULL} }; @@ -1133,7 +1204,8 @@ static command_t CommandTableSet[] = { {"hints", setCmdHint, AlwaysAvailable, "Set hint display"}, {"savepaths", setCmdSavePaths, AlwaysAvailable, "... to be adjusted next ... "}, // {"devicedebug", setCmdDeviceDebug, AlwaysAvailable, "Set device debug level"}, - {"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"}, + {"output", setCmdOutput, AlwaysAvailable, "Set dump output style"}, + {"plotsliders", setCmdPlotSliders, AlwaysAvailable, "Set plot slider display"}, {NULL, NULL, NULL, NULL} }; @@ -1189,6 +1261,7 @@ static int CmdPrefShow(const char *Cmd) { // showDeviceDebugState(prefShowNone); showBarModeState(prefShowNone); showClientExeDelayState(); + showOutputState(prefShowNone); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; diff --git a/client/src/ui.h b/client/src/ui.h index ec496fd80..6b1ac4a83 100644 --- a/client/src/ui.h +++ b/client/src/ui.h @@ -47,6 +47,7 @@ typedef struct { bool pm3_present; bool help_dump_mode; bool show_hints; + bool dense_output; bool window_changed; // track if plot/overlay pos/size changed to save on exit qtWindow_t plot; qtWindow_t overlay;