From f8fbcc2754b49789c810113ca98b51d8f3ebbf99 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Sun, 21 Jul 2024 13:55:17 +0800 Subject: [PATCH] Bugfixes and code improvements for hf iclass legrec 1- Inlined functions related to hf iclass legrec within util.c for marginal performance gains. 2- Fixed bug preventing errors to be displayed properly and the process from interrupting on an error or on completion. 3- Fixed code indentation of the while loop in iclass.c 4- Fixed bug in the while cycle (was missing index++) 5- Improved ways to display hex results by using dbhexdump --- armsrc/iclass.c | 117 +++++++++++++++++++++------------------ armsrc/util.c | 26 +++------ armsrc/util.h | 2 - client/src/cmdhficlass.c | 4 +- 4 files changed, 73 insertions(+), 76 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 4b3ce223d..109b03d8d 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -2174,6 +2174,7 @@ void iClass_Recover(iclass_recover_req_t *msg) { bool shallow_mod = false; LED_A_ON(); + Dbprintf(_RED_("Interrupting this process will render the card unusable!")); Iso15693InitReader(); //Authenticate with AA2 with the standard key to get the AA2 mac @@ -2253,56 +2254,61 @@ Xorring the index of iterations against those decimal numbers allows us to retri //START LOOP while (bits_found == -1){ - //Step3 Calculate New Key - uint8_t genkeyblock[PICOPASS_BLOCK_SIZE]; - uint8_t genkeyblock_old[PICOPASS_BLOCK_SIZE]; - uint8_t xorkeyblock[PICOPASS_BLOCK_SIZE]; - generate_single_key_block_inverted(zero_key, index, genkeyblock); + //Step3 Calculate New Key + uint8_t genkeyblock[PICOPASS_BLOCK_SIZE]; + uint8_t genkeyblock_old[PICOPASS_BLOCK_SIZE]; + uint8_t xorkeyblock[PICOPASS_BLOCK_SIZE]; + generate_single_key_block_inverted(zero_key, index, genkeyblock); - //NOTE BEFORE UPDATING THE KEY WE NEED TO KEEP IN MIND KEYS ARE XORRED - //xor the new key against the previously generated key so that we only update the difference - if(index != 0){ - generate_single_key_block_inverted(zero_key, index - 1, genkeyblock_old); - for (int i = 0; i < 8 ; i++) { - xorkeyblock[i] = genkeyblock[i] ^ genkeyblock_old[i]; - } - }else{ + //NOTE BEFORE UPDATING THE KEY WE NEED TO KEEP IN MIND KEYS ARE XORRED + //xor the new key against the previously generated key so that we only update the difference + if(index != 0){ + generate_single_key_block_inverted(zero_key, index - 1, genkeyblock_old); + for (int i = 0; i < 8 ; i++) { + xorkeyblock[i] = genkeyblock[i] ^ genkeyblock_old[i]; + } + }else{ memcpy(xorkeyblock, genkeyblock, PICOPASS_BLOCK_SIZE); - } - - //Step4 Calculate New Mac - - bool use_mac = true; - uint8_t wb[9] = {0}; - blockno = 3; - wb[0] = blockno; - memcpy(wb + 1, xorkeyblock, 8); - - doMAC_N(wb, sizeof(wb), div_key2, mac2); - - //Step5 Perform Write - - if (iclass_writeblock_ext(blockno, xorkeyblock, mac2, use_mac, shallow_mod)) { - Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), blockno, blockno); - } else { - Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), blockno, blockno); - goto out; - } - //Step6 Perform 8 authentication attempts - - for (int i = 0; i < 8 ; ++i) { - //need to craft the authentication payload accordingly - memcpy(msg->req.key, iclass_mac_table[i], 8); - res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter - if (res == true) { - bits_found = iclass_mac_table_bit_values[i] ^ index; - Dbprintf("Found Card Bits Index: " _GREEN_("[%3d]"), index); - Dbprintf("Mac Table Bit Values: " _GREEN_("[%3d]"), iclass_mac_table_bit_values[i]); - Dbprintf("Decimal Value of Partial Key: " _GREEN_("[%3d]"), bits_found); - goto restore; } - } + //Step4 Calculate New Mac + + bool use_mac = true; + uint8_t wb[9] = {0}; + blockno = 3; + wb[0] = blockno; + memcpy(wb + 1, xorkeyblock, 8); + doMAC_N(wb, sizeof(wb), div_key2, mac2); + + //Step5 Perform Write + + DbpString("Generated XOR Key: "); + Dbhexdump(8, xorkeyblock, false); + + if (iclass_writeblock_ext(blockno, xorkeyblock, mac2, use_mac, shallow_mod)) { + Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), blockno, blockno); + } else { + Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), blockno, blockno); + if (index > 1){ + Dbprintf(_RED_("Card is likely to be unusable!")); + } + goto out; + } + //Step6 Perform 8 authentication attempts + + for (int i = 0; i < 8 ; ++i) { + //need to craft the authentication payload accordingly + memcpy(msg->req.key, iclass_mac_table[i], 8); + res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter + if (res == true) { + bits_found = iclass_mac_table_bit_values[i] ^ index; + Dbprintf("Found Card Bits Index: " _GREEN_("[%3d]"), index); + Dbprintf("Mac Table Bit Values: " _GREEN_("[%3d]"), iclass_mac_table_bit_values[i]); + Dbprintf("Decimal Value of Partial Key: " _GREEN_("[%3d]"), bits_found); + goto restore; + } + } + index++; }//end while @@ -2311,10 +2317,6 @@ restore: uint8_t partialkey[PICOPASS_BLOCK_SIZE]; convertToHexArray(bits_found, partialkey); - for (int i = 0; i < 8; i++){ - Dbprintf("Raw Key Partial Bytes: " _GREEN_("[%3d -> 0x%02X]"), i, partialkey); - } - uint8_t resetkey[PICOPASS_BLOCK_SIZE]; convertToHexArray(index, resetkey); @@ -2325,19 +2327,26 @@ restore: blockno = 3; wb[0] = blockno; memcpy(wb + 1, resetkey, 8); - doMAC_N(wb, sizeof(wb), div_key2, mac2); + + //Write back the card to the original key + DbpString(_YELLOW_("Restoring Card to the original key using Reset Key: ")); + Dbhexdump(8, resetkey, false); if (iclass_writeblock_ext(blockno, resetkey, mac2, use_mac, shallow_mod)) { - Dbprintf("Restore of Original Key [%3d/0x%02X] " _GREEN_("successful"), blockno, blockno); + Dbprintf("Restore of Original Key "_GREEN_("successful. Card is usable again.")); } else { - Dbprintf("Restore of Original Key [%3d/0x%02X] " _RED_("failed"), blockno, blockno); + Dbprintf("Restore of Original Key " _RED_("failed. Card is likely unusable.")); } + //Print the 24 bits found from k1 + DbpString(_YELLOW_("Raw Key Partial Bytes: ")); + Dbhexdump(8, partialkey, false); switch_off(); + reply_ng(CMD_HF_ICLASS_RECOVER, PM3_SUCCESS, NULL, 0); out: switch_off(); - + reply_ng(CMD_HF_ICLASS_RECOVER, PM3_ESOFT, NULL, 0); } \ No newline at end of file diff --git a/armsrc/util.c b/armsrc/util.c index a4d6f2b8b..939272cac 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -396,32 +396,22 @@ uint32_t get_flash_size(void) { return flash_size_from_cidr(*AT91C_DBGU_CIDR); } -// Function to convert an unsigned int to binary string -void intToBinary(uint8_t num, char *binaryStr, int size) { - binaryStr[size] = '\0'; // Null-terminate the string - for (int i = size - 1; i >= 0; i--) { +// Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1 +void convertToHexArray(uint8_t num, uint8_t *partialkey) { + char binaryStr[25]; // 24 bits for binary representation + 1 for null terminator + binaryStr[24] = '\0'; // Null-terminate the string + + // Convert the number to binary string + for (int i = 23; i >= 0; i--) { binaryStr[i] = (num % 2) ? '1' : '0'; num /= 2; } -} - -// Function to convert a binary string to hexadecimal -uint8_t binaryToHex(char *binaryStr) { - return (uint8_t)strtoul(binaryStr, NULL, 2); -} - -// Function to convert an unsigned int to an array of hex values -void convertToHexArray(uint8_t num, uint8_t *partialkey) { - char binaryStr[25]; // 24 bits for binary representation + 1 for null terminator - - // Convert the number to binary string - intToBinary(num, binaryStr, 24); // Split the binary string into groups of 3 and convert to hex for (int i = 0; i < 8 ; i++) { char group[4]; strncpy(group, binaryStr + i * 3, 3); group[3] = '\0'; // Null-terminate the group string - partialkey[i] = binaryToHex(group); + partialkey[i] = (uint8_t)strtoul(group, NULL, 2); } } \ No newline at end of file diff --git a/armsrc/util.h b/armsrc/util.h index 709c11c3e..fac928427 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -88,8 +88,6 @@ int hex2binarray(char *target, char *source); int hex2binarray_n(char *target, const char *source, int sourcelen); int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex); -void intToBinary(uint8_t num, char *binaryStr, int size); -uint8_t binaryToHex(char *binaryStr); void convertToHexArray(uint8_t num, uint8_t *partialKey); void LED(int led, int ms); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 03d66f797..6adeddc8d 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -3874,9 +3874,9 @@ static int CmdHFiClassRecover(uint8_t key[8]) { WaitForResponse(CMD_HF_ICLASS_RECOVER, &resp); if (resp.status == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "iCLASS Recover " _GREEN_("successful")); + PrintAndLogEx(SUCCESS, "iCLASS Key Bits Recovery " _GREEN_("successful")); } else { - PrintAndLogEx(WARNING, "iCLASS Recover " _RED_("failed")); + PrintAndLogEx(WARNING, "iCLASS Key Bits Recovery " _RED_("failed")); } free(payload);