Merge pull request #2556 from douniwan5788/hts_rdbl

fix: `lf hitag hts rdbl` read by page
This commit is contained in:
Iceman 2024-10-04 17:49:45 +03:00 committed by GitHub
commit cd4c2834a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 114 additions and 31 deletions

View file

@ -1282,7 +1282,16 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) {
goto read_end;
}
int pageNum = 0;
if (payload->page >= tag.max_page) {
DBG Dbprintf("Warning, read page "_YELLOW_("%d") " > max page("_YELLOW_("%d") ") ", payload->page, tag.max_page);
}
int page_addr = payload->page;
int page_index = 0;
lf_hts_read_response_t card = {0};
memcpy(card.config_page.asBytes, tag.data.pages[HITAGS_CONFIG_PADR], HITAGS_PAGE_SIZE);
while ((BUTTON_PRESS() == false) && (data_available() == false)) {
@ -1294,7 +1303,7 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) {
size_t txlen = 0;
uint8_t cmd = HITAGS_READ_PAGE;
txlen = concatbits(tx, txlen, &cmd, 0, 4);
uint8_t addr = pageNum;
uint8_t addr = page_addr;
txlen = concatbits(tx, txlen, &addr, 0, 8);
uint8_t crc = CRC8Hitag1Bits(tx, txlen);
txlen = concatbits(tx, txlen, &crc, 0, 8);
@ -1303,33 +1312,37 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) {
if (rxlen != 40) {
DBG Dbprintf("Read page failed!");
status = PM3_ERFTRANS;
goto read_end;
card.pages_reason[page_index] = -4;
// status = PM3_ERFTRANS;
// goto read_end;
page_addr++;
page_index++;
continue;
}
//save received data - 40 bits
for (int i = 0; i < 4 && i < rxlen; i++) { // set page bytes from received bits
tag.data.pages[pageNum][i] = rx[i];
}
memcpy(card.pages[page_index], rx, HITAGS_PAGE_SIZE);
if (g_dbglevel >= DBG_EXTENDED) {
if (tag.data.s.auth && tag.data.s.LKP && pageNum == 1) {
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0,
tag.data.pages[pageNum][2],
tag.data.pages[pageNum][1],
tag.data.pages[pageNum][0]);
} else {
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum,
tag.data.pages[pageNum][3],
tag.data.pages[pageNum][2],
tag.data.pages[pageNum][1],
tag.data.pages[pageNum][0]);
if (page_addr == 1 && (payload->cmd == HTSF_KEY || payload->cmd == HTSF_CHALLENGE) && card.config_page.s.auth == 1) {
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X", page_addr,
card.pages[page_index][0],
card.pages[page_index][1],
card.pages[page_index][2],
pwdh0);
} else { // HTSF_PLAIN or HTSF_82xx can read the full page
DBG Dbprintf("Page[%2d]: %02X %02X %02X %02X", page_addr,
card.pages[page_index][0],
card.pages[page_index][1],
card.pages[page_index][2],
card.pages[page_index][3]);
}
}
pageNum++;
page_addr++;
page_index++;
//display key and password if possible
if (pageNum == 2 && tag.data.s.auth == 1 && tag.data.s.LKP) {
if (page_addr == 2 && card.config_page.s.auth == 1 && card.config_page.s.LKP) {
if (payload->cmd == HTSF_KEY) {
DBG Dbprintf("Page[ 2]: %02X %02X %02X %02X",
payload->key[1],
@ -1343,16 +1356,22 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) {
payload->key[3],
payload->key[2]
);
card.pages_reason[page_index++] = 1;
card.pages_reason[page_index++] = 1;
} else {
//if the authentication is done with a challenge the key and password are unknown
DBG Dbprintf("Page[ 2]: __ __ __ __");
DBG Dbprintf("Page[ 3]: __ __ __ __");
card.pages_reason[page_index++] = -4;
card.pages_reason[page_index++] = -4;
}
// since page 2+3 are not accessible when LKP == 1 and AUT == 1 fastforward to next readable page
pageNum = 4;
page_addr = 4;
}
if (pageNum >= tag.max_page) {
if (payload->page_count == 0) {
if (page_addr > tag.max_page) break;
} else if (page_addr > 255 || page_addr >= payload->page + payload->page_count) {
break;
}
}
@ -1361,7 +1380,7 @@ read_end:
hts_stop_clock();
set_tracing(false);
lf_finalize(ledcontrol);
reply_reason(CMD_LF_HITAGS_READ, status, reason,(uint8_t *)tag.data.pages, sizeof(tag.data.pages));
reply_reason(CMD_LF_HITAGS_READ, status, reason, (uint8_t *)&card, sizeof(card));
}
/*

View file

@ -236,7 +236,8 @@ static int CmdLFHitagSRead(const char *Cmd) {
arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
arg_lit0(NULL, "crypto", "crypto mode"),
arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
arg_int1("p", "page", "<dec>", "page address to read from"),
arg_int0("p", "page", "<dec>", "page address to read from"),
arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the s page (default: 1)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -245,10 +246,25 @@ static int CmdLFHitagSRead(const char *Cmd) {
if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
// int page = arg_get_int_def(ctx, 5, 0); // not implemented yet
uint32_t page = arg_get_int_def(ctx, 5, 0);
if (page > 255) {
PrintAndLogEx(WARNING, "Page address Invalid.");
return PM3_EINVARG;
}
uint32_t count = arg_get_int_def(ctx, 6, 1);
if (count > HITAGS_MAX_PAGES) {
PrintAndLogEx(WARNING, "No more than 64 pages can be read at once.");
return PM3_EINVARG;
}
CLIParserFree(ctx);
packet.page = page;
packet.page_count = count;
clearCommandBuffer();
SendCommandNG(CMD_LF_HITAGS_READ, (uint8_t *) &packet, sizeof(packet));
@ -264,9 +280,9 @@ static int CmdLFHitagSRead(const char *Cmd) {
return PM3_ESOFT;
}
uint8_t *data = resp.data.asBytes;
lf_hts_read_response_t *card = (lf_hts_read_response_t *)resp.data.asBytes;
hitags_config_t config = hitags_config_unpack(&data[HITAGS_PAGE_SIZE * HITAGS_CONFIG_PADR]);
hitags_config_t config = hitags_config_unpack(card->config_page.asBytes);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
@ -275,11 +291,28 @@ static int CmdLFHitagSRead(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Data") " ----------------------------------");
PrintAndLogEx(INFO, "adr| 00 01 02 03 | ascii");
PrintAndLogEx(INFO, "---+-------------+-------");
const int hts_mem_sizes[] = {4, 32, 256, 256};
uint32_t size = hts_mem_sizes[config.memory_type];
const int hts_mem_sizes[] = {1, 8, 64, 64};
if (count == 0) {
count = hts_mem_sizes[config.memory_type] - page;
}
print_hex_break(data, size, HITAGS_PAGE_SIZE);
// int page_end = page + count;
// page_end = MIN(page_end, 255);
for (int i = 0; i < count; ++i) {
int page_addr = page + i;
if (page_addr > 255) {
break;
}
if (card->pages_reason[i] >= 0)
PrintAndLogEx(SUCCESS, "%02u | %s", page_addr, sprint_hex_ascii(card->pages[i], HITAGS_PAGE_SIZE));
else
PrintAndLogEx(INFO, "%02u | -- -- -- -- | read failed reason: " _YELLOW_("%d"), page_addr, card->pages_reason[i]);
}
return PM3_SUCCESS;
}

View file

@ -67,7 +67,8 @@ typedef enum {
typedef struct {
hitag_function cmd;
int16_t page;
uint8_t page;
uint8_t page_count;
uint8_t data[HITAGS_PAGE_SIZE];
uint8_t NrAr[HITAG_NRAR_SIZE];
// unaligned access to key as uint64_t will abort.
@ -165,4 +166,34 @@ struct hitagS_tag {
} PACKED;
typedef struct {
union {
uint8_t asBytes[HITAGS_PAGE_SIZE];
struct {
// page 1
uint8_t CON0;
// con1
bool LKP : 1; // 0 = page2/3 read write 1 =page2/3 read only in Plain mode and no access in authenticate mode
bool LCON : 1; // 0 = con1/2 read write 1 =con1 read only and con2 OTP
int TTFM : 2; // the number of pages that are sent to the RWD
int TTFDR : 2; // data rate in TTF Mode
bool TTFC : 1; // Transponder Talks first coding. 0 = Manchester 1 = Biphase
bool auth : 1; // 0 = Plain 1 = Auth
// con2
// 0 = read write 1 = read only
bool LCK0 : 1; // page48-63
bool LCK1 : 1; // page32-47
bool LCK2 : 1; // page24-31
bool LCK3 : 1; // page16-23
bool LCK4 : 1; // page12-15
bool LCK5 : 1; // page8-11
bool LCK6 : 1; // page6/7
bool LCK7 : 1; // page4/5
// reserved/pwdh0
uint8_t pwdh0;
}s;
} config_page;
int8_t pages_reason[HITAGS_MAX_PAGES];
uint8_t pages[HITAGS_MAX_PAGES][HITAGS_PAGE_SIZE];
} PACKED lf_hts_read_response_t;
#endif