mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
Merge pull request #1128 from tcprst/legic_cliparser
hf legic crc, rdbl, wrbl, sim, info, reader - now use cliparser
This commit is contained in:
commit
4ac50615a9
6 changed files with 158 additions and 289 deletions
|
@ -582,14 +582,14 @@ function writeToTag(tag)
|
||||||
-- write pm3-buffer to Tag
|
-- write pm3-buffer to Tag
|
||||||
for i=1, WriteBytes do
|
for i=1, WriteBytes do
|
||||||
if (i > 7) then
|
if (i > 7) then
|
||||||
cmd = ("hf legic wrbl o %02x d %s "):format(i-1, padString(bytes[i]))
|
cmd = ("hf legic wrbl -o %d -d %s "):format(i-1, padString(bytes[i]))
|
||||||
print(acgreen..cmd..acoff)
|
print(acgreen..cmd..acoff)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
elseif (i == 7) then
|
elseif (i == 7) then
|
||||||
if (writeDCF) then
|
if (writeDCF) then
|
||||||
-- write DCF in reverse order (requires 'mosci-patch')
|
-- write DCF in reverse order (requires 'mosci-patch')
|
||||||
cmd = ('hf legic wrbl o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
cmd = ('hf legic wrbl -o 5 -d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
||||||
print(acgreen..cmd..acoff)
|
print(acgreen..cmd..acoff)
|
||||||
core.console(cmd)
|
core.console(cmd)
|
||||||
core.clearCommandBuffer()
|
core.clearCommandBuffer()
|
||||||
|
|
|
@ -536,7 +536,7 @@ local function main(args)
|
||||||
res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3"
|
res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3, Segment-Header0..3"
|
||||||
res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):"
|
res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):"
|
||||||
res = res .."\n"
|
res = res .."\n"
|
||||||
res = res ..ansicolors.yellow.."hf legic crc d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." u "..newcrc.." c 8"..ansicolors.reset
|
res = res ..ansicolors.yellow.."hf legic crc -d "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26].." --mcc "..newcrc.." -t 8"..ansicolors.reset
|
||||||
-- this can not be calculated without knowing the new MCD, MSN0..2
|
-- this can not be calculated without knowing the new MCD, MSN0..2
|
||||||
print(res)
|
print(res)
|
||||||
end
|
end
|
||||||
|
|
|
@ -109,7 +109,7 @@ int CmdHFSearch(const char *Cmd) {
|
||||||
PROMPT_CLEARLINE;
|
PROMPT_CLEARLINE;
|
||||||
PrintAndLogEx(INPLACE, " Searching for LEGIC tag...");
|
PrintAndLogEx(INPLACE, " Searching for LEGIC tag...");
|
||||||
if (IfPm3Legicrf()) {
|
if (IfPm3Legicrf()) {
|
||||||
if (readLegicUid(false) == PM3_SUCCESS) {
|
if (readLegicUid(false, false) == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") " found\n");
|
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") " found\n");
|
||||||
res = PM3_SUCCESS;
|
res = PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "cliparser.h"
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h" // clearCommandBuffer
|
#include "comms.h" // clearCommandBuffer
|
||||||
#include "cmdtrace.h"
|
#include "cmdtrace.h"
|
||||||
|
@ -27,84 +28,6 @@ static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
#define MAX_LENGTH 1024
|
#define MAX_LENGTH 1024
|
||||||
|
|
||||||
static int usage_legic_calccrc(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Calculates the legic crc8/crc16 on the given data.");
|
|
||||||
PrintAndLogEx(NORMAL, "There must be an even number of hexsymbols as input.\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf legic crc [h] d <data> u <uidcrc> c <8|16>\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
|
||||||
PrintAndLogEx(NORMAL, " d <data> : (hex symbols) bytes to calculate crc over");
|
|
||||||
PrintAndLogEx(NORMAL, " u <uidcrc> : MCC hexbyte");
|
|
||||||
PrintAndLogEx(NORMAL, " c <8|16> : Crc type");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic crc d deadbeef1122"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic crc d deadbeef1122 u 9A c 16"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_legic_rdbl(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Read data from a LEGIC Prime tag\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf legic rdbl [h] [o <offset>] [l <length>] [iv <IV>]\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
|
||||||
PrintAndLogEx(NORMAL, " o <offset> : (hex) offset in data array to start download from");
|
|
||||||
PrintAndLogEx(NORMAL, " l <length> : (hex) number of bytes to read");
|
|
||||||
PrintAndLogEx(NORMAL, " i <IV> : (hex) (optional) Initialization vector to use. Must be odd and 7bits max");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic rdbl o 0 l 16 - reads from byte[0] 0x16 bytes(system header)"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic rdbl o 0 l 4 iv 55 - reads from byte[0] 0x4 bytes with IV 0x55"));
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic rdbl o 0 l 100 iv 55 - reads 0x100 bytes with IV 0x55"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_legic_sim(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated");
|
|
||||||
PrintAndLogEx(NORMAL, "Use " _YELLOW_("`hf legic eload`") " to upload a dump into emulator memory\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf legic sim [h] <tagtype>\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
|
||||||
PrintAndLogEx(NORMAL, " <tagtype> : 0 = MIM22");
|
|
||||||
PrintAndLogEx(NORMAL, " : 1 = MIM256 (default)");
|
|
||||||
PrintAndLogEx(NORMAL, " : 2 = MIM1024");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic sim 2"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_legic_wrbl(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Write data to a LEGIC Prime tag. It autodetects tagsize to make sure size\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf legic wrbl [h] [o <offset>] [d <data (hex symbols)>] [y]\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
|
||||||
PrintAndLogEx(NORMAL, " o <offset> : (hex) offset in data array to start writing");
|
|
||||||
//PrintAndLogEx(NORMAL, " <IV> : (optional) Initialization vector to use (ODD and 7bits)");
|
|
||||||
PrintAndLogEx(NORMAL, " d <data> : (hex symbols) bytes to write ");
|
|
||||||
PrintAndLogEx(NORMAL, " y : Auto-confirm dangerous operations ");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic wrbl o 10 d 11223344 - Write 0x11223344 starting from offset 0x10"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_legic_reader(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Read UID and type information from a LEGIC Prime tag\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf legic reader [h]\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic reader"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_legic_info(void) {
|
|
||||||
PrintAndLogEx(NORMAL, "Reads information from a LEGIC Prime tag like systemarea, user areas etc\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf legic info [h]\n");
|
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
|
||||||
PrintAndLogEx(NORMAL, " h : this help");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
|
||||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic info"));
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
static int usage_legic_dump(void) {
|
static int usage_legic_dump(void) {
|
||||||
PrintAndLogEx(NORMAL, "Read all memory from LEGIC Prime MIM22, MIM256, MIM1024");
|
PrintAndLogEx(NORMAL, "Read all memory from LEGIC Prime MIM22, MIM256, MIM1024");
|
||||||
PrintAndLogEx(NORMAL, "and saves bin/eml/json dump file");
|
PrintAndLogEx(NORMAL, "and saves bin/eml/json dump file");
|
||||||
|
@ -203,9 +126,17 @@ static bool legic_xor(uint8_t *data, uint16_t cardsize) {
|
||||||
* by Henryk Ploetz and Karsten Nohl at 26c3
|
* by Henryk Ploetz and Karsten Nohl at 26c3
|
||||||
*/
|
*/
|
||||||
static int CmdLegicInfo(const char *Cmd) {
|
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");
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
void *argtable[] = {
|
||||||
if (cmdp == 'h') return usage_legic_info();
|
arg_param_begin,
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
int i = 0, k = 0, segmentNum = 0, segment_len = 0, segment_flag = 0;
|
int i = 0, k = 0, segmentNum = 0, segment_len = 0, segment_flag = 0;
|
||||||
int crc = 0, wrp = 0, wrc = 0;
|
int crc = 0, wrp = 0, wrc = 0;
|
||||||
|
@ -526,34 +457,32 @@ out:
|
||||||
// offset in data memory
|
// offset in data memory
|
||||||
// number of bytes to read
|
// number of bytes to read
|
||||||
static int CmdLegicRdbl(const char *Cmd) {
|
static int CmdLegicRdbl(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf legic rdbl",
|
||||||
|
"Read data from a LEGIC Prime tag",
|
||||||
|
"hf legic rdbl -o 0 -l 16 <- reads from byte[0] 16 bytes(system header)\n"
|
||||||
|
"hf legic rdbl -o 0 -l 4 --iv 55 <- reads from byte[0] 4 bytes with IV 0x55\n"
|
||||||
|
"hf legic rdbl -o 0 -l 256 --iv 55 <- reads from byte[0] 256 bytes with IV 0x55");
|
||||||
|
|
||||||
uint32_t offset = 0, len = 0, iv = 1;
|
void *argtable[] = {
|
||||||
bool errors = false;
|
arg_param_begin,
|
||||||
uint8_t cmdp = 0;
|
arg_int1("o", "offset", "<dec>", "offset in data array to start download from"),
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
arg_int1("l", "length", "<dec>", "number of bytes to read"),
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
arg_str0(NULL, "iv", "<hex>", "Initialization vector to use. Must be odd and 7bits max"),
|
||||||
case 'h' :
|
arg_param_end
|
||||||
return usage_legic_rdbl();
|
};
|
||||||
case 'o' :
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
offset = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
|
||||||
cmdp += 2;
|
int offset = arg_get_int_def(ctx, 1, 0);
|
||||||
break;
|
|
||||||
case 'l' :
|
int len = arg_get_int_def(ctx, 2, 0);
|
||||||
len = param_get32ex(Cmd, cmdp + 1, 0, 16);
|
|
||||||
cmdp += 2;
|
int iv_len = 0;
|
||||||
break;
|
uint8_t iv[1] = {0x01}; // formerly uidcrc
|
||||||
case 'i' :
|
|
||||||
iv = param_get32ex(Cmd, cmdp + 1, 1, 16);
|
CLIGetHexWithReturn(ctx, 3, iv, &iv_len);
|
||||||
cmdp += 2;
|
|
||||||
break;
|
CLIParserFree(ctx);
|
||||||
default :
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Validations
|
|
||||||
if (errors || strlen(Cmd) == 0) return usage_legic_rdbl();
|
|
||||||
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
if (len + offset >= MAX_LENGTH) {
|
if (len + offset >= MAX_LENGTH) {
|
||||||
|
@ -571,9 +500,9 @@ static int CmdLegicRdbl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t datalen = 0;
|
uint16_t datalen = 0;
|
||||||
int status = legic_read_mem(offset, len, iv, data, &datalen);
|
int status = legic_read_mem(offset, len, iv[0], data, &datalen);
|
||||||
if (status == PM3_SUCCESS) {
|
if (status == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(NORMAL, "\n ## | 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F");
|
PrintAndLogEx(NORMAL, " ## | 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F");
|
||||||
PrintAndLogEx(NORMAL, "-----+------------------------------------------------------------------------------------------------");
|
PrintAndLogEx(NORMAL, "-----+------------------------------------------------------------------------------------------------");
|
||||||
print_hex_break(data, datalen, 32);
|
print_hex_break(data, datalen, 32);
|
||||||
}
|
}
|
||||||
|
@ -582,9 +511,19 @@ static int CmdLegicRdbl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLegicSim(const char *Cmd) {
|
static int CmdLegicSim(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf legic sim",
|
||||||
|
"Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated",
|
||||||
|
"hf legic sim -t 0 <- Simulate Type MIM22\n"
|
||||||
|
"hf legic sim -t 1 <- Simulate Type MIM256 (default)\n"
|
||||||
|
"hf legic sim -t 2 <- Simulate Type MIM1024");
|
||||||
|
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
void *argtable[] = {
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_legic_sim();
|
arg_param_begin,
|
||||||
|
arg_int0("t", "type", "<dec>", "Tag type to simulate."),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t tagtype;
|
uint8_t tagtype;
|
||||||
|
@ -592,9 +531,13 @@ static int CmdLegicSim(const char *Cmd) {
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
|
|
||||||
payload.send_reply = true;
|
payload.send_reply = true;
|
||||||
payload.tagtype = param_get8ex(Cmd, 0, 1, 10);
|
payload.tagtype = arg_get_int_def(ctx, 1, 1);
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (payload.tagtype > 2) {
|
if (payload.tagtype > 2) {
|
||||||
return usage_legic_sim();
|
PrintAndLogEx(ERR, "Invalid tag type selected.");
|
||||||
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -619,94 +562,37 @@ static int CmdLegicSim(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLegicWrbl(const char *Cmd) {
|
static int CmdLegicWrbl(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf legic wrbl",
|
||||||
|
"Write data to a LEGIC Prime tag. It autodetects tagsize to ensure proper write",
|
||||||
|
"hf legic wrbl -o 0 -d 11223344 <- Write 0x11223344 starting from offset 0)\n"
|
||||||
|
"hf legic wrbl -o 10 -d DEADBEEF <- Write 0xdeadbeef starting from offset 10");
|
||||||
|
|
||||||
uint8_t *data = NULL;
|
void *argtable[] = {
|
||||||
uint8_t cmdp = 0;
|
arg_param_begin,
|
||||||
bool errors = false;
|
arg_int1("o", "offset", "<dec>", "offset in data array to start writing"),
|
||||||
bool autoconfirm = false;
|
arg_str1("d", "data", "<hex>", "data to write"),
|
||||||
int len = 0, bg, en;
|
arg_lit0(NULL, "danger", "Auto-confirm dangerous operations"),
|
||||||
uint32_t offset = 0, IV = 0x55;
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
int offset = arg_get_int_def(ctx, 1, 0);
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
|
||||||
case 'h': {
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'd': {
|
|
||||||
// peek at length of the input string so we can
|
|
||||||
// figure out how many elements to malloc in "data"
|
|
||||||
bg = en = 0;
|
|
||||||
if (param_getptr(Cmd, &bg, &en, cmdp + 1)) {
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len = (en - bg + 1);
|
|
||||||
|
|
||||||
// check that user entered even number of characters
|
int data_len = 0;
|
||||||
// for hex data string
|
uint8_t data[MAX_LENGTH] = {0};
|
||||||
if (len & 1) {
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// limit number of bytes to write. This is not a 'restore' command.
|
CLIGetHexWithReturn(ctx, 2, data, &data_len);
|
||||||
if ((len >> 1) > 100) {
|
|
||||||
PrintAndLogEx(WARNING, "Max bound on 100bytes to write a one time.");
|
|
||||||
PrintAndLogEx(WARNING, "Use the 'hf legic restore' command if you want to write the whole tag at once");
|
|
||||||
errors = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's possible for user to accidentally enter "b" parameter
|
bool autoconfirm = arg_get_lit(ctx, 3);
|
||||||
// more than once - we have to clean previous malloc
|
|
||||||
if (data)
|
|
||||||
free(data);
|
|
||||||
|
|
||||||
data = calloc(len >> 1, sizeof(uint8_t));
|
CLIParserFree(ctx);
|
||||||
if (data == NULL) {
|
|
||||||
PrintAndLogEx(WARNING, "Can't allocate memory. exiting");
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param_gethex(Cmd, cmdp + 1, data, len)) {
|
uint32_t IV = 0x55;
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
len >>= 1;
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'o': {
|
|
||||||
offset = param_get32ex(Cmd, cmdp + 1, 4, 16);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'y': {
|
|
||||||
autoconfirm = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Validations
|
|
||||||
if (errors || cmdp == 0) {
|
|
||||||
if (data)
|
|
||||||
free(data);
|
|
||||||
return usage_legic_wrbl();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OUT-OF-BOUNDS checks
|
// OUT-OF-BOUNDS checks
|
||||||
// UID 4+1 bytes can't be written to.
|
// UID 4+1 bytes can't be written to.
|
||||||
if (offset < 5) {
|
if (offset < 5) {
|
||||||
if (data)
|
|
||||||
free(data);
|
|
||||||
PrintAndLogEx(WARNING, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset);
|
PrintAndLogEx(WARNING, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset);
|
||||||
return PM3_EOUTOFBOUND;
|
return PM3_EOUTOFBOUND;
|
||||||
}
|
}
|
||||||
|
@ -720,8 +606,8 @@ static int CmdLegicWrbl(const char *Cmd) {
|
||||||
|
|
||||||
legic_print_type(card.cardsize, 0);
|
legic_print_type(card.cardsize, 0);
|
||||||
|
|
||||||
if (len + offset > card.cardsize) {
|
if (data_len + offset > card.cardsize) {
|
||||||
PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
|
PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, data_len + offset);
|
||||||
return PM3_EOUTOFBOUND;
|
return PM3_EOUTOFBOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +642,7 @@ static int CmdLegicWrbl(const char *Cmd) {
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_HF_LEGIC_WRITER, offset, len, IV, data, len);
|
SendCommandOLD(CMD_HF_LEGIC_WRITER, offset, data_len, IV, data, data_len);
|
||||||
|
|
||||||
uint8_t timeout = 0;
|
uint8_t timeout = 0;
|
||||||
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||||
|
@ -779,84 +665,45 @@ static int CmdLegicWrbl(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLegicCalcCrc(const char *Cmd) {
|
static int CmdLegicCalcCrc(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf legic crc",
|
||||||
|
"Calculates the legic crc8/crc16 on the given data",
|
||||||
|
"hf legic crc -d deadbeef1122\n"
|
||||||
|
"hf legic crc -d deadbeef1122 --mcc 9A -t 16 <- CRC Type 16");
|
||||||
|
|
||||||
uint8_t *data = NULL;
|
void *argtable[] = {
|
||||||
uint8_t cmdp = 0, uidcrc = 0, type = 0;
|
arg_param_begin,
|
||||||
bool errors = false;
|
arg_str1("d", "data", "<hex>", "bytes to calculate crc over"),
|
||||||
int len = 0;
|
arg_str0(NULL, "mcc", "<hex>", "MCC hex byte (UID CRC)"),
|
||||||
int bg, en;
|
arg_int0("t", "type", "<dec>", "CRC Type (default: 8)"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
int data_len = 0;
|
||||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
uint8_t data[4096] = {0};
|
||||||
case 'd':
|
|
||||||
// peek at length of the input string so we can
|
|
||||||
// figure out how many elements to malloc in "data"
|
|
||||||
bg = en = 0;
|
|
||||||
if (param_getptr(Cmd, &bg, &en, cmdp + 1)) {
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len = (en - bg + 1);
|
|
||||||
|
|
||||||
// check that user entered even number of characters
|
CLIGetHexWithReturn(ctx, 1, data, &data_len);
|
||||||
// for hex data string
|
|
||||||
if (len & 1) {
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's possible for user to accidentally enter "b" parameter
|
int mcc_len = 0;
|
||||||
// more than once - we have to clean previous malloc
|
uint8_t mcc[1] = {0}; // formerly uidcrc
|
||||||
if (data) free(data);
|
|
||||||
data = calloc(len >> 1, sizeof(uint8_t));
|
|
||||||
if (data == NULL) {
|
|
||||||
PrintAndLogEx(WARNING, "Can't allocate memory. exiting");
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param_gethex(Cmd, cmdp + 1, data, len)) {
|
CLIGetHexWithReturn(ctx, 2, mcc, &mcc_len);
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
len >>= 1;
|
int type = arg_get_int_def(ctx, 3, 0);
|
||||||
cmdp += 2;
|
|
||||||
break;
|
CLIParserFree(ctx);
|
||||||
case 'u':
|
|
||||||
uidcrc = param_get8ex(Cmd, cmdp + 1, 0, 16);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
type = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Validations
|
|
||||||
if (errors || cmdp == 0) {
|
|
||||||
if (data) free(data);
|
|
||||||
return usage_legic_calccrc();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 16:
|
case 16:
|
||||||
init_table(CRC_LEGIC);
|
init_table(CRC_LEGIC);
|
||||||
PrintAndLogEx(SUCCESS, "Legic crc16: %X", crc16_legic(data, len, uidcrc));
|
PrintAndLogEx(SUCCESS, "Legic crc16: %X", crc16_legic(data, data_len, mcc[0]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLogEx(SUCCESS, "Legic crc8: %X", CRC8Legic(data, len));
|
PrintAndLogEx(SUCCESS, "Legic crc8: %X", CRC8Legic(data, data_len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data) free(data);
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,12 +801,26 @@ void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) {
|
||||||
SendCommandOLD(CMD_HF_LEGIC_ESET, i, len, 0, src + i, len);
|
SendCommandOLD(CMD_HF_LEGIC_ESET, i, len, 0, src + i, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLegicReader(const char *Cmd) {
|
static int CmdLegicReader(const char *Cmd) {
|
||||||
char cmdp = tolower(param_getchar(Cmd, 0));
|
CLIParserContext *ctx;
|
||||||
if (cmdp == 'h') return usage_legic_reader();
|
CLIParserInit(&ctx, "hf legic reader",
|
||||||
|
"Read UID and type information from a LEGIC Prime tag",
|
||||||
|
"hf legic reader");
|
||||||
|
|
||||||
return readLegicUid(true);
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("@", NULL, "optional - continuous reader mode"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
bool cm = arg_get_lit(ctx, 1);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (cm) {
|
||||||
|
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
return readLegicUid(cm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdLegicDump(const char *Cmd) {
|
static int CmdLegicDump(const char *Cmd) {
|
||||||
|
@ -1438,24 +1299,38 @@ int CmdHFLegic(const char *Cmd) {
|
||||||
return CmdsParse(CommandTable, Cmd);
|
return CmdsParse(CommandTable, Cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int readLegicUid(bool verbose) {
|
int readLegicUid(bool loop, bool verbose) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
legic_card_select_t card;
|
||||||
|
|
||||||
|
int resp = legic_get_type(&card);
|
||||||
|
|
||||||
|
if (loop) {
|
||||||
|
if (resp != PM3_SUCCESS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (resp) {
|
||||||
|
case PM3_EINVARG:
|
||||||
|
return PM3_EINVARG;
|
||||||
|
case PM3_ETIMEOUT:
|
||||||
|
if (verbose) PrintAndLogEx(WARNING, "command execution time out");
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
case PM3_ESOFT:
|
||||||
|
if (verbose) PrintAndLogEx(WARNING, "legic card select failed");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(SUCCESS, " MCD: " _GREEN_("%02X"), card.uid[0]);
|
||||||
|
PrintAndLogEx(SUCCESS, " MSN: " _GREEN_("%s"), sprint_hex(card.uid + 1, sizeof(card.uid) - 1));
|
||||||
|
legic_print_type(card.cardsize, 0);
|
||||||
|
|
||||||
|
} while (loop && kbd_enter_pressed() == false);
|
||||||
|
|
||||||
legic_card_select_t card;
|
|
||||||
switch (legic_get_type(&card)) {
|
|
||||||
case PM3_EINVARG:
|
|
||||||
return PM3_EINVARG;
|
|
||||||
case PM3_ETIMEOUT:
|
|
||||||
if (verbose) PrintAndLogEx(WARNING, "command execution time out");
|
|
||||||
return PM3_ETIMEOUT;
|
|
||||||
case PM3_ESOFT:
|
|
||||||
if (verbose) PrintAndLogEx(WARNING, "legic card select failed");
|
|
||||||
return PM3_ESOFT;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(SUCCESS, " MCD: " _GREEN_("%02X"), card.uid[0]);
|
|
||||||
PrintAndLogEx(SUCCESS, " MSN: " _GREEN_("%s"), sprint_hex(card.uid + 1, sizeof(card.uid) - 1));
|
|
||||||
legic_print_type(card.cardsize, 0);
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
int CmdHFLegic(const char *Cmd);
|
int CmdHFLegic(const char *Cmd);
|
||||||
|
|
||||||
int readLegicUid(bool verbose);
|
int readLegicUid(bool loop, bool verbose);
|
||||||
int legic_print_type(uint32_t tagtype, uint8_t spaces);
|
int legic_print_type(uint32_t tagtype, uint8_t spaces);
|
||||||
int legic_get_type(legic_card_select_t *card);
|
int legic_get_type(legic_card_select_t *card);
|
||||||
void legic_chk_iv(uint32_t *iv);
|
void legic_chk_iv(uint32_t *iv);
|
||||||
|
|
|
@ -74,14 +74,8 @@ hf felica resetmode
|
||||||
hf felica litesim
|
hf felica litesim
|
||||||
hf felica litedump
|
hf felica litedump
|
||||||
hf fido info
|
hf fido info
|
||||||
hf legic reader
|
|
||||||
hf legic info
|
|
||||||
hf legic dump
|
hf legic dump
|
||||||
hf legic restore
|
hf legic restore
|
||||||
hf legic rdbl
|
|
||||||
hf legic sim
|
|
||||||
hf legic wrbl
|
|
||||||
hf legic crc
|
|
||||||
hf legic eload
|
hf legic eload
|
||||||
hf legic esave
|
hf legic esave
|
||||||
hf legic wipe
|
hf legic wipe
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue