From: Iceman Date: Wed, 29 Mar 2017 05:39:40 +0000 (+0200) Subject: Merge pull request #258 from marshmellow42/master X-Git-Tag: v3.0.0~26 X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/2938b3cb12060875655ba9afbd98a69b7eea6d43?hp=160dba86970b71e23770929cb2b15b2454a1496f Merge pull request #258 from marshmellow42/master Add lf jablotron & lf noralsy tag definitions/cmds --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c6f6c8..eb4a62de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,15 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added -- Added lf nexwatch read - reads a nexwatch tag from the antenna -- Added lf paradox read - reads a paradox tag from the antenna +- Added lf noralsy demod, read, clone, sim commands (iceman) +- Added lf jablotron demod, read, clone, sim commands (iceman) +- Added lf nexwatch read - reads a nexwatch tag from the antenna +- Added lf paradox read - reads a paradox tag from the antenna - Added lf fdx sim (iceman) -- Added lf fdx clone - clones an fdx-b animal tag to t55x7 or q5 (iceman) -- Added lf fdx read - reads a fdx-b tag from the antenna (iceman) -- Added lf gproxii read - reads a gproxii tag from the antenna (marshmellow) -- Added lf indala read - reads an indala tag from the antenna (marshmellow) +- Added lf fdx clone - clones an fdx-b animal tag to t55x7 or q5 (iceman) +- Added lf fdx read - reads a fdx-b tag from the antenna (iceman) +- Added lf gproxii read - reads a gproxii tag from the antenna (marshmellow) +- Added lf indala read - reads an indala tag from the antenna (marshmellow) - Added lf visa2000 demod, read, clone, sim commands (iceman) - Added markers in the graph around found Sequence Terminator after askmandemod. - Added data mtrim command to trim out samples between start and stop diff --git a/client/Makefile b/client/Makefile index c8b7a213..a6b1942f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -99,11 +99,14 @@ CMDSRCS = crapto1/crapto1.c\ cmdlfhitag.c \ cmdlfio.c \ cmdlfindala.c \ + cmdlfjablotron.c \ cmdlfnexwatch.c \ + cmdlfnoralsy.c \ cmdlfparadox.c \ - cmdlfpcf7931.c\ - cmdlfpresco.c\ - cmdlfpyramid.c\ + cmdlfpcf7931.c \ + cmdlfpresco.c \ + cmdlfpyramid.c \ + cmdlfsecurakey.c \ cmdlft55xx.c \ cmdlfti.c \ cmdlfviking.c\ diff --git a/client/cmdlf.c b/client/cmdlf.c index 341f1fe4..005aa0e2 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -40,6 +40,9 @@ #include "cmdlffdx.h" // for fdx-b menu #include "cmdlfparadox.h"// for paradox menu #include "cmdlfnexwatch.h"//for nexwatch menu +#include "cmdlfjablotron.h" //for jablotron menu +#include "cmdlfnoralsy.h"// for noralsy menu +#include "cmdlfsecurakey.h"//for securakey menu bool g_lf_threshold_set = false; static int CmdHelp(const char *Cmd); @@ -987,13 +990,31 @@ int CmdLFfind(const char *Cmd) if (ans>0) { PrintAndLog("\nValid EM4x50 ID Found!"); return 1; - } + } + + ans=CmdJablotronDemod(""); + if (ans>0) { + PrintAndLog("\nValid Jablotron ID Found!"); + return CheckChipType(cmdp); + } + + ans=CmdNoralsyDemod(""); + if (ans>0) { + PrintAndLog("\nValid Noralsy ID Found!"); + return CheckChipType(cmdp); + } + + ans=CmdSecurakeyDemod(""); + if (ans>0) { + PrintAndLog("\nValid Securakey ID Found!"); + return CheckChipType(cmdp); + } ans=CmdVikingDemod(""); if (ans>0) { PrintAndLog("\nValid Viking ID Found!"); return CheckChipType(cmdp); - } + } ans=CmdIndalaDecode(""); if (ans>0) { @@ -1053,11 +1074,14 @@ static command_t CommandTable[] = {"hitag", CmdLFHitag, 1, "{ Hitag CHIPs... }"}, {"io", CmdLFIO, 1, "{ ioProx RFIDs... }"}, {"indala", CmdLFINDALA, 1, "{ Indala RFIDs... }"}, + {"jablotron", CmdLFJablotron, 1, "{ Jablotron RFIDs... }"}, {"nexwatch", CmdLFNexWatch, 1, "{ NexWatch RFIDs... }"}, + {"noralsy", CmdLFNoralsy, 1, "{ Noralsy RFIDs... }"}, {"paradox", CmdLFParadox, 1, "{ Paradox RFIDs... }"}, {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 CHIPs... }"}, {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, + {"securakey", CmdLFSecurakey, 1, "{ Securakey RFIDs... }"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx CHIPs... }"}, {"ti", CmdLFTI, 1, "{ TI CHIPs... }"}, {"viking", CmdLFViking, 1, "{ Viking RFIDs... }"}, diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c new file mode 100644 index 00000000..0b7d2811 --- /dev/null +++ b/client/cmdlfjablotron.c @@ -0,0 +1,253 @@ +//----------------------------------------------------------------------------- +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Low frequency jablotron tag commands +// Differential Biphase, RF/64, 64 bits long +//----------------------------------------------------------------------------- + +#include "cmdlfjablotron.h" +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + +static int CmdHelp(const char *Cmd); + +int usage_lf_jablotron_clone(void) { + PrintAndLog("clone a Jablotron tag to a T55x7 tag."); + PrintAndLog("Usage: lf jablotron clone [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : jablotron card ID"); + PrintAndLog(" : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLog(""); + PrintAndLog("Sample: lf jablotron clone 112233"); + return 0; +} + +int usage_lf_jablotron_sim(void) { + PrintAndLog("Enables simulation of jablotron card with specified card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog(""); + PrintAndLog("Usage: lf jablotron sim [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : jablotron card ID"); + PrintAndLog(""); + PrintAndLog("Sample: lf jablotron sim 112233"); + return 0; +} + +static uint8_t jablontron_chksum(uint8_t *bits) { + uint8_t chksum = 0; + for (int i=16; i < 56; i += 8) { + chksum += bytebits_to_byte(bits+i,8); + } + chksum ^= 0x3A; + return chksum; +} + +int getJablotronBits(uint64_t fullcode, uint8_t *bits) { + //preamp + num_to_bytebits(0xFFFF, 16, bits); + + //fullcode + num_to_bytebits(fullcode, 40, bits+16); + + //chksum byte + uint8_t chksum = jablontron_chksum(bits); + num_to_bytebits(chksum, 8, bits+56); + return 1; +} + +// ASK/Diphase fc/64 (inverted Biphase) +// Note: this is not a demod, this is only a detection +// the parameter *bits needs to be demoded before call +// 0xFFFF preamble, 64bits +int JablotronDetect(uint8_t *bits, size_t *size) { + if (*size < 64*2) return -1; //make sure buffer has enough data + size_t startIdx = 0; + uint8_t preamble[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; + if (preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx) == 0) + return -2; //preamble not found + if (*size != 64) return -3; // wrong demoded size + + uint8_t checkchksum = jablontron_chksum(bits+startIdx); + uint8_t crc = bytebits_to_byte(bits+startIdx+56, 8); + if ( checkchksum != crc ) return -5; + return (int)startIdx; +} + +//see ASKDemod for what args are accepted +int CmdJablotronDemod(const char *Cmd) { + + //Differential Biphase / di-phase (inverted biphase) + //get binary from ask wave + if (!ASKbiphaseDemod("0 64 1 0", false)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Jablotron ASKbiphaseDemod failed"); + return 0; + } + size_t size = DemodBufferLen; + int ans = JablotronDetect(DemodBuffer, &size); + if (ans < 0) { + if (g_debugMode) { + if (ans == -1) + PrintAndLog("DEBUG: Error - Jablotron too few bits found"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Jablotron preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Jablotron size not correct: %d", size); + else if (ans == -5) + PrintAndLog("DEBUG: Error - Jablotron checksum failed"); + else + PrintAndLog("DEBUG: Error - Jablotron ans: %d", ans); + } + return 0; + } + + setDemodBuf(DemodBuffer+ans, 64, 0); + //setGrid_Clock(64); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + + uint64_t id = (( (uint64_t)bytebits_to_byte(DemodBuffer+16, 8) )<< 32) | bytebits_to_byte(DemodBuffer+24,32); + + PrintAndLog("Jablotron Tag Found: Card ID: %"PRIx64" :: Raw: %08X%08X", id, raw1, raw2); + + uint8_t chksum = raw2 & 0xFF; + PrintAndLog("Checksum: %02X [OK]", chksum); + + // Printed format: 1410-nn-nnnn-nnnn + PrintAndLog("Printed: 1410-%02X-%04X-%04X", + (uint8_t)(id >> 32) & 0xFF, + (uint16_t)(id >> 16) & 0xFFFF, + (uint16_t)id & 0xFFFF + ); + return 1; +} + +int CmdJablotronRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("10000", true); + return CmdJablotronDemod(Cmd); +} + +int CmdJablotronClone(const char *Cmd) { + + uint64_t fullcode = 0; + uint32_t blocks[3] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0}; + + uint8_t bits[64]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_clone(); + + fullcode = param_get64ex(Cmd, 0, 0, 16); + + //Q5 + if (param_getchar(Cmd, 1) == 'Q' || param_getchar(Cmd, 1) == 'q') { + //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) + blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | ((64-2)>>1) << T5555_BITRATE_SHIFT | 2 << T5555_MAXBLOCK_SHIFT; + } + + // clearing the topbit needed for the preambl detection. + if ((fullcode & 0x7FFFFFFFFF) != fullcode) { + fullcode &= 0x7FFFFFFFFF; + PrintAndLog("Card Number Truncated to 39bits: %"PRIx64, fullcode); + } + + if ( !getJablotronBits(fullcode, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + + blocks[1] = bytebits_to_byte(bs,32); + blocks[2] = bytebits_to_byte(bs+32,32); + + PrintAndLog("Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); + PrintAndLog("Blk | Data "); + PrintAndLog("----+------------"); + PrintAndLog(" 00 | 0x%08x", blocks[0]); + PrintAndLog(" 01 | 0x%08x", blocks[1]); + PrintAndLog(" 02 | 0x%08x", blocks[2]); + + UsbCommand resp; + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; + + for (int i = 2; i >= 0; --i) { + c.arg[0] = blocks[i]; + c.arg[1] = i; + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)) { + PrintAndLog("Error occurred, device did not respond during write operation."); + return -1; + } + } + return 0; +} + +int CmdJablotronSim(const char *Cmd) { + uint64_t fullcode = 0; + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_sim(); + + fullcode = param_get64ex(Cmd, 0, 0, 16); + + // clearing the topbit needed for the preambl detection. + if ((fullcode & 0x7FFFFFFFFF) != fullcode) { + fullcode &= 0x7FFFFFFFFF; + PrintAndLog("Card Number Truncated to 39bits: %"PRIx64, fullcode); + } + + uint8_t clk = 64, encoding = 2, separator = 0, invert = 1; + uint16_t arg1, arg2; + size_t size = 64; + arg1 = clk << 8 | encoding; + arg2 = invert << 8 | separator; + + PrintAndLog("Simulating Jablotron - FullCode: %"PRIx64, fullcode); + + UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; + getJablotronBits(fullcode, c.d.asBytes); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdJablotronDemod, 1, "Attempt to read and extract tag data from the GraphBuffer"}, + {"read", CmdJablotronRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"clone", CmdJablotronClone, 0, "clone jablotron tag"}, + {"sim", CmdJablotronSim, 0, "simulate jablotron tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFJablotron(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfjablotron.h b/client/cmdlfjablotron.h new file mode 100644 index 00000000..8e1e3364 --- /dev/null +++ b/client/cmdlfjablotron.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Low frequency jablotron tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFJABLOTRON_H__ +#define CMDLFJABLOTRON_H__ + +extern int CmdLFJablotron(const char *Cmd); +extern int CmdJablotronClone(const char *Cmd); +extern int CmdJablotronSim(const char *Cmd); +extern int CmdJablotronRead(const char *Cmd); +extern int CmdJablotronDemod(const char *Cmd); + +#endif + diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c new file mode 100644 index 00000000..db450a44 --- /dev/null +++ b/client/cmdlfnoralsy.c @@ -0,0 +1,287 @@ +//----------------------------------------------------------------------------- +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Low frequency Noralsy tag commands +// ASK/Manchester, STT, RF/32, 96 bits long +//----------------------------------------------------------------------------- +#include "cmdlfnoralsy.h" +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // parityTest + +static int CmdHelp(const char *Cmd); + +int usage_lf_noralsy_clone(void){ + PrintAndLog("clone a Noralsy tag to a T55x7 tag."); + PrintAndLog("Usage: lf noralsy clone [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : Noralsy card ID"); + PrintAndLog(" : Tag allocation year"); + PrintAndLog(" : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLog(""); + PrintAndLog("Sample: lf noralsy clone 112233"); + return 0; +} + +int usage_lf_noralsy_sim(void) { + PrintAndLog("Enables simulation of Noralsy card with specified card number."); + PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLog(""); + PrintAndLog("Usage: lf noralsy sim [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" : Noralsy card ID"); + PrintAndLog(" : Tag allocation year"); + PrintAndLog(""); + PrintAndLog("Sample: lf noralsy sim 112233"); + return 0; +} + +static uint8_t noralsy_chksum( uint8_t* bits, uint8_t len) { + uint8_t sum = 0; + for (uint8_t i = 0; i < len; i += 4) + sum ^= bytebits_to_byte(bits+i, 4); + return sum & 0x0F ; +} +int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) { + //preamp + num_to_bytebits(0xBB0214FF, 32, bits); // --> Have seen 0xBB0214FF / 0xBB0314FF UNKNOWN + + year &= 0xFF; + + uint16_t sub1 = (id & 0xFFF0000) >> 16; + uint8_t sub2 = (id & 0x000FF00) >> 8; + uint8_t sub3 = (id & 0x00000FF); + + num_to_bytebits(sub1, 12, bits+32); + num_to_bytebits(year, 8, bits+44); + num_to_bytebits(0, 4, bits+52); // --> UNKNOWN. Flag? + + num_to_bytebits(sub2, 8, bits+56); + num_to_bytebits(sub3, 8, bits+64); + + //chksum byte + uint8_t chksum = noralsy_chksum(bits+32, 40); + num_to_bytebits(chksum, 4, bits+72); + chksum = noralsy_chksum(bits, 76); + num_to_bytebits(chksum, 4, bits+76); + return 1; +} + +// by iceman +// find Noralsy preamble in already demoded data +int NoralsyDemod_AM(uint8_t *dest, size_t *size) { + if (*size < 96) return -1; //make sure buffer has data + size_t startIdx = 0; + uint8_t preamble[] = {1,0,1,1,1,0,1,1,0,0,0,0}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -2; //preamble not found + if (*size != 96) return -3; //wrong demoded size + //return start position + return (int)startIdx; +} + +/* +* +* 2520116 | BB0214FF2529900116360000 | 10111011 00000011 00010100 11111111 00100101 00101001 10010000 00000001 00010110 00110110 00000000 00000000 +* aaaaaaaaiii***iiiicc---- iiiiiiii iiiiYYYY YYYY**** iiiiiiii iiiiiiii cccccccc +* +* a = fixed value BB0314FF +* i = printed id, BCD-format +* Y = year +* c = checksum +* +**/ + +//see ASKDemod for what args are accepted +int CmdNoralsyDemod(const char *Cmd) { + + //ASK / Manchester + bool st = false; + if (!ASKDemod_ext("32 0 0", false, false, 1, &st)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: ASK/Manchester Demod failed"); + return 0; + } + if (!st) return 0; + + size_t size = DemodBufferLen; + int ans = NoralsyDemod_AM(DemodBuffer, &size); + if (ans < 0){ + if (g_debugMode){ + if (ans == -1) + PrintAndLog("DEBUG: Error - Noralsy: too few bits found"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Noralsy: preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Noralsy: Size not correct: %d", size); + else + PrintAndLog("DEBUG: Error - Noralsy: ans: %d", ans); + } + return 0; + } + setDemodBuf(DemodBuffer, 96, ans); + //setGrid_Clock(32); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); + + uint32_t cardid = (bytebits_to_byte(DemodBuffer+32, 12)<<16) | bytebits_to_byte(DemodBuffer+32+24, 16); + + uint16_t year = (raw2 & 0x000ff000) >> 12; + year += ( year > 0x60 ) ? 0x1900: 0x2000; + + // calc checksums + uint8_t calc1 = noralsy_chksum(DemodBuffer+32, 40); + uint8_t calc2 = noralsy_chksum(DemodBuffer, 76); + uint8_t chk1 = 0, chk2 = 0; + chk1 = bytebits_to_byte(DemodBuffer+72, 4); + chk2 = bytebits_to_byte(DemodBuffer+76, 4); + // test checksums + if ( chk1 != calc1 ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: checksum 1 failed %x - %x\n", chk1, calc1); + return 0; + } + if ( chk2 != calc2 ) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: checksum 2 failed %x - %x\n", chk2, calc2); + return 0; + } + + PrintAndLog("Noralsy Tag Found: Card ID %X, Year: %X Raw: %08X%08X%08X", cardid, year, raw1 ,raw2, raw3); + if (raw1 != 0xBB0214FF) { + PrintAndLog("Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1); + PrintAndLog("Please post this output in forum to further research on this format"); + } + return 1; +} + +int CmdNoralsyRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("8000",true); + return CmdNoralsyDemod(Cmd); +} + +int CmdNoralsyClone(const char *Cmd) { + + uint16_t year = 0; + uint32_t id = 0; + uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0}; + uint8_t bits[96]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_noralsy_clone(); + + id = param_get32ex(Cmd, 0, 0, 16); + year = param_get32ex(Cmd, 1, 2000, 16); + + //Q5 + if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q') { + //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) + blocks[0] = T5555_MODULATION_MANCHESTER | ((32-2)>>1) << T5555_BITRATE_SHIFT | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; + } + + if ( !getnoralsyBits(id, year, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + + // + blocks[1] = bytebits_to_byte(bs,32); + blocks[2] = bytebits_to_byte(bs+32,32); + blocks[3] = bytebits_to_byte(bs+64,32); + + PrintAndLog("Preparing to clone Noralsy to T55x7 with CardId: %x", id); + PrintAndLog("Blk | Data "); + PrintAndLog("----+------------"); + PrintAndLog(" 00 | 0x%08x", blocks[0]); + PrintAndLog(" 01 | 0x%08x", blocks[1]); + PrintAndLog(" 02 | 0x%08x", blocks[2]); + PrintAndLog(" 03 | 0x%08x", blocks[3]); + + UsbCommand resp; + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; + + for (int i = 3; i >= 0; --i) { + c.arg[0] = blocks[i]; + c.arg[1] = i; + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)){ + PrintAndLog("Error occurred, device did not respond during write operation."); + return -1; + } + } + return 0; +} + +int CmdNoralsySim(const char *Cmd) { + + uint8_t bits[96]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + uint16_t year = 0; + uint32_t id = 0; + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_noralsy_sim(); + + id = param_get32ex(Cmd, 0, 0, 16); + year = param_get32ex(Cmd, 1, 2000, 16); + + uint8_t clk = 32, encoding = 1, separator = 1, invert = 0; + uint16_t arg1, arg2; + size_t size = 96; + arg1 = clk << 8 | encoding; + arg2 = invert << 8 | separator; + + if ( !getnoralsyBits(id, year, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return 1; + } + + PrintAndLog("Simulating Noralsy - CardId: %x", id); + + UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; + memcpy(c.d.asBytes, bs, size); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdNoralsyDemod,1, "Attempt to read and extract tag data from the GraphBuffer"}, + {"read", CmdNoralsyRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"clone", CmdNoralsyClone,0, "clone Noralsy tag"}, + {"sim", CmdNoralsySim, 0, "simulate Noralsy tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFNoralsy(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfnoralsy.h b/client/cmdlfnoralsy.h new file mode 100644 index 00000000..743c14ec --- /dev/null +++ b/client/cmdlfnoralsy.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Low frequency Noralsy tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFNORALSY_H__ +#define CMDLFNORALSY_H__ + +extern int CmdLFNoralsy(const char *Cmd); +extern int CmdNoralsyClone(const char *Cmd); +extern int CmdNoralsySim(const char *Cmd); +extern int CmdNoralsyRead(const char *Cmd); +extern int CmdNoralsyDemod(const char *Cmd); + +#endif + diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c new file mode 100644 index 00000000..1d55faf9 --- /dev/null +++ b/client/cmdlfsecurakey.c @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Low frequency Securakey tag commands +// ASK/Manchester, RF/40, 96 bits long +//----------------------------------------------------------------------------- +#include "cmdlfsecurakey.h" +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdmain.h" +#include "cmdlf.h" +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // preamble test +#include "parity.h" // for wiegand parity test + +static int CmdHelp(const char *Cmd); + +// by marshmellow +// find Securakey preamble in already demoded data +int SecurakeyFind(uint8_t *dest, size_t *size) { + if (*size < 96) return -1; //make sure buffer has data + size_t startIdx = 0; + uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1,0,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + return -2; //preamble not found + if (*size != 96) return -3; //wrong demoded size + //return start position + return (int)startIdx; +} + +//see ASKDemod for what args are accepted +int CmdSecurakeyDemod(const char *Cmd) { + + //ASK / Manchester + bool st = false; + if (!ASKDemod_ext("40 0 0", false, false, 1, &st)) { + if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: ASK/Manchester Demod failed"); + return 0; + } + if (st) return 0; + size_t size = DemodBufferLen; + int ans = SecurakeyFind(DemodBuffer, &size); + if (ans < 0) { + if (g_debugMode) { + if (ans == -1) + PrintAndLog("DEBUG: Error - Securakey: too few bits found"); + else if (ans == -2) + PrintAndLog("DEBUG: Error - Securakey: preamble not found"); + else if (ans == -3) + PrintAndLog("DEBUG: Error - Securakey: Size not correct: %d", size); + else + PrintAndLog("DEBUG: Error - Securakey: ans: %d", ans); + } + return 0; + } + setDemodBuf(DemodBuffer, 96, ans); + //setGrid_Clock(40); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); + + // 26 bit format + // preamble ??bitlen reserved EPx xxxxxxxy yyyyyyyy yyyyyyyOP CS? CS2? + // 0111111111 0 01011010 0 00000000 0 00000010 0 00110110 0 00111110 0 01100010 0 00001111 0 01100000 0 00000000 0 0000 + + // 32 bit format + // preamble ??bitlen reserved EPxxxxxxx xxxxxxxy yyyyyyyy yyyyyyyOP CS? CS2? + // 0111111111 0 01100000 0 00000000 0 10000100 0 11001010 0 01011011 0 01010110 0 00010110 0 11100000 0 00000000 0 0000 + + // x = FC? + // y = card # + // standard wiegand parities. + // unknown checksum 11 bits? at the end + uint8_t bits_no_spacer[86]; + memcpy(bits_no_spacer, DemodBuffer + 10, 86); + + // remove marker bits (0's every 9th digit after preamble) (pType = 3 (always 0s)) + size = removeParity(bits_no_spacer, 0, 9, 3, 86); + if ( size != 86-10 ) { + if (g_debugMode) PrintAndLog("DEBUG: Error removeParity: %d", size); + return 0; + } + + uint8_t bitLen = (uint8_t)bytebits_to_byte(DemodBuffer+2, 6); + uint32_t fc=0, lWiegand=0, rWiegand=0; + // get FC + // get left 1/2 wiegand & right 1/2 wiegand (for parity test and wiegand print) + lWiegand = bytebits_to_byte(DemodBuffer + 48 - bitLen, bitLen/2); + rWiegand = bytebits_to_byte(DemodBuffer + 48 - bitLen + bitLen/2, bitLen/2); + fc = bytebits_to_byte(DemodBuffer+49-bitLen, bitLen-2-16); + + // test bitLen + if (bitLen != 26 && bitLen != 32) + PrintAndLog("***unknown securakey bitLen - share with forum***"); + + uint32_t cardid = bytebits_to_byte(DemodBuffer+8+23, 16); + // test parities + bool parity = evenparity32(lWiegand) && oddparity32(rWiegand); + + PrintAndLog("Securakey Tag Found--BitLen: %u, Card ID: %u, FC: %X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1 ,raw2, raw3); + if (bitLen <= 32) + PrintAndLog("Wiegand: %08X, Parity: %s", (lWiegand<<(bitLen/2)) | rWiegand, parity ? "Passed" : "Failed"); + PrintAndLog("\nHow the FC translates to printed FC is unknown"); + PrintAndLog("How the checksum is calculated is unknown"); + PrintAndLog("Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members"); + return 1; +} + +int CmdSecurakeyRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("8000",true); + return CmdSecurakeyDemod(Cmd); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdSecurakeyDemod,1, "Attempt to read and extract tag data from the GraphBuffer"}, + {"read", CmdSecurakeyRead, 0, "Attempt to read and extract tag data from the antenna"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFSecurakey(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfsecurakey.h b/client/cmdlfsecurakey.h new file mode 100644 index 00000000..f3c0cf88 --- /dev/null +++ b/client/cmdlfsecurakey.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// +// 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 +// the license. +//----------------------------------------------------------------------------- +// Low frequency Securakey tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFSECURAKEY_H__ +#define CMDLFSECURAKEY_H__ + +extern int CmdLFSecurakey(const char *Cmd); +extern int CmdSecurakeyClone(const char *Cmd); +extern int CmdSecurakeySim(const char *Cmd); +extern int CmdSecurakeyRead(const char *Cmd); +extern int CmdSecurakeyDemod(const char *Cmd); + +#endif +