This commit is contained in:
iceman1001 2018-11-29 17:53:57 +01:00
commit 3c88bb5e59
5 changed files with 238 additions and 14 deletions

View file

@ -330,7 +330,9 @@ int usage_hf14_cload(void){
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " e load card with data from emulator memory");
PrintAndLogEx(NORMAL, " <filename> load card with data from file");
PrintAndLogEx(NORMAL, " j <filename> load card with data from json file");
PrintAndLogEx(NORMAL, " b <filename> load card with data from binary file");
PrintAndLogEx(NORMAL, " <filename> load card with data from eml file");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mf cload mydump");
PrintAndLogEx(NORMAL, " hf mf cload e");
@ -2631,12 +2633,21 @@ int CmdHF14AMfCLoad(const char *Cmd) {
uint8_t buf8[16] = {0x00};
uint8_t fillFromEmulator = 0;
int blockNum, flags = 0;
bool fillFromJson = false;
bool fillFromBin = false;
char fileName[50] = {0};
char ctmp = tolower(param_getchar(Cmd, 0));
if ( strlen(Cmd) == 1 ) {
if ( param_getlength(Cmd, 0) == 1 ) {
if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload();
if (ctmp == 'e' ) fillFromEmulator = 1;
if (ctmp == 'j' ) fillFromJson = true;
if (ctmp == 'b' ) fillFromBin = true;
}
if (fillFromJson || fillFromBin)
param_getstr(Cmd, 1, fileName, sizeof(fileName));
if (fillFromEmulator) {
for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) {
@ -2658,10 +2669,19 @@ int CmdHF14AMfCLoad(const char *Cmd) {
return 0;
}
uint8_t *data = calloc(1, 4096);
size_t maxdatalen = 4096;
uint8_t *data = calloc(1, maxdatalen);
size_t datalen = 0;
//int res = loadFile(Cmd, "bin", data, &datalen);
int res = loadFileEML( Cmd, "eml", data, &datalen);
int res = 0;
if (fillFromBin) {
res = loadFile(fileName, "bin", data, &datalen);
} else {
if (fillFromJson) {
res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen);
} else {
res = loadFileEML( Cmd, "eml", data, &datalen);
}
}
if ( res ) {
free(data);
return 1;
@ -2878,6 +2898,7 @@ int CmdHF14AMfCSave(const char *Cmd) {
saveFile(filename, "bin", dump, bytes);
saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE);
saveFileJSON(filename, "json", jsfCardMemory, dump, bytes);
free(dump);
return 0;
}

View file

@ -135,9 +135,93 @@ out:
return retval;
}
int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen) {
//stub - for merlokk ;)
return 1;
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;
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
int num = 1;
sprintf(fileName,"%s.%s", preferredName, suffix);
while (fileExists(fileName)) {
sprintf(fileName,"%s-%d.%s", preferredName, num, suffix);
num++;
}
json_t *root = json_object();
JsonSaveStr(root, "Created", "proxmark3");
switch(ftype) {
case jsfRaw:
JsonSaveStr(root, "FileType", "raw");
JsonSaveBufAsHexCompact(root, "raw", data, datalen);
break;
case jsfCardMemory:
JsonSaveStr(root, "FileType", "mfcard");
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));
memset(path, 0x00, sizeof(path));
sprintf(path, "$.SectorKeys.%d.AccessConditionsText.UserData", mfSectorNum(i));
JsonSaveBufAsHexCompact(root, path, &adata[3], 1);
}
}
break;
}
int res = json_dump_file(root, fileName, JSON_INDENT(2));
if (res) {
PrintAndLog("ERROR: can't save the file: %s", fileName);
json_decref(root);
retval = 200;
goto out;
}
PrintAndLog("File `%s` saved.", fileName);
json_decref(root);
out:
free(fileName);
return retval;
}
int loadFile(const char *preferredName, const char *suffix, void* data, size_t* datalen) {
@ -253,10 +337,67 @@ out:
return retval;
}
int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t* datalen) {
//stub - for merlokk ;)
datalen = 0;
return 1;
int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen) {
*datalen = 0;
json_t *root;
json_error_t error;
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
sprintf(fileName,"%s.%s", preferredName, suffix);
root = json_load_file(fileName, 0, &error);
if (!root) {
PrintAndLog("ERROR: json (%s) error on line %d: %s", fileName, error.line, error.text);
retval = 2;
goto out;
}
if (!json_is_object(root)) {
PrintAndLog("ERROR: Invalid json (%s) format. root must be an object.", fileName);
retval = 3;
goto out;
}
uint8_t *udata = (uint8_t *)data;
char ctype[100] = {0};
JsonLoadStr(root, "$.FileType", ctype);
if (!strcmp(ctype, "raw")) {
JsonLoadBufAsHex(root, "$.raw", udata, maxdatalen, datalen);
}
if (!strcmp(ctype, "mfcard")) {
size_t sptr = 0;
for (int i = 0; i < 256; i++) {
if (sptr + 16 > maxdatalen) {
retval = 5;
goto out;
}
char path[30] = {0};
sprintf(path, "$.blocks.%d", i);
size_t len = 0;
JsonLoadBufAsHex(root, path, &udata[sptr], 16, &len);
if (!len)
break;
sptr += len;
}
*datalen = sptr;
}
PrintAndLog("Loaded JSON: (%s) OK.", fileName);
out:
json_decref(root);
free(fileName);
return retval;
}
#else //if we're on ARM

View file

@ -47,6 +47,13 @@
#include <sys/stat.h>
#include <stdarg.h>
#include "../ui.h"
#include "../emv/emvjson.h"
#include "mifare4.h"
typedef enum {
jsfRaw,
jsfCardMemory,
} JSONFileType;
int fileExists(const char *filename);
@ -84,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.
@ -121,10 +129,11 @@ extern int loadFileEML(const char *preferredName, const char *suffix, void* data
* @param preferredName
* @param suffix the file suffix. Leave out the ".".
* @param data The data array to store the loaded bytes from file
* @param maxdatalen maximum size of data array in bytes
* @param datalen the number of bytes loaded from file
* @return 0 for ok, 1 for failz
*/
extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t* datalen);
extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen);
#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args)
#else

View file

@ -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);

View file

@ -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);