mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 13:23:51 -07:00
lf t55xx recoverpw .. - now uses cliparser
This commit is contained in:
parent
00b1613afa
commit
55b76f0d4c
3 changed files with 223 additions and 254 deletions
|
@ -236,7 +236,6 @@ static int usage_t55xx_restore(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_t55xx_detect(void) {
|
static int usage_t55xx_detect(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [r <mode>] [p <password>]");
|
PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [r <mode>] [p <password>]");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
|
@ -251,21 +250,6 @@ static int usage_t55xx_detect(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_t55xx_detectP1(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Command: Detect Page 1 of a t55xx chip");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx p1detect [1] [r <mode>] [p <password>]");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag.");
|
|
||||||
PrintAndLogEx(NORMAL, " p <password> - OPTIONAL password (8 hex characters)");
|
|
||||||
print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); // Need to setup to try all modes
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx p1detect"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx p1detect 1"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx p1detect p 11223344"));
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_t55xx_wakup(void) {
|
static int usage_t55xx_wakup(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] [r <mode>] p <password>");
|
PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] [r <mode>] p <password>");
|
||||||
PrintAndLogEx(NORMAL, "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards.");
|
PrintAndLogEx(NORMAL, "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards.");
|
||||||
|
@ -316,49 +300,6 @@ static int usage_t55xx_bruteforce(void) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
static int usage_t55xx_recoverpw(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "This command uses a few tricks to try to recover mangled password");
|
|
||||||
PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
|
|
||||||
PrintAndLogEx(NORMAL, _RED_("WARNING:") " this may brick non-password protected chips!");
|
|
||||||
PrintAndLogEx(NORMAL, "Try reading block 7 before\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [r <mode>] [p <password>]");
|
|
||||||
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
|
|
||||||
PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - this help");
|
|
||||||
print_usage_t55xx_downloadlink(T55XX_DLMODE_ALL, T55XX_DLMODE_ALL);
|
|
||||||
PrintAndLogEx(NORMAL, " p <password> - 4 byte hex value of password written by cloner");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx recoverpw"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx recoverpw p 51243648"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx recoverpw r 3 p 51243648"));
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usage_t55xx_deviceconfig(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Sets t55x7 timings for direct commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig [r <mode>] a <gap> b <gap> c <gap> d <gap> e <gap> f <gap> g <gap> [p]");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h - This help");
|
|
||||||
PrintAndLogEx(NORMAL, " a <8..255> - Set start gap");
|
|
||||||
PrintAndLogEx(NORMAL, " b <8..255> - Set write gap");
|
|
||||||
PrintAndLogEx(NORMAL, " c <8..255> - Set write ZERO gap");
|
|
||||||
PrintAndLogEx(NORMAL, " d <8..255> - Set write ONE gap");
|
|
||||||
PrintAndLogEx(NORMAL, " e <8..255> - Set read gap");
|
|
||||||
PrintAndLogEx(NORMAL, " f <8..255> - Set write TWO gap (1 of 4 only)");
|
|
||||||
PrintAndLogEx(NORMAL, " g <8..255> - Set write THREE gap (1 of 4 only)");
|
|
||||||
PrintAndLogEx(NORMAL, " p - persist to flashmemory");
|
|
||||||
PrintAndLogEx(NORMAL, " z - Set default t55x7 timings (use p to save if required)");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15") " - default T55XX");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx deviceconfig a 55 b 14 c 21 d 30") " - default EM4305");
|
|
||||||
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.");
|
||||||
|
@ -2967,40 +2908,50 @@ static int CmdT55xxWipe(const char *Cmd) {
|
||||||
bool usepwd = false, gotconf = false;
|
bool usepwd = false, gotconf = false;
|
||||||
uint32_t block0 = 0;
|
uint32_t block0 = 0;
|
||||||
int res = arg_get_u32_hexstr_def(ctx, 1, 0, &block0);
|
int res = arg_get_u32_hexstr_def(ctx, 1, 0, &block0);
|
||||||
if (res) {
|
if (res == 1) {
|
||||||
gotconf = true;
|
gotconf = true;
|
||||||
}
|
}
|
||||||
|
if (res == 2) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(WARNING, "config block needs to be 4 hex bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t password = 0;
|
uint32_t password = 0;
|
||||||
res = arg_get_u32_hexstr_def(ctx, 2, 0x51243648, &password);
|
res = arg_get_u32_hexstr_def(ctx, 2, 0x51243648, &password);
|
||||||
if (res) {
|
if (res) {
|
||||||
usepwd = true;
|
usepwd = true;
|
||||||
|
|
||||||
if (usepwd && res == 2)
|
if (usepwd && res == 2)
|
||||||
PrintAndLogEx(INFO, "Password should be 4 bytes, using default pwd instead");
|
PrintAndLogEx(WARNING, "Password should be 4 bytes, using default pwd");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Q5 = arg_get_lit(ctx, 3);
|
bool Q5 = arg_get_lit(ctx, 3);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\nBegin wiping " _YELLOW_("%s")" tag", (Q5) ? "Q5/T5555" : "T55x7");
|
PrintAndLogEx(INFO, "Target " _YELLOW_("%s")" tag", (Q5) ? "Q5/T5555" : "T55x7");
|
||||||
|
|
||||||
// default config blocks.
|
// default config blocks.
|
||||||
if (gotconf == false) {
|
if (gotconf == false) {
|
||||||
block0 = (Q5) ? 0x6001F004 : 0x000880E0;
|
block0 = (Q5) ? 0x6001F004 : 0x000880E0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char writeData[36] = {0};
|
if (usepwd)
|
||||||
char *ptrData = writeData;
|
PrintAndLogEx(INFO, "Using password " _GREEN_("%08X"), password);
|
||||||
|
|
||||||
char msg[80] = {0};
|
char msg[80] = {0};
|
||||||
|
|
||||||
if (gotconf)
|
if (gotconf)
|
||||||
snprintf(msg, sizeof(msg), "User provided configuration block %08X", block0);
|
snprintf(msg, sizeof(msg), "User provided configuration block " _GREEN_("%08X"), block0);
|
||||||
else
|
else
|
||||||
snprintf(msg, sizeof(msg), "Default configation block %08X", block0);
|
snprintf(msg, sizeof(msg), "Default configuration block " _GREEN_("%08X"), block0);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "%s", msg);
|
PrintAndLogEx(INFO, "%s\n", msg);
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Begin wiping...");
|
||||||
|
|
||||||
// Creating cmd string for write block :)
|
// Creating cmd string for write block :)
|
||||||
|
char writeData[36] = {0};
|
||||||
|
char *ptrData = writeData;
|
||||||
snprintf(ptrData, sizeof(writeData), "b 0 ");
|
snprintf(ptrData, sizeof(writeData), "b 0 ");
|
||||||
|
|
||||||
if (usepwd) {
|
if (usepwd) {
|
||||||
|
@ -3295,7 +3246,8 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
return PM3_EOPABORTED;
|
return PM3_EOPABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = tryOnePassword(curr, downlink_mode);
|
// iceman: don't forget to change to true -> ra
|
||||||
|
found = t55xx_try_one_password(curr, downlink_mode, true);
|
||||||
|
|
||||||
if (curr == end_password)
|
if (curr == end_password)
|
||||||
break;
|
break;
|
||||||
|
@ -3316,19 +3268,15 @@ static int CmdT55xxBruteForce(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) {
|
uint8_t t55xx_try_one_password(uint32_t password, uint8_t downlink_mode, bool try_all_dl_modes) {
|
||||||
|
|
||||||
bool try_all_dl_modes = false;
|
|
||||||
uint8_t dl_mode = 0;
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Trying password %08X", password);
|
PrintAndLogEx(INFO, "Trying password %08X", password);
|
||||||
|
|
||||||
if (downlink_mode == 4) try_all_dl_modes = true;
|
// ensure 0-3
|
||||||
|
downlink_mode = (downlink_mode & 3);
|
||||||
downlink_mode = (downlink_mode & 3); // ensure 0-3
|
|
||||||
|
|
||||||
// check if dl mode 4 and loop if needed
|
// check if dl mode 4 and loop if needed
|
||||||
for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) {
|
for (uint8_t dl_mode = downlink_mode; dl_mode < 4; dl_mode++) {
|
||||||
|
|
||||||
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode)) {
|
if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password, dl_mode)) {
|
||||||
// if (getSignalProperties()->isnoise == false) {
|
// if (getSignalProperties()->isnoise == false) {
|
||||||
|
@ -3338,51 +3286,73 @@ uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) {
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
if (!try_all_dl_modes) dl_mode = 4;
|
if (try_all_dl_modes == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdT55xxRecoverPW(const char *Cmd) {
|
static int CmdT55xxRecoverPW(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf t55xx recoverpw",
|
||||||
|
"This command uses a few tricks to try to recover mangled password.\n"
|
||||||
|
"Try reading Page 0, block 7 before.\n\n"
|
||||||
|
_RED_("WARNING") _CYAN_(" this may brick non-password protected chips!"),
|
||||||
|
"lf t55xx recoverpw\n"
|
||||||
|
"lf t55xx recoverpw -p 11223344\n"
|
||||||
|
"lf t55xx recoverpw -p 11223344 --r3\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2 + (5 or 6)
|
||||||
|
void *argtable[8] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str1("p", "pwd", "<hex>", "password (4 hex bytes)"),
|
||||||
|
};
|
||||||
|
uint8_t idx = 2;
|
||||||
|
arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_ALL, T55XX_DLMODE_ALL);
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
|
uint32_t orig_password = 0;
|
||||||
|
int res = arg_get_u32_hexstr_def(ctx, 1, 0x51243648, &orig_password);
|
||||||
|
if (res == 2) {
|
||||||
|
PrintAndLogEx(INFO, "Password should be 4 bytes, using default pwd instead");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool r0 = arg_get_lit(ctx, 2);
|
||||||
|
bool r1 = arg_get_lit(ctx, 3);
|
||||||
|
bool r2 = arg_get_lit(ctx, 4);
|
||||||
|
bool r3 = arg_get_lit(ctx, 5);
|
||||||
|
bool ra = arg_get_lit(ctx, 6);
|
||||||
|
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;
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
|
||||||
|
|
||||||
int bit = 0;
|
int bit = 0;
|
||||||
uint32_t orig_password = 0x0;
|
|
||||||
uint32_t curr_password = 0x0;
|
uint32_t curr_password = 0x0;
|
||||||
uint32_t prev_password = 0xffffffff;
|
uint32_t prev_password = 0xffffffff;
|
||||||
uint32_t mask = 0x0;
|
uint32_t mask = 0x0;
|
||||||
uint8_t downlink_mode = 0;
|
|
||||||
uint8_t found = 0;
|
uint8_t found = 0;
|
||||||
uint8_t cmdp = 0;
|
|
||||||
bool errors = false;
|
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
|
||||||
case 'h':
|
|
||||||
return usage_t55xx_recoverpw();
|
|
||||||
case 'p':
|
|
||||||
// password used by handheld cloners
|
|
||||||
orig_password = param_get32ex(Cmd, cmdp + 1, 0x51243648, 16);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
if (downlink_mode > 4)
|
|
||||||
downlink_mode = 0;
|
|
||||||
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors || cmdp == 0) return usage_t55xx_recoverpw();
|
|
||||||
|
|
||||||
// first try fliping each bit in the expected password
|
// first try fliping each bit in the expected password
|
||||||
while (bit < 32) {
|
while (bit < 32) {
|
||||||
curr_password = orig_password ^ (1u << bit);
|
curr_password = orig_password ^ (1u << bit);
|
||||||
found = tryOnePassword(curr_password, downlink_mode);
|
found = t55xx_try_one_password(curr_password, downlink_mode, ra);
|
||||||
if (found > 0) // xx1 for found xx = dl mode used
|
if (found > 0) // xx1 for found xx = dl mode used
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -3407,7 +3377,7 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = tryOnePassword(curr_password, downlink_mode);
|
found = t55xx_try_one_password(curr_password, downlink_mode, ra);
|
||||||
if (found > 0)
|
if (found > 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -3429,7 +3399,7 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
|
||||||
bit++;
|
bit++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
found = tryOnePassword(curr_password, downlink_mode);
|
found = t55xx_try_one_password(curr_password, downlink_mode, ra);
|
||||||
if (found > 0)
|
if (found > 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -3441,15 +3411,14 @@ static int CmdT55xxRecoverPW(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if (found > 0) {
|
if (found > 0) {
|
||||||
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
|
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
|
||||||
T55xx_Print_DownlinkMode((found >> 1) & 3);
|
T55xx_Print_DownlinkMode((found >> 1) & 3);
|
||||||
} else
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Recover pwd failed");
|
PrintAndLogEx(FAILED, "Recover password failed");
|
||||||
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3567,70 +3536,89 @@ bool tryDetectP1(bool getData) {
|
||||||
}
|
}
|
||||||
// does this need to be a callable command?
|
// does this need to be a callable command?
|
||||||
static int CmdT55xxDetectPage1(const char *Cmd) {
|
static int CmdT55xxDetectPage1(const char *Cmd) {
|
||||||
bool errors = false;
|
CLIParserContext *ctx;
|
||||||
bool useGB = false;
|
CLIParserInit(&ctx, "lf t55xx p1detect",
|
||||||
bool usepwd = false;
|
"Detect Page 1 of a T55xx chip",
|
||||||
bool try_all_dl_modes = true;
|
"lf t55xx p1detect\n"
|
||||||
bool found = false;
|
"lf t55xx p1detect -1\n"
|
||||||
uint8_t found_mode = 0;
|
"lf t55xx p1detect -p 11223344 --r3\n"
|
||||||
uint32_t password = 0;
|
);
|
||||||
uint8_t cmdp = 0;
|
|
||||||
uint8_t downlink_mode = config.downlink_mode;
|
|
||||||
uint8_t dl_mode = 0;
|
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
// 2 + (5 or 6)
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
void *argtable[7] = {
|
||||||
case 'h':
|
arg_param_begin,
|
||||||
return usage_t55xx_detectP1();
|
arg_lit0("1", NULL, "extract using data from graphbuffer"),
|
||||||
case 'p':
|
arg_str0("p", "pwd", "<hex>", "password (4 hex bytes)"),
|
||||||
password = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
};
|
||||||
|
uint8_t idx = 3;
|
||||||
|
arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode);
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
|
bool use_graphbuf = arg_get_lit(ctx, 1);
|
||||||
|
|
||||||
|
bool usepwd = false;
|
||||||
|
uint32_t password = 0;
|
||||||
|
int res = arg_get_u32_hexstr_def(ctx, 2, 0, &password);
|
||||||
|
if (res == 2) {
|
||||||
|
PrintAndLogEx(INFO, "Password should be 4 hex bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if ( res == 1) {
|
||||||
usepwd = true;
|
usepwd = true;
|
||||||
cmdp += 2;
|
}
|
||||||
break;
|
|
||||||
case '1':
|
bool r0 = arg_get_lit(ctx, 3);
|
||||||
// use Graphbuffer data
|
bool r1 = arg_get_lit(ctx, 4);
|
||||||
useGB = true;
|
bool r2 = arg_get_lit(ctx, 5);
|
||||||
cmdp++;
|
bool r3 = arg_get_lit(ctx, 6);
|
||||||
break;
|
CLIParserFree(ctx);
|
||||||
case 'r':
|
|
||||||
|
if ((r0 + r1 + r2 + r3) > 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 try_all_dl_modes = true;
|
||||||
|
|
||||||
//ICEMAN STRANGE
|
//ICEMAN STRANGE
|
||||||
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
if (downlink_mode == 4)
|
if (downlink_mode == 4)
|
||||||
try_all_dl_modes = true;
|
try_all_dl_modes = true;
|
||||||
if (downlink_mode < 4)
|
if (downlink_mode < 4)
|
||||||
try_all_dl_modes = false;
|
try_all_dl_modes = false;
|
||||||
|
|
||||||
if (downlink_mode > 3)
|
if (downlink_mode > 3)
|
||||||
downlink_mode = 0;
|
downlink_mode = 0;
|
||||||
|
|
||||||
cmdp += 2;
|
bool found = false;
|
||||||
break;
|
uint8_t found_mode = 0;
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (errors) return usage_t55xx_detectP1();
|
|
||||||
|
|
||||||
if (!useGB) {
|
if (use_graphbuf == false) {
|
||||||
for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) {
|
for (uint8_t dl_mode = downlink_mode; dl_mode < 4; dl_mode++) {
|
||||||
found = AcquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password, dl_mode);
|
|
||||||
if (found == false)
|
if (AcquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password, dl_mode) == false)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tryDetectP1(false)) {
|
if (tryDetectP1(false)) {
|
||||||
found = true;
|
found = true;
|
||||||
found_mode = dl_mode;
|
found_mode = dl_mode;
|
||||||
dl_mode = 4;
|
break;
|
||||||
} else {
|
} else {
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!try_all_dl_modes) {
|
if (try_all_dl_modes == false) {
|
||||||
dl_mode = 4;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
found = tryDetectP1(false);
|
found = tryDetectP1(false);
|
||||||
}
|
}
|
||||||
|
@ -3645,66 +3633,59 @@ static int CmdT55xxDetectPage1(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdT55xxSetDeviceConfig(const char *Cmd) {
|
static int CmdT55xxSetDeviceConfig(const char *Cmd) {
|
||||||
uint8_t startgap = 0, writegap = 0, readgap = 0;
|
CLIParserContext *ctx;
|
||||||
uint8_t write0 = 0, write1 = 0, write2 = 0, write3 = 0;
|
CLIParserInit(&ctx, "lf t55xx deviceconfig",
|
||||||
uint8_t cmdp = 0, downlink_mode = 0;
|
"Sets t55x7 timings for direct commands.\n"
|
||||||
bool errors = false, shall_persist = false, set_defaults = false;
|
"The timings are set here in Field Clocks (FC) which is converted to (US) on device.",
|
||||||
|
"lf t55xx deviceconfig -a 29 -b 17 -c 15 -d 47 -e 15 -> default T55XX\n"
|
||||||
|
"lf t55xx deviceconfig -a 55 -b 14 -c 21 -d 30 -> default EM4305"
|
||||||
|
);
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
void *argtable[10 + 5] = {
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
arg_param_begin,
|
||||||
case 'h':
|
arg_int0("a", NULL, "<8..255>", "Set start gap"),
|
||||||
return usage_t55xx_deviceconfig();
|
arg_int0("b", NULL, "<8..255>", "Set write gap"),
|
||||||
case 'a':
|
arg_int0("c", NULL, "<8..255>", "Set write ZERO gap"),
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &startgap);
|
arg_int0("d", NULL, "<8..255>", "Set write ONE gap"),
|
||||||
cmdp += 2;
|
arg_int0("e", NULL, "<8..255>", "Set read gap"),
|
||||||
break;
|
arg_int0("f", NULL, "<8..255>", "Set write TWO gap (1 of 4 only)"),
|
||||||
case 'b':
|
arg_int0("g", NULL, "<8..255>", "Set write THREE gap (1 of 4 only)"),
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &writegap);
|
arg_lit0("p", "persist", "persist to flash memory (RDV4)"),
|
||||||
cmdp += 2;
|
arg_lit0("z", NULL, "Set default t55x7 timings (use `-p` to save if required)"),
|
||||||
break;
|
};
|
||||||
case 'c':
|
uint8_t idx = 10;
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &write0);
|
arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode);
|
||||||
cmdp += 2;
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
break;
|
|
||||||
case 'd':
|
uint8_t startgap = arg_get_int(ctx, 1);
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &write1);
|
uint8_t writegap = arg_get_int(ctx, 2);
|
||||||
cmdp += 2;
|
uint8_t write0 = arg_get_int(ctx, 3);
|
||||||
break;
|
uint8_t write1 = arg_get_int(ctx, 4);
|
||||||
case 'e':
|
uint8_t readgap = arg_get_int(ctx, 5);
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &readgap);
|
uint8_t write2 = arg_get_int(ctx, 6);
|
||||||
cmdp += 2;
|
uint8_t write3 = arg_get_int(ctx, 7);
|
||||||
break;
|
bool shall_persist = arg_get_lit(ctx, 8);
|
||||||
case 'f':
|
bool set_defaults = arg_get_lit(ctx, 9);
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &write2);
|
bool r0 = arg_get_lit(ctx, 10);
|
||||||
cmdp += 2;
|
bool r1 = arg_get_lit(ctx, 11);
|
||||||
break;
|
bool r2 = arg_get_lit(ctx, 12);
|
||||||
case 'g':
|
bool r3 = arg_get_lit(ctx, 13);
|
||||||
errors |= param_getdec(Cmd, cmdp + 1, &write3);
|
CLIParserFree(ctx);
|
||||||
cmdp += 2;
|
|
||||||
break;
|
if ((r0 + r1 + r2 + r3) > 1) {
|
||||||
case 'r':
|
PrintAndLogEx(FAILED, "Error multiple downlink encoding");
|
||||||
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
return PM3_EINVARG;
|
||||||
if (downlink_mode > 3)
|
|
||||||
downlink_mode = 0;
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
shall_persist = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 'z':
|
|
||||||
set_defaults = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Validations
|
uint8_t downlink_mode = 0;
|
||||||
if (errors || cmdp == 0) return usage_t55xx_deviceconfig();
|
if (r0)
|
||||||
|
downlink_mode = refFixedBit;
|
||||||
|
else if (r1)
|
||||||
|
downlink_mode = refLongLeading;
|
||||||
|
else if (r2)
|
||||||
|
downlink_mode = refLeading0;
|
||||||
|
else if (r3)
|
||||||
|
downlink_mode = ref1of4;
|
||||||
|
|
||||||
t55xx_configurations_t configurations = {{{0}, {0}, {0}, {0}}};
|
t55xx_configurations_t configurations = {{{0}, {0}, {0}, {0}}};
|
||||||
|
|
||||||
|
@ -3765,13 +3746,13 @@ static int CmdT55xxProtect(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "lf t55xx protect",
|
CLIParserInit(&ctx, "lf t55xx protect",
|
||||||
"This command sets the pwd bit on T5577.\n"
|
"This command sets the pwd bit on T5577.\n"
|
||||||
"WARNING: this locks the tag!",
|
_RED_("WARNING") _CYAN_(" this locks the tag!"),
|
||||||
"lf t55xx protect -n 01020304 -> sets new password to 01020304\n"
|
"lf t55xx protect -n 01020304 -> sets new pwd 01020304\n"
|
||||||
"lf t55xx protect -p 11223344 -n 00000000 -> use pwd 11223344 to set newpwd to 00000000"
|
"lf t55xx protect -p 11223344 -n 00000000 -> use pwd 11223344, sets new pwd 00000000"
|
||||||
);
|
);
|
||||||
|
|
||||||
// 4 + (5 or 6)
|
// 4 + (5 or 6)
|
||||||
void *argtable[9] = {
|
void *argtable[4 + 5] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("o", "override", "override safety check"),
|
arg_lit0("o", "override", "override safety check"),
|
||||||
arg_str1("p", "pwd", "<hex>", "password (4 hex bytes)"),
|
arg_str1("p", "pwd", "<hex>", "password (4 hex bytes)"),
|
||||||
|
@ -3785,21 +3766,27 @@ static int CmdT55xxProtect(const char *Cmd) {
|
||||||
if (arg_get_lit(ctx, 1))
|
if (arg_get_lit(ctx, 1))
|
||||||
override = 2;
|
override = 2;
|
||||||
|
|
||||||
int plen = 0;
|
uint32_t password = 0;
|
||||||
uint8_t pdata[4] = {0x00};
|
bool usepwd = false;
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), pdata, sizeof(pdata), &plen);
|
int res = arg_get_u32_hexstr_def(ctx, 2, 0, &password);
|
||||||
if (res) {
|
if (res == 2) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
PrintAndLogEx(FAILED, "Error parsing password bytes");
|
PrintAndLogEx(FAILED, "Error parsing password bytes");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
} else if ( res == 1) {
|
||||||
|
usepwd = true;
|
||||||
|
override = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nlen = 0;
|
uint32_t new_password = 0;
|
||||||
uint8_t ndata[4] = {0x00};
|
res = arg_get_u32_hexstr_def(ctx, 3, 0, &new_password);
|
||||||
res = CLIParamHexToBuf(arg_get_str(ctx, 3), ndata, sizeof(ndata), &nlen);
|
if (res == 2) {
|
||||||
if (res) {
|
CLIParserFree(ctx);
|
||||||
|
PrintAndLogEx(FAILED, "Error parsing new password bytes");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else if (res == 0) {
|
||||||
|
PrintAndLogEx(FAILED, "Must specify new password param");
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
PrintAndLogEx(FAILED, "Error parsing new passpord bytes");
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3824,21 +3811,6 @@ static int CmdT55xxProtect(const char *Cmd) {
|
||||||
else if (r3)
|
else if (r3)
|
||||||
downlink_mode = ref1of4;
|
downlink_mode = ref1of4;
|
||||||
|
|
||||||
uint32_t password = 0, new_password = 0;
|
|
||||||
bool usepwd = false;
|
|
||||||
if (plen == 4) {
|
|
||||||
usepwd = true;
|
|
||||||
override = 1;
|
|
||||||
password = bytes_to_num(pdata, plen);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nlen == 4) {
|
|
||||||
new_password = bytes_to_num(ndata, nlen);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(WARNING, "Must specify new password param");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanity check.
|
// sanity check.
|
||||||
if (SanityOfflineCheck(false) != PM3_SUCCESS)
|
if (SanityOfflineCheck(false) != PM3_SUCCESS)
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -4205,7 +4177,7 @@ static command_t CommandTable[] = {
|
||||||
{"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
{"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"},
|
||||||
{"dangerraw", CmdT55xxDangerousRaw, IfPm3Lf, "Sends raw bitstream. Dangerous, do not use!! b <bitstream> t <timing>"},
|
{"dangerraw", CmdT55xxDangerousRaw, IfPm3Lf, "Sends raw bitstream. Dangerous, do not use!! b <bitstream> t <timing>"},
|
||||||
{"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."},
|
{"detect", CmdT55xxDetect, AlwaysAvailable, "[1] Try detecting the tag modulation from reading the configuration block."},
|
||||||
{"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"},
|
{"deviceconfig", CmdT55xxSetDeviceConfig, IfPm3Lf, "Set/Get T55XX device configuration"},
|
||||||
{"dump", CmdT55xxDump, IfPm3Lf, "[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]"},
|
{"dump", CmdT55xxDump, IfPm3Lf, "[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]"},
|
||||||
{"info", CmdT55xxInfo, AlwaysAvailable, "[1] Show T55x7 configuration data (page 0/ blk 0)"},
|
{"info", CmdT55xxInfo, AlwaysAvailable, "[1] Show T55x7 configuration data (page 0/ blk 0)"},
|
||||||
{"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "[1] Try detecting if this is a t55xx tag by reading page 1"},
|
{"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "[1] Try detecting if this is a t55xx tag by reading page 1"},
|
||||||
|
@ -4220,10 +4192,10 @@ static command_t CommandTable[] = {
|
||||||
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "<start password> <end password> Simple bruteforce attack to find password"},
|
{"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "<start password> <end password> Simple bruteforce attack to find password"},
|
||||||
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
|
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
|
||||||
{"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"},
|
{"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"},
|
||||||
{"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"},
|
{"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "Try to recover from bad password write from a cloner"},
|
||||||
{"sniff", CmdT55xxSniff, AlwaysAvailable, "Attempt to recover T55xx commands from sample buffer"},
|
{"sniff", CmdT55xxSniff, AlwaysAvailable, "Attempt to recover T55xx commands from sample buffer"},
|
||||||
{"special", special, IfPm3Lf, "Show block changes with 64 different offsets"},
|
{"special", special, IfPm3Lf, "Show block changes with 64 different offsets"},
|
||||||
{"wipe", CmdT55xxWipe, IfPm3Lf, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
|
{"wipe", CmdT55xxWipe, IfPm3Lf, "Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,7 @@ bool tryDetectP1(bool getData);
|
||||||
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5);
|
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5);
|
||||||
int special(const char *Cmd);
|
int special(const char *Cmd);
|
||||||
bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode);
|
bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint8_t downlink_mode);
|
||||||
uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode);
|
uint8_t t55xx_try_one_password(uint32_t password, uint8_t downlink_mode, bool try_all_dl_modes);
|
||||||
|
|
||||||
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat);
|
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat);
|
||||||
void printT5555Trace(t5555_tracedata_t data, uint8_t repeat);
|
void printT5555Trace(t5555_tracedata_t data, uint8_t repeat);
|
||||||
|
|
|
@ -114,10 +114,8 @@ lf hitag cc
|
||||||
lf t55xx config
|
lf t55xx config
|
||||||
lf t55xx dangerraw
|
lf t55xx dangerraw
|
||||||
lf t55xx detect
|
lf t55xx detect
|
||||||
lf t55xx deviceconfig
|
|
||||||
lf t55xx dump
|
lf t55xx dump
|
||||||
lf t55xx info
|
lf t55xx info
|
||||||
lf t55xx p1detect
|
|
||||||
lf t55xx read
|
lf t55xx read
|
||||||
lf t55xx resetread
|
lf t55xx resetread
|
||||||
lf t55xx restore
|
lf t55xx restore
|
||||||
|
@ -126,6 +124,5 @@ lf t55xx wakeup
|
||||||
lf t55xx write
|
lf t55xx write
|
||||||
lf t55xx bruteforce
|
lf t55xx bruteforce
|
||||||
lf t55xx chk
|
lf t55xx chk
|
||||||
lf t55xx recoverpw
|
|
||||||
lf t55xx special
|
lf t55xx special
|
||||||
script run
|
script run
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue