hf mf restore got some textual updates in order to be easier to understand if keyB writes fails. We use a default ACL when wiping a card that doesnt allow key B to be used for writing. Restore command tries key B first, so there will be several failed key b attempts normally.

This commit is contained in:
iceman1001 2023-07-25 22:42:42 +02:00
commit e5b075ed3b
2 changed files with 28 additions and 27 deletions

View file

@ -1352,7 +1352,7 @@ static int CmdHF14AMfRestore(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
PrintAndLogEx(INFO, "Using key file... `" _YELLOW_("%s") "`", keyfilename); PrintAndLogEx(INFO, "Using key file `" _YELLOW_("%s") "`", keyfilename);
// try reading card uid and create filename // try reading card uid and create filename
if (datafnlen == 0) { if (datafnlen == 0) {
@ -1383,10 +1383,9 @@ static int CmdHF14AMfRestore(const char *Cmd) {
// default authentication key // default authentication key
uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", datafilename); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, " blk | data | status");
PrintAndLogEx(INFO, " blk | "); PrintAndLogEx(INFO, "-----+-------------------------------------------------+----------------");
PrintAndLogEx(INFO, "-----+------------------------------------------------------------");
// main loop for restoring. // main loop for restoring.
// a bit more complicated than needed // a bit more complicated than needed
@ -1402,6 +1401,8 @@ static int CmdHF14AMfRestore(const char *Cmd) {
// if sector trailer // if sector trailer
if (mfIsSectorTrailerBasedOnBlocks(s, b)) { if (mfIsSectorTrailerBasedOnBlocks(s, b)) {
// keep the current keys on the card
if (use_keyfile_for_auth == false) { if (use_keyfile_for_auth == false) {
// replace KEY A // replace KEY A
memcpy(bldata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(bldata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
@ -1440,10 +1441,13 @@ static int CmdHF14AMfRestore(const char *Cmd) {
for (int8_t kt = MF_KEY_B; kt > -1; kt--) { for (int8_t kt = MF_KEY_B; kt > -1; kt--) {
if (use_keyfile_for_auth) { if (use_keyfile_for_auth) {
if (kt == MF_KEY_A)
if (kt == MF_KEY_A) {
memcpy(wdata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(wdata, keyA + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
else } else {
memcpy(wdata, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE); memcpy(wdata, keyB + (s * MIFARE_KEY_SIZE), MIFARE_KEY_SIZE);
}
} else { } else {
// use default key to authenticate for the write command // use default key to authenticate for the write command
memcpy(wdata, default_key, MIFARE_KEY_SIZE); memcpy(wdata, default_key, MIFARE_KEY_SIZE);
@ -1451,8 +1455,6 @@ static int CmdHF14AMfRestore(const char *Cmd) {
uint16_t blockno = (mfFirstBlockOfSector(s) + b); uint16_t blockno = (mfFirstBlockOfSector(s) + b);
PrintAndLogEx(INFO, " %3d | %s", blockno, sprint_hex(bldata, sizeof(bldata)));
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, kt, 0, wdata, sizeof(wdata)); SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, kt, 0, wdata, sizeof(wdata));
PacketResponseNG resp; PacketResponseNG resp;
@ -1464,22 +1466,20 @@ static int CmdHF14AMfRestore(const char *Cmd) {
int isOK = resp.oldarg[0] & 0xff; int isOK = resp.oldarg[0] & 0xff;
if (isOK == 1) { if (isOK == 1) {
// if success, skip to next block // if success, skip to next block
PrintAndLogEx(INFO, " %3d | %s| ( " _GREEN_("ok") " )", blockno, sprint_hex(bldata, sizeof(bldata)));
break; break;
} else if (isOK == PM3_ETEAROFF) { }
// write somehow failed. Lets determine why.
if (isOK == PM3_ETEAROFF) {
PrintAndLogEx(INFO, "Tear off triggerd. Recommendation is not to use tear-off with restore command"); PrintAndLogEx(INFO, "Tear off triggerd. Recommendation is not to use tear-off with restore command");
goto out; goto out;
} else {
if (b == 0) {
PrintAndLogEx(INFO, "Writing to manufacture block w key " _YELLOW_("%c") " ( " _RED_("fail") " )",
(kt == MF_KEY_A) ? 'A' : 'B'
);
} else {
PrintAndLogEx(FAILED, "Write to block " _YELLOW_("%u") " w key " _YELLOW_("%c") " ( " _RED_("fail") " ) ",
blockno,
(kt == MF_KEY_A) ? 'A' : 'B'
);
}
} }
PrintAndLogEx(INFO, " %3d | %s| ( " _RED_("fail") " ) key " _YELLOW_("%c"),
blockno,
sprint_hex(bldata, sizeof(bldata)),
(kt == MF_KEY_A) ? 'A' : 'B'
);
} // end loop key types } // end loop key types
} // end loop B } // end loop B
} // end loop S } // end loop S
@ -1488,7 +1488,7 @@ out:
free(ref_dump); free(ref_dump);
free(keyA); free(keyA);
free(keyB); free(keyB);
PrintAndLogEx(INFO, "-----+------------------------------------------------------------"); PrintAndLogEx(INFO, "-----+-------------------------------------------------+----------------");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Done!"); PrintAndLogEx(INFO, "Done!");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -215,6 +215,7 @@ char *newfilenamemcopyEx(const char *preferredName, const char *suffix, savePath
if (str_endswith(preferredName, suffix)) { if (str_endswith(preferredName, suffix)) {
p_namelen -= strlen(suffix); p_namelen -= strlen(suffix);
} }
// modify filename // modify filename
snprintf(pfn, len, "%.*s%s", (int)p_namelen, preferredName, suffix); snprintf(pfn, len, "%.*s%s", (int)p_namelen, preferredName, suffix);
@ -862,7 +863,7 @@ int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata,
*datalen = bytes_read; *datalen = bytes_read;
if (verbose) { if (verbose) {
PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " bytes from binary file " _YELLOW_("%s"), bytes_read, preferredName); PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " bytes from binary file `" _YELLOW_("%s") "`", bytes_read, preferredName);
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -936,7 +937,7 @@ int loadFileEML_safe(const char *preferredName, void **pdata, size_t *datalen) {
} }
} }
fclose(f); fclose(f);
PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " bytes from text file " _YELLOW_("%s"), counter, preferredName); PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " bytes from text file `" _YELLOW_("%s") "`", counter, preferredName);
uint8_t *newdump = realloc(*pdata, counter); uint8_t *newdump = realloc(*pdata, counter);
@ -1023,7 +1024,7 @@ int loadFileMCT_safe(const char *preferredName, void **pdata, size_t *datalen) {
} }
} }
fclose(f); fclose(f);
PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " bytes from MCT file " _YELLOW_("%s"), counter, preferredName); PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " bytes from MCT file `" _YELLOW_("%s") "`", counter, preferredName);
uint8_t *newdump = realloc(*pdata, counter); uint8_t *newdump = realloc(*pdata, counter);
@ -1059,7 +1060,7 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
json_error_t error; json_error_t error;
json_t *root = json_load_file(path, 0, &error); json_t *root = json_load_file(path, 0, &error);
if (verbose) if (verbose)
PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), path); PrintAndLogEx(SUCCESS, "loaded from JSON file `" _YELLOW_("%s") "`", path);
free(path); free(path);
@ -1467,7 +1468,7 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale
} }
fclose(f); fclose(f);
if (verbose) if (verbose)
PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " keys from dictionary file " _YELLOW_("%s"), vkeycnt, path); PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") " keys from dictionary file `" _YELLOW_("%s") "`", vkeycnt, path);
if (datalen) if (datalen)
*datalen = counter; *datalen = counter;