Merge branch 'master' into experimental_varlen
* master: chg: 'hf mf sim' - textual fix: warning on mingw64. This offset is calculated, casting it to u32 should be fine. fix: https://github.com/RfidResearchGroup/proxmark3/issues/174 remove all offending code, return 1. Will only impact the speed of hardnested execution. fix again OSX fix https://github.com/RfidResearchGroup/proxmark3/issues/173 used predefined constants, common types moved to common header files backward compatibility, on load converter for old mfu dump format loops for counters output UL/NTAG new dump file format. Added counters support, simulation
This commit is contained in:
@@ -2132,6 +2132,8 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false, verbose = false, setEmulatorMem = false;
|
||||
nonces_t data[1];
|
||||
char csize[13] = { 0 };
|
||||
char uidsize[8] = { 0 };
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
@@ -2152,24 +2154,21 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||
case 't':
|
||||
switch (param_get8(Cmd, cmdp + 1)) {
|
||||
case 0:
|
||||
// Mifare MINI
|
||||
flags |= FLAG_MF_MINI;
|
||||
break;
|
||||
case 1:
|
||||
// Mifare Classic 1k
|
||||
flags |= FLAG_MF_1K;
|
||||
sprintf(csize, "MINI");
|
||||
break;
|
||||
case 2:
|
||||
// Mifare Classic 2k
|
||||
flags |= FLAG_MF_2K;
|
||||
sprintf(csize, "2K with RATS");
|
||||
break;
|
||||
case 4:
|
||||
// Mifare Classic 4k
|
||||
flags |= FLAG_MF_4K;
|
||||
sprintf(csize, "4K");
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
// Mifare Classic 1k
|
||||
flags |= FLAG_MF_1K;
|
||||
sprintf(csize, "1K");
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
@@ -2179,12 +2178,15 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||
switch (uidlen) {
|
||||
case 20:
|
||||
flags |= FLAG_10B_UID_IN_DATA;
|
||||
sprintf(uidsize, "10 byte");
|
||||
break;
|
||||
case 14:
|
||||
flags |= FLAG_7B_UID_IN_DATA;
|
||||
sprintf(uidsize, "7 byte");
|
||||
break;
|
||||
case 8:
|
||||
flags |= FLAG_4B_UID_IN_DATA;
|
||||
sprintf(uidsize, "4 byte");
|
||||
break;
|
||||
default:
|
||||
return usage_hf14_mfsim();
|
||||
@@ -2209,11 +2211,17 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||
if (errors) return usage_hf14_mfsim();
|
||||
|
||||
// Use UID, SAK, ATQA from EMUL, if uid not defined
|
||||
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0)
|
||||
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
|
||||
flags |= FLAG_UID_IN_EMUL;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, " uid:%s, numreads:%d, flags:%d (0x%02x) "
|
||||
PrintAndLogEx(INFO, _YELLOW_("Mifare %s") " | %s UID " _YELLOW_("%s") ""
|
||||
, csize
|
||||
, uidsize
|
||||
, (uidlen == 0) ? "N/A" : sprint_hex(uid, uidlen >> 1)
|
||||
);
|
||||
|
||||
PrintAndLogEx(INFO, "Options [ numreads: %d, flags: %d (0x%02x) ]"
|
||||
, exitAfterNReads
|
||||
, flags
|
||||
, flags);
|
||||
@@ -2572,6 +2580,16 @@ int CmdHF14AMfELoad(const char *Cmd) {
|
||||
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");
|
||||
|
||||
blockNum = 0;
|
||||
|
||||
@@ -1615,11 +1615,13 @@ void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) {
|
||||
PrintAndLogEx(NORMAL, "----------+-------------------------+---------");
|
||||
PrintAndLogEx(NORMAL, "Version | %s| %s", sprint_hex(card->version, sizeof(card->version)), sprint_ascii(card->version, sizeof(card->version)));
|
||||
PrintAndLogEx(NORMAL, "TBD | %-24s| %s", sprint_hex(card->tbo, sizeof(card->tbo)), sprint_ascii(card->tbo, sizeof(card->tbo)));
|
||||
PrintAndLogEx(NORMAL, "Tearing | %-24s| %s", sprint_hex(card->tearing, sizeof(card->tearing)), sprint_ascii(card->tearing, sizeof(card->tearing)));
|
||||
PrintAndLogEx(NORMAL, "Pack | %-24s| %s", sprint_hex(card->pack, sizeof(card->pack)), sprint_ascii(card->pack, sizeof(card->pack)));
|
||||
PrintAndLogEx(NORMAL, "TBD | %-24s| %s", sprint_hex(card->tbo1, sizeof(card->tbo1)), sprint_ascii(card->tbo1, sizeof(card->tbo1)));
|
||||
PrintAndLogEx(NORMAL, "Signature1| %s| %s", sprint_hex(card->signature, 16), sprint_ascii(card->signature, 16));
|
||||
PrintAndLogEx(NORMAL, "Signature2| %s| %s", sprint_hex(card->signature + 16, 16), sprint_ascii(card->signature + 16, 16));
|
||||
for (uint8_t i = 0; i < 3; i ++) {
|
||||
PrintAndLogEx(NORMAL, "Counter%d | %-24s| %s", i, sprint_hex(card->counter_tearing[i], 3), sprint_ascii(card->counter_tearing[i], 3));
|
||||
PrintAndLogEx(NORMAL, "Tearing%d | %-24s| %s", i, sprint_hex(card->counter_tearing[i] + 3, 1), sprint_ascii(card->counter_tearing[i] + 3, 1));
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
|
||||
PrintAndLogEx(NORMAL, "\nBlock# | Data |lck| Ascii");
|
||||
PrintAndLogEx(NORMAL, "---------+-------------+---+------");
|
||||
@@ -1884,8 +1886,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
mfu_dump_t dump_file_data;
|
||||
uint8_t get_pack[] = {0, 0};
|
||||
uint8_t get_version[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t get_tearing[] = {0, 0, 0};
|
||||
uint8_t get_counter[] = {0, 0, 0};
|
||||
uint8_t get_counter_tearing[][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
|
||||
uint8_t dummy_pack[] = {0, 0};
|
||||
uint8_t get_signature[32];
|
||||
memset(get_signature, 0, sizeof(get_signature));
|
||||
@@ -1915,8 +1916,8 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
|
||||
ulev1_getVersion(get_version, sizeof(get_version));
|
||||
for (uint8_t n = 0; n < 3; ++n) {
|
||||
ulev1_readTearing(n, get_tearing + n, 1);
|
||||
ulev1_readCounter(n, get_counter, sizeof(get_counter));
|
||||
ulev1_readTearing(n, &get_counter_tearing[n][3], 1);
|
||||
ulev1_readCounter(n, &get_counter_tearing[n][0], 3);
|
||||
}
|
||||
|
||||
DropField();
|
||||
@@ -1930,7 +1931,8 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
}
|
||||
|
||||
// format and add keys to block dump output
|
||||
if (hasAuthKey) {
|
||||
// only add keys if not partial read, and complete pages read
|
||||
if (!is_partial && pages == card_mem_size && hasAuthKey) {
|
||||
// if we didn't swapendian before - do it now for the sprint_hex call
|
||||
// NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
|
||||
// need to swap to keep it the same
|
||||
@@ -1949,11 +1951,11 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
}
|
||||
|
||||
//add *special* blocks to dump
|
||||
//iceman: need to add counters and pwd values to the dump format
|
||||
// pack and pwd saved into last pages of dump, if was not partial read
|
||||
dump_file_data.pages = pages - 1;
|
||||
memcpy(dump_file_data.version, get_version, sizeof(dump_file_data.version));
|
||||
memcpy(dump_file_data.tearing, get_tearing, sizeof(dump_file_data.tearing));
|
||||
memcpy(dump_file_data.pack, get_pack, sizeof(dump_file_data.pack));
|
||||
memcpy(dump_file_data.signature, get_signature, sizeof(dump_file_data.signature));
|
||||
memcpy(dump_file_data.counter_tearing, get_counter_tearing, sizeof(dump_file_data.counter_tearing));
|
||||
memcpy(dump_file_data.data, data, pages * 4);
|
||||
|
||||
printMFUdumpEx(&dump_file_data, pages, startPage);
|
||||
@@ -1966,7 +1968,7 @@ static int CmdHF14AMfUDump(const char *Cmd) {
|
||||
fptr += sprintf(fptr, "hf-mfu-");
|
||||
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);
|
||||
saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t *)&dump_file_data, datalen);
|
||||
|
||||
@@ -2086,16 +2088,30 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||
// read all data
|
||||
size_t bytes_read = fread(dump, 1, fsize, f);
|
||||
fclose(f);
|
||||
if (bytes_read < 48) {
|
||||
if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
|
||||
PrintAndLogEx(WARNING, "Error, dump file is too small");
|
||||
free(dump);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", filename);
|
||||
// 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;
|
||||
uint8_t pages = (bytes_read - 48) / 4;
|
||||
uint8_t pages = (bytes_read - MFU_DUMP_PREFIX_LENGTH) / 4;
|
||||
|
||||
if (pages - 1 != mem->pages) {
|
||||
PrintAndLogEx(WARNING, "Error, invalid dump, wrong page count");
|
||||
free(dump);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", filename);
|
||||
|
||||
// print dump
|
||||
printMFUdumpEx(mem, pages, 0);
|
||||
@@ -2129,7 +2145,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||
|
||||
if (read_key) {
|
||||
// try reading key from dump and use.
|
||||
memcpy(data, mem->data + (bytes_read - 48 - 8), 4);
|
||||
memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 8), 4);
|
||||
} else {
|
||||
memcpy(data, p_authkey, 4);
|
||||
}
|
||||
@@ -2147,8 +2163,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
||||
}
|
||||
|
||||
// pack
|
||||
data[0] = mem->pack[0];
|
||||
data[1] = mem->pack[1];
|
||||
memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2);
|
||||
data[2] = 0;
|
||||
data[3] = 0;
|
||||
PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4));
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
#include "comms.h"
|
||||
#include "loclass/fileutils.h"
|
||||
|
||||
#define DUMP_PREFIX_LENGTH 48
|
||||
|
||||
// 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];
|
||||
@@ -23,7 +26,8 @@ typedef struct {
|
||||
uint8_t signature[32];
|
||||
//uint8_t counter[3];
|
||||
uint8_t data[1024];
|
||||
} mfu_dump_t;
|
||||
} old_mfu_dump_t;
|
||||
|
||||
|
||||
uint32_t GetHF14AMfU_Type(void);
|
||||
int ul_print_type(uint32_t tagtype, uint8_t spaces);
|
||||
|
||||
@@ -204,12 +204,10 @@ int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, si
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr,
|
||||
#if __WORDSIZE == 64
|
||||
"CBOR parsing failure at offset %" PRId64 " : %s\n",
|
||||
#else
|
||||
"CBOR parsing failure at offset %" PRId32 " : %s\n",
|
||||
#endif
|
||||
cb.ptr - data, cbor_error_string(err));
|
||||
(uint32_t)(cb.ptr - data),
|
||||
cbor_error_string(err)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,20 +218,24 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
|
||||
memcpy(uid, tmp->data, 3);
|
||||
memcpy(uid + 3, tmp->data + 4, 4);
|
||||
|
||||
char path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid));
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Version", tmp->version, sizeof(tmp->version));
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.TBO_0", tmp->tbo, sizeof(tmp->tbo));
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Tearing", tmp->tearing, sizeof(tmp->tearing));
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Pack", tmp->pack, sizeof(tmp->pack));
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.TBO_1", tmp->tbo1, sizeof(tmp->tbo1));
|
||||
JsonSaveBufAsHexCompact(root, "$.Card.Signature", tmp->signature, sizeof(tmp->signature));
|
||||
JsonSaveStr(root, "$.Card.Counter", "N/A");
|
||||
for (uint8_t i = 0; i < 3; i ++) {
|
||||
sprintf(path, "$.Card.Counter%d", i);
|
||||
JsonSaveBufAsHexCompact(root, path, tmp->counter_tearing[i], 3);
|
||||
sprintf(path, "$.Card.Tearing%d", i);
|
||||
JsonSaveBufAsHexCompact(root, path, tmp->counter_tearing[i] + 3, 1);
|
||||
}
|
||||
|
||||
// size of header 48b
|
||||
size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4;
|
||||
// size of header 56b
|
||||
size_t len = (datalen - MFU_DUMP_PREFIX_LENGTH) / 4;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
char path[PATH_MAX_LENGTH] = {0};
|
||||
sprintf(path, "$.blocks.%zu", i);
|
||||
JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4);
|
||||
}
|
||||
@@ -564,6 +568,39 @@ out:
|
||||
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);
|
||||
memcpy(mfu_dump->tbo, old_mfu_dump->tbo, 2);
|
||||
mfu_dump->tbo1[0] = old_mfu_dump->tbo1[0];
|
||||
memcpy(mfu_dump->signature, old_mfu_dump->signature, 32);
|
||||
for (int i = 0; i < 3; i++)
|
||||
mfu_dump->counter_tearing[i][3] = old_mfu_dump->tearing[i];
|
||||
|
||||
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
|
||||
|
||||
#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);
|
||||
|
||||
/**
|
||||
* @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)
|
||||
#else
|
||||
|
||||
@@ -171,6 +180,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data
|
||||
#define PrintAndLogDevice(level, format, args...) { }
|
||||
|
||||
|
||||
|
||||
#endif //ON_DEVICE
|
||||
|
||||
#endif // FILEUTILS_H
|
||||
|
||||
@@ -104,11 +104,11 @@ local function main(args)
|
||||
-- lua uses start index and endindex, not count.
|
||||
-- UID is 3three skip bcc0 then 4bytes.
|
||||
-- 1 lua is one-index.
|
||||
-- 1 + 96 (48*2) new dump format has version/signature/counter data here
|
||||
-- 97,98,99,100,101,102 UID first three bytes
|
||||
-- 103,104 bcc0
|
||||
-- 105--- UID last four bytes
|
||||
local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7)
|
||||
-- 1 + 112 (56*2) new dump format has version/signature/counter data here
|
||||
-- 113,114,115,116,117,118 UID first three bytes
|
||||
-- 119,120 bcc0
|
||||
-- 121--- UID last four bytes
|
||||
local uid = string.sub(dumpdata, 113, 113+5)..string.sub(dumpdata, 113+8, 113+8+7)
|
||||
output = output or (uid .. ".eml")
|
||||
|
||||
-- Format some linebreaks
|
||||
|
||||
@@ -797,9 +797,22 @@ int num_CPUs(void) {
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
return sysinfo.dwNumberOfProcessors;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
#elif defined(__linux__) && defined(_SC_NPROCESSORS_ONLN)
|
||||
#include <unistd.h>
|
||||
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||
int count = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (count <= 0)
|
||||
count = 1;
|
||||
return count;
|
||||
#elif defined(__APPLE__)
|
||||
/*
|
||||
TODO ICEMAN 2019, its commented out until someone finds a better solution
|
||||
#include "sys/sysctl.h"
|
||||
uint32_t logicalcores = 0;
|
||||
size_t size = sizeof( logicalcores );
|
||||
sysctlbyname( "hw.logicalcpu", &logicalcores, &size, NULL, 0 );
|
||||
return logicalcores;
|
||||
*/
|
||||
return 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user