mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-13 01:57:25 -07:00
fixes and textual
This commit is contained in:
parent
d96c1d0cbf
commit
b5ecdde19e
6 changed files with 117 additions and 26 deletions
|
@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Fixed `hf mfu wrbl` - compabilty write only writes 4 bytes. Now handled correct (@iceman1001)
|
||||
- Changed `hf mfu info` - better magic tag detection (@iceman1001)
|
||||
- Added ELECTRA pattern decoding in `lf search` (@CiRIP)
|
||||
- Firmware size optimization, skipping unused FPGA bitstreams (@douniwan5788)
|
||||
- Added pretty Hitag S config parsing (@CiRIP)
|
||||
|
|
|
@ -2591,6 +2591,8 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
|
|||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "");
|
||||
|
||||
uint16_t isMagic = 0;
|
||||
|
||||
if (isMifareClassic || isMifareMini) {
|
||||
|
|
|
@ -2512,13 +2512,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
|
||||
arg_lit0(NULL, "ns", "No save to file"),
|
||||
|
||||
arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
|
||||
arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"),
|
||||
arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"),
|
||||
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
|
||||
|
||||
arg_lit0(NULL, "ns", "No save"),
|
||||
|
||||
arg_lit0(NULL, "in", "None (use CPU regular instruction set)"),
|
||||
#if defined(COMPILER_HAS_SIMD_X86)
|
||||
arg_lit0(NULL, "im", "MMX"),
|
||||
|
@ -2559,12 +2559,12 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
|||
bool legacy_mfchk = arg_get_lit(ctx, 7);
|
||||
bool verbose = arg_get_lit(ctx, 8);
|
||||
|
||||
bool m0 = arg_get_lit(ctx, 9);
|
||||
bool m1 = arg_get_lit(ctx, 10);
|
||||
bool m2 = arg_get_lit(ctx, 11);
|
||||
bool m4 = arg_get_lit(ctx, 12);
|
||||
bool no_save = arg_get_lit(ctx, 9);
|
||||
|
||||
bool no_save = arg_get_lit(ctx, 13);
|
||||
bool m0 = arg_get_lit(ctx, 10);
|
||||
bool m1 = arg_get_lit(ctx, 11);
|
||||
bool m2 = arg_get_lit(ctx, 12);
|
||||
bool m4 = arg_get_lit(ctx, 13);
|
||||
|
||||
bool in = arg_get_lit(ctx, 14);
|
||||
#if defined(COMPILER_HAS_SIMD_X86)
|
||||
|
@ -3334,7 +3334,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
|
|||
arg_int0(NULL, "blk", "<dec>", "block number (single block recovery mode)"),
|
||||
arg_lit0("a", NULL, "single block recovery key A"),
|
||||
arg_lit0("b", NULL, "single block recovery key B"),
|
||||
arg_lit0(NULL, "no-default", "Don't add the bunch of extra default keys"),
|
||||
arg_lit0(NULL, "no-default", "Skip check default keys"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -3773,7 +3773,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
|
|||
arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
|
||||
arg_lit0(NULL, "dump", "Dump found keys to binary file"),
|
||||
arg_str0("f", "file", "<fn>", "Filename of dictionary"),
|
||||
arg_lit0(NULL, "no-default", "Don't add the bunch of extra default keys"),
|
||||
arg_lit0(NULL, "no-default", "Skip check default keys"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
@ -9565,12 +9565,13 @@ static int CmdHF14AMfInfo(const char *Cmd) {
|
|||
|
||||
uint8_t k08s[6] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
|
||||
if (mfReadBlock(0, 4, k08s, blockdata) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Backdoor key..... " _RED_("%02X%02X%02X%02X%02X%02X"), k08s[0], k08s[1], k08s[2], k08s[3], k08s[4], k08s[5]);
|
||||
PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s)));
|
||||
fKeyType = MF_KEY_BD08S;
|
||||
}
|
||||
|
||||
uint8_t k08[6] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
|
||||
if (mfReadBlock(0, 4, k08, blockdata) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Backdoor key..... " _RED_("%02X%02X%02X%02X%02X%02X"), k08[0], k08[1], k08[2], k08[3], k08[4], k08[5]);
|
||||
PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%02X%02X%02X%02X%02X%02X"), k08[0], k08[1], k08[2], k08[3], k08[4], k08[5]);
|
||||
fKeyType = MF_KEY_BD08;
|
||||
}
|
||||
|
||||
|
|
|
@ -233,6 +233,47 @@ static int ul_print_nxp_silicon_info(uint8_t *card_uid) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int get_ulc_3des_key_magic(uint64_t magic_type, uint8_t *key) {
|
||||
|
||||
mf_readblock_ex_t payload = {
|
||||
.read_cmd = ISO14443A_CMD_READBLOCK,
|
||||
.block_no = 0x2C,
|
||||
};
|
||||
|
||||
if ((magic_type & MFU_TT_MAGIC_1A) == MFU_TT_MAGIC_1A) {
|
||||
payload.wakeup = MF_WAKE_GEN1A;
|
||||
payload.auth_cmd = 0;
|
||||
} else if ((magic_type & MFU_TT_MAGIC_1B) == MFU_TT_MAGIC_1B) {
|
||||
payload.wakeup = MF_WAKE_GEN1B;
|
||||
payload.auth_cmd = 0;
|
||||
} else if ((magic_type & MFU_TT_MAGIC_4) == MFU_TT_MAGIC_4) {
|
||||
payload.wakeup = MF_WAKE_GDM_ALT;
|
||||
payload.auth_cmd = 0;
|
||||
} else if ((magic_type & MFU_TT_MAGIC_NTAG21X) == MFU_TT_MAGIC_NTAG21X) {
|
||||
payload.wakeup = MF_WAKE_WUPA;
|
||||
payload.auth_cmd = 0;
|
||||
} else {
|
||||
payload.wakeup = MF_WAKE_WUPA;
|
||||
payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_READBL_EX, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL_EX, &resp, 1500) == false) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_SUCCESS && resp.length == MFBLOCK_SIZE) {
|
||||
uint8_t *d = resp.data.asBytes;
|
||||
reverse_array(d, 8);
|
||||
reverse_array(d + 8, 8);
|
||||
memcpy(key, d, MFBLOCK_SIZE);
|
||||
}
|
||||
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
/*
|
||||
The 7 MSBits (=n) code the storage size itself based on 2^n,
|
||||
|
@ -1958,7 +1999,6 @@ static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey,
|
|||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, authkey, ak_len);
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||
|
@ -2352,7 +2392,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
|
||||
mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
|
||||
|
||||
if ((tagtype & MFU_TT_MAGIC)) {
|
||||
DropField();
|
||||
|
||||
if ((tagtype & MFU_TT_MAGIC) == MFU_TT_MAGIC) {
|
||||
//just read key
|
||||
uint8_t ulc_deskey[16] = {0x00};
|
||||
status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
|
||||
|
@ -2361,12 +2403,15 @@ 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);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
|
||||
} else {
|
||||
DropField();
|
||||
// if we called info with key, just return
|
||||
if (has_auth_key) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -2612,9 +2657,10 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
}
|
||||
|
||||
out:
|
||||
DropField();
|
||||
|
||||
mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
|
||||
|
||||
DropField();
|
||||
if (locked) {
|
||||
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");
|
||||
|
@ -2718,8 +2764,30 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
|
||||
}
|
||||
|
||||
// Send write Block
|
||||
int res = mfu_write_block(data, datalen, has_auth_key, has_pwd, auth_key_ptr, blockno);
|
||||
|
||||
// Send write Block.
|
||||
uint8_t *d = data;
|
||||
int res = 0;
|
||||
if (datalen == 16) {
|
||||
// Comp write may take 16bytes, but only write 4bytes. See UL-C datasheet
|
||||
for (uint8_t i = 0; i < 4; i++ ) {
|
||||
|
||||
res = mfu_write_block(d, 4, has_auth_key, has_pwd, auth_key_ptr, blockno + i);
|
||||
if ( res == PM3_SUCCESS) {
|
||||
d += 4;
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Write ( %s )", _RED_("fail"));
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno);
|
||||
}
|
||||
|
||||
} else {
|
||||
res = mfu_write_block(data, datalen, has_auth_key, has_pwd, auth_key_ptr, blockno);
|
||||
switch (res) {
|
||||
case PM3_SUCCESS: {
|
||||
PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
|
||||
|
@ -2737,6 +2805,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -3700,7 +3769,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "Restoring configuration blocks");
|
||||
|
||||
PrintAndLogEx(INFO, "authentication with keytype[%x] %s\n", (uint8_t)(keytype & 0xff), sprint_hex(p_authkey, 4));
|
||||
PrintAndLogEx(INFO, "Authentication with keytype[%x] %s\n", (uint8_t)(keytype & 0xff), sprint_hex(p_authkey, 4));
|
||||
|
||||
#if defined ICOPYX
|
||||
// otp, uid, lock, dynlockbits, cfg0, cfg1, pwd, pack
|
||||
|
@ -3715,7 +3784,7 @@ static int CmdHF14AMfURestore(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
|
||||
wait4response(b);
|
||||
PrintAndLogEx(INFO, "special block written %u - %s\n", b, sprint_hex(data, 4));
|
||||
PrintAndLogEx(INFO, "special block written " _YELLOW_("%u") " - %s", b, sprint_hex(data, 4));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5506,9 +5575,9 @@ static int CmdHF14AMfuWipe(const char *Cmd) {
|
|||
"you will need to call it with password in order to wipe the config and sett default pwd/pack\n"
|
||||
"Abort by pressing a key\n"
|
||||
"New password.... FFFFFFFF\n"
|
||||
"New 3-DES key... 425245414B4D454946594F5543414E21\n",
|
||||
"New 3-DES key... 49454D4B41455242214E4143554F5946\n",
|
||||
"hf mfu wipe\n"
|
||||
"hf mfu wipe -k 425245414B4D454946594F5543414E21\n"
|
||||
"hf mfu wipe -k 49454D4B41455242214E4143554F5946\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
@ -5566,6 +5635,21 @@ static int CmdHF14AMfuWipe(const char *Cmd) {
|
|||
|
||||
ul_print_type(tagtype, 0);
|
||||
|
||||
// GDM / GEN1A / GEN4 / NTAG21x read the key
|
||||
if (ak_len == 0) {
|
||||
|
||||
DropField();
|
||||
|
||||
int res = get_ulc_3des_key_magic(tagtype, auth_key_ptr);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Using 3DES key... %s", sprint_hex_inrow(auth_key_ptr, 16));
|
||||
has_auth_key = true;
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
PrintAndLogEx(INFO, "Start wiping...");
|
||||
PrintAndLogEx(INFO, "-----+-----------------------------");
|
||||
// time to wipe card
|
||||
|
@ -5656,6 +5740,7 @@ static int CmdHF14AMfuWipe(const char *Cmd) {
|
|||
res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
|
||||
}
|
||||
*/
|
||||
|
||||
int res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
|
||||
|
||||
PrintAndLogEx(INFO, " %3d | %s" NOLF, i, sprint_hex(data, MFU_BLOCK_SIZE));
|
||||
|
@ -5685,8 +5770,8 @@ ulc:
|
|||
if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
|
||||
|
||||
uint8_t key[16] = {
|
||||
0x42, 0x52, 0x45, 0x41, 0x4B, 0x4D, 0x45, 0x49,
|
||||
0x46, 0x59, 0x4F, 0x55, 0x43, 0x41, 0x4E, 0x21
|
||||
0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42,
|
||||
0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46
|
||||
};
|
||||
|
||||
clearCommandBuffer();
|
||||
|
|
|
@ -94,7 +94,8 @@ int CmdHF14MfUTamper(const char *Cmd);
|
|||
#define MFU_TT_UL_AES 0x100000000ULL
|
||||
#define MFU_TT_MAGIC_2 0x200000000ULL
|
||||
#define MFU_TT_MAGIC_4 0x400000000ULL
|
||||
#define MFU_TT_MAGIC_NTAG21X 0x800000000ULL
|
||||
#define MFU_TT_MAGIC_4_GDM 0x800000000ULL
|
||||
#define MFU_TT_MAGIC_NTAG21X 0x1000000000ULL
|
||||
#define MFU_TT_UL_MAGIC (MFU_TT_UL | MFU_TT_MAGIC)
|
||||
#define MFU_TT_UL_C_MAGIC (MFU_TT_UL_C | MFU_TT_MAGIC)
|
||||
// Don't forget to fill UL_TYPES_ARRAY and UL_MEMORY_ARRAY if new types are added
|
||||
|
|
|
@ -185,7 +185,7 @@ int discoverDevices(unsigned int profile_selected, uint32_t device_types_selecte
|
|||
return -7;
|
||||
}
|
||||
|
||||
strncpy(tmp_buf, "N/A\0", tmp_len);
|
||||
strncpy(tmp_buf, "n/a\0", tmp_len);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
|
@ -454,7 +454,7 @@ int discoverDevices(unsigned int profile_selected, uint32_t device_types_selecte
|
|||
return -7;
|
||||
}
|
||||
|
||||
strncpy(tmp_buf, "N/A\0", tmp_len);
|
||||
strncpy(tmp_buf, "n/a\0", tmp_len);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue