diff --git a/CHANGELOG.md b/CHANGELOG.md index 00233936b..f2395069c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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... ## [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 dump` - now uses default AA1 key when called without a key or key index (@iceman1001) - Renamed `hf iclass trbl` to `hf iclass tear` (@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) - 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 fchk --mem` to actually use flash dict (@doegox) - Fixed `make install` on OSX thanks DaveItsLong (@doegox) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 38627ea70..652993a0a 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -2311,11 +2311,13 @@ void iClass_TearBlock(iclass_tearblock_req_t *msg) { if (memcmp(data_read, ff_data, PICOPASS_BLOCK_SIZE) == 0 && memcmp(data_read_orig, ff_data, PICOPASS_BLOCK_SIZE) != 0) { - erase_phase = true; - DbpString(""); - DbpString(_CYAN_("Erase phase hit... ALL ONES")); + if(erase_phase == false){ + DbpString(""); + 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 { @@ -2459,7 +2461,7 @@ void iClass_TearBlock(iclass_tearblock_req_t *msg) { read_ok = true; tear_success = true; DbpString(""); - DbpString("tear success!"); + DbpString("tear success (expected values)!"); } loop_count++; @@ -2708,6 +2710,7 @@ void iClass_Recover(iclass_recover_req_t *msg) { bool priv_esc = false; 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, 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); @@ -2747,27 +2750,29 @@ void iClass_Recover(iclass_recover_req_t *msg) { Dbhexdump(8, genkeyblock, false); } //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); - 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 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 (msg->test) { - if (res != true) { - 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 { + if (res) { DbpString(_GREEN_("*** CARD EPURSE IS LOUD! OK TO ATTEMPT KEY RETRIEVAL! RUN AGAIN WITH -notest ***")); completed = true; 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 { - if (res != true) { - DbpString("Write Operation : "_GREEN_("VERIFIED! Card Key Updated!")); - written = true; - } else { + if (res) { DbpString("Write Operation : "_RED_("FAILED! Card Key is the Original. Retrying...")); 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) { //Step6 Perform 8 authentication attempts + 1 to verify if we found the weak key 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); - 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 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 if (res == true) { bits_found = i; @@ -2794,9 +2801,10 @@ void iClass_Recover(iclass_recover_req_t *msg) { uint8_t revert_retries = 0; while (!reverted) { //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); // 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. ")); 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...")); //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); // 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 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) { DbpString("Restore of Original Key "_GREEN_("VERIFIED! Card is usable again.")); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 86dff7e43..a60df6ebb 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -3340,10 +3340,13 @@ static int CmdHFiClass_TearBlock(const char *Cmd) { if (memcmp(data_read, 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; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, _CYAN_("Erase phase hit... ALL ONES")); - iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: "); } else { 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 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, "Weak Key: " _GREEN_("%s"), sprint_hex(key, sizeof(key))); 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++; @@ -5896,7 +5899,7 @@ static command_t CommandTable[] = { {"loclass", CmdHFiClass_loclass, AlwaysAvailable, "Use loclass to perform bruteforce reader attack"}, {"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"}, - {"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"}, {"-----------", CmdHelp, IfPm3Iclass, "-------------------- " _CYAN_("Simulation") " -------------------"}, {"sim", CmdHFiClassSim, IfPm3Iclass, "Simulate iCLASS tag"},