From 4d2b2f0c646b19b5eb16570862f96b6be50fbf81 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sat, 19 Sep 2020 11:45:19 -0400 Subject: [PATCH 1/2] add ST25TA password change logic --- client/src/cmdhfst.c | 149 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 758447d6a..e95eced6b 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -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 n "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " p : 16 byte write password"); + PrintAndLogEx(NORMAL, " : Change (r)ead or (w)rite password"); + PrintAndLogEx(NORMAL, " n : 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} }; From 69cdf10350dad0bd7e6a10d069fe1809757a9269 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sat, 19 Sep 2020 12:02:04 -0400 Subject: [PATCH 2/2] rework ST25TA usage text to follow standards --- client/src/cmdhfst.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index e95eced6b..acb6ee361 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -54,12 +54,12 @@ static int usage_hf_st_ndef(void) { static int usage_hf_st_protect(void) { PrintAndLogEx(NORMAL, "\n Change R/W protection for NFC Data Exchange Format (NDEF)\n"); - PrintAndLogEx(NORMAL, "Usage: hf st protect [h] p "); + PrintAndLogEx(NORMAL, "Usage: hf st protect [h] p r|w [0|1]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " p : 16 byte write password"); - PrintAndLogEx(NORMAL, " : Change (r)ead or (w)rite protection"); - PrintAndLogEx(NORMAL, " t : Enable / Disable protection"); + PrintAndLogEx(NORMAL, " r|w : Change (r)ead or (w)rite protection"); + PrintAndLogEx(NORMAL, " [0|1] : Enable / Disable protection"); PrintAndLogEx(NORMAL, " 0 = Disable (default)"); PrintAndLogEx(NORMAL, " 1 = Enable"); PrintAndLogEx(NORMAL, "Examples:"); @@ -69,12 +69,12 @@ static int usage_hf_st_protect(void) { 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 n "); + PrintAndLogEx(NORMAL, "Usage: hf st pwd [h] p r|w n "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " p : 16 byte write password"); - PrintAndLogEx(NORMAL, " : Change (r)ead or (w)rite password"); - PrintAndLogEx(NORMAL, " n : New 16 byte password"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " p : 16 byte write password"); + PrintAndLogEx(NORMAL, " r|w : Change (r)ead or (w)rite password"); + PrintAndLogEx(NORMAL, " n : New 16 byte password"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" hf st pwd p 82E80053D4CA5C0B656D852CC696C8A1 r n 00000000000000000000000000000000")); return PM3_SUCCESS;