From d6a18e02704b2b99b3d8396bd91e5d2b1f2ac56e Mon Sep 17 00:00:00 2001 From: kormax <3392860+kormax@users.noreply.github.com> Date: Wed, 8 Apr 2026 20:46:33 +0300 Subject: [PATCH 1/4] Implement 'hf mfdes brutedamslot' command --- CHANGELOG.md | 1 + client/src/cmdhfmfdes.c | 209 +++++++++++++++++++++++++++++++- client/src/mifare/desfirecore.c | 6 - client/src/mifare/desfirecore.h | 1 - client/src/pm3line_vocabulary.h | 1 + 5 files changed, 210 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 300a9d3f2..1801fe3e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Added `hf mfdes brutedamslot` command (@kormax) - Added `hf mfdes getdelegateappinfo` command (@kormax) - Added `hf secc info` command to retrieve the Card Recognition Template(@antiklesys) - Added `hf mfdes createdelegateapp` command (@kormax) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 79ac9e282..785ed0455 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -58,6 +58,8 @@ #define MFDES_BRUTEAID_MAD_STEP 0x10U #define MFDES_BRUTEFID_RESELECT_ATTEMPTS 3 #define MFDES_BRUTEFID_RESELECT_WAIT_MS 500 +#define MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS 3 +#define MFDES_BRUTEDAMSLOT_RESELECT_WAIT_MS 500 #define status(x) ( ((uint16_t)(0x91 << 8)) + (uint16_t)x ) /* @@ -2659,6 +2661,45 @@ static bool mfdesBruteAIDGeneratorNext(mfdes_bruteaid_generator_t *gen, uint32_t return mfdesBruteAIDGeneratorFullNext(&gen->g.full, id, progress); } +static int DesfireGetDelegatedInfoNoFieldOn(DesfireContext_t *dctx, uint16_t damslot, uint8_t *resp, size_t *resplen) { + uint8_t data[2] = {0}; + Uint2byteToMemLe(data, damslot); + + uint8_t xresp[16] = {0}; + size_t xresplen = 0; + uint8_t respcode = 0xFF; + + int res = DesfireExchangeEx(false, dctx, MFDES_GET_DELEGATE_INFO, data, sizeof(data), &respcode, xresp, &xresplen, true, 0); + if (res != PM3_SUCCESS) { + if (res == PM3_EAPDU_FAIL && respcode == 0xFF && xresplen == 0) { + return PM3_ECARDEXCHANGE; + } + return res; + } + + if (respcode == 0xFF) { + return PM3_ECARDEXCHANGE; + } + + if (respcode != MFDES_S_OPERATION_OK) { + return PM3_EAPDU_FAIL; + } + + if (xresplen != 8) { + return PM3_EAPDU_FAIL; + } + + if (resplen) { + *resplen = xresplen; + } + + if (resp) { + memcpy(resp, xresp, xresplen); + } + + return PM3_SUCCESS; +} + static int CmdHF14ADesBruteApps(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes bruteaid", @@ -2977,6 +3018,171 @@ static int CmdHF14ADesBruteISOFIDs(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes brutedamslot", + "Recover DAM slot to delegated AID mappings by bruteforce.\n" + "WARNING: This command takes a loooong time", + "hf mfdes brutedamslot -> bruteforce all DAM slots\n" + "hf mfdes brutedamslot --start 0000 --end 00ff -> bruteforce specific DAM slot range\n" + "hf mfdes brutedamslot --step 16 -> bruteforce DAM slots with step 16\n" + "hf mfdes brutedamslot --no-auth -> execute without authentication"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "Show APDU requests and responses"), + arg_lit0("v", "verbose", "Verbose output"), + arg_int0("n", "keyno", "", "Key number (default: 0 / PICC key)"), + arg_str0("t", "algo", "", "Crypt algo"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0(NULL, "kdf", "", "Key Derivation Function (KDF)"), + arg_str0("i", "kdfi", "", "KDF input (1-31 hex bytes)"), + arg_str0("m", "cmode", "", "Communicaton mode"), + arg_str0("c", "ccset", "", "Communicaton command set"), + arg_str0(NULL, "schann", "", "Secure channel"), + arg_str0(NULL, "start", "", "Starting DAM slot (2 hex bytes, little endian on card)"), + arg_str0(NULL, "end", "", "Last DAM slot (2 hex bytes, little endian on card)"), + arg_int0(NULL, "step", "", "Increment step when bruteforcing DAM slots"), + arg_lit0(NULL, "no-auth", "Execute without authentication"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 14); + + int keynum = arg_get_int_def(ctx, 3, 0x00); + if (keynum < 0 || keynum > 0xFF) { + CLIParserFree(ctx); + PrintAndLogEx(ERR, "Key number must be in range 0..255"); + return PM3_EINVARG; + } + + DesfireContext_t dctx = {0}; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, + &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL); + if (res) { + CLIParserFree(ctx); + return res; + } + + dctx.keyNum = keynum & 0xFF; + + uint32_t damslotStart = 0x0000; + if (CLIGetUint32Hex(ctx, 11, 0x0000, &damslotStart, NULL, 2, "DAM slot start must have 2 hex bytes")) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint32_t damslotEnd = 0xFFFF; + if (CLIGetUint32Hex(ctx, 12, 0xFFFF, &damslotEnd, NULL, 2, "DAM slot end must have 2 hex bytes")) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + int stepArg = arg_get_int_def(ctx, 13, 1); + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (stepArg <= 0) { + PrintAndLogEx(ERR, "Increment step should be greater than zero"); + return PM3_EINVARG; + } + uint32_t step = (uint32_t)stepArg; + + if (damslotStart > damslotEnd) { + PrintAndLogEx(ERR, "Start should be lower than or equal to end. start: %04x end: %04x", damslotStart, damslotEnd); + return PM3_EINVARG; + } + + res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + uint64_t totalCount = ((damslotEnd - damslotStart) / step) + 1; + uint64_t tested = 0; + uint64_t found = 0; + + PrintAndLogEx(INFO, "Bruteforcing DAM slots range " _YELLOW_("%04x") "-" _YELLOW_("%04x") " step " _YELLOW_("%u") " candidates " _YELLOW_("%llu"), + damslotStart, damslotEnd, step, (unsigned long long)totalCount); + + for (uint32_t damslot = damslotStart;; damslot += step) { + if (kbd_enter_pressed()) { + break; + } + + tested++; + float progress = (totalCount > 0) ? ((float)tested / (float)totalCount) * 100.0f : 100.0f; + PrintAndLogEx(INPLACE, "Brute DESFire DAM slot Progress " _YELLOW_("%0.1f") " %% current slot: %04X", progress, damslot); + + uint8_t resp[16] = {0}; + size_t resplen = 0; + res = DesfireGetDelegatedInfoNoFieldOn(&dctx, damslot & 0xffff, resp, &resplen); + + if (res == PM3_ECARDEXCHANGE || res == PM3_ETIMEOUT || res == PM3_ERFTRANS) { + for (int attempt = 1; attempt <= MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS; attempt++) { + printf("\33[2K\r"); // clear current inplace progress line before logging + PrintAndLogEx(WARNING, "No card response while checking DAM slot " _YELLOW_("%04X") ". Reselecting card (%d/%d)...", + damslot, attempt, MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS); + + msleep(MFDES_BRUTEDAMSLOT_RESELECT_WAIT_MS); + + res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose); + if (res != PM3_SUCCESS) { + if (res != PM3_ECARDEXCHANGE && res != PM3_ETIMEOUT && res != PM3_ERFTRANS) { + res = PM3_ECARDEXCHANGE; + } + continue; + } + + res = DesfireGetDelegatedInfoNoFieldOn(&dctx, damslot & 0xffff, resp, &resplen); + if (res == PM3_SUCCESS || res == PM3_EAPDU_FAIL || + (res != PM3_ECARDEXCHANGE && res != PM3_ETIMEOUT && res != PM3_ERFTRANS)) { + break; + } + } + + if (res == PM3_ECARDEXCHANGE || res == PM3_ETIMEOUT || res == PM3_ERFTRANS) { + PrintAndLogEx(FAILED, "Card is not responding after %d reselect attempts. Aborting at DAM slot " _YELLOW_("%04X"), + MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS, damslot); + DropField(); + return res; + } + } + + if (res == PM3_SUCCESS) { + uint32_t delegatedaid = MemLeToUint3byte(&resp[5]); + printf("\33[2K\r"); // clear current line before printing + if (delegatedaid == 0x000000) { + PrintAndLogEx(SUCCESS, "DAM slot 0x%04X ver 0x%02X AID " _YELLOW_("0x%06X (empty)"), + damslot, resp[0], delegatedaid); + } else { + PrintAndLogEx(SUCCESS, "DAM slot 0x%04X ver 0x%02X AID " _GREEN_("0x%06X"), + damslot, resp[0], delegatedaid); + } + found++; + if (verbose && resplen > 0) { + PrintAndLogEx(INFO, "Response [%zu] " _CYAN_("%s"), resplen, sprint_hex(resp, resplen)); + } + } + + if (damslotEnd - damslot < step) { + break; + } + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Done! Found " _GREEN_("%llu") " matching DAM slot candidate(s)", + (unsigned long long)found); + DropField(); + return PM3_SUCCESS; +} + // MIAFRE DESFire Authentication // keys: // NR DESC KEYLENGTH @@ -3923,7 +4129,7 @@ static int CmdHF14ADesGetDelegateAppInfo(const char *Cmd) { uint8_t resp[16] = {0}; size_t resplen = 0; - res = DesfireGetDelegatedInfo(&dctx, damslot & 0xffff, resp, &resplen); + res = DesfireGetDelegatedInfoNoFieldOn(&dctx, damslot & 0xffff, resp, &resplen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire GetDelegatedInfo command " _RED_("error") ". Result: %d", res); DropField(); @@ -7055,6 +7261,7 @@ static command_t CommandTable[] = { {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, + {"brutedamslot", CmdHF14ADesBruteDAMSlots, IfPm3Iso14443a, "Recover DAM slots to delegated AIDs by bruteforce"}, {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application"}, {"createdelegateapp", CmdHF14ADesCreateDelegateApp, IfPm3Iso14443a, "Create Delegated Application"}, {"getdelegateappinfo", CmdHF14ADesGetDelegateAppInfo, IfPm3Iso14443a, "Get Delegated Application info by DAM slot"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 51fea74a7..e944eb421 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -2249,12 +2249,6 @@ int DesfireCreateDelegatedApplication(DesfireContext_t *dctx, uint8_t *appdata, return PM3_SUCCESS; } -int DesfireGetDelegatedInfo(DesfireContext_t *dctx, uint16_t damslot, uint8_t *resp, size_t *resplen) { - uint8_t data[2] = {0}; - Uint2byteToMemLe(data, damslot); - return DesfireCommand(dctx, MFDES_GET_DELEGATE_INFO, data, sizeof(data), resp, resplen, 8); -} - int DesfireDeleteApplication(DesfireContext_t *dctx, uint32_t aid) { uint8_t data[3] = {0}; DesfireAIDUintToByte(aid, data); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 047e03272..2316d78e7 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -210,7 +210,6 @@ void DesfirePrintAppList(DesfireContext_t *dctx, PICCInfo_t *PICCInfo, AppListS int DesfireCreateApplication(DesfireContext_t *dctx, uint8_t *appdata, size_t appdatalen); int DesfireCreateDelegatedApplication(DesfireContext_t *dctx, uint8_t *appdata, size_t appdatalen, uint8_t *contdata, size_t contdatalen); -int DesfireGetDelegatedInfo(DesfireContext_t *dctx, uint16_t damslot, uint8_t *resp, size_t *resplen); int DesfireDeleteApplication(DesfireContext_t *dctx, uint32_t aid); int DesfireGetKeyVersion(DesfireContext_t *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen); diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index f1783202d..307a65e0d 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -494,6 +494,7 @@ const static vocabulary_t vocabulary[] = { { 0, "hf mfdes getaids" }, { 0, "hf mfdes getappnames" }, { 0, "hf mfdes bruteaid" }, + { 0, "hf mfdes brutedamslot" }, { 0, "hf mfdes createapp" }, { 0, "hf mfdes createdelegateapp" }, { 0, "hf mfdes getdelegateappinfo" }, From f5d659235b81770150347890f7590e59ac0fab97 Mon Sep 17 00:00:00 2001 From: kormax <3392860+kormax@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:15:30 +0300 Subject: [PATCH 2/4] Re-auth after failed response in 'hf mfdes brutedamslot' --- client/src/cmdhfmfdes.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 785ed0455..9add0d20c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3046,7 +3046,7 @@ static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { arg_lit0(NULL, "no-auth", "Execute without authentication"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, true); bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); @@ -3155,6 +3155,39 @@ static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { } } + if (res == PM3_EAPDU_FAIL && noauth == false) { + bool restored = false; + int authres = DesfireAuthenticate(&dctx, securechann, verbose); + + // An APDU-level failure on GetDelegatedInfo drops the authenticated state. + // Try to restore auth in-place first, then fall back to a full reselect. + if (authres == PM3_SUCCESS && DesfireIsAuthenticated(&dctx)) { + restored = true; + } + + for (int attempt = 1; attempt <= MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS && restored == false; attempt++) { + printf("\33[2K\r"); // clear current inplace progress line before logging + PrintAndLogEx(WARNING, "Lost authentication after DAM slot " _YELLOW_("%04X") ". Reselecting card (%d/%d)...", + damslot, attempt, MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS); + + msleep(MFDES_BRUTEDAMSLOT_RESELECT_WAIT_MS); + + authres = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, false, verbose); + if (authres == PM3_SUCCESS && DesfireIsAuthenticated(&dctx)) { + restored = true; + break; + } + } + + if (restored == false) { + printf("\33[2K\r"); // clear current inplace progress line before logging + PrintAndLogEx(FAILED, "Failed to restore authentication after DAM slot " _YELLOW_("%04X"), + damslot); + DropField(); + return PM3_ECARDEXCHANGE; + } + } + if (res == PM3_SUCCESS) { uint32_t delegatedaid = MemLeToUint3byte(&resp[5]); printf("\33[2K\r"); // clear current line before printing From 63a9a46b2d183b7c7c5564986c450f67677c383e Mon Sep 17 00:00:00 2001 From: kormax <3392860+kormax@users.noreply.github.com> Date: Thu, 9 Apr 2026 00:16:52 +0300 Subject: [PATCH 3/4] Replace space padding with dotted padding in 'hf mfdes getdelegateappinfo' --- client/src/cmdhfmfdes.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 9add0d20c..fe77bccb3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4176,11 +4176,11 @@ static int CmdHF14ADesGetDelegateAppInfo(const char *Cmd) { uint16_t freeblocks = MemLeToUint2byte(&resp[3]); uint32_t delegatedaid = MemLeToUint3byte(&resp[5]); - PrintAndLogEx(SUCCESS, "DAM slot 0x%04x", damslot & 0xffff); - PrintAndLogEx(SUCCESS, "DAM slot ver 0x%02x", resp[0]); - PrintAndLogEx(SUCCESS, "Quota limit 0x%04x (%u blocks)", quota, (unsigned int)quota); - PrintAndLogEx(SUCCESS, "Free blocks 0x%04x (%u blocks)", freeblocks, (unsigned int)freeblocks); - PrintAndLogEx(SUCCESS, "Delegated AID 0x%06x", delegatedaid); + PrintAndLogEx(SUCCESS, "DAM slot....... 0x%04x", damslot & 0xffff); + PrintAndLogEx(SUCCESS, "DAM slot ver... 0x%02x", resp[0]); + PrintAndLogEx(SUCCESS, "Quota limit.... 0x%04x (%u blocks)", quota, (unsigned int)quota); + PrintAndLogEx(SUCCESS, "Free blocks.... 0x%04x (%u blocks)", freeblocks, (unsigned int)freeblocks); + PrintAndLogEx(SUCCESS, "Delegated AID.. 0x%06x", delegatedaid); DropField(); return PM3_SUCCESS; From ad27ccae5c6af2900017ad34a4d44b5298c365bd Mon Sep 17 00:00:00 2001 From: kormax <3392860+kormax@users.noreply.github.com> Date: Thu, 9 Apr 2026 00:20:31 +0300 Subject: [PATCH 4/4] Remove use of printf in mfdes module --- client/src/cmdhfmfdes.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index fe77bccb3..9dfe93ca0 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2827,7 +2827,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { res = DesfireSelectAIDHexNoFieldOn(&dctx, id); if (res == PM3_ECARDEXCHANGE || res == PM3_ETIMEOUT || res == PM3_ERFTRANS) { for (int attempt = 1; attempt <= MFDES_BRUTEAID_RESELECT_ATTEMPTS; attempt++) { - printf("\33[2K\r"); // clear current inplace progress line before logging + PROMPT_CLEARLINE; PrintAndLogEx(WARNING, "No card response while checking AID " _YELLOW_("%06X") ". Reselecting card (%d/%d)...", id, attempt, MFDES_BRUTEAID_RESELECT_ATTEMPTS); @@ -2858,7 +2858,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { } if (res == PM3_SUCCESS) { - printf("\33[2K\r"); // clear current line before printing + PROMPT_CLEARLINE; PrintAndLogEx(SUCCESS, "Found New DESFire AID " _GREEN_("%06X"), id); } } @@ -2969,7 +2969,7 @@ static int CmdHF14ADesBruteISOFIDs(const char *Cmd) { if (res == PM3_ECARDEXCHANGE || res == PM3_ETIMEOUT || res == PM3_ERFTRANS) { for (int attempt = 1; attempt <= MFDES_BRUTEFID_RESELECT_ATTEMPTS; attempt++) { - printf("\33[2K\r"); // clear current inplace progress line before logging + PROMPT_CLEARLINE; PrintAndLogEx(WARNING, "No card response while checking ISO ID " _YELLOW_("%04X") ". Reselecting card (%d/%d)...", isofid, attempt, MFDES_BRUTEFID_RESELECT_ATTEMPTS); @@ -2997,7 +2997,7 @@ static int CmdHF14ADesBruteISOFIDs(const char *Cmd) { if (res == PM3_SUCCESS) { found++; - printf("\33[2K\r"); // clear current line before printing + PROMPT_CLEARLINE; PrintAndLogEx(SUCCESS, "Found new ISO file ID " _GREEN_("0x%04X"), isofid); if (verbose && resplen > 0) { PrintAndLogEx(INFO, "Response [%zu] " _CYAN_("%s"), resplen, sprint_hex(resp, resplen)); @@ -3126,7 +3126,7 @@ static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { if (res == PM3_ECARDEXCHANGE || res == PM3_ETIMEOUT || res == PM3_ERFTRANS) { for (int attempt = 1; attempt <= MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS; attempt++) { - printf("\33[2K\r"); // clear current inplace progress line before logging + PROMPT_CLEARLINE; PrintAndLogEx(WARNING, "No card response while checking DAM slot " _YELLOW_("%04X") ". Reselecting card (%d/%d)...", damslot, attempt, MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS); @@ -3166,7 +3166,7 @@ static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { } for (int attempt = 1; attempt <= MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS && restored == false; attempt++) { - printf("\33[2K\r"); // clear current inplace progress line before logging + PROMPT_CLEARLINE; PrintAndLogEx(WARNING, "Lost authentication after DAM slot " _YELLOW_("%04X") ". Reselecting card (%d/%d)...", damslot, attempt, MFDES_BRUTEDAMSLOT_RESELECT_ATTEMPTS); @@ -3180,7 +3180,7 @@ static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { } if (restored == false) { - printf("\33[2K\r"); // clear current inplace progress line before logging + PROMPT_CLEARLINE; PrintAndLogEx(FAILED, "Failed to restore authentication after DAM slot " _YELLOW_("%04X"), damslot); DropField(); @@ -3190,7 +3190,7 @@ static int CmdHF14ADesBruteDAMSlots(const char *Cmd) { if (res == PM3_SUCCESS) { uint32_t delegatedaid = MemLeToUint3byte(&resp[5]); - printf("\33[2K\r"); // clear current line before printing + PROMPT_CLEARLINE; if (delegatedaid == 0x000000) { PrintAndLogEx(SUCCESS, "DAM slot 0x%04X ver 0x%02X AID " _YELLOW_("0x%06X (empty)"), damslot, resp[0], delegatedaid);