add ST25TA password change logic

This commit is contained in:
tcprst 2020-09-19 11:45:19 -04:00
commit 4d2b2f0c64
No known key found for this signature in database
GPG key ID: 9145EAF5121AED25

View file

@ -67,6 +67,19 @@ static int usage_hf_st_protect(void) {
return PM3_SUCCESS;
}
static int usage_hf_st_pwd(void) {
PrintAndLogEx(NORMAL, "\n Change R/W password for NFC Data Exchange Format (NDEF)\n");
PrintAndLogEx(NORMAL, "Usage: hf st pwd [h] p <pwd> <r|w> n <pwd>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " p <pwd> : 16 byte write password");
PrintAndLogEx(NORMAL, " <r|w> : Change (r)ead or (w)rite password");
PrintAndLogEx(NORMAL, " n <pwd> : New 16 byte password");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st pwd p 82E80053D4CA5C0B656D852CC696C8A1 r n 00000000000000000000000000000000"));
return PM3_SUCCESS;
}
// get ST Microelectronics chip model (from UID)
static char *get_st_chip_model(uint8_t pc) {
static char model[40];
@ -589,6 +602,141 @@ static int cmd_hf_st_protect(const char *Cmd) {
return PM3_SUCCESS;
}
static int cmd_hf_st_pwd(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h' || c == 0x00) return usage_hf_st_pwd();
uint8_t cmdp = 0;
bool errors = false;
int pwdlen = 0;
uint8_t pwd[16] = {0};
int newpwdlen = 0;
uint8_t newpwd[16] = {0};
int changePwdlen = 4;
uint8_t changePwd[4] = {0x24, 0x00, 0x00, 0x10};
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_st_pwd();
case 'r':
changePwd[2] = 0x01;
cmdp++;
break;
case 'w':
changePwd[2] = 0x02;
cmdp++;
break;
case 'p':
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
pwdlen >>= 1;
cmdp += 2;
break;
case 'n':
param_gethex_ex(Cmd, cmdp + 1, newpwd, &newpwdlen);
newpwdlen >>= 1;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations
if (changePwd[2] == 0x00) {
PrintAndLogEx(WARNING, "Missing password specification: (r)ead or (w)rite");
errors = true;
}
if (pwdlen != 16) {
PrintAndLogEx(WARNING, "Missing original 16 byte password");
errors = true;
}
if (newpwdlen != 16) {
PrintAndLogEx(WARNING, "Missing new 16 byte password");
errors = true;
}
if (errors || cmdp == 0) return usage_hf_st_pwd();
bool activate_field = true;
bool keep_field_on = true;
uint8_t response[PM3_CMD_DATA_SIZE];
int resplen = 0;
// --------------- Select NDEF Tag application ----------------
uint8_t aSELECT_AID[80];
int aSELECT_AID_n = 0;
param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
if (resplen < 2)
return PM3_ESOFT;
uint16_t sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
activate_field = false;
keep_field_on = true;
// --------------- Select NDEF file ----------------
uint8_t aSELECT_FILE_NDEF[30];
int aSELECT_FILE_NDEF_n = 0;
param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
// --------------- VERIFY ----------------
uint8_t aVERIFY[30];
int aVERIFY_n = 0;
// need to provide 16byte password
param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
// --------------- Change password ----------------
keep_field_on = false;
uint8_t aCHG_PWD[30];
int aCHG_PWD_n = 0;
param_gethex_to_eol("00", 0, aCHG_PWD, sizeof(aCHG_PWD), &aCHG_PWD_n);
memcpy(aCHG_PWD + aCHG_PWD_n, changePwd, changePwdlen);
memcpy(aCHG_PWD + aCHG_PWD_n + changePwdlen, newpwd, newpwdlen);
res = ExchangeAPDU14a(aCHG_PWD, aCHG_PWD_n + changePwdlen + newpwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw != 0x9000) {
PrintAndLogEx(ERR, "password change failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write"));
return PM3_SUCCESS;
}
static int cmd_hf_st_list(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
@ -602,6 +750,7 @@ static command_t CommandTable[] = {
{"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"},
{"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"},
{"protect", cmd_hf_st_protect, IfPm3Iso14443a, "change protection on tag"},
{"pwd", cmd_hf_st_pwd, IfPm3Iso14443a, "change password on tag"},
{"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"},
{NULL, NULL, NULL, NULL}
};