Mifare MAD Card Holder Information

This commit is contained in:
Lukas Kuzmiak 2020-06-09 18:34:59 -07:00
commit 9d71f66d16
4 changed files with 79 additions and 24 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Added Mifare MAD Card Holder Information decoding (@lukaskuzmiak)
- Change Better precision for HF and LF voltage measurements and Add theremin.py script (@rosco) - Change Better precision for HF and LF voltage measurements and Add theremin.py script (@rosco)
- Added Mifare MAD Info Byte decoding. Easier to identify Card Publisher (@lukaskuzmiak) - Added Mifare MAD Info Byte decoding. Easier to identify Card Publisher (@lukaskuzmiak)
- Change use system Bzip2 library instead of Zlib for hardnested tables, tables are now 7x smaller (@doegox) - Change use system Bzip2 library instead of Zlib for hardnested tables, tables are now 7x smaller (@doegox)

View file

@ -4500,6 +4500,7 @@ static int CmdHF14AMfMAD(const char *Cmd) {
arg_str0("kK", "key", "key for printing sectors", NULL), arg_str0("kK", "key", "key for printing sectors", NULL),
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
arg_lit0("", "be", "(optional, BigEndian)"), arg_lit0("", "be", "(optional, BigEndian)"),
arg_lit0("", "dch", "decode Card Holder information"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -4512,11 +4513,12 @@ static int CmdHF14AMfMAD(const char *Cmd) {
CLIGetHexWithReturn(ctx, 3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
bool keyB = arg_get_lit(4); bool keyB = arg_get_lit(4);
bool swapmad = arg_get_lit(5); bool swapmad = arg_get_lit(5);
bool decodeholder = arg_get_lit(6);
CLIParserFree(ctx); CLIParserFree(ctx);
if (aidlen != 2 && keylen > 0) { if (aidlen != 2 && !decodeholder && keylen > 0) {
PrintAndLogEx(WARNING, "do not need a key without aid"); PrintAndLogEx(WARNING, "do not need a key without aid/decode card holder");
} }
uint8_t sector0[16 * 4] = {0}; uint8_t sector0[16 * 4] = {0};
@ -4549,10 +4551,7 @@ static int CmdHF14AMfMAD(const char *Cmd) {
MAD2DecodeAndPrint(sector10, swapmad, verbose); MAD2DecodeAndPrint(sector10, swapmad, verbose);
} }
if (aidlen == 2) { if (aidlen == 2 || decodeholder) {
uint16_t aaid = (aid[0] << 8) + aid[1];
PrintAndLogEx(INFO, "-------------- " _CYAN_("AID 0x%04x") " ---------------", aaid);
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
size_t madlen = 0; size_t madlen = 0;
if (MADDecode(sector0, sector10, mad, &madlen, swapmad)) { if (MADDecode(sector0, sector10, mad, &madlen, swapmad)) {
@ -4566,6 +4565,10 @@ static int CmdHF14AMfMAD(const char *Cmd) {
memcpy(akey, key, 6); memcpy(akey, key, 6);
} }
if (aidlen == 2) {
uint16_t aaid = (aid[0] << 8) + aid[1];
PrintAndLogEx(INFO, "-------------- " _CYAN_("AID 0x%04x") " ---------------", aaid);
for (int i = 0; i < madlen; i++) { for (int i = 0; i < madlen; i++) {
if (aaid == mad[i]) { if (aaid == mad[i]) {
uint8_t vsector[16 * 4] = {0}; uint8_t vsector[16 * 4] = {0};
@ -4581,6 +4584,36 @@ static int CmdHF14AMfMAD(const char *Cmd) {
} }
} }
if (decodeholder) {
uint16_t aaid = 0x0004;
PrintAndLogEx(INFO, "-------- " _CYAN_("Card Holder Info 0x%04x") " --------", aaid);
uint8_t data[4096] = {0};
int datalen = 0;
for (int i = 0; i < madlen; i++) {
if (aaid == mad[i]) {
uint8_t vsector[16 * 4] = {0};
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(ERR, "error, read sector %d", i + 1);
return PM3_ESOFT;
}
memcpy(&data[datalen], vsector, 16 * 3);
datalen += 16 * 3;
}
}
if (!datalen) {
PrintAndLogEx(WARNING, "no Card Holder Info data");
return PM3_SUCCESS;
}
MADCardHolderInfoDecode(data, datalen, verbose);
}
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -232,15 +232,27 @@ 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[] = { static const char *holder_info_type[] = {
"free", "Surname",
"defect", "Given name",
"reserved", "Sex",
"additional directory info", "Other"
"card holder info",
"not applicable"
}; };
int MADCardHolderInfoDecode(uint8_t *data, size_t dataLen, bool verbose) {
size_t idx = 0;
while (idx < dataLen) {
uint8_t len = data[idx] & 0x3f;
uint8_t type = data[idx] >> 6;
idx++;
if (len > 0) {
PrintAndLogEx(INFO, "%s: %.*s", holder_info_type[type], len, &data[idx]);
idx += len;
} else break;
}
return PM3_SUCCESS;
}
static int MADInfoByteDecode(uint8_t *sector, bool swapmad, int MADver, bool verbose) { static int MADInfoByteDecode(uint8_t *sector, bool swapmad, int MADver, bool verbose) {
uint8_t InfoByte; uint8_t InfoByte;
if (MADver == 1) { if (MADver == 1) {
@ -269,6 +281,15 @@ static int MADInfoByteDecode(uint8_t *sector, bool swapmad, int MADver, bool ver
} }
} }
static const char *aid_admin[] = {
"free",
"defect",
"reserved",
"additional directory info",
"card holder info",
"not applicable"
};
int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2) { int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2) {
open_mad_file(&mad_known_aids, verbose); open_mad_file(&mad_known_aids, verbose);

View file

@ -17,6 +17,6 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2);
int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen, bool swapmad); int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen, bool swapmad);
int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2); int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2);
int MAD2DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose); int MAD2DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose);
int MADCardHolderInfoDecode(uint8_t *data, size_t dataLen, bool verbose);
#endif // _MAD_H_ #endif // _MAD_H_