diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d8885d30..21c43c33c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,7 +70,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Updated documentation for installation on macOS with MacPorts (@linuxgemini) - Added possible Paxton id to hitag2 tag info output - Changed `hf mf sim` - reduce 50ms threshold to 6ms for reset to idle #1974 (@net147) - - Updated `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz) + - Update `amiibo_tools.lua` with new identifiers and create a python script `update_amiibo_tools_lua.py` to automate the process in the future. (@CorySolovewicz) + - Added `lf paradox sim --fc --cn` - Simulates Paradox fob from facility code and card number (jerji) + ## [Nitride.4.16191][2023-01-29] - Changed `build_all_firmwares.sh` to fit GENERIC 256kb firmware images (@doegox) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 848f6cab0..e6585d334 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1680,7 +1680,7 @@ int CmdLFfind(const char *Cmd) { goto out; } } - if (demodParadox(true) == PM3_SUCCESS) { + if (demodParadox(true, false) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); if (search_cont) { found++; diff --git a/client/src/cmdlfparadox.c b/client/src/cmdlfparadox.c index a2fa50f11..d750efa51 100644 --- a/client/src/cmdlfparadox.c +++ b/client/src/cmdlfparadox.c @@ -20,7 +20,6 @@ #include #include #include -#include #include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" @@ -53,7 +52,55 @@ static const uint8_t paradox_lut[] = { // Paradox Prox demod - FSK2a RF/50 with preamble of 00001111 (then manchester encoded) // print full Paradox Prox ID and some bit format details if found -int demodParadox(bool verbose) { +// This function will calculate the bitstream for a paradox card and place the result in bs. +// It returns the calculated CRC from the fc and cn. +// CRC calculation by mwalker33 +static uint8_t GetParadoxBits(const uint32_t fc, const uint32_t cn, unsigned int *bs) { + + uint8_t manchester[13] = { 0x00 }; // check size needed + uint32_t t1; + + manchester[0] = 0x0F; // preamble + manchester[1] = 0x05; // Leading zeros - Note: from this byte on, is part of the CRC calculation + manchester[2] = 0x55; // Leading zeros its 4 bits out for the CRC, so we need to move + manchester[3] = 0x55; // Leading zeros back 4 bits once we have the crc (done below) + + // add FC + t1 = manchesterEncode2Bytes(fc); + manchester[4] = (t1 >> 8) & 0xFF; + manchester[5] = t1 & 0xFF; + + // add cn + t1 = manchesterEncode2Bytes(cn); + manchester[6] = (t1 >> 24) & 0xFF; + manchester[7] = (t1 >> 16) & 0xFF; + manchester[8] = (t1 >> 8) & 0xFF; + manchester[9] = t1 & 0xFF; + + uint8_t crc = (CRC8Maxim(manchester + 1, 9) ^ 0x6) & 0xFF; + + // add crc + t1 = manchesterEncode2Bytes(crc); + manchester[10] = (t1 >> 8) & 0xFF; + manchester[11] = t1 & 0xFF; + + // move left 4 bits left 4 bits - Now that we have the CRC we need to re-align the data. + for (int i = 1; i < 12; i++) + manchester[i] = (manchester[i] << 4) + (manchester[i + 1] >> 4); + + // Add trailing 1010 (11) + manchester[11] |= (1 << 3); + manchester[11] |= (1 << 1); + + // move into tag blocks + + for (int i = 0; i < 12; i++) + bs[1 + (i / 4)] += (manchester[i] << (8 * (3 - i % 4))); + + return crc; +} + +int demodParadox(bool verbose, bool oldChksum) { (void) verbose; // unused so far //raw fsk demod no manchester decoding no start bit finding just get binary from wave uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; @@ -134,34 +181,39 @@ int demodParadox(bool verbose) { uint32_t fc = ((hi & 0x3) << 6) | (lo >> 26); uint32_t cardnum = (lo >> 10) & 0xFFFF; uint8_t chksum = (lo >> 2) & 0xFF; + if (oldChksum) { + // Calc CRC & Checksum + // 000088f0b - FC: 8 - Card: 36619 - Checksum: 05 - RAW: 0f55555559595aa559a5566a + // checksum? + uint8_t calc_chksum = 0x47; + uint8_t pos = 0; + for (uint8_t i = 0; i < 8; i++) { + uint8_t ice = rawhex[i + 1]; + for (uint8_t j = 0x80; j > 0; j >>= 2) { - // Calc CRC & Checksum - // 000088f0b - FC: 8 - Card: 36619 - Checksum: 05 - RAW: 0f55555559595aa559a5566a - // checksum? - uint8_t calc_chksum = 0x47; - uint8_t pos = 0; - for (uint8_t i = 0; i < 8; i++) { - - uint8_t ice = rawhex[i + 1]; - for (uint8_t j = 0x80; j > 0; j >>= 2) { - - if (ice & j) { - calc_chksum ^= paradox_lut[pos]; + if (ice & j) { + calc_chksum ^= paradox_lut[pos]; + } + pos++; } - pos++; } + uint32_t crc = CRC8Maxim(rawhex + 1, 8); + PrintAndLogEx(INFO, " FSK/MAN raw : %s", sprint_hex(rawhex, sizeof(rawhex))); + PrintAndLogEx(INFO, " raw : %s = (maxim crc8) %02x == %02x", sprint_hex(rawhex + 1, 8), crc, + calc_chksum); + // PrintAndLogEx(DEBUG, " OTHER sample CRC-8/MAXIM : 55 55 69 A5 55 6A 59 5A = FC"); } - - uint32_t crc = CRC8Maxim(rawhex + 1, 8); - PrintAndLogEx(DEBUG, " FSK/MAN raw : %s", sprint_hex(rawhex, sizeof(rawhex))); - PrintAndLogEx(DEBUG, " raw : %s = (maxim crc8) %02x == %02x", sprint_hex(rawhex + 1, 8), crc, calc_chksum); -// PrintAndLogEx(DEBUG, " OTHER sample CRC-8/MAXIM : 55 55 69 A5 55 6A 59 5A = FC"); - uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32); uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32); + uint32_t blocks[4] = {0}; + uint8_t crc = GetParadoxBits(fc, cardnum, blocks); + if (chksum != crc) + PrintAndLogEx(ERR, "CRC Error! Calculated CRC is " _GREEN_("%d") " but card CRC is " _RED_("%d") ".", crc, chksum); + + PrintAndLogEx(INFO, "Paradox - ID: " _GREEN_("%x%08x") " FC: " _GREEN_("%d") " Card: " _GREEN_("%d") ", Checksum: %02x, Raw: %08x%08x%08x", hi >> 10, (hi & 0x3) << 26 | (lo >> 10), @@ -185,32 +237,37 @@ static int CmdParadoxDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf paradox demod", "Try to find Paradox preamble, if found decode / descramble data", - "lf paradox demod" + "lf paradox demod --old -> Display previous checksum version" ); void *argtable[] = { arg_param_begin, + arg_lit0(NULL, "old", "optional - Display previous checksum version"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + bool old = arg_get_lit(ctx, 1); CLIParserFree(ctx); - return demodParadox(true); + return demodParadox(true, old); } static int CmdParadoxReader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf paradox reader", "read a Paradox tag", - "lf Paradox reader -@ -> continuous reader mode" + "lf paradox reader -@ -> continuous reader mode\n" + "lf paradox reader --old -> Display previous checksum version" ); void *argtable[] = { arg_param_begin, arg_lit0("@", NULL, "optional - continuous reader mode"), + arg_lit0(NULL, "old", "optional - Display previous checksum version"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool cm = arg_get_lit(ctx, 1); + bool old = arg_get_lit(ctx, 2); CLIParserFree(ctx); if (cm) { @@ -219,7 +276,7 @@ static int CmdParadoxReader(const char *Cmd) { do { lf_read(false, 10000); - demodParadox(!cm); + demodParadox(!cm, old); } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; @@ -230,7 +287,7 @@ static int CmdParadoxClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf paradox clone", "clone a paradox tag to a T55x7, Q5/T5555 or EM4305/4469 tag.", - "lf paradox clone --fc 96 --cn 40426 -> encode for T55x7 tag with fc and cn\n" + "lf paradox clone --fc 96 --cn 40426 -> encode for T55x7 tag with fc and cn\n" "lf paradox clone --raw 0f55555695596a6a9999a59a -> encode for T55x7 tag\n" "lf paradox clone --raw 0f55555695596a6a9999a59a --q5 -> encode for Q5/T5555 tag\n" "lf paradox clone --raw 0f55555695596a6a9999a59a --em -> encode for EM4305/4469" @@ -263,6 +320,16 @@ static int CmdParadoxClone(const char *Cmd) { return PM3_EINVARG; } + if ((fc || cn) && raw_len != 0) { + PrintAndLogEx(FAILED, "Can't specify both FC/CN and RAW at the same time"); + return PM3_EINVARG; + } + + if (fc > 999 || cn > 99999) { + PrintAndLogEx(FAILED, "FC has a max value of 999 and CN has a max value of 99999"); + return PM3_EINVARG; + } + uint32_t blocks[4] = {0}; if (raw_len != 0) { @@ -275,44 +342,8 @@ static int CmdParadoxClone(const char *Cmd) { blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); } } else { - uint8_t manchester[13] = { 0x00 }; // check size needed - uint32_t t1; - - manchester[0] = 0x0F; // preamble - manchester[1] = 0x05; // Leading zeros - Note: from this byte on, is part of the CRC calculation - manchester[2] = 0x55; // Leading zeros its 4 bits out for the CRC, so we need too move - manchester[3] = 0x55; // Leading zeros back 4 bits once we have the crc (done below) - - // add FC - t1 = manchesterEncode2Bytes(fc); - manchester[4] = (t1 >> 8) & 0xFF; - manchester[5] = t1 & 0xFF; - - // add cn - t1 = manchesterEncode2Bytes(cn); - manchester[6] = (t1 >> 24) & 0xFF; - manchester[7] = (t1 >> 16) & 0xFF; - manchester[8] = (t1 >> 8) & 0xFF; - manchester[9] = t1 & 0xFF; - - uint8_t crc = (CRC8Maxim(manchester + 1, 9) ^ 0x6) & 0xFF; - - // add crc - t1 = manchesterEncode2Bytes(crc); - manchester[10] = (t1 >> 8) & 0xFF; - manchester[11] = t1 & 0xFF; - - // move left 4 bits left 4 bits - Now that we have the CRC we need to re-align the data. - for (int i = 1; i < 12; i++) - manchester[i] = (manchester[i] << 4) + (manchester[i + 1] >> 4); - - // Add trailing 1010 (11) - manchester[11] |= (1 << 3); - manchester[11] |= (1 << 1); - - // move into tag blocks - for (int i = 0; i < 12; i++) - blocks[1 + (i / 4)] += (manchester[i] << (8 * (3 - i % 4))); + //This function generates the bitstream and puts it in blocks. it returns the crc, but we don't need it here + GetParadoxBits(fc, cn, blocks); } // Paradox - FSK2a, data rate 50, 3 data blocks @@ -355,12 +386,15 @@ static int CmdParadoxSim(const char *Cmd) { CLIParserInit(&ctx, "lf paradox sim", "Enables simulation of paradox card with specified card number.\n" "Simulation runs until the button is pressed or another USB command is issued.", - "lf paradox sim --raw 0f55555695596a6a9999a59a" + "lf paradox sim --raw 0f55555695596a6a9999a59a -> simulate tag\n" + "lf paradox sim --fc 96 --cn 40426 -> simulate tag with fc and cn\n" ); void *argtable[] = { arg_param_begin, - arg_str0("r", "raw", "", " raw hex data. 12 bytes"), + arg_str0("r", "raw", "", "raw hex data. 12 bytes"), + arg_u64_0(NULL, "fc", "", "facility code"), + arg_u64_0(NULL, "cn", "", "card number"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -369,13 +403,32 @@ static int CmdParadoxSim(const char *Cmd) { // skip first block, 3*4 = 12 bytes left uint8_t raw[12] = {0}; CLIGetHexWithReturn(ctx, 1, raw, &raw_len); + + uint32_t fc = arg_get_u32_def(ctx, 2, 0); + uint32_t cn = arg_get_u32_def(ctx, 3, 0); CLIParserFree(ctx); - if (raw_len != 12) { - PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len); + if ((fc || cn) && raw_len != 0) { + PrintAndLogEx(FAILED, "Can't specify both FC/CN and RAW at the same time"); return PM3_EINVARG; } + if (fc > 999 || cn > 99999) { + PrintAndLogEx(FAILED, "FC has a max value of 999 and CN has a max value of 99999"); + return PM3_EINVARG; + } + if (raw_len != 0) { + if (raw_len != 12) { + PrintAndLogEx(ERR, "Data must be 12 bytes (24 HEX characters) %d", raw_len); + return PM3_EINVARG; + } + } else { + uint32_t blocks[4] = {0}; + GetParadoxBits(fc, cn, blocks); + for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + num_to_bytes(blocks[i], sizeof(uint32_t), raw + ((i - 1) * 4)); + } + } PrintAndLogEx(SUCCESS, "Simulating Paradox - raw " _YELLOW_("%s"), sprint_hex_inrow(raw, sizeof(raw))); uint8_t bs[sizeof(raw) * 8]; @@ -404,21 +457,8 @@ static int CmdParadoxSim(const char *Cmd) { return PM3_SUCCESS; } -/* - if (sscanf(Cmd, "%u %u", &fc, &cn) != 2) return usage_lf_paradox_sim(); - facilitycode = (fc & 0x000000FF); - cardnumber = (cn & 0x0000FFFF); - - // if ( GetParadoxBits(facilitycode, cardnumber, bs) != PM3_SUCCESS) { - // PrintAndLogEx(ERR, "Error with tag bitstream generation."); - // return 1; - // } - - PrintAndLogEx(NORMAL, "Simulating Paradox - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber); - -*/ static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"demod", CmdParadoxDemod, AlwaysAvailable, "demodulate a Paradox FSK tag from the GraphBuffer"}, diff --git a/client/src/cmdlfparadox.h b/client/src/cmdlfparadox.h index 010f08301..142ee19a7 100644 --- a/client/src/cmdlfparadox.h +++ b/client/src/cmdlfparadox.h @@ -22,6 +22,6 @@ int CmdLFParadox(const char *Cmd); -int demodParadox(bool verbose); +int demodParadox(bool verbose, bool oldChksum); int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx); #endif diff --git a/doc/commands.json b/doc/commands.json index 70b10c521..efb03edd2 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -9658,13 +9658,14 @@ "command": "lf paradox demod", "description": "Try to find Paradox preamble, if found decode / descramble data", "notes": [ - "lf paradox demod" + "lf paradox demod --old -> Display previous checksum version" ], "offline": true, "options": [ - "-h, --help This help" + "-h, --help This help", + "--old optional - Display previous checksum version" ], - "usage": "lf paradox demod [-h]" + "usage": "lf paradox demod [-h] [--old]" }, "lf paradox help": { "command": "lf paradox help", @@ -9678,27 +9679,32 @@ "command": "lf paradox reader", "description": "read a Paradox tag", "notes": [ - "lf Paradox reader -@ -> continuous reader mode" + "lf paradox reader -@ -> continuous reader mode", + "lf paradox reader --old -> Display previous checksum version" ], "offline": false, "options": [ "-h, --help This help", - "-@ optional - continuous reader mode" + "-@ optional - continuous reader mode", + "--old optional - Display previous checksum version" ], - "usage": "lf paradox reader [-h@]" + "usage": "lf paradox reader [-h@] [--old]" }, "lf paradox sim": { "command": "lf paradox sim", "description": "Enables simulation of paradox card with specified card number. Simulation runs until the button is pressed or another USB command is issued.", "notes": [ - "lf paradox sim --raw 0f55555695596a6a9999a59a" + "lf paradox sim --raw 0f55555695596a6a9999a59a -> simulate tag", + "lf paradox sim --fc 96 --cn 40426 -> simulate tag with fc and cn" ], "offline": false, "options": [ "-h, --help This help", - "-r, --raw raw hex data. 12 bytes" + "-r, --raw raw hex data. 12 bytes", + "--fc facility code", + "--cn card number" ], - "usage": "lf paradox sim [-h] [-r ]" + "usage": "lf paradox sim [-h] [-r ] [--fc ] [--cn ]" }, "lf pcf7931 config": { "command": "lf pcf7931 config", @@ -12018,6 +12024,7 @@ "metadata": { "commands_extracted": 755, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2023-06-02T08:44:26" + "extracted_on": "2023-06-04T15:36:56" + } } \ No newline at end of file