hitag2 crack1,2 fixes. The error response I never seen, the fct to hex2bin prone to overflows. This should make both attack vectors more stable

This commit is contained in:
iceman1001 2024-05-20 14:22:55 +02:00
commit 00407383fe

View file

@ -30,9 +30,6 @@
#include "cmd.h" #include "cmd.h"
#include "lfadc.h" #include "lfadc.h"
// iceman: I have never seen the tag respond with this. Might be something buffer in rfidler.
const static uint8_t ERROR_RESPONSE[] = { 0xF4, 0x02, 0x88, 0x9C };
// #define READP0CMD "1100000111" // #define READP0CMD "1100000111"
const static uint8_t read_p0_cmd[] = {1, 1, 0, 0, 0, 0, 0, 1, 1, 1}; const static uint8_t read_p0_cmd[] = {1, 1, 0, 0, 0, 0, 0, 1, 1, 1};
@ -114,22 +111,18 @@ static bool hitag2crack_read_page(uint8_t *resp, uint8_t pagenum, uint8_t *nrar,
uint8_t e_resp[4]; uint8_t e_resp[4];
if (hitag2crack_send_e_cmd(e_resp, nrar, e_cmd, 10)) { if (hitag2crack_send_e_cmd(e_resp, nrar, e_cmd, 10)) {
// check if it is valid OBS! uint8_t e_response[32] = {0};
if (memcmp(e_resp, ERROR_RESPONSE, 4)) { uint8_t response[32] = {0};
uint8_t e_response[32]; // convert to binarray
uint8_t response[32]; hex2binarray_n((char *)e_response, (char *)e_resp, 4);
// decrypt response
hitag2crack_xor(response, e_response, keybits + 10, 32);
// convert to binarray // convert to hexstring
hex2binarray((char *)e_response, (char *)e_resp); binarray2hex(response, 32, resp);
// decrypt response
hitag2crack_xor(response, e_response, keybits + 10, 32);
// convert to hexstring return true;
binarray2hex(response, 32, resp);
return true;
}
} }
return false; return false;
@ -195,6 +188,7 @@ static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd,
// encrypted command. // encrypted command.
uint8_t guess[10]; uint8_t guess[10];
memcpy(guess, e_firstcmd, 10); memcpy(guess, e_firstcmd, 10);
if (a) { if (a) {
guess[5] = !guess[5]; guess[5] = !guess[5];
guess[0] = !guess[0]; guess[0] = !guess[0];
@ -216,21 +210,17 @@ static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd,
} }
// try the guess // try the guess
uint8_t resp[4]; uint8_t resp[4] = {0};
if (hitag2crack_send_e_cmd(resp, nrar, guess, 10)) { if (hitag2crack_send_e_cmd(resp, nrar, guess, 10)) {
// check if it was valid // convert response to binarray
if (memcmp(resp, ERROR_RESPONSE, 4)) { // response should been encrypted UID
uint8_t e_uid[32] = {0};
hex2binarray_n((char *)e_uid, (char *)resp, 4);
// convert response to binarray // test if the guess was 'read page 0' command
// response should been encrypted UID if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
uint8_t e_uid[32]; return true;
hex2binarray((char *)e_uid, (char *)resp);
// test if the guess was 'read page 0' command
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
return true;
}
} }
} }
} }
@ -257,29 +247,15 @@ static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd, uint8_t *nrar) {
for (uint8_t g = 0; g < 2; g++) { for (uint8_t g = 0; g < 2; g++) {
// build binarray // build binarray
//uint8_t guess[10] = { a, b, c, d, e, 0, g, 0, 0, 0 }; uint8_t guess[10] = { a, b, c, d, e, 0, g, 0, 0, 0 };
uint8_t guess[10];
guess[0] = a;
guess[1] = b;
guess[2] = c;
guess[3] = d;
guess[4] = e;
guess[5] = 0;
guess[6] = g;
guess[7] = 0;
guess[8] = 0;
guess[9] = 0;
// send guess // send guess
uint8_t resp[4]; uint8_t resp[4] = {0};
if (hitag2crack_send_e_cmd(resp, nrar, guess, sizeof(guess))) { if (hitag2crack_send_e_cmd(resp, nrar, guess, sizeof(guess))) {
// check if it was valid // return the guess as the encrypted command
if (memcmp(resp, ERROR_RESPONSE, 4)) { memcpy(e_cmd, guess, 10);
// return the guess as the encrypted command return true;
memcpy(e_cmd, guess, 10);
return true;
}
} }
} }
} }
@ -374,7 +350,7 @@ void ht2_crack2(uint8_t *nrar_hex) {
// find the 'read page 0' command and recover key stream // find the 'read page 0' command and recover key stream
// get uid as hexstring // get uid as hexstring
uint8_t uid_hex[4]; uint8_t uid_hex[4] = {0};
if (ht2_read_uid(uid_hex, false, false, false) != PM3_SUCCESS) { if (ht2_read_uid(uid_hex, false, false, false) != PM3_SUCCESS) {
BigBuf_free(); BigBuf_free();
reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0); reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0);
@ -387,7 +363,7 @@ void ht2_crack2(uint8_t *nrar_hex) {
DbpString("looking for encrypted command"); DbpString("looking for encrypted command");
// find a valid encrypted command // find a valid encrypted command
uint8_t e_firstcmd[10]; uint8_t e_firstcmd[10] = {0};
if (hitag2crack_find_valid_e_cmd(e_firstcmd, c2->nrar) == false) { if (hitag2crack_find_valid_e_cmd(e_firstcmd, c2->nrar) == false) {
BigBuf_free(); BigBuf_free();
reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0); reply_ng(CMD_LF_HITAG2_CRACK_2, PM3_EFAILED, NULL, 0);
@ -415,7 +391,7 @@ void ht2_crack2(uint8_t *nrar_hex) {
hitag2crack_xor(c2->e_ext_cmd + 20, read_p0_cmd, c2->keybits + 20, 10); hitag2crack_xor(c2->e_ext_cmd + 20, read_p0_cmd, c2->keybits + 20, 10);
hitag2crack_xor(c2->e_ext_cmd + 30, read_p0_cmd, c2->keybits + 30, 10); hitag2crack_xor(c2->e_ext_cmd + 30, read_p0_cmd, c2->keybits + 30, 10);
Dbprintf("Recovered " _YELLOW_("%i") " bits of keystream", kslen); Dbprintf("Recovered " _YELLOW_("%4i") " bits of keystream", kslen);
// Get UID // Get UID
if (ht2_read_uid(NULL, true, false, true) != PM3_SUCCESS) { if (ht2_read_uid(NULL, true, false, true) != PM3_SUCCESS) {
@ -452,6 +428,8 @@ void ht2_crack2(uint8_t *nrar_hex) {
kslen += 10; kslen += 10;
} }
Dbprintf("Recovered " _YELLOW_("%4i") " bits of keystream", kslen);
lf_hitag_crack_response_t *packet = (lf_hitag_crack_response_t *)BigBuf_calloc(sizeof(lf_hitag_crack_response_t)); lf_hitag_crack_response_t *packet = (lf_hitag_crack_response_t *)BigBuf_calloc(sizeof(lf_hitag_crack_response_t));
packet->status = 1; packet->status = 1;