hf mfu info - start in identify system of a mfu/ntag tag

This commit is contained in:
iceman1001 2021-02-19 20:41:32 +01:00
parent e729d1804d
commit f00c00c150

View file

@ -745,13 +745,13 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig
// ref: AN11350 NTAG 21x Originality Signature Validation
// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
const ecdsa_publickey_t nxp_mfu_public_keys[] = {
{"NXP Mifare Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{"Manufacturer Mifare Classic MFC1C14_x", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
{"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"},
{"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{"Manufacturer MIFARE Classic MFC1C14_x", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
{"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"},
};
/*
@ -805,7 +805,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig
for (i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_ECDA_KEYLEN];
uint8_t key[PUBLIC_ECDA_KEYLEN] = {0};
param_gethex_to_eol(nxp_mfu_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, signature_len, false);
@ -941,6 +941,249 @@ static char *GenerateFilename(const char *prefix, const char *suffix) {
return fptr;
}
//------------------------------------
/*
static int mfu_decrypt_amiibo(uint8_t *encrypted, uint16_t elen, uint8_t *decrypted, uint16_t *dlen) {
if (elen < NFC3D_AMIIBO_SIZE / 4) {
PrintAndLogEx(ERR, "ERR, data wrong length, got %zu , expected %zu", elen, (NFC3D_AMIIBO_SIZE / 4));
return PM3_ESOFT;
}
nfc3d_amiibo_keys amiibo_keys = {0};
if (nfc3d_amiibo_load_keys(&amiibo_keys) == false) {
return PM3_ESOFT;
}
if (nfc3d_amiibo_unpack(&amiibo_keys, encrypted, decrypted) == false) {
PrintAndLogEx(ERR, "WARNING, Tag signature was NOT valid");
}
*dlen = NFC3D_AMIIBO_SIZE;
return PM3_SUCCESS;
}
static int mfu_dump_tag(uint16_t pages, void **pdata, uint16_t *len) {
int res = PM3_SUCCESS;
uint16_t maxbytes = (pages * 4);
*pdata = calloc(maxbytes, sizeof(uint8_t));
if (*pdata == NULL) {
PrintAndLogEx(FAILED, "error, cannot allocate memory");
res = PM3_EMALLOC;
goto out;
}
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, 0, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "Command execute time-out");
free(*pdata);
res = PM3_ETIMEOUT;
goto out;
}
if (resp.oldarg[0] != 1) {
PrintAndLogEx(WARNING, "Failed reading card");
free(*pdata);
res = PM3_ESOFT;
goto out;
}
// read all memory
uint32_t startindex = resp.oldarg[2];
uint32_t buffer_size = resp.oldarg[1];
if (buffer_size > maxbytes) {
PrintAndLogEx(FAILED, "Data exceeded buffer size!");
buffer_size = maxbytes;
}
if (!GetFromDevice(BIG_BUF, *pdata, buffer_size, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
free(*pdata);
res = PM3_ETIMEOUT;
goto out;
}
if (len)
*len = buffer_size;
out:
return res;
}
*/
/*
Lego Dimensions,
Version: 00 04 04 02 01 00 0F 03
matching bytes:
index 12 ( 3 * 4 )
E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E
*/
typedef struct {
const char *desc;
const char *version;
uint8_t mpos;
uint8_t mlen;
const char *match;
uint32_t (*Pwd)(uint8_t *uid);
uint16_t (*Pack)(uint8_t *uid);
const char *hint;
} PACKED mfu_identify_t;
static mfu_identify_t mfu_ident_table[] = {
{
"Jooki", "0004040201000F03",
12, 32, "E11012000103A00C340329D101255504732E6A6F6F6B692E726F636B732F732F",
NULL, NULL,
"hf jooki decode -r"
},
{
"Lego Dimensions", "0004040201000F03",
12, 18, "E11012000103A00C340313D1010F5402656E",
ul_ev1_pwdgenC, ul_ev1_packgenC,
"hf mfu dump -k %08x"
},
{
"Amiibo", "0004040201001103",
9, 9, "480FE0F110FFEEA500",
ul_ev1_pwdgenB, ul_ev1_packgenB,
"hf mfu dump -k %08x"
},
{NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
};
static mfu_identify_t* mfu_match_fingerprint(uint8_t *version, uint8_t *data) {
uint8_t i = 0;
do {
int vl = 0;
uint8_t vtmp[10] = {0};
param_gethex_to_eol(mfu_ident_table[i].version, 0, vtmp, sizeof(vtmp), &vl);
bool m1 = (memcmp(vtmp, version, vl) == 0);
if (m1 == false) {
PrintAndLogEx(DEBUG, "(fingerprint) wrong version");
continue;
}
int ml = 0;
uint8_t mtmp[40] = {0};
param_gethex_to_eol(mfu_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml);
bool m2 = (memcmp(mtmp, data + mfu_ident_table[i].mpos, mfu_ident_table[i].mlen) == 0);
if (m2) {
PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_ident_table[i].desc);
return &mfu_ident_table[i];
}
} while (mfu_ident_table[++i].desc);
return NULL;
}
static uint8_t mfu_max_len(void) {
uint8_t n = 0, i = 0;
do {
uint8_t tmp = mfu_ident_table[i].mpos + mfu_ident_table[i].mlen;
if (tmp > n) {
n = tmp;
}
} while (mfu_ident_table[++i].desc);
return n;
}
static int mfu_get_version_uid(uint8_t *version, uint8_t *uid) {
iso14a_card_select_t card;
if (ul_select(&card) == false)
return PM3_ESOFT;
uint8_t v[10] = {0x00};
int len = ulev1_getVersion(v, sizeof(v));
DropField();
if (len != sizeof(v))
return PM3_ESOFT;
memcpy(version, v, 8);
memcpy(uid, card.uid, 7);
return PM3_SUCCESS;
}
static int mfu_fingerprint(void) {
uint8_t *data = NULL;
int res = PM3_SUCCESS;
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------");
uint8_t maxbytes = mfu_max_len();
if (maxbytes == 0) {
PrintAndLogEx(ERR, "fingerprint table wrong");
res = PM3_ESOFT;
goto out;
}
maxbytes = ((maxbytes / 4) + 1) * 4;
data = calloc(maxbytes, sizeof(uint8_t));
if (data == NULL) {
PrintAndLogEx(ERR, "failed to allocate memory");
res = PM3_EMALLOC;
goto out;
}
uint8_t pages = (maxbytes / 4);
PrintAndLogEx(INFO, "Reading tag memory...");
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, 0, NULL, 0);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "Command execute time-out");
res = PM3_ETIMEOUT;
goto out;
}
if (resp.oldarg[0] != 1) {
PrintAndLogEx(WARNING, "Failed reading card");
res = PM3_ESOFT;
goto out;
}
// read all memory
uint32_t startindex = resp.oldarg[2];
uint32_t buffer_size = resp.oldarg[1];
if (buffer_size > maxbytes) {
PrintAndLogEx(FAILED, "Data exceeded buffer size!");
buffer_size = maxbytes;
}
if (!GetFromDevice(BIG_BUF, data, buffer_size, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
res = PM3_ETIMEOUT;
goto out;
}
uint8_t version[8] = {0};
uint8_t uid[7] = {0};
if (mfu_get_version_uid(version, uid) == PM3_SUCCESS) {
mfu_identify_t* item = mfu_match_fingerprint(version, data);
if (item) {
PrintAndLogEx(SUCCESS, "Found " _GREEN_("%s"), item->desc);
if (item->Pwd) {
char s[40] = {0};
sprintf(s, item->hint, item->Pwd(uid));
PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", s);
} else {
PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", item->hint);
}
}
}
out:
free(data);
PrintAndLogEx(INFO, "------------------------------------------------------------");
return res;
}
uint32_t GetHF14AMfU_Type(void) {
TagTypeUL_t tagtype = UNKNOWN;
@ -1391,6 +1634,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
}
}
mfu_fingerprint();
out:
DropField();
if (locked) {
@ -2223,6 +2469,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
}
PrintAndLogEx(INFO, "Restoring data blocks.");
PrintAndLogEx(INFO, "." NOLF);
// write all other data
// Skip block 0,1,2,3 (only magic tags can write to them)
// Skip last 5 blocks usually is configuration
@ -2234,6 +2481,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
wait4response(b);
PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
}
PrintAndLogEx(NORMAL, "");
@ -2810,15 +3058,15 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
PrintAndLogEx(INFO, "---------------------------------");
PrintAndLogEx(INFO, " Using UID : %s", sprint_hex(uid, 7));
PrintAndLogEx(INFO, "---------------------------------");
PrintAndLogEx(INFO, " algo | pwd | pack");
PrintAndLogEx(INFO, "------+----------+-----");
PrintAndLogEx(INFO, " EV1 | %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
PrintAndLogEx(INFO, " Ami | %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
PrintAndLogEx(INFO, " LD | %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
PrintAndLogEx(INFO, " XYZ | %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
PrintAndLogEx(INFO, "------+----------+-----");
PrintAndLogEx(INFO, " algo | pwd | pack");
PrintAndLogEx(INFO, "----------------+----------+-----");
PrintAndLogEx(INFO, " EV1 | %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
PrintAndLogEx(INFO, " Amiibo | %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
PrintAndLogEx(INFO, " Lego Dimension | %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
PrintAndLogEx(INFO, " XYZ 3D printer | %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
PrintAndLogEx(INFO, "----------------+----------+-----");
PrintAndLogEx(INFO, " Vingcard algo");
PrintAndLogEx(INFO, "--------------------");
PrintAndLogEx(INFO, "---------------------------------");
return PM3_SUCCESS;
}