From c23552f255c369cdc81677c57415f8c308258f36 Mon Sep 17 00:00:00 2001 From: rioux Date: Wed, 23 Jun 2021 14:49:59 +0200 Subject: [PATCH 1/8] TODO --- client/src/cmdlfnexwatch.c | 219 ++++++++++++++++++++++++++++++++----- 1 file changed, 189 insertions(+), 30 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index d46c40046..c73f8ef04 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -24,6 +24,8 @@ #include "cmdlft55xx.h" // clone.. #include "cmdlfem4x05.h" // #include "cliparser.h" +#include + typedef enum { SCRAMBLE, @@ -52,7 +54,7 @@ static uint8_t nexwatch_parity(uint8_t hexid[5]) { } /// NETWATCH checksum -/// @param magic = 0xBE Quadrakey, 0x88 Nexkey +/// @param magic = 0xBE Quadrakey, 0x88 Nexkey, 0x86 EC /// @param id = descrambled id (printed card number) /// @param parity = the parity based upon the scrambled raw id. static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { @@ -108,6 +110,21 @@ static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *s return PM3_SUCCESS; } +static int nexwatch_magic_bruteforce(uint32_t cn, uint8_t calc_parity, uint8_t chk) { + uint8_t magic = 0; + uint8_t temp_checksum; + for (; magic < 255; magic++) { + temp_checksum = nexwatch_checksum(magic, cn, calc_parity); + if (temp_checksum == chk) { + PrintAndLogEx(SUCCESS, " Magic number : " _GREEN_("0x%X"), magic); + return PM3_SUCCESS; + } + } + PrintAndLogEx(DEBUG, "DEBUG: Error - Magic number not found"); + return PM3_ESOFT; +} + + int demodNexWatch(bool verbose) { (void) verbose; // unused so far if (PSKDemod(0, 0, 100, false) != PM3_SUCCESS) { @@ -138,6 +155,7 @@ int demodNexWatch(bool verbose) { idx += 4; setDemodBuff(DemodBuffer, size, idx); + PrintAndLogEx(SUCCESS, "Indice: %x %s", DemodBuffer, DemodBuffer); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); if (invert) { @@ -204,9 +222,13 @@ int demodNexWatch(bool verbose) { if (m_idx < ARRAYLEN(items)) { PrintAndLogEx(SUCCESS, " fingerprint : " _GREEN_("%s"), items[m_idx].desc); + } else { + nexwatch_magic_bruteforce(cn, calc_parity, chk); } - PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); PrintAndLogEx(SUCCESS, " mode : %x", mode); + PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); + PrintAndLogEx(SUCCESS, " Scambled : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", scambled, scambled); + if (parity == calc_parity) { PrintAndLogEx(DEBUG, " parity : %s (0x%X)", _GREEN_("ok"), parity); @@ -257,12 +279,90 @@ static int CmdNexWatchReader(const char *Cmd) { } do { - lf_read(false, 20000); + lf_read(true, 20000); demodNexWatch(!cm); } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } +//TOCHANGE +static unsigned int bin2int(unsigned char *b, int size) { + unsigned int val = 0; + for (int i = 0; i < size; i++) { + if (b[i] == '1') { + val += pow(2, size - 1 - i); + } + } + return val; +} +static BYTE xor_parity(BYTE *stream_, int bit_number) { + BYTE parity_res = '0'; + for (int i = bit_number - 1; i < 36; i += 4) { + if (stream_[i] == parity_res) { + parity_res = '0'; + } else { + parity_res = '1'; + } + } + return parity_res; +} + +static BYTE *parity(BYTE *stream_) { + BYTE *parity_res = malloc(4 * sizeof(BYTE)); + parity_res[0] = xor_parity(stream_, 4); + parity_res[1] = xor_parity(stream_, 2); + parity_res[2] = xor_parity(stream_, 3); + parity_res[3] = xor_parity(stream_, 1); + return parity_res; +} + +static BYTE *convertUint8toByte(uint8_t number) { + BYTE *res = malloc(8 * sizeof(char)); + uint8_t temp = number; + for (int i = 1; i < 9; i++) { + if (temp % 2) { + res[8 - i] = '1'; + } else { + res[8 - i] = '0'; + } + temp = temp / 2; + } + return res; +} + +static BYTE *convertUint32toByte(uint32_t number) { + BYTE *res = malloc(32 * sizeof(char)); + uint32_t temp = number; + for (int i = 0; i < 32; i++) { + res[i] = '0'; + } + for (int i = 1; i < 33; i++) { + if (temp % 2) { + res[32 - i] = '1'; + } else { + res[32 - i] = '0'; + } + temp = temp / 2; + } + return res; +} + + +static void TOpsk2(BYTE *bits, size_t size) { + BYTE lastbit = '0'; + for (size_t i = 1; i < size; i++) { + //ignore errors + if (bits[i] == 7) continue; + + if (lastbit != bits[i]) { + lastbit = bits[i]; + bits[i] = '1'; + } else { + bits[i] = '0'; + } + } +} +//ENDTOCHANGE static int CmdNexWatchClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf nexwatch clone", @@ -285,6 +385,8 @@ static int CmdNexWatchClone(const char *Cmd) { arg_lit0(NULL, "hc", "Honeywell credential"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), + arg_str0(NULL, "magic", "", "optional - magic hex data. 1 byte"), + arg_lit0(NULL, "psk2", "optional - specify writing a tag in psk2 modulation"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -301,6 +403,10 @@ static int CmdNexWatchClone(const char *Cmd) { bool use_unk = arg_get_lit(ctx, 6); bool q5 = arg_get_lit(ctx, 7); bool em = arg_get_lit(ctx, 8); + bool use_psk2 = arg_get_lit(ctx, 10); + uint8_t magic_arg; + int magic_len = 0; + CLIGetHexWithReturn(ctx, 9, &magic_arg, &magic_len); CLIParserFree(ctx); if (use_nexkey && use_quadrakey) { @@ -316,6 +422,13 @@ static int CmdNexWatchClone(const char *Cmd) { // 56000000 00213C9F 8F150C00 bool use_raw = (raw_len != 0); + bool use_custom_magic = (magic_len != 0); + + if (magic_len > 1) { + PrintAndLogEx(FAILED, "Can't specify a magic number bigger than one byte"); + return PM3_EINVARG; + } + if (use_raw && cn != -1) { PrintAndLogEx(FAILED, "Can't specify both Raw and Card id at the same time"); return PM3_EINVARG; @@ -325,6 +438,7 @@ static int CmdNexWatchClone(const char *Cmd) { uint32_t scrambled; nexwatch_scamble(SCRAMBLE, &cn, &scrambled); num_to_bytes(scrambled, 4, raw + 5); + PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); } if (mode != -1) { @@ -336,42 +450,85 @@ static int CmdNexWatchClone(const char *Cmd) { } uint8_t magic = 0xBE; - if (use_nexkey) - magic = 0x88; + if (use_custom_magic) { + magic = magic_arg; + } else { + if (use_nexkey) + magic = 0x88; - if (use_quadrakey) - magic = 0xBE; + if (use_quadrakey) + magic = 0xBE; - if (use_unk) - magic = 0x86; + if (use_unk) + magic = 0x86; - uint32_t blocks[4]; + } + PrintAndLogEx(INFO, "Magic byte selected : 0x%X", magic); - //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_PSK1 | 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(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; - snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); - } + uint32_t blocks[4]; + if (use_psk2) { + uint32_t scrambled; + nexwatch_scamble(SCRAMBLE, &cn, &scrambled); + num_to_bytes(scrambled, 4, raw + 5); + PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); + blocks[0] = 270464; + raw[0] = 0xFA; + BYTE *byteId = convertUint32toByte(scrambled); + BYTE newmode[4] = "0001"; + BYTE idAndMode[36]; + memcpy(idAndMode, byteId, 32 * sizeof(BYTE)); + memcpy(&idAndMode[32], newmode, 4 * sizeof(BYTE)); + BYTE *newparity = parity(idAndMode); + uint8_t par = bin2int(newparity, 4); + uint8_t checksum = nexwatch_checksum(magic, cn, par); + printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); + BYTE Psk_card[128]; + BYTE Psk2_card[128]; + memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(BYTE)); + memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(BYTE)); + memcpy(&Psk_card[72], byteId, 32 * sizeof(BYTE)); + memcpy(&Psk_card[104], newmode, 4 * sizeof(BYTE)); + memcpy(&Psk_card[108], newparity, 4 * sizeof(BYTE)); + memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(BYTE)); + memcpy(&Psk_card[120], "00000000", 8 * sizeof(BYTE)); + TOpsk2(Psk_card, 128); + memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(BYTE)); + Psk2_card[127] = '0'; + memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(BYTE)); + blocks[0] = bin2int(&Psk2_card[0], 32); + blocks[1] = bin2int(&Psk2_card[32], 32); + blocks[2] = bin2int(&Psk2_card[64], 32); + blocks[3] = bin2int(&Psk2_card[96], 32); + } else { + //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; - // EM4305 - if (em) { - blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; - snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); - } + // Q5 + if (q5) { + blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; + snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); + } - if (use_raw == false) { - uint8_t parity = nexwatch_parity(raw + 5) & 0xF; - raw[9] |= parity; - raw[10] |= nexwatch_checksum(magic, cn, parity); - } + // EM4305 + if (em) { + blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; + snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); + } - for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { - blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); - } + if (use_raw == false) { + uint8_t parity = nexwatch_parity(raw + 5) & 0xF; + raw[9] |= parity; + raw[10] |= nexwatch_checksum(magic, cn, parity); + } + if (use_unk) + magic = 0x86; + + for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); + } + } PrintAndLogEx(INFO, "Preparing to clone NexWatch to " _YELLOW_("%s") " raw " _YELLOW_("%s"), cardtype, sprint_hex_inrow(raw, sizeof(raw))); print_blocks(blocks, ARRAYLEN(blocks)); @@ -408,6 +565,8 @@ static int CmdNexWatchSim(const char *Cmd) { arg_lit0(NULL, "nc", "Nexkey credential"), arg_lit0(NULL, "qc", "Quadrakey credential"), arg_lit0(NULL, "hc", "Honeywell credential"), + arg_str0(NULL, "magic", "", "optional - magic hex data. 1 byte"), + arg_lit0(NULL, "psk2", "optional - specify writing a tag in psk2 modulation"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); From 17d6b76931db0c2f06814827dface9a0a1a6458b Mon Sep 17 00:00:00 2001 From: MaximeBosca Date: Wed, 23 Jun 2021 14:55:22 +0200 Subject: [PATCH 2/8] test --- client/src/cmdlfnexwatch.c | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index c73f8ef04..465b61b9b 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -295,8 +295,8 @@ static unsigned int bin2int(unsigned char *b, int size) { } return val; } -static BYTE xor_parity(BYTE *stream_, int bit_number) { - BYTE parity_res = '0'; +static uint8_t xor_parity uint8_t *stream_, int bit_number) { + uint8_t parity_res = '0'; for (int i = bit_number - 1; i < 36; i += 4) { if (stream_[i] == parity_res) { parity_res = '0'; @@ -307,8 +307,8 @@ static BYTE xor_parity(BYTE *stream_, int bit_number) { return parity_res; } -static BYTE *parity(BYTE *stream_) { - BYTE *parity_res = malloc(4 * sizeof(BYTE)); +static uint8_t *parity uint8_t *stream_) { + uint8_t *parity_res = malloc(4 * sizeof uint8_t)); parity_res[0] = xor_parity(stream_, 4); parity_res[1] = xor_parity(stream_, 2); parity_res[2] = xor_parity(stream_, 3); @@ -316,8 +316,8 @@ static BYTE *parity(BYTE *stream_) { return parity_res; } -static BYTE *convertUint8toByte(uint8_t number) { - BYTE *res = malloc(8 * sizeof(char)); +static uint8_t *convertUint8toByte(uint8_t number) { + uint8_t *res = malloc(8 * sizeof(char)); uint8_t temp = number; for (int i = 1; i < 9; i++) { if (temp % 2) { @@ -330,8 +330,8 @@ static BYTE *convertUint8toByte(uint8_t number) { return res; } -static BYTE *convertUint32toByte(uint32_t number) { - BYTE *res = malloc(32 * sizeof(char)); +static uint8_t *convertUint32toByte(uint32_t number) { + uint8_t *res = malloc(32 * sizeof(char)); uint32_t temp = number; for (int i = 0; i < 32; i++) { res[i] = '0'; @@ -348,8 +348,8 @@ static BYTE *convertUint32toByte(uint32_t number) { } -static void TOpsk2(BYTE *bits, size_t size) { - BYTE lastbit = '0'; +static void TOpsk2 uint8_t *bits, size_t size) { + uint8_t lastbit = '0'; for (size_t i = 1; i < size; i++) { //ignore errors if (bits[i] == 7) continue; @@ -474,28 +474,28 @@ static int CmdNexWatchClone(const char *Cmd) { PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); blocks[0] = 270464; raw[0] = 0xFA; - BYTE *byteId = convertUint32toByte(scrambled); - BYTE newmode[4] = "0001"; - BYTE idAndMode[36]; - memcpy(idAndMode, byteId, 32 * sizeof(BYTE)); - memcpy(&idAndMode[32], newmode, 4 * sizeof(BYTE)); - BYTE *newparity = parity(idAndMode); + uint8_t *byteId = convertUint32toByte(scrambled); + uint8_t newmode[4] = "0001"; + uint8_t idAndMode[36]; + memcpy(idAndMode, byteId, 32 * sizeof uint8_t)); + memcpy(&idAndMode[32], newmode, 4 * sizeof uint8_t)); + uint8_t *newparity = parity(idAndMode); uint8_t par = bin2int(newparity, 4); uint8_t checksum = nexwatch_checksum(magic, cn, par); printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); - BYTE Psk_card[128]; - BYTE Psk2_card[128]; - memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(BYTE)); - memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(BYTE)); - memcpy(&Psk_card[72], byteId, 32 * sizeof(BYTE)); - memcpy(&Psk_card[104], newmode, 4 * sizeof(BYTE)); - memcpy(&Psk_card[108], newparity, 4 * sizeof(BYTE)); - memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(BYTE)); - memcpy(&Psk_card[120], "00000000", 8 * sizeof(BYTE)); + uint8_t Psk_card[128]; + uint8_t Psk2_card[128]; + memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof uint8_t)); + memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof uint8_t)); + memcpy(&Psk_card[72], byteId, 32 * sizeof uint8_t)); + memcpy(&Psk_card[104], newmode, 4 * sizeof uint8_t)); + memcpy(&Psk_card[108], newparity, 4 * sizeof uint8_t)); + memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof uint8_t)); + memcpy(&Psk_card[120], "00000000", 8 * sizeof uint8_t)); TOpsk2(Psk_card, 128); - memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(BYTE)); + memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof uint8_t)); Psk2_card[127] = '0'; - memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(BYTE)); + memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof uint8_t)); blocks[0] = bin2int(&Psk2_card[0], 32); blocks[1] = bin2int(&Psk2_card[32], 32); blocks[2] = bin2int(&Psk2_card[64], 32); From 12bd44c3a862f76671f3d97b9de25655217099f4 Mon Sep 17 00:00:00 2001 From: MaximeBosca Date: Wed, 23 Jun 2021 15:04:00 +0200 Subject: [PATCH 3/8] test --- client/src/cmdlfnexwatch.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 465b61b9b..1d0f9cc28 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -295,7 +295,7 @@ static unsigned int bin2int(unsigned char *b, int size) { } return val; } -static uint8_t xor_parity uint8_t *stream_, int bit_number) { +static uint8_t xor_parity(uint8_t *stream_, int bit_number) { uint8_t parity_res = '0'; for (int i = bit_number - 1; i < 36; i += 4) { if (stream_[i] == parity_res) { @@ -307,8 +307,8 @@ static uint8_t xor_parity uint8_t *stream_, int bit_number) { return parity_res; } -static uint8_t *parity uint8_t *stream_) { - uint8_t *parity_res = malloc(4 * sizeof uint8_t)); +static uint8_t *parity(uint8_t *stream_) { + uint8_t *parity_res = malloc(4 * sizeof(uint8_t)); parity_res[0] = xor_parity(stream_, 4); parity_res[1] = xor_parity(stream_, 2); parity_res[2] = xor_parity(stream_, 3); @@ -348,7 +348,7 @@ static uint8_t *convertUint32toByte(uint32_t number) { } -static void TOpsk2 uint8_t *bits, size_t size) { +static void TOpsk2(uint8_t *bits, size_t size) { uint8_t lastbit = '0'; for (size_t i = 1; i < size; i++) { //ignore errors @@ -477,25 +477,25 @@ static int CmdNexWatchClone(const char *Cmd) { uint8_t *byteId = convertUint32toByte(scrambled); uint8_t newmode[4] = "0001"; uint8_t idAndMode[36]; - memcpy(idAndMode, byteId, 32 * sizeof uint8_t)); - memcpy(&idAndMode[32], newmode, 4 * sizeof uint8_t)); + memcpy(idAndMode, byteId, 32 * sizeof(uint8_t)); + memcpy(&idAndMode[32], newmode, 4 * sizeof(uint8_t)); uint8_t *newparity = parity(idAndMode); uint8_t par = bin2int(newparity, 4); uint8_t checksum = nexwatch_checksum(magic, cn, par); printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); uint8_t Psk_card[128]; uint8_t Psk2_card[128]; - memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof uint8_t)); - memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof uint8_t)); - memcpy(&Psk_card[72], byteId, 32 * sizeof uint8_t)); - memcpy(&Psk_card[104], newmode, 4 * sizeof uint8_t)); - memcpy(&Psk_card[108], newparity, 4 * sizeof uint8_t)); - memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof uint8_t)); - memcpy(&Psk_card[120], "00000000", 8 * sizeof uint8_t)); + memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(uint8_t)); + memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(uint8_t)); + memcpy(&Psk_card[72], byteId, 32 * sizeof(uint8_t)); + memcpy(&Psk_card[104], newmode, 4 * sizeof(uint8_t)); + memcpy(&Psk_card[108], newparity, 4 * sizeof(uint8_t)); + memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(uint8_t)); + memcpy(&Psk_card[120], "00000000", 8 * sizeof(uint8_t)); TOpsk2(Psk_card, 128); - memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof uint8_t)); + memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(uint8_t)); Psk2_card[127] = '0'; - memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof uint8_t)); + memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(uint8_t)); blocks[0] = bin2int(&Psk2_card[0], 32); blocks[1] = bin2int(&Psk2_card[32], 32); blocks[2] = bin2int(&Psk2_card[64], 32); From 5f9f623627c6e78d13d0b7d08b8e9d66dfa109ab Mon Sep 17 00:00:00 2001 From: MaximeBosca Date: Fri, 25 Jun 2021 09:56:30 +0200 Subject: [PATCH 4/8] new clone --- client/src/cmdlfnexwatch.c | 88 +++++++++++++------------------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 1d0f9cc28..3bb44402b 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -467,68 +467,38 @@ static int CmdNexWatchClone(const char *Cmd) { char cardtype[16] = {"T55x7"}; uint32_t blocks[4]; - if (use_psk2) { - uint32_t scrambled; - nexwatch_scamble(SCRAMBLE, &cn, &scrambled); - num_to_bytes(scrambled, 4, raw + 5); - PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); - blocks[0] = 270464; - raw[0] = 0xFA; - uint8_t *byteId = convertUint32toByte(scrambled); - uint8_t newmode[4] = "0001"; - uint8_t idAndMode[36]; - memcpy(idAndMode, byteId, 32 * sizeof(uint8_t)); - memcpy(&idAndMode[32], newmode, 4 * sizeof(uint8_t)); - uint8_t *newparity = parity(idAndMode); - uint8_t par = bin2int(newparity, 4); - uint8_t checksum = nexwatch_checksum(magic, cn, par); - printf("\x1b[1;92m[+]\x1b[0m Checksum : %s --> %u\n", convertUint8toByte(checksum), checksum); - uint8_t Psk_card[128]; - uint8_t Psk2_card[128]; - memcpy(Psk_card, "00000000000000000000000000000000", 32 * sizeof(uint8_t)); - memcpy(&Psk_card[32], "0101011000000000000000000000000000000000", 40 * sizeof(uint8_t)); - memcpy(&Psk_card[72], byteId, 32 * sizeof(uint8_t)); - memcpy(&Psk_card[104], newmode, 4 * sizeof(uint8_t)); - memcpy(&Psk_card[108], newparity, 4 * sizeof(uint8_t)); - memcpy(&Psk_card[112], convertUint8toByte(checksum), 8 * sizeof(uint8_t)); - memcpy(&Psk_card[120], "00000000", 8 * sizeof(uint8_t)); - TOpsk2(Psk_card, 128); - memcpy(&Psk2_card[31], &Psk_card[32], 96 * sizeof(uint8_t)); - Psk2_card[127] = '0'; - memcpy(Psk2_card, "00000000000001000010000010000000", 32 * sizeof(uint8_t)); - blocks[0] = bin2int(&Psk2_card[0], 32); - blocks[1] = bin2int(&Psk2_card[32], 32); - blocks[2] = bin2int(&Psk2_card[64], 32); - blocks[3] = bin2int(&Psk2_card[96], 32); - } else { - //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; - // Q5 - if (q5) { - blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; - snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); - } + //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; - // EM4305 - if (em) { - blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; - snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); - } - - if (use_raw == false) { - uint8_t parity = nexwatch_parity(raw + 5) & 0xF; - raw[9] |= parity; - raw[10] |= nexwatch_checksum(magic, cn, parity); - } - - if (use_unk) - magic = 0x86; - - for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { - blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); - } + // Q5 + if (q5) { + blocks[0] = T5555_FIXED | T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; + snprintf(cardtype, sizeof(cardtype), "Q5/T5555"); } + + // EM4305 + if (em) { + blocks[0] = EM4305_NEXWATCH_CONFIG_BLOCK; + snprintf(cardtype, sizeof(cardtype), "EM4305/4469"); + } + + if (use_raw == false) { + uint8_t parity = nexwatch_parity(raw + 5) & 0xF; + raw[9] |= parity; + raw[10] |= nexwatch_checksum(magic, cn, parity); + } + + if (use_psk2) { + blocks[0] = 270464; + psk1TOpsk2(raw, 12); + } + + + for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(raw + ((i - 1) * 4), sizeof(uint32_t)); + } + PrintAndLogEx(INFO, "Preparing to clone NexWatch to " _YELLOW_("%s") " raw " _YELLOW_("%s"), cardtype, sprint_hex_inrow(raw, sizeof(raw))); print_blocks(blocks, ARRAYLEN(blocks)); From e33f2a76aa7b10ce9230cb6f0669acae22158bf7 Mon Sep 17 00:00:00 2001 From: rioux Date: Fri, 25 Jun 2021 12:00:29 +0200 Subject: [PATCH 5/8] lf nexwatch with psk2 --- client/src/cmdlfnexwatch.c | 87 +++----------------------------------- common/lfdemod.c | 11 +++++ common/lfdemod.h | 2 + 3 files changed, 20 insertions(+), 80 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 3bb44402b..3ad4e1183 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -279,90 +279,12 @@ static int CmdNexWatchReader(const char *Cmd) { } do { - lf_read(true, 20000); + lf_read(false, 20000); demodNexWatch(!cm); } while (cm && !kbd_enter_pressed()); return PM3_SUCCESS; } -//TOCHANGE -static unsigned int bin2int(unsigned char *b, int size) { - unsigned int val = 0; - for (int i = 0; i < size; i++) { - if (b[i] == '1') { - val += pow(2, size - 1 - i); - } - } - return val; -} -static uint8_t xor_parity(uint8_t *stream_, int bit_number) { - uint8_t parity_res = '0'; - for (int i = bit_number - 1; i < 36; i += 4) { - if (stream_[i] == parity_res) { - parity_res = '0'; - } else { - parity_res = '1'; - } - } - return parity_res; -} - -static uint8_t *parity(uint8_t *stream_) { - uint8_t *parity_res = malloc(4 * sizeof(uint8_t)); - parity_res[0] = xor_parity(stream_, 4); - parity_res[1] = xor_parity(stream_, 2); - parity_res[2] = xor_parity(stream_, 3); - parity_res[3] = xor_parity(stream_, 1); - return parity_res; -} - -static uint8_t *convertUint8toByte(uint8_t number) { - uint8_t *res = malloc(8 * sizeof(char)); - uint8_t temp = number; - for (int i = 1; i < 9; i++) { - if (temp % 2) { - res[8 - i] = '1'; - } else { - res[8 - i] = '0'; - } - temp = temp / 2; - } - return res; -} - -static uint8_t *convertUint32toByte(uint32_t number) { - uint8_t *res = malloc(32 * sizeof(char)); - uint32_t temp = number; - for (int i = 0; i < 32; i++) { - res[i] = '0'; - } - for (int i = 1; i < 33; i++) { - if (temp % 2) { - res[32 - i] = '1'; - } else { - res[32 - i] = '0'; - } - temp = temp / 2; - } - return res; -} - - -static void TOpsk2(uint8_t *bits, size_t size) { - uint8_t lastbit = '0'; - for (size_t i = 1; i < size; i++) { - //ignore errors - if (bits[i] == 7) continue; - - if (lastbit != bits[i]) { - lastbit = bits[i]; - bits[i] = '1'; - } else { - bits[i] = '0'; - } - } -} -//ENDTOCHANGE static int CmdNexWatchClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf nexwatch clone", @@ -491,7 +413,12 @@ static int CmdNexWatchClone(const char *Cmd) { if (use_psk2) { blocks[0] = 270464; - psk1TOpsk2(raw, 12); + uint8_t * res_shifted = malloc(96 * sizeof(uint8_t)); + uint8_t * res = byte_to_bytebits(raw, 12); + psk1TOpsk2(res, 96); + memcpy(res_shifted, &res[1], 95 * sizeof(uint8_t)); + res_shifted[95] = 0; + bits_to_array(res_shifted, 96, raw); } diff --git a/common/lfdemod.c b/common/lfdemod.c index 3c32834f6..350944314 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -295,6 +295,17 @@ int bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { return PM3_SUCCESS; } +// Ex: 0x56 and numbytes = 1 ==> return res = {0,1,0,1,0,1,1,0} +uint8_t * byte_to_bytebits(uint8_t * bits, size_t numbytes){ + uint8_t * result = malloc(numbytes * 8 * (sizeof(uint8_t))); + for(int i=0;i Date: Fri, 25 Jun 2021 12:09:40 +0200 Subject: [PATCH 6/8] lf nexwatch with psk2 --- client/src/cmdlfnexwatch.c | 12 ++++-------- common/lfdemod.h | 1 - 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 3ad4e1183..a32a00a8c 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -24,7 +24,6 @@ #include "cmdlft55xx.h" // clone.. #include "cmdlfem4x05.h" // #include "cliparser.h" -#include typedef enum { @@ -54,7 +53,7 @@ static uint8_t nexwatch_parity(uint8_t hexid[5]) { } /// NETWATCH checksum -/// @param magic = 0xBE Quadrakey, 0x88 Nexkey, 0x86 EC +/// @param magic = 0xBE Quadrakey, 0x88 Nexkey, 0x86 Honeywell /// @param id = descrambled id (printed card number) /// @param parity = the parity based upon the scrambled raw id. static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { @@ -155,7 +154,6 @@ int demodNexWatch(bool verbose) { idx += 4; setDemodBuff(DemodBuffer, size, idx); - PrintAndLogEx(SUCCESS, "Indice: %x %s", DemodBuffer, DemodBuffer); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); if (invert) { @@ -225,9 +223,8 @@ int demodNexWatch(bool verbose) { } else { nexwatch_magic_bruteforce(cn, calc_parity, chk); } - PrintAndLogEx(SUCCESS, " mode : %x", mode); PrintAndLogEx(SUCCESS, " 88bit id : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", cn, cn); - PrintAndLogEx(SUCCESS, " Scambled : " _YELLOW_("%"PRIu32) " (" _YELLOW_("0x%08"PRIx32)")", scambled, scambled); + PrintAndLogEx(SUCCESS, " mode : %x", mode); if (parity == calc_parity) { @@ -360,7 +357,6 @@ static int CmdNexWatchClone(const char *Cmd) { uint32_t scrambled; nexwatch_scamble(SCRAMBLE, &cn, &scrambled); num_to_bytes(scrambled, 4, raw + 5); - PrintAndLogEx(SUCCESS, "Scrambled : %u", scrambled); } if (mode != -1) { @@ -387,11 +383,11 @@ static int CmdNexWatchClone(const char *Cmd) { } PrintAndLogEx(INFO, "Magic byte selected : 0x%X", magic); - char cardtype[16] = {"T55x7"}; uint32_t blocks[4]; //Nexwatch - compat mode, PSK, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_16 | 3 << T55x7_MAXBLOCK_SHIFT; + blocks[0] = T55x7_MODULATION_PSK1 | T55x7_BITRATE_RF_32 | 3 << T55x7_MAXBLOCK_SHIFT; + char cardtype[16] = {"T55x7"}; // Q5 if (q5) { diff --git a/common/lfdemod.h b/common/lfdemod.h index e8fc57746..4ead8b9e4 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -81,5 +81,4 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); - #endif From 22add5e108f163ea39a87062bd88124508cd2766 Mon Sep 17 00:00:00 2001 From: Guilhem7 <48909214+Guilhem7@users.noreply.github.com> Date: Fri, 25 Jun 2021 12:12:54 +0200 Subject: [PATCH 7/8] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1532b044b..f7cd6d8d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added bruteforce function for the magic byte in `cmdlfnexwatch.c` and ability to clone with psk2 modulation (@Guilhem7, @MaximeBosca) - Changed `hw setmux` - improve user feedback for special case (@iceman1001) - Changed 'filename' - unified file name param across client (@iceman1001) - Fix `lf em 4x05 brute/chk` - fixed input params crash (@iceman1001) From f7c4336645fbcb82e4a06c2467f2ec82db33f8e9 Mon Sep 17 00:00:00 2001 From: rioux Date: Fri, 25 Jun 2021 13:26:16 +0200 Subject: [PATCH 8/8] last update askip --- client/src/cmdlfnexwatch.c | 14 ++++++++------ common/lfdemod.c | 11 ----------- common/lfdemod.h | 1 - 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index a32a00a8c..39a3ff7cc 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -24,6 +24,7 @@ #include "cmdlft55xx.h" // clone.. #include "cmdlfem4x05.h" // #include "cliparser.h" +#include "util.h" typedef enum { @@ -110,9 +111,8 @@ static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *s } static int nexwatch_magic_bruteforce(uint32_t cn, uint8_t calc_parity, uint8_t chk) { - uint8_t magic = 0; - uint8_t temp_checksum; - for (; magic < 255; magic++) { + for (uint8_t magic = 0; magic < 255; magic++) { + uint8_t temp_checksum; temp_checksum = nexwatch_checksum(magic, cn, calc_parity); if (temp_checksum == chk) { PrintAndLogEx(SUCCESS, " Magic number : " _GREEN_("0x%X"), magic); @@ -409,12 +409,14 @@ static int CmdNexWatchClone(const char *Cmd) { if (use_psk2) { blocks[0] = 270464; - uint8_t * res_shifted = malloc(96 * sizeof(uint8_t)); - uint8_t * res = byte_to_bytebits(raw, 12); + uint8_t * res_shifted = calloc(96, sizeof(uint8_t)); + uint8_t * res = calloc(96, sizeof(uint8_t)); + bytes_to_bytebits(raw, 12, res); psk1TOpsk2(res, 96); memcpy(res_shifted, &res[1], 95 * sizeof(uint8_t)); - res_shifted[95] = 0; + free(res); bits_to_array(res_shifted, 96, raw); + free(res_shifted); } diff --git a/common/lfdemod.c b/common/lfdemod.c index 350944314..3c32834f6 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -295,17 +295,6 @@ int bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { return PM3_SUCCESS; } -// Ex: 0x56 and numbytes = 1 ==> return res = {0,1,0,1,0,1,1,0} -uint8_t * byte_to_bytebits(uint8_t * bits, size_t numbytes){ - uint8_t * result = malloc(numbytes * 8 * (sizeof(uint8_t))); - for(int i=0;i