mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
Merge pull request #2699 from Nya0/hts-restore
lf hitag hts restore & 82xx improvements
This commit is contained in:
commit
7843de1988
3 changed files with 247 additions and 1 deletions
|
@ -357,6 +357,8 @@ static int CmdLFHitagSRead(const char *Cmd) {
|
||||||
|
|
||||||
// access right
|
// access right
|
||||||
if (page_addr == HITAGS_UID_PADR) {
|
if (page_addr == HITAGS_UID_PADR) {
|
||||||
|
PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);\
|
||||||
|
} else if (packet.cmd == HTSF_82xx && page_addr > 40) { // using an 82xx (pages>40 are RO)
|
||||||
PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
|
PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
|
||||||
} else if (page_addr == HITAGS_CONFIG_PADR) {
|
} else if (page_addr == HITAGS_CONFIG_PADR) {
|
||||||
if (card->config_page.s.LCON)
|
if (card->config_page.s.LCON)
|
||||||
|
@ -454,6 +456,7 @@ static int CmdLFHitagSDump(const char *Cmd) {
|
||||||
" - default key 4F4E4D494B52 (ONMIKR)\n\n"
|
" - default key 4F4E4D494B52 (ONMIKR)\n\n"
|
||||||
" 8268/8310 password mode: \n"
|
" 8268/8310 password mode: \n"
|
||||||
" - default password BBDD3399\n",
|
" - default password BBDD3399\n",
|
||||||
|
"lf hitag hts dump --82xx -> use def pwd\n"
|
||||||
"lf hitag hts dump --82xx -k BBDD3399 -> pwd mode\n"
|
"lf hitag hts dump --82xx -k BBDD3399 -> pwd mode\n"
|
||||||
"lf hitag hts dump --crypto -> use def crypto\n"
|
"lf hitag hts dump --crypto -> use def crypto\n"
|
||||||
"lf hitag hts dump -k 4F4E4D494B52 -> crypto mode\n"
|
"lf hitag hts dump -k 4F4E4D494B52 -> crypto mode\n"
|
||||||
|
@ -534,6 +537,225 @@ static int CmdLFHitagSDump(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdLFHitagSRestore(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf hitag hts restore",
|
||||||
|
"Restore a dump file onto Hitag S tag\n"
|
||||||
|
" Crypto mode: \n"
|
||||||
|
" - key format ISK high + ISK low\n"
|
||||||
|
" - default key 4F4E4D494B52 (ONMIKR)\n\n"
|
||||||
|
" 8268/8310 password mode: \n"
|
||||||
|
" - default password BBDD3399\n",
|
||||||
|
"lf hitag hts restore -f myfile --82xx -> use def pwd\n"
|
||||||
|
"lf hitag hts restore -f myfile --82xx -k BBDD3399 -> pwd mode\n"
|
||||||
|
"lf hitag hts restore -f myfile --crypto -> use def crypto\n"
|
||||||
|
"lf hitag hts restore -f myfile -k 4F4E4D494B52 -> crypto mode\n"
|
||||||
|
"lf hitag hts restore -f myfile --nrar 0102030411223344\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("8", "82xx", "8268/8310 mode"),
|
||||||
|
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_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"),
|
||||||
|
arg_str0("f", "file", "<fn>", "specify file name"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
lf_hitag_data_t packet;
|
||||||
|
memset(&packet, 0, sizeof(packet));
|
||||||
|
|
||||||
|
if (process_hitags_common_args(ctx, &packet) < 0) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fnlen = 0;
|
||||||
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
|
||||||
|
if (fnlen == 0) {
|
||||||
|
PrintAndLogEx(ERR, "Must specify a file");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read dump file
|
||||||
|
uint32_t *dump = NULL;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
if (pm3_load_dump(filename, (void **)&dump, &bytes_read, jsfHitag) != PM3_SUCCESS) {
|
||||||
|
return PM3_EFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read config to determine memory size and other stuff
|
||||||
|
packet.page = HITAGS_CONFIG_PADR;
|
||||||
|
packet.page_count = 1;
|
||||||
|
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_LF_HITAGS_READ, (uint8_t *)&packet, sizeof(packet));
|
||||||
|
|
||||||
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_LF_HITAGS_READ, &resp, 2000) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.status != PM3_SUCCESS) {
|
||||||
|
print_error(resp.reason);
|
||||||
|
free(dump);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
lf_hts_read_response_t *config = (lf_hts_read_response_t *)resp.data.asBytes;
|
||||||
|
hitags_config_t tag_config = config->config_page.s;
|
||||||
|
|
||||||
|
const int hts_mem_sizes[] = {1, 8, 64, 64};
|
||||||
|
int mem_size = hts_mem_sizes[tag_config.MEMT] * HITAGS_PAGE_SIZE;
|
||||||
|
|
||||||
|
if (bytes_read != mem_size) {
|
||||||
|
free(dump);
|
||||||
|
PrintAndLogEx(FAILED, "Wrong length of dump file. Expected %d bytes, got %zu", mem_size, bytes_read);
|
||||||
|
return PM3_EFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* dump_bytes = (uint8_t*)dump;
|
||||||
|
bool auth_changed = false;
|
||||||
|
|
||||||
|
for (int page = packet.page_count + 1; page < hts_mem_sizes[tag_config.MEMT]; page++) { // skip config page
|
||||||
|
|
||||||
|
if (packet.cmd == HTSF_82xx && page > 40) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(WARNING, "Using " _YELLOW_("82xx") ", Pages " _YELLOW_("41-63") " will be skipped");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t offset = page * HITAGS_PAGE_SIZE;
|
||||||
|
|
||||||
|
packet.page = page;
|
||||||
|
memcpy(packet.data, &dump_bytes[offset], HITAGS_PAGE_SIZE);
|
||||||
|
|
||||||
|
PrintAndLogEx(INPLACE, " Writing page "_YELLOW_("%d")", data: " _GREEN_("%02X %02X %02X %02X"), page,
|
||||||
|
dump_bytes[offset],
|
||||||
|
dump_bytes[offset + 1],
|
||||||
|
dump_bytes[offset + 2],
|
||||||
|
dump_bytes[offset + 3]);
|
||||||
|
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *)&packet, sizeof(packet));
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 2000) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.status != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(FAILED, "Write failed for page %d", page);
|
||||||
|
print_error(resp.reason);
|
||||||
|
free(dump);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (page) {
|
||||||
|
case 2: // auth first page
|
||||||
|
if (packet.cmd == HTSF_82xx) {
|
||||||
|
if (memcmp(packet.pwd, &dump_bytes[offset], HITAGS_PAGE_SIZE) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auth_changed = true;
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(WARNING, "Password Changed! Old: " _BACK_BLUE_("%02X %02X %02X %02X") ", New: "_BACK_BLUE_("%02X %02X %02X %02X"),
|
||||||
|
packet.pwd[0], packet.pwd[1], packet.pwd[2], packet.pwd[3],
|
||||||
|
dump_bytes[offset], dump_bytes[offset + 1],
|
||||||
|
dump_bytes[offset + 2], dump_bytes[offset + 3]);
|
||||||
|
|
||||||
|
|
||||||
|
memcpy(packet.pwd, &dump_bytes[offset], HITAG_PASSWORD_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Using new password for subsequent writes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: // crypto mode
|
||||||
|
if (packet.cmd == HTSF_KEY) {
|
||||||
|
|
||||||
|
if (memcmp(packet.key, &dump_bytes[offset - HITAGS_PAGE_SIZE], HITAG_CRYPTOKEY_SIZE) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auth_changed = true;
|
||||||
|
|
||||||
|
memcpy(packet.key, &dump_bytes[offset - HITAGS_PAGE_SIZE], HITAG_CRYPTOKEY_SIZE);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(WARNING, "New key detected: " _BACK_BLUE_("%02X %02X %02X %02X %02X %02X"),
|
||||||
|
packet.key[0], packet.key[1], packet.key[2],
|
||||||
|
packet.key[3], packet.key[4], packet.key[5]);
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Using new key for subsequent writes");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore config page at end
|
||||||
|
size_t config_offset = HITAGS_PAGE_SIZE * 1; // page 1
|
||||||
|
packet.page = HITAGS_CONFIG_PADR;
|
||||||
|
memcpy(packet.data, &dump_bytes[HITAGS_PAGE_SIZE], HITAGS_PAGE_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Applying "_YELLOW_("restored config: ") _GREEN_("%02X %02X %02X %02X"),
|
||||||
|
dump_bytes[config_offset],
|
||||||
|
dump_bytes[config_offset + 1],
|
||||||
|
dump_bytes[config_offset + 2],
|
||||||
|
dump_bytes[config_offset + 3]);
|
||||||
|
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *)&packet, sizeof(packet));
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 2000) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.status != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(FAILED, "Failed to apply config");
|
||||||
|
print_error(resp.reason);
|
||||||
|
free(dump);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Write process completed");
|
||||||
|
|
||||||
|
if (auth_changed) {
|
||||||
|
if (packet.cmd == HTSF_82xx) {
|
||||||
|
PrintAndLogEx(SUCCESS, "New Password: " _BACK_BLUE_("%02X %02X %02X %02X"),
|
||||||
|
packet.pwd[0], packet.pwd[1], packet.pwd[2], packet.pwd[3]);
|
||||||
|
} else if (packet.cmd == HTSF_KEY) {
|
||||||
|
PrintAndLogEx(SUCCESS, "New Key: " _BACK_BLUE_("%02X %02X %02X %02X %02X %02X"),
|
||||||
|
packet.key[0], packet.key[1], packet.key[2],
|
||||||
|
packet.key[3], packet.key[4], packet.key[5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdLFHitagSWrite(const char *Cmd) {
|
static int CmdLFHitagSWrite(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "lf hitag hts wrbl",
|
CLIParserInit(&ctx, "lf hitag hts wrbl",
|
||||||
|
@ -544,6 +766,7 @@ static int CmdLFHitagSWrite(const char *Cmd) {
|
||||||
" 8268/8310 password mode: \n"
|
" 8268/8310 password mode: \n"
|
||||||
" - default password BBDD3399\n",
|
" - default password BBDD3399\n",
|
||||||
" lf hitag hts wrbl -p 6 -d 01020304 -> Hitag S/8211, plain mode\n"
|
" lf hitag hts wrbl -p 6 -d 01020304 -> Hitag S/8211, plain mode\n"
|
||||||
|
" lf hitag hts wrbl -p 6 -d 01020304 --82xx -> use def pwd\n"
|
||||||
" lf hitag hts wrbl -p 6 -d 01020304 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
|
" lf hitag hts wrbl -p 6 -d 01020304 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
|
||||||
" lf hitag hts wrbl -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
|
" lf hitag hts wrbl -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
|
||||||
" lf hitag hts wrbl -p 6 -d 01020304 --crypto -> Hitag S, crypto mode, default key\n"
|
" lf hitag hts wrbl -p 6 -d 01020304 --crypto -> Hitag S, crypto mode, default key\n"
|
||||||
|
@ -705,7 +928,8 @@ static command_t CommandTable[] = {
|
||||||
{"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("General") " ------------------------"},
|
{"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("General") " ------------------------"},
|
||||||
{"reader", CmdLFHitagSReader, IfPm3Hitag, "Act like a Hitag S reader"},
|
{"reader", CmdLFHitagSReader, IfPm3Hitag, "Act like a Hitag S reader"},
|
||||||
{"rdbl", CmdLFHitagSRead, IfPm3Hitag, "Read Hitag S page"},
|
{"rdbl", CmdLFHitagSRead, IfPm3Hitag, "Read Hitag S page"},
|
||||||
{"dump", CmdLFHitagSDump, IfPm3Hitag, "Dump Hitag S pages to a file"},
|
{"dump", CmdLFHitagSDump, IfPm3Hitag, "Dump Hitag S pages to a file"},
|
||||||
|
{"restore", CmdLFHitagSRestore,IfPm3Hitag, "Restore Hitag S memory from dump file"},
|
||||||
{"wrbl", CmdLFHitagSWrite, IfPm3Hitag, "Write Hitag S page"},
|
{"wrbl", CmdLFHitagSWrite, IfPm3Hitag, "Write Hitag S page"},
|
||||||
{"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("Simulation") " -----------------------"},
|
{"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("Simulation") " -----------------------"},
|
||||||
{"sim", CmdLFHitagSSim, IfPm3Hitag, "Simulate Hitag S transponder"},
|
{"sim", CmdLFHitagSSim, IfPm3Hitag, "Simulate Hitag S transponder"},
|
||||||
|
|
|
@ -9838,6 +9838,27 @@
|
||||||
],
|
],
|
||||||
"usage": "lf hitag hts dump [-h8] [--nrar <hex>] [--crypto] [-k <hex>] [-m <dec>] [-f <fn>] [--ns]"
|
"usage": "lf hitag hts dump [-h8] [--nrar <hex>] [--crypto] [-k <hex>] [-m <dec>] [-f <fn>] [--ns]"
|
||||||
},
|
},
|
||||||
|
"lf hitag hts restore": {
|
||||||
|
"command": "lf hitag hts restore",
|
||||||
|
"description": "Restore a dump file onto Hitag S tag Crypto mode: - key format ISK high + ISK low - default key 4F4E4D494B52 (ONMIKR) 8268/8310 password mode: - default password BBDD3399",
|
||||||
|
"notes": [
|
||||||
|
"lf hitag hts restore -f myfile --82xx -k BBDD3399 -> pwd mode",
|
||||||
|
"lf hitag hts restore -f myfile --crypto -> use def crypto",
|
||||||
|
"lf hitag hts restore -f myfile -k 4F4E4D494B52 -> crypto mode",
|
||||||
|
"lf hitag hts restore -f myfile --nrar 0102030411223344"
|
||||||
|
],
|
||||||
|
"offline": false,
|
||||||
|
"options": [
|
||||||
|
"-h, --help This help",
|
||||||
|
"-8, --82xx 8268/8310 mode",
|
||||||
|
"--nrar <hex> nonce / answer writer, 8 hex bytes",
|
||||||
|
"--crypto crypto mode",
|
||||||
|
"-k, --key <hex> pwd or key, 4 or 6 hex bytes",
|
||||||
|
"-m, --mode <dec> response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)",
|
||||||
|
"-f, --file <fn> specify file name"
|
||||||
|
],
|
||||||
|
"usage": "lf hitag hts restore [-h8] [--nrar <hex>] [--crypto] [-k <hex>] [-m <dec>] [-f <fn>]"
|
||||||
|
},
|
||||||
"lf hitag hts help": {
|
"lf hitag hts help": {
|
||||||
"command": "lf hitag hts help",
|
"command": "lf hitag hts help",
|
||||||
"description": "help This help list List Hitag S trace history --------------------------------------------------------------------------------------- lf hitag hts list available offline: yes Alias of `trace list -t hitags` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
|
"description": "help This help list List Hitag S trace history --------------------------------------------------------------------------------------- lf hitag hts list available offline: yes Alias of `trace list -t hitags` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
|
||||||
|
|
|
@ -1084,6 +1084,7 @@ Check column "offline" for their availability.
|
||||||
|`lf hitag hts rdbl `|N |`Read Hitag S page`
|
|`lf hitag hts rdbl `|N |`Read Hitag S page`
|
||||||
|`lf hitag hts dump `|N |`Dump Hitag S pages to a file`
|
|`lf hitag hts dump `|N |`Dump Hitag S pages to a file`
|
||||||
|`lf hitag hts wrbl `|N |`Write Hitag S page`
|
|`lf hitag hts wrbl `|N |`Write Hitag S page`
|
||||||
|
|`lf hitag hts restore `|N |`Restore Hitag S memory from a dump file`
|
||||||
|`lf hitag hts sim `|N |`Simulate Hitag S transponder`
|
|`lf hitag hts sim `|N |`Simulate Hitag S transponder`
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue