better string handling in the client in felica, hitagU, hitagS

This commit is contained in:
iceman1001
2026-09-12 12:28:28 +02:00
parent 58580c690f
commit 47507a1d21
4 changed files with 55 additions and 48 deletions
+2
View File
@@ -3,6 +3,8 @@ 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 `trace list` - the Hitag U and Hitag S annotators now build their text with the `strlen()` offset (@iceman1001)
- Fixed `hf felica` - the service code footer wrote its closing bar past the end of a 128 byte buffer (@iceman1001)
- Fixed `trace list` - a Hitag U LOGIN or WRITE SINGLE BLOCK frame could write up to 17 bytes past the end of the 60 byte annotation buffer (@iceman1001)
- Fixed `hf mf autopwn` - it now re-authenticates and retries the block with the other key (@iceman1001)
- Fixed `hf mf hardnested` - the device declared `num_nonces * 4` bytes but packs 9 bytes per nonce pair. Thanks @TheArchitect0880 (@iceman1001)
+5 -6
View File
@@ -5313,13 +5313,12 @@ static void felica_scsvcode_print_footer(const felica_scsvcode_context_t *scsv_c
return;
}
char bar[128];
size_t pos = 0;
pos += snprintf(bar + pos, sizeof(bar) - pos, "");
for (int i = 0; i < scsv_ctx->depth - 1 && pos < sizeof(bar); i++) {
pos += snprintf(bar + pos, sizeof(bar) - pos, "───┴");
char bar[128] = {0};
str_append(bar, sizeof(bar), "");
for (int i = 0; i < scsv_ctx->depth - 1; i++) {
str_append(bar, sizeof(bar), "───┴");
}
snprintf(bar + pos, sizeof(bar) - pos, "───────────────────────");
str_append(bar, sizeof(bar), "───────────────────────");
PrintAndLogEx(INFO, "%s", bar);
}
+26 -21
View File
@@ -18,6 +18,7 @@
#include "cmdlfhitaghts.h"
#include <ctype.h>
#include <string.h> // strlen
#include "cmdparser.h" // command_t
#include "comms.h"
#include "cmdtrace.h"
@@ -37,15 +38,19 @@
static int CmdHelp(const char *Cmd);
void annotateHitagS(char *exp, size_t size, const uint8_t *cmd, uint8_t nbits, bool is_response) {
size_t exp_len = 0;
uint8_t command = 0;
// the caller reuses this buffer across frames, and the appends below are
// strlen() based now, so clear it here instead of relying on the first
// write landing at offset 0
exp[0] = '\0';
if (is_response) {
// Handle responses
if (nbits == 32) {
exp_len = snprintf(exp, size, "UID: [%02X%02X%02X%02X]", cmd[0], cmd[1], cmd[2], cmd[3]);
snprintf(exp, size, "UID: [%02X%02X%02X%02X]", cmd[0], cmd[1], cmd[2], cmd[3]);
} else if (nbits == 40) {
exp_len = snprintf(exp, size, "Data");
snprintf(exp, size, "Data");
}
} else if (nbits >= 5) {
concatbits(&command, 0, cmd, 0, 5, false);
@@ -55,62 +60,62 @@ void annotateHitagS(char *exp, size_t size, const uint8_t *cmd, uint8_t nbits, b
switch (command) {
case HITAGS_UID_REQ_STD:
exp_len += snprintf(exp + exp_len, size - exp_len, "UID Request (Standard 00110)");
snprintf(exp + strlen(exp), size - strlen(exp), "UID Request (Standard 00110)");
break;
case HITAGS_UID_REQ_ADV1:
exp_len += snprintf(exp + exp_len, size - exp_len, "UID Request (Advanced 11000)");
snprintf(exp + strlen(exp), size - strlen(exp), "UID Request (Advanced 11000)");
break;
case HITAGS_UID_REQ_ADV2:
exp_len += snprintf(exp + exp_len, size - exp_len, "UID Request (Advanced 11001)");
snprintf(exp + strlen(exp), size - strlen(exp), "UID Request (Advanced 11001)");
break;
case HITAGS_UID_REQ_FADV:
exp_len += snprintf(exp + exp_len, size - exp_len, "UID Request (Fast Advanced 11010)");
snprintf(exp + strlen(exp), size - strlen(exp), "UID Request (Fast Advanced 11010)");
break;
}
} else if (nbits == 4 + 8 + 8) {
concatbits(&command, 0, cmd, 0, 4, false);
if (command == HITAGS_READ_PAGE) {
exp_len += snprintf(exp + exp_len, size - exp_len, "READ");
snprintf(exp + strlen(exp), size - strlen(exp), "READ");
} else if (command == HITAGS_WRITE_PAGE) {
exp_len += snprintf(exp + exp_len, size - exp_len, "WRITE");
snprintf(exp + strlen(exp), size - strlen(exp), "WRITE");
} else if (command == HITAGS_READ_BLOCK) {
exp_len += snprintf(exp + exp_len, size - exp_len, "READ_BLOCK");
snprintf(exp + strlen(exp), size - strlen(exp), "READ_BLOCK");
} else if (command == HITAGS_WRITE_BLOCK) {
exp_len += snprintf(exp + exp_len, size - exp_len, "WRITE_BLOCK");
snprintf(exp + strlen(exp), size - strlen(exp), "WRITE_BLOCK");
} else if (command == HITAGS_QUIET) {
exp_len += snprintf(exp + exp_len, size - exp_len, "QUIET");
snprintf(exp + strlen(exp), size - strlen(exp), "QUIET");
}
// Hitag 1 commands
else if (command == HITAG1_RDCPAGE) {
exp_len += snprintf(exp + exp_len, size - exp_len, "RDCPAGE");
snprintf(exp + strlen(exp), size - strlen(exp), "RDCPAGE");
} else if (command == HITAG1_RDCBLK) {
exp_len += snprintf(exp + exp_len, size - exp_len, "RDCBLK");
snprintf(exp + strlen(exp), size - strlen(exp), "RDCBLK");
} else if (command == HITAG1_WRCPAGE) {
exp_len += snprintf(exp + exp_len, size - exp_len, "WRCPAGE");
snprintf(exp + strlen(exp), size - strlen(exp), "WRCPAGE");
} else if (command == HITAG1_WRCBLK) {
exp_len += snprintf(exp + exp_len, size - exp_len, "WRCBLK");
snprintf(exp + strlen(exp), size - strlen(exp), "WRCBLK");
} else {
exp_len += snprintf(exp + exp_len, size - exp_len, "Unknown (%02X)", command);
snprintf(exp + strlen(exp), size - strlen(exp), "Unknown (%02X)", command);
}
uint8_t page = 0;
concatbits(&page, 0, cmd, 5, 8, false);
exp_len += snprintf(exp + exp_len, size - exp_len, " Page: %d", page);
snprintf(exp + strlen(exp), size - strlen(exp), " Page: %d", page);
} else if (nbits == 32 + 8) {
concatbits(&command, 0, cmd, 0, 5, false);
exp_len += snprintf(exp + exp_len, size - exp_len, "Data");
snprintf(exp + strlen(exp), size - strlen(exp), "Data");
} else if (nbits == 5 + 32 + 8 || nbits == 5 + 32 + 1 + 8) {
concatbits(&command, 0, cmd, 0, 5, false);
if (command == HITAGS_SELECT) {
uint8_t uid[4] = {0};
concatbits(uid, 0, cmd, 5, 32, false);
exp_len = snprintf(exp, size, "SELECT UID: %02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3]);
snprintf(exp, size, "SELECT UID: %02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3]);
}
}
} else {
exp_len = snprintf(exp, size, "Invalid command (too short)");
snprintf(exp, size, "Invalid command (too short)");
}
}
+22 -21
View File
@@ -16,6 +16,7 @@
// Low frequency Hitag µ support
//-----------------------------------------------------------------------------
#include "cmdlfhitagu.h"
#include <string.h> // strlen
#include "cliparser.h"
#include "cmddata.h" // setDemodBuff
@@ -53,41 +54,41 @@ void annotateHitagU(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize,
uint8_t command = ((reflect8(cmd[0]) >> 5) & 0x07) | ((reflect8(cmd[1]) & 0x07) << 3);
bool has_uid = false;
size_t exp_len = snprintf(exp, size, "Flg:");
snprintf(exp, size, "Flg:");
if ((flag & HITAGU_FLAG_PEXT) == HITAGU_FLAG_PEXT) {
exp_len += snprintf(exp + exp_len, size - exp_len, " PEXT");
snprintf(exp + strlen(exp), size - strlen(exp), " PEXT");
}
if ((flag & HITAGU_FLAG_INV) == HITAGU_FLAG_INV) {
exp_len += snprintf(exp + exp_len, size - exp_len, " INV");
snprintf(exp + strlen(exp), size - strlen(exp), " INV");
if ((flag & HITAGU_FLAG_RFU) == HITAGU_FLAG_RFU) {
exp_len += snprintf(exp + exp_len, size - exp_len, " RFU");
snprintf(exp + strlen(exp), size - strlen(exp), " RFU");
}
if ((flag & HITAGU_FLAG_NOS) == HITAGU_FLAG_NOS) {
exp_len += snprintf(exp + exp_len, size - exp_len, " NOS");
snprintf(exp + strlen(exp), size - strlen(exp), " NOS");
}
} else {
if ((flag & HITAGU_FLAG_SEL) == HITAGU_FLAG_SEL) {
exp_len += snprintf(exp + exp_len, size - exp_len, " SEL");
snprintf(exp + strlen(exp), size - strlen(exp), " SEL");
}
if ((flag & HITAGU_FLAG_ADR) == HITAGU_FLAG_ADR) {
exp_len += snprintf(exp + exp_len, size - exp_len, " ADR");
snprintf(exp + strlen(exp), size - strlen(exp), " ADR");
has_uid = true;
}
}
if ((flag & HITAGU_FLAG_CRCT) == HITAGU_FLAG_CRCT) {
exp_len += snprintf(exp + exp_len, size - exp_len, " CRCT");
snprintf(exp + strlen(exp), size - strlen(exp), " CRCT");
}
exp_len += snprintf(exp + exp_len, size - exp_len, "|Cmd: ");
snprintf(exp + strlen(exp), size - strlen(exp), "|Cmd: ");
switch (command) {
case HITAGU_CMD_LOGIN: {
@@ -96,29 +97,29 @@ void annotateHitagU(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize,
if (cmdsize == (6 + (has_uid * HITAGU_UID_SIZE)) || cmdsize == (8 + (has_uid * HITAGU_UID_SIZE))) {
exp_len += snprintf(exp + exp_len, size - exp_len, "8265 LOGIN");
snprintf(exp + strlen(exp), size - strlen(exp), "8265 LOGIN");
} else if (cmdsize == (7 + (has_uid * HITAGU_UID_SIZE)) || cmdsize == (9 + (has_uid * HITAGU_UID_SIZE))) {
uint8_t mfc = 0;
concatbits(&mfc, 0, cmd, 5 + 6 + 8 + 32, 8, false);
exp_len += snprintf(exp + exp_len, size - exp_len, "LOGIN mfc:%02x ", mfc);
snprintf(exp + strlen(exp), size - strlen(exp), "LOGIN mfc:%02x ", mfc);
has_mfc = true;
}
if (has_uid) {
uint8_t uid[HITAGU_UID_SIZE] = {0};
concatbits(uid, 0, cmd, 5 + 6 + has_mfc * 8 + 32, HITAGU_UID_SIZE * 8, false);
exp_len += snprintf(exp + exp_len, size - exp_len, " uid:%s", sprint_hex_inrow(uid, HITAGU_UID_SIZE));
snprintf(exp + strlen(exp), size - strlen(exp), " uid:%s", sprint_hex_inrow(uid, HITAGU_UID_SIZE));
}
uint8_t password[HITAG_PASSWORD_SIZE] = {0};
concatbits(password, 0, cmd, 5 + 6 + has_mfc * 8 + has_uid * HITAGU_UID_SIZE * 8, HITAG_PASSWORD_SIZE * 8, false);
exp_len += snprintf(exp + exp_len, size - exp_len, " pwd:%s", sprint_hex_inrow(password, HITAG_PASSWORD_SIZE));
snprintf(exp + strlen(exp), size - strlen(exp), " pwd:%s", sprint_hex_inrow(password, HITAG_PASSWORD_SIZE));
break;
}
case HITAGU_CMD_INVENTORY: {
exp_len += snprintf(exp + exp_len, size - exp_len, "INVENTORY");
snprintf(exp + strlen(exp), size - strlen(exp), "INVENTORY");
break;
}
case HITAGU_CMD_READ_MULTIPLE_BLOCK: {
@@ -128,7 +129,7 @@ void annotateHitagU(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize,
uint8_t block_count = 0;
concatbits(&block_count, 0, cmd, 5 + 6 + 8, 8, false);
exp_len += snprintf(exp + exp_len, size - exp_len, "READ MULTIPLE BLOCK start:%d num:%d"
snprintf(exp + strlen(exp), size - strlen(exp), "READ MULTIPLE BLOCK start:%d num:%d"
, reflect8(block_addr)
, reflect8(block_count)
);
@@ -141,30 +142,30 @@ void annotateHitagU(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize,
uint8_t block_data[4] = {0};
concatbits(block_data, 0, cmd, 5 + 6 + 8, 32, false);
exp_len += snprintf(exp + exp_len, size - exp_len, "WRITE SINGLE BLOCK start:%d data:[%s]"
snprintf(exp + strlen(exp), size - strlen(exp), "WRITE SINGLE BLOCK start:%d data:[%s]"
, reflect8(block_addr)
, sprint_hex_inrow(block_data, 4)
);
break;
}
case HITAGU_CMD_SELECT: {
exp_len += snprintf(exp + exp_len, size - exp_len, "SELECT");
snprintf(exp + strlen(exp), size - strlen(exp), "SELECT");
break;
}
case HITAGU_CMD_SYSINFO: {
exp_len += snprintf(exp + exp_len, size - exp_len, "GET SYSTEM INFORMATION");
snprintf(exp + strlen(exp), size - strlen(exp), "GET SYSTEM INFORMATION");
break;
}
case HITAGU_CMD_READ_UID: {
exp_len += snprintf(exp + exp_len, size - exp_len, "READ UID");
snprintf(exp + strlen(exp), size - strlen(exp), "READ UID");
break;
}
case HITAGU_CMD_STAY_QUIET: {
exp_len += snprintf(exp + exp_len, size - exp_len, "STAY QUIET");
snprintf(exp + strlen(exp), size - strlen(exp), "STAY QUIET");
break;
}
default: {
exp_len += snprintf(exp + exp_len, size - exp_len, "Unknown 0x%02X", command);
snprintf(exp + strlen(exp), size - strlen(exp), "Unknown 0x%02X", command);
break;
}
}