Merge pull request #3404 from dangerous-tac0s/hf-mfu-esetblk

Hf mfu esetblk
This commit is contained in:
Iceman authored and GitHub committed 2026-07-03 13:04:05 +07:00
commit ccfd25cd9b
2 files changed
+94 -14

No files matched your search

+27 -14
View File
@@ -1644,18 +1644,21 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
AddCrc14A(rPPS, sizeof(rPPS) - 2);
// EV1/NTAG, set PWD w AMIIBO algo if all zero.
// EV1/NTAG Amiibo: if no PWD is set, populate emulator memory with the UID-derived
// password and its PACK (0x8080) at the PWD/PACK pages, so the sim serves them from
// emulator memory like any other value. Auth and PACK are then read straight from
// memory, keeping eset/eview authoritative (what you set is what the sim serves).
if (tagType == 7) {
uint8_t pwd[4] = {0, 0, 0, 0};
uint8_t gen_pwd[4] = {0, 0, 0, 0};
emlGet(pwd, (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(pwd));
emlGet(rPACK, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(rPACK));
Uint4byteToMemBe(gen_pwd, ul_ev1_pwdgenB(data));
if (memcmp(pwd, gen_pwd, sizeof(pwd)) == 0) {
rPACK[0] = 0x80;
rPACK[1] = 0x80;
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
uint8_t amiibo_pwd[4] = {0, 0, 0, 0};
Uint4byteToMemLe(amiibo_pwd, ul_ev1_pwdgenB(data));
emlSet(amiibo_pwd, (*pages - 1) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(amiibo_pwd));
uint8_t amiibo_pack[4] = {0x80, 0x80, 0x00, 0x00};
emlSet(amiibo_pack, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(amiibo_pack));
}
emlGet(rPACK, (*pages) * 4 + MFU_DUMP_PREFIX_LENGTH, sizeof(rPACK));
}
AddCrc14A(rPACK, sizeof(rPACK) - 2);
@@ -2347,14 +2350,24 @@ void SimulateIso14443aTagEx(uint8_t tagType, uint16_t flags, uint8_t *useruid, u
Dbhexdump(4, pwd, 0);
}
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(useruid));
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]);
}
// PWD comes straight from emulator memory (read above). For an unset (all-zero)
// PWD, the Amiibo password is populated into memory at sim init, so there's no
// substitution here -- eset/eview stay authoritative.
if (memcmp(receivedCmd + 1, pwd, 4) == 0) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password match, responding with PACK.");
p_response = &responses[RESP_INDEX_PACK];
// Serve PACK straight from the PACK page (page `pages`) in emulator memory, so
// eset/eload of the PACK page is honored live. The Amiibo PACK (0x8080) for an
// unset PWD is populated into memory at sim init, so nothing special-cases here.
uint8_t pack_live[4] = {0, 0, 0, 0};
emlGet(pack_live, pages * 4 + MFU_DUMP_PREFIX_LENGTH, 2);
dynamic_response_info.response[0] = pack_live[0];
dynamic_response_info.response[1] = pack_live[1];
AddCrc14A(dynamic_response_info.response, 2);
dynamic_response_info.response_n = 4; // 2 PACK + 2 CRC
prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE);
p_response = &dynamic_response_info;
} else {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Password did not match, NACK_IV.");
p_response = NULL;
+67
View File
@@ -24,6 +24,7 @@
#include "aes.h"
#include "cmdhfmf.h"
#include "cmdhf14a.h"
#include "mifare/mifarehost.h" // mf_eml_set_mem_xt
#include "comms.h"
#include "protocols.h"
#include "generator.h"
@@ -8053,6 +8054,71 @@ static int CmdHF14AMfUIncr(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdHF14AMfUeSetBlk(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu esetblk",
"Set emulator memory page(s). One page = 4 bytes; pass multiple\n"
"whole pages of data to set consecutive pages from --blk.",
"hf mfu esetblk --blk 4 -d 04E10CDA\n"
"hf mfu esetblk --blk 4 -d 04E10CDA993C8048 -> sets pages 4-5\n"
);
void *argtable[] = {
arg_param_begin,
arg_int1("b", "blk", "<dec>", "page number to start at"),
arg_str0("d", "data", "<hex>", "bytes to write, whole pages (multiple of 4 bytes)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int blk = arg_get_int_def(ctx, 1, 0);
uint8_t data[MFU_MAX_BYTES] = {0x00};
int datalen = 0;
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &datalen);
CLIParserFree(ctx);
if (res) {
PrintAndLogEx(FAILED, "Error parsing bytes");
return PM3_EINVARG;
}
if (blk < 0) {
PrintAndLogEx(WARNING, "page number must be positive");
return PM3_EINVARG;
}
if (datalen == 0 || (datalen % MFU_BLOCK_SIZE) != 0) {
PrintAndLogEx(WARNING, "data must be whole pages (multiples of %d bytes). Got %i", MFU_BLOCK_SIZE, datalen);
return PM3_EINVARG;
}
int count = datalen / MFU_BLOCK_SIZE;
// live MFU emulator data region is MFU_MAX_BYTES (pages 0..254); page 255 is not round-trippable
if ((blk + count) * MFU_BLOCK_SIZE > MFU_MAX_BYTES) {
PrintAndLogEx(WARNING, "page range exceeds emulator memory (max page %u)", (MFU_MAX_BYTES / MFU_BLOCK_SIZE) - 1);
return PM3_EINVARG;
}
// one esetblk is a single CMD_HF_MIFARE_EML_MEMSET; its payload (data + a 4-byte
// header) must fit the command buffer. Larger sets should use `hf mfu eload`.
if (datalen > (int)(PM3_CMD_DATA_SIZE - 4)) {
PrintAndLogEx(WARNING, "too many pages for one command: max %d pages (%d bytes). Use " _YELLOW_("`hf mfu eload`") " for larger sets",
(int)((PM3_CMD_DATA_SIZE - 4) / MFU_BLOCK_SIZE), (int)(PM3_CMD_DATA_SIZE - 4));
return PM3_EINVARG;
}
// MFU emulator page data starts after the 56-byte mfu_dump_t prefix, so shift the
// page index by MFU_DUMP_PREFIX_LENGTH/MFU_BLOCK_SIZE (=14), width = MFU_BLOCK_SIZE (4).
res = mf_eml_set_mem_xt(data, blk + (MFU_DUMP_PREFIX_LENGTH / MFU_BLOCK_SIZE), count, MFU_BLOCK_SIZE);
if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Failed to set emulator memory");
return res;
}
PrintAndLogEx(SUCCESS, "Set " _YELLOW_("%d") " page(s) from page " _YELLOW_("%d"), count, blk);
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"list", CmdHF14AMfuList, AlwaysAvailable, "List MIFARE Ultralight / NTAG history"},
@@ -8082,6 +8148,7 @@ static command_t CommandTable[] = {
{"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Upload file into emulator memory"},
{"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save emulator memory to file"},
{"eview", CmdHF14AMfuEView, IfPm3Iso14443a, "View emulator memory"},
{"esetblk", CmdHF14AMfUeSetBlk, IfPm3Iso14443a, "Set emulator memory block"},
{"sim", CmdHF14AMfUSim, IfPm3Iso14443a, "Simulate MIFARE Ultralight from emulator memory"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " ----------------------------"},
{"setuid", CmdHF14AMfUCSetUid, IfPm3Iso14443a, "Set UID - MAGIC tags only"},