mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-21 07:46:12 +08:00
Merge pull request #1996 from jerji/master
Add ability to simulate paradox fobs from fc and cn
This commit is contained in:
commit
005fddfe6d
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#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", "<hex>", " raw hex data. 12 bytes"),
|
||||
arg_str0("r", "raw", "<hex>", "raw hex data. 12 bytes"),
|
||||
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
|
||||
arg_u64_0(NULL, "cn", "<dec>", "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"},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <hex> raw hex data. 12 bytes"
|
||||
"-r, --raw <hex> raw hex data. 12 bytes",
|
||||
"--fc <dec> facility code",
|
||||
"--cn <dec> card number"
|
||||
],
|
||||
"usage": "lf paradox sim [-h] [-r <hex>]"
|
||||
"usage": "lf paradox sim [-h] [-r <hex>] [--fc <dec>] [--cn <dec>]"
|
||||
},
|
||||
"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"
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue