Merge branch 'master' into update_4x50

merge 20120merge 2012033
This commit is contained in:
tharexde 2020-12-03 21:17:46 +01:00
commit d546936f5c
39 changed files with 890 additions and 583 deletions

View file

@ -22,6 +22,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- EM4x50: switched to cliparser for all functions (@tharexde)
- EM4x50: stabilized and accelerated tag detection (@tharexde)
- EM4x50: removed global tag structure on device side (@tharexde)
- Fix `hf 15 sim` - Added basic response to GET_SYSTEM_INFO and READBLOCK requests in order to fix iso15693 tag sim
- Added `mf mfu sim t 7 n <numreads>` - MFU emulation now supports automatic exit after <num> blocks read. (@cyberpunk-re)
- Added T55xx Guide to assist in learning how to use the T55xx chip (@mwalker33)
- Fix 'hf iclass wrbl' - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001)

View file

@ -104,10 +104,12 @@
#define ISO15693_MAX_COMMAND_LENGTH 45 // allows write single block with the maximum block size of 256bits. Write multiple blocks not supported yet
// 32 + 2 crc + 1
#define ISO15_MAX_FRAME 35
#define CMD_ID_RESP 5
#define CMD_READ_RESP 13
#define CMD_INV_RESP 12
#define ISO15_MAX_FRAME 35
#define CMD_ID_RESP 5
#define CMD_READ_RESP 13
#define CMD_INV_RESP 12
#define CMD_SYSINFO_RESP 17
#define CMD_READBLOCK_RESP 7
//#define Crc(data, len) Crc(CRC_15693, (data), (len))
#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
@ -1679,27 +1681,7 @@ void SimTagIso15693(uint8_t *uid) {
LED_C_ON();
// Build INVENTORY command
uint8_t resp_inv[CMD_INV_RESP] = {0};
resp_inv[0] = 0; // No error, no protocol format extension
resp_inv[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
// 64-bit UID
resp_inv[2] = uid[7];
resp_inv[3] = uid[6];
resp_inv[4] = uid[5];
resp_inv[5] = uid[4];
resp_inv[6] = uid[3];
resp_inv[7] = uid[2];
resp_inv[8] = uid[1];
resp_inv[9] = uid[0];
// CRC
AddCrc15(resp_inv, 10);
CodeIso15693AsTag(resp_inv, CMD_INV_RESP);
tosend_t *ts = get_tosend();
enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD;
@ -1745,11 +1727,96 @@ void SimTagIso15693(uint8_t *uid) {
if ((cmd_len >= 5) && (cmd[0] & ISO15_REQ_INVENTORY) && (cmd[1] == ISO15_CMD_INVENTORY)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build INVENTORY command
uint8_t resp_inv[CMD_INV_RESP] = {0};
resp_inv[0] = 0; // No error, no protocol format extension
resp_inv[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
// 64-bit UID
resp_inv[2] = uid[7];
resp_inv[3] = uid[6];
resp_inv[4] = uid[5];
resp_inv[5] = uid[4];
resp_inv[6] = uid[3];
resp_inv[7] = uid[2];
resp_inv[8] = uid[1];
resp_inv[9] = uid[0];
// CRC
AddCrc15(resp_inv, 10);
CodeIso15693AsTag(resp_inv, CMD_INV_RESP);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
LogTrace_ISO15693(resp_inv, CMD_INV_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
chip_state = SELECTED;
}
// GET_SYSTEM_INFO
if ((cmd[1] == ISO15_CMD_SYSINFO)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build GET_SYSTEM_INFO command
uint8_t resp_sysinfo[CMD_SYSINFO_RESP] = {0};
resp_sysinfo[0] = 0; // Response flags.
resp_sysinfo[1] = 0x0F; // Information flags (0x0F - DSFID, AFI, Mem size, IC)
// 64-bit UID
resp_sysinfo[2] = uid[7];
resp_sysinfo[3] = uid[6];
resp_sysinfo[4] = uid[5];
resp_sysinfo[5] = uid[4];
resp_sysinfo[6] = uid[3];
resp_sysinfo[7] = uid[2];
resp_sysinfo[8] = uid[1];
resp_sysinfo[9] = uid[0];
resp_sysinfo[10] = 0; // DSFID
resp_sysinfo[11] = 0; // AFI
resp_sysinfo[12] = 0x1B; // Memory size.
resp_sysinfo[13] = 0x03; // Memory size.
resp_sysinfo[14] = 0x01; // IC reference.
// CRC
AddCrc15(resp_sysinfo, 15);
CodeIso15693AsTag(resp_sysinfo, CMD_SYSINFO_RESP);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
LogTrace_ISO15693(resp_sysinfo, CMD_SYSINFO_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
}
// READ_BLOCK
if ((cmd[1] == ISO15_CMD_READ)) {
bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH);
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM;
// Build GET_SYSTEM_INFO command
uint8_t resp_readblock[CMD_READBLOCK_RESP] = {0};
resp_readblock[0] = 0; // Response flags.
resp_readblock[1] = 0; // Block data.
resp_readblock[2] = 0; // Block data.
resp_readblock[3] = 0; // Block data.
resp_readblock[4] = 0; // Block data.
// CRC
AddCrc15(resp_readblock, 5);
CodeIso15693AsTag(resp_readblock, CMD_READBLOCK_RESP);
tosend_t *ts = get_tosend();
TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow);
LogTrace_ISO15693(resp_readblock, CMD_READBLOCK_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false);
}
}
switch_off();

View file

@ -509,10 +509,21 @@ void doCotagAcquisition(void) {
bool firsthigh = false, firstlow = false;
uint16_t i = 0, noise_counter = 0;
uint16_t checker = 0;
while ((i < bufsize - 1) && (noise_counter < COTAG_T1 << 1)) {
if (BUTTON_PRESS())
break;
if (checker == 4000) {
if (data_available())
break;
else
checker = 0;
} else {
++checker;
}
WDT_HIT();
@ -567,12 +578,22 @@ uint16_t doCotagAcquisitionManchester(uint8_t *dest, uint16_t destlen) {
bool firsthigh = false, firstlow = false;
uint8_t curr = 0, prev = 0;
uint16_t i = 0;
uint16_t period = 0;
uint16_t period = 0, checker = 0;
while ((i < destlen) && BUTTON_PRESS() == false) {
WDT_HIT();
if (checker == 4000) {
if (data_available())
break;
else
checker = 0;
} else {
++checker;
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;

View file

@ -1702,9 +1702,11 @@ int CmdTuneSamples(const char *Cmd) {
if (package->peak_v > NON_VOLTAGE && package->peak_f > 0)
PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->peak_f));
// Empirical measures in mV
const double vdd_rdv4 = 9000;
const double vdd_other = 5400; // Empirical measures in mV
const double vdd_other = 5400;
double vdd = IfPm3Rdv4Fw() ? vdd_rdv4 : vdd_other;
if (package->peak_v > NON_VOLTAGE && package->peak_f > 0) {
// Q measure with Q=f/delta_f
@ -1737,9 +1739,15 @@ int CmdTuneSamples(const char *Cmd) {
// cross-check results
if (lfq1 > 3) {
double approx_vdd = (double)package->peak_v * 3.14 / 2 / lfq1;
if ((approx_vdd > (vdd_rdv4 + vdd_other) / 2) && (! IfPm3Rdv4Fw()))
// Got 8858 on a RDV4 with large antenna 134/14
// Got 8761 on a non-RDV4
const double approx_vdd_other_max = 8840;
// 1% over threshold and supposedly non-RDV4
if ((approx_vdd > approx_vdd_other_max * 1.01) && (! IfPm3Rdv4Fw()))
PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_OTHER firmware on a RDV4") ", please check your setup");
if ((approx_vdd < (vdd_rdv4 + vdd_other) / 2) && (IfPm3Rdv4Fw()))
// 1% below threshold and supposedly RDV4
if ((approx_vdd < approx_vdd_other_max * 0.99) && (IfPm3Rdv4Fw()))
PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_RDV4 firmware on a non-RDV4") ", please check your setup");
}
}

View file

@ -568,6 +568,17 @@ static int CmdHFiClassSim(const char *Cmd) {
}
static int CmdHFiClassInfo(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass info",
"Act as a iCLASS reader. Reads / fingerprints a iCLASS tag.",
"hf iclass info");
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
return info_iclass();
}
@ -576,8 +587,7 @@ int read_iclass_csn(bool loop, bool verbose) {
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
int res = PM3_SUCCESS;
while (kbd_enter_pressed() == false) {
do {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
PacketResponseNG resp;
@ -585,27 +595,24 @@ int read_iclass_csn(bool loop, bool verbose) {
uint8_t status = resp.oldarg[0] & 0xff;
if (loop == false) {
if (loop) {
if (status == 0xFF) {
continue;
}
} else {
if (status == 0 || status == 0xFF) {
if (verbose) PrintAndLogEx(WARNING, "iCLASS / ISO15693 card select failed");
res = PM3_EOPABORTED;
break;
}
} else {
if (status == 0xFF)
continue;
}
picopass_hdr *hdr = (picopass_hdr *)resp.data.asBytes;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(hdr->csn, sizeof(hdr->csn)));
PrintAndLogEx(SUCCESS, " Config: " _GREEN_("%s"), sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
if (loop == false)
break;
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(hdr->csn, sizeof(hdr->csn)));
}
}
} while (loop && kbd_enter_pressed() == false);
DropField();
return res;
@ -615,22 +622,24 @@ static int CmdHFiClassReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass reader",
"Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed\n",
"hf iclass reader\n"
"hf iclass reader -1");
"Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed",
"hf iclass reader -@ -> continuous reader mode"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("1", "one", "read once"),
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool read_once = arg_get_lit(ctx, 1);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
PrintAndLogEx(INFO, "Starting iCLASS reader mode");
PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel");
return read_iclass_csn(!read_once, true);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
return read_iclass_csn(cm, true);
}
static int CmdHFiClassELoad(const char *Cmd) {
@ -3272,10 +3281,10 @@ static int CmdHFiClassPermuteKey(const char *Cmd) {
int len = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf iclass permute",
CLIParserInit(&ctx, "hf iclass permutekey",
"Permute function from 'heart of darkness' paper.",
"hf iclass permute --reverse --key 0123456789abcdef\n"
"hf iclass permute --key ff55330f0055330f\n");
"hf iclass permutekey --reverse --key 0123456789abcdef\n"
"hf iclass permutekey --key ff55330f0055330f\n");
void *argtable[] = {
arg_param_begin,
@ -3473,10 +3482,7 @@ int info_iclass(void) {
uint8_t cardtype = get_mem_config(hdr);
PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
}
DropField();
return PM3_SUCCESS;
}

View file

@ -128,7 +128,7 @@ static int CmdHfLTOInfo(const char *Cmd) {
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
return infoLTO(true);
}

View file

@ -1434,8 +1434,8 @@ int CmdLFfind(const char *Cmd) {
return PM3_SUCCESS;
}
PrintAndLogEx(INPLACE, "Searching for COTAG tag...");
if (readCOTAGUid()) {
PrintAndLogEx(INPLACE, "Searching for COTAG tag...");
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!");
return PM3_SUCCESS;
}

View file

@ -313,6 +313,10 @@ static int CmdAWIDReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 12000);
demodAWID(!cm);

View file

@ -122,15 +122,22 @@ static int CmdCOTAGReader(const char *Cmd) {
SendCommandNG(CMD_LF_COTAG_READ, (uint8_t *)&payload, sizeof(payload));
uint8_t timeout = 3;
while (!WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 2000)) {
int res = PM3_SUCCESS;
while (!WaitForResponseTimeout(CMD_LF_COTAG_READ, &resp, 1000)) {
timeout--;
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout == 0) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
res = PM3_ETIMEOUT;
}
}
if (res != PM3_SUCCESS) {
return res;
}
if (timeout != 3)
PrintAndLogEx(NORMAL, "");
@ -157,7 +164,6 @@ static command_t CommandTable[] = {
{"reader", CmdCOTAGReader, IfPm3Lf, "Attempt to read and extract tag data"},
{NULL, NULL, NULL, NULL}
};
static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable);
@ -170,5 +176,5 @@ int CmdLFCOTAG(const char *Cmd) {
}
int readCOTAGUid(void) {
return (CmdCOTAGReader("") == PM3_SUCCESS);
return (CmdCOTAGReader("-2") == PM3_SUCCESS);
}

View file

@ -113,6 +113,10 @@ static int CmdDestronReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 16000);
demodDestron(!cm);

View file

@ -47,7 +47,7 @@
static int CmdHelp(const char *Cmd);
static int getFDXBBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint16_t extended, uint8_t *bits) {
static int getFDXBBits(uint64_t national_code, uint16_t country_code, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits) {
// add preamble ten 0x00 and one 0x01
memset(bits, 0x00, 10);
@ -103,7 +103,7 @@ static int getFDXBBits(uint64_t national_code, uint16_t country_code, uint8_t is
}
// clearing the topbit needed for the preambl detection.
static void verify_values(uint64_t *animalid, uint32_t *countryid, uint16_t *extended) {
static void verify_values(uint64_t *animalid, uint32_t *countryid, uint32_t *extended) {
if ((*animalid & 0x3FFFFFFFFF) != *animalid) {
*animalid &= 0x3FFFFFFFFF;
PrintAndLogEx(INFO, "Animal ID truncated to 38bits: " _YELLOW_("%"PRIx64), *animalid);
@ -112,8 +112,8 @@ static void verify_values(uint64_t *animalid, uint32_t *countryid, uint16_t *ext
*countryid &= 0x3FF;
PrintAndLogEx(INFO, "Country ID truncated to 10bits:" _YELLOW_("%03d"), *countryid);
}
if ((*extended & 0xFFF) != *extended) {
*extended &= 0xFFF;
if ((*extended & 0xFFFFFF) != *extended) {
*extended &= 0xFFFFFF;
PrintAndLogEx(INFO, "Extended truncated to 24bits: " _YELLOW_("0x%03X"), *extended);
}
}
@ -713,7 +713,7 @@ static int CmdFdxBClone(const char *Cmd) {
uint64_t national_code = arg_get_u64_def(ctx, 2, 0);
int extended_len = 0;
uint8_t edata[2] = {0};
uint8_t edata[3] = {0};
CLIGetHexWithReturn(ctx, 3, edata, &extended_len);
bool is_animal = arg_get_lit(ctx, 4);
@ -726,7 +726,7 @@ static int CmdFdxBClone(const char *Cmd) {
return PM3_EINVARG;
}
uint16_t extended = 0;
uint32_t extended = 0;
bool has_extended = false;
if (extended_len) {
extended = bytes_to_num(edata, extended_len);
@ -813,13 +813,13 @@ static int CmdFdxBSim(const char *Cmd) {
uint32_t country_code = arg_get_u32_def(ctx, 1, 0);
uint64_t national_code = arg_get_u64_def(ctx, 2, 0);
int extended_len = 0;
uint8_t edata[2] = {0};
uint8_t edata[3] = {0};
CLIGetHexWithReturn(ctx, 3, edata, &extended_len);
bool is_animal = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
uint16_t extended = 0;
uint32_t extended = 0;
bool has_extended = false;
if (extended_len) {
extended = bytes_to_num(edata, extended_len);

View file

@ -154,6 +154,10 @@ static int CmdGallagherReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 4096 * 2 + 20);
demodGallagher(!cm);

View file

@ -147,6 +147,10 @@ static int CmdGuardReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 10000);
demodGuard(!cm);

View file

@ -45,8 +45,7 @@ static int CmdHelp(const char *Cmd);
// sending three times. Didn't seem to break the previous sim?
static int sendPing(void) {
SendCommandNG(CMD_PING, NULL, 0);
SendCommandNG(CMD_PING, NULL, 0);
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
SendCommandNG(CMD_PING, NULL, 0);
clearCommandBuffer();
PacketResponseNG resp;
@ -183,6 +182,10 @@ static int CmdHIDReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 16000);
demodHID(!cm);
@ -223,7 +226,8 @@ static int CmdHIDSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf hid sim",
"Enables simulation of HID card with card number.",
"Enables simulation of HID card with card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf hid sim -r 2006ec0c86 -> HID 10301 26 bit\n"
"lf hid sim -r 2e0ec00c87 -> HID Corporate 35 bit\n"
"lf hid sim -r 01f0760643c3 -> HID P10001 40 bit\n"
@ -312,7 +316,8 @@ static int CmdHIDClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf hid clone",
"Clone HID to T55x7. Tag must be on antenna!",
"clone a HID Prox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
"Tag must be on the antenna when issuing this command.",
"lf hid clone -r 2006ec0c86 -> HID 10301 26 bit\n"
"lf hid clone -r 2e0ec00c87 -> HID Corporate 35 bit\n"
"lf hid clone -r 01f0760643c3 -> HID P10001 40 bit\n"

View file

@ -117,6 +117,10 @@ static int CmdIdteckReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 5000);
demodIdteck(!cm);

View file

@ -38,41 +38,6 @@ static uint8_t preamble224[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// standard 64 bit indala formats including 26 bit 40134 format
static uint8_t preamble64[] = {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
static int usage_lf_indala_demod(void) {
PrintAndLogEx(NORMAL, "Tries to psk demodulate the graphbuffer as Indala ");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf indala demod [h] <clock> <0|1> <maxerror>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " clock : Set clock (as integer) optional, if not set, autodetect.");
PrintAndLogEx(NORMAL, " invert : 1 for invert output");
PrintAndLogEx(NORMAL, " maxerror : Set maximum allowed errors, default = 100.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod"));
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod 32") " = demod a Indala tag from GraphBuffer using a clock of RF/32");
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod 32 1") " = demod a Indala tag from GraphBuffer using a clock of RF/32 and inverting data");
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala demod 64 1 0") " = demod a Indala tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_lf_indala_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of Indala card with specified uid.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf indala sim [h] <u uid> <c cardnum>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " u <uid> : 64/224 UID");
PrintAndLogEx(NORMAL, " c <cardnum> : Cardnumber for Heden 2L format (decimal)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf indala sim deadc0de"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
#define HEDEN2L_OFFSET 31
static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) {
@ -119,7 +84,7 @@ static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) {
dest[i / 8] = bytebits_to_byte(template + i, 8);
}
PrintAndLogEx(INFO, "Heden-2L card number %u", cardnumber);
PrintAndLogEx(INFO, "Heden-2L card number " _GREEN_("%u"), cardnumber);
}
static void decodeHeden2L(uint8_t *bits) {
@ -186,7 +151,7 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) {
uint64_t foo = uid2 & 0x7FFFFFFF;
if (DemodBufferLen == 64) {
PrintAndLogEx(SUCCESS, "Indala - len %zu, Raw: %x%08x", DemodBufferLen, uid1, uid2);
PrintAndLogEx(SUCCESS, "Indala - len " _GREEN_("%zu") " Raw: %x%08x", DemodBufferLen, uid1, uid2);
uint16_t p1 = 0;
p1 |= DemodBuffer[32 + 3] << 8;
@ -253,7 +218,7 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) {
uint32_t uid7 = bytebits_to_byte(DemodBuffer + 192, 32);
PrintAndLogEx(
SUCCESS
, "Indala - len %zu, Raw: %x%08x%08x%08x%08x%08x%08x"
, "Indala - len " _GREEN_("%zu") " Raw: %x%08x%08x%08x%08x%08x%08x"
, DemodBufferLen
, uid1
, uid2
@ -278,28 +243,55 @@ int demodIndala(bool verbose) {
static int CmdIndalaDemod(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_lf_indala_demod();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf indala demod",
"Tries to psk demodulate the graphbuffer as Indala Prox",
"lf indala demod\n"
"lf indala demod --clock 32 -> demod a Indala tag from GraphBuffer using a clock of RF/32\n"
"lf indala demod --clock 32 -i -> demod a Indala tag from GraphBuffer using a clock of RF/32 and inverting data\n"
"lf indala demod --clock 64 -i --maxerror 0 -> demod a Indala tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"
);
int clk = 32, invert = 0, maxErr = 100;
if (strlen(Cmd) > 0) {
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
}
if (clk == 1) {
invert = 1;
clk = 0;
}
if (invert != 0 && invert != 1) {
PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert);
return PM3_EINVARG;
}
return demodIndalaEx(clk, invert, maxErr, true);
void *argtable[] = {
arg_param_begin,
arg_int0(NULL, "clock", "<dec>", "optional - set clock (as integer), if not set, autodetect."),
arg_int0(NULL, "maxerr", "<dec>", "optional - set maximum allowed errors, default = 100"),
arg_lit0("i", "invert", "optional - invert output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint32_t clk = arg_get_u32_def(ctx, 1, 32);
uint32_t max_err = arg_get_u32_def(ctx, 2, 100);
bool invert = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
return demodIndalaEx(clk, invert, max_err, true);
}
// older alternative indala demodulate (has some positives and negatives)
// returns false positives more often - but runs against more sets of samples
// poor psk signal can be difficult to demod this approach might succeed when the other fails
// but the other appears to currently be more accurate than this approach most of the time.
static int CmdIndalaDemodAlt(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf indala altdemod",
"Tries to psk demodulate the graphbuffer as Indala Prox\n"
"This is uses a alternative way to demodulate and was used from the beginning in the Pm3 client.\n"
"It's now considered obsolete but remains because it has sometimes its advantages.",
"lf indala altdemod\n"
"lf indala altdemod --long -> demod a Indala tag from GraphBuffer as 224 bit long format"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("l", "long", "optional - demod as 224b long format"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool is_long = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
// Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
int state = -1;
int count = 0;
@ -360,7 +352,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) {
// Finding the start of a UID
int uidlen, long_wait;
if (strcmp(Cmd, "224") == 0) {
if (is_long) {
uidlen = 224;
long_wait = 30;
} else {
@ -520,6 +512,10 @@ static int CmdIndalaReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 4);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 30000);
demodIndalaEx(clk, invert, max_err, !cm);
@ -529,26 +525,56 @@ static int CmdIndalaReader(const char *Cmd) {
static int CmdIndalaSim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_indala_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf indala sim",
"Enables simulation of IOProx card with specified facility-code and card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf indala sim --heden 888\n"
"lf indala sim --raw a0000000a0002021\n"
"lf indala sim --raw 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"
);
void *argtable[] = {
arg_param_begin,
arg_strx0("r", "raw", "<hex>", "raw bytes"),
arg_int0(NULL, "heden", "<decimal>", "Cardnumber for Heden 2L format"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
// raw param
int raw_len = 0;
uint8_t raw[(7 * 4) + 1 ];
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool is_long_uid = (raw_len == 28);
int32_t cardnumber;
bool got_cn = false;
if (is_long_uid == false) {
// Heden param
cardnumber = arg_get_int_def(ctx, 2, -1);
got_cn = (cardnumber != -1);
}
CLIParserFree(ctx);
if (got_cn) {
encodeHeden2L(raw, cardnumber);
raw_len = 8;
}
// convert to binarray
uint8_t bs[224];
memset(bs, 0x00, sizeof(bs));
// uid
uint8_t hexuid[100];
int len = 0;
param_gethex_ex(Cmd, 0, hexuid, &len);
if (len > 28)
return usage_lf_indala_sim();
// convert to binarray
uint8_t counter = 223;
for (uint8_t i = 0; i < len; i++) {
for (uint8_t i = 0; i < raw_len; i++) {
uint8_t tmp = raw[i];
for (uint8_t j = 0; j < 8; j++) {
bs[counter--] = hexuid[i] & 1;
hexuid[i] >>= 1;
bs[counter--] = tmp & 1;
tmp >>= 1;
}
}
@ -556,7 +582,10 @@ static int CmdIndalaSim(const char *Cmd) {
// It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not.
// lf simpsk 1 c 32 r 2 d 0102030405060708
PrintAndLogEx(SUCCESS, "Simulating Indala UID: %s", sprint_hex(hexuid, len));
PrintAndLogEx(SUCCESS, "Simulating " _YELLOW_("%s") " Indala raw " _YELLOW_("%s")
, (is_long_uid) ? "224b" : "64b"
, sprint_hex_inrow(raw, raw_len)
);
PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command");
// indala PSK, clock 32, carrier 0
@ -566,8 +595,6 @@ static int CmdIndalaSim(const char *Cmd) {
payload->clock = 32;
memcpy(payload->data, bs, sizeof(bs));
PrintAndLogEx(INFO, "Simulating");
clearCommandBuffer();
SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs));
free(payload);
@ -584,8 +611,6 @@ static int CmdIndalaSim(const char *Cmd) {
static int CmdIndalaClone(const char *Cmd) {
int32_t cardnumber;
uint32_t blocks[8] = {0};
uint8_t max = 0;
uint8_t fc = 0;
uint16_t cn = 0;
@ -595,28 +620,27 @@ static int CmdIndalaClone(const char *Cmd) {
"lf indala clone --heden 888\n"
"lf indala clone --fc 123 --cn 1337\n"
"lf indala clone -r a0000000a0002021\n"
"lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
"lf indala clone -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
void *argtable[] = {
arg_param_begin,
arg_lit0("l", "long", "optional - long UID 224 bits"),
arg_int0("c", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
arg_strx0("r", "raw", "<hex>", "raw bytes"),
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
arg_strx0("r", "raw", "<hex>", "raw bytes"),
arg_int0(NULL, "heden", "<decimal>", "Cardnumber for Heden 2L format"),
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
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);
bool is_long_uid = arg_get_lit(ctx, 1);
// raw param
int datalen = 0;
uint8_t data[(7 * 4) + 1 ];
CLIGetHexWithReturn(ctx, 3, data, &datalen);
int raw_len = 0;
uint8_t raw[(7 * 4) + 1];
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool is_t5555 = arg_get_lit(ctx, 4);
bool is_long_uid = (raw_len == 28);
bool q5 = arg_get_lit(ctx, 5);
bool em = arg_get_lit(ctx, 6);
bool got_cn = false, got_26 = false;
if (is_long_uid == false) {
@ -626,43 +650,59 @@ static int CmdIndalaClone(const char *Cmd) {
got_cn = (cardnumber != -1);
// 26b FC/CN param
fc = arg_get_int_def(ctx, 5, 0);
cn = arg_get_int_def(ctx, 6, 0);
fc = arg_get_int_def(ctx, 3, 0);
cn = arg_get_int_def(ctx, 4, 0);
got_26 = (fc != 0 && cn != 0);
}
CLIParserFree(ctx);
PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7");
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint8_t max = 0;
uint32_t blocks[8] = {0};
char cardtype[16] = {"T55x7"};
if (is_long_uid) {
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
if (q5) {
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
if (em) {
blocks[0] = EM4305_INDALA_224_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
blocks[1] = bytes_to_num(raw, 4);
blocks[2] = bytes_to_num(raw + 4, 4);
blocks[3] = bytes_to_num(raw + 8, 4);
blocks[4] = bytes_to_num(raw + 12, 4);
blocks[5] = bytes_to_num(raw + 16, 4);
blocks[6] = bytes_to_num(raw + 20, 4);
blocks[7] = bytes_to_num(raw + 24, 4);
max = 8;
// 224 BIT UID
// config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag");
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit to " _YELLOW_("%s") " raw " _GREEN_("%s")
, cardtype
, sprint_hex_inrow(raw, raw_len)
);
if (is_t5555)
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
else
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
blocks[1] = bytes_to_num(data, 4);
blocks[2] = bytes_to_num(data + 4, 4);
blocks[3] = bytes_to_num(data + 8, 4);
blocks[4] = bytes_to_num(data + 12, 4);
blocks[5] = bytes_to_num(data + 16, 4);
blocks[6] = bytes_to_num(data + 20, 4);
blocks[7] = bytes_to_num(data + 24, 4);
max = 8;
} else {
// 64 BIT UID
if (got_cn) {
PrintAndLogEx(INFO, "Using Indala HEDEN cardnumber %u", cardnumber);
encodeHeden2L(data, cardnumber);
datalen = 8;
encodeHeden2L(raw, cardnumber);
raw_len = 8;
} else if (got_26) {
PrintAndLogEx(INFO, "Using Indala 26b FC %u CN %u", fc, cn);
PrintAndLogEx(INFO, "Using Indala 26b FC " _GREEN_("%u") " CN " _GREEN_("%u"), fc, cn);
// Used with the 26bit FC/CSN
uint8_t *bits = calloc(INDALA_ARR_LEN, sizeof(uint8_t));
@ -677,37 +717,52 @@ static int CmdIndalaClone(const char *Cmd) {
return PM3_ESOFT;
}
data[0] = bytebits_to_byte(bits, 8);
data[1] = bytebits_to_byte(bits + 8, 8);
data[2] = bytebits_to_byte(bits + 16, 8);
data[3] = bytebits_to_byte(bits + 24, 8);
data[4] = bytebits_to_byte(bits + 32, 8);
data[5] = bytebits_to_byte(bits + 40, 8);
data[6] = bytebits_to_byte(bits + 48, 8);
data[7] = bytebits_to_byte(bits + 56, 8);
datalen = 8;
raw[0] = bytebits_to_byte(bits, 8);
raw[1] = bytebits_to_byte(bits + 8, 8);
raw[2] = bytebits_to_byte(bits + 16, 8);
raw[3] = bytebits_to_byte(bits + 24, 8);
raw[4] = bytebits_to_byte(bits + 32, 8);
raw[5] = bytebits_to_byte(bits + 40, 8);
raw[6] = bytebits_to_byte(bits + 48, 8);
raw[7] = bytebits_to_byte(bits + 56, 8);
raw_len = 8;
free(bits);
}
// config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag");
PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
if (is_t5555)
if (q5) {
blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT);
else
blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
if (em) {
blocks[0] = EM4305_INDALA_64_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
blocks[1] = bytes_to_num(data, 4);
blocks[2] = bytes_to_num(data + 4, 4);
blocks[1] = bytes_to_num(raw, 4);
blocks[2] = bytes_to_num(raw + 4, 4);
max = 3;
// config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit to " _YELLOW_("%s") " raw " _GREEN_("%s")
, cardtype
, sprint_hex_inrow(raw, raw_len)
);
}
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));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf indala read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf indala reader`") " to verify");
return res;
}

View file

@ -1,4 +1,5 @@
//-----------------------------------------------------------------------------
// marshmellow
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
@ -28,58 +29,22 @@
static int CmdHelp(const char *Cmd);
static int usage_lf_io_watch(void) {
PrintAndLogEx(NORMAL, "Enables IOProx compatible reader mode printing details of scanned tags.");
PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf io watch");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf io watch"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_lf_io_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of IOProx card with specified facility-code and card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf io sim [h] <version> <facility-code> <card-number>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (" _YELLOW_("decimal") ")");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf io sim 01 101 1337"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_lf_io_clone(void) {
PrintAndLogEx(NORMAL, "Enables cloning of IOProx card with specified facility-code and card number onto T55x7 or Q5/T5555 tag");
PrintAndLogEx(NORMAL, "The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf io clone [h] <version> <facility-code> <card-number> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <version> : 8bit version (" _YELLOW_("decimal") ")");
PrintAndLogEx(NORMAL, " <facility-code> : 8bit value facility code (" _YELLOW_("hex") ")");
PrintAndLogEx(NORMAL, " <card number> : 16bit value card number (" _YELLOW_("decimal") ")");
PrintAndLogEx(NORMAL, " <Q5> : optional - specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf io clone 01 101 1337"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
// this read loops on device side.
// uses the demod in lfops.c
static int CmdIOProxWatch(const char *Cmd) {
uint8_t c = tolower(param_getchar(Cmd, 0));
if (c == 'h') return usage_lf_io_watch();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf io watch",
"Enables IOProx compatible reader mode printing details.\n"
"By default, values are printed and logged until the button is pressed or another USB command is issued.",
"lf io watch"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
PrintAndLogEx(SUCCESS, "Watching for IO Prox cards - place tag on antenna");
PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
@ -91,7 +56,6 @@ static int CmdIOProxWatch(const char *Cmd) {
return resp.status;
}
//by marshmellow
//IO-Prox demod - FSK RF/64 with preamble of 000000001
//print ioprox ID and some format details
int demodIOProx(bool verbose) {
@ -193,8 +157,8 @@ int demodIOProx(bool verbose) {
static int CmdIOProxDemod(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf io demod",
"Try to find IO Prox preamble, if found decode / descramble data",
"lf io demod\n"
"Try to find IOProx preamble, if found decode / descramble data",
"lf io demod"
);
void *argtable[] = {
@ -209,7 +173,7 @@ static int CmdIOProxDemod(const char *Cmd) {
static int CmdIOProxReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf io reader",
"read a IO Prox tag",
"read a IOProx tag",
"lf io reader -@ -> continuous reader mode"
);
@ -229,29 +193,42 @@ static int CmdIOProxReader(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdIOProxSim(const char *Cmd) {
uint16_t cn = 0;
uint8_t version = 0, fc = 0;
uint8_t bs[64];
memset(bs, 0x00, sizeof(bs));
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_io_sim();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf io sim",
"Enables simulation of IOProx card with specified facility-code and card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf io sim --vn 1 --fc 101 --cn 1337"
);
version = param_get8(Cmd, 0);
fc = param_get8ex(Cmd, 1, 0, 16);
cn = param_get32ex(Cmd, 2, 0, 10);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "vn", "<dec>", "8bit version"),
arg_u64_1(NULL, "fc", "<dec>", "8bit facility code"),
arg_u64_1(NULL, "cn", "<dec>", "16bit card number"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
if (!version || !fc || !cn) return usage_lf_io_sim();
uint8_t version = arg_get_u32_def(ctx, 1, 0);
uint8_t fc = arg_get_u32_def(ctx, 2, 0);
uint16_t cn = arg_get_u32_def(ctx, 3, 0);
CLIParserFree(ctx);
if ((cn & 0xFFFF) != cn) {
cn &= 0xFFFF;
PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn);
}
PrintAndLogEx(SUCCESS, "Simulating IOProx version: %u FC: %u; CN: %u\n", version, fc, cn);
PrintAndLogEx(SUCCESS, "Simulating IOProx version: " _YELLOW_("%u") " FC: " _YELLOW_("%u (0x%02x)") " CN: " _YELLOW_("%u"), version, fc, fc, cn);
PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command");
uint8_t bs[64];
memset(bs, 0x00, sizeof(bs));
if (getIOProxBits(version, fc, cn, bs) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
return PM3_ESOFT;
@ -270,10 +247,8 @@ static int CmdIOProxSim(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs));
free(payload);
PacketResponseNG resp;
WaitForResponse(CMD_LF_FSK_SIMULATE, &resp);
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
@ -282,20 +257,39 @@ static int CmdIOProxSim(const char *Cmd) {
static int CmdIOProxClone(const char *Cmd) {
uint16_t cn = 0;
uint8_t version = 0, fc = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf io clone",
"Enables simulation of IOProx card with specified facility-code and card number.\n"
"Tag must be on the antenna when issuing this command.",
"lf io clone --vn 1 --fc 101 --cn 1337"
);
void *argtable[] = {
arg_param_begin,
arg_u64_1(NULL, "vn", "<dec>", "8bit version"),
arg_u64_1(NULL, "fc", "<dec>", "8bit facility code"),
arg_u64_1(NULL, "cn", "<dec>", "16bit card number"),
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);
uint8_t version = arg_get_u32_def(ctx, 1, 0);
uint8_t fc = arg_get_u32_def(ctx, 2, 0);
uint16_t cn = arg_get_u32_def(ctx, 3, 0);
bool q5 = arg_get_lit(ctx, 4);
bool em = arg_get_lit(ctx, 5);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint8_t bits[64];
memset(bits, 0, sizeof(bits));
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_io_clone();
version = param_get8(Cmd, 0);
fc = param_get8ex(Cmd, 1, 0, 16);
cn = param_get32ex(Cmd, 2, 0, 10);
if (!version || !fc || !cn) return usage_lf_io_clone();
if ((cn & 0xFFFF) != cn) {
cn &= 0xFFFF;
PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn);
@ -307,20 +301,39 @@ static int CmdIOProxClone(const char *Cmd) {
}
uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
bool q5 = tolower(param_getchar(Cmd, 3) == 'q');
if (q5)
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_IOPROX_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
blocks[1] = bytebits_to_byte(bits, 32);
blocks[2] = bytebits_to_byte(bits + 32, 32);
PrintAndLogEx(INFO, "Preparing to clone IOProx to " _YELLOW_("%s") " with Version: %u FC: %u, CN: %u", (q5) ? "Q5/T5555" : "T55x7", version, fc, cn);
PrintAndLogEx(INFO, "Preparing to clone IOProx to " _YELLOW_("%s") " with Version: " _GREEN_("%u") " FC: " _GREEN_("%u (0x%02x)") " CN: " _GREEN_("%u")
, cardtype
, version
, fc
, fc
, cn
);
print_blocks(blocks, ARRAYLEN(blocks));
int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
int res;
if (em) {
res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
} else {
res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
}
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf io read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf io reader`") " to verify");
return res;
}

View file

@ -29,21 +29,6 @@
static int CmdHelp(const char *Cmd);
static int usage_lf_jablotron_sim(void) {
PrintAndLogEx(NORMAL, "Enables simulation of jablotron card with specified card number.");
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf jablotron sim [h] <card ID>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card ID> : jablotron card ID");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron sim 112233"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static uint8_t jablontron_chksum(uint8_t *bits) {
uint8_t chksum = 0;
for (int i = 16; i < 56; i += 8) {
@ -151,6 +136,10 @@ static int CmdJablotronReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 16000);
demodJablotron(!cm);
@ -247,12 +236,26 @@ static int CmdJablotronClone(const char *Cmd) {
}
static int CmdJablotronSim(const char *Cmd) {
uint64_t fullcode = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf jablotron sim",
"Enables simulation of jablotron card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.",
"lf jablotron sim --cn 01b669"
);
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_jablotron_sim();
void *argtable[] = {
arg_param_begin,
arg_str1(NULL, "cn", "<hex>", "Jablotron card ID - 5 bytes max"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
fullcode = param_get64ex(Cmd, 0, 0, 16);
int raw_len = 0;
uint8_t raw[5] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
CLIParserFree(ctx);
uint64_t fullcode = bytes_to_num(raw, raw_len);
// clearing the topbit needed for the preambl detection.
if ((fullcode & 0x7FFFFFFFFF) != fullcode) {

View file

@ -206,6 +206,10 @@ static int CmdKeriReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 10000);
demodKeri(!cm);

View file

@ -33,6 +33,7 @@ int demodMotorola(bool verbose) {
PrintAndLogEx(DEBUG, "DEBUG: Error - Motorola: PSK Demod failed");
return PM3_ESOFT;
}
size_t size = DemodBufferLen;
int ans = detectMotorola(DemodBuffer, &size);
if (ans < 0) {
@ -148,6 +149,10 @@ static int CmdMotorolaReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
// Motorola Flexpass seem to work at 74 kHz
// and take about 4400 samples to befor modulating
sample_config sc = {
@ -161,10 +166,11 @@ static int CmdMotorolaReader(const char *Cmd) {
};
lf_config(&sc);
int res;
do {
// 64 * 32 * 2 * n-ish
lf_read(false, 5000);
demodMotorola(!cm);
res = demodMotorola(!cm);
} while (cm && !kbd_enter_pressed());
// reset back to 125 kHz
@ -172,7 +178,7 @@ static int CmdMotorolaReader(const char *Cmd) {
sc.samples_to_skip = 0;
lf_config(&sc);
return PM3_SUCCESS;
return res;
}
static int CmdMotorolaClone(const char *Cmd) {

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

@ -248,6 +248,10 @@ static int CmdNexWatchReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 20000);
demodNexWatch(!cm);

View file

@ -134,6 +134,10 @@ static int CmdNoralsyReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 8000);
demodNoralsy(!cm);

View file

@ -189,6 +189,10 @@ static int CmdPacReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 4096 * 2 + 20);
demodPac(!cm);

View file

@ -201,6 +201,10 @@ static int CmdParadoxReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 10000);
demodParadox(!cm);

View file

@ -9,13 +9,12 @@
// Low frequency PCF7931 commands
//-----------------------------------------------------------------------------
#include "cmdlfpcf7931.h"
#include <string.h>
#include <ctype.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
@ -37,87 +36,106 @@ int pcf7931_resetConfig(void) {
configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
PrintAndLogEx(INFO, "Configuration resetted");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 config`") " to view current settings");
return PM3_SUCCESS;
}
int pcf7931_printConfig(void) {
PrintAndLogEx(NORMAL, "Password (LSB first on bytes) : %s", sprint_hex(configPcf.Pwd, sizeof(configPcf.Pwd)));
PrintAndLogEx(NORMAL, "Tag initialization delay : %d us", configPcf.InitDelay);
PrintAndLogEx(NORMAL, "Offset low pulses width : %d us", configPcf.OffsetWidth);
PrintAndLogEx(NORMAL, "Offset low pulses position : %d us", configPcf.OffsetPosition);
PrintAndLogEx(INFO, "Password (LSB first on bytes)... " _YELLOW_("%s"), sprint_hex(configPcf.Pwd, sizeof(configPcf.Pwd)));
PrintAndLogEx(INFO, "Tag initialization delay........ " _YELLOW_("%d") " us", configPcf.InitDelay);
PrintAndLogEx(INFO, "Offset low pulses width......... " _YELLOW_("%d") " us", configPcf.OffsetWidth);
PrintAndLogEx(INFO, "Offset low pulses position...... " _YELLOW_("%d") " us", configPcf.OffsetPosition);
return PM3_SUCCESS;
}
static int usage_pcf7931_read(void) {
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 read [h] ");
PrintAndLogEx(NORMAL, "This command tries to read a PCF7931 tag.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 read");
return PM3_SUCCESS;
}
static int CmdLFPCF7931Reader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pcf7931 reader",
"read a PCF7931 tag",
"lf pcf7931 reader -@ -> continuous reader mode"
);
static int usage_pcf7931_write(void) {
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 write [h] <block address> <byte address> <data>");
PrintAndLogEx(NORMAL, "This command tries to write a PCF7931 tag.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " blockaddress Block to save [0-7]");
PrintAndLogEx(NORMAL, " byteaddress Index of byte inside block to write [0-15]");
PrintAndLogEx(NORMAL, " data one byte of data (hex)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 write 2 1 FF");
return PM3_SUCCESS;
}
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);
static int usage_pcf7931_config(void) {
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 config [h] [r] <pwd> <delay> <offset width> <offset position>");
PrintAndLogEx(NORMAL, "This command tries to set the configuration used with PCF7931 commands");
PrintAndLogEx(NORMAL, "The time offsets could be useful to correct slew rate generated by the antenna");
PrintAndLogEx(NORMAL, "Caling without some parameter will print the current configuration.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " r Reset configuration to default values");
PrintAndLogEx(NORMAL, " pwd Password, hex, 7bytes, LSB-order");
PrintAndLogEx(NORMAL, " delay Tag initialization delay (in us) decimal");
PrintAndLogEx(NORMAL, " offset Low pulses width (in us) decimal");
PrintAndLogEx(NORMAL, " offset Low pulses position (in us) decimal");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 config");
PrintAndLogEx(NORMAL, " lf pcf7931 config r");
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 20000");
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 17500 -10 30");
return PM3_SUCCESS;
}
static int CmdLFPCF7931Read(const char *Cmd) {
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_pcf7931_read();
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdLFPCF7931Config(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pcf7931 config",
"This command tries to set the configuration used with PCF7931 commands\n"
"The time offsets could be useful to correct slew rate generated by the antenna\n"
"Caling without some parameter will print the current configuration.",
"lf pcf7931 config --reset\n"
"lf pcf7931 config --pwd 11223344556677 -d 20000\n"
"lf pcf7931 config --pwd 11223344556677 -d 17500 --lw -10 --lp 30"
);
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 0) return pcf7931_printConfig();
if (ctmp == 'h') return usage_pcf7931_config();
if (ctmp == 'r') return pcf7931_resetConfig();
void *argtable[] = {
arg_param_begin,
arg_lit0("r", "reset", "Reset configuration to default values"),
arg_str0("p", "pwd", "<hex>", "Password, 7bytes, LSB-order"),
arg_u64_0("d", "delay", "<dec>", "Tag initialization delay (in us)"),
arg_int0(NULL, "lw", "<dec>", "offset, low pulses width (in us)"),
arg_int0(NULL, "lp", "<dec>", "offset, low pulses position (in us)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
if (param_gethex(Cmd, 0, configPcf.Pwd, 14)) return usage_pcf7931_config();
bool use_reset = arg_get_lit(ctx, 1);
if (use_reset) {
CLIParserFree(ctx);
return pcf7931_resetConfig();
}
configPcf.InitDelay = (param_get32ex(Cmd, 1, 0, 10) & 0xFFFF);
configPcf.OffsetWidth = (int)(param_get32ex(Cmd, 2, 0, 10) & 0xFFFF);
configPcf.OffsetPosition = (int)(param_get32ex(Cmd, 3, 0, 10) & 0xFFFF);
int pwd_len = 0;
uint8_t pwd[7] = {0};
CLIGetHexWithReturn(ctx, 2, pwd, &pwd_len);
uint32_t delay = arg_get_u32_def(ctx, 3, -1);
int ow = arg_get_int_def(ctx, 4, 0xFFFF);
int op = arg_get_int_def(ctx, 5, 0xFFFF);
CLIParserFree(ctx);
if (pwd_len && pwd_len < sizeof(pwd)) {
PrintAndLogEx(ERR, "Password must be 7 bytes");
return PM3_EINVARG;
}
if (pwd_len) {
memcpy(configPcf.Pwd, pwd, sizeof(configPcf.Pwd));
}
if (delay != -1) {
configPcf.InitDelay = (delay & 0xFFFF);
}
if (ow != 0xFFFF) {
configPcf.OffsetWidth = (ow & 0xFFFF);
}
if (op != 0xFFFF) {
configPcf.OffsetPosition =(op & 0xFFFF);
}
pcf7931_printConfig();
return PM3_SUCCESS;
@ -125,21 +143,39 @@ static int CmdLFPCF7931Config(const char *Cmd) {
static int CmdLFPCF7931Write(const char *Cmd) {
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_pcf7931_write();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pcf7931 write",
"This command tries to write a PCF7931 tag.",
"lf pcf7931 write --blk 2 --idx 1 -d FF -> Write 0xFF to block 2, index 1 "
);
uint8_t block = 0, bytepos = 0, data = 0;
void *argtable[] = {
arg_param_begin,
arg_u64_1("b", "blk", "<dec>", "[0-7] block number"),
arg_u64_1("i", "idx", "<dec>", "[0-15] index of byte inside block"),
arg_str1("d", "data", "<hex>", "one byte to be written"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t block = arg_get_u32_def(ctx, 1, 0);
uint8_t idx = arg_get_u32_def(ctx, 2, 0);
if (param_getdec(Cmd, 0, &block)) return usage_pcf7931_write();
if (param_getdec(Cmd, 1, &bytepos)) return usage_pcf7931_write();
int data_len = 0;
uint8_t data[1] = {0};
CLIGetHexWithReturn(ctx, 3, data, &data_len);
CLIParserFree(ctx);
if ((block > 7) || (bytepos > 15)) return usage_pcf7931_write();
if (block > 7) {
PrintAndLogEx(ERR, "out-of-range error, block must be between 0-7");
return PM3_EINVARG;
}
data = param_get8ex(Cmd, 2, 0, 16);
if (idx > 15) {
PrintAndLogEx(ERR, "out-of-range error, index must be between 0-15");
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Writing block: %d", block);
PrintAndLogEx(INFO, " pos: %d", bytepos);
PrintAndLogEx(INFO, " data: 0x%02X", data);
PrintAndLogEx(INFO, "Writing block %u at idx %u with data 0x%02X", block, idx, data[0]);
uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7!
memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd));
@ -148,16 +184,16 @@ static int CmdLFPCF7931Write(const char *Cmd) {
buf[9] = configPcf.InitDelay;
clearCommandBuffer();
SendCommandMIX(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf));
SendCommandMIX(CMD_LF_PCF7931_WRITE, block, idx, data[0], buf, sizeof(buf));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 reader`") " to verify");
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"read", CmdLFPCF7931Read, IfPm3Lf, "Read content of a PCF7931 transponder"},
{"reader", CmdLFPCF7931Reader, IfPm3Lf, "Read content of a PCF7931 transponder"},
{"write", CmdLFPCF7931Write, IfPm3Lf, "Write data on a PCF7931 transponder."},
{"config", CmdLFPCF7931Config, AlwaysAvailable, "Configure the password, the tags initialization delay and time offsets (optional)"},
{NULL, NULL, NULL, NULL}

View file

@ -144,6 +144,10 @@ static int CmdPrescoReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 12000);
demodPresco(!cm);

View file

@ -209,6 +209,10 @@ static int CmdPyramidReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 15000);
demodPyramid(true);

View file

@ -145,6 +145,10 @@ static int CmdSecurakeyReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 8000);
demodSecurakey(!cm);

View file

@ -304,6 +304,10 @@ static int CmdTIReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
clearCommandBuffer();
SendCommandNG(CMD_LF_TI_READ, NULL, 0);

View file

@ -87,6 +87,10 @@ static int CmdVikingReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 10000);
demodViking(true);

View file

@ -165,6 +165,10 @@ static int CmdVisa2kReader(const char *Cmd) {
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
lf_read(false, 20000);
demodVisa2k(!cm);

View file

@ -155,13 +155,26 @@ static int CmdAuto(const char *Cmd) {
CmdPlot("");
lf_read(false, 40000);
char *fname = calloc(100, sizeof(uint8_t));
AppendDate(fname, 100, "f lf_unknown_%Y-%m-%d_%H:%M");
AppendDate(fname, 100, "-f lf_unknown_%Y-%m-%d_%H:%M");
CmdSave(fname);
free(fname);
return PM3_SUCCESS;
}
int CmdRem(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "rem",
"Add a text line in log file",
"rem"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
char buf[22] = {0};
AppendDate(buf, sizeof(buf), NULL);
PrintAndLogEx(NORMAL, "%s remark: %s", buf, Cmd);

View file

@ -13,6 +13,7 @@
#include <string.h>
#include "proxguiqt.h"
#include "proxmark3.h"
#include "ui.h" // for prints
static ProxGuiQT *gui = NULL;
static WorkerThread *main_loop_thread = NULL;
@ -28,8 +29,15 @@ void WorkerThread::run() {
}
extern "C" void ShowGraphWindow(void) {
if (!gui)
if (!gui) {
// Show a notice if X11/XQuartz isn't available
#if defined(__MACH__) && defined(__APPLE__)
PrintAndLogEx(WARNING, "You appear to be on a MacOS device without XQuartz.\nYou may need to install XQuartz (https://www.xquartz.org/) to make the plot work.");
#else
PrintAndLogEx(WARNING, "You appear to be on an environment without an X11 server or without DISPLAY environment variable set.\nPlot may not work until you resolve these issues.");
#endif
return;
}
gui->ShowGraphWindow();
}

View file

@ -139,7 +139,9 @@ endif
ifneq ($(strip $(filter $(PLATFORM_DEFS),$(STANDALONE_REQ_DEFS))),$(strip $(STANDALONE_REQ_DEFS)))
$(error Chosen Standalone mode $(STANDALONE) requires $(strip $(STANDALONE_REQ_DEFS)), unsupported by $(PLTNAME))
endif
PLATFORM_DEFS+=$(STANDALONE_PLATFORM_DEFS)
ifneq (,$(STANDALONE_PLATFORM_DEFS))
PLATFORM_DEFS+=$(STANDALONE_PLATFORM_DEFS)
endif
$(info $(findstring WITH_STANDALONE_*,$(PLATFORM_DEFS)))

View file

@ -1,6 +1,5 @@
clear
pref
rem
analyse lcr
analyse crc
analyse chksum
@ -79,8 +78,6 @@ hf felica resetmode
hf felica litesim
hf felica litedump
hf fido info
hf iclass info
hf iclass permutekey
hf legic reader
hf legic info
hf legic dump
@ -197,7 +194,6 @@ lf em 4x50_write
lf em 4x50_write_password
lf em 4x50_read
lf em 4x50_wipe
lf hid read
lf hitag info
lf hitag reader
lf hitag sim
@ -205,20 +201,6 @@ lf hitag sniff
lf hitag writer
lf hitag dump
lf hitag cc
lf indala demod
lf indala altdemod
lf indala sim
lf io clone
lf io sim
lf io watch
lf jablotron sim
lf nedap generate
lf nedap read
lf nedap clone
lf nedap sim
lf pcf7931 read
lf pcf7931 write
lf pcf7931 config
lf t55xx config
lf t55xx dangerraw
lf t55xx detect

View file

@ -649,7 +649,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`lf hid help `|Y |`this help`
|`lf hid demod `|Y |`demodulate HID Prox tag from the GraphBuffer`
|`lf hid read `|N |`attempt to read and extract tag data`
|`lf hid reader `|N |`attempt to read and extract tag data`
|`lf hid clone `|N |`clone HID tag to T55x7`
|`lf hid sim `|N |`simulate HID tag`
|`lf hid brute `|N |`bruteforce card number against reader`
@ -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`
@ -824,7 +823,7 @@ Check column "offline" for their availability.
|command |offline |description
|------- |------- |-----------
|`lf pcf7931 help `|Y |`This help`
|`lf pcf7931 read `|N |`Read content of a PCF7931 transponder`
|`lf pcf7931 reader `|N |`Read content of a PCF7931 transponder`
|`lf pcf7931 write `|N |`Write data on a PCF7931 transponder.`
|`lf pcf7931 config `|Y |`Configure the password, the tags initialization delay and time offsets (optional)`

View file

@ -238,6 +238,8 @@ hf 14a info
## MIFARE Classic DirectWrite aka Gen2 aka CUID
(also referred as MCT compatible by some sellers)
### Identify
```

View file

@ -391,7 +391,7 @@ while true; do
"Fmt 26 FC: 123 Card: 1337 checksum: 10"; then break; fi
if ! CheckExecute slow "lf T55 indala_224 test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_indala_224.pm3; lf search 1'" "Indala ID found"; then break; fi
if ! CheckExecute slow "lf T55 indala_224 test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_indala_224.pm3; lf indala demod'" \
"Indala - len 224, Raw: 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"; then break; fi
"Indala - len 224 Raw: 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"; then break; fi
if ! CheckExecute slow "lf T55 io test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_io.pm3; lf search 1'" "IO Prox ID found"; then break; fi
if ! CheckExecute slow "lf T55 io test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_io.pm3; lf io demod'" \
"IO Prox - XSF(01)01:01337, Raw: 007840603059cf3f (ok)"; then break; fi
@ -412,7 +412,7 @@ while true; do
"Motorola - fmt: 26 FC: 258 Card: 2, Raw: A0000000A0002021"; then break; fi
if ! CheckExecute slow "lf T55 nedap test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nedap.pm3; lf search 1'" "NEDAP ID found"; then break; fi
if ! CheckExecute slow "lf T55 nedap test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nedap.pm3; lf nedap demod'" \
"NEDAP - Card: 12345 subtype: 1 customer code: 123, Raw: FF82246508209953"; then break; fi
"NEDAP (64b) - ID: 12345 subtype: 1 customer code: 291 / 0x123 Raw: FF82246508209953"; then break; fi
if ! CheckExecute slow "lf T55 nexwatch test" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nexwatch.pm3; lf search 1'" "NexWatch ID found"; then break; fi
if ! CheckExecute slow "lf T55 nexwatch test2" "$CLIENTBIN -c 'data load -f traces/lf_ATA5577_nexwatch.pm3; lf nexwatch demod'" \
"Raw : 56000000213C9F8F150C00"; then break; fi