hf st commands - now use cliparser

This commit is contained in:
tcprst 2020-10-02 21:23:03 -04:00
commit 3787c6e991
No known key found for this signature in database
GPG key ID: 9145EAF5121AED25

View file

@ -14,6 +14,7 @@
#include "cmdparser.h" // command_t
#include "comms.h" // clearCommandBuffer
#include "cmdtrace.h"
#include "cliparser.h"
#include "crc16.h"
#include "cmdhf14a.h"
#include "protocols.h" // definitions of ISO14A/7816 protocol
@ -21,65 +22,9 @@
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
#define TIMEOUT 2000
static int CmdHelp(const char *Cmd);
static int usage_hf_st_info(void) {
PrintAndLogEx(NORMAL, "Usage: hf st info [h]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st info"));
return PM3_SUCCESS;
}
static int usage_hf_st_sim(void) {
PrintAndLogEx(NORMAL, "\n Emulating ST25TA512B tag with 7 byte UID\n");
PrintAndLogEx(NORMAL, "Usage: hf st sim [h] u <uid> ");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " u : 7 byte UID");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st sim u 02E2007D0FCA4C"));
return PM3_SUCCESS;
}
static int usage_hf_st_ndef(void) {
PrintAndLogEx(NORMAL, "\n Print NFC Data Exchange Format (NDEF)\n");
PrintAndLogEx(NORMAL, "Usage: hf st ndef [h] p <pwd> ");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " p <pwd> : 16 byte password");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st ndef p 82E80053D4CA5C0B656D852CC696C8A1"));
return PM3_SUCCESS;
}
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 <pwd> r|w [0|1]");
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 protection");
PrintAndLogEx(NORMAL, " [0|1] : Enable / Disable protection");
PrintAndLogEx(NORMAL, " 0 = Disable (default)");
PrintAndLogEx(NORMAL, " 1 = Enable");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf st protect p 82E80053D4CA5C0B656D852CC696C8A1 r 0"));
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 <newpwd>");
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 <newpwd> : 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];
@ -348,26 +293,44 @@ int infoHF_ST(void) {
return PM3_SUCCESS;
}
// menu command to get and print all info known about any known 14b tag
// menu command to get and print all info known about any known ST25TA tag
static int cmd_hf_st_info(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h') return usage_hf_st_info();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf st info",
"Get info about ST25TA tag",
"hf st info"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
return infoHF_ST();
}
static int cmd_hf_st_sim(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h' || c == 0x00) return usage_hf_st_sim();
int uidlen = 0;
uint8_t cmdp = 0;
uint8_t uid[7] = {0};
if (c == 'u') {
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
uidlen >>= 1;
if (uidlen != 7) {
return usage_hf_st_sim();
}
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf st sim",
"Emulating ST25TA512B tag with 7 byte UID",
"hf st sim -u 02E2007D0FCA4C\n");
void *argtable[] = {
arg_param_begin,
arg_strx1("u", "uid", "<hex>", "7 byte UID"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
if (uidlen != 7) {
PrintAndLogEx(ERR, "UID must be 7 hex bytes");
return PM3_EINVARG;
}
char param[40];
@ -376,18 +339,32 @@ static int cmd_hf_st_sim(const char *Cmd) {
}
static int cmd_hf_st_ndef(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h' || c == 0x00) return usage_hf_st_ndef();
int pwdlen = 0;
uint8_t cmdp = 0;
uint8_t pwd[16] = {0};
if (c == 'p') {
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
pwdlen >>= 1;
bool with_pwd = false;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf st ndef",
"Read NFC Data Exchange Format (NDEF) file on ST25TA",
"hf st ndef -p 82E80053D4CA5C0B656D852CC696C8A1\n");
void *argtable[] = {
arg_param_begin,
arg_str0("p", "password", "<hex>", "16 byte read password"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIGetHexWithReturn(ctx, 1, pwd, &pwdlen);
if (pwdlen == 0) {
with_pwd = false;
} else {
if (pwdlen != 16) {
return usage_hf_st_ndef();
PrintAndLogEx(ERR, "Password must be 16 hex bytes");
return PM3_EINVARG;
}
with_pwd = true;
}
bool activate_field = true;
@ -429,27 +406,29 @@ static int cmd_hf_st_ndef(const char *Cmd) {
return PM3_ESOFT;
}
// --------------- VERIFY ----------------
uint8_t aVERIFY[30];
int aVERIFY_n = 0;
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
if (res)
return res;
sw = get_sw(response, resplen);
if (sw == 0x6300) {
// need to provide 16byte password
param_gethex_to_eol("0020000110", 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 (with_pwd) {
// --------------- VERIFY ----------------
uint8_t aVERIFY[30];
int aVERIFY_n = 0;
param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n);
res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, 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;
if (sw == 0x6300) {
// need to provide 16byte password
param_gethex_to_eol("0020000110", 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;
}
}
}
@ -473,57 +452,72 @@ static int cmd_hf_st_ndef(const char *Cmd) {
static int cmd_hf_st_protect(const char *Cmd) {
uint8_t cmdp = 0;
bool errors = false;
int pwdlen = 0;
uint8_t pwd[16] = {0};
int statelen = 3;
uint8_t state[3] = {0x26, 0, 0};
uint8_t state[3] = {0x26, 0, 0x02};
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_st_protect();
case '0':
state[0] = 0x26; //Disable protection
cmdp++;
break;
case '1':
state[0] = 0x28; //Enable protection
cmdp++;
break;
case 'r':
state[2] = 0x01;
cmdp++;
break;
case 'w':
state[2] = 0x02;
cmdp++;
break;
case 'p':
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
pwdlen >>= 1;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
bool disable_protection = false;
bool enable_protection = false;
bool read_protection = false;
bool write_protection = false;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf st protect",
"Change read or write protection for NFC Data Exchange Format (NDEF) file on ST25TA",
"hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -r -e -> enable read protection\n"
"hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -w -d -> disable write protection\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("e", "enable", "enable protection"),
arg_lit0("d", "disable", "disable protection (default)"),
arg_lit0("r", "read", "change read protection"),
arg_lit0("w", "write", "change write protection (default)"),
arg_str1("p", "password", "<hex>", "16 byte write password"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
enable_protection = arg_get_lit(ctx, 1);
disable_protection = arg_get_lit(ctx, 2);
read_protection = arg_get_lit(ctx, 3);
write_protection = arg_get_lit(ctx, 4);
CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen);
CLIParserFree(ctx);
//Validations
if (state[2] == 0x00) {
PrintAndLogEx(WARNING, "Missing action (r)ead or (w)rite");
errors = true;
}
if (pwdlen != 16) {
PrintAndLogEx(WARNING, "Missing 16 byte password");
errors = true;
if (enable_protection && disable_protection) {
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
return PM3_EINVARG;
} else {
if (enable_protection) {
state[0] = 0x28;
}
if (disable_protection) {
state[0] = 0x26;
}
}
if (errors || cmdp == 0) return usage_hf_st_protect();
if (read_protection && write_protection) {
PrintAndLogEx(ERR, "Must specify either read or write protection, not both");
return PM3_EINVARG;
} else {
if (read_protection) {
state[2] = 0x01;
}
if (write_protection) {
state[2] = 0x02;
}
}
if (pwdlen != 16) {
PrintAndLogEx(ERR, "Missing 16 byte password");
return PM3_EINVARG;
}
bool activate_field = true;
bool keep_field_on = true;
@ -603,63 +597,63 @@ static int cmd_hf_st_protect(const char *Cmd) {
}
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};
uint8_t changePwd[4] = {0x24, 0x00, 0x01, 0x10};
bool change_read_password = false;
bool change_write_password = false;
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;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf st pwd",
"Change read or write password for NFC Data Exchange Format (NDEF) file on ST25TA",
"hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -r -n 00000000000000000000000000000000 -> change read password\n"
"hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -w -n 00000000000000000000000000000000 -> change write password\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("r", "read", "change the read password (default)"),
arg_lit0("w", "write", "change the write password"),
arg_str1("p", "password", "<hex>", "current 16 byte write password"),
arg_str1("n", "new", "<hex>", "new 16 byte password"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
change_read_password = arg_get_lit(ctx, 1);
change_write_password = arg_get_lit(ctx, 2);
CLIGetHexWithReturn(ctx, 3, pwd, &pwdlen);
CLIGetHexWithReturn(ctx, 4, newpwd, &newpwdlen);
if (change_read_password && change_write_password) {
PrintAndLogEx(ERR, "Must specify either read or write, not both");
CLIParserFree(ctx);
return PM3_EINVARG;
} else {
if (change_read_password) {
changePwd[2] = 0x01;
}
if (change_write_password) {
changePwd[2] = 0x02;
}
}
//Validations
CLIParserFree(ctx);
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;
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
return PM3_EINVARG;
}
if (newpwdlen != 16) {
PrintAndLogEx(WARNING, "Missing new 16 byte password");
errors = true;
PrintAndLogEx(ERR, "New password must be 16 hex bytes");
return PM3_EINVARG;
}
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];
@ -745,13 +739,13 @@ static int cmd_hf_st_list(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"},
{"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"},
{"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"},
{"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"},
{"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}
};