mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
changed magic detection to use flags. Fixes previous problems with magic ntag, also renamed defines to seperate them better.
This commit is contained in:
parent
14c3eb6dc8
commit
81ce1fd4ab
9 changed files with 198 additions and 140 deletions
|
@ -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...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed the magic card detection. It now acts as flags (@iceman1001)
|
||||
- Added `hf ict` - skeleton commands in preperation (@iceman1001)
|
||||
- Added `lf hitag eview` - now supports viewing of emulator memory (@iceman1001)
|
||||
- Added `lf hitag view` - now supports viewing of dump files (@iceman1001)
|
||||
|
|
|
@ -2457,8 +2457,8 @@ static void mf_reset_card(void) {
|
|||
|
||||
void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||
// variables
|
||||
uint8_t rec[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
uint8_t recpar[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
uint8_t rec[1] = {0x00};
|
||||
uint8_t recpar[1] = {0x00};
|
||||
uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73};
|
||||
uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||
|
@ -2467,39 +2467,36 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0};
|
||||
uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D};
|
||||
bool isGen2 = false;
|
||||
bool isGen1AGdm = false;
|
||||
|
||||
uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE);
|
||||
uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE);
|
||||
uint8_t *uid = BigBuf_calloc(10);
|
||||
uint8_t *data = BigBuf_calloc(16);
|
||||
|
||||
uint16_t flag = MAGIC_FLAG_NONE;
|
||||
uint32_t cuid = 0;
|
||||
size_t data_off = 0;
|
||||
int res = 0;
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
// Generation 1 test
|
||||
ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
|
||||
if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) {
|
||||
uint8_t isGen = MAGIC_GEN_1A;
|
||||
if (ReaderReceive(rec, recpar) && (rec[0] == 0x0A)) {
|
||||
flag = MAGIC_FLAG_GEN_1A;
|
||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||
if (!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) {
|
||||
isGen = MAGIC_GEN_1B;
|
||||
};
|
||||
data[data_off++] = isGen;
|
||||
if (ReaderReceive(rec, recpar) && (rec[0] != 0x0A)) {
|
||||
flag = MAGIC_FLAG_GEN_1B;
|
||||
}
|
||||
|
||||
// check for GDM config
|
||||
ReaderTransmit(gen4gdmGetConf, sizeof(gen4gdmGetConf), NULL);
|
||||
int res = ReaderReceive(buf, par);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res > 1) {
|
||||
isGen1AGdm = true;
|
||||
flag |= MAGIC_FLAG_GDM_WUP_40;
|
||||
}
|
||||
}
|
||||
|
||||
mf_reset_card();
|
||||
|
||||
int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
// Check for Magic Gen4 GTU with default password:
|
||||
// Get config should return 30 or 32 bytes
|
||||
|
@ -2507,7 +2504,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
ReaderTransmit(gen4GetConf, sizeof(gen4GetConf), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 32 || res == 34) {
|
||||
data[data_off++] = MAGIC_GEN_4GTU;
|
||||
flag |= MAGIC_FLAG_GEN_4GTU;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2517,7 +2514,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, false);
|
||||
if (res) {
|
||||
if (cuid == 0xAA55C396) {
|
||||
data[data_off++] = MAGIC_GEN_UNFUSED;
|
||||
flag |= MAGIC_FLAG_GEN_UNFUSED;
|
||||
}
|
||||
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
|
@ -2527,38 +2524,38 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
|
||||
// test for some MFC gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
|
||||
// test for some MFC 7b gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
|
||||
// test for Ultralight magic gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
|
||||
// test for Ultralight EV1 magic gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
|
||||
// test for some other Ultralight EV1 magic gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
|
||||
// test for some other Ultralight magic gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
|
||||
// test for NTAG213 magic gen2
|
||||
isGen2 = true;
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
}
|
||||
|
||||
// test for super card
|
||||
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 22) {
|
||||
uint8_t isGen = MAGIC_SUPER_GEN1;
|
||||
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
|
||||
|
||||
// check for super card gen2
|
||||
// not available after RATS, reset card before executing
|
||||
|
@ -2568,10 +2565,10 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 18) {
|
||||
isGen = MAGIC_SUPER_GEN2;
|
||||
isGen = MAGIC_FLAG_SUPER_GEN2;
|
||||
}
|
||||
|
||||
data[data_off++] = isGen;
|
||||
flag |= isGen;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2584,7 +2581,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
ReaderTransmit(rdblf0, sizeof(rdblf0), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 18) {
|
||||
data[data_off++] = MAGIC_NTAG21X;
|
||||
flag |= MAGIC_FLAG_NTAG21X;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2597,7 +2594,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
// regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it
|
||||
// if we do get an ACK, we immediately abort to ensure nothing is ever actually written
|
||||
// only perform test if we haven't already identified Gen2. No need test if we have a positive identification already
|
||||
if (!isGen2) {
|
||||
if (isGen2 == false) {
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
|
@ -2607,7 +2604,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) {
|
||||
|
||||
if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, par, NULL) == 1) && (buf[0] == 0x0A)) {
|
||||
data[data_off++] = MAGIC_GEN_2;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
// turn off immediately to ensure nothing ever accidentally writes to the block
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
||||
|
@ -2624,7 +2621,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 18) {
|
||||
data[data_off++] = MAGIC_GEN_3;
|
||||
flag |= MAGIC_FLAG_GEN_3;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2636,7 +2633,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
ReaderTransmit(gen4gdmAuth, sizeof(gen4gdmAuth), NULL);
|
||||
res = ReaderReceive(buf, par);
|
||||
if (res == 4) {
|
||||
data[data_off++] = MAGIC_GDM_AUTH;
|
||||
flag |= MAGIC_FLAG_GDM_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2646,24 +2643,20 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) {
|
||||
data[data_off++] = MAGIC_QL88;
|
||||
flag |= MAGIC_FLAG_QL88;
|
||||
}
|
||||
crypto1_deinit(pcs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isGen1AGdm == true) {
|
||||
data[data_off++] = MAGIC_GDM_WUP_40;
|
||||
}
|
||||
|
||||
// GDM alt magic wakeup (20)
|
||||
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
|
||||
if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) {
|
||||
data[data_off++] = MAGIC_GDM_WUP_20;
|
||||
flag |= MAGIC_FLAG_GDM_WUP_20;
|
||||
}
|
||||
|
||||
reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, data, data_off);
|
||||
reply_ng(CMD_HF_MIFARE_CIDENT, PM3_SUCCESS, (uint8_t *)&flag, sizeof(uint16_t));
|
||||
// turns off
|
||||
OnSuccessMagic();
|
||||
BigBuf_free();
|
||||
|
|
|
@ -2487,34 +2487,40 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
int isMagic = 0;
|
||||
uint16_t isMagic = 0;
|
||||
if (isMifareClassic) {
|
||||
isMagic = detect_mf_magic(true, MF_KEY_B, 0xFFFFFFFFFFFF);
|
||||
}
|
||||
|
||||
if (isMifareUltralight) {
|
||||
isMagic = (detect_mf_magic(false, MF_KEY_A, 0) == MAGIC_NTAG21X);
|
||||
isMagic = ((detect_mf_magic(false, MF_KEY_A, 0) & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X);
|
||||
}
|
||||
|
||||
if (isMifareClassic) {
|
||||
int res = detect_classic_static_nonce();
|
||||
if (res == NONCE_STATIC)
|
||||
if (res == NONCE_STATIC) {
|
||||
PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
|
||||
}
|
||||
|
||||
if (res == NONCE_FAIL && verbose)
|
||||
if (res == NONCE_FAIL && verbose) {
|
||||
PrintAndLogEx(SUCCESS, "Static nonce......... " _RED_("read failed"));
|
||||
}
|
||||
|
||||
if (res == NONCE_NORMAL) {
|
||||
|
||||
// not static
|
||||
res = detect_classic_prng();
|
||||
if (res == 1)
|
||||
if (res == 1) {
|
||||
PrintAndLogEx(SUCCESS, "Prng detection....... " _GREEN_("weak"));
|
||||
else if (res == 0)
|
||||
} else if (res == 0) {
|
||||
PrintAndLogEx(SUCCESS, "Prng detection....... " _YELLOW_("hard"));
|
||||
else
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "Prng detection........ " _RED_("fail"));
|
||||
}
|
||||
|
||||
if (do_nack_test)
|
||||
if (do_nack_test) {
|
||||
detect_classic_nackbug(false);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t signature[32] = {0};
|
||||
|
@ -2522,7 +2528,6 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
if (res == PM3_SUCCESS) {
|
||||
mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
|
||||
}
|
||||
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands");
|
||||
}
|
||||
|
||||
|
@ -2530,20 +2535,25 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
if (isMifareUltralight)
|
||||
if (isMifareUltralight) {
|
||||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`");
|
||||
}
|
||||
|
||||
if (isMifarePlus && isMagic == 0 && isEMV == false)
|
||||
if (isMifarePlus && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) {
|
||||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfp info") "`");
|
||||
}
|
||||
|
||||
if (isMifareDESFire && isMagic == 0 && isEMV == false)
|
||||
if (isMifareDESFire && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) {
|
||||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfdes info") "`");
|
||||
}
|
||||
|
||||
if (isST)
|
||||
if (isST) {
|
||||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st info") "`");
|
||||
}
|
||||
|
||||
if (isEMV)
|
||||
if (isEMV) {
|
||||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv reader") "`");
|
||||
}
|
||||
|
||||
if (isFUDAN) {
|
||||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`");
|
||||
|
@ -2564,6 +2574,35 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf ntag424 info") "`");
|
||||
}
|
||||
|
||||
if (isMifareClassic &&
|
||||
(((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B))
|
||||
) {
|
||||
PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf c*") "` commands when interacting");
|
||||
}
|
||||
|
||||
if (isMifareClassic &&
|
||||
((isMagic & MAGIC_FLAG_GEN_2) == MAGIC_FLAG_GEN_2)
|
||||
) {
|
||||
PrintAndLogEx(HINT, "Hint: Use normal `" _YELLOW_("hf mf") "` commands when interacting");
|
||||
}
|
||||
|
||||
if (isMifareClassic &&
|
||||
((isMagic & MAGIC_FLAG_GEN_3) == MAGIC_FLAG_GEN_3)
|
||||
) {
|
||||
PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mf gen3*") "` commands when interacting");
|
||||
}
|
||||
|
||||
if (isMifareClassic &&
|
||||
((isMagic & MAGIC_FLAG_GEN_4GTU) == MAGIC_FLAG_GEN_4GTU)
|
||||
) {
|
||||
PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mf g*") "` commands when interacting");
|
||||
}
|
||||
|
||||
if (isMifareClassic &&
|
||||
((isMagic & MAGIC_FLAG_GDM_AUTH) == MAGIC_FLAG_GDM_AUTH)
|
||||
) {
|
||||
PrintAndLogEx(HINT, "Hint: Use `" _YELLOW_("hf mf gdm*") "` commands when interacting");
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
DropField();
|
||||
|
|
|
@ -9341,13 +9341,12 @@ static int CmdHF14AMfInfo(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Magic Tag Information"));
|
||||
if (detect_mf_magic(true, MF_KEY_B, e_sector[0].Key[MF_KEY_B]) == 0) {
|
||||
if (detect_mf_magic(true, MF_KEY_A, e_sector[0].Key[MF_KEY_A]) == 0) {
|
||||
if (detect_mf_magic(true, MF_KEY_B, e_sector[0].Key[MF_KEY_B]) == MAGIC_FLAG_NONE) {
|
||||
if (detect_mf_magic(true, MF_KEY_A, e_sector[0].Key[MF_KEY_A]) == MAGIC_FLAG_NONE) {
|
||||
PrintAndLogEx(INFO, "<N/A>");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(keyBlock);
|
||||
free(e_sector);
|
||||
|
||||
|
|
|
@ -381,7 +381,6 @@ static int CmdHFMFPInfo(const char *Cmd) {
|
|||
// https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161
|
||||
uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00};
|
||||
int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false);
|
||||
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "identification failed");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
|
|
@ -467,17 +467,23 @@ static int ulev1_readSignature(uint8_t *response, uint16_t responseLength) {
|
|||
// make sure field is off before calling this function
|
||||
static int ul_fudan_check(void) {
|
||||
iso14a_card_select_t card;
|
||||
if (!ul_select(&card))
|
||||
if (ul_select(&card) == false) {
|
||||
return MFU_TT_UL_ERROR;
|
||||
}
|
||||
|
||||
uint8_t cmd[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa7}; //wrong crc on purpose should be 0xa8
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return MFU_TT_UL_ERROR;
|
||||
if (resp.oldarg[0] != 1) return MFU_TT_UL_ERROR;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
||||
return MFU_TT_UL_ERROR;
|
||||
}
|
||||
if (resp.oldarg[0] != 1) {
|
||||
return MFU_TT_UL_ERROR;
|
||||
}
|
||||
|
||||
return (!resp.data.asBytes[0]) ? MFU_TT_FUDAN_UL : MFU_TT_UL; //if response == 0x00 then Fudan, else Genuine NXP
|
||||
return (resp.data.asBytes[0] == 0)
|
||||
? MFU_TT_FUDAN_UL : MFU_TT_UL; //if response == 0x00 then Fudan, else Genuine NXP
|
||||
}
|
||||
|
||||
static int ul_print_default(uint8_t *data, uint8_t *real_uid) {
|
||||
|
@ -776,7 +782,8 @@ static int ulc_print_configuration(uint8_t *data) {
|
|||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("UL-C Configuration") " --------------------------");
|
||||
PrintAndLogEx(INFO, "Available memory... " _YELLOW_("%u") " bytes", 0x2F * 4);
|
||||
PrintAndLogEx(INFO, "Total memory....... " _YELLOW_("%u") " bytes", MAX_ULC_BLOCKS * 4);
|
||||
PrintAndLogEx(INFO, "Available memory... " _YELLOW_("%u") " bytes", (MAX_ULC_BLOCKS - 4) * 4);
|
||||
PrintAndLogEx(INFO, "40 / 0x28 | %s - %s Higher lockbits", sprint_hex(data, 4), sprint_bin(data, 2));
|
||||
PrintAndLogEx(INFO, "41 / 0x29 | %s - %s Counter", sprint_hex(data + 4, 4), sprint_bin(data + 4, 2));
|
||||
|
||||
|
@ -1271,35 +1278,41 @@ static int ul_magic_test(void) {
|
|||
// 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
|
||||
|
||||
iso14a_card_select_t card;
|
||||
if (ul_select(&card) == false)
|
||||
if (ul_select(&card) == false) {
|
||||
return MFU_TT_UL_ERROR;
|
||||
}
|
||||
|
||||
int status = ul_comp_write(0, NULL, 0);
|
||||
DropField();
|
||||
if (status == 0)
|
||||
if (status == 0) {
|
||||
return MFU_TT_MAGIC;
|
||||
}
|
||||
|
||||
// check for GEN1A, GEN1B and NTAG21x
|
||||
uint8_t is_generation = 0;
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
uint8_t payload[] = { 0 };
|
||||
SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload));
|
||||
|
||||
uint16_t is_generation = MAGIC_FLAG_NONE;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) {
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
is_generation = resp.data.asBytes[0];
|
||||
if ((resp.status == PM3_SUCCESS) && resp.length == sizeof(uint16_t)) {
|
||||
is_generation = resp.data.asDwords[0] & 0xFFFF;
|
||||
}
|
||||
}
|
||||
switch (is_generation) {
|
||||
case MAGIC_GEN_1A:
|
||||
return MFU_TT_MAGIC_1A;
|
||||
case MAGIC_GEN_1B:
|
||||
return MFU_TT_MAGIC_1B;
|
||||
case MAGIC_NTAG21X:
|
||||
return MFU_TT_MAGIC_NTAG;
|
||||
default:
|
||||
break;
|
||||
|
||||
if ((is_generation & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) {
|
||||
return MFU_TT_MAGIC_1A;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if ((is_generation & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B) {
|
||||
return MFU_TT_MAGIC_1B;
|
||||
}
|
||||
if ((is_generation & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
|
||||
return MFU_TT_MAGIC_NTAG;
|
||||
}
|
||||
|
||||
return MFU_TT_UNKNOWN;
|
||||
}
|
||||
|
||||
static char *GenerateFilename(const char *prefix, const char *suffix) {
|
||||
|
|
|
@ -1389,10 +1389,10 @@ int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, ui
|
|||
return NONCE_FAIL;
|
||||
}
|
||||
|
||||
/* try to see if card responses to "Chinese magic backdoor" commands. */
|
||||
int detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) {
|
||||
// try to see if card responses to "Chinese magic backdoor" commands.
|
||||
// returns flag
|
||||
uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) {
|
||||
|
||||
uint8_t isMagic = 0;
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
uint8_t payload[1 + 1 + MIFARE_KEY_SIZE] = { is_mfc, key_type };
|
||||
|
@ -1401,54 +1401,67 @@ int detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key) {
|
|||
SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload));
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return 0;
|
||||
return MAGIC_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < resp.length; i++) {
|
||||
isMagic = 1;
|
||||
switch (resp.data.asBytes[i]) {
|
||||
case MAGIC_GEN_1A:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1a"));
|
||||
break;
|
||||
case MAGIC_GEN_1B:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1b"));
|
||||
break;
|
||||
case MAGIC_GEN_2:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 2 / CUID"));
|
||||
break;
|
||||
case MAGIC_GEN_3:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 3 / APDU") " ( possibly )");
|
||||
break;
|
||||
case MAGIC_GEN_4GTU:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GTU"));
|
||||
break;
|
||||
case MAGIC_GDM_AUTH:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Magic Auth )");
|
||||
break;
|
||||
case MAGIC_GDM_WUP_20:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Alt Magic Wakeup )");
|
||||
break;
|
||||
case MAGIC_GDM_WUP_40:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Gen1 Magic Wakeup )");
|
||||
break;
|
||||
case MAGIC_GEN_UNFUSED:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Write Once / FUID"));
|
||||
break;
|
||||
case MAGIC_SUPER_GEN1:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 1") _GREEN_(" )"));
|
||||
break;
|
||||
case MAGIC_SUPER_GEN2:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 2") _GREEN_(" )"));
|
||||
break;
|
||||
case MAGIC_NTAG21X:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("NTAG21x"));
|
||||
break;
|
||||
case MAGIC_QL88:
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("QL88"));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint16_t isMagic = MAGIC_FLAG_NONE;
|
||||
if ((resp.status == PM3_SUCCESS) && resp.length == sizeof(uint16_t)) {
|
||||
isMagic = resp.data.asDwords[0] & 0xFFFF;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "...%04x", isMagic);
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1a"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 1b"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GEN_2) == MAGIC_FLAG_GEN_2) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 2 / CUID"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GEN_3) == MAGIC_FLAG_GEN_3) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 3 / APDU") " ( possibly )");
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GEN_4GTU) == MAGIC_FLAG_GEN_4GTU) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GTU"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GDM_AUTH) == MAGIC_FLAG_GDM_AUTH) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Magic Auth )");
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GDM_WUP_20) == MAGIC_FLAG_GDM_WUP_20) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Alt Magic Wakeup )");
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GDM_WUP_40) == MAGIC_FLAG_GDM_WUP_40) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Gen 4 GDM / USCUID") " ( Gen1 Magic Wakeup )");
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_GEN_UNFUSED) == MAGIC_FLAG_GEN_UNFUSED) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Write Once / FUID"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_SUPER_GEN1) == MAGIC_FLAG_SUPER_GEN1) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 1") _GREEN_(" )"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_SUPER_GEN2) == MAGIC_FLAG_SUPER_GEN2) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("Super card ( ") _CYAN_("Gen 2") _GREEN_(" )"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("NTAG21x"));
|
||||
}
|
||||
|
||||
if ((isMagic & MAGIC_FLAG_QL88) == MAGIC_FLAG_QL88) {
|
||||
PrintAndLogEx(SUCCESS, "Magic capabilities... " _GREEN_("QL88"));
|
||||
}
|
||||
return isMagic;
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data,
|
|||
|
||||
int detect_classic_prng(void);
|
||||
int detect_classic_nackbug(bool verbose);
|
||||
int detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key);
|
||||
uint16_t detect_mf_magic(bool is_mfc, uint8_t key_type, uint64_t key);
|
||||
int detect_classic_static_nonce(void);
|
||||
int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key);
|
||||
bool detect_mfc_ev1_signature(void);
|
||||
|
|
|
@ -256,20 +256,21 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define MAGIC_WIPE 0x40
|
||||
#define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E
|
||||
|
||||
// by CMD_HF_MIFARE_CIDENT
|
||||
#define MAGIC_GEN_1A 1
|
||||
#define MAGIC_GEN_1B 2
|
||||
#define MAGIC_GEN_2 4
|
||||
#define MAGIC_GEN_UNFUSED 5
|
||||
#define MAGIC_SUPER_GEN1 6
|
||||
#define MAGIC_SUPER_GEN2 7
|
||||
#define MAGIC_NTAG21X 8
|
||||
#define MAGIC_GEN_3 9
|
||||
#define MAGIC_GEN_4GTU 10
|
||||
#define MAGIC_GDM_AUTH 11
|
||||
#define MAGIC_QL88 12
|
||||
#define MAGIC_GDM_WUP_20 13
|
||||
#define MAGIC_GDM_WUP_40 14
|
||||
// by CMD_HF_MIFARE_CIDENT / Flags
|
||||
#define MAGIC_FLAG_NONE 0x0000
|
||||
#define MAGIC_FLAG_GEN_1A 0x0001
|
||||
#define MAGIC_FLAG_GEN_1B 0x0002
|
||||
#define MAGIC_FLAG_GEN_2 0x0004
|
||||
#define MAGIC_FLAG_GEN_UNFUSED 0x0008
|
||||
#define MAGIC_FLAG_SUPER_GEN1 0x0010
|
||||
#define MAGIC_FLAG_SUPER_GEN2 0x0020
|
||||
#define MAGIC_FLAG_NTAG21X 0x0040
|
||||
#define MAGIC_FLAG_GEN_3 0x0080
|
||||
#define MAGIC_FLAG_GEN_4GTU 0x0100
|
||||
#define MAGIC_FLAG_GDM_AUTH 0x0200
|
||||
#define MAGIC_FLAG_QL88 0x0400
|
||||
#define MAGIC_FLAG_GDM_WUP_20 0x0800
|
||||
#define MAGIC_FLAG_GDM_WUP_40 0x1000
|
||||
|
||||
|
||||
// Commands for configuration of Gen4 GTU cards.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue