mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
backward compatibility, on load converter for old mfu dump format
This commit is contained in:
parent
8793a9e596
commit
a8c1fa7a3b
6 changed files with 96 additions and 10 deletions
|
@ -1318,6 +1318,9 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
|
||||||
p_response = NULL;
|
p_response = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (receivedCmd[0] == MIFARE_ULEV1_VCSL) {
|
||||||
|
EmSend4bit(CARD_NACK_NA);
|
||||||
|
p_response = NULL;
|
||||||
} else {
|
} else {
|
||||||
// Check for ISO 14443A-4 compliant commands, look at left nibble
|
// Check for ISO 14443A-4 compliant commands, look at left nibble
|
||||||
switch (receivedCmd[0]) {
|
switch (receivedCmd[0]) {
|
||||||
|
@ -1371,8 +1374,10 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
|
||||||
default: {
|
default: {
|
||||||
// Never seen this command before
|
// Never seen this command before
|
||||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||||
Dbprintf("Received unknown command (len=%d):", len);
|
if (MF_DBGLEVEL >= 3) {
|
||||||
Dbhexdump(len, receivedCmd, false);
|
Dbprintf("Received unknown command (len=%d):", len);
|
||||||
|
Dbhexdump(len, receivedCmd, false);
|
||||||
|
}
|
||||||
// Do not respond
|
// Do not respond
|
||||||
dynamic_response_info.response_n = 0;
|
dynamic_response_info.response_n = 0;
|
||||||
}
|
}
|
||||||
|
@ -1388,7 +1393,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
|
||||||
dynamic_response_info.response_n += 2;
|
dynamic_response_info.response_n += 2;
|
||||||
|
|
||||||
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
|
if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) {
|
||||||
DbpString("Error preparing tag response");
|
if (MF_DBGLEVEL >= 3) DbpString("Error preparing tag response");
|
||||||
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2590,6 +2590,16 @@ int CmdHF14AMfELoad(const char *Cmd) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert old mfu format to new
|
||||||
|
if (blockWidth == 4) {
|
||||||
|
res = convertOldMfuDump(&data, &datalen);
|
||||||
|
if (res) {
|
||||||
|
PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
|
||||||
|
free(data);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Copying to emulator memory");
|
PrintAndLogEx(INFO, "Copying to emulator memory");
|
||||||
|
|
||||||
blockNum = 0;
|
blockNum = 0;
|
||||||
|
|
|
@ -1973,7 +1973,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||||
fptr += sprintf(fptr, "hf-mfu-");
|
fptr += sprintf(fptr, "hf-mfu-");
|
||||||
FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
|
FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
|
||||||
}
|
}
|
||||||
uint16_t datalen = pages * 4 + DUMP_PREFIX_LENGTH;
|
uint16_t datalen = pages * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||||
saveFile(filename, "bin", (uint8_t *)&dump_file_data, datalen);
|
saveFile(filename, "bin", (uint8_t *)&dump_file_data, datalen);
|
||||||
saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t *)&dump_file_data, datalen);
|
saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t *)&dump_file_data, datalen);
|
||||||
|
|
||||||
|
@ -2094,14 +2094,22 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||||
// read all data
|
// read all data
|
||||||
size_t bytes_read = fread(dump, 1, fsize, f);
|
size_t bytes_read = fread(dump, 1, fsize, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (bytes_read < DUMP_PREFIX_LENGTH) {
|
if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
|
||||||
PrintAndLogEx(WARNING, "Error, dump file is too small");
|
PrintAndLogEx(WARNING, "Error, dump file is too small");
|
||||||
free(dump);
|
free(dump);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert old format to new format, if need
|
||||||
|
int res = convertOldMfuDump(&dump, &bytes_read);
|
||||||
|
if (res) {
|
||||||
|
PrintAndLogEx(WARNING, "Failed convert on load to new Ultralight/NTAG format");
|
||||||
|
free(dump);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
mfu_dump_t *mem = (mfu_dump_t *)dump;
|
mfu_dump_t *mem = (mfu_dump_t *)dump;
|
||||||
uint8_t pages = (bytes_read - DUMP_PREFIX_LENGTH) / 4;
|
uint8_t pages = (bytes_read - MFU_DUMP_PREFIX_LENGTH) / 4;
|
||||||
|
|
||||||
if (pages - 1 != mem->pages) {
|
if (pages - 1 != mem->pages) {
|
||||||
PrintAndLogEx(WARNING, "Error, invalid dump, wrong page count");
|
PrintAndLogEx(WARNING, "Error, invalid dump, wrong page count");
|
||||||
|
@ -2142,7 +2150,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||||
|
|
||||||
if (read_key) {
|
if (read_key) {
|
||||||
// try reading key from dump and use.
|
// try reading key from dump and use.
|
||||||
memcpy(c.d.asBytes, mem->data + (bytes_read - DUMP_PREFIX_LENGTH - 8), 4);
|
memcpy(c.d.asBytes, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 8), 4);
|
||||||
} else {
|
} else {
|
||||||
memcpy(c.d.asBytes, p_authkey, 4);
|
memcpy(c.d.asBytes, p_authkey, 4);
|
||||||
}
|
}
|
||||||
|
@ -2160,7 +2168,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||||
|
|
||||||
// pack now stored in dump
|
// pack now stored in dump
|
||||||
c.arg[0] = MFU_NTAG_SPECIAL_PACK;
|
c.arg[0] = MFU_NTAG_SPECIAL_PACK;
|
||||||
memcpy(c.d.asBytes, mem->data + (bytes_read - DUMP_PREFIX_LENGTH - 4), 2);
|
memcpy(c.d.asBytes, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2);
|
||||||
c.d.asBytes[2] = 0;
|
c.d.asBytes[2] = 0;
|
||||||
c.d.asBytes[3] = 0;
|
c.d.asBytes[3] = 0;
|
||||||
PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(c.d.asBytes, 4));
|
PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(c.d.asBytes, 4));
|
||||||
|
|
|
@ -12,8 +12,10 @@
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "loclass/fileutils.h"
|
#include "loclass/fileutils.h"
|
||||||
|
|
||||||
|
|
||||||
|
// New Ultralight/NTAG dump file format
|
||||||
// Length must be aligned to 4 bytes (UL/NTAG page)
|
// Length must be aligned to 4 bytes (UL/NTAG page)
|
||||||
#define DUMP_PREFIX_LENGTH 56
|
#define MFU_DUMP_PREFIX_LENGTH 56
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t version[8];
|
uint8_t version[8];
|
||||||
|
@ -25,6 +27,22 @@ typedef struct {
|
||||||
uint8_t data[1024];
|
uint8_t data[1024];
|
||||||
} mfu_dump_t;
|
} mfu_dump_t;
|
||||||
|
|
||||||
|
// Old Ultralight/NTAG dump file format
|
||||||
|
// It is used only for converting
|
||||||
|
#define OLD_MFU_DUMP_PREFIX_LENGTH 48
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t version[8];
|
||||||
|
uint8_t tbo[2];
|
||||||
|
uint8_t tearing[3];
|
||||||
|
uint8_t pack[2];
|
||||||
|
uint8_t tbo1[1];
|
||||||
|
uint8_t signature[32];
|
||||||
|
//uint8_t counter[3];
|
||||||
|
uint8_t data[1024];
|
||||||
|
} old_mfu_dump_t;
|
||||||
|
|
||||||
|
|
||||||
uint32_t GetHF14AMfU_Type(void);
|
uint32_t GetHF14AMfU_Type(void);
|
||||||
int ul_print_type(uint32_t tagtype, uint8_t spaces);
|
int ul_print_type(uint32_t tagtype, uint8_t spaces);
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
|
||||||
}
|
}
|
||||||
|
|
||||||
// size of header 56b
|
// size of header 56b
|
||||||
size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4;
|
size_t len = (datalen - MFU_DUMP_PREFIX_LENGTH) / 4;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
sprintf(path, "$.blocks.%zu", i);
|
sprintf(path, "$.blocks.%zu", i);
|
||||||
|
@ -568,6 +568,41 @@ out:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int convertOldMfuDump(uint8_t **dump, size_t *dumplen) {
|
||||||
|
if (!dump || !dumplen || *dumplen < OLD_MFU_DUMP_PREFIX_LENGTH)
|
||||||
|
return 1;
|
||||||
|
// try to check new file format
|
||||||
|
mfu_dump_t *mfu_dump = (mfu_dump_t *) *dump;
|
||||||
|
if ((*dumplen - MFU_DUMP_PREFIX_LENGTH) / 4 - 1 == mfu_dump->pages)
|
||||||
|
return 0;
|
||||||
|
// convert old format
|
||||||
|
old_mfu_dump_t *old_mfu_dump = (old_mfu_dump_t *) *dump;
|
||||||
|
|
||||||
|
size_t old_data_len = *dumplen - OLD_MFU_DUMP_PREFIX_LENGTH;
|
||||||
|
size_t new_dump_len = old_data_len + MFU_DUMP_PREFIX_LENGTH;
|
||||||
|
|
||||||
|
mfu_dump = (mfu_dump_t *) calloc(new_dump_len, sizeof(uint8_t));
|
||||||
|
|
||||||
|
memcpy(mfu_dump->version, old_mfu_dump->version, 8);
|
||||||
|
mfu_dump->tbo[0] = old_mfu_dump->tbo[0];
|
||||||
|
mfu_dump->tbo[1] = old_mfu_dump->tbo[1];
|
||||||
|
mfu_dump->tbo1[0] = old_mfu_dump->tbo1[0];
|
||||||
|
memcpy(mfu_dump->signature, old_mfu_dump->signature, 32);
|
||||||
|
mfu_dump->counter_tearing[0][3] = old_mfu_dump->tearing[0];
|
||||||
|
mfu_dump->counter_tearing[1][3] = old_mfu_dump->tearing[1];
|
||||||
|
mfu_dump->counter_tearing[2][3] = old_mfu_dump->tearing[2];
|
||||||
|
|
||||||
|
memcpy(mfu_dump->data, old_mfu_dump->data, old_data_len);
|
||||||
|
mfu_dump->pages = old_data_len / 4 - 1;
|
||||||
|
// free old buffer, return new buffer
|
||||||
|
*dumplen = new_dump_len;
|
||||||
|
free(*dump);
|
||||||
|
*dump = (uint8_t *) mfu_dump;
|
||||||
|
PrintAndLogDevice(SUCCESS, "old mfu dump format, was converted on load to " _GREEN_("%d") " pages", mfu_dump->pages + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#else //if we're on ARM
|
#else //if we're on ARM
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -158,6 +158,15 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size
|
||||||
*/
|
*/
|
||||||
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt);
|
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility function to check and convert old mfu dump format to new
|
||||||
|
*
|
||||||
|
* @param dump pointer to loaded dump to check and convert format
|
||||||
|
* @param dumplen the number of bytes loaded dump and converted
|
||||||
|
* @return 0 for ok, 1 for fails
|
||||||
|
*/
|
||||||
|
int convertOldMfuDump(uint8_t **dump, size_t *dumplen);
|
||||||
|
|
||||||
#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args)
|
#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args)
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -171,6 +180,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data
|
||||||
#define PrintAndLogDevice(level, format, args...) { }
|
#define PrintAndLogDevice(level, format, args...) { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //ON_DEVICE
|
#endif //ON_DEVICE
|
||||||
|
|
||||||
#endif // FILEUTILS_H
|
#endif // FILEUTILS_H
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue