mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
Merge pull request #2869 from Antiklesys/master
Modified iclass recover and tear operations
This commit is contained in:
commit
be65279475
3 changed files with 40 additions and 25 deletions
|
@ -3,14 +3,16 @@ 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]
|
||||||
- Modified `hf iclass tear` - now has a device side implementation also. @antiklesys (@iceman1001)
|
- Changed `hf iclass tear` - readability improvements for erase phase (@antiklesys)
|
||||||
|
- Changed `hf iclass legrec` - code optimizations gaining a ~8% speed increase (@antiklesys)
|
||||||
|
- Modified `hf iclass tear` - now has a device side implementation also. (@antiklesys) (@iceman1001)
|
||||||
- Changed `hf iclass info` - now uses CSN values based checks (@antiklesys)
|
- Changed `hf iclass info` - now uses CSN values based checks (@antiklesys)
|
||||||
- Changed `hf iclass dump` - now uses default AA1 key when called without a key or key index (@iceman1001)
|
- Changed `hf iclass dump` - now uses default AA1 key when called without a key or key index (@iceman1001)
|
||||||
- Renamed `hf iclass trbl` to `hf iclass tear` (@iceman1001)
|
- Renamed `hf iclass trbl` to `hf iclass tear` (@iceman1001)
|
||||||
- Changed `hw tearoff` - the device side message is now debug log controlled (@iceman1001)
|
- Changed `hw tearoff` - the device side message is now debug log controlled (@iceman1001)
|
||||||
- Changed `pm3.sh` - Serial ports enumeration on Proxspace3.xx / MINGW environments, now using powershell.exe since wmic is deprecated (@iceman1001)
|
- Changed `pm3.sh` - Serial ports enumeration on Proxspace3.xx / MINGW environments, now using powershell.exe since wmic is deprecated (@iceman1001)
|
||||||
- Fixed and updated `hf iclass trbl` to correctly use the credit key when passed and show partial tearoff results (@antiklesys)
|
- Fixed and updated `hf iclass trbl` to correctly use the credit key when passed and show partial tearoff results (@antiklesys)
|
||||||
- Fixed `hf iclass legbrute` was not correctly parsin the index value
|
- Fixed `hf iclass legbrute` was not correctly parsing the index value
|
||||||
- Fixed `hf mf ekeyprn` - failed to download emulator memory due to wrong size calculation (@iceman1001)
|
- Fixed `hf mf ekeyprn` - failed to download emulator memory due to wrong size calculation (@iceman1001)
|
||||||
- Fixed `hf mf fchk --mem` to actually use flash dict (@doegox)
|
- Fixed `hf mf fchk --mem` to actually use flash dict (@doegox)
|
||||||
- Fixed `make install` on OSX thanks DaveItsLong (@doegox)
|
- Fixed `make install` on OSX thanks DaveItsLong (@doegox)
|
||||||
|
|
|
@ -2311,11 +2311,13 @@ void iClass_TearBlock(iclass_tearblock_req_t *msg) {
|
||||||
if (memcmp(data_read, ff_data, PICOPASS_BLOCK_SIZE) == 0 &&
|
if (memcmp(data_read, ff_data, PICOPASS_BLOCK_SIZE) == 0 &&
|
||||||
memcmp(data_read_orig, ff_data, PICOPASS_BLOCK_SIZE) != 0) {
|
memcmp(data_read_orig, ff_data, PICOPASS_BLOCK_SIZE) != 0) {
|
||||||
|
|
||||||
erase_phase = true;
|
if(erase_phase == false){
|
||||||
DbpString("");
|
DbpString("");
|
||||||
DbpString(_CYAN_("Erase phase hit... ALL ONES"));
|
DbpString(_CYAN_("Erase phase hit... ALL ONES"));
|
||||||
|
|
||||||
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
||||||
|
}
|
||||||
|
erase_phase = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -2459,7 +2461,7 @@ void iClass_TearBlock(iclass_tearblock_req_t *msg) {
|
||||||
read_ok = true;
|
read_ok = true;
|
||||||
tear_success = true;
|
tear_success = true;
|
||||||
DbpString("");
|
DbpString("");
|
||||||
DbpString("tear success!");
|
DbpString("tear success (expected values)!");
|
||||||
}
|
}
|
||||||
|
|
||||||
loop_count++;
|
loop_count++;
|
||||||
|
@ -2708,6 +2710,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
bool priv_esc = false;
|
bool priv_esc = false;
|
||||||
while (!priv_esc) {
|
while (!priv_esc) {
|
||||||
//The privilege escalation is done with a readcheck and not just a normal read!
|
//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, 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);
|
||||||
// expect a 8-byte response here
|
// expect a 8-byte response here
|
||||||
res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
||||||
|
@ -2747,27 +2750,29 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
Dbhexdump(8, genkeyblock, false);
|
Dbhexdump(8, genkeyblock, false);
|
||||||
}
|
}
|
||||||
//Reset cypher state
|
//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);
|
iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
|
||||||
res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
//res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
||||||
//try to authenticate with the original mac to verify the write happened
|
//try to authenticate with the original mac to verify the write happened
|
||||||
memcpy(msg->req.key, original_mac, 8);
|
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);
|
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
|
||||||
if (msg->test) {
|
if (msg->test) {
|
||||||
if (res != true) {
|
if (res) {
|
||||||
DbpString(_RED_("*** CARD EPURSE IS SILENT! RISK OF BRICKING! DO NOT EXECUTE KEY UPDATES! SCAN IT ON READER FOR EPURSE UPDATE, COLLECT NEW TRACES AND TRY AGAIN! ***"));
|
|
||||||
goto out;
|
|
||||||
} else {
|
|
||||||
DbpString(_GREEN_("*** CARD EPURSE IS LOUD! OK TO ATTEMPT KEY RETRIEVAL! RUN AGAIN WITH -notest ***"));
|
DbpString(_GREEN_("*** CARD EPURSE IS LOUD! OK TO ATTEMPT KEY RETRIEVAL! RUN AGAIN WITH -notest ***"));
|
||||||
completed = true;
|
completed = true;
|
||||||
goto out;
|
goto out;
|
||||||
|
} else {
|
||||||
|
DbpString(_RED_("*** CARD EPURSE IS SILENT! RISK OF BRICKING! DO NOT EXECUTE KEY UPDATES! SCAN IT ON READER FOR EPURSE UPDATE, COLLECT NEW TRACES AND TRY AGAIN! ***"));
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res != true) {
|
if (res) {
|
||||||
DbpString("Write Operation : "_GREEN_("VERIFIED! Card Key Updated!"));
|
|
||||||
written = true;
|
|
||||||
} else {
|
|
||||||
DbpString("Write Operation : "_RED_("FAILED! Card Key is the Original. Retrying..."));
|
DbpString("Write Operation : "_RED_("FAILED! Card Key is the Original. Retrying..."));
|
||||||
write_error = true;
|
write_error = true;
|
||||||
|
} else {
|
||||||
|
DbpString("Write Operation : "_GREEN_("VERIFIED! Card Key Updated!"));
|
||||||
|
written = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2775,10 +2780,12 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
if (!write_error) {
|
if (!write_error) {
|
||||||
//Step6 Perform 8 authentication attempts + 1 to verify if we found the weak key
|
//Step6 Perform 8 authentication attempts + 1 to verify if we found the weak key
|
||||||
for (int i = 0; i < 8 ; ++i) {
|
for (int i = 0; i < 8 ; ++i) {
|
||||||
|
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);
|
iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
|
||||||
res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
//res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
||||||
//need to craft the authentication payload accordingly
|
//need to craft the authentication payload accordingly
|
||||||
memcpy(msg->req.key, iclass_mac_table[i], 8);
|
memcpy(msg->req.key, iclass_mac_table[i], 8);
|
||||||
|
start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
|
||||||
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter
|
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
bits_found = i;
|
bits_found = i;
|
||||||
|
@ -2794,9 +2801,10 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
uint8_t revert_retries = 0;
|
uint8_t revert_retries = 0;
|
||||||
while (!reverted) {
|
while (!reverted) {
|
||||||
//Regain privilege escalation with a readcheck
|
//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);
|
iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
|
||||||
// TODO: check result
|
// TODO: check result
|
||||||
GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
//GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
||||||
|
|
||||||
DbpString(_YELLOW_("Attempting to restore the original key. "));
|
DbpString(_YELLOW_("Attempting to restore the original key. "));
|
||||||
if (iclass_writeblock_ext(blockno, genkeyblock, mac2, use_mac, shallow_mod)) {
|
if (iclass_writeblock_ext(blockno, genkeyblock, mac2, use_mac, shallow_mod)) {
|
||||||
|
@ -2806,12 +2814,14 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
}
|
}
|
||||||
DbpString(_YELLOW_("Verifying Key Restore..."));
|
DbpString(_YELLOW_("Verifying Key Restore..."));
|
||||||
//Do a readcheck first to reset the cypher state
|
//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);
|
iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
|
||||||
// TODO: check result
|
// TODO: check result
|
||||||
GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
//GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
|
||||||
|
|
||||||
//need to craft the authentication payload accordingly
|
//need to craft the authentication payload accordingly
|
||||||
memcpy(msg->req.key, original_mac, 8);
|
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);
|
res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
DbpString("Restore of Original Key "_GREEN_("VERIFIED! Card is usable again."));
|
DbpString("Restore of Original Key "_GREEN_("VERIFIED! Card is usable again."));
|
||||||
|
|
|
@ -3340,10 +3340,13 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
|
||||||
|
|
||||||
if (memcmp(data_read, ff_data, 8) == 0 &&
|
if (memcmp(data_read, ff_data, 8) == 0 &&
|
||||||
memcmp(data_read_orig, ff_data, 8) != 0) {
|
memcmp(data_read_orig, ff_data, 8) != 0) {
|
||||||
|
|
||||||
|
if (erase_phase == false){
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(SUCCESS, _CYAN_("Erase phase hit... ALL ONES"));
|
||||||
|
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
||||||
|
}
|
||||||
erase_phase = true;
|
erase_phase = true;
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(SUCCESS, _CYAN_("Erase phase hit... ALL ONES"));
|
|
||||||
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (erase_phase) {
|
if (erase_phase) {
|
||||||
|
@ -4578,7 +4581,7 @@ void generate_key_block_inverted(const uint8_t *startingKey, uint64_t index, uin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHFiClassLegRecLookUp(const char *Cmd) {
|
static int CmdHFiClassLegBrute(const char *Cmd) {
|
||||||
|
|
||||||
//Standalone Command Start
|
//Standalone Command Start
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
@ -4805,7 +4808,7 @@ static int CmdHFiClassLegacyRecSim(void) {
|
||||||
PrintAndLogEx(SUCCESS, "Original Key: " _GREEN_("%s"), sprint_hex(original_key, sizeof(original_key)));
|
PrintAndLogEx(SUCCESS, "Original Key: " _GREEN_("%s"), sprint_hex(original_key, sizeof(original_key)));
|
||||||
PrintAndLogEx(SUCCESS, "Weak Key: " _GREEN_("%s"), sprint_hex(key, sizeof(key)));
|
PrintAndLogEx(SUCCESS, "Weak Key: " _GREEN_("%s"), sprint_hex(key, sizeof(key)));
|
||||||
PrintAndLogEx(SUCCESS, "Key Updates Required to Weak Key: " _GREEN_("%d"), index);
|
PrintAndLogEx(SUCCESS, "Key Updates Required to Weak Key: " _GREEN_("%d"), index);
|
||||||
PrintAndLogEx(SUCCESS, "Estimated Time: ~" _GREEN_("%d")" hours", index / 6545);
|
PrintAndLogEx(SUCCESS, "Estimated Time: ~" _GREEN_("%d")" hours", index / 7250);
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
@ -5896,7 +5899,7 @@ static command_t CommandTable[] = {
|
||||||
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "Use loclass to perform bruteforce reader attack"},
|
{"loclass", CmdHFiClass_loclass, AlwaysAvailable, "Use loclass to perform bruteforce reader attack"},
|
||||||
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "Uses authentication trace to check for key in dictionary file"},
|
{"lookup", CmdHFiClassLookUp, AlwaysAvailable, "Uses authentication trace to check for key in dictionary file"},
|
||||||
{"legrec", CmdHFiClassLegacyRecover, IfPm3Iclass, "Recovers 24 bits of the diversified key of a legacy card provided a valid nr-mac combination"},
|
{"legrec", CmdHFiClassLegacyRecover, IfPm3Iclass, "Recovers 24 bits of the diversified key of a legacy card provided a valid nr-mac combination"},
|
||||||
{"legbrute", CmdHFiClassLegRecLookUp, AlwaysAvailable, "Bruteforces 40 bits of a partial diversified key, provided 24 bits of the key and two valid nr-macs"},
|
{"legbrute", CmdHFiClassLegBrute, AlwaysAvailable, "Bruteforces 40 bits of a partial diversified key, provided 24 bits of the key and two valid nr-macs"},
|
||||||
{"unhash", CmdHFiClassUnhash, AlwaysAvailable, "Reverses a diversified key to retrieve hash0 pre-images after DES encryption"},
|
{"unhash", CmdHFiClassUnhash, AlwaysAvailable, "Reverses a diversified key to retrieve hash0 pre-images after DES encryption"},
|
||||||
{"-----------", CmdHelp, IfPm3Iclass, "-------------------- " _CYAN_("Simulation") " -------------------"},
|
{"-----------", CmdHelp, IfPm3Iclass, "-------------------- " _CYAN_("Simulation") " -------------------"},
|
||||||
{"sim", CmdHFiClassSim, IfPm3Iclass, "Simulate iCLASS tag"},
|
{"sim", CmdHFiClassSim, IfPm3Iclass, "Simulate iCLASS tag"},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue