Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: lf hitag hts rdbl read by page #2556

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions armsrc/hitagS.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {

Expand All @@ -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);
Expand All @@ -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],
Expand All @@ -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;
}
}
Expand All @@ -1361,7 +1380,7 @@ void hts_read(const lf_hitag_data_t *payload, bool ledcontrol) {
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));
}

/*
Expand Down
47 changes: 40 additions & 7 deletions client/src/cmdlfhitaghts.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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));

Expand All @@ -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") " ---------------------------");
Expand All @@ -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[] = {1, 8, 64, 64};

if (count == 0) {
count = hts_mem_sizes[config.memory_type] - page;
}

const int hts_mem_sizes[] = {4, 32, 256, 256};
uint32_t size = hts_mem_sizes[config.memory_type];
// int page_end = page + count;
// page_end = MIN(page_end, 255);

print_hex_break(data, size, HITAGS_PAGE_SIZE);
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;
}
Expand Down
33 changes: 32 additions & 1 deletion include/hitag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Loading