mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-29 19:19:06 -07:00
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
This commit is contained in:
parent
2208d4e3e6
commit
f8fbcc2754
4 changed files with 73 additions and 76 deletions
117
armsrc/iclass.c
117
armsrc/iclass.c
|
@ -2174,6 +2174,7 @@ void iClass_Recover(iclass_recover_req_t *msg) {
|
||||||
bool shallow_mod = false;
|
bool shallow_mod = false;
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
Dbprintf(_RED_("Interrupting this process will render the card unusable!"));
|
||||||
|
|
||||||
Iso15693InitReader();
|
Iso15693InitReader();
|
||||||
//Authenticate with AA2 with the standard key to get the AA2 mac
|
//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
|
//START LOOP
|
||||||
while (bits_found == -1){
|
while (bits_found == -1){
|
||||||
|
|
||||||
//Step3 Calculate New Key
|
//Step3 Calculate New Key
|
||||||
uint8_t genkeyblock[PICOPASS_BLOCK_SIZE];
|
uint8_t genkeyblock[PICOPASS_BLOCK_SIZE];
|
||||||
uint8_t genkeyblock_old[PICOPASS_BLOCK_SIZE];
|
uint8_t genkeyblock_old[PICOPASS_BLOCK_SIZE];
|
||||||
uint8_t xorkeyblock[PICOPASS_BLOCK_SIZE];
|
uint8_t xorkeyblock[PICOPASS_BLOCK_SIZE];
|
||||||
generate_single_key_block_inverted(zero_key, index, genkeyblock);
|
generate_single_key_block_inverted(zero_key, index, genkeyblock);
|
||||||
|
|
||||||
//NOTE BEFORE UPDATING THE KEY WE NEED TO KEEP IN MIND KEYS ARE XORRED
|
//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
|
//xor the new key against the previously generated key so that we only update the difference
|
||||||
if(index != 0){
|
if(index != 0){
|
||||||
generate_single_key_block_inverted(zero_key, index - 1, genkeyblock_old);
|
generate_single_key_block_inverted(zero_key, index - 1, genkeyblock_old);
|
||||||
for (int i = 0; i < 8 ; i++) {
|
for (int i = 0; i < 8 ; i++) {
|
||||||
xorkeyblock[i] = genkeyblock[i] ^ genkeyblock_old[i];
|
xorkeyblock[i] = genkeyblock[i] ^ genkeyblock_old[i];
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
memcpy(xorkeyblock, genkeyblock, PICOPASS_BLOCK_SIZE);
|
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
|
}//end while
|
||||||
|
|
||||||
|
|
||||||
|
@ -2311,10 +2317,6 @@ restore:
|
||||||
uint8_t partialkey[PICOPASS_BLOCK_SIZE];
|
uint8_t partialkey[PICOPASS_BLOCK_SIZE];
|
||||||
convertToHexArray(bits_found, partialkey);
|
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];
|
uint8_t resetkey[PICOPASS_BLOCK_SIZE];
|
||||||
convertToHexArray(index, resetkey);
|
convertToHexArray(index, resetkey);
|
||||||
|
|
||||||
|
@ -2325,19 +2327,26 @@ restore:
|
||||||
blockno = 3;
|
blockno = 3;
|
||||||
wb[0] = blockno;
|
wb[0] = blockno;
|
||||||
memcpy(wb + 1, resetkey, 8);
|
memcpy(wb + 1, resetkey, 8);
|
||||||
|
|
||||||
doMAC_N(wb, sizeof(wb), div_key2, mac2);
|
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)) {
|
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 {
|
} 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();
|
switch_off();
|
||||||
|
reply_ng(CMD_HF_ICLASS_RECOVER, PM3_SUCCESS, NULL, 0);
|
||||||
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
switch_off();
|
switch_off();
|
||||||
|
reply_ng(CMD_HF_ICLASS_RECOVER, PM3_ESOFT, NULL, 0);
|
||||||
|
|
||||||
}
|
}
|
|
@ -396,32 +396,22 @@ uint32_t get_flash_size(void) {
|
||||||
return flash_size_from_cidr(*AT91C_DBGU_CIDR);
|
return flash_size_from_cidr(*AT91C_DBGU_CIDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to convert an unsigned int to binary string
|
// Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1
|
||||||
void intToBinary(uint8_t num, char *binaryStr, int size) {
|
void convertToHexArray(uint8_t num, uint8_t *partialkey) {
|
||||||
binaryStr[size] = '\0'; // Null-terminate the string
|
char binaryStr[25]; // 24 bits for binary representation + 1 for null terminator
|
||||||
for (int i = size - 1; i >= 0; i--) {
|
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';
|
binaryStr[i] = (num % 2) ? '1' : '0';
|
||||||
num /= 2;
|
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
|
// Split the binary string into groups of 3 and convert to hex
|
||||||
for (int i = 0; i < 8 ; i++) {
|
for (int i = 0; i < 8 ; i++) {
|
||||||
char group[4];
|
char group[4];
|
||||||
strncpy(group, binaryStr + i * 3, 3);
|
strncpy(group, binaryStr + i * 3, 3);
|
||||||
group[3] = '\0'; // Null-terminate the group string
|
group[3] = '\0'; // Null-terminate the group string
|
||||||
partialkey[i] = binaryToHex(group);
|
partialkey[i] = (uint8_t)strtoul(group, NULL, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -88,8 +88,6 @@ int hex2binarray(char *target, char *source);
|
||||||
int hex2binarray_n(char *target, const char *source, int sourcelen);
|
int hex2binarray_n(char *target, const char *source, int sourcelen);
|
||||||
int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex);
|
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 convertToHexArray(uint8_t num, uint8_t *partialKey);
|
||||||
|
|
||||||
void LED(int led, int ms);
|
void LED(int led, int ms);
|
||||||
|
|
|
@ -3874,9 +3874,9 @@ static int CmdHFiClassRecover(uint8_t key[8]) {
|
||||||
WaitForResponse(CMD_HF_ICLASS_RECOVER, &resp);
|
WaitForResponse(CMD_HF_ICLASS_RECOVER, &resp);
|
||||||
|
|
||||||
if (resp.status == PM3_SUCCESS) {
|
if (resp.status == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "iCLASS Recover " _GREEN_("successful"));
|
PrintAndLogEx(SUCCESS, "iCLASS Key Bits Recovery " _GREEN_("successful"));
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "iCLASS Recover " _RED_("failed"));
|
PrintAndLogEx(WARNING, "iCLASS Key Bits Recovery " _RED_("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(payload);
|
free(payload);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue