fix lf em 4x05 write - pwd/data. t55xx chk - now uses cliparser, and color to cliparser empty message

This commit is contained in:
iceman1001 2021-01-27 22:52:08 +01:00
commit fdcc4b741c
5 changed files with 197 additions and 124 deletions

View file

@ -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;
} }

View file

@ -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

View file

@ -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;
} }

View file

@ -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);

View file

@ -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;