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

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

View file

@ -24,6 +24,7 @@
#include "protocols.h"
#include "cliparser.h"
#include "cmdlfem4x05.h" // EM defines
#include "commonutil.h"
#define FIXED_71 0x71
#define FIXED_40 0x40
@ -32,60 +33,6 @@
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 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
@ -197,7 +144,14 @@ int demodNedap(bool verbose) {
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);
} else {
@ -320,10 +274,32 @@ lf t55xx wr b 4 d 4c0003ff
*/
static int CmdLFNedapRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
lf_read(false, 16000);
return demodNedap(true);
static int CmdLFNedapReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf nedap reader",
"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
@ -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 CmdLfNedapGen(const char *Cmd) {
uint8_t cmdp = 0, subType = 5, data[16], i, bin[128];
uint16_t customerCode = 0;
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)"
static int CmdLFNedapClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf nedap clone",
"clone a Nedap tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf nedap clone --st 1 --cc 101 --id 1337"
);
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++)
num_to_bytebits(data[i], 8, bin + i * 8);
uint8_t sub_type = arg_get_u32_def(ctx, 1, 5);
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);
return PM3_SUCCESS;
}
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;
// Validations
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
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
// DI-phase (CDP) T55x7_MODULATION_DIPHASE
if (DemodBufferLen == 64) {
max = 3;
blocks[0] = T55X7_NEDAP_64_CONFIG_BLOCK;
} else {
uint8_t max;
uint32_t blocks[5] = {0};
if (is_long) {
max = 5;
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 (DemodBufferLen == 64) {
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
} else {
if (is_long) {
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++) {
blocks[i] = bytebits_to_byte(DemodBuffer + ((i - 1) * 32), 32);
// EM4305
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);
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) {
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 {
PrintAndLogEx(NORMAL, "");
}
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;
}
static int CmdLFNedapSim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_nedap_sim();
CLIParserContext *ctx;
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);
if (ret != PM3_SUCCESS)
return ret;
if ((DemodBufferLen != 128) && (DemodBufferLen != 64)) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
uint8_t sub_type = arg_get_u32_def(ctx, 1, 5);
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);
CLIParserFree(ctx);
if (sub_type > 0xF) {
PrintAndLogEx(FAILED, "out-of-range, valid subtype is between 0-15");
return PM3_EINVARG;
}
PrintAndLogEx(SUCCESS, "Simulating NEDAP - Raw");
CmdPrintDemodBuff("x");
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
);
// 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)
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->separator = 0;
payload->clock = 64;
memcpy(payload->data, DemodBuffer, DemodBufferLen);
memcpy(payload->data, bs, (max * 8));
clearCommandBuffer();
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[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"},
{"generate", CmdLfNedapGen, AlwaysAvailable, "Generate Nedap bitstream in DemodBuffer"},
{"read", CmdLFNedapRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7 or Q5/T5555"},
{"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"},
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdLFNedapDemod, AlwaysAvailable, "Demodulate Nedap tag from the GraphBuffer"},
{"reader", CmdLFNedapReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdLFNedapClone, IfPm3Lf, "Clone Nedap tag to T55x7 or Q5/T5555"},
{"sim", CmdLFNedapSim, IfPm3Lf, "Simulate Nedap tag"},
{NULL, NULL, NULL, NULL}
};

View file

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

View file

@ -759,8 +759,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`lf nedap help `|Y |`This help`
|`lf nedap demod `|Y |`Demodulate Nedap tag from the GraphBuffer`
|`lf nedap generate `|Y |`Generate Nedap bitstream in DemodBuffer`
|`lf nedap read `|N |`Attempt to read and extract tag data from the antenna`
|`lf nedap reader `|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 sim `|N |`Simulate Nedap tag`