From 11fe8f783afae17f7605ae4bf04fcf67259815d8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 9 Oct 2025 22:26:52 +0200 Subject: [PATCH] Add --skip to hw tearoff, to cope with more complex commands. Example provided for hf mfu wrbl --- armsrc/appmain.c | 17 +++++++++++------ armsrc/mifareutil.c | 6 ++++++ client/src/cmdhw.c | 25 +++++++++++++++++++++---- include/pm3_cmd.h | 1 + 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 632646eaf..49fcafa66 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -94,6 +94,7 @@ static int button_status = BUTTON_NO_CLICK; static bool allow_send_wtx = false; uint16_t g_tearoff_delay_us = 0; bool g_tearoff_enabled = false; +uint8_t g_tearoff_skip = 0; int tearoff_hook(void) { if (g_tearoff_enabled) { @@ -102,6 +103,11 @@ int tearoff_hook(void) { g_tearoff_enabled = false; return PM3_SUCCESS; // SUCCESS = the hook didn't do anything } + if (g_tearoff_skip > 0) { + Dbprintf(_GREEN_("Tear-off skipped!")); + g_tearoff_skip--; + return PM3_SUCCESS; // SUCCESS = the hook didn't do anything + } SpinDelayUsPrecision(g_tearoff_delay_us); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); g_tearoff_enabled = false; @@ -882,12 +888,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_SET_TEAROFF: { - struct p { - uint16_t delay_us; - bool on; - bool off; - } PACKED; - struct p *payload = (struct p *)packet->data.asBytes; + tearoff_params_t *payload = (tearoff_params_t *)packet->data.asBytes; if (payload->on && payload->off) { reply_ng(CMD_SET_TEAROFF, PM3_EINVARG, NULL, 0); } @@ -903,6 +904,10 @@ static void PacketReceived(PacketCommandNG *packet) { if (payload->delay_us > 0) { g_tearoff_delay_us = payload->delay_us; } + + if (payload->skip > -1) { + g_tearoff_skip = payload->skip; + } reply_ng(CMD_SET_TEAROFF, PM3_SUCCESS, NULL, 0); break; } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 8c62a7a6a..e0342b769 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -87,6 +87,9 @@ uint16_t mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t * AddCrc14A(dcmd, data_size + 1); ReaderTransmit(dcmd, sizeof(dcmd), timing); + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred + return 0; + } uint16_t len = ReaderReceive(answer, answer_len, answer_parity); if (len == 0) { if (g_dbglevel >= DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); @@ -114,6 +117,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t } else { ReaderTransmit(dcmd, sizeof(dcmd), timing); } + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred + return 0; + } uint16_t len = ReaderReceive(answer, answer_len, par); diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index 850211c76..9bbdc9836 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1174,6 +1174,11 @@ int handle_tearoff(tearoff_params_t *params, bool verbose) { if (params->delay_us > 0 && verbose) PrintAndLogEx(INFO, "Tear-off hook configured with delay of " _GREEN_("%i us"), params->delay_us); + if (params->skip > 0 && verbose) + PrintAndLogEx(INFO, "Tear-off hook will be skipped " _YELLOW_("%i times") " before being activated", params->skip); + if (params->skip == 0 && verbose) + PrintAndLogEx(INFO, "Tear-off hook skipping " _GREEN_("disabled")); + if (params->on && verbose) PrintAndLogEx(INFO, "Tear-off hook " _GREEN_("enabled")); @@ -1201,6 +1206,7 @@ static int CmdTearoff(const char *Cmd) { arg_int0(NULL, "delay", "", "Delay in us before triggering tear-off, must be between 1 and 43000"), arg_lit0(NULL, "on", "Activate tear-off hook"), arg_lit0(NULL, "off", "Deactivate tear-off hook"), + arg_int0(NULL, "skip", "", "Skip N triggers before activating the hook"), arg_lit0("s", "silent", "less verbose output"), arg_lit0(NULL, "list", "List commands implementing tear-off hooks"), arg_param_end @@ -1211,8 +1217,9 @@ static int CmdTearoff(const char *Cmd) { int delay = arg_get_int_def(ctx, 1, -1); params.on = arg_get_lit(ctx, 2); params.off = arg_get_lit(ctx, 3); - bool silent = arg_get_lit(ctx, 4); - bool list = arg_get_lit(ctx, 5); + int skip = arg_get_int_def(ctx, 4, -1); + bool silent = arg_get_lit(ctx, 5); + bool list = arg_get_lit(ctx, 6); CLIParserFree(ctx); if (list) { @@ -1223,8 +1230,8 @@ static int CmdTearoff(const char *Cmd) { PrintAndLogEx(INFO, " hf 15 raw"); PrintAndLogEx(INFO, " hf iclass creditepurse"); PrintAndLogEx(INFO, " hf iclass wrbl"); - PrintAndLogEx(INFO, " hf mfc wrbl"); - // PrintAndLogEx(INFO, " hf mfu wrbl"); + PrintAndLogEx(INFO, " hf mf wrbl"); + PrintAndLogEx(INFO, " hf mfu wrbl (with --skip 3)"); PrintAndLogEx(INFO, " hf topaz wrbl"); PrintAndLogEx(INFO, " lf em 4x05 write"); PrintAndLogEx(INFO, " lf em 4x50 wrbl"); @@ -1251,6 +1258,16 @@ static int CmdTearoff(const char *Cmd) { } params.delay_us = delay; + + if (skip != -1) { + if ((skip < 0) || (skip > 127)) { + PrintAndLogEx(WARNING, "You can't set skip out of 0..127 range!"); + return PM3_EINVARG; + } + } + + params.skip = skip; + if (params.on && params.off) { PrintAndLogEx(WARNING, "You can't set both --on and --off!"); return PM3_EINVARG; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index d8ecc06a1..f0584061c 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -371,6 +371,7 @@ typedef struct { typedef struct { uint16_t delay_us; + int8_t skip; bool on; bool off; } PACKED tearoff_params_t;