diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c90a11968..b14dde768 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2878,7 +2878,7 @@ int CmdHF14AMfCSave(const char *Cmd) { saveFile(filename, "bin", dump, bytes); saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); - saveFileJSON(filename, "json", dump, bytes); + saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); free(dump); return 0; } diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index f1431ee52..f110e02fc 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -135,7 +135,7 @@ out: return retval; } -int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen) { +int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t* data, size_t datalen) { if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; if ( data == NULL ) return 1; @@ -152,7 +152,58 @@ int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, s json_t *root = json_object(); JsonSaveStr(root, "Created", "proxmark3"); - JsonSaveBufAsHexCompact(root, "raw", data, datalen); + switch(ftype) { + case jsfRaw: + JsonSaveStr(root, "FileType", "raw"); + JsonSaveBufAsHexCompact(root, "raw", data, datalen); + break; + case jsfCardMemory: + JsonSaveStr(root, "FileType", "mifare card dump"); + for (int i = 0; i < (datalen / 16); i++) { + char path[30] = {0}; + sprintf(path, "$.blocks.%d", i); + JsonSaveBufAsHexCompact(root, path, &data[i * 16], 16); + + if (i == 0) { + JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 4); + JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[5], 1); + JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[6], 2); + } + + if (mfIsSectorTrailer(i)) { + char patha[30] = {0}; + sprintf(patha, "$.SectorKeys.%d.KeyA", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, patha, &data[i * 16], 6); + + char pathb[30] = {0}; + sprintf(pathb, "$.SectorKeys.%d.KeyB", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, pathb, &data[i * 16 + 10], 6); + + char pathc[30] = {0}; + uint8_t *adata = &data[i * 16 + 6]; + sprintf(pathc, "$.SectorKeys.%d.AccessConditions", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, pathc, &data[i * 16 + 6], 4); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 3); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(0, adata)); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 2); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(1, adata)); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 1); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(2, adata)); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(3, adata)); + + } + } + break; + } int res = json_dump_file(root, fileName, JSON_INDENT(2)); if (res) { diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index c699be3de..3852b4bf4 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -48,6 +48,12 @@ #include #include "../ui.h" #include "../emv/emvjson.h" +#include "mifare4.h" + +typedef enum { + jsfRaw, + jsfCardMemory, +} JSONFileType; int fileExists(const char *filename); @@ -85,11 +91,12 @@ extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t* d * * @param preferredName * @param suffix the file suffix. Leave out the ".". + * @param ftype type of file. * @param data The binary data to write to the file * @param datalen the length of the data * @return 0 for ok, 1 for failz */ -extern int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen); +extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t* data, size_t datalen); /** STUB * @brief Utility function to load data from a binary file. This method takes a preferred name. diff --git a/client/mifare4.c b/client/mifare4.c index 39869ab77..0c53a1f9b 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -17,6 +17,52 @@ #include "ui.h" #include "crypto/libpcrypto.h" +AccessConditions_t MFAccessConditions[] = { + {0x00, "rdAB wrAB incAB dectrAB"}, + {0x01, "rdAB dectrAB"}, + {0x02, "rdAB"}, + {0x03, "rdB wrB"}, + {0x04, "rdAB wrB"}, + {0x05, "rdB"}, + {0x06, "rdAB wrB incB dectrAB"}, + {0x07, "none"} +}; + +AccessConditions_t MFAccessConditionsTrailer[] = { + {0x00, "rdAbyA rdCbyA rdBbyA wrBbyA"}, + {0x01, "wrAbyA rdCbyA wrCbyA rdBbyA wrBbyA"}, + {0x02, "rdCbyA rdBbyA"}, + {0x03, "wrAbyB rdCbyAB wrCbyB wrBbyB"}, + {0x04, "wrAbyB rdCbyAB wrBbyB"}, + {0x05, "rdCbyAB wrCbyB"}, + {0x06, "rdCbyAB"}, + {0x07, "rdCbyAB"} +}; + +char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { + static char StaticNone[] = "none"; + + uint8_t data1 = ((data[1] >> 4) & 0x0f) >> blockn; + uint8_t data2 = ((data[2]) & 0x0f) >> blockn; + uint8_t data3 = ((data[2] >> 4) & 0x0f) >> blockn; + + uint8_t cond = (data1 & 0x01) << 2 | (data2 & 0x01) << 1 | (data3 & 0x01); + + if (blockn == 3) { + for (int i = 0; i < ARRAYLEN(MFAccessConditionsTrailer); i++) + if (MFAccessConditionsTrailer[i].cond == cond) { + return MFAccessConditionsTrailer[i].description; + } + } else { + for (int i = 0; i < ARRAYLEN(MFAccessConditions); i++) + if (MFAccessConditions[i].cond == cond) { + return MFAccessConditions[i].description; + } + }; + + return StaticNone; +}; + int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) { memcpy(&iv[0], session->TI, 4); memcpy(&iv[4], &session->R_Ctr, 2); diff --git a/client/mifare4.h b/client/mifare4.h index b85d512f1..011567a1e 100644 --- a/client/mifare4.h +++ b/client/mifare4.h @@ -38,9 +38,16 @@ typedef enum { mtypWriteResp, } MACType_t; +typedef struct { + uint8_t cond; + char *description; +} AccessConditions_t; + extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); +extern char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); + extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); extern uint8_t mfFirstBlockOfSector(uint8_t sectorNo); extern uint8_t mfSectorTrailer(uint8_t blockNo);