mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-30 11:39:14 -07:00
Fix hf mf dump/auto/csave MFC JSON dumps - save real ATQA/SAK
This commit is contained in:
parent
347b5c9614
commit
1850e9fa40
4 changed files with 92 additions and 19 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...
|
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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue