refactoring loading dump files

This commit is contained in:
iceman1001 2022-05-15 23:06:46 +02:00
commit d4c3082741
6 changed files with 84 additions and 162 deletions

View file

@ -36,8 +36,6 @@
#include "cmdhf14a.h" // exchange APDU #include "cmdhf14a.h" // exchange APDU
#include "crypto/libpcrypto.h" #include "crypto/libpcrypto.h"
#define MFBLOCK_SIZE 16
#define MIFARE_4K_MAXBLOCK 256 #define MIFARE_4K_MAXBLOCK 256
#define MIFARE_2K_MAXBLOCK 128 #define MIFARE_2K_MAXBLOCK 128
#define MIFARE_1K_MAXBLOCK 64 #define MIFARE_1K_MAXBLOCK 64
@ -264,7 +262,7 @@ static void mf_print_blocks(uint16_t n, uint8_t *d, bool verbose) {
PrintAndLogEx(HINT, _CYAN_("cyan") " = value block with decoded value"); PrintAndLogEx(HINT, _CYAN_("cyan") " = value block with decoded value");
// MAD detection // MAD detection
if (memcmp(d + (3 * MFBLOCK_SIZE), g_mifare_mad_key, 6) == 0) { if (HasMADKey(d)) {
PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details"); PrintAndLogEx(HINT, "MAD key detected. Try " _YELLOW_("`hf mf mad`") " for more details");
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -1110,38 +1108,11 @@ static int CmdHF14AMfRestore(const char *Cmd) {
} }
// read dump file // read dump file
bytes_read = 0;
uint8_t *dump = NULL; uint8_t *dump = NULL;
int res = 0; bytes_read = 0;
DumpFileType_t dftype = getfiletype(datafilename); int res = pm3_load_dump(datafilename, (void **)&dump, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
switch (dftype) {
case BIN: {
res = loadFile_safe(datafilename, ".bin", (void **)&dump, &bytes_read);
break;
}
case EML: {
res = loadFileEML_safe(datafilename, (void **)&dump, &bytes_read);
break;
}
case JSON: {
dump = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (dump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(datafilename, (void *)dump, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
free(dump);
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
free(dump); return res;
return PM3_EFILE;
} }
// default authentication key // default authentication key
@ -3944,41 +3915,14 @@ int CmdHF14AMfELoad(const char *Cmd) {
} }
uint8_t *data = NULL; uint8_t *data = NULL;
size_t datalen = 0; size_t bytes_read = 0;
int res = PM3_SUCCESS; int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
DumpFileType_t dftype = getfiletype(filename);
switch (dftype) {
case BIN: {
res = loadFile_safe(filename, ".bin", (void **)&data, &datalen);
break;
}
case EML: {
res = loadFileEML_safe(filename, (void **)&data, &datalen);
break;
}
case JSON: {
data = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (data == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(filename, (void *)data, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &datalen, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
free(data);
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
free(data); return res;
return PM3_EFILE;
} }
// 64 or 256 blocks. // 64 or 256 blocks.
if ((datalen % block_width) != 0) { if ((bytes_read % block_width) != 0) {
PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth ");
free(data); free(data);
return PM3_ESOFT; return PM3_ESOFT;
@ -3986,7 +3930,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
// convert plain or old mfu format to new format // convert plain or old mfu format to new format
if (block_width == MFU_BLOCK_SIZE) { if (block_width == MFU_BLOCK_SIZE) {
res = convert_mfu_dump_format(&data, &datalen, true); res = convert_mfu_dump_format(&data, &bytes_read, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format"); PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
free(data); free(data);
@ -3997,7 +3941,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0); printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0);
// update expected blocks to match converted data. // update expected blocks to match converted data.
block_cnt = datalen / MFU_BLOCK_SIZE; block_cnt = bytes_read / MFU_BLOCK_SIZE;
PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width); PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width);
} }
@ -4010,8 +3954,8 @@ int CmdHF14AMfELoad(const char *Cmd) {
size_t offset = 0; size_t offset = 0;
int cnt = 0; int cnt = 0;
while (datalen && cnt < block_cnt) { while (bytes_read && cnt < block_cnt) {
if (datalen == block_width) { if (bytes_read == block_width) {
// Disable fast mode on last packet // Disable fast mode on last packet
g_conn.block_after_ACK = false; g_conn.block_after_ACK = false;
} }
@ -4026,7 +3970,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
cnt++; cnt++;
offset += block_width; offset += block_width;
datalen -= block_width; bytes_read -= block_width;
} }
free(data); free(data);
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
@ -4642,38 +4586,12 @@ static int CmdHF14AMfCLoad(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
// reserve memory
uint8_t *data = NULL; uint8_t *data = NULL;
size_t bytes_read = 0; size_t bytes_read = 0;
int res = 0; int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
DumpFileType_t dftype = getfiletype(filename);
switch (dftype) {
case BIN: {
res = loadFile_safe(filename, ".bin", (void **)&data, &bytes_read);
break;
}
case EML: {
res = loadFileEML_safe(filename, (void **)&data, &bytes_read);
break;
}
case JSON: {
data = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (data == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(filename, (void *)data, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
free(data);
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
free(data); return res;
return PM3_EFILE;
} }
// 64 or 256blocks. // 64 or 256blocks.
@ -5430,37 +5348,9 @@ static int CmdHF14AMfMAD(const char *Cmd) {
// reserve memory // reserve memory
uint8_t *dump = NULL; uint8_t *dump = NULL;
size_t bytes_read = 0; size_t bytes_read = 0;
int res = 0; int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
DumpFileType_t dftype = getfiletype(filename);
switch (dftype) {
case BIN: {
res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read);
break;
}
case EML: {
res = loadFileEML_safe(filename, (void **)&dump, &bytes_read);
break;
}
case JSON: {
dump = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (dump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(filename, (void *)dump, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
free(dump);
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); return res;
free(dump);
return PM3_EFILE;
} }
uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE)); uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE));
@ -5477,7 +5367,7 @@ static int CmdHF14AMfMAD(const char *Cmd) {
} }
// MAD detection // MAD detection
if (memcmp(dump + (3 * MFBLOCK_SIZE), g_mifare_mad_key, 6) != 0) { if (HasMADKey(dump)) {
PrintAndLogEx(FAILED, "No MAD key was detected in the dump file"); PrintAndLogEx(FAILED, "No MAD key was detected in the dump file");
free(dump); free(dump);
return PM3_ESOFT; return PM3_ESOFT;
@ -6249,40 +6139,12 @@ static int CmdHF14AMfView(const char *Cmd) {
bool verbose = arg_get_lit(ctx, 2); bool verbose = arg_get_lit(ctx, 2);
CLIParserFree(ctx); CLIParserFree(ctx);
// reserve memory // read dump file
uint8_t *dump = NULL; uint8_t *dump = NULL;
size_t bytes_read = 0; size_t bytes_read = 0;
int res = 0; int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK));
DumpFileType_t dftype = getfiletype(filename);
switch (dftype) {
case BIN: {
res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read);
break;
}
case EML: {
res = loadFileEML_safe(filename, (void **)&dump, &bytes_read);
break;
}
case JSON: {
dump = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t));
if (dump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(filename, (void *)dump, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed");
free(dump);
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); return res;
free(dump);
return PM3_EFILE;
} }
uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE)); uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE));

View file

@ -83,7 +83,7 @@ DumpFileType_t getfiletype(const char *filename) {
} else if (str_endswith(s, "json")) { } else if (str_endswith(s, "json")) {
o = JSON; o = JSON;
} else if (str_endswith(s, "dic")) { } else if (str_endswith(s, "dic")) {
o = DICTIONARY; o = DICTIONARY;
} else { } else {
// mfd, trc, trace is binary // mfd, trc, trace is binary
o = BIN; o = BIN;
@ -1880,3 +1880,41 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con
free(filename); free(filename);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumplen) {
int res = 0;
DumpFileType_t dftype = getfiletype(fn);
switch (dftype) {
case BIN: {
res = loadFile_safe(fn, ".bin", pdump, dumplen);
break;
}
case EML: {
res = loadFileEML_safe(fn, pdump, dumplen);
break;
}
case JSON: {
*pdump = calloc(maxdumplen, sizeof(uint8_t));
if (*pdump == NULL) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC;
}
res = loadFileJSON(fn, *pdump, maxdumplen, dumplen, NULL);
break;
}
case DICTIONARY: {
PrintAndLogEx(ERR, "Error: Only BIN/EML/JSON formats allowed");
return PM3_EINVARG;
}
}
if (res != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", fn);
PrintAndLogEx(INFO, "%d", res);
free(*pdump);
return PM3_EFILE;
}
return res;
}

View file

@ -260,4 +260,16 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con
* @return * @return
*/ */
DumpFileType_t getfiletype(const char *filename); DumpFileType_t getfiletype(const char *filename);
/**
* @brief load dump file into a data array dynamically allocated
* @param fn
* @param pdump pointer to loaded dump
* @param dumplen the number of bytes loaded from dump file
* @param maxdumplen maximum size of data array in bytes (JSON files)
* @return PM3_SUCCESS if OK
*/
int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumplen);
#endif // FILEUTILS_H #endif // FILEUTILS_H

View file

@ -24,6 +24,7 @@
#include "util.h" #include "util.h"
#include "fileutils.h" #include "fileutils.h"
#include "jansson.h" #include "jansson.h"
#include "mifaredefault.h"
// https://www.nxp.com/docs/en/application-note/AN10787.pdf // https://www.nxp.com/docs/en/application-note/AN10787.pdf
static json_t *mad_known_aids = NULL; static json_t *mad_known_aids = NULL;
@ -396,3 +397,10 @@ int MADDFDecodeAndPrint(uint32_t short_aid) {
close_mad_file(mad_known_aids); close_mad_file(mad_known_aids);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
bool HasMADKey(uint8_t *d) {
if (d == NULL)
return false;
return (memcmp(d + (3 * MFBLOCK_SIZE), g_mifare_mad_key, 6) != 0);
}

View file

@ -28,5 +28,5 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose);
int MADDFDecodeAndPrint(uint32_t short_aid); int MADDFDecodeAndPrint(uint32_t short_aid);
int MADCardHolderInfoDecode(uint8_t *data, size_t datalen, bool verbose); int MADCardHolderInfoDecode(uint8_t *data, size_t datalen, bool verbose);
void MADPrintHeader(void); void MADPrintHeader(void);
bool HasMADKey(uint8_t *d);
#endif // _MAD_H_ #endif // _MAD_H_

View file

@ -21,6 +21,8 @@
#include "common.h" #include "common.h"
#define MFBLOCK_SIZE 16
static const uint64_t g_mifare_default_keys[] = { static const uint64_t g_mifare_default_keys[] = {
0xffffffffffff, // Default key (first key used by program if no user defined key) 0xffffffffffff, // Default key (first key used by program if no user defined key)
0x000000000000, // Blank key 0x000000000000, // Blank key