diff --git a/CHANGELOG.md b/CHANGELOG.md index e353b49b9..845278bca 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] + - Changed `hf mfu dump/view/eview` - now supports `-z` flag for dense output (@iceman1001) - Added `data crypto` to encrypt and decrypt data in the proxmark client using built-in methods (@team-orangeBlue) - Changed `hf tune` and `lf tune` - Added an option to show statistical data after tuning (@wh201906) - Changed `lf idteck demod --raw` - now supports raw hex string to decode (@iceman1001) @@ -10,7 +11,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Changed `lf em 4x05 info` - use `-v` verbose flag to see protection bits (@iceman1001) - Changed `lf em 4x05 info` - output now shows detailed bits (@iceman1001) - Added `lf em 4x05 view` - now supports viewing of dump files (@iceman1001) - - Changed `hf 15 eview/view` - now supports the `-z` flag for dense output (@iceman1001) + - Changed `hf 15 eview/view` - now supports `-z` flag for dense output (@iceman1001) - Changed `hf mf cload` - now supports specifying tag size (@augustozanellato) - Added `hf 14b raw --pico` - now supports picopass anticollision over ISO14443-B (@iceman1001) - Changed `hf 14b *` - worked apdu and comms. Improved output. Uses NG packets (@iceman1001) diff --git a/client/src/cmdhfjooki.c b/client/src/cmdhfjooki.c index 261a6194a..2abbfbb87 100644 --- a/client/src/cmdhfjooki.c +++ b/client/src/cmdhfjooki.c @@ -521,7 +521,7 @@ static int CmdHF14AJookiSim(const char *Cmd) { mfu_dump->counter_tearing[2][3] = 0xBD; mfu_dump->pages = 0x2c; - printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0); + printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0, false); // upload to emulator memory PrintAndLogEx(INFO, "Uploading to emulator memory"); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 13e5dfaf6..5aa878994 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4514,7 +4514,7 @@ int CmdHF14AMfELoad(const char *Cmd) { if (verbose) { mfu_dump_t *mfu_dump = (mfu_dump_t *)data; - printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0); + printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0, false); } // update expected blocks to match converted data. diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index cd78d1d4d..3fc74c898 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -2328,7 +2328,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { return PM3_SUCCESS; } -void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) { +void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage, bool dense_output) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, _CYAN_("MFU dump file information")); @@ -2377,6 +2377,8 @@ void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) { PrintAndLogEx(INFO, "DYNAMIC LOCK: %s", sprint_hex(lockbytes_dyn, 3)); } + bool in_repeated_block = false; + for (uint16_t i = 0; i < pages; ++i) { if (i < 3) { PrintAndLogEx(INFO, "%3d/0x%02X | " _RED_("%s")"| | %s", @@ -2478,7 +2480,40 @@ void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) { default: break; } - PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s", i + startpage, i + startpage, sprint_hex(data + i * 4, 4), (lckbit) ? _RED_("1") : "0", sprint_ascii(data + i * 4, 4)); + + + // 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 dense_output is enabled + uint8_t *blk = data + (i * MFU_BLOCK_SIZE); + if (dense_output && + (i > 3) && + (i < (pages - 1)) && + (in_repeated_block == false) && + (memcmp(blk, blk - MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) == 0) && + (memcmp(blk, blk + MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) == 0) && + (memcmp(blk, blk + (MFU_BLOCK_SIZE * 2), MFU_BLOCK_SIZE) == 0) + ) { + // 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 + in_repeated_block = true; + PrintAndLogEx(INFO, " ......"); + } else if (in_repeated_block && + (memcmp(blk, blk + MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) || i == pages) + ) { + // in a repeating block, but the next block doesn't match anymore, or we're at the end block + in_repeated_block = false; + } + + + if (in_repeated_block == false) { + PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s" + , i + startpage + , i + startpage + , sprint_hex(data + i * 4, 4) + , (lckbit) ? _RED_("1") : "0" + , sprint_ascii(data + i * 4, 4) + ); + } } PrintAndLogEx(INFO, "---------------------------------"); } @@ -2510,6 +2545,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { arg_int0("p", "page", "", "Manually set start page number to start from"), arg_int0("q", "qty", "", "Manually set number of pages to dump"), arg_lit0(NULL, "ns", "no save to file"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2526,6 +2562,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { int start_page = arg_get_int_def(ctx, 4, 0); int pages = arg_get_int_def(ctx, 5, 16); bool nosave = arg_get_lit(ctx, 6); + bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 7)); CLIParserFree(ctx); bool has_auth_key = false; @@ -2719,7 +2756,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { memcpy(dump_file_data.counter_tearing, get_counter_tearing, sizeof(dump_file_data.counter_tearing)); memcpy(dump_file_data.data, data, pages * 4); - printMFUdumpEx(&dump_file_data, pages, start_page); + printMFUdumpEx(&dump_file_data, pages, start_page, dense_output); if (nosave) { PrintAndLogEx(INFO, "Called with no save option"); @@ -2914,6 +2951,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { arg_lit0("e", NULL, "enable special write version/signature -MAGIC NTAG 21* ONLY-"), arg_lit0("r", NULL, "use password found in dumpfile to configure tag. Requires " _YELLOW_("'-e'") " parameter to work"), arg_lit0("v", "verbose", "verbose output"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2932,9 +2970,9 @@ static int CmdHF14AMfURestore(const char *Cmd) { bool write_extra = arg_get_lit(ctx, 5); bool read_key = arg_get_lit(ctx, 6); bool verbose = arg_get_lit(ctx, 7); + bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 8)); CLIParserFree(ctx); - bool has_key = false; if (ak_len > 0) { if (ak_len != 4 && ak_len != 16) { @@ -2989,7 +3027,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", filename); // print dump - printMFUdumpEx(mem, pages, 0); + printMFUdumpEx(mem, pages, 0, dense_output); // Swap endianness if (swap_endian && has_key) { @@ -4591,11 +4629,13 @@ static int CmdHF14AMfuEView(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_int0("e", "end", "", "index of last block"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); int end = arg_get_int_def(ctx, 1, -1); + bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 2)); CLIParserFree(ctx); bool override_end = (end != -1) ; @@ -4617,7 +4657,7 @@ static int CmdHF14AMfuEView(const char *Cmd) { end = dump->pages ; } - printMFUdumpEx(dump, end, 0); + printMFUdumpEx(dump, end, 0, dense_output); free(dump); return PM3_SUCCESS; } @@ -4698,6 +4738,7 @@ static int CmdHF14AMfuView(const char *Cmd) { arg_param_begin, arg_str1("f", "file", "", "Specify a filename for dump file"), arg_lit0("v", "verbose", "Verbose output"), + arg_lit0("z", "dense", "dense dump output style"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -4705,6 +4746,7 @@ static int CmdHF14AMfuView(const char *Cmd) { char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); bool verbose = arg_get_lit(ctx, 2); + bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 3)); CLIParserFree(ctx); // read dump file @@ -4735,7 +4777,7 @@ static int CmdHF14AMfuView(const char *Cmd) { PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt); } - printMFUdumpEx((mfu_dump_t *)dump, block_cnt, 0); + printMFUdumpEx((mfu_dump_t *)dump, block_cnt, 0, dense_output); free(dump); return PM3_SUCCESS; } diff --git a/client/src/cmdhfmfu.h b/client/src/cmdhfmfu.h index 7b1acf27a..463659b97 100644 --- a/client/src/cmdhfmfu.h +++ b/client/src/cmdhfmfu.h @@ -44,7 +44,7 @@ typedef struct { uint32_t GetHF14AMfU_Type(void); int ul_print_type(uint64_t tagtype, uint8_t spaces); -void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage); +void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage, bool dense_output); int ul_read_uid(uint8_t *uid); int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (*authdata)[16]);