lf gallagher - now uses cliparser, supports continuous mode, EM (untested)

This commit is contained in:
iceman1001 2020-11-29 12:49:09 +01:00
commit c05f75c551
5 changed files with 251 additions and 113 deletions

View file

@ -30,6 +30,7 @@
#define EM4305_NORALSY_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK, data rate 32, 3 data blocks
#define EM4305_PRESCO_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(4) ) // ASK/MAN, data rate 32, 4 data blocks
#define EM4305_SECURAKEY_CONFIG_BLOCK (EM4x05_SET_BITRATE(40) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK/MAN, data rate 40, 3 data blocks
#define EM4305_GALLAGHER_CONFIG_BLOCK (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(3) ) // ASK/MAN, data rate 32, 3 data blocks
#define EM4305_HID_26_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks
#define EM4305_PARADOX_CONFIG_BLOCK (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_SET_NUM_BLOCKS(3) ) // FSK2a, hid 26 bit, data rate 50, 3 data blocks

View file

@ -10,7 +10,7 @@
// sample Q5 , ASK RF/32, STT, 96 bits (3blocks) ( 0x9000F006)
//-----------------------------------------------------------------------------
#include "cmdlfgallagher.h"
#include <string.h> // memcpy
#include <ctype.h> // tolower
#include <stdio.h>
#include "commonutil.h" // ARRAYLEN
@ -24,22 +24,11 @@
#include "protocols.h" // t55xx defines
#include "cmdlft55xx.h" // clone..
#include "crc.h" // CRC8/Cardx
#include "cmdlfem4x05.h" //
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
static int usage_lf_gallagher_clone(void) {
PrintAndLogEx(NORMAL, "clone a GALLAGHER tag to a T55x7 tag.");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf gallagher clone [h] [b <raw hex>]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf gallagher clone b 0FFD5461A9DA1346B2D1AC32"));
return PM3_SUCCESS;
}
static void descramble(uint8_t *arr, uint8_t len) {
uint8_t lut[] = {
@ -134,71 +123,163 @@ int demodGallagher(bool verbose) {
}
static int CmdGallagherDemod(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf gallagher demod",
"Try to find GALLAGHER preamble, if found decode / descramble data",
"lf gallagher demod"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
return demodGallagher(true);
}
static int CmdGallagherRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
static int CmdGallagherReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf gallagher reader",
"read a GALLAGHER tag",
"lf gallagher 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);
do {
lf_read(false, 4096 * 2 + 20);
return demodGallagher(true);
demodGallagher(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdGallagherClone(const char *Cmd) {
uint32_t blocks[4];
bool errors = false;
uint8_t cmdp = 0;
int datalen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf gallagher clone",
"clone a GALLAGHER tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf gallagher clone --raw 0FFD5461A9DA1346B2D1AC32\n"
"lf gallagher clone --q5 --raw 0FFD5461A9DA1346B2D1AC32 -> encode for Q5/T5555 tag\n"
"lf gallagher clone --em --raw 0FFD5461A9DA1346B2D1AC32 -> encode for EM4305/4469"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_lf_gallagher_clone();
case 'b': {
void *argtable[] = {
arg_param_begin,
arg_str1("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
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);
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t rawhex[12] = {0};
int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen);
if (res != 0)
errors = true;
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint32_t blocks[4];
for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) {
blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t));
blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t));
}
cmdp += 2;
break;
}
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors || cmdp == 0) return usage_lf_gallagher_clone();
//Pac - compat mode, NRZ, data rate 40, 3 data blocks
blocks[0] = T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 3 << T55x7_MAXBLOCK_SHIFT;
char cardtype[16] = {"T55x7"};
// Q5
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | 3 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
PrintAndLogEx(INFO, "Preparing to clone Gallagher to T55x7 with raw hex");
// EM4305
if (em) {
blocks[0] = EM4305_GALLAGHER_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
PrintAndLogEx(INFO, "Preparing to clone Gallagher to " _YELLOW_("%s") " with raw hex", cardtype);
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 gallagher read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf gallagher reader`") " to verify");
return res;
}
static int CmdGallagherSim(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf gallagher sim",
"Enables simulation of GALLAGHER card with specified card number.\n"
"Simulation runs until the button is pressed or another USB command is issued.\n",
"lf gallagher sim --raw 0FFD5461A9DA1346B2D1AC32"
);
void *argtable[] = {
arg_param_begin,
arg_str1("r", "raw", "<hex>", "raw hex data. 12 bytes max"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int raw_len = 0;
// skip first block, 3*4 = 12 bytes left
uint8_t raw[12] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
CLIParserFree(ctx);
// ASK/MAN sim.
PrintAndLogEx(INFO, " To be implemented, feel free to contribute!");
PrintAndLogEx(SUCCESS, "Simulating Gallagher - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw)));
uint8_t bs[sizeof(raw) * 8];
bytes_to_bytebits(raw, sizeof(raw), bs);
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + sizeof(bs));
payload->encoding = 1;
payload->invert = 0;
payload->separator = 0;
payload->clock = 32;
memcpy(payload->data, bs, sizeof(bs));
clearCommandBuffer();
SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs));
free(payload);
PacketResponseNG resp;
WaitForResponse(CMD_LF_ASK_SIMULATE, &resp);
PrintAndLogEx(INFO, "Done");
if (resp.status != PM3_EOPABORTED)
return resp.status;
return PM3_SUCCESS;
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdGallagherDemod, AlwaysAvailable, "Demodulate an GALLAGHER tag from the GraphBuffer"},
{"read", CmdGallagherRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"reader", CmdGallagherReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdGallagherClone, IfPm3Lf, "clone GALLAGHER tag to T55x7"},
{"sim", CmdGallagherSim, IfPm3Lf, "simulate GALLAGHER tag"},
{NULL, NULL, NULL, NULL}

View file

@ -9,12 +9,10 @@
//-----------------------------------------------------------------------------
#include "cmdlfjablotron.h"
#include <string.h>
#include <inttypes.h>
#include <stdlib.h>
#include <ctype.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "commonutil.h" // ARRAYLEN
@ -24,25 +22,13 @@
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
#include "cliparser.h"
#include "cmdlfem4x05.h" // EM defines
#define JABLOTRON_ARR_LEN 64
static int CmdHelp(const char *Cmd);
static int usage_lf_jablotron_clone(void) {
PrintAndLogEx(NORMAL, "clone a Jablotron tag to a T55x7 or Q5/T5555 tag.");
PrintAndLogEx(NORMAL, "Usage: lf jablotron clone [h] <card ID> <Q5>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <card ID> : jablotron card ID");
PrintAndLogEx(NORMAL, " <Q5> : specify writing to Q5/T5555 tag");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" lf jablotron clone 112233"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
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.");
@ -134,30 +120,93 @@ int demodJablotron(bool verbose) {
//see ASKDemod for what args are accepted
static int CmdJablotronDemod(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf jablotron demod",
"Try to find Jablotron preamble, if found decode / descramble data",
"lf jablotron demod\n"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
return demodJablotron(true);
}
static int CmdJablotronRead(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
static int CmdJablotronReader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf jablotron reader",
"read a jablotron tag",
"lf jablotron 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);
do {
lf_read(false, 16000);
return demodJablotron(true);
demodJablotron(!cm);
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdJablotronClone(const char *Cmd) {
uint64_t fullcode = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf jablotron clone",
"clone a Jablotron tag to a T55x7, Q5/T5555 or EM4305/4469 tag.",
"lf jablotron clone --cn 01b669\n"
"lf jablotron clone --q5 --cn 01b669 -> encode for Q5/T5555 tag\n"
"lf jablotron clone --em --cn 01b669 -> encode for EM4305/4469"
);
void *argtable[] = {
arg_param_begin,
arg_str1(NULL, "cn", "<hex>", "Jablotron card ID - 5 bytes max"),
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);
int raw_len = 0;
uint8_t raw[5] = {0};
CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
bool q5 = arg_get_lit(ctx, 2);
bool em = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (q5 && em) {
PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
return PM3_EINVARG;
}
uint32_t blocks[3] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_jablotron_clone();
fullcode = param_get64ex(Cmd, 0, 0, 16);
char cardtype[16] = {"T55x7"};
// Q5
bool q5 = tolower(param_getchar(Cmd, 1)) == 'q';
if (q5)
if (q5) {
blocks[0] = T5555_FIXED | T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
}
// EM4305
if (em) {
blocks[0] = EM4305_JABLOTRON_CONFIG_BLOCK;
snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
}
uint64_t fullcode = bytes_to_num(raw, raw_len);
// clearing the topbit needed for the preambl detection.
if ((fullcode & 0x7FFFFFFFFF) != fullcode) {
@ -181,10 +230,20 @@ static int CmdJablotronClone(const char *Cmd) {
free(bits);
PrintAndLogEx(INFO, "Preparing to clone Jablotron to " _YELLOW_("%s") " with FullCode: %"PRIx64, (q5) ? "Q5/T5555" : "T55x7", fullcode);
uint64_t id = getJablontronCardId(fullcode);
PrintAndLogEx(INFO, "Preparing to clone Jablotron to " _YELLOW_("%s") " with FullCode: " _GREEN_("%"PRIx64)" id: " _GREEN_("%"PRIx64), cardtype, fullcode, id);
print_blocks(blocks, ARRAYLEN(blocks));
return 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 jablotron reader`") " to verify");
return res;
}
static int CmdJablotronSim(const char *Cmd) {
@ -201,7 +260,7 @@ static int CmdJablotronSim(const char *Cmd) {
PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode);
}
PrintAndLogEx(SUCCESS, "Simulating Jablotron - FullCode: %"PRIx64, fullcode);
PrintAndLogEx(SUCCESS, "Simulating Jablotron - FullCode: " _YELLOW_("%"PRIx64), fullcode);
uint8_t *bs = calloc(JABLOTRON_ARR_LEN, sizeof(uint8_t));
if (bs == NULL) {
@ -236,7 +295,7 @@ static int CmdJablotronSim(const char *Cmd) {
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"demod", CmdJablotronDemod, AlwaysAvailable, "Demodulate an Jablotron tag from the GraphBuffer"},
{"read", CmdJablotronRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"reader", CmdJablotronReader, IfPm3Lf, "Attempt to read and extract tag data from the antenna"},
{"clone", CmdJablotronClone, IfPm3Lf, "clone jablotron tag to T55x7 or Q5/T5555"},
{"sim", CmdJablotronSim, IfPm3Lf, "simulate jablotron tag"},
{NULL, NULL, NULL, NULL}

View file

@ -229,10 +229,7 @@ lf fdxb demod
lf fdxb read
lf fdxb clone
lf fdxb sim
lf gallagher demod
lf gallagher read
lf gallagher clone
lf gallagher sim
lf gproxii demod
lf gproxii read
lf gproxii clone