mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-15 03:34:22 +08:00
Merge branch 'master' of https://github.com/RfidResearchGroup/proxmark3
This commit is contained in:
commit
3c88bb5e59
5 changed files with 238 additions and 14 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue