mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
added lf hitag view command to view dump files
This commit is contained in:
parent
5a828bd6a8
commit
53a5087d67
3 changed files with 225 additions and 134 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added `lf hitag view` - now supports viewing of dump files (@iceman1001)
|
||||||
- Changed `lf hitag dump --ns` - now support nosave flag (@iceman1001)
|
- Changed `lf hitag dump --ns` - now support nosave flag (@iceman1001)
|
||||||
- Added `hf xerox rdbl` - read block of a Fuji/Xerox tag (@iceman1001)
|
- Added `hf xerox rdbl` - read block of a Fuji/Xerox tag (@iceman1001)
|
||||||
- Added a xerox trace file, thanks @jeroenSteen, (@iceman1001)
|
- Added a xerox trace file, thanks @jeroenSteen, (@iceman1001)
|
||||||
|
@ -20,8 +21,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Changed `hw readmem` to allow larger reads, write to file and better hex viewer (@martian01010)
|
- Changed `hw readmem` to allow larger reads, write to file and better hex viewer (@martian01010)
|
||||||
- Added `CMD_READ_MEM_DOWNLOAD` and `CMD_READ_MEM_DOWNLOADED` to osimage and bootloader (@martian01010)
|
- Added `CMD_READ_MEM_DOWNLOAD` and `CMD_READ_MEM_DOWNLOADED` to osimage and bootloader (@martian01010)
|
||||||
- Changed `hf mfu info` - now correctly identifies NTAG I2C tags (@icemann1001)
|
- Changed `hf mfu info` - now correctly identifies NTAG I2C tags (@icemann1001)
|
||||||
- Changed `hf 14b dump/view` - now supports `z` flag for dense output (@iceman1001)
|
- Changed `hf 14b dump/view` - now supports `-z` flag for dense output (@iceman1001)
|
||||||
- Changed `hf xerox dump/view` - now supports `z` flag for dense output (@iceman1001)
|
- Changed `hf xerox dump/view` - now supports `-z` flag for dense output (@iceman1001)
|
||||||
- Changed `hf mfu dump/view/eview` - now supports `-z` flag for dense output (@iceman1001)
|
- Changed `hf mfu dump/view/eview` - now supports `-z` flag for dense output (@iceman1001)
|
||||||
- Added `data crypto` to encrypt and decrypt data in the proxmark client using built-in methods (@team-orangeBlue)
|
- Added `data crypto` to encrypt and decrypt data in the proxmark client using built-in methods (@team-orangeBlue)
|
||||||
- Changed `hf tune` and `lf tune` - Added an option to show statistical data after tuning (@wh201906)
|
- Changed `hf tune` and `lf tune` - Added an option to show statistical data after tuning (@wh201906)
|
||||||
|
@ -44,9 +45,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Changed `hf 15 findafi` - improved the params (@iceman1001)
|
- Changed `hf 15 findafi` - improved the params (@iceman1001)
|
||||||
- Changed `hf 15 rdbl/rdmulti/dump` - should handle 4 vs 8 bytes block sizes in cards (@iceman1001)
|
- Changed `hf 15 rdbl/rdmulti/dump` - should handle 4 vs 8 bytes block sizes in cards (@iceman1001)
|
||||||
- Changed `hf 15 *` - all 15 commands now uses NG packets (@iceman1001)
|
- Changed `hf 15 *` - all 15 commands now uses NG packets (@iceman1001)
|
||||||
- Changed `hf 15 raw` - now supports "-k" keep field on and "-s" select (@iceman1001)
|
- Changed `hf 15 raw` - now supports `-k` keep field on and `-s` select (@iceman1001)
|
||||||
- Changed `prefs set client.debug` - now also toggles the client side APDU logging (@iceman1001)
|
- Changed `prefs set client.debug` - now also toggles the client side APDU logging (@iceman1001)
|
||||||
- Changed `hf 14b sriwrbl` - now supports --force to override block checks. Thanks @gentilkiwi for the idea! (@iceman1001)
|
- Changed `hf 14b sriwrbl` - now supports `--force` to override block checks. Thanks @gentilkiwi for the idea! (@iceman1001)
|
||||||
- Changed `hf 14b sriwrbl` - now tries to verify the write (@iceman1001)
|
- Changed `hf 14b sriwrbl` - now tries to verify the write (@iceman1001)
|
||||||
- Changed `hf 14b apdu` - now supports tearoff (@iceman1001)
|
- Changed `hf 14b apdu` - now supports tearoff (@iceman1001)
|
||||||
- Fixed `hf 14b raw` - fixed a potential write out of bounds. (@iceman1001)
|
- Fixed `hf 14b raw` - fixed a potential write out of bounds. (@iceman1001)
|
||||||
|
|
|
@ -332,8 +332,7 @@ static int CmdLFHitagSim(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_hitag2_paxton(const uint8_t *data) {
|
||||||
static void printHitag2PaxtonDowngrade(const uint8_t *data) {
|
|
||||||
|
|
||||||
uint64_t bytes = 0;
|
uint64_t bytes = 0;
|
||||||
uint64_t num = 0;
|
uint64_t num = 0;
|
||||||
|
@ -359,116 +358,150 @@ static void printHitag2PaxtonDowngrade(const uint8_t *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
|
PrintAndLogEx(INFO, "");
|
||||||
PrintAndLogEx(SUCCESS, "Paxton id: %lu | 0x%lx", paxton_id, paxton_id);
|
PrintAndLogEx(INFO, "--- " _CYAN_("Possible de-scramble patterns") " -------------");
|
||||||
|
PrintAndLogEx(SUCCESS, "Paxton id... %" PRIu64 " | 0x%" PRIx64, paxton_id, paxton_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printHitag2Configuration(uint8_t config) {
|
static void print_hitag2_configuration(uint32_t uid, uint8_t config) {
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||||
|
PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid);
|
||||||
|
PrintAndLogEx(SUCCESS, "TYPE... " _GREEN_("%s"), getHitagTypeStr(uid));
|
||||||
|
|
||||||
char msg[100];
|
char msg[100];
|
||||||
memset(msg, 0, sizeof(msg));
|
memset(msg, 0, sizeof(msg));
|
||||||
|
|
||||||
char bits[9];
|
uint8_t bits[8 + 1] = {0};
|
||||||
char *bs = bits;
|
num_to_bytebits(config, 8, bits);
|
||||||
for (uint8_t i = 0 ; i < 8 ; i++) {
|
const char *bs = sprint_bytebits_bin(bits, 8);
|
||||||
snprintf(bs, sizeof(bits) - i, "%1d", (config >> (7 - i)) & 1);
|
|
||||||
bs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\n\nHitag2 tag information ");
|
|
||||||
PrintAndLogEx(INFO, "------------------------------------");
|
|
||||||
|
|
||||||
//configuration byte
|
//configuration byte
|
||||||
PrintAndLogEx(SUCCESS, "Config byte : 0x%02X [ %s ]", config, bits);
|
PrintAndLogEx(SUCCESS, "");
|
||||||
|
PrintAndLogEx(SUCCESS, "Config byte... 0x%02X", config);
|
||||||
|
PrintAndLogEx(SUCCESS, " %s", bs);
|
||||||
|
|
||||||
// encoding
|
|
||||||
strcat(msg, "Encoding : ");
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 0, 4, "RFU"));
|
||||||
if (config & 0x1) {
|
|
||||||
strcat(msg + strlen(msg), _YELLOW_("Biphase"));
|
if (config & 0x8) {
|
||||||
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_YELLOW, bs, 8, 4, 1, "Crypto mode"));
|
||||||
} else {
|
} else {
|
||||||
strcat(msg + strlen(msg), _YELLOW_("Manchester"));
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 4, 1, "Password mode"));
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "%s", msg);
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
// version
|
// version
|
||||||
strcat(msg, "Coding in HITAG 2 operation: %s");
|
uint8_t foo = ((config & 0x6) >> 1);
|
||||||
uint8_t foo = (config & 0x6) >> 1;
|
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 0:
|
case 0:
|
||||||
PrintAndLogEx(SUCCESS, "Version : public mode B, Coding: biphase");
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Public mode B, Coding: biphase"));
|
||||||
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
PrintAndLogEx(SUCCESS, "Version : public mode A, Coding: manchester");
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Public mode A, Coding: manchester"));
|
||||||
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
PrintAndLogEx(SUCCESS, "Version : public mode C, Coding: biphase");
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Public mode C, Coding: biphase"));
|
||||||
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
PrintAndLogEx(SUCCESS, "Version : Hitag2");
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Hitag2"));
|
||||||
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
// mode
|
// encoding
|
||||||
strcat(msg, "Tag is in : ");
|
if (config & 0x01) {
|
||||||
if (config & 0x8) {
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "Biphase"));
|
||||||
strcat(msg + strlen(msg), _YELLOW_("Crypto mode"));
|
|
||||||
} else {
|
} else {
|
||||||
strcat(msg + strlen(msg), _YELLOW_("Password mode"));
|
PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "Manchester"));
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "%s", msg);
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
// page access
|
}
|
||||||
strcat(msg, "Page 6,7 : ");
|
|
||||||
if (config & 0x10) {
|
|
||||||
strcat(msg + strlen(msg), "read only");
|
|
||||||
} else {
|
|
||||||
strcat(msg + strlen(msg), _GREEN_("RW"));
|
|
||||||
}
|
|
||||||
PrintAndLogEx(SUCCESS, "%s", msg);
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
// page access
|
const char* annotation[] = {
|
||||||
strcat(msg, "Page 4,5 : ");
|
"UID", "Pwd", "Key/Pwd", "Config",
|
||||||
if (config & 0x20) {
|
"User", "User", "User", "User",
|
||||||
strcat(msg + strlen(msg), "read only");
|
"User", "User", "User", "User"
|
||||||
} else {
|
};
|
||||||
strcat(msg + strlen(msg), _GREEN_("RW"));
|
|
||||||
}
|
|
||||||
PrintAndLogEx(SUCCESS, "%s", msg);
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
// OTP
|
static void print_hitag2_blocks(uint8_t *d, uint16_t n) {
|
||||||
strcat(msg, "Page 3 : ");
|
|
||||||
if (config & 0x40) {
|
|
||||||
strcat(msg + strlen(msg), "read only. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE"));
|
|
||||||
} else {
|
|
||||||
strcat(msg + strlen(msg), _GREEN_("RW"));
|
|
||||||
}
|
|
||||||
PrintAndLogEx(SUCCESS, "%s", msg);
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
|
|
||||||
// OTP
|
PrintAndLogEx(INFO, "");
|
||||||
|
PrintAndLogEx(INFO, "-----------------------------------------------");
|
||||||
|
PrintAndLogEx(INFO, "block# | data | ascii | lck | Info");
|
||||||
|
PrintAndLogEx(INFO, "---------+-------------+-------+-----+---------");
|
||||||
|
|
||||||
|
uint8_t config = d[HITAG2_CONFIG_OFFSET];
|
||||||
|
uint8_t blocks = (n / HITAG_BLOCK_SIZE);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < blocks; ++i) {
|
||||||
|
|
||||||
|
char lckstr[20] = {0};
|
||||||
|
sprintf(lckstr, " ");
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
sprintf(lckstr, "%s", _RED_("L "));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (config & 0x80) {
|
||||||
|
sprintf(lckstr, "%s", _RED_("L "));
|
||||||
|
} else {
|
||||||
|
sprintf(lckstr, "%s", _GREEN_("RW"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
if (config & 0x80) {
|
if (config & 0x80) {
|
||||||
strcat(msg, "Page 1 : " _RED_("locked") "\n");
|
|
||||||
|
|
||||||
strcat(msg + strlen(msg), "Page 2 : ");
|
|
||||||
if (config & 0x8) {
|
if (config & 0x8) {
|
||||||
strcat(msg + strlen(msg), _RED_("locked"));
|
sprintf(lckstr, "%s", _RED_("L "));
|
||||||
} else {
|
} else {
|
||||||
strcat(msg + strlen(msg), "read only");
|
sprintf(lckstr, "%s", _RED_("R "));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strcat(msg, "Page 1,2 : " _GREEN_("RW"));
|
sprintf(lckstr, "%s", _GREEN_("RW"));
|
||||||
}
|
}
|
||||||
PrintAndLogEx(SUCCESS, "%s", msg);
|
break;
|
||||||
PrintAndLogEx(INFO, "------------------------------------");
|
case 3:
|
||||||
|
// OTP Page 3.
|
||||||
|
if (config & 0x40) {
|
||||||
|
sprintf(lckstr, "%s", _RED_("R "));
|
||||||
|
//. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE"));
|
||||||
|
} else {
|
||||||
|
sprintf(lckstr, "%s", _GREEN_("RW"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
if (config & 0x20) {
|
||||||
|
sprintf(lckstr, "%s", _RED_("R "));
|
||||||
|
} else {
|
||||||
|
sprintf(lckstr, "%s", _GREEN_("RW"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
if (config & 0x10) {
|
||||||
|
sprintf(lckstr, "%s", _RED_("R "));
|
||||||
|
} else {
|
||||||
|
sprintf(lckstr, "%s", _GREEN_("RW"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s | %s"
|
||||||
|
, i
|
||||||
|
, i
|
||||||
|
, sprint_hex(d + (i * HITAG_BLOCK_SIZE), HITAG_BLOCK_SIZE)
|
||||||
|
, sprint_ascii(d + (i * HITAG_BLOCK_SIZE), HITAG_BLOCK_SIZE)
|
||||||
|
, lckstr
|
||||||
|
, annotation[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PrintAndLogEx(INFO, "---------+-------------+-------+-----+---------");
|
||||||
|
PrintAndLogEx(INFO, " L = Locked, "_GREEN_("RW") " = Read Write, R = Read Only");
|
||||||
|
PrintAndLogEx(INFO, " FI = Fixed / Irreversible");
|
||||||
|
PrintAndLogEx(INFO, "-----------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool getHitag2Uid(uint32_t *uid) {
|
static bool getHitag2Uid(uint32_t *uid) {
|
||||||
|
@ -477,7 +510,7 @@ static bool getHitag2Uid(uint32_t *uid) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_LF_HITAG_READER, RHT2F_UID_ONLY, 0, 0, &htd, sizeof(htd));
|
SendCommandMIX(CMD_LF_HITAG_READER, RHT2F_UID_ONLY, 0, 0, &htd, sizeof(htd));
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -487,8 +520,9 @@ static bool getHitag2Uid(uint32_t *uid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid)
|
if (uid) {
|
||||||
*uid = bytes_to_num(resp.data.asBytes, 4);
|
*uid = bytes_to_num(resp.data.asBytes, HITAG_UID_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -509,24 +543,18 @@ static int CmdLFHitagInfo(const char *Cmd) {
|
||||||
|
|
||||||
// read UID
|
// read UID
|
||||||
uint32_t uid = 0;
|
uint32_t uid = 0;
|
||||||
if (getHitag2Uid(&uid) == false)
|
if (getHitag2Uid(&uid) == false) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%08X"), uid);
|
|
||||||
PrintAndLogEx(SUCCESS, " TYPE: " _GREEN_("%s"), getHitagTypeStr(uid));
|
|
||||||
|
|
||||||
// how to determine Hitag types?
|
// how to determine Hitag types?
|
||||||
// read block3, get configuration byte.
|
// read block3, get configuration byte.
|
||||||
|
|
||||||
// common configurations.
|
// common configurations.
|
||||||
// printHitag2Configuration(0x06);
|
print_hitag2_configuration( uid, 0x06 );
|
||||||
//printHitag2Configuration( 0x0E );
|
// print_hitag2_configuration( uid, 0x0E );
|
||||||
//printHitag2Configuration( 0x02 );
|
// print_hitag2_configuration( uid, 0x02 );
|
||||||
//printHitag2Configuration( 0x00 );
|
// print_hitag2_configuration( uid, 0x00 );
|
||||||
//printHitag2Configuration( 0x04 );
|
// print_hitag2_configuration( uid, 0x04 );
|
||||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,12 +728,11 @@ static int CmdLFHitagReader(const char *Cmd) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t id = bytes_to_num(resp.data.asBytes, 4);
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id);
|
uint32_t uid = bytes_to_num(data, HITAG_UID_SIZE);
|
||||||
printHitag2Configuration(data[4 * 3]);
|
print_hitag2_configuration(uid, data[HITAG_BLOCK_SIZE * 3]);
|
||||||
print_hex_break(data, 48, 4);
|
print_hex_break(data, HITAG2_MAX_BYTE_SIZE, HITAG_BLOCK_SIZE);
|
||||||
printHitag2PaxtonDowngrade(data);
|
print_hitag2_paxton(data);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +800,6 @@ static int CmdLFHitag2CheckChallenges(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int CmdLFHitagWriter(const char *Cmd) {
|
static int CmdLFHitagWriter(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "lf hitag wrbl",
|
CLIParserInit(&ctx, "lf hitag wrbl",
|
||||||
|
@ -985,6 +1011,7 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||||
arg_lit0(NULL, "crypto", "crypto mode"),
|
arg_lit0(NULL, "crypto", "crypto mode"),
|
||||||
arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
|
arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
|
||||||
arg_str0("f", "file", "<fn>", "specify file name"),
|
arg_str0("f", "file", "<fn>", "specify file name"),
|
||||||
|
arg_lit0(NULL, "ns", "no save to file"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
@ -1006,7 +1033,7 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||||
bool use_nrar = nalen > 0;
|
bool use_nrar = nalen > 0;
|
||||||
bool use_crypto = arg_get_lit(ctx, 3);
|
bool use_crypto = arg_get_lit(ctx, 3);
|
||||||
|
|
||||||
uint8_t key[6];
|
uint8_t key[HITAG_CRYPTOKEY_SIZE];
|
||||||
int keylen = 0;
|
int keylen = 0;
|
||||||
res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &keylen);
|
res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &keylen);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
|
@ -1018,6 +1045,7 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
|
||||||
|
bool nosave = arg_get_lit(ctx, 6);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -1036,19 +1064,21 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete options
|
// complete options
|
||||||
if (keylen == 4) {
|
if (keylen == HITAG_PASSWORD_SIZE) {
|
||||||
use_pwd = true;
|
use_pwd = true;
|
||||||
}
|
}
|
||||||
if (keylen == 6) {
|
if (keylen == HITAG_CRYPTOKEY_SIZE) {
|
||||||
use_crypto = true;
|
use_crypto = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set default key / pwd
|
||||||
if ((keylen == 0) && use_pwd) {
|
if ((keylen == 0) && use_pwd) {
|
||||||
memcpy(key, "MIKR", 4);
|
memcpy(key, "MIKR", HITAG_PASSWORD_SIZE);
|
||||||
keylen = 4;
|
keylen = HITAG_PASSWORD_SIZE;
|
||||||
}
|
}
|
||||||
if ((keylen == 0) && use_crypto) {
|
if ((keylen == 0) && use_crypto) {
|
||||||
memcpy(key, "ONMIKR", 6);
|
memcpy(key, "ONMIKR", HITAG_CRYPTOKEY_SIZE);
|
||||||
keylen = 6;
|
keylen = HITAG_CRYPTOKEY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check coherence
|
// check coherence
|
||||||
|
@ -1081,11 +1111,11 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||||
if (use_ht2 && use_pwd) {
|
if (use_ht2 && use_pwd) {
|
||||||
htf = RHT2F_PASSWORD;
|
htf = RHT2F_PASSWORD;
|
||||||
memcpy(htd.pwd.password, key, sizeof(htd.pwd.password));
|
memcpy(htd.pwd.password, key, sizeof(htd.pwd.password));
|
||||||
PrintAndLogEx(INFO, "Authenticating to Hitag 2 in Password mode");
|
PrintAndLogEx(INFO, "Authenticating to Hitag2 in Password mode");
|
||||||
} else if (use_ht2 && use_crypto) {
|
} else if (use_ht2 && use_crypto) {
|
||||||
htf = RHT2F_CRYPTO;
|
htf = RHT2F_CRYPTO;
|
||||||
memcpy(htd.crypto.key, key, sizeof(htd.crypto.key));
|
memcpy(htd.crypto.key, key, sizeof(htd.crypto.key));
|
||||||
PrintAndLogEx(INFO, "Authenticating to Hitag 2 in Crypto mode");
|
PrintAndLogEx(INFO, "Authenticating to Hitag2 in Crypto mode");
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "Sorry, not yet implemented");
|
PrintAndLogEx(WARNING, "Sorry, not yet implemented");
|
||||||
return PM3_ENOTIMPL;
|
return PM3_ENOTIMPL;
|
||||||
|
@ -1103,34 +1133,77 @@ static int CmdLFHitag2Dump(const char *Cmd) {
|
||||||
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
|
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *data = resp.data.asBytes;
|
uint8_t *data = resp.data.asBytes;
|
||||||
|
|
||||||
if (data == NULL)
|
// block3, 1 byte
|
||||||
return PM3_ESOFT;
|
uint32_t uid = bytes_to_num(data, HITAG_UID_SIZE);
|
||||||
|
print_hitag2_configuration(uid, data[HITAG_BLOCK_SIZE * 3]);
|
||||||
|
print_hitag2_blocks(data, HITAG2_MAX_BYTE_SIZE);
|
||||||
|
print_hitag2_paxton(data);
|
||||||
|
|
||||||
uint32_t id = bytes_to_num(resp.data.asBytes, 4);
|
if (nosave) {
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id);
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "Called with no save option");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (fnlen < 1) {
|
if (fnlen < 1) {
|
||||||
char *fptr = filename;
|
char *fptr = filename;
|
||||||
fptr += snprintf(filename, sizeof(filename), "lf-hitag-");
|
fptr += snprintf(filename, sizeof(filename), "lf-hitag-");
|
||||||
FillFileNameByUID(fptr, data, "-dump", 4);
|
FillFileNameByUID(fptr, data, "-dump", HITAG_UID_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// block3, 1 byte
|
pm3_save_dump(filename, data, HITAG2_MAX_BYTE_SIZE, jsfHitag);
|
||||||
printHitag2Configuration(data[4 * 3]);
|
|
||||||
|
|
||||||
// print data
|
|
||||||
print_hex_break(data, 48, 4);
|
|
||||||
|
|
||||||
printHitag2PaxtonDowngrade(data);
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Dumping tag memory...");
|
|
||||||
|
|
||||||
pm3_save_dump(filename, data, 48, jsfHitag);
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdLFHitagView(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf hitag view",
|
||||||
|
"Print a HITAG dump file (bin/eml/json)",
|
||||||
|
"lf hitag view -f lf-hitag-01020304-dump.bin"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
|
||||||
|
arg_lit0("v", "verbose", "Verbose output"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
int fnlen = 0;
|
||||||
|
char filename[FILE_PATH_SIZE];
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
// read dump file
|
||||||
|
uint8_t *dump = NULL;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, HITAG2_MAX_BYTE_SIZE);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read < HITAG2_MAX_BYTE_SIZE) {
|
||||||
|
PrintAndLogEx(ERR, "Error, dump file is too small");
|
||||||
|
free(dump);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
// block3, 1 byte
|
||||||
|
uint8_t config = dump[HITAG_BLOCK_SIZE * 3];
|
||||||
|
uint32_t uid = bytes_to_num(dump, HITAG_UID_SIZE);
|
||||||
|
print_hitag2_configuration(uid, config);
|
||||||
|
print_hitag2_paxton(dump);
|
||||||
|
}
|
||||||
|
print_hitag2_blocks(dump, HITAG2_MAX_BYTE_SIZE);
|
||||||
|
free(dump);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// Annotate HITAG protocol
|
// Annotate HITAG protocol
|
||||||
void annotateHitag1(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response) {
|
void annotateHitag1(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response) {
|
||||||
|
@ -1197,6 +1270,7 @@ static command_t CommandTable[] = {
|
||||||
{"info", CmdLFHitagInfo, IfPm3Hitag, "Hitag 2 tag information"},
|
{"info", CmdLFHitagInfo, IfPm3Hitag, "Hitag 2 tag information"},
|
||||||
{"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag 2 tag"},
|
{"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag 2 tag"},
|
||||||
{"read", CmdLFHitagReader, IfPm3Hitag, "Read Hitag memory"},
|
{"read", CmdLFHitagReader, IfPm3Hitag, "Read Hitag memory"},
|
||||||
|
{"view", CmdLFHitagView, AlwaysAvailable, "Display content from tag dump file"},
|
||||||
{"wrbl", CmdLFHitagWriter, IfPm3Hitag, "Write a block (page) in Hitag memory"},
|
{"wrbl", CmdLFHitagWriter, IfPm3Hitag, "Write a block (page) in Hitag memory"},
|
||||||
{"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication"},
|
{"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication"},
|
||||||
{"cc", CmdLFHitagSCheckChallenges, IfPm3Hitag, "Hitag S: test all provided challenges"},
|
{"cc", CmdLFHitagSCheckChallenges, IfPm3Hitag, "Hitag S: test all provided challenges"},
|
||||||
|
@ -1223,6 +1297,8 @@ int readHitagUid(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit) {
|
uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit) {
|
||||||
if (nbit < 9) return 2;
|
if (nbit < 9) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
return (CRC8Hitag1Bits(d, nbit) == 0);
|
return (CRC8Hitag1Bits(d, nbit) == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,20 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define HITAG_CRYPTOKEY_SIZE 6
|
||||||
|
#define HITAG_PASSWORD_SIZE 4
|
||||||
|
#define HITAG_UID_SIZE 4
|
||||||
|
#define HITAG_BLOCK_SIZE 4
|
||||||
|
#define HITAG2_MAX_BYTE_SIZE 48
|
||||||
|
// need to see which limits these cards has
|
||||||
|
#define HITAG1_MAX_BYTE_SIZE 64
|
||||||
|
#define HITAGS_MAX_BYTE_SIZE 64
|
||||||
|
#define HITAGU_MAX_BYTE_SIZE 64
|
||||||
|
|
||||||
|
#define HITAG2_CONFIG_BLOCK 3
|
||||||
|
#define HITAG2_CONFIG_OFFSET (HITAG_BLOCK_SIZE * HITAG2_CONFIG_BLOCK)
|
||||||
|
|
||||||
int CmdLFHitag(const char *Cmd);
|
int CmdLFHitag(const char *Cmd);
|
||||||
|
|
||||||
int readHitagUid(void);
|
int readHitagUid(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue