From 99b1093702aaf53a63f5396b97b357f615516d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 8 Feb 2021 01:12:14 +0100 Subject: [PATCH 1/5] Added actual MF DESfire enumeration --- client/src/cmdhfmfdes.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f5222fb9a..5c5966cdc 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3907,7 +3907,26 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { dfname_t dfnames[255]; uint8_t dfname_count = 0; - if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { + int resAID = handler_desfire_appids(app_ids, &app_ids_len); + if (resAID == PM3_EAPDU_FAIL && bruteforce) { + PrintAndLogEx(WARNING, "Tag doesn't allow listing AIDs"); + PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!"); + for (uint32_t id = 0; id <= 0xFFFFFF; id++) { + uint8_t appId[3] = {(id & 0xFF), (id >> 8 & 0xFF), (id >> 16 & 0xFF)}; + sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, appId}; //0x5a + uint16_t sw = 0; + uint8_t data[255 * 5] = {0x00}; + uint32_t resplen = 0; + DESFIRESendApdu(!tag->rf_field_on, true, apdu, data, sizeof(data), &resplen, &sw); + if (sw == status(MFDES_S_OPERATION_OK)) { + PrintAndLogEx(DEBUG, "Got new APPID 0x%02X%02X%02X\n", appId[2], appId[1], appId[0]); + app_ids[app_ids_len] = appId[0]; + app_ids[app_ids_len+1] = appId[1]; + app_ids[app_ids_len+2] = appId[2]; + app_ids_len+=3; + } + } + } else if (resAID != PM3_SUCCESS) { PrintAndLogEx(ERR, "Can't get list of applications on tag"); DropFieldDesfire(); return PM3_ESOFT; From 6d10525c09536b0539e1510ea3effcc14221667f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 8 Feb 2021 03:32:27 +0100 Subject: [PATCH 2/5] fixed missing parameter --- client/src/cmdhfmfdes.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 5c5966cdc..4fb1721a3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3890,9 +3890,11 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { void *argtable[] = { arg_param_begin, + arg_lit0("b", "bruteforce", "Bruteforce AIDs if tag doesn't allow listing"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + bool bruteforce = arg_get_lit(ctx, 1); CLIParserFree(ctx); DropFieldDesfire(); From 8af1cedf1f2f363859d04252cee75e81360884d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Tue, 9 Feb 2021 15:17:20 +0100 Subject: [PATCH 3/5] Improved MFDES AID bruteforce --- client/src/cmdhfmfdes.c | 87 ++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 4fb1721a3..c8a79af4b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3890,11 +3890,9 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("b", "bruteforce", "Bruteforce AIDs if tag doesn't allow listing"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool bruteforce = arg_get_lit(ctx, 1); CLIParserFree(ctx); DropFieldDesfire(); @@ -3909,26 +3907,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { dfname_t dfnames[255]; uint8_t dfname_count = 0; - int resAID = handler_desfire_appids(app_ids, &app_ids_len); - if (resAID == PM3_EAPDU_FAIL && bruteforce) { - PrintAndLogEx(WARNING, "Tag doesn't allow listing AIDs"); - PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!"); - for (uint32_t id = 0; id <= 0xFFFFFF; id++) { - uint8_t appId[3] = {(id & 0xFF), (id >> 8 & 0xFF), (id >> 16 & 0xFF)}; - sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, appId}; //0x5a - uint16_t sw = 0; - uint8_t data[255 * 5] = {0x00}; - uint32_t resplen = 0; - DESFIRESendApdu(!tag->rf_field_on, true, apdu, data, sizeof(data), &resplen, &sw); - if (sw == status(MFDES_S_OPERATION_OK)) { - PrintAndLogEx(DEBUG, "Got new APPID 0x%02X%02X%02X\n", appId[2], appId[1], appId[0]); - app_ids[app_ids_len] = appId[0]; - app_ids[app_ids_len+1] = appId[1]; - app_ids[app_ids_len+2] = appId[2]; - app_ids_len+=3; - } - } - } else if (resAID != PM3_SUCCESS) { + if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Can't get list of applications on tag"); DropFieldDesfire(); return PM3_ESOFT; @@ -4004,6 +3983,69 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesBruteApps(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes bruteaid", + "Recover AIDs by bruteforce.\n" + "WARNING: This command takes a long time", + "hf mfdes bruteaid -> Search all apps\n" + "hf mfdes bruteaid -s F0000F -i 16 -> Search MAD range manually"); + + void *argtable[] = { + arg_param_begin, + arg_strx0("s", "start", "", "Starting App ID as hex bytes (3 bytes,big endian)"), + arg_strx0("e", "end", "", "Last App ID as hex bytes (3 bytes,big endian)"), + arg_int0("i", "step", "", "Increment step when bruteforcing (decimal integer)"), + arg_lit0("m", "mad", "Only bruteforce the MAD range"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint8_t startAid[3] = {0}; + uint8_t endAid[3] = {0xFF, 0xFF, 0xFF}; + int startLen = 0; + int endLen = 0; + CLIGetHexWithReturn(ctx, 1, startAid, &startLen); + CLIGetHexWithReturn(ctx, 2, endAid, &endLen); + uint32_t idIncrement = arg_get_int_def(ctx, 3, 1); + bool mad = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + // TODO: We need to check the tag version, EV1 should stop after 26 apps are found + + // uint8_t app_ids[32*3] = {0}; // we are hoping to find less than 32 apps, this can backfire spectacularly + // uint8_t app_ids_len = 0; + if (mad) { + idIncrement = 0x10; + startAid[0] = 0xF0; + startAid[1] = 0x00; + startAid[2] = 0x0F; + } + uint32_t idStart = (startAid[0] << 16) + (startAid[1] << 8) + startAid[2]; + uint32_t idEnd = (endAid[0] << 16) + (endAid[1] << 8) + endAid[2]; + PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!"); + for (uint32_t id = idStart; id <= idEnd && id >= idStart; id += idIncrement) { + if (kbd_enter_pressed()) break; + int progress = ((id - idStart)*100) / ((idEnd - idStart)); + PrintAndLogEx(INPLACE, "Progress: %d %%, current AID: %06X", progress, id); + uint8_t appId[3] = {(id & 0xFF), (id >> 8 & 0xFF), (id >> 16 & 0xFF)}; + sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, appId}; //0x5a + uint16_t sw = 0; + uint8_t data[255 * 5] = {0x00}; + uint32_t resplen = 0; + DESFIRESendApdu(!tag->rf_field_on, true, apdu, data, sizeof(data), &resplen, &sw); + if (sw == status(MFDES_S_OPERATION_OK)) { + printf("\33[2K\r"); // clear current line before printing + PrintAndLogEx(SUCCESS, "Got new APPID %06X", id); + // app_ids[app_ids_len] = appId[0]; + // app_ids[app_ids_len+1] = appId[1]; + // app_ids[app_ids_len+2] = appId[2]; + // app_ids_len+=3; + } + } + PrintAndLogEx(SUCCESS, "Done"); + DropFieldDesfire(); + return PM3_SUCCESS; +} + static int CmdHF14ADesChangeKey(const char *Cmd) { //DropFieldDesfire(); // NR DESC KEYLENGHT @@ -4945,6 +4987,7 @@ static command_t CommandTable[] = { // {"ndef", CmdHF14aDesNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("AID") " -----------------------"}, + {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, {"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"}, {"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"}, {"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, From cf8256979d6c2bd3fa460345884780bb81f6cfd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Tue, 9 Feb 2021 16:15:52 +0100 Subject: [PATCH 4/5] fix code per comments --- client/src/cmdhfmfdes.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c8a79af4b..4fb4703df 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3993,9 +3993,9 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("s", "start", "", "Starting App ID as hex bytes (3 bytes,big endian)"), - arg_strx0("e", "end", "", "Last App ID as hex bytes (3 bytes,big endian)"), - arg_int0("i", "step", "", "Increment step when bruteforcing (decimal integer)"), + arg_strx0("s", "start", "", "Starting App ID as hex bytes (3 bytes,big endian)"), + arg_strx0("e", "end", "", "Last App ID as hex bytes (3 bytes,big endian)"), + arg_int0("i", "step", "", "Increment step when bruteforcing (decimal integer)"), arg_lit0("m", "mad", "Only bruteforce the MAD range"), arg_param_end }; @@ -4010,23 +4010,21 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { bool mad = arg_get_lit(ctx, 4); CLIParserFree(ctx); // TODO: We need to check the tag version, EV1 should stop after 26 apps are found - - // uint8_t app_ids[32*3] = {0}; // we are hoping to find less than 32 apps, this can backfire spectacularly - // uint8_t app_ids_len = 0; if (mad) { idIncrement = 0x10; startAid[0] = 0xF0; startAid[1] = 0x00; startAid[2] = 0x0F; } - uint32_t idStart = (startAid[0] << 16) + (startAid[1] << 8) + startAid[2]; - uint32_t idEnd = (endAid[0] << 16) + (endAid[1] << 8) + endAid[2]; + uint32_t idStart = le24toh(startAid); + uint32_t idEnd = le24toh(endAid); PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!"); for (uint32_t id = idStart; id <= idEnd && id >= idStart; id += idIncrement) { if (kbd_enter_pressed()) break; int progress = ((id - idStart)*100) / ((idEnd - idStart)); PrintAndLogEx(INPLACE, "Progress: %d %%, current AID: %06X", progress, id); - uint8_t appId[3] = {(id & 0xFF), (id >> 8 & 0xFF), (id >> 16 & 0xFF)}; + uint8_t appId[3] = {0}; + htole24(id, appId); sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, appId}; //0x5a uint16_t sw = 0; uint8_t data[255 * 5] = {0x00}; @@ -4035,10 +4033,6 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { if (sw == status(MFDES_S_OPERATION_OK)) { printf("\33[2K\r"); // clear current line before printing PrintAndLogEx(SUCCESS, "Got new APPID %06X", id); - // app_ids[app_ids_len] = appId[0]; - // app_ids[app_ids_len+1] = appId[1]; - // app_ids[app_ids_len+2] = appId[2]; - // app_ids_len+=3; } } PrintAndLogEx(SUCCESS, "Done"); From 8760068a0304940654f75e54b8ff2895f15fa6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Tue, 9 Feb 2021 16:52:48 +0100 Subject: [PATCH 5/5] make style --- client/src/cmdhfmfdes.c | 2 +- doc/commands.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 4fb4703df..fa9b29b18 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4021,7 +4021,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { PrintAndLogEx(INFO, "Enumerating through all AIDs manually, this will take a while!"); for (uint32_t id = idStart; id <= idEnd && id >= idStart; id += idIncrement) { if (kbd_enter_pressed()) break; - int progress = ((id - idStart)*100) / ((idEnd - idStart)); + int progress = ((id - idStart) * 100) / ((idEnd - idStart)); PrintAndLogEx(INPLACE, "Progress: %d %%, current AID: %06X", progress, id); uint8_t appId[3] = {0}; htole24(id, appId); diff --git a/doc/commands.md b/doc/commands.md index 3c55c5368..b20dfe64d 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -433,6 +433,7 @@ Check column "offline" for their availability. |`hf mfdes getuid `|N |`Get random uid` |`hf mfdes info `|N |`Tag information` |`hf mfdes list `|Y |`List DESFire (ISO 14443A) history` +|`hf mfdes bruteaid `|N |`Recover AIDs by bruteforce` |`hf mfdes createaid `|N |`Create Application ID` |`hf mfdes deleteaid `|N |`Delete Application ID` |`hf mfdes selectaid `|N |`Select Application ID`