mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
fix lf em 4x05 write - pwd/data. t55xx chk - now uses cliparser, and color to cliparser empty message
This commit is contained in:
parent
7f78b0a85d
commit
fdcc4b741c
5 changed files with 197 additions and 124 deletions
|
@ -118,7 +118,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta
|
||||||
if (nerrors > 0) {
|
if (nerrors > 0) {
|
||||||
/* Display the error details contained in the arg_end struct.*/
|
/* Display the error details contained in the arg_end struct.*/
|
||||||
arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
|
arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
|
||||||
PrintAndLogEx(WARNING, "Try '%s --help' for more information.\n", ctx->programName);
|
PrintAndLogEx(WARNING, "Try " _YELLOW_("'%s --help'") " for more information.\n", ctx->programName);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
@ -269,15 +269,19 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hexstr -> u64, w optional len input and default value fallback.
|
||||||
|
// 0 = failed
|
||||||
|
// 1 = OK
|
||||||
|
// 3 = optional param - not set
|
||||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
|
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def) {
|
||||||
uint64_t rv = 0;
|
uint64_t rv = 0;
|
||||||
uint8_t data[8];
|
uint8_t d[8];
|
||||||
int datalen = 0;
|
int dlen = 0;
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), data, sizeof(data), &datalen);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &dlen);
|
||||||
if (res == 0 && datalen > 0) {
|
if (res == 0 && dlen > 0) {
|
||||||
for (uint8_t i = 0; i < datalen; i++) {
|
for (uint8_t i = 0; i < dlen; i++) {
|
||||||
rv <<= 8;
|
rv <<= 8;
|
||||||
rv |= data[i];
|
rv |= d[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rv = def;
|
rv = def;
|
||||||
|
@ -285,11 +289,38 @@ uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out) {
|
// hexstr -> u64, w optional len input and default value fallback.
|
||||||
return arg_get_u32_hexstr_def_nlen(ctx, paramnum, def, out, 4);
|
// 0 = failed
|
||||||
|
// 1 = OK
|
||||||
|
// 2 = wrong len param, use default
|
||||||
|
// 3 = optional param, if fail, use default.
|
||||||
|
int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional) {
|
||||||
|
int n = 0;
|
||||||
|
uint8_t d[nlen];
|
||||||
|
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &n);
|
||||||
|
if (res == 0 && n == nlen) {
|
||||||
|
uint64_t rv = 0;
|
||||||
|
for (uint8_t i = 0; i < n; i++) {
|
||||||
|
rv <<= 8;
|
||||||
|
rv |= d[i];
|
||||||
|
}
|
||||||
|
*out = rv;
|
||||||
|
return 1;
|
||||||
|
} else if (res == 0 && n) {
|
||||||
|
*out = def;
|
||||||
|
return 2;
|
||||||
|
} else if (res == 0 && n == 0 && optional) {
|
||||||
|
*out = def;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen) {
|
int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out) {
|
||||||
|
return arg_get_u32_hexstr_def_nlen(ctx, paramnum, def, out, 4, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen, bool optional) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
uint8_t d[nlen];
|
uint8_t d[nlen];
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &n);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, paramnum), d, sizeof(d), &n);
|
||||||
|
@ -304,6 +335,9 @@ int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_
|
||||||
} else if (res == 0 && n) {
|
} else if (res == 0 && n) {
|
||||||
*out = def;
|
*out = def;
|
||||||
return 2;
|
return 2;
|
||||||
|
} else if (res == 0 && n == 0 && optional) {
|
||||||
|
*out = def;
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,13 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
|
||||||
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
|
||||||
|
|
||||||
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
|
uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def);
|
||||||
|
int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional);
|
||||||
int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out);
|
int arg_get_u32_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out);
|
||||||
int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen);
|
int arg_get_u32_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint32_t def, uint32_t *out, uint8_t nlen, bool optional);
|
||||||
|
|
||||||
|
#define CP_SUCCESS_OPTIONAL 1
|
||||||
|
#define CP_SUCCESS 0
|
||||||
|
#define CP_ENOPARAM -1
|
||||||
|
#define CP_WRONGLEN -2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -170,6 +170,14 @@ static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0xFF - ( n1 ^ n... )
|
||||||
|
static uint16_t calcXORchecksum(uint8_t *bytes, uint8_t len, uint32_t mask) {
|
||||||
|
return 0xFF - calcSumByteXor(bytes, len, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//2148050707DB0A0E000001C4000000
|
||||||
|
|
||||||
// measuring LFSR maximum length
|
// measuring LFSR maximum length
|
||||||
static int CmdAnalyseLfsr(const char *Cmd) {
|
static int CmdAnalyseLfsr(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
@ -421,11 +429,12 @@ static int CmdAnalyseCHKSUM(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "Mask value 0x%x", mask);
|
PrintAndLogEx(INFO, "Mask value 0x%x", mask);
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, " add | sub | add 1's compl | sub 1's compl | xor");
|
PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+------------------+-----------+-------------");
|
||||||
PrintAndLogEx(INFO, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |");
|
PrintAndLogEx(INFO, " add | sub | add 1's compl | sub 1's compl | xor | |");
|
||||||
PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+--------------------");
|
PrintAndLogEx(INFO, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD | 0xFF - (n^n)");
|
||||||
|
PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+------------------+-----------+-------------");
|
||||||
}
|
}
|
||||||
PrintAndLogEx(INFO, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n",
|
PrintAndLogEx(INFO, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X\n",
|
||||||
calcSumByteAdd(data, dlen, mask)
|
calcSumByteAdd(data, dlen, mask)
|
||||||
, calcSumNibbleAdd(data, dlen, mask)
|
, calcSumNibbleAdd(data, dlen, mask)
|
||||||
, calcSumCrumbAdd(data, dlen, mask)
|
, calcSumCrumbAdd(data, dlen, mask)
|
||||||
|
@ -441,6 +450,7 @@ static int CmdAnalyseCHKSUM(const char *Cmd) {
|
||||||
, calcSumCrumbXor(data, dlen, mask)
|
, calcSumCrumbXor(data, dlen, mask)
|
||||||
, calcBSDchecksum8(data, dlen, mask)
|
, calcBSDchecksum8(data, dlen, mask)
|
||||||
, calcBSDchecksum4(data, dlen, mask)
|
, calcBSDchecksum4(data, dlen, mask)
|
||||||
|
, calcXORchecksum(data, dlen, mask)
|
||||||
);
|
);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -773,15 +773,38 @@ int CmdEM4x05Write(const char *Cmd) {
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_int0("a", "addr", "<dec>", "memory address to write to. (0-13)"),
|
arg_int0("a", "addr", "<dec>", "memory address to write to. (0-13)"),
|
||||||
arg_str1("d", "data", "<hex>", "data to write, 4 bytes hex"),
|
arg_str1("d", "data", "<hex>", "data to write (4 hex bytes)"),
|
||||||
arg_str0("p", "pwd", "<hex>", "optional - password, 4 bytes hex"),
|
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
|
||||||
arg_lit0(NULL, "po", "protect operation"),
|
arg_lit0(NULL, "po", "protect operation"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
uint8_t addr = (uint8_t)arg_get_int_def(ctx, 1, 50);
|
uint8_t addr = (uint8_t)arg_get_int_def(ctx, 1, 50);
|
||||||
uint32_t data = arg_get_u32(ctx, 2);
|
uint32_t data = 0;
|
||||||
uint64_t inputpwd = arg_get_u64_hexstr_def(ctx, 3, 0xFFFFFFFFFFFFFFFF);
|
int res = arg_get_u32_hexstr_def(ctx, 2, 0, &data);
|
||||||
|
if (res == 2) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "Data must be 4 hex bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if (res == 0) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "Data must be 4 hex bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool use_pwd = false;
|
||||||
|
uint32_t pwd = 0;
|
||||||
|
res = arg_get_u32_hexstr_def_nlen(ctx, 3, 0, &pwd, 4, true);
|
||||||
|
if (res == 2) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "Password must be 4 hex bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if (res == 3) {
|
||||||
|
use_pwd = false;
|
||||||
|
} else if (res == 1) {
|
||||||
|
use_pwd = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool protect_operation = arg_get_lit(ctx, 4);
|
bool protect_operation = arg_get_lit(ctx, 4);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -790,22 +813,19 @@ int CmdEM4x05Write(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_pwd = false;
|
if (use_pwd) {
|
||||||
uint32_t pwd = (inputpwd != 0xFFFFFFFFFFFFFFFF) ? (inputpwd & 0xFFFFFFFF) : 0;
|
|
||||||
if (pwd == 0xFFFFFFFF) {
|
|
||||||
if (protect_operation)
|
|
||||||
PrintAndLogEx(INFO, "Writing protection words data %08X", data);
|
|
||||||
else
|
|
||||||
PrintAndLogEx(INFO, "Writing address %d data %08X", addr, data);
|
|
||||||
} else {
|
|
||||||
use_pwd = true;
|
|
||||||
if (protect_operation)
|
if (protect_operation)
|
||||||
PrintAndLogEx(INFO, "Writing protection words data %08X using password %08X", data, pwd);
|
PrintAndLogEx(INFO, "Writing protection words data %08X using password %08X", data, pwd);
|
||||||
else
|
else
|
||||||
PrintAndLogEx(INFO, "Writing address %d data %08X using password %08X", addr, data, pwd);
|
PrintAndLogEx(INFO, "Writing address %d data %08X using password %08X", addr, data, pwd);
|
||||||
|
} else {
|
||||||
|
if (protect_operation)
|
||||||
|
PrintAndLogEx(INFO, "Writing protection words data %08X", data);
|
||||||
|
else
|
||||||
|
PrintAndLogEx(INFO, "Writing address %d data %08X", addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = PM3_SUCCESS;
|
res = PM3_SUCCESS;
|
||||||
// set Protect Words
|
// set Protect Words
|
||||||
if (protect_operation) {
|
if (protect_operation) {
|
||||||
res = em4x05_protect(pwd, use_pwd, data);
|
res = em4x05_protect(pwd, use_pwd, data);
|
||||||
|
|
|
@ -262,26 +262,7 @@ static int usage_t55xx_wakup(void) {
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wakeup p 11223344") " - send wakeup password");
|
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx wakeup p 11223344") " - send wakeup password");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_t55xx_chk(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "This command uses a dictionary attack");
|
|
||||||
PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
|
|
||||||
PrintAndLogEx(NORMAL, _RED_("WARNING:") " this may brick non-password protected chips!");
|
|
||||||
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx chk [h] [m] [r <mode>] [f <*.dic>] [e <em4100 id>]");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
|
||||||
PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n");
|
|
||||||
print_usage_t55xx_downloadlink(T55XX_DLMODE_ALL, T55XX_DLMODE_ALL);
|
|
||||||
PrintAndLogEx(NORMAL, " f <*.dic> - loads a default keys dictionary file <*.dic>");
|
|
||||||
PrintAndLogEx(NORMAL, " e <EM4100> - will try the calculated password from some cloners based on EM4100 ID");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx chk m"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx chk f t55xx_default_pwds"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx chk e aa11223344"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_t55xx_dangerraw(void) {
|
static int usage_t55xx_dangerraw(void) {
|
||||||
PrintAndLogEx(NORMAL, "This command allows to emit arbitrary raw commands on T5577 and cut the field after arbitrary duration.");
|
PrintAndLogEx(NORMAL, "This command allows to emit arbitrary raw commands on T5577 and cut the field after arbitrary duration.");
|
||||||
PrintAndLogEx(NORMAL, _RED_("WARNING:") " this may lock definitively the tag in an unusable state!");
|
PrintAndLogEx(NORMAL, _RED_("WARNING:") " this may lock definitively the tag in an unusable state!");
|
||||||
|
@ -2974,68 +2955,83 @@ static bool IsCancelled(void) {
|
||||||
|
|
||||||
// load a default pwd file.
|
// load a default pwd file.
|
||||||
static int CmdT55xxChkPwds(const char *Cmd) {
|
static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf t55xx chk",
|
||||||
|
"This command uses a dictionary attack.\n"
|
||||||
|
"For some cloners, try '--em' for known pwdgen algo.\n"
|
||||||
|
"Try to reading Page 0 block 7 before.\n"
|
||||||
|
_RED_("WARNING:") _CYAN_(" this may brick non-password protected chips!"),
|
||||||
|
"lf t55xx chk -m -> use dictionary from flash memory (RDV4)\n"
|
||||||
|
"lf t55xx chk -f my_dictionary_pwds -> loads a default keys dictionary file\n"
|
||||||
|
"lf t55xx chk --em aa11223344 -> try known pwdgen algo from some cloners based on EM4100 ID"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4 + (5 or 6)
|
||||||
|
void *argtable[9] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("m", "fm", "use dictionary from flash memory (RDV4)"),
|
||||||
|
arg_str0("f", "file", "<filename>", "file name"),
|
||||||
|
arg_str0(NULL, "em", "<hex>", "EM4100 ID (5 hex bytes)"),
|
||||||
|
};
|
||||||
|
uint8_t idx = 4;
|
||||||
|
arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_ALL, T55XX_DLMODE_ALL);
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
|
bool from_flash = arg_get_lit(ctx, 1);
|
||||||
|
|
||||||
|
int fnlen = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
bool found = false;
|
CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, sizeof(filename), &fnlen);
|
||||||
uint8_t timeout = 0;
|
|
||||||
uint8_t *keyBlock = NULL;
|
|
||||||
bool from_flash = false;
|
|
||||||
bool try_all_dl_modes = false;
|
|
||||||
uint8_t downlink_mode = 0;
|
|
||||||
bool use_pwd_file = false;
|
|
||||||
int dl_mode; // to try each downlink mode for each password
|
|
||||||
uint8_t cmdp = 0;
|
|
||||||
bool errors = false;
|
|
||||||
bool useCardPassword = false;
|
|
||||||
uint32_t cardPassword = 0x00;
|
|
||||||
uint64_t cardID = 0x00;
|
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
|
||||||
case 'h':
|
|
||||||
return usage_t55xx_chk();
|
|
||||||
case 'r':
|
|
||||||
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
if (downlink_mode >= 4) {
|
|
||||||
try_all_dl_modes = true;
|
|
||||||
downlink_mode = 0;
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
from_flash = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
if (param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)) == 0) {
|
|
||||||
PrintAndLogEx(ERR, "Error, no filename after 'f' was found");
|
|
||||||
errors = true;
|
|
||||||
}
|
|
||||||
use_pwd_file = true;
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
// White cloner password based on EM4100 ID
|
// White cloner password based on EM4100 ID
|
||||||
useCardPassword = true;
|
bool use_calc_password = false;
|
||||||
cardID = param_get64ex(Cmd, cmdp + 1, 0, 16);
|
uint32_t card_password = 0x00;
|
||||||
uint32_t card32Bit = cardID & 0xFFFFFFFF;
|
uint64_t cardid = 0;
|
||||||
cardPassword = lf_t55xx_white_pwdgen(card32Bit);
|
int res = arg_get_u64_hexstr_def_nlen(ctx, 3, 0x00, &cardid, 5, true);
|
||||||
cmdp += 2;
|
if (res == 1) {
|
||||||
break;
|
use_calc_password = true;
|
||||||
default:
|
uint32_t calc = cardid & 0xFFFFFFFF;
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
card_password = lf_t55xx_white_pwdgen(calc);
|
||||||
errors = true;
|
}
|
||||||
break;
|
if (res == 2) {
|
||||||
}
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "EM4100 ID must be 5 hex bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors) return usage_t55xx_chk();
|
bool r0 = arg_get_lit(ctx, 4);
|
||||||
|
bool r1 = arg_get_lit(ctx, 5);
|
||||||
|
bool r2 = arg_get_lit(ctx, 6);
|
||||||
|
bool r3 = arg_get_lit(ctx, 7);
|
||||||
|
bool ra = arg_get_lit(ctx, 8);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if ((r0 + r1 + r2 + r3 + ra) > 1) {
|
||||||
|
PrintAndLogEx(FAILED, "Error multiple downlink encoding");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t downlink_mode = config.downlink_mode;
|
||||||
|
if (r0)
|
||||||
|
downlink_mode = refFixedBit;
|
||||||
|
else if (r1)
|
||||||
|
downlink_mode = refLongLeading;
|
||||||
|
else if (r2)
|
||||||
|
downlink_mode = refLeading0;
|
||||||
|
else if (r3)
|
||||||
|
downlink_mode = ref1of4;
|
||||||
|
|
||||||
|
bool use_pwd_file = false;
|
||||||
if (strlen(filename) == 0) {
|
if (strlen(filename) == 0) {
|
||||||
snprintf(filename, sizeof(filename), "t55xx_default_pwds");
|
snprintf(filename, sizeof(filename), "t55xx_default_pwds");
|
||||||
use_pwd_file = true;
|
use_pwd_file = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "press " _GREEN_("'enter'") " to cancel the command");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
/*
|
/*
|
||||||
// block 7, page1 = false, usepwd = false, override = false, pwd = 00000000
|
// block 7, page1 = false, usepwd = false, override = false, pwd = 00000000
|
||||||
|
@ -3047,6 +3043,8 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
uint8_t flags = downlink_mode << 3;
|
uint8_t flags = downlink_mode << 3;
|
||||||
|
|
||||||
|
@ -3055,6 +3053,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
SendCommandNG(CMD_LF_T55XX_CHK_PWDS, &flags, sizeof(flags));
|
SendCommandNG(CMD_LF_T55XX_CHK_PWDS, &flags, sizeof(flags));
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
|
||||||
timeout++;
|
timeout++;
|
||||||
PrintAndLogEx(NORMAL, "." NOLF);
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
|
@ -3090,55 +3089,59 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try calculated password
|
// to try each downlink mode for each password
|
||||||
if (useCardPassword) {
|
int dl_mode;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", cardPassword);
|
// try calculated password
|
||||||
|
if (use_calc_password) {
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", card_password);
|
||||||
for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) {
|
for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) {
|
||||||
|
|
||||||
if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, cardPassword, dl_mode)) {
|
if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, card_password, dl_mode)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, cardPassword);
|
found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, card_password);
|
||||||
if (found) {
|
if (found) {
|
||||||
PrintAndLogEx(SUCCESS, "found valid password : [ " _GREEN_("%08"PRIX32) " ]", cardPassword);
|
PrintAndLogEx(SUCCESS, "found valid password : [ " _GREEN_("%08"PRIX32) " ]", card_password);
|
||||||
dl_mode = 4; // Exit other downlink mode checks
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!try_all_dl_modes) // Exit loop if not trying all downlink modes
|
if (ra == false)
|
||||||
dl_mode = 4;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((found == false) && use_pwd_file) {
|
if ((found == false) && use_pwd_file) {
|
||||||
uint32_t keycount = 0;
|
uint32_t keycount = 0;
|
||||||
|
uint8_t *keyblock = NULL;
|
||||||
|
|
||||||
int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount);
|
res = loadFileDICTIONARY_safe(filename, (void **) &keyblock, 4, &keycount);
|
||||||
if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) {
|
if (res != PM3_SUCCESS || keycount == 0 || keyblock == NULL) {
|
||||||
PrintAndLogEx(WARNING, "no keys found in file");
|
PrintAndLogEx(WARNING, "no keys found in file");
|
||||||
if (keyBlock != NULL)
|
if (keyblock != NULL)
|
||||||
free(keyBlock);
|
free(keyblock);
|
||||||
|
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command");
|
PrintAndLogEx(INFO, "press " _GREEN_("'enter'") " to cancel the command");
|
||||||
|
|
||||||
for (uint32_t c = 0; c < keycount; ++c) {
|
for (uint32_t c = 0; c < keycount && found == false; ++c) {
|
||||||
|
|
||||||
if (!session.pm3_present) {
|
if (!session.pm3_present) {
|
||||||
PrintAndLogEx(WARNING, "device offline\n");
|
PrintAndLogEx(WARNING, "device offline\n");
|
||||||
free(keyBlock);
|
free(keyblock);
|
||||||
return PM3_ENODATA;
|
return PM3_ENODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsCancelled()) {
|
if (IsCancelled()) {
|
||||||
free(keyBlock);
|
free(keyblock);
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t curr_password = bytes_to_num(keyBlock + 4 * c, 4);
|
uint32_t curr_password = bytes_to_num(keyblock + 4 * c, 4);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password);
|
PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password);
|
||||||
for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) {
|
for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) {
|
||||||
|
@ -3150,20 +3153,19 @@ static int CmdT55xxChkPwds(const char *Cmd) {
|
||||||
found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password);
|
found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password);
|
||||||
if (found) {
|
if (found) {
|
||||||
PrintAndLogEx(SUCCESS, "found valid password: [ " _GREEN_("%08"PRIX32) " ]", curr_password);
|
PrintAndLogEx(SUCCESS, "found valid password: [ " _GREEN_("%08"PRIX32) " ]", curr_password);
|
||||||
dl_mode = 4; // Exit other downlink mode checks
|
break;
|
||||||
c = keycount; // Exit loop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!try_all_dl_modes) // Exit loop if not trying all downlink modes
|
if (ra == false) // Exit loop if not trying all downlink modes
|
||||||
dl_mode = 4;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(keyblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == false)
|
if (found == false)
|
||||||
PrintAndLogEx(WARNING, "check pwd failed");
|
PrintAndLogEx(WARNING, "failed to find password");
|
||||||
|
|
||||||
free(keyBlock);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
t1 = msclock() - t1;
|
t1 = msclock() - t1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue