Fix hf mf dump/auto/csave MFC JSON dumps - save real ATQA/SAK

This commit is contained in:
Philippe Teuwen 2021-09-25 01:12:44 +02:00
parent 347b5c9614
commit 1850e9fa40
4 changed files with 92 additions and 19 deletions

View file

@ -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... 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] ## [unreleased][unreleased]
- Fix `hf mf dump/auto/csave` MFC JSON dumps - save real ATQA/SAK (@doegox)
- Added option to load raw NDEF to `nfc decode` command (@doegox) - Added option to load raw NDEF to `nfc decode` command (@doegox)
- Added option to save raw NDEF to all `hf * ndefread` commands (@doegox) - Added option to save raw NDEF to all `hf * ndefread` commands (@doegox)
- Changed `hf 14a info` - different FUDAN clone detection (@iceman1001) - Changed `hf 14a info` - different FUDAN clone detection (@iceman1001)

View file

@ -623,6 +623,24 @@ static int CmdHF14AMfDump(const char *Cmd) {
char *fptr; char *fptr;
// Select card to get UID/UIDLEN/ATQA/SAK information
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
PrintAndLogEx(WARNING, "iso14443a card select timeout");
return PM3_ETIMEOUT;
}
uint64_t select_status = resp.oldarg[0];
if (select_status == 0) {
PrintAndLogEx(WARNING, "iso14443a card select failed");
return select_status;
}
// store card info
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
if (keyFilename[0] == 0x00) { if (keyFilename[0] == 0x00) {
fptr = GenerateFilename("hf-mf-", "-key.bin"); fptr = GenerateFilename("hf-mf-", "-key.bin");
if (fptr == NULL) if (fptr == NULL)
@ -799,7 +817,12 @@ static int CmdHF14AMfDump(const char *Cmd) {
saveFile(dataFilename, ".bin", (uint8_t *)carddata, bytes); saveFile(dataFilename, ".bin", (uint8_t *)carddata, bytes);
saveFileEML(dataFilename, (uint8_t *)carddata, bytes, MFBLOCK_SIZE); saveFileEML(dataFilename, (uint8_t *)carddata, bytes, MFBLOCK_SIZE);
saveFileJSON(dataFilename, jsfCardMemory, (uint8_t *)carddata, bytes, NULL);
iso14a_mf_extdump_t xdump;
xdump.card_info = card;
xdump.dump = (uint8_t *)carddata;
xdump.dumplen = bytes;
saveFileJSON(dataFilename, jsfCardMemory, (uint8_t*)&xdump, sizeof(xdump), NULL);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1972,6 +1995,25 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// ------------------------------ // ------------------------------
// Select card to get UID/UIDLEN/ATQA/SAK information
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
PrintAndLogEx(WARNING, "iso14443a card select timeout");
return PM3_ETIMEOUT;
}
uint64_t select_status = resp.oldarg[0];
if (select_status == 0) {
PrintAndLogEx(WARNING, "iso14443a card select failed");
return select_status;
}
// store card info
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
// create/initialize key storage structure // create/initialize key storage structure
uint32_t e_sector_size = sector_cnt > sectorno ? sector_cnt : sectorno + 1; uint32_t e_sector_size = sector_cnt > sectorno ? sector_cnt : sectorno + 1;
res = initSectorTable(&e_sector, e_sector_size); res = initSectorTable(&e_sector, e_sector_size);
@ -2314,7 +2356,6 @@ noValidKeyFound:
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) goto skipReadBKey; if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) goto skipReadBKey;
if (resp.status != PM3_SUCCESS) goto skipReadBKey; if (resp.status != PM3_SUCCESS) goto skipReadBKey;
@ -2558,7 +2599,11 @@ all_found:
saveFile(filename, ".bin", dump, bytes); saveFile(filename, ".bin", dump, bytes);
saveFileEML(filename, dump, bytes, MFBLOCK_SIZE); saveFileEML(filename, dump, bytes, MFBLOCK_SIZE);
saveFileJSON(filename, jsfCardMemory, dump, bytes, NULL); iso14a_mf_extdump_t xdump;
xdump.card_info = card;
xdump.dump = dump;
xdump.dumplen = bytes;
saveFileJSON(filename, jsfCardMemory, (uint8_t*)&xdump, sizeof(xdump), NULL);
// Generate and show statistics // Generate and show statistics
t1 = msclock() - t1; t1 = msclock() - t1;
@ -3942,7 +3987,28 @@ static int CmdHF14AMfESave(const char *Cmd) {
saveFile(filename, ".bin", dump, bytes); saveFile(filename, ".bin", dump, bytes);
saveFileEML(filename, dump, bytes, MFBLOCK_SIZE); saveFileEML(filename, dump, bytes, MFBLOCK_SIZE);
saveFileJSON(filename, jsfCardMemory, dump, bytes, NULL);
iso14a_mf_extdump_t xdump = {0};
xdump.card_info.ats_len = 0;
// Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
if ((dump[0] ^ dump[1] ^ dump[2] ^ dump[3]) == dump[4] && (dump[6] & 0xc0) == 0) {
xdump.card_info.uidlen = 4;
memcpy(xdump.card_info.uid, dump, xdump.card_info.uidlen);
xdump.card_info.sak = dump[5];
memcpy(xdump.card_info.atqa, &dump[6], sizeof(xdump.card_info.atqa));
}
// Check for 7 bytes UID: double size uid bits in ATQA
else if ((dump[8] & 0xc0) == 0x40) {
xdump.card_info.uidlen = 7;
memcpy(xdump.card_info.uid, dump, xdump.card_info.uidlen);
xdump.card_info.sak = dump[7];
memcpy(xdump.card_info.atqa, &dump[8], sizeof(xdump.card_info.atqa));
} else {
PrintAndLogEx(WARNING, "Invalid dump. UID/SAK/ATQA not found");
}
xdump.dump = dump;
xdump.dumplen = bytes;
saveFileJSON(filename, jsfCardMemory, (uint8_t*)&xdump, sizeof(xdump), NULL);
free(dump); free(dump);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -4775,7 +4841,11 @@ static int CmdHF14AMfCSave(const char *Cmd) {
saveFile(filename, ".bin", dump, bytes); saveFile(filename, ".bin", dump, bytes);
saveFileEML(filename, dump, bytes, MFBLOCK_SIZE); saveFileEML(filename, dump, bytes, MFBLOCK_SIZE);
saveFileJSON(filename, jsfCardMemory, dump, bytes, NULL); iso14a_mf_extdump_t xdump;
xdump.card_info = card;
xdump.dump = dump;
xdump.dumplen = bytes;
saveFileJSON(filename, jsfCardMemory, (uint8_t*)&xdump, sizeof(xdump), NULL);
free(dump); free(dump);
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -375,29 +375,25 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data,
break; break;
} }
case jsfCardMemory: { case jsfCardMemory: {
iso14a_mf_extdump_t* xdump = (iso14a_mf_extdump_t*) data;
JsonSaveStr(root, "FileType", "mfcard"); JsonSaveStr(root, "FileType", "mfcard");
for (size_t i = 0; i < (datalen / 16); i++) { JsonSaveBufAsHexCompact(root, "$.Card.UID", xdump->card_info.uid, xdump->card_info.uidlen);
JsonSaveBufAsHexCompact(root, "$.Card.ATQA", xdump->card_info.atqa, 2);
JsonSaveBufAsHexCompact(root, "$.Card.SAK", &(xdump->card_info.sak), 1);
for (size_t i = 0; i < (xdump->dumplen / 16); i++) {
char path[PATH_MAX_LENGTH] = {0}; char path[PATH_MAX_LENGTH] = {0};
sprintf(path, "$.blocks.%zu", i); sprintf(path, "$.blocks.%zu", i);
JsonSaveBufAsHexCompact(root, path, &data[i * 16], 16); JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * 16], 16);
if (i == 0) {
JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 4);
JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[5], 1);
JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[6], 2);
}
if (mfIsSectorTrailer(i)) { if (mfIsSectorTrailer(i)) {
snprintf(path, sizeof(path), "$.SectorKeys.%d.KeyA", mfSectorNum(i)); snprintf(path, sizeof(path), "$.SectorKeys.%d.KeyA", mfSectorNum(i));
JsonSaveBufAsHexCompact(root, path, &data[i * 16], 6); JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * 16], 6);
snprintf(path, sizeof(path), "$.SectorKeys.%d.KeyB", mfSectorNum(i)); snprintf(path, sizeof(path), "$.SectorKeys.%d.KeyB", mfSectorNum(i));
JsonSaveBufAsHexCompact(root, path, &data[i * 16 + 10], 6); JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * 16 + 10], 6);
uint8_t *adata = &data[i * 16 + 6]; uint8_t *adata = &xdump->dump[i * 16 + 6];
snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditions", mfSectorNum(i)); snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditions", mfSectorNum(i));
JsonSaveBufAsHexCompact(root, path, &data[i * 16 + 6], 4); JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * 16 + 6], 4);
snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.block%zu", mfSectorNum(i), i - 3); snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.block%zu", mfSectorNum(i), i - 3);
JsonSaveStr(root, path, mfGetAccessConditionsDesc(0, adata)); JsonSaveStr(root, path, mfGetAccessConditionsDesc(0, adata));

View file

@ -48,6 +48,12 @@ typedef struct {
uint8_t ats[256]; uint8_t ats[256];
} PACKED iso14a_card_select_t; } PACKED iso14a_card_select_t;
typedef struct {
iso14a_card_select_t card_info;
uint8_t *dump;
uint16_t dumplen;
} iso14a_mf_extdump_t;
typedef enum ISO14A_COMMAND { typedef enum ISO14A_COMMAND {
ISO14A_CONNECT = (1 << 0), ISO14A_CONNECT = (1 << 0),
ISO14A_NO_DISCONNECT = (1 << 1), ISO14A_NO_DISCONNECT = (1 << 1),