This commit is contained in:
iceman1001 2025-07-04 12:22:09 +02:00
parent 03a3abfc64
commit 24d80f51a9
5 changed files with 101 additions and 86 deletions

View file

@ -2553,28 +2553,27 @@ out:
}
static bool do_privilege_escalation(uint8_t *read_check_cc, size_t cc_len, uint32_t *eof_time) {
int priv_esc_tries = 0;
bool priv_esc = false;
uint32_t start_time = 0;
while (!priv_esc) {
int priv_esc_tries = 5;
while (priv_esc_tries--) {
uint16_t resp_len = 0;
int res2;
uint8_t resp[10] = {0};
//The privilege escalation is done with a readcheck and not just a normal read!
start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
uint32_t start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc, cc_len, &start_time, eof_time, false);
// expect a 8-byte response here
res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
if (res2 != PM3_SUCCESS || resp_len != 8) {
priv_esc_tries++;
} else {
int res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
if (res == PM3_SUCCESS && resp_len == 8) {
return true;
}
if (priv_esc_tries == 5) {
}
if (g_dbglevel == DBG_INFO) {
DbpString("");
DbpString(_RED_("Unable to complete privilege escalation! Stopping."));
return false;
}
}
return false;
}
@ -2629,7 +2628,7 @@ void iClass_Restore(iclass_restore_req_t *msg) {
if (msg->req.use_replay) {
priv_esc = do_privilege_escalation(read_check_cc, sizeof(read_check_cc), &eof_time);
if (!priv_esc){
if (priv_esc == false) {
goto out;
}
}
@ -2765,10 +2764,10 @@ void iClass_Recover(iclass_recover_req_t *msg) {
uint8_t original_mac[8] = {0};
uint8_t mac1[4] = {0};
while (!card_select || !card_auth) {
while ((card_select == false) || (card_auth == false)) {
Iso15693InitReader(); //has to be at the top as it starts tracing
if (!msg->debug) {
if (msg->debug == false) {
set_tracing(false); //disable tracing to prevent crashes - set to true for debugging
} else {
if (loops == 1) {
@ -2796,10 +2795,12 @@ void iClass_Recover(iclass_recover_req_t *msg) {
card_auth = true;
}
}
if (!card_auth || !card_select) {
if ((card_select == false) || (card_auth == false)) {
reinit_tentatives++;
switch_off();
}
if (reinit_tentatives == 5) {
DbpString("");
DbpString(_RED_("Unable to select or authenticate with card multiple times! Stopping."));
@ -2827,13 +2828,13 @@ void iClass_Recover(iclass_recover_req_t *msg) {
if (msg->test) {
Dbprintf(_YELLOW_("*Cycled Reader*") " TEST Index - Loops: "_YELLOW_("%3d / %3d") " *", loops, msg->loop);
} else if (msg->debug || (!card_select && !card_auth)) {
} else if (msg->debug || ((card_select == false) || (card_auth == false))) {
Dbprintf(_YELLOW_("*Cycled Reader*") " Index: "_RED_("%3d")" Loops: "_YELLOW_("%3d / %3d") " *", index, loops, msg->loop);
} else {
DbprintfEx(FLAG_INPLACE, "[" _BLUE_("#") "] Index: "_CYAN_("%3d")" Loops: "_YELLOW_("%3d / %3d")" ", index, loops, msg->loop);
}
while (!card_select || !card_auth) {
while ((card_select == false) || (card_auth == false)) {
Iso15693InitReader(); // has to be at the top as it starts tracing
set_tracing(false); // disable tracing to prevent crashes - set to true for debugging
@ -2855,10 +2856,12 @@ void iClass_Recover(iclass_recover_req_t *msg) {
card_auth = true;
}
}
if (!card_auth || !card_select) {
if ((card_select == false) || (card_auth == false)) {
reinit_tentatives++;
switch_off();
}
if (reinit_tentatives == 5) {
DbpString("");
DbpString(_RED_("Unable to select or authenticate with card multiple times! Stopping."));
@ -2867,7 +2870,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
}
// Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1
if(!priv_esc){
if (priv_esc == false) {
priv_esc = do_privilege_escalation(read_check_cc, sizeof(read_check_cc), &eof_time);
if (priv_esc) {
status_message = 3;
@ -2889,15 +2892,18 @@ void iClass_Recover(iclass_recover_req_t *msg) {
}
if (msg->fast) { // if we're skipping restoring the original key to gain speed, xor the new index key with the previous index key and update the difference and track restore values differently
if (index > 0 && loops > 1) {
generate_single_key_block_inverted_opt(zero_key, index - 1, fast_previous_key);
} else {
memcpy(fast_previous_key, zero_key, PICOPASS_BLOCK_SIZE);
}
for (int i = 0; i < PICOPASS_BLOCK_SIZE; i++) {
fast_current_key[i] = genkeyblock[i] ^ fast_previous_key[i];
fast_restore_key[i] = fast_restore_key[i] ^ fast_current_key[i];
}
memcpy(genkeyblock, fast_current_key, PICOPASS_BLOCK_SIZE);
}
@ -2910,13 +2916,14 @@ void iClass_Recover(iclass_recover_req_t *msg) {
doMAC_N(wb, sizeof(wb), div_key2, mac2);
bool written = false;
bool write_error = false;
while (written == false && write_error == false) {
// Step5 Perform Write
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
if (iclass_writeblock_sp(blockno, genkeyblock, mac2, shallow_mod, &start_time, &eof_time, short_delay)) {
status_message = 4; // wrote new key on the card - unverified
}
if (!msg->fast) { //if we're going slow we check at every write that the write actually happened
if (msg->fast == false) { // if we're going slow we check at every write that the write actually happened
// Reset cypher state
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
@ -2972,7 +2979,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
}
} else {
// if we're NOT going fast, regardless of bits being found, restore the original key and verify it
while (!reverted) {
while (reverted == false) {
// Regain privilege escalation with a readcheck
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
@ -2983,9 +2990,11 @@ void iClass_Recover(iclass_recover_req_t *msg) {
// Do a readcheck first to reset the cypher state
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
// need to craft the authentication payload accordingly
memcpy(msg->req.key, original_mac, 8);
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
if (res == true) {
status_message = 7; // restore of original key verified - card usable again
@ -3005,8 +3014,6 @@ void iClass_Recover(iclass_recover_req_t *msg) {
}
}
}
}
if (msg->debug) {
@ -3056,27 +3063,33 @@ fast_restore:
wb[0] = blockno;
bool reverted = false;
uint8_t revert_retries = 0;
while (!reverted) {
while (reverted == false) {
// Regain privilege escalation with a readcheck
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
memcpy(wb + 1, fast_restore_key, 8);
doMAC_N(wb, sizeof(wb), div_key2, mac2);
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
if (iclass_writeblock_sp(blockno, fast_restore_key, mac2, shallow_mod, &start_time, &eof_time, short_delay)) {
status_message = 6; // restore of original key successful but unverified
}
// Do a readcheck first to reset the cypher state
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
// need to craft the authentication payload accordingly
memcpy(msg->req.key, original_mac, 8);
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
if (res == true) {
status_message = 7; // restore of original key verified - card usable again
reverted = true;
}
revert_retries++;
if (revert_retries >= 7) { // must always be an odd number!
DbpString("");
@ -3126,5 +3139,4 @@ out:
} else {
reply_ng(CMD_HF_ICLASS_RECOVER, PM3_ESOFT, NULL, 0);
}
}

View file

@ -985,10 +985,11 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
DecodeTagFSK_t dtfm = { 0 };
DecodeTagFSK_t *dtf = &dtfm;
if (fsk)
if (fsk) {
DecodeTagFSKInit(dtf, response, max_len);
else
} else {
DecodeTagInit(dt, response, max_len);
}
// wait for last transfer to complete
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY));
@ -1014,8 +1015,9 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
for (;;) {
volatile uint16_t behindBy = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1);
if (behindBy == 0)
if (behindBy == 0) {
continue;
}
samples++;
if (samples == 1) {

View file

@ -3663,9 +3663,10 @@
"--elite elite computations applied to key",
"--raw no computations applied to key",
"-v, --verbose verbose output",
"--shallow use shallow (ASK) reader modulation instead of OOK"
"--shallow use shallow (ASK) reader modulation instead of OOK",
"--nr replay of nr mac with privilege escalation"
],
"usage": "hf iclass restore [-hv] -f <fn> [-k <hex>] [--ki <dec>] --first <dec> --last <dec> [--credit] [--elite] [--raw] [--shallow]"
"usage": "hf iclass restore [-hv] -f <fn> [-k <hex>] [--ki <dec>] --first <dec> --last <dec> [--credit] [--elite] [--raw] [--shallow] [--nr]"
},
"hf iclass sam": {
"command": "hf iclass sam",
@ -13376,6 +13377,6 @@
"metadata": {
"commands_extracted": 768,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2025-07-01T14:12:39"
"extracted_on": "2025-07-04T10:19:21"
}
}