mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
Merge branch 'master' into update_4x50
merge 20120merge 2012033
This commit is contained in:
commit
d546936f5c
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ static int CmdHfLTOInfo(const char *Cmd) {
|
|||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
return infoLTO(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)`
|
||||
|
||||
|
|
|
@ -238,6 +238,8 @@ hf 14a info
|
|||
|
||||
## MIFARE Classic DirectWrite aka Gen2 aka CUID
|
||||
|
||||
(also referred as MCT compatible by some sellers)
|
||||
|
||||
### Identify
|
||||
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue