mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-11 02:31:23 +08:00
legic: info command available for more sources, add memory check.
This commit is contained in:
parent
1cc19c3429
commit
03f6ad02f3
1 changed files with 153 additions and 39 deletions
|
@ -57,54 +57,28 @@ static bool legic_xor(uint8_t *data, uint16_t cardsize) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output BigBuf and deobfuscate LEGIC RF tag data.
|
||||
* This is based on information given in the talk held
|
||||
* by Henryk Ploetz and Karsten Nohl at 26c3
|
||||
*/
|
||||
static int CmdLegicInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic info",
|
||||
"Gets information from a LEGIC Prime tag like systemarea, user areas, etc",
|
||||
"hf legic info");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
static int decode_and_print_memory(uint16_t card_size, const uint8_t *input_buffer) {
|
||||
int i = 0, k = 0, segmentNum = 0, segment_len = 0, segment_flag = 0;
|
||||
int crc = 0, wrp = 0, wrc = 0;
|
||||
uint8_t stamp_len = 0;
|
||||
uint16_t datalen = 0;
|
||||
char token_type[6] = {0, 0, 0, 0, 0, 0};
|
||||
int dcf = 0;
|
||||
int bIsSegmented = 0;
|
||||
int return_value = PM3_SUCCESS;
|
||||
|
||||
// tagtype
|
||||
legic_card_select_t card;
|
||||
if (legic_get_type(&card) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Failed to identify tagtype");
|
||||
return PM3_ESOFT;
|
||||
if (!(card_size == LEGIC_PRIME_MIM22 || card_size == LEGIC_PRIME_MIM256 || card_size == LEGIC_PRIME_MIM1024)) {
|
||||
PrintAndLogEx(FAILED, "Bytebuffer is not any known legic card size! (MIM22, MIM256, MIM1024)");
|
||||
return_value = PM3_EFAILED;
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Reading full tag memory of " _YELLOW_("%d") " bytes...", card.cardsize);
|
||||
|
||||
// allocate receiver buffer
|
||||
uint8_t *data = calloc(card.cardsize, sizeof(uint8_t));
|
||||
// copy input buffer into newly allocated buffer, because the existing code mutates the data inside.
|
||||
uint8_t *data = calloc(card_size, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
PrintAndLogEx(WARNING, "Cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen);
|
||||
if (status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Failed reading memory");
|
||||
free(data);
|
||||
return status;
|
||||
}
|
||||
memcpy(data, input_buffer, card_size);
|
||||
|
||||
// Output CDF System area (9 bytes) plus remaining header area (12 bytes)
|
||||
crc = data[4];
|
||||
|
@ -217,9 +191,10 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
uint32_t segCalcCRC = 0;
|
||||
uint32_t segCRC = 0;
|
||||
|
||||
// Not Data card?
|
||||
if (dcf > 60000)
|
||||
// Not a data card by dcf or too small to contain data (MIM22)?
|
||||
if (dcf > 60000 || card_size == LEGIC_PRIME_MIM22) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, _CYAN_("ADF: User Area"));
|
||||
PrintAndLogEx(NORMAL, "------------------------------------------------------");
|
||||
|
@ -231,6 +206,13 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
|
||||
// decode segments
|
||||
for (segmentNum = 1; segmentNum < 128; segmentNum++) {
|
||||
// for decoding the segment header we need at least 4 bytes left in buffer
|
||||
if ((i + 4) > card_size) {
|
||||
PrintAndLogEx(FAILED, "Cannot read segment header, because the input buffer is too small. "
|
||||
"Please check that the data is correct and properly aligned. ");
|
||||
return_value = PM3_EOUTOFBOUND;
|
||||
goto out;
|
||||
}
|
||||
segment_len = ((data[i + 1] ^ crc) & 0x0f) * 256 + (data[i] ^ crc);
|
||||
segment_flag = ((data[i + 1] ^ crc) & 0xf0) >> 4;
|
||||
wrp = (data[i + 2] ^ crc);
|
||||
|
@ -277,6 +259,14 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
|
||||
i += 5;
|
||||
|
||||
// for printing the complete segment we need at least wrc + wrp_len + remain_seg_payload_len bytes
|
||||
if ((i + wrc + wrp_len + remain_seg_payload_len) > card_size) {
|
||||
PrintAndLogEx(FAILED, "Cannot read segment body, because the input buffer is too small. "
|
||||
"Please check that the data is correct and properly aligned. ");
|
||||
return_value = PM3_EOUTOFBOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hasWRC) {
|
||||
PrintAndLogEx(SUCCESS, "\nWRC protected area: (I %d | K %d| WRC %d)", i, k, wrc);
|
||||
PrintAndLogEx(NORMAL, "\nrow | data");
|
||||
|
@ -330,7 +320,6 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
} // end for loop
|
||||
|
||||
} else {
|
||||
|
||||
// Data start point on unsegmented cards
|
||||
i = 8;
|
||||
|
||||
|
@ -340,7 +329,7 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
bool hasWRC = (wrc > 0);
|
||||
bool hasWRP = (wrp > wrc);
|
||||
int wrp_len = (wrp - wrc);
|
||||
int remain_seg_payload_len = (card.cardsize - 22 - wrp);
|
||||
int remain_seg_payload_len = (card_size - 22 - wrp);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Unsegmented card - WRP: %02u, WRC: %02u, RD: %01u",
|
||||
wrp,
|
||||
|
@ -348,6 +337,14 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
(data[7] & 0x80) >> 7
|
||||
);
|
||||
|
||||
// for printing the complete segment we need at least wrc + wrp_len + remain_seg_payload_len bytes
|
||||
if ((i + wrc + wrp_len + remain_seg_payload_len) > card_size) {
|
||||
PrintAndLogEx(FAILED, "Cannot read segment body, because the input buffer is too small. "
|
||||
"Please check that the data is correct and properly aligned. ");
|
||||
return_value = PM3_EOUTOFBOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hasWRC) {
|
||||
PrintAndLogEx(SUCCESS, "WRC protected area: (I %d | WRC %d)", i, wrc);
|
||||
PrintAndLogEx(NORMAL, "\nrow | data");
|
||||
|
@ -386,6 +383,55 @@ static int CmdLegicInfo(const char *Cmd) {
|
|||
}
|
||||
|
||||
out:
|
||||
free(data);
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output BigBuf and deobfuscate LEGIC RF tag data.
|
||||
* This is based on information given in the talk held
|
||||
* by Henryk Ploetz and Karsten Nohl at 26c3
|
||||
*/
|
||||
static int CmdLegicInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic info",
|
||||
"Gets information from a LEGIC Prime tag like systemarea, user areas, etc",
|
||||
"hf legic info");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint16_t datalen = 0;
|
||||
|
||||
// tagtype
|
||||
legic_card_select_t card;
|
||||
if (legic_get_type(&card) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Failed to identify tagtype");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Reading full tag memory of " _YELLOW_("%d") " bytes...", card.cardsize);
|
||||
|
||||
// allocate receiver buffer
|
||||
uint8_t *data = calloc(card.cardsize, sizeof(uint8_t));
|
||||
if (!data) {
|
||||
PrintAndLogEx(WARNING, "Cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen);
|
||||
if (status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Failed reading memory");
|
||||
free(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
decode_and_print_memory(card.cardsize, data);
|
||||
|
||||
free(data);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -1174,6 +1220,41 @@ static int CmdLegicEView(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdLegicEInfo(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic einfo",
|
||||
"It decodes and displays emulator memory",
|
||||
"hf legic einfo\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
size_t card_size = LEGIC_PRIME_MIM256;
|
||||
|
||||
uint8_t *dump = calloc(card_size, sizeof(uint8_t));
|
||||
if (dump == NULL) {
|
||||
PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "downloading emulator memory");
|
||||
if (GetFromDevice(BIG_BUF_EML, dump, card_size, 0, NULL, 0, NULL, 2500, false) == false) {
|
||||
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||
free(dump);
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
decode_and_print_memory(card_size, dump);
|
||||
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdLegicWipe(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic wipe",
|
||||
|
@ -1290,6 +1371,37 @@ static int CmdLegicView(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdLegicDInfo(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic view",
|
||||
"Print a LEGIC Prime dump file (bin/eml/json)",
|
||||
"hf legic view -f hf-legic-01020304-dump.bin"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("f", "file", "<fn>", "Filename of dump"),
|
||||
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);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// read dump file
|
||||
uint8_t *dump = NULL;
|
||||
size_t bytes_read = 0;
|
||||
int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, LEGIC_PRIME_MIM1024);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
decode_and_print_memory(bytes_read, dump);
|
||||
|
||||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
|
@ -1306,9 +1418,11 @@ static command_t CommandTable[] = {
|
|||
{"eload", CmdLegicELoad, IfPm3Legicrf, "Load binary dump to emulator memory"},
|
||||
{"esave", CmdLegicESave, IfPm3Legicrf, "Save emulator memory to binary file"},
|
||||
{"eview", CmdLegicEView, IfPm3Legicrf, "View emulator memory"},
|
||||
{"einfo", CmdLegicEInfo, IfPm3Legicrf, "Display deobfuscated and decoded emulator memory"},
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("utils") " ---------------------"},
|
||||
{"crc", CmdLegicCalcCrc, AlwaysAvailable, "Calculate Legic CRC over given bytes"},
|
||||
{"view", CmdLegicView, AlwaysAvailable, "Display content from tag dump file"},
|
||||
{"dinfo", CmdLegicDInfo, AlwaysAvailable, "Display deobfuscated and decoded content from tag dump file"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue