mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
Merge pull request #2556 from douniwan5788/hts_rdbl
fix: `lf hitag hts rdbl` read by page
This commit is contained in:
commit
cd4c2834a6
3 changed files with 114 additions and 31 deletions
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue