Merge pull request #107 from merlokk/mad_read

Mad read
This commit is contained in:
Oleg Moiseenko 2019-03-04 19:45:58 +02:00 committed by GitHub
commit 6fa81303a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 185 additions and 28 deletions

View file

@ -3219,39 +3219,87 @@ int CmdHF14AMfMAD(const char *cmd) {
CLIParserInit("hf mf mad", CLIParserInit("hf mf mad",
"Checks and prints Mifare Application Directory (MAD)", "Checks and prints Mifare Application Directory (MAD)",
"Usage:\n\thf mf mad -> shows MAD if exists\n"); "Usage:\n\thf mf mad -> shows MAD if exists\n"
"\thf mf mad -a 03e1 -k d3f7d3f7d3f7 -> shows NDEF data if exists\n");
void* argtable[] = { void* argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("vV", "verbose", "show technical data"), arg_lit0("vV", "verbose", "show technical data"),
arg_str0("aA", "aid", "print all sectors with aid", 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_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
uint8_t aid[2] = {0};
int aidlen;
CLIGetHexWithReturn(2, aid, &aidlen);
uint8_t key[6] = {0};
int keylen;
CLIGetHexWithReturn(3, key, &keylen);
bool keyB = arg_get_lit(4);
CLIParserFree(); CLIParserFree();
uint8_t sector[16 * 4] = {0}; if (aidlen != 2 && keylen > 0) {
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { PrintAndLogEx(WARNING, "do not need a key without aid.");
}
uint8_t sector0[16 * 4] = {0};
uint8_t sector10[16 * 4] = {0};
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) {
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
return 2; return 2;
} }
if (verbose) { if (verbose) {
for(int i = 0; i < 4; i ++) for(int i = 0; i < 4; i ++)
PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(&sector[i * 16], 16)); PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(&sector0[i * 16], 16));
} }
bool haveMAD2 = false; bool haveMAD2 = false;
MAD1DecodeAndPrint(sector, verbose, &haveMAD2); MAD1DecodeAndPrint(sector0, verbose, &haveMAD2);
if (haveMAD2) { if (haveMAD2) {
if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) {
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
return 2; return 2;
} }
MAD2DecodeAndPrint(sector, verbose); MAD2DecodeAndPrint(sector10, verbose);
}
if (aidlen == 2) {
uint16_t aaid = (aid[0] << 8) + aid[1];
PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid);
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
size_t madlen = 0;
if (MADDecode(sector0, sector10, mad, &madlen)) {
PrintAndLogEx(ERR, "can't decode mad.");
return 10;
}
uint8_t akey[6] = {0};
memcpy(akey, g_mifare_ndef_key, 6);
if (keylen == 6) {
memcpy(akey, key, 6);
}
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, "read sector %d error.", i + 1);
return 2;
}
for(int j = 0; j < (verbose ? 4 : 3); j ++)
PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16));
}
}
} }
return 0; return 0;

View file

@ -643,20 +643,38 @@ int CmdHFMFPMAD(const char *cmd) {
CLIParserInit("hf mfp mad", CLIParserInit("hf mfp mad",
"Checks and prints Mifare Application Directory (MAD)", "Checks and prints Mifare Application Directory (MAD)",
"Usage:\n\thf mfp mad -> shows MAD if exists\n"); "Usage:\n\thf mfp mad -> shows MAD if exists\n"
"\thf mfp mad -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists\n");
void* argtable[] = { void* argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("vV", "verbose", "show technical data"), arg_lit0("vV", "verbose", "show technical data"),
arg_str0("aA", "aid", "print all sectors with aid", 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_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
uint8_t aid[2] = {0};
int aidlen;
CLIGetHexWithReturn(2, aid, &aidlen);
uint8_t key[16] = {0};
int keylen;
CLIGetHexWithReturn(3, key, &keylen);
bool keyB = arg_get_lit(4);
CLIParserFree(); CLIParserFree();
if (aidlen != 2 && keylen > 0) {
PrintAndLogEx(WARNING, "do not need a key without aid.");
}
uint8_t sector[16 * 4] = {0}; uint8_t sector0[16 * 4] = {0};
if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) { uint8_t sector10[16 * 4] = {0};
if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
return 2; return 2;
@ -664,20 +682,52 @@ int CmdHFMFPMAD(const char *cmd) {
if (verbose) { if (verbose) {
for(int i = 0; i < 4; i ++) for(int i = 0; i < 4; i ++)
PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(&sector[i * 16], 16)); PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(&sector0[i * 16], 16));
} }
bool haveMAD2 = false; bool haveMAD2 = false;
MAD1DecodeAndPrint(sector, verbose, &haveMAD2); MAD1DecodeAndPrint(sector0, verbose, &haveMAD2);
if (haveMAD2) { if (haveMAD2) {
if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) { if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
return 2; return 2;
} }
MAD2DecodeAndPrint(sector, verbose); MAD2DecodeAndPrint(sector10, verbose);
}
if (aidlen == 2) {
uint16_t aaid = (aid[0] << 8) + aid[1];
PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid);
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
size_t madlen = 0;
if (MADDecode(sector0, sector10, mad, &madlen)) {
PrintAndLogEx(ERR, "can't decode mad.");
return 10;
}
uint8_t akey[16] = {0};
memcpy(akey, g_mifarep_ndef_key, 16);
if (keylen == 16) {
memcpy(akey, key, 16);
}
for (int i = 0; i < madlen; i++) {
if (aaid == mad[i]) {
uint8_t vsector[16 * 4] = {0};
if (mfpReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector, false)) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
return 2;
}
for(int j = 0; j < (verbose ? 4 : 3); j ++)
PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16));
}
}
} }
return 0; return 0;

View file

@ -134,10 +134,13 @@ uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) {
return (sector[2 + (sectorNo - 1) * 2] << 8) + (sector[2 + (sectorNo - 1) * 2 + 1]); return (sector[2 + (sectorNo - 1) * 2] << 8) + (sector[2 + (sectorNo - 1) * 2 + 1]);
} }
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) {
if (!sector0)
return 1;
uint8_t GPB = sector[3 * 16 + 9]; uint8_t GPB = sector0[3 * 16 + 9];
PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB); if (verbose)
PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB);
// DA (MAD available) // DA (MAD available)
if (!(GPB & 0x80)) { if (!(GPB & 0x80)) {
@ -146,13 +149,16 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
} }
// MA (multi-application card) // MA (multi-application card)
if (GPB & 0x40) if (verbose) {
PrintAndLogEx(NORMAL, "Multi application card."); if (GPB & 0x40)
else PrintAndLogEx(NORMAL, "Multi application card.");
PrintAndLogEx(NORMAL, "Single application card."); else
PrintAndLogEx(NORMAL, "Single application card.");
}
uint8_t MADVer = GPB & 0x03; uint8_t MADVer = GPB & 0x03;
PrintAndLogEx(NORMAL, "MAD version: %d", MADVer); if (verbose)
PrintAndLogEx(NORMAL, "MAD version: %d", MADVer);
// MAD version // MAD version
if ((MADVer != 0x01) && (MADVer != 0x02)) { if ((MADVer != 0x01) && (MADVer != 0x02)) {
@ -163,7 +169,56 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
if (haveMAD2) if (haveMAD2)
*haveMAD2 = (MADVer == 2); *haveMAD2 = (MADVer == 2);
int res = madCRCCheck(sector, true, 1); int res = madCRCCheck(sector0, true, 1);
if (res)
return res;
if (verbose)
PrintAndLogEx(NORMAL, "CRC8-MAD1 OK.");
if (MADVer == 2 && sector10) {
int res = madCRCCheck(sector10, true, 2);
if (res)
return res;
if (verbose)
PrintAndLogEx(NORMAL, "CRC8-MAD2 OK.");
}
return 0;
}
int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen) {
*madlen = 0;
bool haveMAD2 = false;
int res = MADCheck(sector0, sector10, false, &haveMAD2);
if (res)
return res;
for (int i = 1; i < 16; i++) {
mad[*madlen] = madGetAID(sector0, 1, i);
(*madlen)++;
}
if (haveMAD2) {
// mad2 sector (0x10 == 16dec) here
mad[*madlen] = 0x0005;
(*madlen)++;
for (int i = 1; i < 24; i++) {
mad[*madlen] = madGetAID(sector10, 2, i);
(*madlen)++;
}
}
return 0;
}
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
// check MAD1 only
int res = MADCheck(sector, NULL, verbose, haveMAD2);
if (res) if (res)
return res; return res;

View file

@ -19,8 +19,10 @@ typedef struct {
const char *Description; const char *Description;
} madAIDDescr; } madAIDDescr;
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2); extern int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2);
int MAD2DecodeAndPrint(uint8_t *sector, bool verbose); extern int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen);
extern int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2);
extern int MAD2DecodeAndPrint(uint8_t *sector, bool verbose);
#endif // _MAD_H_ #endif // _MAD_H_

View file

@ -302,7 +302,8 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF
memmove(session->Kmac, kmac, 16); memmove(session->Kmac, kmac, 16);
} }
PrintAndLogEx(INFO, "Authentication OK"); if (verbose)
PrintAndLogEx(INFO, "Authentication OK");
return 0; return 0;
} }

View file

@ -42,8 +42,9 @@ static const uint64_t g_mifare_default_keys[] =
0x96a301bce267 0x96a301bce267
}; };
static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5};
static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7};
static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7};
static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7};
#endif #endif