X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/2767fc02919545bd65082b4682b2331def9a5ad5..8c6b22980cac809f51cdb307a2043b380659fe9c:/client/cmddata.c diff --git a/client/cmddata.c b/client/cmddata.c index e2e2ca6d..22da1805 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -23,10 +23,12 @@ #include "lfdemod.h" #include "usb_cmd.h" #include "crc.h" +#include "crc16.h" +#include "loclass/cipherutils.h" uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; -uint8_t g_debugMode; -int DemodBufferLen; +uint8_t g_debugMode=0; +size_t DemodBufferLen=0; static int CmdHelp(const char *Cmd); //set the demod buffer with given array of binary (one bit per byte) @@ -55,6 +57,15 @@ int CmdSetDebugMode(const char *Cmd) return 1; } +int usage_data_printdemodbuf(){ + PrintAndLog("Usage: data printdemodbuffer x o "); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" x output in hex (omit for binary output)"); + PrintAndLog(" o enter offset in # of bits"); + return 0; +} + //by marshmellow void printDemodBuff(void) { @@ -73,23 +84,50 @@ void printDemodBuff(void) int CmdPrintDemodBuff(const char *Cmd) { - char hex; - char printBuff[512]={0x00}; - uint8_t numBits = DemodBufferLen & 0xFFFC; - sscanf(Cmd, "%c", &hex); - if (hex == 'h'){ - PrintAndLog("Usage: data printdemodbuffer [x]"); - PrintAndLog("Options: "); - PrintAndLog(" h This help"); - PrintAndLog(" x output in hex (omit for binary output)"); - return 0; + char hex[512]={0x00}; + bool hexMode = false; + bool errors = false; + uint8_t offset = 0; + char cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_data_printdemodbuf(); + case 'x': + case 'X': + hexMode = true; + cmdp++; + break; + case 'o': + case 'O': + offset = param_get8(Cmd, cmdp+1); + if (!offset) errors = true; + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; } - if (hex == 'x'){ - numBits = binarraytohex(printBuff, (char *)DemodBuffer, numBits); + //Validations + if(errors) return usage_data_printdemodbuf(); + + int numBits = (DemodBufferLen-offset) & 0x7FC; //make sure we don't exceed our string + + if (hexMode){ + char *buf = (char *) (DemodBuffer + offset); + numBits = binarraytohex(hex, buf, numBits); if (numBits==0) return 0; - PrintAndLog("DemodBuffer: %s",printBuff); + PrintAndLog("DemodBuffer: %s",hex); } else { - printDemodBuff(); + //setDemodBuf(DemodBuffer, DemodBufferLen-offset, offset); + char *bin = sprint_bin_break(DemodBuffer+offset,numBits,16); + PrintAndLog("DemodBuffer:\n%s",bin); } return 1; } @@ -208,22 +246,34 @@ void printEM410x(uint32_t hi, uint64_t id) return; } - -int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo) +int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) { - int ans = ASKmanDemod(Cmd, FALSE, FALSE); - if (!ans) return 0; - - size_t idx=0; - if (Em410xDecode(DemodBuffer,(size_t *) &DemodBufferLen, &idx, hi, lo)){ + size_t idx = 0; + size_t BitLen = DemodBufferLen; + uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; + memcpy(BitStream, DemodBuffer, BitLen); + if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)){ + //set GraphBuffer for clone or sim command + setDemodBuf(BitStream, BitLen, idx); if (g_debugMode){ - PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, DemodBufferLen); + PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen); printDemodBuff(); } + if (verbose){ + PrintAndLog("EM410x pattern found: "); + printEM410x(*hi, *lo); + } return 1; } return 0; } + +int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose) +{ + if (!ASKDemod(Cmd, FALSE, FALSE, 1)) return 0; + return AskEm410xDecode(verbose, hi, lo); +} + //by marshmellow //takes 3 arguments - clock, invert and maxErr as integers //attempts to demodulate ask while decoding manchester @@ -244,28 +294,28 @@ int CmdAskEM410xDemod(const char *Cmd) PrintAndLog(" : data askem410xdemod 64 1 0 = demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"); return 0; } - uint32_t hi = 0; uint64_t lo = 0; - if (AskEm410xDemod(Cmd, &hi, &lo)) { - PrintAndLog("EM410x pattern found: "); - printEM410x(hi, lo); - return 1; - } - return 0; + uint32_t hi = 0; + return AskEm410xDemod(Cmd, &hi, &lo, true); } -int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch) +//by marshmellow +//Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a' +// (amp may not be needed anymore) +//verbose will print results and demoding messages +//emSearch will auto search for EM410x format in bitstream +//askType switches decode: ask/raw = 0, ask/manchester = 1 +int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) { int invert=0; int clk=0; int maxErr=100; - int maxLen=512*64; - //param_getdec(Cmd, 0, &clk); - //param_getdec(Cmd, 1, &invert); - //maxErr = param_get32ex(Cmd, 2, 0xFFFFFFFF, 10); - //if (maxErr == 0xFFFFFFFF) maxErr=100; + int maxLen=0; + uint8_t askAmp = 0; + char amp = param_getchar(Cmd, 0); uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - sscanf(Cmd, "%i %i %i %i", &clk, &invert, &maxErr, &maxLen); + sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &); + if (!maxLen) maxLen = 512*64; if (invert != 0 && invert != 1) { PrintAndLog("Invalid argument: %s", Cmd); return 0; @@ -274,12 +324,14 @@ int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch) invert=1; clk=0; } + if (amp == 'a' || amp == 'A') askAmp=1; size_t BitLen = getFromGraphBuf(BitStream); if (g_debugMode) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen); - if (!BitLen) return 0; + if (BitLen<255) return 0; if (maxLen0){ - if (verbose || g_debugMode) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); - } - if (verbose || g_debugMode) PrintAndLog("ASK/Manchester decoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits setDemodBuf(BitStream,BitLen,0); - if (verbose || g_debugMode) printDemodBuff(); - uint64_t lo =0; - uint32_t hi =0; - size_t idx=0; + if (verbose || g_debugMode){ + if (errCnt>0) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); + if (askType) PrintAndLog("ASK/Manchester - Clock: %d - Decoded bitstream:",clk); + else PrintAndLog("ASK/Raw - Clock: %d - Decoded bitstream:",clk); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + + } + uint64_t lo = 0; + uint32_t hi = 0; if (emSearch){ - if (Em410xDecode(BitStream, &BitLen, &idx, &hi, &lo)){ - //set GraphBuffer for clone or sim command - setDemodBuf(BitStream, BitLen, idx); - if (g_debugMode){ - PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen); - printDemodBuff(); - } - if (verbose) PrintAndLog("EM410x pattern found: "); - if (verbose) printEM410x(hi, lo); - return 1; - } + AskEm410xDecode(true, &hi, &lo); } return 1; } //by marshmellow -//takes 3 arguments - clock, invert, maxErr as integers +//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a' //attempts to demodulate ask while decoding manchester //prints binary found and saves in graphbuffer for further commands int Cmdaskmandemod(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 20 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: data rawdemod am [clock] <0|1> [maxError] [setSmplLen]"); - PrintAndLog(" [set clock as integer] optional, if not set, autodetect."); - PrintAndLog(" , 1 for invert output"); - PrintAndLog(" [set maximum allowed errors], default = 100."); - PrintAndLog(" [set maximum Samples to read], default = 32768 (512 bits at rf/64)."); + if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]"); + PrintAndLog(" [set clock as integer] optional, if not set, autodetect"); + PrintAndLog(" , 1 to invert output"); + PrintAndLog(" [set maximum allowed errors], default = 100"); + PrintAndLog(" [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); + PrintAndLog(" , 'a' to attempt demod with ask amplification, default = no amp"); PrintAndLog(""); PrintAndLog(" sample: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); PrintAndLog(" : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); @@ -337,7 +381,7 @@ int Cmdaskmandemod(const char *Cmd) PrintAndLog(" : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); return 0; } - return ASKmanDemod(Cmd, TRUE, TRUE); + return ASKDemod(Cmd, TRUE, TRUE, 1); } //by marshmellow @@ -348,12 +392,15 @@ int Cmdmandecoderaw(const char *Cmd) int i =0; int errCnt=0; size_t size=0; - size_t maxErr = 20; + int invert=0; + int maxErr = 20; char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: data manrawdecode"); + if (strlen(Cmd) > 5 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: data manrawdecode [invert] [maxErr]"); PrintAndLog(" Takes 10 and 01 and converts to 0 and 1 respectively"); PrintAndLog(" --must have binary sequence in demodbuffer (run data askrawdemod first)"); + PrintAndLog(" [invert] invert output"); + PrintAndLog(" [maxErr] set number of errors allowed (default = 20)"); PrintAndLog(""); PrintAndLog(" sample: data manrawdecode = decode manchester bitstream from the demodbuffer"); return 0; @@ -366,12 +413,14 @@ int Cmdmandecoderaw(const char *Cmd) else if(DemodBuffer[i]1 || low <0 ){ + if (high>7 || low <0 ){ PrintAndLog("Error: please raw demod the wave first then manchester raw decode"); return 0; } + + sscanf(Cmd, "%i %i", &invert, &maxErr); size=i; - errCnt=manrawdecode(BitStream, &size); + errCnt=manrawdecode(BitStream, &size, invert); if (errCnt>=maxErr){ PrintAndLog("Too many errors: %d",errCnt); return 0; @@ -445,81 +494,25 @@ int CmdBiphaseDecodeRaw(const char *Cmd) return 1; } -//by marshmellow -//takes 4 arguments - clock, invert, maxErr as integers and amplify as char -//attempts to demodulate ask only -//prints binary found and saves in graphbuffer for further commands -int ASKrawDemod(const char *Cmd, bool verbose) -{ - int invert=0; - int clk=0; - int maxErr=100; - uint8_t askAmp = 0; - char amp = param_getchar(Cmd, 0); - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; - sscanf(Cmd, "%i %i %i %c", &clk, &invert, &maxErr, &); - if (invert != 0 && invert != 1) { - if (verbose || g_debugMode) PrintAndLog("Invalid argument: %s", Cmd); - return 0; - } - if (clk==1){ - invert=1; - clk=0; - } - if (amp == 'a' || amp == 'A') askAmp=1; - size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen==0) return 0; - int errCnt = askrawdemod(BitStream, &BitLen, &clk, &invert, maxErr, askAmp); - if (errCnt==-1||BitLen<16){ //throw away static - allow 1 and -1 (in case of threshold command first) - if (verbose || g_debugMode) PrintAndLog("no data found"); - if (g_debugMode) PrintAndLog("errCnt: %d, BitLen: %d, clk: %d, invert: %d", errCnt, BitLen, clk, invert); - return 0; - } - if (errCnt>maxErr) { - if (g_debugMode) - PrintAndLog("Too many errors found, errCnt: %d, BitLen: %d, clk: %d, invert: %d", errCnt, BitLen, clk, invert); - return 0; - } - if (verbose || g_debugMode) - PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen); - - //move BitStream back to DemodBuffer - setDemodBuf(BitStream,BitLen,0); - - //output - if (errCnt>0 && (verbose || g_debugMode)){ - PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); - } - if (verbose || g_debugMode){ - PrintAndLog("ASK demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - } - return 1; -} - //by marshmellow // - ASK Demod then Biphase decode GraphBuffer samples int ASKbiphaseDemod(const char *Cmd, bool verbose) { //ask raw demod GraphBuffer first - int offset=0, clk=0, invert=0, maxErr=0, ans=0; - ans = sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); - if (ans>0) - ans = ASKrawDemod(Cmd+1, FALSE); - else - ans = ASKrawDemod(Cmd, FALSE); - if (!ans) { - if (g_debugMode || verbose) PrintAndLog("Error AskrawDemod: %d", ans); - return 0; - } - - //attempt to Biphase decode DemodBuffer - size_t size = DemodBufferLen; - uint8_t BitStream[MAX_DEMOD_BUF_LEN]; - memcpy(BitStream, DemodBuffer, DemodBufferLen); + int offset=0, clk=0, invert=0, maxErr=0; + sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); + + uint8_t BitStream[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(BitStream); + //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer + int errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0); + if ( errCnt < 0 || errCnt > maxErr ) { + if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk); + return 0; + } - int errCnt = BiphaseRawDecode(BitStream, &size, offset, invert); + //attempt to Biphase decode BitStream + errCnt = BiphaseRawDecode(BitStream, &size, offset, invert); if (errCnt < 0){ if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode: %d", errCnt); return 0; @@ -531,7 +524,7 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) //success set DemodBuffer and return setDemodBuf(BitStream, size, 0); if (g_debugMode || verbose){ - PrintAndLog("Biphase Decoded using offset: %d - # errors:%d - data:",offset,errCnt); + PrintAndLog("Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt); printDemodBuff(); } return 1; @@ -540,12 +533,13 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) int Cmdaskbiphdemod(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 12 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: data rawdemod ab [offset] [clock] [maxError] "); + if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] "); PrintAndLog(" [offset], offset to begin biphase, default=0"); PrintAndLog(" [set clock as integer] optional, if not set, autodetect"); PrintAndLog(" , 1 to invert output"); PrintAndLog(" [set maximum allowed errors], default = 100"); + PrintAndLog(" [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); PrintAndLog(" , 'a' to attempt demod with ask amplification, default = no amp"); PrintAndLog(" NOTE: can be entered as second or third argument"); PrintAndLog(" NOTE: can be entered as first, second or last argument"); @@ -553,13 +547,13 @@ int Cmdaskbiphdemod(const char *Cmd) PrintAndLog(""); PrintAndLog(" NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); PrintAndLog(""); - PrintAndLog(" sample: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); - PrintAndLog(" : data rawdemod ab a = demod an ask/biph tag from GraphBuffer, amplified"); - PrintAndLog(" : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); - PrintAndLog(" : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLog(" : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); - PrintAndLog(" : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLog(" : data rawdemod ab 0 64 1 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + PrintAndLog(" sample: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); + PrintAndLog(" : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); + PrintAndLog(" : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); + PrintAndLog(" : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLog(" : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); + PrintAndLog(" : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLog(" : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); return 0; } return ASKbiphaseDemod(Cmd, TRUE); @@ -643,27 +637,28 @@ int CmdG_Prox_II_Demod(const char *Cmd) return 1; } -//by marshmellow - see ASKrawDemod +//by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 12 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: data rawdemod ar [clock] [maxError] [amplify]"); + if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]"); PrintAndLog(" [set clock as integer] optional, if not set, autodetect"); PrintAndLog(" , 1 to invert output"); PrintAndLog(" [set maximum allowed errors], default = 100"); + PrintAndLog(" [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); PrintAndLog(" , 'a' to attempt demod with ask amplification, default = no amp"); PrintAndLog(""); - PrintAndLog(" sample: data rawdemod ar = demod an ask tag from GraphBuffer"); - PrintAndLog(" : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); - PrintAndLog(" : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); - PrintAndLog(" : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLog(" : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); - PrintAndLog(" : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLog(" : data rawdemod ar 64 1 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + PrintAndLog(" sample: data rawdemod ar = demod an ask tag from GraphBuffer"); + PrintAndLog(" : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); + PrintAndLog(" : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); + PrintAndLog(" : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLog(" : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); + PrintAndLog(" : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLog(" : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); return 0; } - return ASKrawDemod(Cmd, TRUE); + return ASKDemod(Cmd, TRUE, FALSE, 0); } int AutoCorrelate(int window, bool SaveGrph, bool verbose) @@ -846,24 +841,14 @@ int CmdAskEdgeDetect(const char *Cmd) { int thresLen = 25; sscanf(Cmd, "%i", &thresLen); - int shift = 127; - int shiftedVal=0; + for(int i = 1; i=thresLen) //large jump up - shift=127; + GraphBuffer[i-1] = 127; else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down - shift=-127; - - shiftedVal=GraphBuffer[i]+shift; - - if (shiftedVal>127) - shiftedVal=127; - else if (shiftedVal<-127) - shiftedVal=-127; - GraphBuffer[i-1] = shiftedVal; + GraphBuffer[i-1] = -127; } RepaintGraphWindow(); - //CmdNorm(""); return 0; } @@ -873,9 +858,10 @@ int CmdAskEdgeDetect(const char *Cmd) int CmdDetectClockRate(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 3 || strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: data detectclock [modulation]"); + if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: data detectclock [modulation] "); PrintAndLog(" [modulation as char], specify the modulation type you want to detect the clock of"); + PrintAndLog(" , specify the clock (optional - to get best start position only)"); PrintAndLog(" 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk"); PrintAndLog(""); PrintAndLog(" sample: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer"); @@ -885,7 +871,7 @@ int CmdDetectClockRate(const char *Cmd) } int ans=0; if (cmdp == 'a'){ - ans = GetAskClock("", true, false); + ans = GetAskClock(Cmd+1, true, false); } else if (cmdp == 'f'){ ans = GetFskClock("", true, false); } else if (cmdp == 'n'){ @@ -1471,6 +1457,83 @@ int CmdFSKdemodPyramid(const char *Cmd) return 1; } +// FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits) +// 8 databits + 1 parity (1) +// CIITT 16 chksum +// NATIONAL CODE, ICAR database +// COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf +// FLAG (animal/non-animal) +int CmdFDXBdemodBI(const char *Cmd){ + + int invert = 1; + int clk = 32; + int errCnt = 0; + int maxErr = 0; + uint8_t BitStream[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(BitStream); + + errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0); + if ( errCnt < 0 || errCnt > maxErr ) { + if (g_debugMode) PrintAndLog("DEBUG: no data or error found %d, clock: %d", errCnt, clk); + return 0; + } + + errCnt = BiphaseRawDecode(BitStream, &size, maxErr, 1); + if (errCnt < 0 || errCnt > maxErr ) { + if (g_debugMode) PrintAndLog("Error BiphaseRawDecode: %d", errCnt); + return 0; + } + + int preambleIndex = FDXBdemodBI(BitStream, &size); + if (preambleIndex < 0){ + if (g_debugMode) PrintAndLog("Error FDXBDemod , no startmarker found :: %d",preambleIndex); + return 0; + } + + setDemodBuf(BitStream, 128, preambleIndex); + + // remove marker bits (1's every 9th digit after preamble) (pType = 2) + size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117); + if ( size != 104 ) { + if (g_debugMode) PrintAndLog("Error removeParity:: %d", size); + return 0; + } + if (g_debugMode) { + char *bin = sprint_bin_break(BitStream,size,16); + PrintAndLog("DEBUG BinStream:\n%s",bin); + } + PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); + if (g_debugMode) PrintAndLog("Start marker %d; Size %d", preambleIndex, size); + + //got a good demod + uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32); + uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10); + uint8_t dataBlockBit = BitStream[48]; + uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14); + uint8_t animalBit = BitStream[63]; + uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16); + uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24); + + uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32); + uint8_t raw[8]; + num_to_bytes(rawid, 8, raw); + + if (g_debugMode) PrintAndLog("Raw ID Hex: %s", sprint_hex(raw,8)); + + uint16_t calcCrc = crc16_ccitt_kermit(raw, 8); + PrintAndLog("Animal ID: %04u-%012llu", countryCode, NationalCode); + PrintAndLog("National Code: %012llu", NationalCode); + PrintAndLog("CountryCode: %04u", countryCode); + PrintAndLog("Extended Data: %s", dataBlockBit ? "True" : "False"); + PrintAndLog("reserved Code: %u", reservedCode); + PrintAndLog("Animal Tag: %s", animalBit ? "True" : "False"); + PrintAndLog("CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); + PrintAndLog("Extended: 0x%X\n", extended); + + return 1; +} + + //by marshmellow //attempt to psk1 demod graph buffer int PSKDemod(const char *Cmd, bool verbose) @@ -1484,12 +1547,12 @@ int PSKDemod(const char *Cmd, bool verbose) clk=0; } if (invert != 0 && invert != 1) { - if (verbose) PrintAndLog("Invalid argument: %s", Cmd); + if (g_debugMode || verbose) PrintAndLog("Invalid argument: %s", Cmd); return 0; } uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen==0) return -1; + if (BitLen==0) return 0; uint8_t carrier=countFC(BitStream, BitLen, 0); if (carrier!=2 && carrier!=4 && carrier!=8){ //invalid carrier @@ -1534,7 +1597,7 @@ int CmdIndalaDecode(const char *Cmd) return 0; } uint8_t invert=0; - ans = indala26decode(DemodBuffer,(size_t *) &DemodBufferLen, &invert); + ans = indala26decode(DemodBuffer, &DemodBufferLen, &invert); if (ans < 1) { if (g_debugMode==1) PrintAndLog("Error2: %d",ans); @@ -1597,11 +1660,49 @@ int CmdIndalaDecode(const char *Cmd) return 1; } +int CmdPSKNexWatch(const char *Cmd) +{ + if (!PSKDemod("", false)) return 0; + uint8_t preamble[28] = {0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + size_t startIdx = 0, size = DemodBufferLen; + bool invert = false; + if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)){ + // if didn't find preamble try again inverting + if (!PSKDemod("1", false)) return 0; + size = DemodBufferLen; + if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)) return 0; + invert = true; + } + if (size != 128) return 0; + setDemodBuf(DemodBuffer, size, startIdx+4); + startIdx = 8+32; //4 = extra i added, 8 = preamble, 32 = reserved bits (always 0) + //get ID + uint32_t ID = 0; + for (uint8_t wordIdx=0; wordIdx<4; wordIdx++){ + for (uint8_t idx=0; idx<8; idx++){ + ID = (ID << 1) | DemodBuffer[startIdx+wordIdx+(idx*4)]; + } + } + //parity check (TBD) + + //checksum check (TBD) + + //output + PrintAndLog("NexWatch ID: %d", ID); + if (invert){ + PrintAndLog("Had to Invert - probably NexKey"); + for (uint8_t idx=0; idxposition >> 3; // divide by 8 - int bitpos = (stream->position++) & 7; // mask out 00000111 - return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; -} -uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) +uint8_t getByte(uint8_t bits_per_sample, BitstreamIn* b) { int i; uint8_t val = 0; for(i =0 ; i < bits_per_sample; i++) { - val |= (_headBit(b) << (7-i)); + val |= (headBit(b) << (7-i)); } return val; } @@ -1902,9 +1991,9 @@ int getSamples(const char *Cmd, bool silent) if(bits_per_sample < 8) { PrintAndLog("Unpacking..."); - BitstreamOut bout = { got, bits_per_sample * n, 0}; + BitstreamIn bout = { got, bits_per_sample * n, 0}; int j =0; - for (j = 0; j * bits_per_sample < n * 8 && j < sizeof(GraphBuffer); j++) { + for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { uint8_t sample = getByte(bits_per_sample, &bout); GraphBuffer[j] = ((int) sample )- 128; } @@ -2017,7 +2106,7 @@ int CmdLoad(const char *Cmd) int CmdLtrim(const char *Cmd) { int ds = atoi(Cmd); - + if (GraphTraceLen<=0) return 0; for (int i = ds; i < GraphTraceLen; ++i) GraphBuffer[i-ds] = GraphBuffer[i]; GraphTraceLen -= ds; @@ -2165,18 +2254,113 @@ int CmdZerocrossings(const char *Cmd) return 0; } +int usage_data_bin2hex(){ + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); + return 0; +} + +/** + * @brief Utility for conversion via cmdline. + * @param Cmd + * @return + */ +int Cmdbin2hex(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_bin2hex(); + } + //Number of digits supplied as argument + size_t length = en - bg +1; + size_t bytelen = (length+7) / 8; + uint8_t* arr = (uint8_t *) malloc(bytelen); + memset(arr, 0, bytelen); + BitstreamOut bout = { arr, 0, 0 }; + + for(; bg <= en ;bg++) + { + char c = Cmd[bg]; + if( c == '1') pushBit(&bout, 1); + else if( c == '0') pushBit(&bout, 0); + else PrintAndLog("Ignoring '%c'", c); + } + + if(bout.numbits % 8 != 0) + { + printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8)); + } + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + for(size_t x = 0; x < bytelen ; x++) + { + printf("%02X", arr[x]); + } + printf("\n"); + free(arr); + return 0; +} + +int usage_data_hex2bin(){ + + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); + return 0; + +} + +int Cmdhex2bin(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_hex2bin(); + } + + + while(bg <= en ) + { + char x = Cmd[bg++]; + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else + continue; + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + + for(int i= 0 ; i < 4 ; ++i) + printf("%d",(x >> (3 - i)) & 1); + } + printf("\n"); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ask demod using length of sample differences to detect the edge of a wave (default = 25)"}, + {"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)"}, {"askem410xdemod", CmdAskEM410xDemod, 1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"}, {"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>] Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, + {"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"}, {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"}, {"dec", CmdDec, 1, "Decimate samples"}, {"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"}, + {"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"}, {"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"}, //{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"}, {"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"}, @@ -2186,16 +2370,18 @@ static command_t CommandTable[] = {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, + {"hex2bin", Cmdhex2bin, 1, "hex2bin -- Converts hexadecimal to binary"}, {"hide", CmdHide, 1, "Hide graph window"}, {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, {"load", CmdLoad, 1, " -- Load trace (to graph window"}, {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, {"rtrim", CmdRtrim, 1, " -- Trim samples from right of trace"}, - {"manrawdecode", Cmdmandecoderaw, 1, "Manchester decode binary stream in DemodBuffer"}, + {"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"}, {"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] -- print the data in the DemodBuffer - 'x' for hex output"}, + {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] -- 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)"}, {"save", CmdSave, 1, " -- Save trace (from graph window)"},