diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c
index 43c8d645d..e6363d64c 100644
--- a/client/cmdhfmfp.c
+++ b/client/cmdhfmfp.c
@@ -643,20 +643,38 @@ int CmdHFMFPMAD(const char *cmd) {
 
 	CLIParserInit("hf mfp 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[] = {
 		arg_param_begin,
 		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
 	};
 	CLIExecWithReturn(cmd, argtable, true);
+	
 	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();
+	
+	if (aidlen != 2 && keylen > 0) {
+		PrintAndLogEx(WARNING, "do not need a key without aid.");
+	}
 
-	uint8_t sector[16 * 4] = {0};
-	if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) {
+	uint8_t sector0[16 * 4] = {0};
+	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(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
 		return 2;
@@ -664,20 +682,52 @@ int CmdHFMFPMAD(const char *cmd) {
 	
 	if (verbose) {
 		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;
-	MAD1DecodeAndPrint(sector, verbose, &haveMAD2);
+	MAD1DecodeAndPrint(sector0, verbose, &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(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
 			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;
diff --git a/client/mifare/mad.c b/client/mifare/mad.c
index ff6991f22..34ea50cfc 100644
--- a/client/mifare/mad.c
+++ b/client/mifare/mad.c
@@ -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]);	
 }
 
-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];
-	PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB);
+	uint8_t GPB = sector0[3 * 16 + 9];
+	if (verbose)
+		PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB);
 	
 	// DA (MAD available)
 	if (!(GPB & 0x80)) {
@@ -146,13 +149,16 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
 	}
 	
 	// MA (multi-application card)
-	if (GPB & 0x40)
-		PrintAndLogEx(NORMAL, "Multi application card.");
-	else
-		PrintAndLogEx(NORMAL, "Single application card.");
+	if (verbose) {
+		if (GPB & 0x40)
+			PrintAndLogEx(NORMAL, "Multi application card.");
+		else
+			PrintAndLogEx(NORMAL, "Single application card.");
+	}
 	
 	uint8_t MADVer = GPB & 0x03;
-	PrintAndLogEx(NORMAL, "MAD version: %d", MADVer);
+	if (verbose)
+		PrintAndLogEx(NORMAL, "MAD version: %d", MADVer);
 	
 	//  MAD version
 	if ((MADVer != 0x01) && (MADVer != 0x02)) {
@@ -163,7 +169,56 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
 	if (haveMAD2)
 		*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)
 		return res;	
 	
diff --git a/client/mifare/mad.h b/client/mifare/mad.h
index dc2b2e3c0..ee362adb6 100644
--- a/client/mifare/mad.h
+++ b/client/mifare/mad.h
@@ -19,8 +19,10 @@ typedef struct {
 	const char *Description;
 } madAIDDescr;	
 
-int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2);
-int MAD2DecodeAndPrint(uint8_t *sector, bool verbose);
+extern int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2);
+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_
diff --git a/client/mifare/mifaredefault.h b/client/mifare/mifaredefault.h
index e7218cbe7..b12a57c03 100644
--- a/client/mifare/mifaredefault.h
+++ b/client/mifare/mifaredefault.h
@@ -42,8 +42,9 @@ static const uint64_t g_mifare_default_keys[] =
 	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_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