From 6bcf31e68c09aef9687bc2b3d3212eb858ccbf04 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Feb 2021 14:32:52 +0100 Subject: [PATCH] lf t55 detect - now use cliparse .. which also makes it work with the wakeup command again --- client/src/cmdlft55xx.c | 297 +++++++++++++++++++++------------------- 1 file changed, 153 insertions(+), 144 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 3614a0e2f..64a6c0ae4 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -235,22 +235,6 @@ static int usage_t55xx_restore(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_t55xx_detect(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [r ] [p ]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); - PrintAndLogEx(NORMAL, " p send wakeup with password\n" + ); + + // 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[3 + 5] = { + arg_param_begin, + arg_str0("p", "pwd", "", "password (4 hex bytes)"), + arg_lit0("v", "verbose", "verbose output"), + }; + uint8_t idx = 3; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint32_t password = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &password, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password should be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 2); + bool r0 = arg_get_lit(ctx, 3); + bool r1 = arg_get_lit(ctx, 4); + bool r2 = arg_get_lit(ctx, 5); + bool r3 = arg_get_lit(ctx, 6); + CLIParserFree(ctx); + + 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; + + struct p { + uint32_t password; + uint8_t flags; + } PACKED payload; + + payload.password = password; + payload.flags = (downlink_mode << 3); + + clearCommandBuffer(); + SendCommandNG(CMD_LF_T55XX_WAKEUP, (uint8_t *)&payload, sizeof(payload)); + if (WaitForResponseTimeout(CMD_LF_T55XX_WAKEUP, NULL, 1000) == false) { + PrintAndLogEx(WARNING, "command execution time out"); + return PM3_ETIMEOUT; + } + + if (verbose) + PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now"); + + return PM3_SUCCESS; +} static int CmdT55xxDetect(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx detect", + "Try detecting the tag modulation from reading the configuration block", + "lf t55xx detect\n" + "lf t55xx detect -1\n" + "lf t55xx detect -p 11223344\n" + ); + + // 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL) + void *argtable[3 + 6] = { + arg_param_begin, + arg_lit0("1", NULL, "extract using data from graphbuffer"), + arg_str0("p", "pwd", "", "password (4 hex bytes)"), + }; + uint8_t idx = 3; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_ALL, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool use_gb = arg_get_lit(ctx, 1); - bool errors = false; - bool useGB = false; bool usepwd = false; + uint64_t password = -1; + uint32_t tmp_pwd = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &tmp_pwd, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password should be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (res == 1) { + usepwd = true; + password = tmp_pwd; + } + + bool r0 = arg_get_lit(ctx, 3); + bool r1 = arg_get_lit(ctx, 4); + bool r2 = arg_get_lit(ctx, 5); + bool r3 = arg_get_lit(ctx, 6); + bool ra = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + + if ((r0 + r1 + r2 + r3 + ra) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; + } + + bool try_all_dl_modes = false; + 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; + + if (ra) + try_all_dl_modes = true; + bool try_with_pwd = false; - bool try_all_dl_modes = true; bool found = false; bool usewake = false; - uint64_t password = -1; - uint8_t cmdp = 0; - uint8_t downlink_mode = 0; - char wakecmd[20] = { 0x00 }; - struct timespec sleepperiod; // Setup the 90ms time value to sleep for after the wake, to allow delay init to complete (~70ms) + struct timespec sleepperiod; sleepperiod.tv_sec = 0; sleepperiod.tv_nsec = 90000000; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_detect(); - case 'p': - password = param_get32ex(Cmd, cmdp + 1, 0, 16); - sprintf(wakecmd, "p %08x q", (uint32_t)(password & 0xFFFFFFFF)); - usepwd = true; - cmdp += 2; - break; - case '1': - useGB = true; - cmdp++; - break; - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode <= 3) try_all_dl_modes = false; // User selected ONLY 1 so honor. - if (downlink_mode == 4) try_all_dl_modes = true; - if (downlink_mode > 3) downlink_mode = 0; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_t55xx_detect(); - - // detect called so clear data blocks T55x7_ClearAllBlockData(); // sanity check. - if (SanityOfflineCheck(useGB) != PM3_SUCCESS) + if (SanityOfflineCheck(use_gb) != PM3_SUCCESS) return PM3_ESOFT; - if (useGB == false) { + if (use_gb == false) { + + char wakecmd[20] = { 0x00 }; + sprintf(wakecmd, "-p %08" PRIx64, password); + // do ... while not found and not yet tried with wake (for AOR or Init Delay) do { // do ... while to check without password then loop back if password supplied @@ -975,7 +1048,7 @@ static int CmdT55xxDetect(const char *Cmd) { if (try_with_pwd) CmdT55xxWakeUp(wakecmd); else - CmdT55xxWakeUp("q"); + CmdT55xxWakeUp(""); // sleep 90 ms nanosleep(&sleepperiod, &sleepperiod); } @@ -987,7 +1060,6 @@ static int CmdT55xxDetect(const char *Cmd) { continue; found = true; - break; } } else { @@ -996,7 +1068,7 @@ static int CmdT55xxDetect(const char *Cmd) { if (try_with_pwd) CmdT55xxWakeUp(wakecmd); else - CmdT55xxWakeUp("q"); + CmdT55xxWakeUp(""); // sleep 90 ms nanosleep(&sleepperiod, &sleepperiod); } @@ -1007,7 +1079,7 @@ static int CmdT55xxDetect(const char *Cmd) { } // toggle so we loop back if not found and try with pwd - if (!found && usepwd) + if (found == false && usepwd) try_with_pwd = !try_with_pwd; // force exit as detect block has been found @@ -1017,7 +1089,7 @@ static int CmdT55xxDetect(const char *Cmd) { } while (try_with_pwd); // Toggle so we loop back and try with wakeup. usewake = !usewake; - } while (!found && usewake); + } while (found == false && usewake); } else { found = t55xxTryDetectModulation(downlink_mode, T55XX_PrintConfig); } @@ -1541,74 +1613,6 @@ int printConfiguration(t55xx_conf_block_t b) { return PM3_SUCCESS; } -static int CmdT55xxWakeUp(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "lf t55xx wakeup", - "This commands sends the Answer-On-Request command and leaves the readerfield ON afterwards", - "lf t55xx wakeup -p 11223344 --> send wakeup with password\n" - ); - - // 3 + (5 or 6) - void *argtable[8] = { - arg_param_begin, - arg_str1("p", "pwd", "", "password (4 hex bytes)"), - arg_lit0("v", "verbose", "verbose output"), - }; - uint8_t idx = 3; - arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); - CLIExecWithReturn(ctx, Cmd, argtable, true); - - uint32_t password = 0; - int res = arg_get_u32_hexstr_def(ctx, 1, 0, &password); - if (res == 0 || res == 2) { - PrintAndLogEx(ERR, "Password should be 4 hex bytes"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - bool verbose = arg_get_lit(ctx, 2); - bool r0 = arg_get_lit(ctx, 3); - bool r1 = arg_get_lit(ctx, 4); - bool r2 = arg_get_lit(ctx, 5); - bool r3 = arg_get_lit(ctx, 6); - CLIParserFree(ctx); - - 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; - - struct p { - uint32_t password; - uint8_t flags; - } PACKED payload; - - payload.password = password; - payload.flags = (downlink_mode << 3); - - clearCommandBuffer(); - SendCommandNG(CMD_LF_T55XX_WAKEUP, (uint8_t *)&payload, sizeof(payload)); - if (WaitForResponseTimeout(CMD_LF_T55XX_WAKEUP, NULL, 1000) == false) { - PrintAndLogEx(WARNING, "command execution time out"); - return PM3_ETIMEOUT; - } - - if (verbose) - PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now"); - - return PM3_SUCCESS; -} - static int CmdT55xxWriteBlock(const char *Cmd) { uint8_t block = 0xFF; // default to invalid block uint32_t data = 0; // default to blank Block @@ -2867,8 +2871,8 @@ static int CmdT55xxWipe(const char *Cmd) { "lf t55xx wipe -p 11223344 -> wipes a T55x7 tag, config block 0x000880E0, using pwd" ); - // 4 + (5 or 6) - void *argtable[9] = { + // 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[4 + 5] = { arg_param_begin, arg_str0("c", "cfg", "", "configuration block0 (4 hex bytes)"), arg_str0("p", "pwd", "", "password (4 hex bytes)"), @@ -2978,11 +2982,14 @@ static int CmdT55xxChkPwds(const char *Cmd) { "lf t55xx chk --em aa11223344 -> try known pwdgen algo from some cloners based on EM4100 ID" ); - // Calculate size of argtable accordingly: - // 1 (help) + 3 (three user specified params) + ( 5 or 6 T55XX_DLMODE) - // 4 + (T55XX_DLMODE_xxx 5) - // 4 + (T55XX_DLMODE_ALL 6) == 10 - void *argtable[10] = { + /* + Calculate size of argtable accordingly: + 1 (help) + 3 (three user specified params) + ( 5 or 6 T55XX_DLMODE) + start index to call arg_add_t55xx_downloadlink() is 4 (1 + 3) given the above sample + */ + + // 1 (help) + 3 (three user specified params) + (6 T55XX_DLMODE_ALL) + void *argtable[4 + 6] = { arg_param_begin, arg_lit0("m", "fm", "use dictionary from flash memory (RDV4)"), arg_str0("f", "file", "", "file name"), @@ -3198,6 +3205,7 @@ static int CmdT55xxBruteForce(const char *Cmd) { "lf t55xx bruteforce --r2 -s aaaaaa77 -e aaaaaa99\n" ); + // 1 (help) + 2 (two user specified params) + (6 T55XX_DLMODE_ALL) void *argtable[3 + 6] = { arg_param_begin, arg_str1("s", "start", "", "search start password (4 hex bytes)"), @@ -3324,8 +3332,8 @@ static int CmdT55xxRecoverPW(const char *Cmd) { "lf t55xx recoverpw -p 11223344 --r3\n" ); - // 2 + (5 or 6) - void *argtable[8] = { + // 1 (help) + 1 (one user specified params) + (6 T55XX_DLMODE_ALL) + void *argtable[2 + 6] = { arg_param_begin, arg_str0("p", "pwd", "", "password (4 hex bytes)"), }; @@ -3564,8 +3572,8 @@ static int CmdT55xxDetectPage1(const char *Cmd) { "lf t55xx p1detect -p 11223344 --r3\n" ); - // 1 (help) + 2 (two user specified params) + ( 5 T55XX_DLMODE_SINGLE) - void *argtable[8] = { + // 1 (help) + 2 (two user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[3 + 5] = { arg_param_begin, arg_lit0("1", NULL, "extract using data from graphbuffer"), arg_str0("p", "pwd", "", "password (4 hex bytes)"), @@ -3662,6 +3670,7 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) { "lf t55xx deviceconfig -a 55 -b 14 -c 21 -d 30 -> default EM4305" ); + // 1 (help) + 9 (nine user specified params) + (5 T55XX_DLMODE_SINGLE) void *argtable[10 + 5] = { arg_param_begin, arg_int0("a", NULL, "<8..255>", "Set start gap"), @@ -3772,7 +3781,7 @@ static int CmdT55xxProtect(const char *Cmd) { "lf t55xx protect -p 11223344 -n 00000000 -> use pwd 11223344, sets new pwd 00000000" ); - // 4 + (5 or 6) + // 1 (help) + 3 (three user specified params) + (5 T55XX_DLMODE_SINGLE) void *argtable[4 + 5] = { arg_param_begin, arg_lit0("o", "override", "override safety check"),