From 69f40df005c6ba50c522170a48b226be2f2c2398 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 19 Apr 2026 08:52:16 +0700 Subject: [PATCH] unified some minor hint text messages. added a ndef detection to hf mfu dump, hf mfu view, hf mfu eview in order to suggest that there is actually a ndefmessage --- client/src/cmdhf14b.c | 2 +- client/src/cmdhficlass.c | 10 +++--- client/src/cmdhfmf.c | 10 +++--- client/src/cmdhfmfp.c | 2 +- client/src/cmdhfmfu.c | 76 +++++++++++++++++++++++++++++++++++++--- client/src/cmdlfem4x50.c | 2 +- client/src/cmdtrace.c | 2 +- 7 files changed, 85 insertions(+), 19 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 46ef875f6..7f231e4ea 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -3320,7 +3320,7 @@ static int CmdHF14BSriTearoff(const char *Cmd) { } PrintAndLogEx(INFO, ""); - PrintAndLogEx(HINT, "Hint: use " _YELLOW_("`hf 14b rdbl -b %d`") " to verify the block", blockno); + PrintAndLogEx(HINT, "Hint: Use " _YELLOW_("`hf 14b rdbl -b %d`") " to verify the block", blockno); return PM3_SUCCESS; } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 7763a0f48..888a8e453 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -4210,8 +4210,8 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { if (blockno == 2) { if (memcmp(data_read, ff_data, 8) == 0 && memcmp(data_read_orig, ff_data, 8) != 0) { PrintAndLogEx(SUCCESS, "E-purse has been teared ( %s )", _GREEN_("ok")); - PrintAndLogEx(HINT, "Hint: try `hf iclass creditepurse -d FEFFFEFF --ki 1`"); - PrintAndLogEx(HINT, "Hint: try `hf iclass wrbl -d 'FFFFFFFF FFFF FEFF' --blk 2 --ki 1 --credit`"); + PrintAndLogEx(HINT, "Hint: Try `hf iclass creditepurse -d FEFFFEFF --ki 1`"); + PrintAndLogEx(HINT, "Hint: Try `hf iclass wrbl -d 'FFFFFFFF FFFF FEFF' --blk 2 --ki 1 --credit`"); isok = PM3_SUCCESS; goto_out = true; } @@ -6308,7 +6308,8 @@ static int CmdHFiClassLegBrute_MT(uint8_t epurse[8], uint8_t macs[8], uint8_t ma _Atomic uint64_t aborted_at = 0; pthread_mutex_t log_lock; pthread_mutex_init(&log_lock, NULL); - PrintAndLogEx(HINT, "Hint: Press " _YELLOW_("") " to abort"); + + PrintAndLogEx(INFO, "Press " _GREEN_("") " to abort"); // Divide the full 40-bit keyspace into equal non-overlapping slices, one per thread. // All threads use the same startingKey; only their index range differs. @@ -6379,8 +6380,7 @@ static int CmdHFiClassLegBrute_MT(uint8_t epurse[8], uint8_t macs[8], uint8_t ma if (aborted) { uint64_t resume_millions = aborted_at / 1000000; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(WARNING, "aborted via keyboard!"); + PrintAndLogEx(WARNING, "\naborted via keyboard!"); PrintAndLogEx(HINT, "Hint: resume with " _YELLOW_("--index %" PRIu64 " --threads %d"), resume_millions, thread_count); return PM3_EOPABORTED; } diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index f81c91a28..c26ef47c1 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -10370,33 +10370,33 @@ static int CmdHF14AMfInfo(const char *Cmd) { if ((card_type & MTDESFIRE) == MTDESFIRE) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "MIFARE DESFire detected"); - PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfdes info") "`"); + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfdes info") "`"); goto out; } if ((card_type & MTULTRALIGHT) == MTULTRALIGHT) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "MIFARE Ultralight / NTAG detected"); - PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`"); + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfu info") "`"); goto out; } if ((card_type & MTPLUS) == MTPLUS) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "MIFARE Plus detected"); - PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfp info") "`"); + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfp info") "`"); } if ((card_type & MTEMV) == MTEMV) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "EMV detected"); - PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv info") "`"); + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("emv info") "`"); } if ((card_type & MTFUDAN) == MTFUDAN) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "FUDAN FM11RF005 detected"); - PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`"); + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf fudan dump") "`"); goto out; } diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 861cfc813..18d326229 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -2386,7 +2386,7 @@ static int CmdHFMFPDump(const char *Cmd) { if (sectorsRead != numSectors) { PrintAndLogEx(HINT, "Partial dump: %d of %d sectors read", sectorsRead, numSectors); - PrintAndLogEx(HINT, "Hint: use " _YELLOW_("`hf mfp chk --dump`") " and/or " _YELLOW_("`hf mf chk`") " to find more keys"); + PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf mfp chk --dump`") " and/or " _YELLOW_("`hf mf chk`") " to find more keys"); } free(carddata); diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 596b3d40b..7824c7f97 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -859,6 +859,39 @@ static int ul_print_default(uint8_t *data, uint8_t *real_uid) { return PM3_SUCCESS; } +static bool ndef_detect_message(const uint8_t *d, uint16_t n) { + + if (n < 17) { + return false; + } + + // start at OTP block and detect a CC container instead + const uint8_t *p = d + (3 * MFU_BLOCK_SIZE); + + // no NDEF capability container + if (p[0] != 0xE1 && p[0] != 0xF1) { + return false; + } + + p += 4; + const uint8_t *end = d + n; + + // empty data area + if (p[0] == 0x00) { + return false; + } + + while (p < end) { + + // NDEF terminator TLV (0xFE 0x00) + if (p[0] == 0xFE && (p + 1) < end && p[1] == 0x00) { + return true; + } + p++; + } + return false; +} + static int ndef_get_maxsize(const uint8_t *data) { // no NDEF message if (data[0] != 0xE1) @@ -2567,7 +2600,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { status = ul_read(0x28, ulc_conf, sizeof(ulc_conf), false); if (status <= 0) { PrintAndLogEx(ERR, "Error: tag didn't answer to page 40 read command"); - PrintAndLogEx(HINT, "Hint: tag config may be set to read-protect those pages, try dumping"); + PrintAndLogEx(HINT, "Hint: Tag config may be set to read-protect those pages, try dumping"); DropField(); return PM3_ESOFT; } @@ -3400,6 +3433,7 @@ void mfu_print_dump(mfu_dump_t *card, uint16_t pages, uint8_t startpage, bool de // 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) ) { @@ -3411,14 +3445,29 @@ void mfu_print_dump(mfu_dump_t *card, uint16_t pages, uint8_t startpage, bool de if ((startpage == 0) && ((i < 16) || (pages == 44))) { lckbitchar = (lckbit) ? _RED_("1") : "0"; } + if (in_repeated_block == false) { - PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s" + + if (i == 3) { + // otp block + PrintAndLogEx(INFO, "%3d/0x%02X | " _CYAN_("%s")"| %s | %s" , i + startpage , i + startpage , sprint_hex(data + i * 4, 4) , lckbitchar , sprint_ascii(data + i * 4, 4) - ); + ); + + } else { + // normal block + PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s" + , i + startpage + , i + startpage + , sprint_hex(data + i * 4, 4) + , lckbitchar + , sprint_ascii(data + i * 4, 4) + ); + } } } PrintAndLogEx(INFO, "---------------------------------"); @@ -3746,6 +3795,10 @@ static int CmdHF14AMfUDump(const char *Cmd) { mfu_print_dump(&dump_file_data, pages, start_page, dense_output); + if (ndef_detect_message(dump_file_data.data, pages * MFU_BLOCK_SIZE)) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfu ndefread")"`"); + } + if (nosave) { PrintAndLogEx(INFO, "Called with no save option"); PrintAndLogEx(NORMAL, ""); @@ -3768,6 +3821,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { if (is_partial) { PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size); } + return PM3_SUCCESS; } @@ -6495,7 +6549,7 @@ static int CmdHF14AMfuEView(const char *Cmd) { bool override_end = (end != -1) ; if (override_end && (end < 0 || end > MFU_MAX_BLOCKS)) { - PrintAndLogEx(WARNING, "Invalid value for end: %d Must be be positive integer < %d", end, MFU_MAX_BLOCKS); + PrintAndLogEx(WARNING, "Invalid value for end: " _RED_("%d") ". Must be be positive integer < %d", end, MFU_MAX_BLOCKS); return PM3_EINVARG ; } @@ -6512,6 +6566,11 @@ static int CmdHF14AMfuEView(const char *Cmd) { } mfu_print_dump(dump, end, 0, dense_output); + + if (ndef_detect_message(dump->data, end * MFU_BLOCK_SIZE)) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfu ndefread")"`"); + } + free(dump); return PM3_SUCCESS; } @@ -6631,7 +6690,14 @@ static int CmdHF14AMfuView(const char *Cmd) { PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt); } - mfu_print_dump((mfu_dump_t *)dump, block_cnt, 0, dense_output); + mfu_dump_t *p = (mfu_dump_t *)dump; + mfu_print_dump(p, block_cnt, 0, dense_output); + + // we need to skip prefix + if (ndef_detect_message(p->data, block_cnt * MFU_BLOCK_SIZE)) { + PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf mfu ndefread")"`"); + } + free(dump); return PM3_SUCCESS; } diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index a8b199700..81e456328 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -215,7 +215,7 @@ static int CmdEM4x50ELoad(const char *Cmd) { // upload to emulator memory em4x50_seteml(data, 0, EM4X50_DUMP_FILESIZE); - PrintAndLogEx(HINT, "Hint: You are ready to simulate. See `" _YELLOW_("lf em 4x50 sim -h") "`"); + PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("lf em 4x50 sim -h") "` to simulate"); PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 6405d7ad4..6653f46f4 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -1605,7 +1605,7 @@ int CmdTraceList(const char *Cmd) { } if (show_hex) { - PrintAndLogEx(HINT, "Hint: Syntax to use: `" _YELLOW_("text2pcap -t \"%%S.\" -l 264 -n ") "`"); + PrintAndLogEx(HINT, "Hint: Syntax is: `" _YELLOW_("text2pcap -t \"%%S.\" -l 264 -n ") "`"); } return PM3_SUCCESS;