rework a bit mfc mad
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
#include "jansson.h"
|
#include "jansson.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;
|
||||||
|
|
||||||
static int open_mad_file(json_t **root, bool verbose) {
|
static int open_mad_file(json_t **root, bool verbose) {
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ static int open_mad_file(json_t **root, bool verbose) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(SUCCESS, "Loaded file (%s) OK. %zu records.", path, json_array_size(*root));
|
PrintAndLogEx(SUCCESS, "Loaded file (%s) OK. %zu records.", path, json_array_size(*root));
|
||||||
out:
|
out:
|
||||||
free(path);
|
free(path);
|
||||||
@@ -74,93 +74,52 @@ static const char *mad_json_get_str(json_t *data, const char *name) {
|
|||||||
return cstr;
|
return cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mad_print(json_t **xroot, char *mad, bool verbose, char *out) {
|
static int print_aid_description(json_t *root, uint16_t aid, char *fmt, bool verbose) {
|
||||||
|
char lmad[7] = {0};
|
||||||
json_t *root = *xroot;
|
sprintf(lmad, "0x%04x", BSWAP_16(aid)); // must be lowercase
|
||||||
if (root == NULL) {
|
|
||||||
int res = open_mad_file(&root, verbose);
|
|
||||||
if (res != PM3_SUCCESS)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
*xroot = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
int retval = PM3_EUNDEF;
|
|
||||||
|
|
||||||
if (root == NULL)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
json_t *elm = NULL;
|
json_t *elm = NULL;
|
||||||
|
|
||||||
for (uint32_t idx = 0; idx < json_array_size(root); idx++) {
|
|
||||||
|
|
||||||
|
for (uint32_t idx = 0; idx < json_array_size(root); idx++) {
|
||||||
json_t *data = json_array_get(root, idx);
|
json_t *data = json_array_get(root, idx);
|
||||||
if (!json_is_object(data)) {
|
if (!json_is_object(data)) {
|
||||||
PrintAndLogEx(ERR, "data [%d] is not an object\n", idx);
|
PrintAndLogEx(ERR, "data [%d] is not an object\n", idx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fmad = mad_json_get_str(data, "mad");
|
const char *fmad = mad_json_get_str(data, "mad");
|
||||||
if (strcmp(mad, fmad) == 0) {
|
|
||||||
elm = data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
char lfmad[strlen(fmad) + 1];
|
char lfmad[strlen(fmad) + 1];
|
||||||
strcpy(lfmad, fmad);
|
strcpy(lfmad, fmad);
|
||||||
str_lower(lfmad);
|
str_lower(lfmad);
|
||||||
char lmad[strlen(mad) + 1];
|
|
||||||
strcpy(lmad, mad);
|
|
||||||
str_lower(lmad);
|
|
||||||
if (strcmp(lmad, lfmad) == 0) {
|
if (strcmp(lmad, lfmad) == 0) {
|
||||||
elm = data;
|
elm = data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elm == NULL)
|
if (elm == NULL) {
|
||||||
goto out;
|
PrintAndLogEx(INFO, fmt, " (unknown)");
|
||||||
|
return PM3_ENODATA;
|
||||||
retval = PM3_SUCCESS;
|
}
|
||||||
|
const char *vmad = mad_json_get_str(elm, "mad");
|
||||||
// print here
|
|
||||||
const char *application = mad_json_get_str(elm, "application");
|
const char *application = mad_json_get_str(elm, "application");
|
||||||
const char *company = mad_json_get_str(elm, "company");
|
const char *company = mad_json_get_str(elm, "company");
|
||||||
const char *vmad = mad_json_get_str(elm, "mad");
|
|
||||||
const char *provider = mad_json_get_str(elm, "service_provider");
|
const char *provider = mad_json_get_str(elm, "service_provider");
|
||||||
const char *integrator = mad_json_get_str(elm, "system_integrator");
|
const char *integrator = mad_json_get_str(elm, "system_integrator");
|
||||||
|
char result[4 + strlen(application) + strlen(company)];
|
||||||
sprintf(out, "%s [%s]", application, company);
|
sprintf(result, " %s [%s]", application, company);
|
||||||
|
PrintAndLogEx(INFO, fmt, result);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(SUCCESS, "MAD %s", vmad);
|
PrintAndLogEx(SUCCESS, " MAD: %s", vmad);
|
||||||
if (application)
|
if (application)
|
||||||
PrintAndLogEx(SUCCESS, "Application %s", application);
|
PrintAndLogEx(SUCCESS, " Application: %s", application);
|
||||||
if (company)
|
if (company)
|
||||||
PrintAndLogEx(SUCCESS, "Company %s", company);
|
PrintAndLogEx(SUCCESS, " Company: %s", company);
|
||||||
if (provider)
|
if (provider)
|
||||||
PrintAndLogEx(SUCCESS, "Service provider %s", provider);
|
PrintAndLogEx(SUCCESS, " Service provider: %s", provider);
|
||||||
if (integrator)
|
if (integrator)
|
||||||
PrintAndLogEx(SUCCESS, "System integrator %s", integrator);
|
PrintAndLogEx(SUCCESS, " System integrator: %s", integrator);
|
||||||
}
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
out:
|
|
||||||
if (*xroot == NULL) {
|
|
||||||
close_mad_file(root);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *get_aid_description(uint16_t aid, bool verbose) {
|
|
||||||
|
|
||||||
static char result[200];
|
|
||||||
char s[7] = {0};
|
|
||||||
sprintf(s, "0x%04X", aid);
|
|
||||||
int res = mad_print(&mad_known_aids, s, verbose, result);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int madCRCCheck(uint8_t *sector, bool verbose, int MADver) {
|
static int madCRCCheck(uint8_t *sector, bool verbose, int MADver) {
|
||||||
@@ -267,7 +226,17 @@ int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen
|
|||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *aid_admin[] = {
|
||||||
|
"free",
|
||||||
|
"defect",
|
||||||
|
"reserved",
|
||||||
|
"additional directory info",
|
||||||
|
"card holder info",
|
||||||
|
"not applicable"
|
||||||
|
};
|
||||||
|
|
||||||
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
|
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
|
||||||
|
open_mad_file(&mad_known_aids, verbose);
|
||||||
|
|
||||||
// check MAD1 only
|
// check MAD1 only
|
||||||
MADCheck(sector, NULL, verbose, haveMAD2);
|
MADCheck(sector, NULL, verbose, haveMAD2);
|
||||||
@@ -284,15 +253,26 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
|
|||||||
PrintAndLogEx(WARNING, "Info byte error");
|
PrintAndLogEx(WARNING, "Info byte error");
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " 00 MAD 1");
|
PrintAndLogEx(INFO, " 00 MAD 1");
|
||||||
|
uint32_t prev_aid = 0xFFFFFFFF;
|
||||||
for (int i = 1; i < 16; i++) {
|
for (int i = 1; i < 16; i++) {
|
||||||
uint16_t AID = madGetAID(sector, 1, i);
|
uint16_t aid = madGetAID(sector, 1, i);
|
||||||
PrintAndLogEx(INFO, " %02d [%04X] %s", i, AID, get_aid_description(AID, verbose));
|
if (aid < 6) {
|
||||||
|
PrintAndLogEx(INFO, " %02d [%04X] (%s)", i, aid, aid_admin[aid]);
|
||||||
|
} else if (prev_aid == aid) {
|
||||||
|
PrintAndLogEx(INFO, " %02d [%04X] (continuation)", i, aid);
|
||||||
|
} else {
|
||||||
|
char fmt[20];
|
||||||
|
sprintf(fmt, " %02d [%04X]%s", i, aid, "%s");
|
||||||
|
print_aid_description(mad_known_aids, aid, fmt, verbose);
|
||||||
|
prev_aid = aid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
close_mad_file(mad_known_aids);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
|
int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
|
||||||
|
open_mad_file(&mad_known_aids, verbose);
|
||||||
PrintAndLogEx(INFO, " 16 MAD 2");
|
PrintAndLogEx(INFO, " 16 MAD 2");
|
||||||
|
|
||||||
int res = madCRCCheck(sector, true, 2);
|
int res = madCRCCheck(sector, true, 2);
|
||||||
@@ -310,11 +290,21 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(WARNING, "Card publisher sector not present");
|
PrintAndLogEx(WARNING, "Card publisher sector not present");
|
||||||
}
|
}
|
||||||
|
uint32_t prev_aid = 0xFFFFFFFF;
|
||||||
for (int i = 1; i < 8 + 8 + 7 + 1; i++) {
|
for (int i = 1; i < 8 + 8 + 7 + 1; i++) {
|
||||||
uint16_t aid = madGetAID(sector, 2, i);
|
uint16_t aid = madGetAID(sector, 2, i);
|
||||||
PrintAndLogEx(INFO, "%02d [%04X] %s", i + 16, aid, get_aid_description(aid, verbose));
|
if (aid < 6) {
|
||||||
|
PrintAndLogEx(INFO, " %02d [%04X] (%s)", i + 16, aid, aid_admin[aid]);
|
||||||
|
} else if (prev_aid == aid) {
|
||||||
|
PrintAndLogEx(INFO, " %02d [%04X] (continuation)", i + 16, aid);
|
||||||
|
} else {
|
||||||
|
char fmt[20];
|
||||||
|
sprintf(fmt, " %02d [%04X]%s", i + 16, aid, "%s");
|
||||||
|
print_aid_description(mad_known_aids, aid, fmt, verbose);
|
||||||
|
prev_aid = aid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
close_mad_file(mad_known_aids);
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user