From: Iceman Date: Sun, 26 Mar 2017 06:28:43 +0000 (+0200) Subject: Merge pull request #249 from pwpiwi/parity X-Git-Tag: v3.0.0~33 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/1ee79256095a770dd406a9cbd48f2a04c2d1499a?hp=1f065e1dad00ff5a63ebfedb8fbe04a9720bf2a6 Merge pull request #249 from pwpiwi/parity Refactor parity functions --- diff --git a/CHANGELOG.md b/CHANGELOG.md index abd2dd37..ef9c316c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added lf gproxii read - reads a gproxii tag from the antenna +- Added lf indala read - reads an indala tag from the antenna - 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 @@ -45,6 +47,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added option c to 'hf list' (mark CRC bytes) (piwi) ### Changed +- `data askgproxiidemod has been moved to `lf gproxii demod` (reads from graphbuffer) +- `lf indalaclone` has been moved to `lf indala clone` +- `lf indalademod` has been moved to `lf indala altdemod` (reads from graphbuffer) +- `data pskindalademod` has been moved to `lf indala demod` (reads from graphbuffer) - `data askvikingdemod` has been moved to `lf viking demod` (reads from graphbuffer) - `data fskpyramiddemod` has been moved to `lf pyramid demod` (reads from graphbuffer) - `data fskiodemod` has been moved to `lf io demod` (reads from graphbuffer) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 6a072bf4..dd0211da 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -993,7 +993,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 58e09a45..dc2281b9 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1023,8 +1023,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); diff --git a/client/Makefile b/client/Makefile index d59787c3..36d0c994 100644 --- a/client/Makefile +++ b/client/Makefile @@ -93,9 +93,11 @@ CMDSRCS = crapto1/crapto1.c\ cmdlfawid.c \ cmdlfcotag.c\ cmdlfem4x.c \ + cmdlfgproxii.c \ cmdlfhid.c \ cmdlfhitag.c \ cmdlfio.c \ + cmdlfindala.c \ cmdlfpcf7931.c\ cmdlfpresco.c\ cmdlfpyramid.c\ diff --git a/client/cmddata.c b/client/cmddata.c index 49c94674..1acce2ed 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -444,72 +444,6 @@ int Cmdaskbiphdemod(const char *Cmd) return ASKbiphaseDemod(Cmd, true); } -//could be split to a gProxII file -//by marshmellow -//attempts to demodulate and identify a G_Prox_II verex/chubb card -//WARNING: if it fails during some points it will destroy the DemodBuffer data -// but will leave the GraphBuffer intact. -//if successful it will push askraw data back to demod buffer ready for emulation -int CmdG_Prox_II_Demod(const char *Cmd) -{ - if (!ASKbiphaseDemod(Cmd, false)){ - if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try"); - return 0; - } - size_t size = DemodBufferLen; - //call lfdemod.c demod for gProxII - int ans = gProxII_Demod(DemodBuffer, &size); - if (ans < 0){ - if (g_debugMode) PrintAndLog("Error gProxII_Demod"); - return 0; - } - //got a good demod of 96 bits - uint8_t ByteStream[8] = {0x00}; - uint8_t xorKey=0; - size_t startIdx = ans + 6; //start after 6 bit preamble - - uint8_t bits_no_spacer[90]; - //so as to not mess with raw DemodBuffer copy to a new sample array - memcpy(bits_no_spacer, DemodBuffer + startIdx, 90); - // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72)) - size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run - if (bitLen != 72) { - if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx); - return 0; - } - // get key and then get all 8 bytes of payload decoded - xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8); - for (size_t idx = 0; idx < 8; idx++) { - ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey; - if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); - } - //now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data - // - uint8_t fmtLen = ByteStream[0]>>2; - uint32_t FC = 0; - uint32_t Card = 0; - //get raw 96 bits to print - uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32); - uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); - uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32); - - if (fmtLen==36){ - FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); - Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); - PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); - } else if(fmtLen==26){ - FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); - Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); - PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); - } else { - PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen); - PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8)); - } - PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3); - setDemodBuf(DemodBuffer+ans, 96, 0); - return 1; -} - //by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { @@ -1056,59 +990,6 @@ int PSKDemod(const char *Cmd, bool verbose) return 1; } -// Indala 26 bit decode -// by marshmellow -// optional arguments - same as CmdpskNRZrawDemod (clock & invert) -int CmdIndalaDecode(const char *Cmd) -{ - int ans; - if (strlen(Cmd)>0){ - ans = PSKDemod(Cmd, 0); - } else{ //default to RF/32 - ans = PSKDemod("32", 0); - } - - if (!ans){ - if (g_debugMode) - PrintAndLog("Error1: %d",ans); - return 0; - } - uint8_t invert=0; - size_t size = DemodBufferLen; - int startIdx = indala26decode(DemodBuffer, &size, &invert); - if (startIdx < 0 || size > 224) { - if (g_debugMode) - PrintAndLog("Error2: %d",ans); - return -1; - } - setDemodBuf(DemodBuffer, size, (size_t)startIdx); - if (invert) - if (g_debugMode) - PrintAndLog("Had to invert bits"); - - PrintAndLog("BitLen: %d",DemodBufferLen); - //convert UID to HEX - uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; - uid1=bytebits_to_byte(DemodBuffer,32); - uid2=bytebits_to_byte(DemodBuffer+32,32); - if (DemodBufferLen==64) { - PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2); - } else { - uid3=bytebits_to_byte(DemodBuffer+64,32); - uid4=bytebits_to_byte(DemodBuffer+96,32); - uid5=bytebits_to_byte(DemodBuffer+128,32); - uid6=bytebits_to_byte(DemodBuffer+160,32); - uid7=bytebits_to_byte(DemodBuffer+192,32); - PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)", - sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7); - } - if (g_debugMode){ - PrintAndLog("DEBUG: printing demodbuffer:"); - printDemodBuff(); - } - return 1; -} - int CmdPSKNexWatch(const char *Cmd) { if (!PSKDemod("", false)) return 0; @@ -1829,7 +1710,6 @@ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ask demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, - {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"}, {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, {"bin2hex", Cmdbin2hex, 1, "bin2hex -- Converts binary to hexadecimal"}, @@ -1854,7 +1734,6 @@ static command_t CommandTable[] = {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, - {"pskindalademod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"}, {"psknexwatchdemod",CmdPSKNexWatch, 1, "Demodulate a NexWatch tag (nexkey, quadrakey) (PSK1) from GraphBuffer"}, {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, diff --git a/client/cmddata.h b/client/cmddata.h index 552a37a1..86d905b1 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -23,7 +23,6 @@ int CmdData(const char *Cmd); void printDemodBuff(void); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); int CmdPrintDemodBuff(const char *Cmd); -int CmdG_Prox_II_Demod(const char *Cmd); int Cmdaskrawdemod(const char *Cmd); int Cmdaskmandemod(const char *Cmd); int AutoCorrelate(int window, bool SaveGrph, bool verbose); @@ -59,7 +58,6 @@ int CmdSave(const char *Cmd); int CmdScale(const char *Cmd); int CmdDirectionalThreshold(const char *Cmd); int CmdZerocrossings(const char *Cmd); -int CmdIndalaDecode(const char *Cmd); int ASKbiphaseDemod(const char *Cmd, bool verbose); int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType); int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck); diff --git a/client/cmdlf.c b/client/cmdlf.c index f34637db..10a70d7c 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -35,6 +35,8 @@ #include "cmdlfviking.h" // for viking menu #include "cmdlfcotag.h" // for COTAG menu #include "cmdlfvisa2000.h" // for VISA2000 menu +#include "cmdlfindala.h" // for indala menu +#include "cmdlfgproxii.h"// for gproxii menu bool g_lf_threshold_set = false; static int CmdHelp(const char *Cmd); @@ -195,243 +197,7 @@ int CmdFlexdemod(const char *Cmd) RepaintGraphWindow(); return 0; -} - -int CmdIndalaDemod(const char *Cmd) -{ - // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID - - int state = -1; - int count = 0; - int i, j; - - // worst case with GraphTraceLen=64000 is < 4096 - // under normal conditions it's < 2048 - - uint8_t rawbits[4096]; - int rawbit = 0; - int worst = 0, worstPos = 0; - // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); - - // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) - for (i = 0; i < GraphTraceLen-1; i += 2) { - count += 1; - if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { - // appears redundant - marshmellow - if (state == 0) { - for (j = 0; j < count - 8; j += 16) { - rawbits[rawbit++] = 0; - } - if ((abs(count - j)) > worst) { - worst = abs(count - j); - worstPos = i; - } - } - state = 1; - count = 0; - } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { - //appears redundant - if (state == 1) { - for (j = 0; j < count - 8; j += 16) { - rawbits[rawbit++] = 1; - } - if ((abs(count - j)) > worst) { - worst = abs(count - j); - worstPos = i; - } - } - state = 0; - count = 0; - } - } - - if (rawbit>0){ - PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); - PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); - } else { - return 0; - } - - // Finding the start of a UID - int uidlen, long_wait; - if (strcmp(Cmd, "224") == 0) { - uidlen = 224; - long_wait = 30; - } else { - uidlen = 64; - long_wait = 29; - } - - int start; - int first = 0; - for (start = 0; start <= rawbit - uidlen; start++) { - first = rawbits[start]; - for (i = start; i < start + long_wait; i++) { - if (rawbits[i] != first) { - break; - } - } - if (i == (start + long_wait)) { - break; - } - } - - if (start == rawbit - uidlen + 1) { - PrintAndLog("nothing to wait for"); - return 0; - } - - // Inverting signal if needed - if (first == 1) { - for (i = start; i < rawbit; i++) { - rawbits[i] = !rawbits[i]; - } - } - - // Dumping UID - uint8_t bits[224] = {0x00}; - char showbits[225] = {0x00}; - int bit; - i = start; - int times = 0; - - if (uidlen > rawbit) { - PrintAndLog("Warning: not enough raw bits to get a full UID"); - for (bit = 0; bit < rawbit; bit++) { - bits[bit] = rawbits[i++]; - // As we cannot know the parity, let's use "." and "/" - showbits[bit] = '.' + bits[bit]; - } - showbits[bit+1]='\0'; - PrintAndLog("Partial UID=%s", showbits); - return 0; - } else { - for (bit = 0; bit < uidlen; bit++) { - bits[bit] = rawbits[i++]; - showbits[bit] = '0' + bits[bit]; - } - times = 1; - } - - //convert UID to HEX - uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; - int idx; - uid1 = uid2 = 0; - - if (uidlen==64){ - for( idx=0; idx<64; idx++) { - if (showbits[idx] == '0') { - uid1=(uid1<<1)|(uid2>>31); - uid2=(uid2<<1)|0; - } else { - uid1=(uid1<<1)|(uid2>>31); - uid2=(uid2<<1)|1; - } - } - PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2); - } - else { - uid3 = uid4 = uid5 = uid6 = uid7 = 0; - - for( idx=0; idx<224; idx++) { - uid1=(uid1<<1)|(uid2>>31); - uid2=(uid2<<1)|(uid3>>31); - uid3=(uid3<<1)|(uid4>>31); - uid4=(uid4<<1)|(uid5>>31); - uid5=(uid5<<1)|(uid6>>31); - uid6=(uid6<<1)|(uid7>>31); - - if (showbits[idx] == '0') - uid7 = (uid7<<1) | 0; - else - uid7 = (uid7<<1) | 1; - } - PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); - } - - // Checking UID against next occurrences - int failed = 0; - for (; i + uidlen <= rawbit;) { - failed = 0; - for (bit = 0; bit < uidlen; bit++) { - if (bits[bit] != rawbits[i++]) { - failed = 1; - break; - } - } - if (failed == 1) { - break; - } - times += 1; - } - - PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); - - // Remodulating for tag cloning - // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) - // since this changes graphbuffer data. - GraphTraceLen = 32*uidlen; - i = 0; - int phase = 0; - for (bit = 0; bit < uidlen; bit++) { - if (bits[bit] == 0) { - phase = 0; - } else { - phase = 1; - } - int j; - for (j = 0; j < 32; j++) { - GraphBuffer[i++] = phase; - phase = !phase; - } - } - - RepaintGraphWindow(); - return 1; -} - -int CmdIndalaClone(const char *Cmd) -{ - UsbCommand c; - unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7; - - uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; - int n = 0, i = 0; - - if (strchr(Cmd,'l') != 0) { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - uid1 = (uid1 << 4) | (uid2 >> 28); - uid2 = (uid2 << 4) | (uid3 >> 28); - uid3 = (uid3 << 4) | (uid4 >> 28); - uid4 = (uid4 << 4) | (uid5 >> 28); - uid5 = (uid5 << 4) | (uid6 >> 28); - uid6 = (uid6 << 4) | (uid7 >> 28); - uid7 = (uid7 << 4) | (n & 0xf); - } - PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); - c.cmd = CMD_INDALA_CLONE_TAG_L; - c.d.asDwords[0] = uid1; - c.d.asDwords[1] = uid2; - c.d.asDwords[2] = uid3; - c.d.asDwords[3] = uid4; - c.d.asDwords[4] = uid5; - c.d.asDwords[5] = uid6; - c.d.asDwords[6] = uid7; - } else { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - uid1 = (uid1 << 4) | (uid2 >> 28); - uid2 = (uid2 << 4) | (n & 0xf); - } - PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); - c.cmd = CMD_INDALA_CLONE_TAG; - c.arg[0] = uid1; - c.arg[1] = uid2; - } - - clearCommandBuffer(); - SendCommand(&c); - return 0; -} +} int usage_lf_read(void) { @@ -1278,9 +1044,11 @@ static command_t CommandTable[] = {"awid", CmdLFAWID, 1, "{ AWID RFIDs... }"}, {"cotag", CmdLFCOTAG, 1, "{ COTAG RFIDs... }"}, {"em", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, + {"gproxii", CmdLF_G_Prox_II, 1, "{ G Prox II tags... }"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, {"io", CmdLFIO, 1, "{ ioProx tags... }"}, + {"indala", CmdLFINDALA, 1, "{ Indala tags... }"}, {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"}, {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, @@ -1291,8 +1059,6 @@ static command_t CommandTable[] = {"cmdread", CmdLFCommandRead, 0, " ['H'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'H' for 134)"}, {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"}, {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, - {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, - {"indalaclone", CmdIndalaClone, 0, " ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"}, {"read", CmdLFRead, 0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"}, {"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"}, {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, diff --git a/client/cmdlfgproxii.c b/client/cmdlfgproxii.c new file mode 100644 index 00000000..06bd53eb --- /dev/null +++ b/client/cmdlfgproxii.c @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// +// 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 G Prox II tag commands +//----------------------------------------------------------------------------- +#include +#include +#include +#include "cmdlfgproxii.h" +#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 "lfdemod.h" +static int CmdHelp(const char *Cmd); + +//by marshmellow +//attempts to demodulate and identify a G_Prox_II verex/chubb card +//WARNING: if it fails during some points it will destroy the DemodBuffer data +// but will leave the GraphBuffer intact. +//if successful it will push askraw data back to demod buffer ready for emulation +int CmdG_Prox_II_Demod(const char *Cmd) +{ + if (!ASKbiphaseDemod(Cmd, false)){ + if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try"); + return 0; + } + size_t size = DemodBufferLen; + //call lfdemod.c demod for gProxII + int ans = gProxII_Demod(DemodBuffer, &size); + if (ans < 0){ + if (g_debugMode) PrintAndLog("Error gProxII_Demod"); + return 0; + } + //got a good demod of 96 bits + uint8_t ByteStream[8] = {0x00}; + uint8_t xorKey=0; + size_t startIdx = ans + 6; //start after 6 bit preamble + + uint8_t bits_no_spacer[90]; + //so as to not mess with raw DemodBuffer copy to a new sample array + memcpy(bits_no_spacer, DemodBuffer + startIdx, 90); + // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72)) + size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run + if (bitLen != 72) { + if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx); + return 0; + } + // get key and then get all 8 bytes of payload decoded + xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8); + for (size_t idx = 0; idx < 8; idx++) { + ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey; + if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); + } + //now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data + // + uint8_t fmtLen = ByteStream[0]>>2; + uint32_t FC = 0; + uint32_t Card = 0; + //get raw 96 bits to print + uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32); + uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32); + + if (fmtLen==36){ + FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); + Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); + PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); + } else if(fmtLen==26){ + FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); + Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); + PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card); + } else { + PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen); + PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8)); + } + PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3); + setDemodBuf(DemodBuffer+ans, 96, 0); + return 1; +} +//by marshmellow +//see ASKDemod for what args are accepted +int CmdG_Prox_II_Read(const char *Cmd) { + // read lf silently + CmdLFRead("s"); + // get samples silently + getSamples("10000",false); + // demod and output viking ID + return CmdG_Prox_II_Demod(Cmd); +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from the GraphBuffer"}, + {"read", CmdG_Prox_II_Read, 0, "Attempt to read and Extract tag data from the antenna"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLF_G_Prox_II(const char *Cmd) { + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfgproxii.h b/client/cmdlfgproxii.h new file mode 100644 index 00000000..35d982f4 --- /dev/null +++ b/client/cmdlfgproxii.h @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// +// 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 G Prox II tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFGPROXII_H__ +#define CMDLFGPROXII_H__ +extern int CmdLF_G_Prox_II(const char *Cmd); +extern int CmdG_Prox_II_Demod(const char *Cmd); +extern int CmdG_Prox_II_Read(const char *Cmd); +#endif diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c new file mode 100644 index 00000000..1a1d2a06 --- /dev/null +++ b/client/cmdlfindala.c @@ -0,0 +1,339 @@ +//----------------------------------------------------------------------------- +// +// 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 Indala commands +//----------------------------------------------------------------------------- + +#include +#include +#include "cmdlfindala.h" +#include "proxmark3.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" //for g_debugMode, demodbuff cmds +#include "lfdemod.h" //for indala26decode +#include "util.h" //for sprint_bin_break +#include "cmdlf.h" //for CmdLFRead +#include "cmdmain.h" //for clearCommandBuffer + +static int CmdHelp(const char *Cmd); + +// Indala 26 bit decode +// by marshmellow +// optional arguments - same as PSKDemod (clock & invert & maxerr) +int CmdIndalaDecode(const char *Cmd) { + int ans; + if (strlen(Cmd)>0) { + ans = PSKDemod(Cmd, 0); + } else { //default to RF/32 + ans = PSKDemod("32", 0); + } + + if (!ans) { + if (g_debugMode) + PrintAndLog("Error1: %i",ans); + return 0; + } + uint8_t invert=0; + size_t size = DemodBufferLen; + int startIdx = indala26decode(DemodBuffer, &size, &invert); + if (startIdx < 0 || size > 224) { + if (g_debugMode) + PrintAndLog("Error2: %i",startIdx); + return -1; + } + setDemodBuf(DemodBuffer, size, (size_t)startIdx); + if (invert) + if (g_debugMode) + PrintAndLog("Had to invert bits"); + + PrintAndLog("BitLen: %d",DemodBufferLen); + //convert UID to HEX + uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; + uid1=bytebits_to_byte(DemodBuffer,32); + uid2=bytebits_to_byte(DemodBuffer+32,32); + if (DemodBufferLen==64) { + PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2); + } else if (DemodBufferLen==224) { + uid3=bytebits_to_byte(DemodBuffer+64,32); + uid4=bytebits_to_byte(DemodBuffer+96,32); + uid5=bytebits_to_byte(DemodBuffer+128,32); + uid6=bytebits_to_byte(DemodBuffer+160,32); + uid7=bytebits_to_byte(DemodBuffer+192,32); + PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)", + sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7); + } + if (g_debugMode) { + PrintAndLog("DEBUG: printing demodbuffer:"); + printDemodBuff(); + } + return 1; +} + +int CmdIndalaRead(const char *Cmd) { + CmdLFRead("s"); + getSamples("30000",false); + return CmdIndalaDecode(""); +} + +// older alternative indala demodulate (has some positives and negatives) +// returns false positives more often - but runs against more sets of samples +// poor psk signal can be difficult to demod this approach might succeed when the other fails +// but the other appears to currently be more accurate than this approach most of the time. +int CmdIndalaDemod(const char *Cmd) { + // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID + + int state = -1; + int count = 0; + int i, j; + + // worst case with GraphTraceLen=64000 is < 4096 + // under normal conditions it's < 2048 + + uint8_t rawbits[4096]; + int rawbit = 0; + int worst = 0, worstPos = 0; + // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); + + // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) + for (i = 0; i < GraphTraceLen-1; i += 2) { + count += 1; + if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { + // appears redundant - marshmellow + if (state == 0) { + for (j = 0; j < count - 8; j += 16) { + rawbits[rawbit++] = 0; + } + if ((abs(count - j)) > worst) { + worst = abs(count - j); + worstPos = i; + } + } + state = 1; + count = 0; + } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { + //appears redundant + if (state == 1) { + for (j = 0; j < count - 8; j += 16) { + rawbits[rawbit++] = 1; + } + if ((abs(count - j)) > worst) { + worst = abs(count - j); + worstPos = i; + } + } + state = 0; + count = 0; + } + } + + if (rawbit>0){ + PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); + PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); + } else { + return 0; + } + + // Finding the start of a UID + int uidlen, long_wait; + if (strcmp(Cmd, "224") == 0) { + uidlen = 224; + long_wait = 30; + } else { + uidlen = 64; + long_wait = 29; + } + + int start; + int first = 0; + for (start = 0; start <= rawbit - uidlen; start++) { + first = rawbits[start]; + for (i = start; i < start + long_wait; i++) { + if (rawbits[i] != first) { + break; + } + } + if (i == (start + long_wait)) { + break; + } + } + + if (start == rawbit - uidlen + 1) { + PrintAndLog("nothing to wait for"); + return 0; + } + + // Inverting signal if needed + if (first == 1) { + for (i = start; i < rawbit; i++) { + rawbits[i] = !rawbits[i]; + } + } + + // Dumping UID + uint8_t bits[224] = {0x00}; + char showbits[225] = {0x00}; + int bit; + i = start; + int times = 0; + + if (uidlen > rawbit) { + PrintAndLog("Warning: not enough raw bits to get a full UID"); + for (bit = 0; bit < rawbit; bit++) { + bits[bit] = rawbits[i++]; + // As we cannot know the parity, let's use "." and "/" + showbits[bit] = '.' + bits[bit]; + } + showbits[bit+1]='\0'; + PrintAndLog("Partial UID=%s", showbits); + return 0; + } else { + for (bit = 0; bit < uidlen; bit++) { + bits[bit] = rawbits[i++]; + showbits[bit] = '0' + bits[bit]; + } + times = 1; + } + + //convert UID to HEX + uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; + int idx; + uid1 = uid2 = 0; + + if (uidlen==64){ + for( idx=0; idx<64; idx++) { + if (showbits[idx] == '0') { + uid1=(uid1<<1)|(uid2>>31); + uid2=(uid2<<1)|0; + } else { + uid1=(uid1<<1)|(uid2>>31); + uid2=(uid2<<1)|1; + } + } + PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2); + } + else { + uid3 = uid4 = uid5 = uid6 = uid7 = 0; + + for( idx=0; idx<224; idx++) { + uid1=(uid1<<1)|(uid2>>31); + uid2=(uid2<<1)|(uid3>>31); + uid3=(uid3<<1)|(uid4>>31); + uid4=(uid4<<1)|(uid5>>31); + uid5=(uid5<<1)|(uid6>>31); + uid6=(uid6<<1)|(uid7>>31); + + if (showbits[idx] == '0') + uid7 = (uid7<<1) | 0; + else + uid7 = (uid7<<1) | 1; + } + PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); + } + + // Checking UID against next occurrences + int failed = 0; + for (; i + uidlen <= rawbit;) { + failed = 0; + for (bit = 0; bit < uidlen; bit++) { + if (bits[bit] != rawbits[i++]) { + failed = 1; + break; + } + } + if (failed == 1) { + break; + } + times += 1; + } + + PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); + + // Remodulating for tag cloning + // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) + // since this changes graphbuffer data. + GraphTraceLen = 32*uidlen; + i = 0; + int phase = 0; + for (bit = 0; bit < uidlen; bit++) { + if (bits[bit] == 0) { + phase = 0; + } else { + phase = 1; + } + int j; + for (j = 0; j < 32; j++) { + GraphBuffer[i++] = phase; + phase = !phase; + } + } + + RepaintGraphWindow(); + return 1; +} + +int CmdIndalaClone(const char *Cmd) { + UsbCommand c; + unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7; + + uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; + int n = 0, i = 0; + + if (strchr(Cmd,'l') != 0) { + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + uid1 = (uid1 << 4) | (uid2 >> 28); + uid2 = (uid2 << 4) | (uid3 >> 28); + uid3 = (uid3 << 4) | (uid4 >> 28); + uid4 = (uid4 << 4) | (uid5 >> 28); + uid5 = (uid5 << 4) | (uid6 >> 28); + uid6 = (uid6 << 4) | (uid7 >> 28); + uid7 = (uid7 << 4) | (n & 0xf); + } + PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); + c.cmd = CMD_INDALA_CLONE_TAG_L; + c.d.asDwords[0] = uid1; + c.d.asDwords[1] = uid2; + c.d.asDwords[2] = uid3; + c.d.asDwords[3] = uid4; + c.d.asDwords[4] = uid5; + c.d.asDwords[5] = uid6; + c.d.asDwords[6] = uid7; + } else { + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + uid1 = (uid1 << 4) | (uid2 >> 28); + uid2 = (uid2 << 4) | (n & 0xf); + } + PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); + c.cmd = CMD_INDALA_CLONE_TAG; + c.arg[0] = uid1; + c.arg[1] = uid2; + } + + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"}, + {"read", CmdIndalaRead, 0, "Read an Indala Prox tag from the antenna"}, + {"clone", CmdIndalaClone, 0, " ['l']-- Clone Indala to T55x7 (tag must be on antenna)(UID in HEX)(option 'l' for 224 UID"}, + {"altdemod", CmdIndalaDemod, 1, "['224'] -- Alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, + //{"sim", CmdIndalaSim, 0, " -- indala tag simulator"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFINDALA(const char *Cmd) { + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfindala.h b/client/cmdlfindala.h new file mode 100644 index 00000000..78502419 --- /dev/null +++ b/client/cmdlfindala.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// +// 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 Indala commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFINDALA_H__ +#define CMDLFINDALA_H__ + +extern int CmdLFINDALA(const char *Cmd); +extern int CmdIndalaDecode(const char *Cmd); +extern int CmdIndalaRead(const char *Cmd); +extern int CmdIndalaClone(const char *Cmd); + +#endif diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 801df8a9..5e80fbb1 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.h @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency T55xx commands +// Low frequency Presco tag commands //----------------------------------------------------------------------------- #ifndef CMDLFPRESCO_H__ #define CMDLFPRESCO_H__ diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h index 80d81d2a..786e5db8 100644 --- a/client/cmdlfpyramid.h +++ b/client/cmdlfpyramid.h @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency T55xx commands +// Low frequency Farpoint / Pyramid commands //----------------------------------------------------------------------------- #ifndef CMDLFPYRAMID_H__ #define CMDLFPYRAMID_H__ diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 601c29f2..838bf79d 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -51,7 +51,6 @@ uint64_t getVikingBits(uint32_t id) { return ((uint64_t)0xF2 << 56) | ((uint64_t)id << 8) | checksum; } -//could be moved to a viking file //by marshmellow //see ASKDemod for what args are accepted int CmdVikingDemod(const char *Cmd) { diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h index cdaad26f..a45dd9a8 100644 --- a/client/cmdlfviking.h +++ b/client/cmdlfviking.h @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency T55xx commands +// Low frequency viking tag commands //----------------------------------------------------------------------------- #ifndef CMDLFVIKING_H__ #define CMDLFVIKING_H__ @@ -14,4 +14,3 @@ extern int CmdVikingRead(const char *Cmd); extern int CmdVikingClone(const char *Cmd); extern int CmdVikingSim(const char *Cmd); #endif - diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 292fa1a3..61669035 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency visa 200 tag commands +// Low frequency visa 2000 tag commands // by iceman //----------------------------------------------------------------------------- diff --git a/client/cmdlfvisa2000.h b/client/cmdlfvisa2000.h index 611768b2..e54ded3b 100644 --- a/client/cmdlfvisa2000.h +++ b/client/cmdlfvisa2000.h @@ -4,7 +4,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency T55xx commands +// Low frequency visa 2000 commands //----------------------------------------------------------------------------- #ifndef CMDLFVISA2000_H__ #define CMDLFVISA2000_H__