diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c382664b..f8a648c2 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -141,12 +141,23 @@ int CmdHF14AMfRdBl(const char *Cmd) uint8_t isOK = resp.arg[0] & 0xff; uint8_t *data = resp.d.asBytes; - if (isOK) + if (isOK) { PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16)); - else + } else { PrintAndLog("isOk:%02x", isOK); + return 1; + } + + if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) { + PrintAndLogEx(NORMAL, "Trailer decoded:"); + for (int i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d: %s", i + mfFirstBlockOfSector(mfSectorNum(blockNo)), mfGetAccessConditionsDesc(i, &data[6])); + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); + } } else { PrintAndLog("Command execute timeout"); + return 2; } return 0; @@ -2272,6 +2283,17 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { } PrintAndLog("block data:%s", sprint_hex(memBlock, 16)); + + if (mfIsSectorTrailer(blockNo)) { + PrintAndLogEx(NORMAL, "Trailer decoded:"); + PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(memBlock, 6)); + PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&memBlock[10], 6)); + for (int i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d: %s", i + mfFirstBlockOfSector(mfSectorNum(blockNo)), mfGetAccessConditionsDesc(i, &memBlock[6])); + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&memBlock[9], 1)); + } + return 0; } diff --git a/client/mifare4.c b/client/mifare4.c index 069c54d4..295b26b4 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -17,6 +17,52 @@ #include "ui.h" #include "crypto/libpcrypto.h" +AccessConditions_t MFAccessConditions[] = { + {0x00, "rdAB wrAB incAB dectrAB"}, + {0x01, "rdAB dectrAB"}, + {0x02, "rdAB"}, + {0x03, "rdB wrB"}, + {0x04, "rdAB wrB"}, + {0x05, "rdB"}, + {0x06, "rdAB wrB incB dectrAB"}, + {0x07, "none"} +}; + +AccessConditions_t MFAccessConditionsTrailer[] = { + {0x00, "rdAbyA rdCbyA rdBbyA wrBbyA"}, + {0x01, "wrAbyA rdCbyA wrCbyA rdBbyA wrBbyA"}, + {0x02, "rdCbyA rdBbyA"}, + {0x03, "wrAbyB rdCbyAB wrCbyB wrBbyB"}, + {0x04, "wrAbyB rdCbyAB wrBbyB"}, + {0x05, "rdCbyAB wrCbyB"}, + {0x06, "rdCbyAB"}, + {0x07, "rdCbyAB"} +}; + +char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { + static char StaticNone[] = "none"; + + uint8_t data1 = ((data[1] >> 4) & 0x0f) >> blockn; + uint8_t data2 = ((data[2]) & 0x0f) >> blockn; + uint8_t data3 = ((data[2] >> 4) & 0x0f) >> blockn; + + uint8_t cond = (data1 & 0x01) << 2 | (data2 & 0x01) << 1 | (data3 & 0x01); + + if (blockn == 3) { + for (int i = 0; i < ARRAYLEN(MFAccessConditionsTrailer); i++) + if (MFAccessConditionsTrailer[i].cond == cond) { + return MFAccessConditionsTrailer[i].description; + } + } else { + for (int i = 0; i < ARRAYLEN(MFAccessConditions); i++) + if (MFAccessConditions[i].cond == cond) { + return MFAccessConditions[i].description; + } + }; + + return StaticNone; +}; + int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) { memcpy(&iv[0], session->TI, 4); memcpy(&iv[4], &session->R_Ctr, 2); diff --git a/client/mifare4.h b/client/mifare4.h index 2453797b..5d9735da 100644 --- a/client/mifare4.h +++ b/client/mifare4.h @@ -38,9 +38,16 @@ typedef enum { mtypWriteResp, } MACType_t; +typedef struct { + uint8_t cond; + char *description; +} AccessConditions_t; + extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); +extern char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); + extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); extern uint8_t mfFirstBlockOfSector(uint8_t sectorNo); extern uint8_t mfSectorTrailer(uint8_t blockNo);