From c062c44230012d73f15b8f5df82c7deef7c9b21e Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 09:52:08 +0200 Subject: [PATCH 01/12] Refactor emulator accessor helpers for ISO15693. --- armsrc/iso15693.c | 17 +++++++++++------ armsrc/iso15693.h | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 7e4c5c4f3..d4ab6e14e 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2111,6 +2111,11 @@ void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset) { memcpy(emCARD + offset, data, count); } +void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset) { + uint8_t *emCARD = BigBuf_get_EM_addr(); + memcpy(output, emCARD + offset, count); +} + // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands // all demodulation performed in arm rather than host. - greg void SimTagIso15693(uint8_t *uid, uint8_t block_size) { @@ -2272,7 +2277,6 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { resp_readblock[i] = 0; } - uint8_t *emCARD = BigBuf_get_EM_addr(); resp_readblock[0] = 0; // Response flags for (int j = 0; j < block_count; j++) { // where to put the data of the current block @@ -2280,11 +2284,12 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { if (option) { resp_readblock[work_offset] = 0; // Security status } - for (int i = 0; i < block_size; i++) { - // Block data - if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) { - resp_readblock[work_offset + security_offset + i] = emCARD[block_size * (block_idx + j) + i]; - } else { + // Block data + if (block_size * (block_idx + j + 1) <= CARD_MEMORY_SIZE) { + EmlGetMemIso15693(block_size, resp_readblock + (work_offset + security_offset), + block_size * (block_idx + j)); + } else { + for (int i = 0; i < block_size; i++) { resp_readblock[work_offset + security_offset + i] = 0; } } diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 6bd3882bc..f9ba6e9da 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -48,6 +48,7 @@ void AcquireRawAdcSamplesIso15693(void); void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader void EmlClearIso15693(void); void EmlSetMemIso15693(uint8_t count, uint8_t *data, uint32_t offset); +void EmlGetMemIso15693(uint8_t count, uint8_t *output, uint32_t offset); void SimTagIso15693(uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI From 7cc47eebba30df6338ea3d58d3582f6ed37fad70 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Fri, 2 Sep 2022 10:36:34 +0200 Subject: [PATCH 02/12] Accept eml and json files for `hf 15 eload`. --- client/src/cmdhf15.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 0d25e38f9..fb80c57ab 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1043,7 +1043,7 @@ static int CmdHF15ELoad(const char *Cmd) { uint8_t *data = NULL; size_t bytes_read = 0; - int res = loadFile_safe(filename, ".bin", (void **)&data, &bytes_read); + int res = pm3_load_dump(filename, (void **)&data, &bytes_read, CARD_MEMORY_SIZE); if (res != PM3_SUCCESS) { return res; } From 2d7e1d30b94981adee0583ed80a276a92e33e5f4 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 10:12:25 +0200 Subject: [PATCH 03/12] Refactor ISO 15693 READ commands to handle addressed flag. --- armsrc/iso15693.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index d4ab6e14e..060ce0124 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2240,29 +2240,19 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { // READ_BLOCK and READ_MULTI_BLOCK if ((cmd[1] == ISO15693_READBLOCK) || (cmd[1] == ISO15693_READ_MULTI_BLOCK)) { bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH); + bool addressed = cmd[0] & ISO15_REQ_ADDRESS; bool option = cmd[0] & ISO15_REQ_OPTION; uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; - uint8_t block_idx = 0; + uint8_t address_offset = 0; + if (addressed) { + address_offset = 8; + } + + uint8_t block_idx = cmd[2 + address_offset]; uint8_t block_count = 1; - if (cmd[1] == ISO15693_READBLOCK) { - if (cmd_len == 13) { - // addressed mode - block_idx= cmd[10]; - } else if (cmd_len == 5) { - // non-addressed mode - block_idx = cmd[2]; - } - } else if (cmd[1] == ISO15693_READ_MULTI_BLOCK) { - if (cmd_len == 14) { - // addressed mode - block_idx= cmd[10]; - block_count= cmd[11] + 1; - } else if (cmd_len == 6) { - // non-addressed mode - block_idx = cmd[2]; - block_count = cmd[3] + 1; - } + if (cmd[1] == ISO15693_READ_MULTI_BLOCK) { + block_count = cmd[3 + address_offset] + 1; } // Build READ_(MULTI_)BLOCK response From f6096367b31af17aa4c5962728c7ed07882b8139 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 10:24:22 +0200 Subject: [PATCH 04/12] Add ISO15693 write commands to simulation. --- armsrc/iso15693.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 060ce0124..d2035d70b 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2294,6 +2294,47 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow); LogTrace_ISO15693(resp_readblock, response_length, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false); } + + // WRITE_BLOCK and WRITE_MULTI_BLOCK + if ((cmd[1] == ISO15693_WRITEBLOCK) || (cmd[1] == ISO15693_WRITE_MULTI_BLOCK)) { + bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH); + bool addressed = cmd[0] & ISO15_REQ_ADDRESS; + uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; + + uint8_t address_offset = 0; + if (addressed) { + address_offset = 8; + } + + uint8_t block_idx = cmd[2 + address_offset]; + uint8_t block_count = 1; + uint8_t multi_offset = 0; + if (cmd[1] == ISO15693_WRITE_MULTI_BLOCK) { + block_count = cmd[3 + address_offset] + 1; + multi_offset = 1; + } + uint8_t *data = cmd + 3 + address_offset + multi_offset; + + // write data + EmlSetMemIso15693(block_count * block_size, data, block_idx * block_size); + + // Build WRITE_(MULTI_)BLOCK response + int response_length = 3; + uint8_t resp_writeblock[response_length]; + for (int i = 0; i < response_length; i++) { + resp_writeblock[i] = 0; + } + resp_writeblock[0] = 0; // Response flags + + // CRC + AddCrc15(resp_writeblock, response_length - 2); + CodeIso15693AsTag(resp_writeblock, response_length); + + tosend_t *ts = get_tosend(); + + TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow); + LogTrace_ISO15693(resp_writeblock, response_length, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false); + } } switch_off(); From de99fee83c2ab18b26aa7de08097649ab8ec77d7 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Fri, 2 Sep 2022 11:17:28 +0200 Subject: [PATCH 05/12] Add commands `hf 15 eview` and `hf 15 esave`. --- client/src/cmdhf15.c | 131 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index fb80c57ab..708b1e73c 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1098,6 +1098,133 @@ static int CmdHF15ELoad(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF15ESave(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 esave", + "Save emulator memory into three files (BIN/EML/JSON) ", + "hf 15 esave -f hf-15-01020304" + "hf 15 esave -b 8 -c 42 -f hf-15-01020304" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + arg_int0("b", "blocksize", "", "block size, defaults to 4"), + arg_int0("c", "count", "", "number of blocks to export, defaults to all"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; + char filename[FILE_PATH_SIZE]; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + int blocksize = arg_get_int_def(ctx, 2, 4); + int count = arg_get_int_def(ctx, 3, -1); + CLIParserFree(ctx); + + int bytes = CARD_MEMORY_SIZE; + if (count > 0 && count * blocksize <= bytes) { + bytes = count * blocksize; + } + + // reserve memory + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + PrintAndLogEx(INFO, "Downloading %u bytes from emulator memory", bytes); + if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(dump); + return PM3_ETIMEOUT; + } + + saveFile(filename, ".bin", dump, bytes); + saveFileEML(filename, dump, bytes, blocksize); + saveFileJSON(filename, jsf15, dump, bytes, NULL); + free(dump); + return PM3_SUCCESS; +} + +static void print_hrule(int blocksize) { + PrintAndLogEx(INFO, "-----+" NOLF); + for (int i = 0; i < blocksize; i++) { + PrintAndLogEx(NORMAL, "---" NOLF); + } + PrintAndLogEx(NORMAL, "-+-" NOLF); + for (int i = 0; i < blocksize; i++) { + PrintAndLogEx(NORMAL, "-" NOLF); + } + PrintAndLogEx(NORMAL, ""); +} + +static void print_blocks_15693(uint8_t *data, uint16_t bytes, int blocksize) { + int blocks = bytes / blocksize; + PrintAndLogEx(NORMAL, ""); + print_hrule(blocksize); + PrintAndLogEx(INFO, " blk | data " NOLF); + for (int i = 2; i < blocksize; i++) { + PrintAndLogEx(NORMAL, " " NOLF); + } + PrintAndLogEx(NORMAL, "| ascii"); + print_hrule(blocksize); + for (uint16_t i = 0; i < blocks; i++) { + PrintAndLogEx(INFO, "%4d | %s ", i, sprint_hex_ascii(data + (i * blocksize), blocksize)); + + } + if (bytes % blocksize != 0) { + // If there is something left over print it too + // This will have a broken layout, but should not happen anyway + PrintAndLogEx(INFO, "%4d | %s ", blocks, sprint_hex_ascii(data + (blocks * blocksize), + bytes % blocksize)); + } + print_hrule(blocksize); + PrintAndLogEx(NORMAL, ""); +} + +static int CmdHF15EView(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 eview", + "It displays emulator memory", + "hf 15 eview\n" + "hf 15 eview -b 8 -c 60\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("b", "blocksize", "", "block size, defaults to 4"), + arg_int0("c", "count", "", "number of blocks to display, defaults to all"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + int blocksize = arg_get_int_def(ctx, 1, 4); + int count = arg_get_int_def(ctx, 2, -1); + CLIParserFree(ctx); + + int bytes = CARD_MEMORY_SIZE; + if (count > 0 && count * blocksize <= bytes) { + bytes = count * blocksize; + } + + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + PrintAndLogEx(INFO, "Downloading %u bytes from emulator memory", bytes); + if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(dump); + return PM3_ETIMEOUT; + } + + print_blocks_15693(dump, bytes, blocksize); + free(dump); + return PM3_SUCCESS; +} + // Simulation is still not working very good // helptext static int CmdHF15Sim(const char *Cmd) { @@ -2289,7 +2416,9 @@ static command_t CommandTable[] = { {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO-15693 reader"}, {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO-15693 tag"}, {"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire samples as reader (enables carrier, sends inquiry)"}, - {"eload", CmdHF15ELoad, IfPm3Iso15693, "Load image file to be used by 'sim' command"}, + {"eload", CmdHF15ELoad, IfPm3Iso15693, "Load image file into emulator to be used by 'sim' command"}, + {"esave", CmdHF15ESave, IfPm3Iso15693, "Save emulator memory into image file"}, + {"eview", CmdHF15EView, IfPm3Iso15693, "View emulator memory"}, {"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO-15693 tag"}, {"slixdisable", CmdHF15SlixDisable, IfPm3Iso15693, "Disable privacy mode on SLIX ISO-15693 tag"}, {"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"}, From 42d0c6d8c135c56d688f745efe266e1dc7bb4980 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 10:27:54 +0200 Subject: [PATCH 06/12] Use memset to zero memory for better code style. --- armsrc/iso15693.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index d2035d70b..388aaddce 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2263,9 +2263,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { security_offset = 1; } uint8_t resp_readblock[response_length]; - for (int i = 0; i < response_length; i++) { - resp_readblock[i] = 0; - } + memset(resp_readblock, 0, response_length); resp_readblock[0] = 0; // Response flags for (int j = 0; j < block_count; j++) { @@ -2279,9 +2277,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { EmlGetMemIso15693(block_size, resp_readblock + (work_offset + security_offset), block_size * (block_idx + j)); } else { - for (int i = 0; i < block_size; i++) { - resp_readblock[work_offset + security_offset + i] = 0; - } + memset(resp_readblock + work_offset + security_offset, 0, block_size); } } @@ -2321,9 +2317,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) { // Build WRITE_(MULTI_)BLOCK response int response_length = 3; uint8_t resp_writeblock[response_length]; - for (int i = 0; i < response_length; i++) { - resp_writeblock[i] = 0; - } + memset(resp_writeblock, 0, response_length); resp_writeblock[0] = 0; // Response flags // CRC From 8ac9ba9a3dd78031e4b9cf9f3a485baa7d3d412c Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 10:44:06 +0200 Subject: [PATCH 07/12] Updated changelog. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c99a941f5..025c4adc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `script run hf_mf_hid_sim.lua` (@micsen) - Added `hf 15 sim --blocksize` - configure block size for simulation (@markus-oehme-pg40) - Added `hf 15 eload` - specify memory image for ISO15693 simulation (@markus-oehme-pg40) + - Added write command support to `hf 15 sim` (@markus-oehme-pg40) + - Added `hf 15 eview` and `hf 15 esave` - Retrieve emulator image for ISO15693 simulation (@markus-oehme-pg40) ## [Frostbit.4.14831][2022-01-11] From 84b58129dd391eadea871cc62937211ab5cbedc7 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 10:46:06 +0200 Subject: [PATCH 08/12] Fix API breakage. --- armsrc/Standalone/hf_tmudford.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Standalone/hf_tmudford.c b/armsrc/Standalone/hf_tmudford.c index 158250a0c..394d37e2d 100644 --- a/armsrc/Standalone/hf_tmudford.c +++ b/armsrc/Standalone/hf_tmudford.c @@ -75,7 +75,7 @@ void RunMod(void) { } else if (state == STATE_EMUL) { Iso15693InitTag(); Dbprintf("Starting simulation, press pm3-button to stop and go back to search state."); - SimTagIso15693(card.uid); + SimTagIso15693(card.uid, 4); state = STATE_READ; } From f511333b4d0b768a7ef1fb2b09a48551f6047a79 Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Mon, 5 Sep 2022 11:13:18 +0200 Subject: [PATCH 09/12] Fix linter complaint. --- client/src/cmdhf15.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 57c065b94..58a1e9005 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1169,7 +1169,7 @@ static void print_blocks_15693(uint8_t *data, uint16_t bytes, int blocksize) { } PrintAndLogEx(NORMAL, "| ascii"); print_hrule(blocksize); - for (uint16_t i = 0; i < blocks; i++) { + for (int i = 0; i < blocks; i++) { PrintAndLogEx(INFO, "%4d | %s ", i, sprint_hex_ascii(data + (i * blocksize), blocksize)); } From b49201ea6e4aefe85a68bd93356f3a8df823e3eb Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Tue, 6 Sep 2022 10:00:43 +0200 Subject: [PATCH 10/12] Use pm3_save_dump() for storing to disk. --- client/src/cmdhf15.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 58a1e9005..c4a335104 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1140,9 +1140,7 @@ static int CmdHF15ESave(const char *Cmd) { return PM3_ETIMEOUT; } - saveFile(filename, ".bin", dump, bytes); - saveFileEML(filename, dump, bytes, blocksize); - saveFileJSON(filename, jsf15, dump, bytes, NULL); + pm3_save_dump(filename, dump, bytes, jsf15, blocksize); free(dump); return PM3_SUCCESS; } From 751260b9d701a0ca79a89a0b6a457321bb9af91f Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Tue, 6 Sep 2022 10:28:36 +0200 Subject: [PATCH 11/12] Adjust changelog to convention. --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad14fefdc..2023e24bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ 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 `hf 15 eview` and `hf 15 esave` - Retrieve emulator image for ISO15693 simulation (@markus-oehme-pg40) + - Changed `hf 15 sim` - now supports reader writes (@markus-oehme-pg40) + - Added `hf 15 eload` - specify memory image for ISO15693 simulation (@markus-oehme-pg40) + - Added `hf 15 sim --blocksize` - configure block size for simulation (@markus-oehme-pg40) - Fixed buffer overflow in mfu ndef decode (@mwalker) - Changed spiffs write/append to send in 8192 chunks to ensure its eraised (@mwalker) - Fixed spiffs dump to ensure to fails correctly if no big_buff was allocated (@mwalker) @@ -90,10 +94,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added new standalone mode `lf_em4100rsww` (@zabszk) - Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz) - Added `script run hf_mf_hid_sim.lua` (@micsen) - - Added `hf 15 sim --blocksize` - configure block size for simulation (@markus-oehme-pg40) - - Added `hf 15 eload` - specify memory image for ISO15693 simulation (@markus-oehme-pg40) - - Added write command support to `hf 15 sim` (@markus-oehme-pg40) - - Added `hf 15 eview` and `hf 15 esave` - Retrieve emulator image for ISO15693 simulation (@markus-oehme-pg40) ## [Frostbit.4.14831][2022-01-11] From 69100e0e04c16732afcbcce0d494b2b5668d6d8b Mon Sep 17 00:00:00 2001 From: Markus Walter Date: Tue, 6 Sep 2022 10:59:43 +0200 Subject: [PATCH 12/12] Use printf options to output variable width segments. --- client/src/cmdhf15.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index c4a335104..285769f68 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1146,26 +1146,16 @@ static int CmdHF15ESave(const char *Cmd) { } static void print_hrule(int blocksize) { - PrintAndLogEx(INFO, "-----+" NOLF); - for (int i = 0; i < blocksize; i++) { - PrintAndLogEx(NORMAL, "---" NOLF); - } - PrintAndLogEx(NORMAL, "-+-" NOLF); - for (int i = 0; i < blocksize; i++) { - PrintAndLogEx(NORMAL, "-" NOLF); - } - PrintAndLogEx(NORMAL, ""); + char dashes[] = "------------------------------------------------------------"; + PrintAndLogEx(INFO, "-----+%.*s-+-%.*s-", 3*blocksize, dashes, blocksize, dashes); } static void print_blocks_15693(uint8_t *data, uint16_t bytes, int blocksize) { int blocks = bytes / blocksize; PrintAndLogEx(NORMAL, ""); print_hrule(blocksize); - PrintAndLogEx(INFO, " blk | data " NOLF); - for (int i = 2; i < blocksize; i++) { - PrintAndLogEx(NORMAL, " " NOLF); - } - PrintAndLogEx(NORMAL, "| ascii"); + char spaces[] = " "; + PrintAndLogEx(INFO, " blk | data %.*s| ascii", MAX(0, 3*blocksize - 5), spaces); print_hrule(blocksize); for (int i = 0; i < blocks; i++) { PrintAndLogEx(INFO, "%4d | %s ", i, sprint_hex_ascii(data + (i * blocksize), blocksize));