mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
commit
007df35266
4 changed files with 232 additions and 206 deletions
|
@ -4270,10 +4270,15 @@ static void arg_cat_optionv(char *dest,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datatype) {
|
if (datatype) {
|
||||||
if (longopts)
|
/* if (longopts)
|
||||||
arg_cat(&dest, "=", &ndest);
|
arg_cat(&dest, "=", &ndest);
|
||||||
else if (shortopts)
|
else if (shortopts)
|
||||||
arg_cat(&dest, " ", &ndest);
|
arg_cat(&dest, " ", &ndest);
|
||||||
|
*/
|
||||||
|
if (longopts)
|
||||||
|
arg_cat(&dest, " ", &ndest);
|
||||||
|
else if (shortopts)
|
||||||
|
arg_cat(&dest, " ", &ndest);
|
||||||
|
|
||||||
if (optvalue) {
|
if (optvalue) {
|
||||||
arg_cat(&dest, "[", &ndest);
|
arg_cat(&dest, "[", &ndest);
|
||||||
|
|
|
@ -69,7 +69,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
|
PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:"));
|
||||||
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
|
PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName);
|
||||||
arg_print_syntaxv(stdout, ctx->argtable, "\n\n");
|
arg_print_syntax(stdout, ctx->argtable, "\n\n");
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
|
PrintAndLogEx(NORMAL, _SectionTagColor_("options:"));
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h" // clearCommandBuffer
|
#include "comms.h" // clearCommandBuffer
|
||||||
#include "cmdtrace.h"
|
#include "cmdtrace.h"
|
||||||
|
#include "cliparser.h"
|
||||||
#include "crc16.h"
|
#include "crc16.h"
|
||||||
#include "cmdhf14a.h"
|
#include "cmdhf14a.h"
|
||||||
#include "protocols.h" // definitions of ISO14A/7816 protocol
|
#include "protocols.h" // definitions of ISO14A/7816 protocol
|
||||||
|
@ -21,65 +22,9 @@
|
||||||
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
|
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
|
||||||
|
|
||||||
#define TIMEOUT 2000
|
#define TIMEOUT 2000
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
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)
|
// get ST Microelectronics chip model (from UID)
|
||||||
static char *get_st_chip_model(uint8_t pc) {
|
static char *get_st_chip_model(uint8_t pc) {
|
||||||
static char model[40];
|
static char model[40];
|
||||||
|
@ -348,26 +293,44 @@ int infoHF_ST(void) {
|
||||||
return PM3_SUCCESS;
|
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) {
|
static int cmd_hf_st_info(const char *Cmd) {
|
||||||
char c = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (c == 'h') return usage_hf_st_info();
|
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();
|
return infoHF_ST();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_hf_st_sim(const char *Cmd) {
|
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;
|
int uidlen = 0;
|
||||||
uint8_t cmdp = 0;
|
|
||||||
uint8_t uid[7] = {0};
|
uint8_t uid[7] = {0};
|
||||||
if (c == 'u') {
|
|
||||||
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
CLIParserContext *ctx;
|
||||||
uidlen >>= 1;
|
CLIParserInit(&ctx, "hf st sim",
|
||||||
|
"Emulating ST25TA512B tag with 7 byte UID",
|
||||||
|
"hf st sim -u 02E2007D0FCA4C\n");
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str1("u", "uid", "<hex>", "7 byte UID"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
CLIGetHexWithReturn(ctx, 1, uid, &uidlen);
|
||||||
|
|
||||||
if (uidlen != 7) {
|
if (uidlen != 7) {
|
||||||
return usage_hf_st_sim();
|
PrintAndLogEx(ERR, "UID must be 7 hex bytes");
|
||||||
}
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
char param[40];
|
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) {
|
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;
|
int pwdlen = 0;
|
||||||
uint8_t cmdp = 0;
|
|
||||||
uint8_t pwd[16] = {0};
|
uint8_t pwd[16] = {0};
|
||||||
if (c == 'p') {
|
bool with_pwd = false;
|
||||||
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
|
|
||||||
pwdlen >>= 1;
|
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) {
|
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;
|
bool activate_field = true;
|
||||||
|
@ -429,6 +406,7 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (with_pwd) {
|
||||||
// --------------- VERIFY ----------------
|
// --------------- VERIFY ----------------
|
||||||
uint8_t aVERIFY[30];
|
uint8_t aVERIFY[30];
|
||||||
int aVERIFY_n = 0;
|
int aVERIFY_n = 0;
|
||||||
|
@ -452,6 +430,7 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keep_field_on = false;
|
keep_field_on = false;
|
||||||
uint8_t aREAD_NDEF[30];
|
uint8_t aREAD_NDEF[30];
|
||||||
|
@ -473,57 +452,72 @@ static int cmd_hf_st_ndef(const char *Cmd) {
|
||||||
|
|
||||||
static int cmd_hf_st_protect(const char *Cmd) {
|
static int cmd_hf_st_protect(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t cmdp = 0;
|
|
||||||
bool errors = false;
|
|
||||||
int pwdlen = 0;
|
int pwdlen = 0;
|
||||||
uint8_t pwd[16] = {0};
|
uint8_t pwd[16] = {0};
|
||||||
int statelen = 3;
|
int statelen = 3;
|
||||||
uint8_t state[3] = {0x26, 0, 0};
|
uint8_t state[3] = {0x26, 0, 0x02};
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
bool disable_protection = false;
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
bool enable_protection = false;
|
||||||
case 'h':
|
bool read_protection = false;
|
||||||
return usage_hf_st_protect();
|
bool write_protection = false;
|
||||||
case '0':
|
|
||||||
state[0] = 0x26; //Disable protection
|
CLIParserContext *ctx;
|
||||||
cmdp++;
|
CLIParserInit(&ctx, "hf st protect",
|
||||||
break;
|
"Change read or write protection for NFC Data Exchange Format (NDEF) file on ST25TA",
|
||||||
case '1':
|
"hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -r -e -> enable read protection\n"
|
||||||
state[0] = 0x28; //Enable protection
|
"hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -w -d -> disable write protection\n");
|
||||||
cmdp++;
|
|
||||||
break;
|
void *argtable[] = {
|
||||||
case 'r':
|
arg_param_begin,
|
||||||
state[2] = 0x01;
|
arg_lit0("e", "enable", "enable protection"),
|
||||||
cmdp++;
|
arg_lit0("d", "disable", "disable protection (default)"),
|
||||||
break;
|
arg_lit0("r", "read", "change read protection"),
|
||||||
case 'w':
|
arg_lit0("w", "write", "change write protection (default)"),
|
||||||
state[2] = 0x02;
|
arg_str1("p", "password", "<hex>", "16 byte write password"),
|
||||||
cmdp++;
|
arg_param_end
|
||||||
break;
|
};
|
||||||
case 'p':
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen);
|
|
||||||
pwdlen >>= 1;
|
enable_protection = arg_get_lit(ctx, 1);
|
||||||
cmdp += 2;
|
disable_protection = arg_get_lit(ctx, 2);
|
||||||
break;
|
read_protection = arg_get_lit(ctx, 3);
|
||||||
default:
|
write_protection = arg_get_lit(ctx, 4);
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen);
|
||||||
break;
|
|
||||||
}
|
CLIParserFree(ctx);
|
||||||
}
|
|
||||||
|
|
||||||
//Validations
|
//Validations
|
||||||
|
|
||||||
if (state[2] == 0x00) {
|
if (enable_protection && disable_protection) {
|
||||||
PrintAndLogEx(WARNING, "Missing action (r)ead or (w)rite");
|
PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both");
|
||||||
errors = true;
|
return PM3_EINVARG;
|
||||||
|
} else {
|
||||||
|
if (enable_protection) {
|
||||||
|
state[0] = 0x28;
|
||||||
|
}
|
||||||
|
if (disable_protection) {
|
||||||
|
state[0] = 0x26;
|
||||||
}
|
}
|
||||||
if (pwdlen != 16) {
|
|
||||||
PrintAndLogEx(WARNING, "Missing 16 byte password");
|
|
||||||
errors = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 activate_field = true;
|
||||||
bool keep_field_on = true;
|
bool keep_field_on = true;
|
||||||
|
@ -603,62 +597,62 @@ static int cmd_hf_st_protect(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_hf_st_pwd(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;
|
int pwdlen = 0;
|
||||||
uint8_t pwd[16] = {0};
|
uint8_t pwd[16] = {0};
|
||||||
int newpwdlen = 0;
|
int newpwdlen = 0;
|
||||||
uint8_t newpwd[16] = {0};
|
uint8_t newpwd[16] = {0};
|
||||||
int changePwdlen = 4;
|
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) {
|
CLIParserContext *ctx;
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
CLIParserInit(&ctx, "hf st pwd",
|
||||||
case 'h':
|
"Change read or write password for NFC Data Exchange Format (NDEF) file on ST25TA",
|
||||||
return usage_hf_st_pwd();
|
"hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -r -n 00000000000000000000000000000000 -> change read password\n"
|
||||||
case 'r':
|
"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;
|
changePwd[2] = 0x01;
|
||||||
cmdp++;
|
}
|
||||||
break;
|
if (change_write_password) {
|
||||||
case 'w':
|
|
||||||
changePwd[2] = 0x02;
|
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
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (changePwd[2] == 0x00) {
|
|
||||||
PrintAndLogEx(WARNING, "Missing password specification: (r)ead or (w)rite");
|
|
||||||
errors = true;
|
|
||||||
}
|
|
||||||
if (pwdlen != 16) {
|
if (pwdlen != 16) {
|
||||||
PrintAndLogEx(WARNING, "Missing original 16 byte password");
|
PrintAndLogEx(ERR, "Original write password must be 16 hex bytes");
|
||||||
errors = true;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
if (newpwdlen != 16) {
|
if (newpwdlen != 16) {
|
||||||
PrintAndLogEx(WARNING, "Missing new 16 byte password");
|
PrintAndLogEx(ERR, "New password must be 16 hex bytes");
|
||||||
errors = true;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
if (errors || cmdp == 0) return usage_hf_st_pwd();
|
|
||||||
|
|
||||||
bool activate_field = true;
|
bool activate_field = true;
|
||||||
bool keep_field_on = true;
|
bool keep_field_on = true;
|
||||||
|
|
|
@ -10,16 +10,30 @@ hf 14b raw -ss
|
||||||
lf search 1
|
lf search 1
|
||||||
lf config h H
|
lf config h H
|
||||||
```
|
```
|
||||||
In order to counter this and unify it, there was discussion over at the official repository a few years ago (link to issue) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
|
even the external tools which we collected into this repo, under folder */tools/* folder uses their own argument parsing.
|
||||||
|
|
||||||
|
|
||||||
|
In order to counter this and unify it, there was discussion over at the official repository a few years ago [link to issue](https://github.com/Proxmark/proxmark3/issues/467) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
|
||||||
|
|
||||||
```
|
```
|
||||||
emv
|
[usb] pm3 --> emv
|
||||||
hf fido
|
[usb] pm3 --> hf fido
|
||||||
```
|
```
|
||||||
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there. Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client. After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way. The aftermath was a design and layout specfied which lead to a simpler implemtentation of the cliparser in the client source code while still unfiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
|
||||||
|
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there.
|
||||||
|
|
||||||
|
Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client.
|
||||||
|
After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way.
|
||||||
|
|
||||||
|
The aftermath was a design and layout specfied which lead to a simpler implemtentation of the cliparser in the client source code while still unfiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
Furthermore @mrwalker offered to take notes and thus this document was created.
|
||||||
|
|
||||||
|
This is the _new_ and _prefered_ way to implement _helptext_ and _cli parsing_ for Proxmark3 client commands and it's external tools.
|
||||||
|
|
||||||
|
|
||||||
## cliparser setup and use
|
## cliparser setup and use
|
||||||
|
|
||||||
|
@ -28,11 +42,11 @@ It will also add the `-h --help` option automatic.
|
||||||
|
|
||||||
## design comments
|
## design comments
|
||||||
|
|
||||||
* where possiable all options should be lowercase.
|
* where possible all options should be lowercase.
|
||||||
* extended options preceeded with -- should be short
|
* extended options preceded with -- should be short
|
||||||
* options provided directly (without an option identifier) should be avoided.
|
* options provided directly (without an option identifier) should be avoided.
|
||||||
* -vv for extra verbos should be avoided; use of debug level is prefered.
|
* -vv for extra verbos should be avoided; use of debug level is preferred.
|
||||||
* with --options the equal is not needed (will work with and without) so dont use '='
|
* with --options the equal is not needed (will work with and without) so don't use '='
|
||||||
e.g. cmd --cn 12345
|
e.g. cmd --cn 12345
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,10 +76,10 @@ In the command function, setup the context
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
|
||||||
|
|
||||||
### define the text
|
### define the context
|
||||||
CLIParserInit (\<context\>, \<description\>, \<notes\n examples ... \>);
|
CLIParserInit (\<context\>, \<description\>, \<notes\n examples ... \>);
|
||||||
|
|
||||||
use -> to seperate example and example comment and \\n to seperate examples.
|
use -> to separate example and example comment and \\n to separate examples.
|
||||||
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
|
||||||
|
|
||||||
CLIParserInit(&ctx, "lf indala clone",
|
CLIParserInit(&ctx, "lf indala clone",
|
||||||
|
@ -92,18 +106,25 @@ _All options has a parameter index, since `-h --help` is added automatic, it wi
|
||||||
Hence all options you add will start at index 1 and upwards._
|
Hence all options you add will start at index 1 and upwards._
|
||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
booleen : arg_lit0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
**bool option. true if supplied**
|
||||||
|
bool : arg_lit0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
**integer**
|
**integer that is optional**
|
||||||
optional integer : arg_int0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
|
optional integer : arg_int0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
|
**integer that is required**
|
||||||
required integer : arg_int1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
required integer : arg_int1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
**Strings 0 or 1**
|
**String option that is optional and only one instance can be provided**
|
||||||
optional string : arg_str0("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
|
optional string : arg_str0("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
|
**String option that is required and only one instance can be provided**
|
||||||
required string : arg_str1("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
required string : arg_str1("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
**Strings x to 250**
|
**String option that is optional and can have up to 250 instances provided**
|
||||||
optional string : arg_strx0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
|
optional string : arg_strx0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
|
**String option that is required/at least one instance and can have up to 250 instances**
|
||||||
required string : arg_strx1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
required string : arg_strx1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
|
||||||
|
|
||||||
**if an option does not have a short or long option, use NULL in its place**
|
**if an option does not have a short or long option, use NULL in its place**
|
||||||
|
@ -119,6 +140,12 @@ Once you have extracted the options, cleanup the context.
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
### retreiving options
|
### retreiving options
|
||||||
|
|
||||||
|
|
||||||
|
The parser will format and color and layout as needed.
|
||||||
|
It will also add the `-h --help` option automatic.
|
||||||
|
|
||||||
|
|
||||||
**bool option**
|
**bool option**
|
||||||
arg_get_lit(\<context\>, \<opt index\>);
|
arg_get_lit(\<context\>, \<opt index\>);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue