From 257358ac12a86b6b2b52e982a1067515b64682ed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Oct 2020 02:04:44 +0100 Subject: [PATCH] added "hf mf supercard" , to extract key from card --- client/src/cmdhfmf.c | 127 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 3f65af4dd..65371c7cb 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -18,13 +18,16 @@ #include "cmdtrace.h" #include "emv/dump.h" #include "mifare/mifaredefault.h" // mifare default key array -#include "cliparser.h" // argtable +#include "cliparser.h" // argtable #include "hardnested_bf_core.h" // SetSIMDInstr #include "mifare/mad.h" #include "mifare/ndef.h" #include "protocols.h" -#include "util_posix.h" // msclock +#include "util_posix.h" // msclock #include "cmdhfmfhard.h" +#include "des.h" // des ecb +#include "crapto1/crapto1.h" // prng_successor +#include "cmdhf14a.h" // exchange APDU #define MFBLOCK_SIZE 16 @@ -627,7 +630,6 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) { } } - static uint16_t NumOfBlocks(char card) { switch (card) { case '0' : @@ -3691,7 +3693,6 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { return PM3_SUCCESS; } - static int CmdHF14AMfEClear(const char *Cmd) { char c = tolower(param_getchar(Cmd, 0)); if (c == 'h') return usage_hf14_eclr(); @@ -5265,6 +5266,123 @@ static int CmdHf14AGen3Freeze(const char *Cmd) { return PM3_SUCCESS; } + +static void des_decrypt(void *out, const void *in, const void *key) { + mbedtls_des_context ctx; + mbedtls_des_setkey_dec(&ctx, key); + mbedtls_des_crypt_ecb(&ctx, in, out); +} + +static int CmdHf14AMfSuperCard(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf supercard", + "Extract info from a `super card`", + "hf mf supercard"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); +/* + uint8_t reset[] = { 0x02, 0x00, 0xa6, 0xc0, 0x00 }; +*/ + + bool activate_field = true; + bool keep_field_on = true; + uint8_t responseA[22]; + uint8_t responseB[22]; + int respAlen = 0; + int respBlen = 0; + + // --------------- First ---------------- + uint8_t aFIRST[] = { 0x00, 0xa6, 0xb0, 0x00, 0x10 }; + int res = ExchangeAPDU14a(aFIRST, sizeof(aFIRST), activate_field, keep_field_on, responseA, sizeof(responseA), &respAlen); + if (res) { + DropField(); + return res; + } + + // --------------- Second ---------------- + activate_field = false; + keep_field_on = false; + + uint8_t aSECOND[] = { 0x00, 0xa6, 0xb0, 0x01, 0x10 }; + res = ExchangeAPDU14a(aSECOND, sizeof(aSECOND), activate_field, keep_field_on, responseB, sizeof(responseB), &respBlen); + if (res) { + DropField(); + return res; + } + +// uint8_t inA[] = { 0x72, 0xD7, 0xF4, 0x3E, 0xFD, 0xAB, 0xF2, 0x35, 0xFD, 0x49, 0xEE, 0xDC, 0x44, 0x95, 0x43, 0xC4}; +// uint8_t inB[] = { 0xF0, 0xA2, 0x67, 0x6A, 0x04, 0x6A, 0x72, 0x12, 0x76, 0xA4, 0x1D, 0x02, 0x1F, 0xEA, 0x20, 0x85}; + + uint8_t outA[16] = {0}; + uint8_t outB[16] = {0}; + + uint8_t key[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + for (uint8_t i=0; i < 16; i += 8) { + des_decrypt(outA + i, responseA + i, key); + des_decrypt(outB + i, responseB + i, key); + } + + PrintAndLogEx(INFO, " in : %s", sprint_hex_inrow(responseA, respAlen)); + PrintAndLogEx(INFO, "out : %s", sprint_hex_inrow(outA, sizeof(outA))); + + PrintAndLogEx(INFO, " in : %s", sprint_hex_inrow(responseB, respAlen)); + PrintAndLogEx(INFO, "out : %s", sprint_hex_inrow(outB, sizeof(outB))); + + if (memcmp(outA, "\x01\x01\x01\x01\x01\x01\x01\x01", 8) == 0) { + PrintAndLogEx(INFO, "No trace recorded"); + return PM3_SUCCESS; + } + + // second trace? + if (memcmp(outB, "\x01\x01\x01\x01\x01\x01\x01\x01", 8) == 0) { + PrintAndLogEx(INFO, "Only one trace recorded"); + return PM3_SUCCESS; + } + + nonces_t data; + + // first + uint16_t NT0 = (outA[6] << 8) | outA[7]; + data.cuid = bytes_to_num(outA, 4); + data.nonce = prng_successor(NT0, 31); + data.nr = bytes_to_num(outA + 8, 4); + data.ar = bytes_to_num(outA + 12, 4); + data.at = 0; + + // second + NT0 = (outB[6] << 8) | outB[7]; + data.nonce2 = prng_successor(NT0, 31);; + data.nr2 = bytes_to_num(outB + 8, 4); + data.ar2 = bytes_to_num(outB + 12, 4); + data.sector = 0; + data.keytype = outA[4]; + data.state = FIRST; + + PrintAndLogEx(DEBUG, "A NT %08x", data.nonce); + PrintAndLogEx(DEBUG, "A NR %08x", data.nr); + PrintAndLogEx(DEBUG, "A AR %08x", data.ar); + PrintAndLogEx(DEBUG, ""); + PrintAndLogEx(DEBUG, "B NT %08x", data.nonce2); + PrintAndLogEx(DEBUG, "B NR %08x", data.nr2); + PrintAndLogEx(DEBUG, "B AR %08x", data.ar2); + + uint64_t key64 = -1; + res = mfkey32_moebius(&data, &key64); + + if (res) + PrintAndLogEx(SUCCESS, "recovered key [ " _GREEN_("%12" PRIX64) " ]", key64); + else + PrintAndLogEx(FAILED, "failed to recover any key"); + + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, @@ -5279,6 +5397,7 @@ static command_t CommandTable[] = { {"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"}, {"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"}, {"decrypt", CmdHf14AMfDecryptBytes, AlwaysAvailable, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"}, + {"supercard", CmdHf14AMfSuperCard, IfPm3Iso14443a, "Extract info from a `super card`"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"}, {"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"}, {"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE Classic tag to binary file"},