mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-11 01:55:38 +08:00
Merge remote-tracking branch 'origin/master' into emrtd
This commit is contained in:
commit
ee87abd047
2 changed files with 188 additions and 118 deletions
|
@ -13,6 +13,7 @@
|
|||
#include "commonutil.h"
|
||||
#include "crypto/libpcrypto.h"
|
||||
#include "des.h"
|
||||
#include "aes.h"
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "comms.h"
|
||||
|
@ -23,7 +24,6 @@
|
|||
#include "cliparser.h"
|
||||
#include "cmdmain.h"
|
||||
|
||||
|
||||
#define MAX_UL_BLOCKS 0x0F
|
||||
#define MAX_ULC_BLOCKS 0x2F
|
||||
#define MAX_ULEV1a_BLOCKS 0x13
|
||||
|
@ -42,26 +42,6 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int usage_hf_mfu_info(void) {
|
||||
PrintAndLogEx(NORMAL, "It gathers information about the tag and tries to detect what kind it is.");
|
||||
PrintAndLogEx(NORMAL, "Sometimes the tags are locked down, and you may need a key to be able to read the information");
|
||||
PrintAndLogEx(NORMAL, "The following tags can be identified:\n");
|
||||
PrintAndLogEx(NORMAL, "Ultralight, Ultralight-C, Ultralight EV1, NTAG 203, NTAG 210,");
|
||||
PrintAndLogEx(NORMAL, "NTAG 212, NTAG 213, NTAG 215, NTAG 216, NTAG I2C 1K & 2K");
|
||||
PrintAndLogEx(NORMAL, "my-d, my-d NFC, my-d move, my-d move NFC\n");
|
||||
PrintAndLogEx(NORMAL, "Usage: hf mfu info k <key> l");
|
||||
PrintAndLogEx(NORMAL, " Options : ");
|
||||
PrintAndLogEx(NORMAL, " k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
|
||||
PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info k 00112233445566778899AABBCCDDEEFF"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info k AABBCCDD"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_hf_mfu_dump(void) {
|
||||
PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1");
|
||||
PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216");
|
||||
|
@ -684,62 +664,80 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) {
|
|||
|
||||
if (spaces > 10)
|
||||
spaces = 10;
|
||||
|
||||
char typestr[100];
|
||||
memset(typestr, 0x00, sizeof(typestr));
|
||||
|
||||
if (tagtype & UL)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1) %s"), spaces, "", (tagtype & MAGIC) ? "<magic>" : "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)s"), spaces, "");
|
||||
else if (tagtype & UL_C)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC) %s"), spaces, "", (tagtype & MAGIC) ? "<magic>" : "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, "");
|
||||
else if (tagtype & UL_NANO_40)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces, "");
|
||||
else if (tagtype & UL_EV1_48)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces, "");
|
||||
else if (tagtype & UL_EV1_128)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces, "");
|
||||
else if (tagtype & UL_EV1)
|
||||
PrintAndLogEx(NORMAL, "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces, "");
|
||||
else if (tagtype & NTAG)
|
||||
PrintAndLogEx(NORMAL, "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces, "");
|
||||
else if (tagtype & NTAG_203)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces, "");
|
||||
else if (tagtype & NTAG_210)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces, "");
|
||||
else if (tagtype & NTAG_212)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces, "");
|
||||
else if (tagtype & NTAG_213)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, "");
|
||||
else if (tagtype & NTAG_213_F)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, "");
|
||||
else if (tagtype & NTAG_213_C)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces, "");
|
||||
else if (tagtype & NTAG_213_TT)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, "");
|
||||
else if (tagtype & NTAG_215)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, "");
|
||||
else if (tagtype & NTAG_216)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces, "");
|
||||
else if (tagtype & NTAG_216_F)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces, "");
|
||||
else if (tagtype & NTAG_I2C_1K)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces, "");
|
||||
else if (tagtype & NTAG_I2C_2K)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces, "");
|
||||
else if (tagtype & NTAG_I2C_1K_PLUS)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces, "");
|
||||
else if (tagtype & NTAG_I2C_2K_PLUS)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces, "");
|
||||
else if (tagtype & MY_D)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces, "");
|
||||
else if (tagtype & MY_D_NFC)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces, "");
|
||||
else if (tagtype & MY_D_MOVE)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces, "");
|
||||
else if (tagtype & MY_D_MOVE_NFC)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces, "");
|
||||
else if (tagtype & MY_D_MOVE_LEAN)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, "");
|
||||
else if (tagtype & FUDAN_UL)
|
||||
PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible) %s"), spaces, "", (tagtype & MAGIC) ? "<magic>" : "");
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces, "");
|
||||
else
|
||||
PrintAndLogEx(NORMAL, "%*sTYPE: " _YELLOW_("Unknown %06x"), spaces, "", tagtype);
|
||||
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("Unknown %06x"), spaces, "", tagtype);
|
||||
|
||||
bool ismagic = ((tagtype & MAGIC) == MAGIC);
|
||||
if (ismagic)
|
||||
snprintf(typestr + strlen(typestr), 4, " (");
|
||||
|
||||
snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : "");
|
||||
tagtype ^= MAGIC;
|
||||
snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1A) ? _GREEN_("Gen 1a") : "");
|
||||
snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : "");
|
||||
|
||||
if (ismagic)
|
||||
snprintf(typestr + strlen(typestr), 4, " )");
|
||||
|
||||
PrintAndLogEx(SUCCESS, "%s", typestr);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -895,7 +893,10 @@ static int ulev1_print_counters(void) {
|
|||
len = ulev1_readCounter(i, counter, sizeof(counter));
|
||||
if (len == 3) {
|
||||
PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing (%s)", tear[0], (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("failure"));
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing (%s)"
|
||||
, tear[0]
|
||||
, (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
@ -983,7 +984,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig
|
|||
if (is_valid == false || i == ARRAYLEN(nxp_mfu_public_keys)) {
|
||||
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
|
||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification (" _RED_("fail") ")");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -991,7 +992,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig
|
|||
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value);
|
||||
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
|
||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification (" _GREEN_("successful") ")" );
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1021,7 +1022,10 @@ static int ntag_print_counter(void) {
|
|||
len = ulev1_readCounter(0x02, counter, sizeof(counter));
|
||||
(void)len;
|
||||
PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3));
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing (" _GREEN_("%s")")", tear[0], (tear[0] == 0xBD) ? "ok" : "failure");
|
||||
PrintAndLogEx(SUCCESS, " - %02X tearing (%s)"
|
||||
, tear[0]
|
||||
, (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
|
||||
);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -1057,12 +1061,34 @@ static int ul_magic_test(void) {
|
|||
// 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
|
||||
|
||||
iso14a_card_select_t card;
|
||||
if (!ul_select(&card))
|
||||
if (ul_select(&card) == false)
|
||||
return UL_ERROR;
|
||||
|
||||
int status = ul_comp_write(0, NULL, 0);
|
||||
DropField();
|
||||
if (status == 0)
|
||||
return MAGIC;
|
||||
|
||||
// check for GEN1A, GEN1B and NTAG21x
|
||||
uint8_t is_generation = 0;
|
||||
PacketResponseNG resp;
|
||||
clearCommandBuffer();
|
||||
uint8_t payload[] = { 0 };
|
||||
SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload));
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) {
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
is_generation = resp.data.asBytes[0];
|
||||
}
|
||||
switch (is_generation) {
|
||||
case MAGIC_GEN_1A:
|
||||
return MAGIC_1A;
|
||||
case MAGIC_GEN_1B:
|
||||
return MAGIC_1B;
|
||||
case MAGIC_NTAG21X:
|
||||
return MAGIC_NTAG;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1071,7 +1097,8 @@ uint32_t GetHF14AMfU_Type(void) {
|
|||
TagTypeUL_t tagtype = UNKNOWN;
|
||||
iso14a_card_select_t card;
|
||||
|
||||
if (!ul_select(&card)) return UL_ERROR;
|
||||
if (ul_select(&card) == false)
|
||||
return UL_ERROR;
|
||||
|
||||
// Ultralight - ATQA / SAK
|
||||
if (card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00) {
|
||||
|
@ -1177,7 +1204,8 @@ uint32_t GetHF14AMfU_Type(void) {
|
|||
tagtype = UL_C;
|
||||
} else {
|
||||
// need to re-select after authentication error
|
||||
if (!ul_select(&card)) return UL_ERROR;
|
||||
if (ul_select(&card) == false)
|
||||
return UL_ERROR;
|
||||
|
||||
uint8_t data[16] = {0x00};
|
||||
// read page 0x26-0x29 (last valid ntag203 page)
|
||||
|
@ -1222,7 +1250,9 @@ uint32_t GetHF14AMfU_Type(void) {
|
|||
}
|
||||
|
||||
tagtype |= ul_magic_test();
|
||||
if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC);
|
||||
if (tagtype == (UNKNOWN | MAGIC)) {
|
||||
tagtype = (UL_MAGIC);
|
||||
}
|
||||
return tagtype;
|
||||
}
|
||||
//
|
||||
|
@ -1230,56 +1260,53 @@ uint32_t GetHF14AMfU_Type(void) {
|
|||
//
|
||||
static int CmdHF14AMfUInfo(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfu info",
|
||||
"Get info about MIFARE Ultralight Family styled tag.\n"
|
||||
"Sometimes the tags are locked down, and you may need a key to be able to read the information",
|
||||
"hf mfu info\n"
|
||||
"hf mfu info k AABBCCDD\n"
|
||||
"hf mfu info k 00112233445566778899AABBCCDDEEFF"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
|
||||
arg_lit0("l", NULL, "swap entered key's endianness"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
int ak_len = 0;
|
||||
uint8_t authenticationkey[16] = {0x00};
|
||||
CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
|
||||
bool swap_endian = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (ak_len) {
|
||||
if (ak_len != 16 || ak_len != 8) {
|
||||
PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
bool has_auth_key = false;
|
||||
if (ak_len > 0)
|
||||
has_auth_key = true;
|
||||
|
||||
uint8_t authlim = 0xff;
|
||||
uint8_t data[16] = {0x00};
|
||||
iso14a_card_select_t card;
|
||||
int status;
|
||||
bool errors = false;
|
||||
bool hasAuthKey = false;
|
||||
bool locked = false;
|
||||
bool swapEndian = false;
|
||||
uint8_t cmdp = 0;
|
||||
uint8_t dataLen = 0;
|
||||
uint8_t authenticationkey[16] = {0x00};
|
||||
uint8_t *authkeyptr = authenticationkey;
|
||||
uint8_t pwd[4] = {0, 0, 0, 0};
|
||||
uint8_t *key = pwd;
|
||||
uint8_t pack[4] = {0, 0, 0, 0};
|
||||
int len;
|
||||
|
||||
char tempStr[50];
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_hf_mfu_info();
|
||||
case 'k':
|
||||
dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr));
|
||||
if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length
|
||||
errors = param_gethex(tempStr, 0, authenticationkey, dataLen);
|
||||
dataLen /= 2; // handled as bytes from now on
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
|
||||
errors = true;
|
||||
}
|
||||
cmdp += 2;
|
||||
hasAuthKey = true;
|
||||
break;
|
||||
case 'l':
|
||||
swapEndian = true;
|
||||
cmdp++;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Validations
|
||||
if (errors) return usage_hf_mfu_info();
|
||||
|
||||
TagTypeUL_t tagtype = GetHF14AMfU_Type();
|
||||
if (tagtype == UL_ERROR) return PM3_ESOFT;
|
||||
if (tagtype == UL_ERROR)
|
||||
return PM3_ESOFT;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
|
||||
|
@ -1287,10 +1314,15 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
ul_print_type(tagtype, 6);
|
||||
|
||||
// Swap endianness
|
||||
if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4);
|
||||
if (swap_endian && has_auth_key) {
|
||||
authkeyptr = SwapEndian64(authenticationkey, ak_len, (ak_len == 16) ? 8 : 4);
|
||||
}
|
||||
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
bool locked = false;
|
||||
// read pages 0,1,2,3 (should read 4pages)
|
||||
status = ul_read(0, data, sizeof(data));
|
||||
if (status == -1) {
|
||||
|
@ -1329,12 +1361,16 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
PrintAndLogEx(ERR, "Error: tag didn't answer to READ magic");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (status == 16) ulc_print_3deskey(ulc_deskey);
|
||||
if (status == 16) {
|
||||
ulc_print_3deskey(ulc_deskey);
|
||||
}
|
||||
|
||||
} else {
|
||||
DropField();
|
||||
// if we called info with key, just return
|
||||
if (hasAuthKey) return PM3_SUCCESS;
|
||||
if (has_auth_key) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
|
||||
if (try_default_3des_keys(&key)) {
|
||||
|
@ -1353,7 +1389,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1))) {
|
||||
if (ulev1_print_counters() != 3) {
|
||||
// failed - re-select
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1361,7 +1399,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
if ((tagtype & (NTAG_213 | NTAG_213_F | NTAG_213_C | NTAG_213_TT | NTAG_215 | NTAG_216))) {
|
||||
if (ntag_print_counter()) {
|
||||
// failed - re-select
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1378,7 +1418,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
ulev1_print_signature(tagtype, card.uid, ulev1_signature, sizeof(ulev1_signature));
|
||||
} else {
|
||||
// re-select
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
// Get Version
|
||||
|
@ -1392,7 +1434,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
ulev1_print_version(version);
|
||||
} else {
|
||||
locked = true;
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t startconfigblock = 0;
|
||||
|
@ -1416,7 +1460,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
// save AUTHENTICATION LIMITS for later:
|
||||
authlim = (ulev1_conf[4] & 0x07);
|
||||
// add pwd / pack if used from cli
|
||||
if (hasAuthKey) {
|
||||
if (has_auth_key) {
|
||||
memcpy(ulev1_conf + 8, authkeyptr, 4);
|
||||
memcpy(ulev1_conf + 12, pack, 2);
|
||||
}
|
||||
|
@ -1428,57 +1472,67 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
// 0 = limitless.
|
||||
// 1-7 = limit. No automatic tries then.
|
||||
// hasAuthKey, if we was called with key, skip test.
|
||||
if (!authlim && !hasAuthKey) {
|
||||
if (!authlim && !has_auth_key) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known EV1/NTAG passwords"));
|
||||
// test pwd gen A
|
||||
num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key);
|
||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||
if (len > -1) {
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") "|| Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// test pwd gen B
|
||||
num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
|
||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||
if (len > -1) {
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// test pwd gen C
|
||||
num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key);
|
||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||
if (len > -1) {
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
// test pwd gen D
|
||||
num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key);
|
||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||
if (len > -1) {
|
||||
PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < ARRAYLEN(default_pwd_pack); ++i) {
|
||||
key = default_pwd_pack[i];
|
||||
len = ulev1_requestAuthentication(key, pack, sizeof(pack));
|
||||
if (len > -1) {
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
|
||||
break;
|
||||
} else {
|
||||
if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len < 1) {
|
||||
|
@ -1492,7 +1546,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
out:
|
||||
DropField();
|
||||
if (locked) {
|
||||
PrintAndLogEx(INFO, "\nTag appears to be locked, try using the key to get more info");
|
||||
PrintAndLogEx(INFO, "\nTag appears to be locked, try using a key to get more info");
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen r`") " to get see known pwd gen algo suggestions");
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -2709,7 +2763,6 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) {
|
|||
uint8_t dkeyB[8] = { 0x00 };
|
||||
|
||||
uint8_t masterkey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
|
||||
uint8_t mix[8] = { 0x00 };
|
||||
uint8_t divkey[8] = { 0x00 };
|
||||
|
||||
|
@ -2774,6 +2827,20 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd)));
|
||||
|
||||
mbedtls_des3_free(&ctx);
|
||||
|
||||
mbedtls_aes_context ctx_aes;
|
||||
uint8_t aes_iv[16] = { 0x00 };
|
||||
uint8_t aes_masterkey[] = { 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
|
||||
uint8_t aes_input[16] = {0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80, 0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80};
|
||||
uint8_t aes_output[16] = {0x00};
|
||||
mbedtls_aes_setkey_enc(&ctx_aes, aes_masterkey, 128);
|
||||
mbedtls_aes_crypt_cbc(&ctx_aes, MBEDTLS_AES_ENCRYPT, 16, aes_iv, aes_input, aes_output);
|
||||
mbedtls_aes_free(&ctx_aes);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "\n-- AES version");
|
||||
PrintAndLogEx(SUCCESS, "Mifare AES m :\t %s", sprint_hex(aes_masterkey, sizeof(aes_masterkey)));
|
||||
PrintAndLogEx(SUCCESS, "Mifare Div :\t %s", sprint_hex(aes_output, sizeof(aes_output)));
|
||||
|
||||
// next. from the diversify_key method.
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,9 @@ typedef enum TAGTYPE_UL {
|
|||
UL_NANO_40 = 0x2000000,
|
||||
NTAG_213_TT = 0x4000000,
|
||||
NTAG_213_C = 0x8000000,
|
||||
MAGIC_1A = 0x10000000 | MAGIC,
|
||||
MAGIC_1B = 0x20000000 | MAGIC,
|
||||
MAGIC_NTAG = 0x40000000 | MAGIC,
|
||||
UL_MAGIC = UL | MAGIC,
|
||||
UL_C_MAGIC = UL_C | MAGIC,
|
||||
UL_ERROR = 0xFFFFFF,
|
||||
|
|
Loading…
Reference in a new issue