mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
added "hf mf supercard" , to extract key from card
This commit is contained in:
parent
748f067143
commit
257358ac12
1 changed files with 123 additions and 4 deletions
|
@ -25,6 +25,9 @@
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "util_posix.h" // msclock
|
#include "util_posix.h" // msclock
|
||||||
#include "cmdhfmfhard.h"
|
#include "cmdhfmfhard.h"
|
||||||
|
#include "des.h" // des ecb
|
||||||
|
#include "crapto1/crapto1.h" // prng_successor
|
||||||
|
#include "cmdhf14a.h" // exchange APDU
|
||||||
|
|
||||||
#define MFBLOCK_SIZE 16
|
#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) {
|
static uint16_t NumOfBlocks(char card) {
|
||||||
switch (card) {
|
switch (card) {
|
||||||
case '0' :
|
case '0' :
|
||||||
|
@ -3691,7 +3693,6 @@ static int CmdHF14AMfEGetSc(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdHF14AMfEClear(const char *Cmd) {
|
static int CmdHF14AMfEClear(const char *Cmd) {
|
||||||
char c = tolower(param_getchar(Cmd, 0));
|
char c = tolower(param_getchar(Cmd, 0));
|
||||||
if (c == 'h') return usage_hf14_eclr();
|
if (c == 'h') return usage_hf14_eclr();
|
||||||
|
@ -5265,6 +5266,123 @@ static int CmdHf14AGen3Freeze(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
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[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
|
{"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"},
|
||||||
|
@ -5279,6 +5397,7 @@ static command_t CommandTable[] = {
|
||||||
{"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"},
|
{"chk", CmdHF14AMfChk, IfPm3Iso14443a, "Check keys"},
|
||||||
{"fchk", CmdHF14AMfChk_fast, IfPm3Iso14443a, "Check keys fast, targets all keys on card"},
|
{"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"},
|
{"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") " -----------------------"},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
|
||||||
{"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"},
|
{"auth4", CmdHF14AMfAuth4, IfPm3Iso14443a, "ISO14443-4 AES authentication"},
|
||||||
{"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE Classic tag to binary file"},
|
{"dump", CmdHF14AMfDump, IfPm3Iso14443a, "Dump MIFARE Classic tag to binary file"},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue