hf mfu eload/restore/sim/cauth - now uses cliparser

This commit is contained in:
iceman1001 2020-12-31 13:51:38 +01:00
commit afc4d78d68

View file

@ -42,73 +42,6 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int usage_hf_mfu_restore(void) {
PrintAndLogEx(NORMAL, "Restore dumpfile onto card.");
PrintAndLogEx(NORMAL, "Usage: hf mfu restore [h] [l] [s] k <key> n <filename w .bin> ");
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, " s : (optional) enable special write UID " _BLUE_("-MAGIC TAG ONLY-"));
PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature " _BLUE_("-MAGIC NTAG 21* ONLY-"));
PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires " _YELLOW_("'e'") " parameter to work");
PrintAndLogEx(NORMAL, " f <fn> : " _YELLOW_("filename w .bin") " to restore");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore s f myfile"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore k AABBCCDD s f myfile"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore k AABBCCDD s e r f myfile"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_mfu_eload(void) {
PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`"));
PrintAndLogEx(NORMAL, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to the eml");
PrintAndLogEx(NORMAL, "Usage: hf mfu eload u <file name w/o `.eml`> [numblocks]");
PrintAndLogEx(NORMAL, " Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " u : UL (required)");
PrintAndLogEx(NORMAL, " [filename] : without `.eml` (required)");
PrintAndLogEx(NORMAL, " numblocks : number of blocks to load from eml file (optional)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu eload u filename"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu eload u filename 57"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_mfu_sim(void) {
PrintAndLogEx(NORMAL, "\nEmulating Ultralight tag from emulator memory\n");
PrintAndLogEx(NORMAL, "\nBe sure to load the emulator memory first!\n");
PrintAndLogEx(NORMAL, "Usage: hf mfu sim t 7 u <uid> [n <num>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " t 7 : 7 = NTAG or Ultralight sim (required)");
PrintAndLogEx(NORMAL, " n <num> : exit simulation after <num> blocks have been read by reader. 0 = infinite (optional)");
PrintAndLogEx(NORMAL, " u <uid> : 4 or 7 byte UID (optional)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7 u 1122344556677"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7 u 1122344556677 n 5"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_mfu_ucauth(void) {
PrintAndLogEx(NORMAL, "Tests 3DES password on Mifare Ultralight-C tag.");
PrintAndLogEx(NORMAL, "If password is not specified, a set of known defaults will be tested.");
PrintAndLogEx(NORMAL, "Usage: hf mfu cauth [k] <password (32 hex symbols)>");
PrintAndLogEx(NORMAL, " k - keep field on (only if a password is provided too)");
PrintAndLogEx(NORMAL, " [password] - (32 hex symbols)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth 000102030405060708090a0b0c0d0e0f"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_mfu_ucsetpwd(void) { static int usage_hf_mfu_ucsetpwd(void) {
PrintAndLogEx(NORMAL, "Set 3DES password on Mifare Ultralight-C tag."); PrintAndLogEx(NORMAL, "Set 3DES password on Mifare Ultralight-C tag.");
PrintAndLogEx(NORMAL, "Usage: hf mfu setpwd <password (32 hex symbols)>"); PrintAndLogEx(NORMAL, "Usage: hf mfu setpwd <password (32 hex symbols)>");
@ -349,10 +282,10 @@ static int try_default_3des_keys(uint8_t **correct_key) {
uint8_t *key = default_3des_keys[i]; uint8_t *key = default_3des_keys[i];
if (ulc_authentication(key, true)) { if (ulc_authentication(key, true)) {
*correct_key = key; *correct_key = key;
return 1; return PM3_SUCCESS;
} }
} }
return 0; return PM3_ESOFT;
} }
static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) { static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) {
@ -615,7 +548,7 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) {
memset(typestr, 0x00, sizeof(typestr)); memset(typestr, 0x00, sizeof(typestr));
if (tagtype & UL) if (tagtype & UL)
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)s"), spaces, ""); snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)"), spaces, "");
else if (tagtype & UL_C) else if (tagtype & UL_C)
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, ""); snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, "");
else if (tagtype & UL_NANO_40) else if (tagtype & UL_NANO_40)
@ -676,7 +609,7 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) {
snprintf(typestr + strlen(typestr), 4, " ("); snprintf(typestr + strlen(typestr), 4, " (");
snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : ""); snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : "");
tagtype ^= 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_1A) ? _GREEN_("Gen 1a") : "");
snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : ""); snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : "");
@ -688,11 +621,11 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) {
} }
static int ulc_print_3deskey(uint8_t *data) { static int ulc_print_3deskey(uint8_t *data) {
PrintAndLogEx(NORMAL, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data, 4), sprint_ascii(data, 4)); PrintAndLogEx(INFO, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data, 4), sprint_ascii(data, 4));
PrintAndLogEx(NORMAL, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data + 4, 4), sprint_ascii(data + 4, 4)); PrintAndLogEx(INFO, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data + 4, 4), sprint_ascii(data + 4, 4));
PrintAndLogEx(NORMAL, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4)); PrintAndLogEx(INFO, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4));
PrintAndLogEx(NORMAL, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4)); PrintAndLogEx(INFO, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4));
PrintAndLogEx(NORMAL, "\n 3des key: %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); PrintAndLogEx(INFO, "3des key: " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(data, 16, 8), 16));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -839,7 +772,7 @@ static int ulev1_print_counters(void) {
len = ulev1_readCounter(i, counter, sizeof(counter)); len = ulev1_readCounter(i, counter, sizeof(counter));
if (len == 3) { if (len == 3) {
PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3)); PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
, tear[0] , tear[0]
, (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
); );
@ -930,7 +863,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)) { if (is_valid == false || i == ARRAYLEN(nxp_mfu_public_keys)) {
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
PrintAndLogEx(SUCCESS, " Signature verification (" _RED_("fail") ")"); PrintAndLogEx(SUCCESS, " Signature verification ( " _RED_("fail") " )");
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -938,7 +871,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, "IC signature public key value: %s", nxp_mfu_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); 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; return PM3_SUCCESS;
} }
@ -968,7 +901,7 @@ static int ntag_print_counter(void) {
len = ulev1_readCounter(0x02, counter, sizeof(counter)); len = ulev1_readCounter(0x02, counter, sizeof(counter));
(void)len; (void)len;
PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3)); PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3));
PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
, tear[0] , tear[0]
, (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
); );
@ -1038,6 +971,19 @@ static int ul_magic_test(void) {
return 0; return 0;
} }
static char *GenerateFilename(const char *prefix, const char *suffix) {
iso14a_card_select_t card;
if (ul_select(&card) == false) {
PrintAndLogEx(WARNING, "No tag found.");
return NULL;
}
char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(card.uid) * 2 + 1, sizeof(uint8_t));
strcpy(fptr, prefix);
FillFileNameByUID(fptr, card.uid, suffix, card.uidlen);
return fptr;
}
uint32_t GetHF14AMfU_Type(void) { uint32_t GetHF14AMfU_Type(void) {
TagTypeUL_t tagtype = UNKNOWN; TagTypeUL_t tagtype = UNKNOWN;
@ -1319,7 +1265,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
} }
// also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
if (try_default_3des_keys(&key)) { if (try_default_3des_keys(&key) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Found default 3des key: "); PrintAndLogEx(SUCCESS, "Found default 3des key: ");
uint8_t keySwap[16]; uint8_t keySwap[16];
memcpy(keySwap, SwapEndian64(key, 16, 8), 16); memcpy(keySwap, SwapEndian64(key, 16, 8), 16);
@ -1425,7 +1371,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key); num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key);
len = ulev1_requestAuthentication(key, pack, sizeof(pack)); len = ulev1_requestAuthentication(key, pack, sizeof(pack));
if (len > -1) { 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 default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
goto out; goto out;
} }
@ -1437,7 +1383,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key); num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
len = ulev1_requestAuthentication(key, pack, sizeof(pack)); len = ulev1_requestAuthentication(key, pack, sizeof(pack));
if (len > -1) { 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 default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
goto out; goto out;
} }
@ -1449,7 +1395,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key); num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key);
len = ulev1_requestAuthentication(key, pack, sizeof(pack)); len = ulev1_requestAuthentication(key, pack, sizeof(pack));
if (len > -1) { 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 default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
goto out; goto out;
} }
@ -1461,7 +1407,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key); num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key);
len = ulev1_requestAuthentication(key, pack, sizeof(pack)); len = ulev1_requestAuthentication(key, pack, sizeof(pack));
if (len > -1) { 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 default password" _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
goto out; goto out;
} }
@ -1473,7 +1419,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
key = default_pwd_pack[i]; key = default_pwd_pack[i];
len = ulev1_requestAuthentication(key, pack, sizeof(pack)); len = ulev1_requestAuthentication(key, pack, sizeof(pack));
if (len > -1) { 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 default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
break; break;
} else { } else {
if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
@ -1729,7 +1675,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) {
PrintAndLogEx(INFO, "-----------------------------"); PrintAndLogEx(INFO, "-----------------------------");
PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s\n", blockno, blockno, sprint_hex(d, 4), sprint_ascii(d, 4)); PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s\n", blockno, blockno, sprint_hex(d, 4), sprint_ascii(d, 4));
} else { } else {
PrintAndLogEx(WARNING, "Failed reading block: (%02x)", isOK); PrintAndLogEx(WARNING, "Failed reading block: ( %02x )", isOK);
} }
} else { } else {
PrintAndLogEx(WARNING, "Command execute time-out"); PrintAndLogEx(WARNING, "Command execute time-out");
@ -2154,82 +2100,58 @@ static void wait4response(uint8_t b) {
// Restore dump file onto tag // Restore dump file onto tag
// //
static int CmdHF14AMfURestore(const char *Cmd) { static int CmdHF14AMfURestore(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu restore",
"Restore dumpfile onto card.",
"hf mfu restore -f myfile -s -> user specified filename and special write\n"
"hf mfu restore -f myfile -k AABBCCDD -s -> user specified filename, special write and use key\n"
"hf mfu restore -f myfile -k AABBCCDD -ser -> user specified filename, special write, use key, ..."
);
char tempStr[50] = {0}; void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<fn>", "specify a filename to restore"),
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_lit0("s", NULL, "enable special write UID -MAGIC TAG ONLY-"),
arg_lit0("e", NULL, "enable special write version/signature -MAGIC NTAG 21* ONLY-"),
arg_lit0("r", NULL, "use the password found in dumpfile to configure tag. requires " _YELLOW_("'-e'") " parameter to work"),
arg_lit0("v", "verbose", "verbose"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
uint8_t authkey[16] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
int ak_len = 0;
uint8_t authkey[16] = {0x00};
uint8_t *p_authkey = authkey; uint8_t *p_authkey = authkey;
uint8_t cmdp = 0, keylen = 0; CLIGetHexWithReturn(ctx, 2, authkey, &ak_len);
bool swap_endian = arg_get_lit(ctx, 3);
bool write_special = arg_get_lit(ctx, 4);
bool write_extra = arg_get_lit(ctx, 5);
bool read_key = arg_get_lit(ctx, 6);
bool verbose = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
bool hasKey = false; bool hasKey = false;
bool swapEndian = false;
bool errors = false;
bool write_special = false;
bool write_extra = false;
bool read_key = false;
bool verbose = false;
size_t filelen = 0;
memset(authkey, 0x00, sizeof(authkey));
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_mfu_restore();
case 'k':
keylen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr));
if (keylen == 32 || keylen == 8) { //ul-c or ev1/ntag key length
errors = param_gethex(tempStr, 0, authkey, keylen);
keylen /= 2;
} else {
PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
errors = true;
}
cmdp += 2;
hasKey = true;
break;
case 'l':
swapEndian = true;
cmdp++;
break;
case 'f':
filelen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
if (filelen > FILE_PATH_SIZE - 5)
filelen = FILE_PATH_SIZE - 5;
if (filelen < 1)
sprintf(filename, "dumpdata.bin");
cmdp += 2;
break;
case 's':
cmdp++;
write_special = true;
break;
case 'e':
cmdp++;
write_extra = true;
break;
case 'r':
cmdp++;
read_key = true;
break;
case 'v':
cmdp++;
verbose = true;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations
if (errors || cmdp == 0) return usage_hf_mfu_restore();
uint8_t *dump = NULL; uint8_t *dump = NULL;
size_t bytes_read = 0; size_t bytes_read = 0;
if (fnlen == 0) {
char *fptr = GenerateFilename("hf-mfu-", "-dump.bin");
if (fptr != NULL) {
strcpy(filename, fptr);
} else {
snprintf(filename, sizeof(filename), "dumpdata.bin");
}
free(fptr);
}
if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) { if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), filename); PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), filename);
return PM3_EIO; return PM3_EIO;
@ -2263,19 +2185,19 @@ static int CmdHF14AMfURestore(const char *Cmd) {
printMFUdumpEx(mem, pages, 0); printMFUdumpEx(mem, pages, 0);
// Swap endianness // Swap endianness
if (swapEndian && hasKey) { if (swap_endian && hasKey) {
if (keylen == 16) if (ak_len == 16)
p_authkey = SwapEndian64(authkey, keylen, 8); p_authkey = SwapEndian64(authkey, ak_len, 8);
else else
p_authkey = SwapEndian64(authkey, keylen, 4); p_authkey = SwapEndian64(authkey, ak_len, 4);
} }
uint8_t data[20] = {0}; uint8_t data[20] = {0};
uint8_t keytype = 0; uint8_t keytype = 0;
// set key - only once // set key - only once
if (hasKey) { if (hasKey) {
keytype = (keylen == 16) ? 1 : 2; keytype = (ak_len == 16) ? 1 : 2;
memcpy(data + 4, p_authkey, keylen); memcpy(data + 4, p_authkey, ak_len);
} }
// write version, signature, pack // write version, signature, pack
@ -2379,16 +2301,54 @@ static int CmdHF14AMfURestore(const char *Cmd) {
// Load emulator with dump file // Load emulator with dump file
// //
static int CmdHF14AMfUeLoad(const char *Cmd) { static int CmdHF14AMfUeLoad(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0));
if (c == 'h' || c == 0x00) return usage_hf_mfu_eload(); CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu eload",
"It loads emul dump from the file `filename.eml`",
"hf mfu eload -u -f myfile\n"
"hf mfu eload -u -f myfile -q 57 -> load 57 blocks from myfile"
);
void *argtable[] = {
arg_param_begin,
arg_str1("f", "file", "<fn>", "specify a filename w/o `.eml` to load"),
arg_lit1("u", NULL, "Ultralight Family type"),
arg_int0("q", "qty", "<dec>", "number of blocks to load from eml file"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
PrintAndLogEx(HINT, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to .eml");
return CmdHF14AMfELoad(Cmd); return CmdHF14AMfELoad(Cmd);
} }
// //
// Simulate tag // Simulate tag
// //
static int CmdHF14AMfUSim(const char *Cmd) { static int CmdHF14AMfUSim(const char *Cmd) {
char c = tolower(param_getchar(Cmd, 0)); CLIParserContext *ctx;
if (c == 'h' || c == 0x00) return usage_hf_mfu_sim(); CLIParserInit(&ctx, "hf mfu sim",
"Simulate MIFARE Ultralight family type based upon\n"
"ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
"from emulator memory. See `hf mfu eload` first",
"hf mfu sim -t 2 --uid 1122344556677 -> MIFARE Ultralight\n"
"hf mfu sim -t 7 --uid 1122344556677 -n 5 -> AMIIBO (NTAG 215), pack 0x8080"
);
void *argtable[] = {
arg_param_begin,
arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
arg_str0("u", "uid", "<hex>", "4, 7 or 10 byte UID"),
arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
arg_lit0("v", "verbose", "verbose output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIParserFree(ctx);
return CmdHF14ASim(Cmd); return CmdHF14ASim(Cmd);
} }
@ -2396,43 +2356,58 @@ static int CmdHF14AMfUSim(const char *Cmd) {
// Ultralight C Methods // Ultralight C Methods
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
//
// Ultralight C Authentication // Ultralight C Authentication
// //
static int CmdHF14AMfUCAuth(const char *Cmd) { static int CmdHF14AMfUCAuth(const char *Cmd) {
uint8_t cmdp = 0; CLIParserContext *ctx;
char c = tolower(param_getchar(Cmd, 0)); CLIParserInit(&ctx, "hf mfu cauth",
if (c == 'h') { "Tests 3DES password on Mifare Ultralight-C tag.\n"
return usage_hf_mfu_ucauth(); "If password is not specified, a set of known defaults will be tested.",
} "hf mfu cauth\n"
bool keep_field_on = false; "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f"
if (c == 'k') { );
keep_field_on = true;
cmdp++;
}
uint8_t key_buf[16]; void *argtable[] = {
uint8_t *key; arg_param_begin,
int succeeded; 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_lit0("k", NULL, "keep field on (only if a password is provided too)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
// If no hex key is specified, try all known ones int ak_len = 0;
if (strlen(Cmd + cmdp) == 0) { uint8_t authenticationkey[16] = {0x00};
succeeded = try_default_3des_keys(&key); uint8_t *authKeyPtr = authenticationkey;
// Else try user-supplied CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
} else { bool swap_endian = arg_get_lit(ctx, 2);
if (param_gethex(Cmd, cmdp, key_buf, 32)) { bool keep_field_on = arg_get_lit(ctx, 3);
PrintAndLogEx(WARNING, "Password must include 32 HEX symbols"); CLIParserFree(ctx);
if (ak_len != 16 && ak_len != 0) {
PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
return PM3_EINVARG; return PM3_EINVARG;
} }
succeeded = ulc_authentication(key_buf, ! keep_field_on);
key = key_buf; // Swap endianness
if (swap_endian && ak_len) {
authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
} }
if (succeeded) bool isok = false;
PrintAndLogEx(SUCCESS, "Authentication successful. 3des key: %s", sprint_hex(key, 16));
// If no hex key is specified, try default keys
if (ak_len == 0) {
isok = (try_default_3des_keys(&authKeyPtr) == PM3_SUCCESS);
} else {
// try user-supplied
isok = ulc_authentication(authKeyPtr, !keep_field_on);
}
if (isok)
PrintAndLogEx(SUCCESS, "Authentication success. 3des key: " _GREEN_("%s"), sprint_hex_inrow(authKeyPtr, 16));
else else
PrintAndLogEx(WARNING, "Authentication failed"); PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " )");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -3484,7 +3459,7 @@ static int CmdHF14MfuNDEF(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("k", "key", "replace default key for NDEF", NULL), arg_str0("k", "key", "replace default key for NDEF", NULL),
arg_lit0("l", "key", "(optional) swap entered key's endianness"), arg_lit0("l", NULL, "swap entered key's endianness"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);