This commit is contained in:
iceman1001 2024-01-25 01:55:07 +01:00
parent 9f015ad964
commit 414275802d
11 changed files with 93 additions and 73 deletions

View file

@ -75,7 +75,7 @@ void RunMod(void) {
} else if (state == STATE_EMUL) { } else if (state == STATE_EMUL) {
Iso15693InitTag(); Iso15693InitTag();
Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state."); Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
// default block size is 4.. // default block size is 4..
// iceman: which can be 4,8 all the way to 32 // iceman: which can be 4,8 all the way to 32
SimTagIso15693(card.uid, 4); SimTagIso15693(card.uid, 4);

View file

@ -1323,19 +1323,19 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t offset; uint32_t offset;
uint16_t length; uint16_t length;
} PACKED; } PACKED;
struct p *payload = (struct p *) packet->data.asBytes; struct p *payload = (struct p *) packet->data.asBytes;
if (payload->length > PM3_CMD_DATA_SIZE) { if (payload->length > PM3_CMD_DATA_SIZE) {
reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_EMALLOC, NULL, 0); reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_EMALLOC, NULL, 0);
return; return;
} }
uint8_t *buf = BigBuf_malloc(payload->length); uint8_t *buf = BigBuf_malloc(payload->length);
emlGet(buf, payload->offset, payload->length); emlGet(buf, payload->offset, payload->length);
LED_B_ON(); LED_B_ON();
reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_SUCCESS, buf, payload->length); reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_SUCCESS, buf, payload->length);
LED_B_OFF(); LED_B_OFF();
BigBuf_free_keep_EM(); BigBuf_free_keep_EM();
break; break;
} }
case CMD_HF_ISO15693_SIMULATE: { case CMD_HF_ISO15693_SIMULATE: {

View file

@ -2139,7 +2139,7 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
} }
if (uid != NULL) { if (uid != NULL) {
uint8_t empty[8] = { 0 }; uint8_t empty[8] = { 0 };
// User supplied not empty? // User supplied not empty?
@ -2168,9 +2168,9 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
} }
if ((tag->pagesCount > ISO15693_TAG_MAX_PAGES) || if ((tag->pagesCount > ISO15693_TAG_MAX_PAGES) ||
((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) || ((tag->pagesCount * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) ||
(tag->pagesCount == 0) || (tag->pagesCount == 0) ||
(tag->bytesPerPage == 0)) { (tag->bytesPerPage == 0)) {
Dbprintf("Tag size error: pagesCount = %d, bytesPerPage=%d", tag->pagesCount, tag->bytesPerPage); Dbprintf("Tag size error: pagesCount = %d, bytesPerPage=%d", tag->pagesCount, tag->bytesPerPage);
reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_EOPABORTED, NULL, 0); reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_EOPABORTED, NULL, 0);
return; return;
@ -2182,17 +2182,17 @@ void SimTagIso15693(uint8_t *uid, uint8_t block_size) {
if (g_dbglevel >= DBG_DEBUG) { if (g_dbglevel >= DBG_DEBUG) {
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X, %u bytes/blocks x %u blocks" Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X, %u bytes/blocks x %u blocks"
, tag->uid[7] , tag->uid[7]
, tag->uid[6] , tag->uid[6]
, tag->uid[5] , tag->uid[5]
, tag->uid[4] , tag->uid[4]
, tag->uid[3] , tag->uid[3]
, tag->uid[2] , tag->uid[2]
, tag->uid[1] , tag->uid[1]
, tag->uid[0] , tag->uid[0]
, tag->bytesPerPage , tag->bytesPerPage
, tag->pagesCount , tag->pagesCount
); );
} }
LED_C_ON(); LED_C_ON();

View file

@ -637,11 +637,11 @@ bool emlCheckValBl(int blockNum) {
uint8_t *d = mem + (blockNum * 16); uint8_t *d = mem + (blockNum * 16);
if ((d[0] != (d[4] ^ 0xff)) || (d[0] != d[8]) || if ((d[0] != (d[4] ^ 0xff)) || (d[0] != d[8]) ||
(d[1] != (d[5] ^ 0xff)) || (d[1] != d[9]) || (d[1] != (d[5] ^ 0xff)) || (d[1] != d[9]) ||
(d[2] != (d[6] ^ 0xff)) || (d[2] != d[10]) || (d[2] != (d[6] ^ 0xff)) || (d[2] != d[10]) ||
(d[3] != (d[7] ^ 0xff)) || (d[3] != d[11]) || (d[3] != (d[7] ^ 0xff)) || (d[3] != d[11]) ||
(d[12] != (d[13] ^ 0xff)) || (d[12] != d[14]) || (d[12] != (d[13] ^ 0xff)) || (d[12] != d[14]) ||
(d[12] != (d[15] ^ 0xff))) { (d[12] != (d[15] ^ 0xff))) {
return false; return false;
} }
return true; return true;

View file

@ -86,25 +86,25 @@ bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys_t *amiiboKeys, const uint8_t *t
nfc3d_amiibo_cipher(&dataKeys, internal, plain); nfc3d_amiibo_cipher(&dataKeys, internal, plain);
// Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256)
, tagKeys.hmacKey , tagKeys.hmacKey
, sizeof(tagKeys.hmacKey) , sizeof(tagKeys.hmacKey)
, plain + 0x1D4 , plain + 0x1D4
, 0x34 , 0x34
, plain + HMAC_POS_TAG , plain + HMAC_POS_TAG
); );
// Regenerate data HMAC // Regenerate data HMAC
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256)
, dataKeys.hmacKey , dataKeys.hmacKey
, sizeof(dataKeys.hmacKey) , sizeof(dataKeys.hmacKey)
, plain + 0x029 , plain + 0x029
, 0x1DF , 0x1DF
, plain + HMAC_POS_DATA , plain + HMAC_POS_DATA
); );
return ((memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0) && return ((memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0) &&
(memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0)); (memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0));
} }
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys_t *amiiboKeys, const uint8_t *plain, uint8_t *tag) { void nfc3d_amiibo_pack(const nfc3d_amiibo_keys_t *amiiboKeys, const uint8_t *plain, uint8_t *tag) {
@ -118,12 +118,12 @@ void nfc3d_amiibo_pack(const nfc3d_amiibo_keys_t *amiiboKeys, const uint8_t *pla
// Generate tag HMAC // Generate tag HMAC
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256)
, tagKeys.hmacKey , tagKeys.hmacKey
, sizeof(tagKeys.hmacKey) , sizeof(tagKeys.hmacKey)
, plain + 0x1D4 , plain + 0x1D4
, 0x34 , 0x34
, cipher + HMAC_POS_TAG , cipher + HMAC_POS_TAG
); );
// Init mbedtls HMAC context // Init mbedtls HMAC context
mbedtls_md_context_t ctx; mbedtls_md_context_t ctx;

View file

@ -20,7 +20,7 @@ static void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys_t *baseKeys,
// 1: Copy whole type string // 1: Copy whole type string
// output = (uint8_t *)strcpy((char *)output, baseKeys->typeString); // output = (uint8_t *)strcpy((char *)output, baseKeys->typeString);
output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString));
// 2: Append (16 - magicBytesSize) from the input seed // 2: Append (16 - magicBytesSize) from the input seed
size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize;

View file

@ -1309,11 +1309,11 @@ static int mfu_dump_tag(uint16_t pages, void **pdata, uint16_t *len) {
} }
// UL_EV1/NTAG auth // UL_EV1/NTAG auth
uint8_t keytype = 2; uint8_t keytype = 2;
// generate PWD // generate PWD
uint8_t key[4] = {0}; uint8_t key[4] = {0};
num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key); num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, key, 4); SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, key, 4);
PacketResponseNG resp; PacketResponseNG resp;
@ -4834,7 +4834,7 @@ static int CmdHF14AMfuList(const char *Cmd) {
return CmdTraceListAlias(Cmd, "hf 14a", "14a -c"); return CmdTraceListAlias(Cmd, "hf 14a", "14a -c");
} }
static int CmdHF14AAmiibo(const char *Cmd){ static int CmdHF14AAmiibo(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu amiibo", CLIParserInit(&ctx, "hf mfu amiibo",
@ -4888,7 +4888,7 @@ static int CmdHF14AAmiibo(const char *Cmd){
// load dump file if available // load dump file if available
if (infnlen > 0) { if (infnlen > 0) {
uint8_t *dump = NULL; uint8_t *dump = NULL;
size_t dumplen = 0; size_t dumplen = 0;
res = loadFile_safe(infilename, "", (void **)&dump, &dumplen); res = loadFile_safe(infilename, "", (void **)&dump, &dumplen);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
free(dump); free(dump);
@ -4914,7 +4914,7 @@ static int CmdHF14AAmiibo(const char *Cmd){
} else { } else {
uint16_t dlen = 0; uint16_t dlen = 0;
uint8_t *dump = NULL; uint8_t *dump = NULL;
res = mfu_dump_tag( MAX_NTAG_215, (void **)&dump, &dlen); res = mfu_dump_tag(MAX_NTAG_215, (void **)&dump, &dlen);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Failed to dump memory from tag"); PrintAndLogEx(FAILED, "Failed to dump memory from tag");
free(dump); free(dump);
@ -4925,7 +4925,7 @@ static int CmdHF14AAmiibo(const char *Cmd){
} }
uint8_t decrypted[NFC3D_AMIIBO_SIZE] = {0}; uint8_t decrypted[NFC3D_AMIIBO_SIZE] = {0};
if (shall_decrypt) { if (shall_decrypt) {
if (nfc3d_amiibo_unpack(&amiibo_keys, original, decrypted) == false) { if (nfc3d_amiibo_unpack(&amiibo_keys, original, decrypted) == false) {
PrintAndLogEx(INFO, "Tag signature ( " _RED_("fail") " )"); PrintAndLogEx(INFO, "Tag signature ( " _RED_("fail") " )");
@ -4933,7 +4933,7 @@ static int CmdHF14AAmiibo(const char *Cmd){
} }
// print // print
if (verbose) { if (verbose) {
for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++ ) { for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++) {
PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(decrypted + (i * 16), 16)); PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(decrypted + (i * 16), 16));
} }
} }
@ -4944,7 +4944,7 @@ static int CmdHF14AAmiibo(const char *Cmd){
nfc3d_amiibo_pack(&amiibo_keys, decrypted, encrypted); nfc3d_amiibo_pack(&amiibo_keys, decrypted, encrypted);
// print // print
if (verbose) { if (verbose) {
for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++ ) { for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++) {
PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(encrypted + (i * 16), 16)); PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(encrypted + (i * 16), 16));
} }
} }

View file

@ -544,10 +544,10 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
snprintf(path, sizeof(path), "$.blocks.%u", i); snprintf(path, sizeof(path), "$.blocks.%u", i);
JsonSaveBufAsHexCompact(root JsonSaveBufAsHexCompact(root
, path , path
, &tag->data[i * tag->bytesPerPage] , &tag->data[i * tag->bytesPerPage]
, tag->bytesPerPage , tag->bytesPerPage
); );
} }
break; break;
} }
@ -1691,13 +1691,13 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
if (sptr + 8 > maxdatalen) { if (sptr + 8 > maxdatalen) {
PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen" PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen"
, maxdatalen , maxdatalen
, maxdatalen , maxdatalen
, i , i
, i , i
, sptr , sptr
, sptr , sptr
); );
retval = PM3_EMALLOC; retval = PM3_EMALLOC;
goto out; goto out;
@ -1735,13 +1735,13 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
if (((i + 1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) { if (((i + 1) * tag->bytesPerPage) > ISO15693_TAG_MAX_SIZE) {
PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen" PrintAndLogEx(ERR, "loadFileJSONex: maxdatalen=%zu (%04zx) block (i)=%4d (%04x) sptr=%zu (%04zx) -- exceeded maxdatalen"
, maxdatalen , maxdatalen
, maxdatalen , maxdatalen
, i , i
, i , i
, sptr , sptr
, sptr , sptr
); );
retval = PM3_EMALLOC; retval = PM3_EMALLOC;
goto out; goto out;

View file

@ -423,6 +423,7 @@ const static vocabulary_t vocabulary[] = {
{ 0, "hf mfu sim" }, { 0, "hf mfu sim" },
{ 0, "hf mfu setpwd" }, { 0, "hf mfu setpwd" },
{ 0, "hf mfu setuid" }, { 0, "hf mfu setuid" },
{ 0, "hf mfu amiibo" },
{ 1, "hf mfdes help" }, { 1, "hf mfdes help" },
{ 0, "hf mfdes info" }, { 0, "hf mfdes info" },
{ 0, "hf mfdes getuid" }, { 0, "hf mfdes getuid" },

View file

@ -6668,6 +6668,24 @@
], ],
"usage": "hf mfp wrp [-hv] -a <hex> [-d <hex>]" "usage": "hf mfp wrp [-hv] -a <hex> [-d <hex>]"
}, },
"hf mfu amiibo": {
"command": "hf mfu amiibo",
"description": "Tries to read all memory from amiibo tag and decrypt it",
"notes": [
"hf mfu amiiboo --dec -f hf-mfu-04579DB27C4880-dump.bin -> decrypt file",
"hf mfu amiiboo -v --dec -> decrypt tag"
],
"offline": false,
"options": [
"-h, --help This help",
"--dec Decrypt memory",
"--enc Encrypt memory",
"-i, --in <fn> Specify a filename for input dump file",
"-o, --out <fn> Specify a filename for output dump file",
"-v, --verbose Verbose output"
],
"usage": "hf mfu amiibo [-hv] [--dec] [--enc] [-i <fn>] [-o <fn>]"
},
"hf mfu cauth": { "hf mfu cauth": {
"command": "hf mfu cauth", "command": "hf mfu cauth",
"description": "Tests 3DES password on Mifare Ultralight-C tag. If password is not specified, a set of known defaults will be tested.", "description": "Tests 3DES password on Mifare Ultralight-C tag. If password is not specified, a set of known defaults will be tested.",
@ -12336,8 +12354,8 @@
} }
}, },
"metadata": { "metadata": {
"commands_extracted": 711, "commands_extracted": 712,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2024-01-24T17:12:09" "extracted_on": "2024-01-25T00:53:56"
} }
} }

View file

@ -602,6 +602,7 @@ Check column "offline" for their availability.
|`hf mfu sim `|N |`Simulate MIFARE Ultralight from emulator memory` |`hf mfu sim `|N |`Simulate MIFARE Ultralight from emulator memory`
|`hf mfu setpwd `|N |`Set 3DES key - Ultralight-C` |`hf mfu setpwd `|N |`Set 3DES key - Ultralight-C`
|`hf mfu setuid `|N |`Set UID - MAGIC tags only` |`hf mfu setuid `|N |`Set UID - MAGIC tags only`
|`hf mfu amiibo `|N |`Amiibo tag operations`
### hf mfdes ### hf mfdes