lf nedap - now uses cliparser, supports continuos mode, EM (untested)

This commit is contained in:
iceman1001 2020-12-02 12:51:37 +01:00
commit 512b8aa272
3 changed files with 183 additions and 178 deletions

View file

@ -24,6 +24,7 @@
#include "protocols.h" #include "protocols.h"
#include "cliparser.h" #include "cliparser.h"
#include "cmdlfem4x05.h" // EM defines #include "cmdlfem4x05.h" // EM defines
#include "commonutil.h"
#define FIXED_71 0x71 #define FIXED_71 0x71
#define FIXED_40 0x40 #define FIXED_40 0x40
@ -32,60 +33,6 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int usage_lf_nedap_gen(void) {
PrintAndLogEx(NORMAL, "generate Nedap bitstream in DemodBuffer");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf nedap generate [h] [s <subtype>] c <code> i <id> [l]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " s <subtype> : optional, default=5");
PrintAndLogEx(NORMAL, " c <code> : customerCode");
PrintAndLogEx(NORMAL, " i <id> : ID (max 99999)");
PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap generate s 1 c 123 i 12345"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_lf_nedap_clone(void) {
PrintAndLogEx(NORMAL, "clone a Nedap tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf nedap clone [h] [s <subtype>] c <code> i <id> [l] <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " s <subtype> : optional, default=5");
PrintAndLogEx(NORMAL, " c <code> : customerCode");
PrintAndLogEx(NORMAL, " i <id> : ID (max 99999)");
PrintAndLogEx(NORMAL, " l : optional - long (128), default to short (64)");
PrintAndLogEx(NORMAL, " Q5 : optional - specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap clone s 1 c 123 i 12345"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_lf_nedap_sim(void) {
PrintAndLogEx(NORMAL, "simulate Nedap card.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf nedap sim [h] [s <subtype>] c <code> i <id> [l]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " s <subtype> : subtype, default=5");
PrintAndLogEx(NORMAL, " c <code> : customerCode");
PrintAndLogEx(NORMAL, " i <id> : ID (max 99999)");
PrintAndLogEx(NORMAL, " l : long (128), default to short (64)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
// TODO proper example?
PrintAndLogEx(NORMAL, _YELLOW_(" lf nedap sim s 1 c 7 i 1337"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
const uint8_t translateTable[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9}; const uint8_t translateTable[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9};
const uint8_t invTranslateTable[16] = {8, 2, 1, 0xff, 4, 5, 0xff, 0xff, 0, 9, 6, 0xff, 3, 7, 0xff, 0xff}; const uint8_t invTranslateTable[16] = {8, 2, 1, 0xff, 4, 5, 0xff, 0xff, 0, 9, 6, 0xff, 3, 7, 0xff, 0xff};
const uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; // zero inside const uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; // zero inside
@ -197,7 +144,14 @@ int demodNedap(bool verbose) {
badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5; badgeId = r1 * 10000 + r2 * 1000 + r3 * 100 + r4 * 10 + r5;
PrintAndLogEx(SUCCESS, "NEDAP - Card: " _YELLOW_("%05u") " subtype: " _YELLOW_("%1u")" customer code: " _YELLOW_("%03x") ", Raw: " _YELLOW_("%s"), badgeId, subtype, customerCode, sprint_hex_inrow(data, size / 8)); PrintAndLogEx(SUCCESS, "NEDAP (%s) - ID: " _YELLOW_("%05u") " subtype: " _YELLOW_("%1u")" customer code: " _YELLOW_("%u / 0x%03X") " Raw: " _YELLOW_("%s")
, (size == 128) ? "128b" : "64b"
, badgeId
, subtype
, customerCode
, customerCode
, sprint_hex_inrow(data, size / 8)
);
PrintAndLogEx(DEBUG, "Checksum (%s) 0x%04X", _GREEN_("ok"), checksum); PrintAndLogEx(DEBUG, "Checksum (%s) 0x%04X", _GREEN_("ok"), checksum);
} else { } else {
@ -320,10 +274,32 @@ lf t55xx wr b 4 d 4c0003ff
*/ */
static int CmdLFNedapRead(const char *Cmd) { static int CmdLFNedapReader(const char *Cmd) {
(void)Cmd; // Cmd is not used so far CLIParserContext *ctx;
lf_read(false, 16000); CLIParserInit(&ctx, "lf nedap reader",
return demodNedap(true); "read a Nedap tag",
"lf nedap reader -@ -> continuous reader mode"
);
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");
}
do {
lf_read(false, 16000);
demodNedap(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
} }
static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data) { // 8 or 16 static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data) { // 8 or 16
@ -385,147 +361,182 @@ static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool i
} }
} }
static int (*usage_to_be_displayed)(void) = NULL; static int CmdLFNedapClone(const char *Cmd) {
CLIParserContext *ctx;
static int CmdLfNedapGen(const char *Cmd) { CLIParserInit(&ctx, "lf nedap clone",
uint8_t cmdp = 0, subType = 5, data[16], i, bin[128]; "clone a Nedap tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
uint16_t customerCode = 0; "lf nedap clone --st 1 --cc 101 --id 1337"
uint32_t id = 0;
bool isLong = false, errors = false;
int (*usage)(void) = usage_lf_nedap_gen;
if (usage_to_be_displayed != NULL) {
usage = usage_to_be_displayed;
usage_to_be_displayed = NULL;
}
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 's':
subType = param_get8ex(Cmd, cmdp + 1, 5, 10);
cmdp += 2;
break;
case 'c':
customerCode = param_get32ex(Cmd, cmdp + 1, 0, 16);
cmdp += 2;
break;
case 'i':
id = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'l':
isLong = true;
cmdp++;
break;
case 'q':
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations
if ((!customerCode) || (!id) || (subType > 0xF) || (customerCode > 0xFFF) || (id > 99999))
errors = true;
if (errors || cmdp == 0) {
usage();
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS,
"Tag - subtype: %1u , customer code: %03x , ID: %05u | %s"
, subType
, customerCode
, id
, isLong ? "(128b)" : "(64b)"
); );
NedapGen(subType, customerCode, id, isLong, data); void *argtable[] = {
arg_param_begin,
arg_u64_0(NULL, "st", "<dec>", "optional - sub type (default 5)"),
arg_u64_1(NULL, "cc", "<dec>", "customer code (0-4095)"),
arg_u64_1(NULL, "id", "<dec>", "ID (0-99999)"),
arg_lit0("l", "long", "optional - long (128), default to short (64)"),
arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
for (i = 0; i < (isLong ? 16 : 8); i++) uint8_t sub_type = arg_get_u32_def(ctx, 1, 5);
num_to_bytebits(data[i], 8, bin + i * 8); uint16_t customer_code = arg_get_u32_def(ctx, 2, 0);
uint32_t id = arg_get_u32_def(ctx, 3, 0);
bool is_long = arg_get_lit(ctx, 4);
bool q5 = arg_get_lit(ctx, 5);
bool em = arg_get_lit(ctx, 6);
CLIParserFree(ctx);
setDemodBuff(bin, (isLong ? 128 : 64), 0); // Validations
return PM3_SUCCESS; if (q5 && em) {
} PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
static int CmdLFNedapClone(const char *Cmd) {
uint8_t max;
uint32_t blocks[5] = {0};
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_nedap_clone();
usage_to_be_displayed = usage_lf_nedap_clone;
int ret = CmdLfNedapGen(Cmd);
if (ret != PM3_SUCCESS)
return ret;
if ((DemodBufferLen != 128) && (DemodBufferLen != 64)) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
} }
if (sub_type > 0xF) {
PrintAndLogEx(FAILED, "out-of-range, valid subtype is between 0-15");
return PM3_EINVARG;
}
if (customer_code > 0xFFF) {
PrintAndLogEx(FAILED, "out-of-range, valid customer code is between 0-4095");
return PM3_EINVARG;
}
if (id > 99999) {
PrintAndLogEx(FAILED, "out-of-range, id max value is 99999");
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X")
, is_long ? "128b" : "64b"
, id
, sub_type
, customer_code
, customer_code
);
//NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks //NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks
// DI-phase (CDP) T55x7_MODULATION_DIPHASE // DI-phase (CDP) T55x7_MODULATION_DIPHASE
uint8_t max;
if (DemodBufferLen == 64) { uint32_t blocks[5] = {0};
max = 3; if (is_long) {
blocks[0] = T55X7_NEDAP_64_CONFIG_BLOCK;
} else {
max = 5; max = 5;
blocks[0] = T55X7_NEDAP_128_CONFIG_BLOCK; blocks[0] = T55X7_NEDAP_128_CONFIG_BLOCK;
} else {
max = 3;
blocks[0] = T55X7_NEDAP_64_CONFIG_BLOCK;
} }
bool q5 = (strstr(Cmd, "q") != NULL); char cardtype[16] = {"T55x7"};
// Q5
if (q5) { if (q5) {
if (DemodBufferLen == 64) { if (is_long) {
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
} else {
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 4 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 4 << T5555_MAXBLOCK_SHIFT;
} else {
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
} }
} }
for (uint8_t i = 1; i < max ; i++) { // EM4305
blocks[i] = bytebits_to_byte(DemodBuffer + ((i - 1) * 32), 32); if (em) {
if (is_long) {
blocks[0] = EM4305_NEDAP_128_CONFIG_BLOCK;
} else {
blocks[0] = EM4305_NEDAP_64_CONFIG_BLOCK;
}
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
} }
PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to " _YELLOW_("%s") " tag", (q5) ? "Q5/T5555" : "T55x7"); // generate nedap bitstream
uint8_t data[16];
NedapGen(sub_type, customer_code, id, is_long, data);
for (uint8_t i = 1; i < max ; i++) {
blocks[i] = bytes_to_num (data + ((i - 1) * 4), 4);
}
PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to " _YELLOW_("%s") " tag", cardtype);
print_blocks(blocks, max); print_blocks(blocks, max);
int res = clone_t55xx_tag(blocks, max); int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
PrintAndLogEx(INFO, "The block 0 was changed (eXtended) which can be hard to detect."); PrintAndLogEx(INFO, "The block 0 was changed (eXtended) which can be hard to detect.");
PrintAndLogEx(INFO, " Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`")); PrintAndLogEx(INFO, "Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`"));
} else { } else {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
} }
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nedap read`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf nedap reader`") " to verify");
return res; return res;
} }
static int CmdLFNedapSim(const char *Cmd) { static int CmdLFNedapSim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0)); CLIParserContext *ctx;
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_nedap_sim(); CLIParserInit(&ctx, "lf nedap sim",
"Enables simulation of NEDAP card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf nedap sim --st 1 --cc 101 --id 1337"
);
usage_to_be_displayed = usage_lf_nedap_sim; void *argtable[] = {
arg_param_begin,
arg_u64_0(NULL, "st", "<dec>", "optional - sub type (default 5)"),
arg_u64_1(NULL, "cc", "<dec>", "customer code (0-4095)"),
arg_u64_1(NULL, "id", "<dec>", "ID (0-99999)"),
arg_lit0("l", "long", "optional - long (128), default to short (64)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int ret = CmdLfNedapGen(Cmd); uint8_t sub_type = arg_get_u32_def(ctx, 1, 5);
if (ret != PM3_SUCCESS) uint16_t customer_code = arg_get_u32_def(ctx, 2, 0);
return ret; uint32_t id = arg_get_u32_def(ctx, 3, 0);
bool is_long = arg_get_lit(ctx, 4);
if ((DemodBufferLen != 128) && (DemodBufferLen != 64)) { CLIParserFree(ctx);
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT; if (sub_type > 0xF) {
PrintAndLogEx(FAILED, "out-of-range, valid subtype is between 0-15");
return PM3_EINVARG;
} }
PrintAndLogEx(SUCCESS, "Simulating NEDAP - Raw"); if (customer_code > 0xFFF) {
CmdPrintDemodBuff("x"); PrintAndLogEx(FAILED, "out-of-range, valid customer code is between 0-4095");
return PM3_EINVARG;
}
if (id > 99999) {
PrintAndLogEx(FAILED, "out-of-range, id max value is 99999");
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X")
, is_long ? "128b" : "64b"
, id
, sub_type
, customer_code
, customer_code
);
// generate nedap bitstream
uint8_t max = (is_long) ? 16 : 8;
uint8_t data[16];
NedapGen(sub_type, customer_code, id, is_long, data);
uint8_t bs[16 * 8];
for (uint8_t i = 0; i < max; i++) {
num_to_bytebits(data[i], 8, bs + i * 8);
}
PrintAndLogEx(SUCCESS, "Simulating NEDAP - Raw: " _YELLOW_("%s"), sprint_hex_inrow(data, max));
// NEDAP, Biphase = 2, clock 64, inverted, (DIPhase == inverted BIphase) // NEDAP, Biphase = 2, clock 64, inverted, (DIPhase == inverted BIphase)
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + DemodBufferLen); lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + DemodBufferLen);
@ -533,7 +544,7 @@ static int CmdLFNedapSim(const char *Cmd) {
payload->invert = 1; payload->invert = 1;
payload->separator = 0; payload->separator = 0;
payload->clock = 64; payload->clock = 64;
memcpy(payload->data, DemodBuffer, DemodBufferLen); memcpy(payload->data, bs, (max * 8));
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + DemodBufferLen); SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + DemodBufferLen);
@ -550,12 +561,11 @@ static int CmdLFNedapSim(const char *Cmd) {
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"}, {"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"},
{"generate", CmdLfNedapGen, AlwaysAvailable, "Generate Nedap bitstream in DemodBuffer"}, {"reader", CmdLFNedapReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"read", CmdLFNedapRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"}, {"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7 or Q5/T5555"},
{"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7 or Q5/T5555"}, {"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"},
{"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };

View file

@ -204,10 +204,6 @@ lf hitag cc
lf indala demod lf indala demod
lf indala altdemod lf indala altdemod
lf indala sim lf indala sim
lf nedap generate
lf nedap read
lf nedap clone
lf nedap sim
lf t55xx config lf t55xx config
lf t55xx dangerraw lf t55xx dangerraw
lf t55xx detect lf t55xx detect

View file

@ -759,8 +759,7 @@ Check column "offline" for their availability.
|------- |------- |----------- |------- |------- |-----------
|`lf nedap help `|Y |`This help` |`lf nedap help `|Y |`This help`
|`lf nedap demod `|Y |`Demodulate Nedap tag from the GraphBuffer` |`lf nedap demod `|Y |`Demodulate Nedap tag from the GraphBuffer`
|`lf nedap generate `|Y |`Generate Nedap bitstream in DemodBuffer` |`lf nedap reader `|N |`Attempt to read and extract tag data from the antenna`
|`lf nedap read `|N |`Attempt to read and extract tag data from the antenna`
|`lf nedap clone `|N |`Clone Nedap tag to T55x7 or Q5/T5555` |`lf nedap clone `|N |`Clone Nedap tag to T55x7 or Q5/T5555`
|`lf nedap sim `|N |`Simulate Nedap tag` |`lf nedap sim `|N |`Simulate Nedap tag`