mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
Merge remote-tracking branch 'public/master' into mifare-mad-fix
This commit is contained in:
commit
3cbad6fa4c
5 changed files with 127 additions and 104 deletions
|
@ -741,7 +741,6 @@ D3A297DC2698
|
||||||
9EA3387A63C1
|
9EA3387A63C1
|
||||||
A3FAA6DAFF67
|
A3FAA6DAFF67
|
||||||
A7141147D430
|
A7141147D430
|
||||||
AAFB06045877
|
|
||||||
ACFFFFFFFFFF
|
ACFFFFFFFFFF
|
||||||
AFCEF64C9913
|
AFCEF64C9913
|
||||||
B27ADDFB64B0
|
B27ADDFB64B0
|
||||||
|
@ -763,7 +762,6 @@ FD8705E721B0
|
||||||
00ada2cd516d
|
00ada2cd516d
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
D3F7D3F7D3F7
|
|
||||||
##
|
##
|
||||||
237a4d0d9119
|
237a4d0d9119
|
||||||
0ed7846c2bc9
|
0ed7846c2bc9
|
||||||
|
@ -1068,7 +1066,6 @@ a2a3cca2a3cc
|
||||||
385efa542907
|
385efa542907
|
||||||
3864fcba5937
|
3864fcba5937
|
||||||
3f3865fccb69
|
3f3865fccb69
|
||||||
5c8ff9990da2
|
|
||||||
6291b3860fc8
|
6291b3860fc8
|
||||||
63fca9492f38
|
63fca9492f38
|
||||||
863fcb959373
|
863fcb959373
|
||||||
|
@ -1114,7 +1111,6 @@ fe04ecfe5577
|
||||||
5a7a52d5e20d # Bosch Solution 6000
|
5a7a52d5e20d # Bosch Solution 6000
|
||||||
#
|
#
|
||||||
# Found in TagInfo app
|
# Found in TagInfo app
|
||||||
8A19D40CF2B5 # Hotel key card key
|
|
||||||
C1E51C63B8F5 # RATB key
|
C1E51C63B8F5 # RATB key
|
||||||
1DB710648A65
|
1DB710648A65
|
||||||
18F34C92A56E # E-GO card key
|
18F34C92A56E # E-GO card key
|
||||||
|
|
|
@ -1256,7 +1256,7 @@ int CmdHF14A(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printTag(const char *tag) {
|
static void printTag(const char *tag) {
|
||||||
PrintAndLogEx(SUCCESS, "POSSIBLE TYPE:" _YELLOW_(" %s"), tag);
|
PrintAndLogEx(SUCCESS, " " _YELLOW_("%s"), tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1274,6 +1274,8 @@ typedef enum {
|
||||||
static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
||||||
int type = MTNONE;
|
int type = MTNONE;
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Possible types:");
|
||||||
|
|
||||||
if (sak == 0x00) {
|
if (sak == 0x00) {
|
||||||
printTag("NTAG 20x / 21x / 21x TT / I2C plus");
|
printTag("NTAG 20x / 21x / 21x TT / I2C plus");
|
||||||
printTag("MIFARE Ultralight / C / EV1 / Nano");
|
printTag("MIFARE Ultralight / C / EV1 / Nano");
|
||||||
|
@ -1284,10 +1286,12 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
||||||
printTag("TNP3xxx (Activision Game Appliance)");
|
printTag("TNP3xxx (Activision Game Appliance)");
|
||||||
type = MTCLASSIC;
|
type = MTCLASSIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x04) == 0x04) {
|
if ((sak & 0x04) == 0x04) {
|
||||||
printTag("Any MIFARE CL1 / NTAG424DNA");
|
printTag("Any MIFARE CL1 / NTAG424DNA");
|
||||||
type |= MTDESFIRE;
|
type |= MTDESFIRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x08) == 0x08) {
|
if ((sak & 0x08) == 0x08) {
|
||||||
printTag("MIFARE Classic 1K / Classic 1K CL2");
|
printTag("MIFARE Classic 1K / Classic 1K CL2");
|
||||||
printTag("MIFARE Plus 2K / Plus EV1 2K");
|
printTag("MIFARE Plus 2K / Plus EV1 2K");
|
||||||
|
@ -1295,18 +1299,22 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
||||||
type |= MTCLASSIC;
|
type |= MTCLASSIC;
|
||||||
type |= MTPLUS;
|
type |= MTPLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x09) == 0x09) {
|
if ((sak & 0x09) == 0x09) {
|
||||||
printTag("MIFARE Mini 0.3K / Mini CL2 0.3K");
|
printTag("MIFARE Mini 0.3K / Mini CL2 0.3K");
|
||||||
type |= MTMINI;
|
type |= MTMINI;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x10) == 0x10) {
|
if ((sak & 0x10) == 0x10) {
|
||||||
printTag("MIFARE Plus 2K / Plus CL2 2K");
|
printTag("MIFARE Plus 2K / Plus CL2 2K");
|
||||||
type |= MTPLUS;
|
type |= MTPLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x11) == 0x11) {
|
if ((sak & 0x11) == 0x11) {
|
||||||
printTag("MIFARE Plus 4K / Plus CL2 4K");
|
printTag("MIFARE Plus 4K / Plus CL2 4K");
|
||||||
type |= MTPLUS;
|
type |= MTPLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x18) == 0x18) {
|
if ((sak & 0x18) == 0x18) {
|
||||||
if (atqa == 0x0042) {
|
if (atqa == 0x0042) {
|
||||||
printTag("MIFARE Plus 4K / Plus EV1 4K");
|
printTag("MIFARE Plus 4K / Plus EV1 4K");
|
||||||
|
@ -1316,8 +1324,8 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
||||||
printTag("MIFARE Classic 4K / Classic 4K CL2");
|
printTag("MIFARE Classic 4K / Classic 4K CL2");
|
||||||
type |= MTCLASSIC;
|
type |= MTCLASSIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x20) == 0x20) {
|
if ((sak & 0x20) == 0x20) {
|
||||||
if (atqa == 0x0344) {
|
if (atqa == 0x0344) {
|
||||||
printTag("MIFARE DESFire EV1 2K/4K/8K / DESFire EV1 CL2 2K/4K/8K");
|
printTag("MIFARE DESFire EV1 2K/4K/8K / DESFire EV1 CL2 2K/4K/8K");
|
||||||
|
@ -1332,18 +1340,25 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) {
|
||||||
type |= MTPLUS;
|
type |= MTPLUS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x24) == 0x24) {
|
if ((sak & 0x24) == 0x24) {
|
||||||
if (atqa == 0x0344) {
|
if (atqa == 0x0344) {
|
||||||
printTag("MIFARE DESFire CL1 / DESFire EV1 CL1");
|
printTag("MIFARE DESFire CL1 / DESFire EV1 CL1");
|
||||||
type |= MTDESFIRE;
|
type |= MTDESFIRE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sak & 0x28) == 0x28) {
|
if ((sak & 0x28) == 0x28) {
|
||||||
if (atqa == 0x0344) {
|
if (atqa == 0x0344) {
|
||||||
printTag("MIFARE DESFire CL1 / DESFire EV1 CL1");
|
printTag("MIFARE DESFire CL1 / DESFire EV1 CL1");
|
||||||
type |= MTDESFIRE;
|
type |= MTDESFIRE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == MTNONE) {
|
||||||
|
PrintAndLogEx(WARNING, " failed to fingerprint");
|
||||||
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1351,9 +1366,9 @@ typedef struct {
|
||||||
uint8_t uid0;
|
uint8_t uid0;
|
||||||
uint8_t uid1;
|
uint8_t uid1;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
} uidname;
|
} uid_label_name;
|
||||||
|
|
||||||
const uidname uidmap[] = {
|
const uid_label_name uid_label_map[] = {
|
||||||
// UID0, UID1, TEXT
|
// UID0, UID1, TEXT
|
||||||
{0x02, 0x84, "M24SR64-Y"},
|
{0x02, 0x84, "M24SR64-Y"},
|
||||||
{0x02, 0xA3, "25TA02KB-P"},
|
{0x02, 0xA3, "25TA02KB-P"},
|
||||||
|
@ -1367,14 +1382,13 @@ const uidname uidmap[] = {
|
||||||
|
|
||||||
static void getTagLabel(uint8_t uid0, uint8_t uid1) {
|
static void getTagLabel(uint8_t uid0, uint8_t uid1) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (uidmap[i].uid0 != 0x00) {
|
while (uid_label_map[i].uid0 != 0x00) {
|
||||||
if ((uidmap[i].uid0 == uid0) && (uidmap[i].uid1 == uid1)) {
|
if ((uid_label_map[i].uid0 == uid0) && (uid_label_map[i].uid1 == uid1)) {
|
||||||
PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uidmap[i].desc);
|
PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uid_label_map[i].desc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
|
@ -1414,7 +1428,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(SUCCESS, "-- ISO14443-a Information -----------------------------------");
|
PrintAndLogEx(SUCCESS, "------ " _CYAN_("ISO14443-a Information") "------------------");
|
||||||
PrintAndLogEx(SUCCESS, "-------------------------------------------------------------");
|
PrintAndLogEx(SUCCESS, "-------------------------------------------------------------");
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||||
|
@ -1426,7 +1440,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
bool isMifarePlus = false;
|
bool isMifarePlus = false;
|
||||||
bool isMifareUltralight = false;
|
bool isMifareUltralight = false;
|
||||||
int nxptype = MTNONE;
|
int nxptype = MTNONE;
|
||||||
// Double & triple sized UID, can be mapped to a manufacturer.
|
|
||||||
if (card.uidlen <= 4) {
|
if (card.uidlen <= 4) {
|
||||||
nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]));
|
nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]));
|
||||||
|
|
||||||
|
@ -1437,9 +1451,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
|
|
||||||
if ((nxptype & MTOTHER) == MTOTHER)
|
if ((nxptype & MTOTHER) == MTOTHER)
|
||||||
isMifareClassic = true;
|
isMifareClassic = true;
|
||||||
}
|
|
||||||
if (card.uidlen > 4) {
|
} else {
|
||||||
|
|
||||||
|
// Double & triple sized UID, can be mapped to a manufacturer.
|
||||||
PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0]));
|
PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0]));
|
||||||
|
|
||||||
switch (card.uid[0]) {
|
switch (card.uid[0]) {
|
||||||
case 0x04: // NXP
|
case 0x04: // NXP
|
||||||
nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]));
|
nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]));
|
||||||
|
@ -1756,16 +1773,6 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
|
PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMifareUltralight) {
|
|
||||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`"));
|
|
||||||
}
|
|
||||||
if (isMifarePlus) {
|
|
||||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`"));
|
|
||||||
}
|
|
||||||
if (isMifareDESFire) {
|
|
||||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMifareClassic || isMifareUltralight) {
|
if (isMifareClassic || isMifareUltralight) {
|
||||||
detect_classic_magic();
|
detect_classic_magic();
|
||||||
|
|
||||||
|
@ -1790,6 +1797,15 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isMifareUltralight)
|
||||||
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`"));
|
||||||
|
|
||||||
|
if (isMifarePlus)
|
||||||
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`"));
|
||||||
|
|
||||||
|
if (isMifareDESFire)
|
||||||
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`"));
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return select_status;
|
return select_status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4496,7 +4496,7 @@ static int CmdHF14AMfMAD(const char *Cmd) {
|
||||||
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("aA", "aid", "print all sectors with specified aid", NULL),
|
||||||
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_param_end
|
arg_param_end
|
||||||
|
@ -4543,7 +4543,7 @@ static int CmdHF14AMfMAD(const char *Cmd) {
|
||||||
|
|
||||||
if (aidlen == 2) {
|
if (aidlen == 2) {
|
||||||
uint16_t aaid = (aid[0] << 8) + aid[1];
|
uint16_t aaid = (aid[0] << 8) + aid[1];
|
||||||
PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid);
|
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;
|
||||||
|
@ -4621,58 +4621,57 @@ static int CmdHFMFNDEF(const char *Cmd) {
|
||||||
uint8_t data[4096] = {0};
|
uint8_t data[4096] = {0};
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) {
|
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, "error, read sector 0. card don't have MAD or don't have MAD on default keys");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool haveMAD2 = false;
|
bool haveMAD2 = false;
|
||||||
int res = MADCheck(sector0, NULL, verbose, &haveMAD2);
|
int res = MADCheck(sector0, NULL, verbose, &haveMAD2);
|
||||||
if (res) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "MAD error %d.", res);
|
PrintAndLogEx(ERR, "MAD error %d", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveMAD2) {
|
if (haveMAD2) {
|
||||||
if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) {
|
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, "error, read sector 0x10. card don't have MAD or don't have MAD on default keys");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, (haveMAD2 ? sector10 : NULL), mad, &madlen)) {
|
res = MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen);
|
||||||
PrintAndLogEx(ERR, "can't decode mad.");
|
if (res != PM3_SUCCESS) {
|
||||||
return PM3_ESOFT;
|
PrintAndLogEx(ERR, "can't decode MAD");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("data reading:");
|
PrintAndLogEx(INFO, "data reading:");
|
||||||
for (int i = 0; i < madlen; i++) {
|
for (int i = 0; i < madlen; i++) {
|
||||||
if (ndefAID == mad[i]) {
|
if (ndefAID == mad[i]) {
|
||||||
uint8_t vsector[16 * 4] = {0};
|
uint8_t vsector[16 * 4] = {0};
|
||||||
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) {
|
if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) {
|
||||||
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
|
PrintAndLogEx(ERR, "error, reading sector %d ", i + 1);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&data[datalen], vsector, 16 * 3);
|
memcpy(&data[datalen], vsector, 16 * 3);
|
||||||
datalen += 16 * 3;
|
datalen += 16 * 3;
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(INPLACE, ".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(" OK\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (!datalen) {
|
if (!datalen) {
|
||||||
PrintAndLogEx(ERR, "no NDEF data.");
|
PrintAndLogEx(WARNING, "no NDEF data");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose2) {
|
if (verbose2) {
|
||||||
PrintAndLogEx(NORMAL, "NDEF data:");
|
PrintAndLogEx(SUCCESS, "NDEF data:");
|
||||||
dump_buffer(data, datalen, stdout, 1);
|
dump_buffer(data, datalen, stdout, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1423,63 +1423,61 @@ static int CmdHFMFPNDEF(const char *Cmd) {
|
||||||
uint8_t data[4096] = {0};
|
uint8_t data[4096] = {0};
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) {
|
if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) {
|
||||||
PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys.");
|
PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't have MAD on default keys");
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool haveMAD2 = false;
|
bool haveMAD2 = false;
|
||||||
int res = MADCheck(sector0, NULL, verbose, &haveMAD2);
|
int res = MADCheck(sector0, NULL, verbose, &haveMAD2);
|
||||||
if (res) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "MAD error %d.", res);
|
PrintAndLogEx(ERR, "MAD error %d", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveMAD2) {
|
if (haveMAD2) {
|
||||||
if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) {
|
if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) {
|
||||||
PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys.");
|
PrintAndLogEx(ERR, "error, read sector 0x10. card don't have MAD or don't have MAD on default keys");
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, (haveMAD2 ? sector10 : NULL), mad, &madlen)) {
|
res = MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen);
|
||||||
PrintAndLogEx(ERR, "can't decode mad.");
|
if (res != PM3_SUCCESS) {
|
||||||
return 10;
|
PrintAndLogEx(ERR, "can't decode MAD");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("data reading:");
|
PrintAndLogEx(INFO, "data reading:");
|
||||||
for (int i = 0; i < madlen; i++) {
|
for (int i = 0; i < madlen; i++) {
|
||||||
if (ndefAID == mad[i]) {
|
if (ndefAID == mad[i]) {
|
||||||
uint8_t vsector[16 * 4] = {0};
|
uint8_t vsector[16 * 4] = {0};
|
||||||
if (mfpReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector, false)) {
|
if (mfpReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector, false)) {
|
||||||
PrintAndLogEx(ERR, "read sector %d error.", i + 1);
|
PrintAndLogEx(ERR, "error, reading sector %d", i + 1);
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&data[datalen], vsector, 16 * 3);
|
memcpy(&data[datalen], vsector, 16 * 3);
|
||||||
datalen += 16 * 3;
|
datalen += 16 * 3;
|
||||||
|
|
||||||
printf(".");
|
PrintAndLogEx(INPLACE, ".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(" OK\n");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (!datalen) {
|
if (!datalen) {
|
||||||
PrintAndLogEx(ERR, "no NDEF data.");
|
PrintAndLogEx(ERR, "no NDEF data");
|
||||||
return 11;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose2) {
|
if (verbose2) {
|
||||||
PrintAndLogEx(NORMAL, "NDEF data:");
|
PrintAndLogEx(INFO, "NDEF data:");
|
||||||
dump_buffer(data, datalen, stdout, 1);
|
dump_buffer(data, datalen, stdout, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NDEFDecodeAndPrint(data, datalen, verbose);
|
NDEFDecodeAndPrint(data, datalen, verbose);
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "mad.h"
|
#include "mad.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "commonutil.h" // ARRAYLEN
|
#include "commonutil.h" // ARRAYLEN
|
||||||
|
#include "pm3_cmd.h"
|
||||||
#include "crc.h"
|
#include "crc.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -110,21 +110,20 @@ static const char *GetAIDDescription(uint16_t AID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int madCRCCheck(uint8_t *sector, bool verbose, int MADver) {
|
static int madCRCCheck(uint8_t *sector, bool verbose, int MADver) {
|
||||||
if (MADver == 1) {
|
if (MADver == 2) {
|
||||||
uint8_t crc = CRC8Mad(§or[16 + 1], 15 + 16);
|
uint8_t crc = CRC8Mad(§or[16 + 1], 15 + 16);
|
||||||
if (crc != sector[16]) {
|
if (crc != sector[16]) {
|
||||||
PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]);
|
PrintAndLogEx(WARNING, _RED_("Wrong MAD %d CRC") " calculated: 0x%02x != 0x%02x", MADver, crc, sector[16]);
|
||||||
return 3;
|
return PM3_ESOFT;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
uint8_t crc = CRC8Mad(§or[1], 15 + 16 + 16);
|
uint8_t crc = CRC8Mad(§or[1], 15 + 16 + 16);
|
||||||
if (crc != sector[0]) {
|
if (crc != sector[0]) {
|
||||||
PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]);
|
PrintAndLogEx(WARNING, _RED_("Wrong MAD %d CRC") " calculated: 0x%02x != 0x%02x", MADver, crc, sector[16]);
|
||||||
return 3;
|
return PM3_ESOFT;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) {
|
static uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) {
|
||||||
|
@ -135,54 +134,53 @@ static uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) {
|
int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) {
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
if (!sector0)
|
if (sector0 == NULL)
|
||||||
return 1;
|
return PM3_EINVARG;
|
||||||
|
|
||||||
uint8_t GPB = sector0[3 * 16 + 9];
|
uint8_t GPB = sector0[3 * 16 + 9];
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB);
|
PrintAndLogEx(INFO, "GPB: 0x%02x", GPB);
|
||||||
|
|
||||||
// DA (MAD available)
|
// DA (MAD available)
|
||||||
if (!(GPB & 0x80)) {
|
if (!(GPB & 0x80)) {
|
||||||
PrintAndLogEx(ERR, "DA=0! MAD not available.");
|
PrintAndLogEx(ERR, "DA=0! MAD not available.");
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MA (multi-application card)
|
// MA (multi-application card)
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (GPB & 0x40)
|
if (GPB & 0x40)
|
||||||
PrintAndLogEx(NORMAL, "Multi application card.");
|
PrintAndLogEx(INFO, "Multi application card.");
|
||||||
else
|
else
|
||||||
PrintAndLogEx(NORMAL, "Single application card.");
|
PrintAndLogEx(INFO, "Single application card.");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t MADVer = GPB & 0x03;
|
uint8_t MADVer = GPB & 0x03;
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(NORMAL, "MAD version: %d", MADVer);
|
PrintAndLogEx(INFO, "MAD version: %d", MADVer);
|
||||||
|
|
||||||
// MAD version
|
// MAD version
|
||||||
if ((MADVer != 0x01) && (MADVer != 0x02)) {
|
if ((MADVer != 0x01) && (MADVer != 0x02)) {
|
||||||
PrintAndLogEx(ERR, "Wrong MAD version: 0x%02x", MADVer);
|
PrintAndLogEx(ERR, "Wrong MAD version: 0x%02x", MADVer);
|
||||||
return 2;
|
return PM3_ESOFT;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (haveMAD2)
|
if (haveMAD2)
|
||||||
*haveMAD2 = (MADVer == 2);
|
*haveMAD2 = (MADVer == 2);
|
||||||
|
|
||||||
res = madCRCCheck(sector0, true, 1);
|
int res = madCRCCheck(sector0, true, 1);
|
||||||
|
|
||||||
if (verbose && !res)
|
if (verbose && res == PM3_SUCCESS)
|
||||||
PrintAndLogEx(NORMAL, "CRC8-MAD1 OK.");
|
PrintAndLogEx(INFO, "CRC8-MAD1 (%s)", _GREEN_("ok"));
|
||||||
|
|
||||||
if (MADVer == 2 && sector10) {
|
if (MADVer == 2 && sector10) {
|
||||||
int res2 = madCRCCheck(sector10, true, 2);
|
int res2 = madCRCCheck(sector10, true, 2);
|
||||||
if (!res)
|
if (res == PM3_SUCCESS)
|
||||||
res = res2;
|
res = res2;
|
||||||
|
|
||||||
if (verbose && !res2)
|
if (verbose && !res2)
|
||||||
PrintAndLogEx(NORMAL, "CRC8-MAD2 OK.");
|
PrintAndLogEx(INFO, "CRC8-MAD2 (%)", _GREEN_("ok"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -191,7 +189,11 @@ 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) {
|
int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen) {
|
||||||
*madlen = 0;
|
*madlen = 0;
|
||||||
bool haveMAD2 = false;
|
bool haveMAD2 = false;
|
||||||
MADCheck(sector0, sector10, false, &haveMAD2);
|
int res = MADCheck(sector0, sector10, false, &haveMAD2);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(INFO, "Not a valid MAD");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; i < 16; i++) {
|
for (int i = 1; i < 16; i++) {
|
||||||
mad[*madlen] = madGetAID(sector0, 1, i);
|
mad[*madlen] = madGetAID(sector0, 1, i);
|
||||||
|
@ -208,51 +210,63 @@ int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen
|
||||||
(*madlen)++;
|
(*madlen)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
|
int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) {
|
||||||
|
|
||||||
// check MAD1 only
|
// check MAD1 only
|
||||||
MADCheck(sector, NULL, verbose, haveMAD2);
|
int res = MADCheck(sector, NULL, verbose, haveMAD2);
|
||||||
|
if (verbose) {
|
||||||
|
if (res == PM3_SUCCESS)
|
||||||
|
PrintAndLogEx(INFO, "CRC8-MAD1 (%s)", _GREEN_("ok"));
|
||||||
|
else
|
||||||
|
PrintAndLogEx(INFO, "CRC8-MAD1 (%s)", _RED_("fail"));
|
||||||
|
}
|
||||||
|
|
||||||
// info byte
|
// info byte
|
||||||
uint8_t InfoByte = sector[16 + 1] & 0x3f;
|
uint8_t InfoByte = sector[16 + 1] & 0x3f;
|
||||||
if (InfoByte) {
|
if (InfoByte) {
|
||||||
PrintAndLogEx(NORMAL, "Card publisher sector: 0x%02x", InfoByte);
|
PrintAndLogEx(INFO, "Card publisher sector: " _GREEN_("0x%02x"), InfoByte);
|
||||||
} else {
|
} else {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(NORMAL, "Card publisher sector not present.");
|
PrintAndLogEx(WARNING, "Card publisher sector not present");
|
||||||
}
|
}
|
||||||
if (InfoByte == 0x10 || InfoByte >= 0x28)
|
if (InfoByte == 0x10 || InfoByte >= 0x28)
|
||||||
PrintAndLogEx(WARNING, "Info byte error");
|
PrintAndLogEx(WARNING, "Info byte error");
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "00 MAD1");
|
PrintAndLogEx(INFO, " 00 MAD 1");
|
||||||
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(NORMAL, "%02d [%04X] %s", i, AID, GetAIDDescription(AID));
|
PrintAndLogEx(INFO, " %02d [%04X] %s", i, AID, GetAIDDescription(AID));
|
||||||
};
|
}
|
||||||
|
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
|
int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) {
|
||||||
PrintAndLogEx(NORMAL, "16 MAD2");
|
PrintAndLogEx(INFO, " 16 MAD 2");
|
||||||
|
|
||||||
int res = madCRCCheck(sector, true, 2);
|
int res = madCRCCheck(sector, true, 2);
|
||||||
|
if (verbose) {
|
||||||
if (verbose && !res)
|
if (res == PM3_SUCCESS)
|
||||||
PrintAndLogEx(NORMAL, "CRC8-MAD2 OK.");
|
PrintAndLogEx(INFO, "CRC8-MAD2 (%s)", _GREEN_("ok"));
|
||||||
|
else
|
||||||
|
PrintAndLogEx(INFO, "CRC8-MAD2 (%s)", _RED_("fail"));
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t InfoByte = sector[1] & 0x3f;
|
uint8_t InfoByte = sector[1] & 0x3f;
|
||||||
PrintAndLogEx(NORMAL, "MAD2 Card publisher sector: 0x%02x", InfoByte);
|
if (InfoByte) {
|
||||||
|
PrintAndLogEx(INFO, "MAD2 Card publisher sector: " _GREEN_("0x%02x"), InfoByte);
|
||||||
|
} else {
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLogEx(WARNING, "Card publisher sector not present");
|
||||||
|
}
|
||||||
|
|
||||||
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(NORMAL, "%02d [%04X] %s", i + 16, AID, GetAIDDescription(AID));
|
PrintAndLogEx(INFO, "%02d [%04X] %s", i + 16, AID, GetAIDDescription(AID));
|
||||||
};
|
}
|
||||||
|
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue