From: Martin Holst Swende Date: Tue, 14 Apr 2015 18:36:10 +0000 (+0200) Subject: Merge pull request #92 from marshmellow42/master X-Git-Tag: v2.1.0~16^2 X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/cb8220ee769ac07bdf7656161a3961cf6515223a?hp=83602affe5ae7fd7fdc1b91722599c2450285929 Merge pull request #92 from marshmellow42/master lf cleanup, dedup & minor additions --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ff77396..85e7f915 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,13 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [Unreleased][unreleased] ### Changed +- Improved LF manchester and biphase demodulation and ask clock detection especially for reads with heavy clipping. (marshmellow) - Iclass read, `hf iclass read` now also reads tag config and prints configuration. (holiman) - *bootrom* needs to be flashed, due to new address boundaries between os and fpga, after a size optimization (piwi) ### Fixed -- Fixed issue #19, problems with LF T55xx commands (marshmellow) +- Fixed EM4x50 read/demod of the tags broadcasted memory blocks. 'lf em4x em4x50read' (not page read) (marshmellow) +- Fixed issue #19, problems with LF T55xx commands (iceman1001, marshmellow) ### Added - Added changelog diff --git a/armsrc/lfops.c b/armsrc/lfops.c index e5a40b2e..e45b55fc 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -861,7 +861,7 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol) size = BigBuf_max_traceLen(); //askdemod and manchester decode if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format - errCnt = askmandemod(dest, &size, &clk, &invert, maxErr); + errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); WDT_HIT(); if (errCnt<0) continue; diff --git a/client/cmddata.c b/client/cmddata.c index 55959984..556ede06 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -58,37 +58,16 @@ int CmdSetDebugMode(const char *Cmd) //by marshmellow void printDemodBuff(void) { - uint32_t i = 0; int bitLen = DemodBufferLen; - if (bitLen<16) { + if (bitLen<1) { PrintAndLog("no bits found in demod buffer"); return; } if (bitLen>512) bitLen=512; //max output to 512 bits if we have more - should be plenty - // ensure equally divided by 16 - bitLen &= 0xfff0; - - for (i = 0; i <= (bitLen-16); i+=16) { - PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i", - DemodBuffer[i], - DemodBuffer[i+1], - DemodBuffer[i+2], - DemodBuffer[i+3], - DemodBuffer[i+4], - DemodBuffer[i+5], - DemodBuffer[i+6], - DemodBuffer[i+7], - DemodBuffer[i+8], - DemodBuffer[i+9], - DemodBuffer[i+10], - DemodBuffer[i+11], - DemodBuffer[i+12], - DemodBuffer[i+13], - DemodBuffer[i+14], - DemodBuffer[i+15] - ); - } + char *bin = sprint_bin_break(DemodBuffer,bitLen,16); + PrintAndLog("%s",bin); + return; } @@ -96,7 +75,7 @@ int CmdPrintDemodBuff(const char *Cmd) { char hex; char printBuff[512]={0x00}; - uint8_t numBits = DemodBufferLen & 0xFFF0; + uint8_t numBits = DemodBufferLen & 0xFFFC; sscanf(Cmd, "%c", &hex); if (hex == 'h'){ PrintAndLog("Usage: data printdemodbuffer [x]"); @@ -114,105 +93,8 @@ int CmdPrintDemodBuff(const char *Cmd) } return 1; } -int CmdAmp(const char *Cmd) -{ - int i, rising, falling; - int max = INT_MIN, min = INT_MAX; - - for (i = 10; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] > max) - max = GraphBuffer[i]; - if (GraphBuffer[i] < min) - min = GraphBuffer[i]; - } - - if (max != min) { - rising = falling= 0; - for (i = 0; i < GraphTraceLen; ++i) { - if (GraphBuffer[i + 1] < GraphBuffer[i]) { - if (rising) { - GraphBuffer[i] = max; - rising = 0; - } - falling = 1; - } - if (GraphBuffer[i + 1] > GraphBuffer[i]) { - if (falling) { - GraphBuffer[i] = min; - falling = 0; - } - rising= 1; - } - } - } - RepaintGraphWindow(); - return 0; -} - -/* - * Generic command to demodulate ASK. - * - * Argument is convention: positive or negative (High mod means zero - * or high mod means one) - * - * Updates the Graph trace with 0/1 values - * - * Arguments: - * c : 0 or 1 (or invert) - */ - //this method ignores the clock - - //this function strictly converts highs and lows to 1s and 0s for each sample in the graphbuffer -int Cmdaskdemod(const char *Cmd) -{ - int i; - int c, high = 0, low = 0; - - sscanf(Cmd, "%i", &c); - - /* Detect high and lows */ - for (i = 0; i < GraphTraceLen; ++i) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - high=abs(high*.75); - low=abs(low*.75); - if (c != 0 && c != 1) { - PrintAndLog("Invalid argument: %s", Cmd); - return 0; - } - //prime loop - if (GraphBuffer[0] > 0) { - GraphBuffer[0] = 1-c; - } else { - GraphBuffer[0] = c; - } - for (i = 1; i < GraphTraceLen; ++i) { - /* Transitions are detected at each peak - * Transitions are either: - * - we're low: transition if we hit a high - * - we're high: transition if we hit a low - * (we need to do it this way because some tags keep high or - * low for long periods, others just reach the peak and go - * down) - */ - //[marhsmellow] change == to >= for high and <= for low for fuzz - if ((GraphBuffer[i] >= high) && (GraphBuffer[i - 1] == c)) { - GraphBuffer[i] = 1 - c; - } else if ((GraphBuffer[i] <= low) && (GraphBuffer[i - 1] == (1 - c))){ - GraphBuffer[i] = c; - } else { - /* No transition */ - GraphBuffer[i] = GraphBuffer[i - 1]; - } - } - RepaintGraphWindow(); - return 0; -} +//by marshmellow //this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer int CmdGetBitStream(const char *Cmd) { @@ -229,43 +111,6 @@ int CmdGetBitStream(const char *Cmd) return 0; } - -//by marshmellow -void printBitStream(uint8_t BitStream[], uint32_t bitLen) -{ - uint32_t i = 0; - if (bitLen<16) { - PrintAndLog("Too few bits found: %d",bitLen); - return; - } - if (bitLen>512) bitLen=512; - - // ensure equally divided by 16 - bitLen &= 0xfff0; - - - for (i = 0; i <= (bitLen-16); i+=16) { - PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i", - BitStream[i], - BitStream[i+1], - BitStream[i+2], - BitStream[i+3], - BitStream[i+4], - BitStream[i+5], - BitStream[i+6], - BitStream[i+7], - BitStream[i+8], - BitStream[i+9], - BitStream[i+10], - BitStream[i+11], - BitStream[i+12], - BitStream[i+13], - BitStream[i+14], - BitStream[i+15] - ); - } - return; -} //by marshmellow //print 64 bit EM410x ID in multiple formats void printEM410x(uint32_t hi, uint64_t id) @@ -282,11 +127,11 @@ void printEM410x(uint32_t hi, uint64_t id) } if (hi){ //output 88 bit em id - PrintAndLog("\nEM TAG ID : %06x%016llx", hi, id); + PrintAndLog("\nEM TAG ID : %06X%016llX", hi, id); } else{ //output 40 bit em id - PrintAndLog("\nEM TAG ID : %010llx", id); - PrintAndLog("Unique TAG ID : %010llx", id2lo); + PrintAndLog("\nEM TAG ID : %010llX", id); + PrintAndLog("Unique TAG ID : %010llX", id2lo); PrintAndLog("\nPossible de-scramble patterns"); PrintAndLog("HoneyWell IdentKey {"); PrintAndLog("DEZ 8 : %08lld",id & 0xFFFFFF); @@ -311,7 +156,7 @@ void printEM410x(uint32_t hi, uint64_t id) ); uint64_t paxton = (((id>>32) << 24) | (id & 0xffffff)) + 0x143e00; PrintAndLog("}\nOther : %05lld_%03lld_%08lld",(id&0xFFFF),((id>>16LL) & 0xFF),(id & 0xFFFFFF)); - PrintAndLog("Pattern Paxton : %0d", paxton); + PrintAndLog("Pattern Paxton : %lld [0x%llX]", paxton, paxton); uint32_t p1id = (id & 0xFFFFFF); uint8_t arr[32] = {0x00}; @@ -352,33 +197,45 @@ void printEM410x(uint32_t hi, uint64_t id) p1 |= arr[2] << 4; p1 |= arr[1] << 5; p1 |= arr[0] << 9; - PrintAndLog("Pattern 1 : 0x%X - %d", p1, p1); + PrintAndLog("Pattern 1 : %d [0x%X]", p1, p1); uint16_t sebury1 = id & 0xFFFF; uint8_t sebury2 = (id >> 16) & 0x7F; uint32_t sebury3 = id & 0x7FFFFF; - PrintAndLog("Pattern Sebury : %d %d %d (hex: %X %X %X)", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3); + PrintAndLog("Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3); } } 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 @@ -399,27 +256,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; - //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", &clk, &invert, &maxErr); + 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; @@ -428,56 +286,55 @@ 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==1) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen); - if (BitLen==0) return 0; - int errCnt=0; - errCnt = askmandemod(BitStream, &BitLen, &clk, &invert, maxErr); - if (errCnt<0||BitLen<16){ //if fatal error (or -1) - if (g_debugMode==1) PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk); + if (g_debugMode) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen); + if (BitLen<255) return 0; + if (maxLenmaxErr){ + if (g_debugMode) PrintAndLog("DEBUG: Too many errors found, errors:%d, bits:%d, clock:%d",errCnt, BitLen, clk); + return 0; + } + if (verbose || g_debugMode) PrintAndLog("\nUsing Clock:%d, Invert:%d, Bits Found:%d",clk,invert,BitLen); //output - if (errCnt>0){ - if (verbose || g_debugMode) PrintAndLog("# Errors during Demoding (shown as 77 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 decoded bitstream:"); + else PrintAndLog("ASK/Raw decoded bitstream:"); + // 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) > 10 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: data rawdemod am [clock] <0|1> [maxError]"); - PrintAndLog(" [set clock as integer] optional, if not set, autodetect."); - PrintAndLog(" , 1 for invert output"); - PrintAndLog(" [set maximum allowed errors], default = 100."); + 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"); @@ -486,7 +343,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 @@ -497,12 +354,15 @@ int Cmdmandecoderaw(const char *Cmd) int i =0; int errCnt=0; size_t size=0; + int invert=0; size_t 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; @@ -515,18 +375,20 @@ int Cmdmandecoderaw(const char *Cmd) else if(DemodBuffer[i]1 || low <0 ){ - PrintAndLog("Error: please raw demod the wave first then mancheseter raw decode"); + 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; } PrintAndLog("Manchester Decoded - # errors:%d - data:",errCnt); - printBitStream(BitStream, size); + PrintAndLog("%s", sprint_bin_break(BitStream, size, 16)); if (errCnt==0){ uint64_t id = 0; uint32_t hi = 0; @@ -546,11 +408,7 @@ int Cmdmandecoderaw(const char *Cmd) //take 01 or 10 = 0 and 11 or 00 = 1 //takes 2 arguments "offset" default = 0 if 1 it will shift the decode by one bit // and "invert" default = 0 if 1 it will invert output -// since it is not like manchester and doesn't have an incorrect bit pattern we -// cannot determine if our decode is correct or if it should be shifted by one bit -// the argument offset allows us to manually shift if the output is incorrect -// (better would be to demod and decode at the same time so we can distinguish large -// width waves vs small width waves to help the decode positioning) or askbiphdemod +// the argument offset allows us to manually shift if the output is incorrect - [EDIT: now auto detects] int CmdBiphaseDecodeRaw(const char *Cmd) { size_t size=0; @@ -589,87 +447,15 @@ int CmdBiphaseDecodeRaw(const char *Cmd) } if (errCnt>0){ - PrintAndLog("# Errors found during Demod (shown as 77 in bit stream): %d",errCnt); + PrintAndLog("# Errors found during Demod (shown as 7 in bit stream): %d",errCnt); } PrintAndLog("Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert); - printBitStream(BitStream, size); + PrintAndLog("%s", sprint_bin_break(BitStream, size, 16)); if (offset) setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); //remove first bit from raw demod return 1; } -// set demod buffer back to raw after biphase demod -void setBiphasetoRawDemodBuf(uint8_t *BitStream, size_t size) -{ - uint8_t rawStream[512]={0x00}; - size_t i=0; - uint8_t curPhase=0; - if (size > 256) { - PrintAndLog("ERROR - Biphase Demod Buffer overrun"); - return; - } - for (size_t idx=0; idx0 && (verbose || g_debugMode)){ - PrintAndLog("# Errors during Demoding (shown as 77 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 - printBitStream(BitStream,BitLen); - } - return 1; -} - //by marshmellow // - ASK Demod then Biphase decode GraphBuffer samples int ASKbiphaseDemod(const char *Cmd, bool verbose) @@ -678,11 +464,11 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) 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); + ans = ASKDemod(Cmd+1, FALSE, FALSE, 0); else - ans = ASKrawDemod(Cmd, FALSE); + ans = ASKDemod(Cmd, FALSE, FALSE, 0); if (!ans) { - if (g_debugMode || verbose) PrintAndLog("Error AskrawDemod: %d", ans); + if (g_debugMode || verbose) PrintAndLog("Error AskDemod: %d", ans); return 0; } @@ -690,8 +476,7 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) size_t size = DemodBufferLen; uint8_t BitStream[MAX_DEMOD_BUF_LEN]; memcpy(BitStream, DemodBuffer, DemodBufferLen); - - int errCnt = BiphaseRawDecode(BitStream, &size, offset, invert); + int errCnt = BiphaseRawDecode(BitStream, &size, offset, 0); if (errCnt < 0){ if (g_debugMode || verbose) PrintAndLog("Error BiphaseRawDecode: %d", errCnt); return 0; @@ -712,12 +497,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"); @@ -725,13 +511,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); @@ -815,27 +601,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) @@ -934,67 +721,6 @@ int CmdBitsamples(const char *Cmd) return 0; } -/* - * Convert to a bitstream - */ -int CmdBitstream(const char *Cmd) -{ - int i, j; - int bit; - int gtl; - int clock; - int low = 0; - int high = 0; - int hithigh, hitlow, first; - - /* Detect high and lows and clock */ - for (i = 0; i < GraphTraceLen; ++i) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* Get our clock */ - clock = GetAskClock(Cmd, high, 1); - gtl = ClearGraph(0); - - bit = 0; - for (i = 0; i < (int)(gtl / clock); ++i) - { - hithigh = 0; - hitlow = 0; - first = 1; - /* Find out if we hit both high and low peaks */ - for (j = 0; j < clock; ++j) - { - if (GraphBuffer[(i * clock) + j] == high) - hithigh = 1; - else if (GraphBuffer[(i * clock) + j] == low) - hitlow = 1; - /* it doesn't count if it's the first part of our read - because it's really just trailing from the last sequence */ - if (first && (hithigh || hitlow)) - hithigh = hitlow = 0; - else - first = 0; - - if (hithigh && hitlow) - break; - } - - /* If we didn't hit both high and low peaks, we had a bit transition */ - if (!hithigh || !hitlow) - bit ^= 1; - - AppendGraph(0, clock, bit); - } - - RepaintGraphWindow(); - return 0; -} - int CmdBuffClear(const char *Cmd) { UsbCommand c = {CMD_BUFF_CLEAR}; @@ -1073,30 +799,20 @@ int CmdGraphShiftZero(const char *Cmd) //by marshmellow //use large jumps in read samples to identify edges of waves and then amplify that wave to max -//similar to dirtheshold, threshold, and askdemod commands +//similar to dirtheshold, threshold commands //takes a threshold length which is the measured length between two samples then determines an edge 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; } @@ -1106,9 +822,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"); @@ -1118,7 +835,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'){ @@ -1131,6 +848,25 @@ int CmdDetectClockRate(const char *Cmd) return ans; } +char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) +{ + char *fskType; + if (fchigh==10 && fclow==8){ + if (invert) //fsk2a + fskType = "FSK2a"; + else //fsk2 + fskType = "FSK2"; + } else if (fchigh == 8 && fclow == 5) { + if (invert) + fskType = "FSK1"; + else + fskType = "FSK1a"; + } else { + fskType = "FSK??"; + } + return fskType; +} + //by marshmellow //fsk raw demod and print binary //takes 4 arguments - Clock, invert, fchigh, fclow @@ -1174,21 +910,20 @@ int FSKrawDemod(const char *Cmd, bool verbose) rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow); if (rfLen == 0) rfLen = 50; } - if (verbose) PrintAndLog("Args invert: %d - Clock:%d - fchigh:%d - fclow: %d",invert,rfLen,fchigh, fclow); int size = fskdemod(BitStream,BitLen,(uint8_t)rfLen,(uint8_t)invert,(uint8_t)fchigh,(uint8_t)fclow); if (size>0){ setDemodBuf(BitStream,size,0); // Now output the bitstream to the scrollback by line of 16 bits - if(size > (8*32)+2) size = (8*32)+2; //only output a max of 8 blocks of 32 bits most tags will have full bit stream inside that sample size - if (verbose) { - PrintAndLog("FSK decoded bitstream:"); - printBitStream(BitStream,size); + if (verbose || g_debugMode) { + PrintAndLog("\nUsing Clock:%d, invert:%d, fchigh:%d, fclow:%d", rfLen, invert, fchigh, fclow); + PrintAndLog("%s decoded bitstream:",GetFSKType(fchigh,fclow,invert)); + printDemodBuff(); } return 1; } else{ - if (verbose) PrintAndLog("no FSK data found"); + if (g_debugMode) PrintAndLog("no FSK data found"); } return 0; } @@ -1392,9 +1127,9 @@ int CmdFSKdemodIO(const char *Cmd) return 0; } if (idx==0){ - if (g_debugMode==1){ + if (g_debugMode){ PrintAndLog("DEBUG: IO Prox Data not found - FSK Bits: %d",BitLen); - if (BitLen > 92) printBitStream(BitStream,92); + if (BitLen > 92) PrintAndLog("%s", sprint_bin_break(BitStream,92,16)); } return 0; } @@ -1408,7 +1143,7 @@ int CmdFSKdemodIO(const char *Cmd) //XSF(version)facility:codeone+codetwo (raw) //Handle the data if (idx+64>BitLen) { - if (g_debugMode==1) PrintAndLog("not enough bits found - bitlen: %d",BitLen); + if (g_debugMode) PrintAndLog("not enough bits found - bitlen: %d",BitLen); return 0; } PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx], BitStream[idx+1], BitStream[idx+2], BitStream[idx+3], BitStream[idx+4], BitStream[idx+5], BitStream[idx+6], BitStream[idx+7], BitStream[idx+8]); @@ -1429,7 +1164,6 @@ int CmdFSKdemodIO(const char *Cmd) for (uint8_t i=1; i<6; ++i){ calccrc += bytebits_to_byte(BitStream+idx+9*i,8); - //PrintAndLog("%d", calccrc); } calccrc &= 0xff; calccrc = 0xff - calccrc; @@ -1687,124 +1421,6 @@ int CmdFSKdemodPyramid(const char *Cmd) return 1; } -int CmdFSKdemod(const char *Cmd) //old CmdFSKdemod needs updating -{ - static const int LowTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 - }; - static const int HighTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, -1, - }; - - int lowLen = sizeof (LowTone) / sizeof (int); - int highLen = sizeof (HighTone) / sizeof (int); - int convLen = (highLen > lowLen) ? highLen : lowLen; - uint32_t hi = 0, lo = 0; - - int i, j; - int minMark = 0, maxMark = 0; - - for (i = 0; i < GraphTraceLen - convLen; ++i) { - int lowSum = 0, highSum = 0; - - for (j = 0; j < lowLen; ++j) { - lowSum += LowTone[j]*GraphBuffer[i+j]; - } - for (j = 0; j < highLen; ++j) { - highSum += HighTone[j] * GraphBuffer[i + j]; - } - lowSum = abs(100 * lowSum / lowLen); - highSum = abs(100 * highSum / highLen); - GraphBuffer[i] = (highSum << 16) | lowSum; - } - - for(i = 0; i < GraphTraceLen - convLen - 16; ++i) { - int lowTot = 0, highTot = 0; - // 10 and 8 are f_s divided by f_l and f_h, rounded - for (j = 0; j < 10; ++j) { - lowTot += (GraphBuffer[i+j] & 0xffff); - } - for (j = 0; j < 8; j++) { - highTot += (GraphBuffer[i + j] >> 16); - } - GraphBuffer[i] = lowTot - highTot; - if (GraphBuffer[i] > maxMark) maxMark = GraphBuffer[i]; - if (GraphBuffer[i] < minMark) minMark = GraphBuffer[i]; - } - - GraphTraceLen -= (convLen + 16); - RepaintGraphWindow(); - - // Find bit-sync (3 lo followed by 3 high) (HID ONLY) - int max = 0, maxPos = 0; - for (i = 0; i < 6000; ++i) { - int dec = 0; - for (j = 0; j < 3 * lowLen; ++j) { - dec -= GraphBuffer[i + j]; - } - for (; j < 3 * (lowLen + highLen ); ++j) { - dec += GraphBuffer[i + j]; - } - if (dec > max) { - max = dec; - maxPos = i; - } - } - - // place start of bit sync marker in graph - GraphBuffer[maxPos] = maxMark; - GraphBuffer[maxPos + 1] = minMark; - - maxPos += j; - - // place end of bit sync marker in graph - GraphBuffer[maxPos] = maxMark; - GraphBuffer[maxPos+1] = minMark; - - PrintAndLog("actual data bits start at sample %d", maxPos); - PrintAndLog("length %d/%d", highLen, lowLen); - - uint8_t bits[46] = {0x00}; - - // find bit pairs and manchester decode them - for (i = 0; i < arraylen(bits) - 1; ++i) { - int dec = 0; - for (j = 0; j < lowLen; ++j) { - dec -= GraphBuffer[maxPos + j]; - } - for (; j < lowLen + highLen; ++j) { - dec += GraphBuffer[maxPos + j]; - } - maxPos += j; - // place inter bit marker in graph - GraphBuffer[maxPos] = maxMark; - GraphBuffer[maxPos + 1] = minMark; - - // hi and lo form a 64 bit pair - hi = (hi << 1) | (lo >> 31); - lo = (lo << 1); - // store decoded bit as binary (in hi/lo) and text (in bits[]) - if(dec < 0) { - bits[i] = '1'; - lo |= 1; - } else { - bits[i] = '0'; - } - } - PrintAndLog("bits: '%s'", bits); - PrintAndLog("hex: %08x %08x", hi, lo); - return 0; -} - //by marshmellow //attempt to psk1 demod graph buffer int PSKDemod(const char *Cmd, bool verbose) @@ -1832,17 +1448,17 @@ int PSKDemod(const char *Cmd, bool verbose) int errCnt=0; errCnt = pskRawDemod(BitStream, &BitLen, &clk, &invert); if (errCnt > maxErr){ - if (g_debugMode==1 && verbose) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); + if (g_debugMode || verbose) PrintAndLog("Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); return 0; } if (errCnt<0|| BitLen<16){ //throw away static - allow 1 and -1 (in case of threshold command first) - if (g_debugMode==1 && verbose) PrintAndLog("no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); + if (g_debugMode || verbose) PrintAndLog("no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); return 0; } - if (verbose){ - PrintAndLog("Tried PSK Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen); + if (verbose || g_debugMode){ + PrintAndLog("\nUsing Clock:%d, invert:%d, Bits Found:%d",clk,invert,BitLen); if (errCnt>0){ - PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt); + PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); } } //prime demod buffer for output @@ -1931,11 +1547,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; idx0 && (verbose || g_debugMode)) PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt); + if (errCnt>0 && (verbose || g_debugMode)) PrintAndLog("# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); if (verbose || g_debugMode) { PrintAndLog("NRZ demoded bitstream:"); // Now output the bitstream to the scrollback by line of 16 bits @@ -2023,7 +1677,7 @@ int CmdPSK1rawDemod(const char *Cmd) return 0; } - PrintAndLog("PSK demoded bitstream:"); + PrintAndLog("PSK1 demoded bitstream:"); // Now output the bitstream to the scrollback by line of 16 bits printDemodBuff(); return 1; @@ -2065,7 +1719,7 @@ int CmdRawDemod(const char *Cmd) { char cmdp = Cmd[0]; //param_getchar(Cmd, 0); - if (strlen(Cmd) > 14 || cmdp == 'h' || cmdp == 'H' || strlen(Cmd)<2) { + if (strlen(Cmd) > 20 || cmdp == 'h' || cmdp == 'H' || strlen(Cmd)<2) { PrintAndLog("Usage: data rawdemod [modulation] |"); PrintAndLog(" [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); PrintAndLog(" 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); @@ -2292,10 +1946,10 @@ int CmdTuneSamples(const char *Cmd) PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); -#define LF_UNUSABLE_V 2948 // was 2000. Changed due to bugfix in voltage measurements. LF results are now 47% higher. -#define LF_MARGINAL_V 14739 // was 10000. Changed due to bugfix bug in voltage measurements. LF results are now 47% higher. -#define HF_UNUSABLE_V 3167 // was 2000. Changed due to bugfix in voltage measurements. HF results are now 58% higher. -#define HF_MARGINAL_V 7917 // was 5000. Changed due to bugfix in voltage measurements. HF results are now 58% higher. + #define LF_UNUSABLE_V 2948 // was 2000. Changed due to bugfix in voltage measurements. LF results are now 47% higher. + #define LF_MARGINAL_V 14739 // was 10000. Changed due to bugfix bug in voltage measurements. LF results are now 47% higher. + #define HF_UNUSABLE_V 3167 // was 2000. Changed due to bugfix in voltage measurements. HF results are now 58% higher. + #define HF_MARGINAL_V 7917 // was 5000. Changed due to bugfix in voltage measurements. HF results are now 58% higher. if (peakv < LF_UNUSABLE_V) PrintAndLog("# Your LF antenna is unusable."); @@ -2351,7 +2005,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; @@ -2371,245 +2025,6 @@ int CmdRtrim(const char *Cmd) return 0; } -/* - * Manchester demodulate a bitstream. The bitstream needs to be already in - * the GraphBuffer as 0 and 1 values - * - * Give the clock rate as argument in order to help the sync - the algorithm - * resyncs at each pulse anyway. - * - * Not optimized by any means, this is the 1st time I'm writing this type of - * routine, feel free to improve... - * - * 1st argument: clock rate (as number of samples per clock rate) - * Typical values can be 64, 32, 128... - */ -int CmdManchesterDemod(const char *Cmd) -{ - int i, j, invert= 0; - int bit; - int clock; - int lastval = 0; - int low = 0; - int high = 0; - int hithigh, hitlow, first; - int lc = 0; - int bitidx = 0; - int bit2idx = 0; - int warnings = 0; - - /* check if we're inverting output */ - if (*Cmd == 'i') - { - PrintAndLog("Inverting output"); - invert = 1; - ++Cmd; - do - ++Cmd; - while(*Cmd == ' '); // in case a 2nd argument was given - } - - /* Holds the decoded bitstream: each clock period contains 2 bits */ - /* later simplified to 1 bit after manchester decoding. */ - /* Add 10 bits to allow for noisy / uncertain traces without aborting */ - /* int BitStream[GraphTraceLen*2/clock+10]; */ - - /* But it does not work if compiling on WIndows: therefore we just allocate a */ - /* large array */ - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; - - /* Detect high and lows */ - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* Get our clock */ - clock = GetAskClock(Cmd, high, 1); - - int tolerance = clock/4; - - /* Detect first transition */ - /* Lo-Hi (arbitrary) */ - /* skip to the first high */ - for (i= 0; i < GraphTraceLen; i++) - if (GraphBuffer[i] == high) - break; - /* now look for the first low */ - for (; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] == low) - { - lastval = i; - break; - } - } - - /* If we're not working with 1/0s, demod based off clock */ - if (high != 1) - { - bit = 0; /* We assume the 1st bit is zero, it may not be - * the case: this routine (I think) has an init problem. - * Ed. - */ - for (; i < (int)(GraphTraceLen / clock); i++) - { - hithigh = 0; - hitlow = 0; - first = 1; - - /* Find out if we hit both high and low peaks */ - for (j = 0; j < clock; j++) - { - if (GraphBuffer[(i * clock) + j] == high) - hithigh = 1; - else if (GraphBuffer[(i * clock) + j] == low) - hitlow = 1; - - /* it doesn't count if it's the first part of our read - because it's really just trailing from the last sequence */ - if (first && (hithigh || hitlow)) - hithigh = hitlow = 0; - else - first = 0; - - if (hithigh && hitlow) - break; - } - - /* If we didn't hit both high and low peaks, we had a bit transition */ - if (!hithigh || !hitlow) - bit ^= 1; - - BitStream[bit2idx++] = bit ^ invert; - } - } - - /* standard 1/0 bitstream */ - else - { - - /* Then detect duration between 2 successive transitions */ - for (bitidx = 1; i < GraphTraceLen; i++) - { - if (GraphBuffer[i-1] != GraphBuffer[i]) - { - lc = i-lastval; - lastval = i; - - // Error check: if bitidx becomes too large, we do not - // have a Manchester encoded bitstream or the clock is really - // wrong! - if (bitidx > (GraphTraceLen*2/clock+8) ) { - PrintAndLog("Error: the clock you gave is probably wrong, aborting."); - return 0; - } - // Then switch depending on lc length: - // Tolerance is 1/4 of clock rate (arbitrary) - if (abs(lc-clock/2) < tolerance) { - // Short pulse : either "1" or "0" - BitStream[bitidx++]=GraphBuffer[i-1]; - } else if (abs(lc-clock) < tolerance) { - // Long pulse: either "11" or "00" - BitStream[bitidx++]=GraphBuffer[i-1]; - BitStream[bitidx++]=GraphBuffer[i-1]; - } else { - // Error - warnings++; - PrintAndLog("Warning: Manchester decode error for pulse width detection."); - PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); - - if (warnings > 10) - { - PrintAndLog("Error: too many detection errors, aborting."); - return 0; - } - } - } - } - - // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream - // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful - // to stop output at the final bitidx2 value, not bitidx - for (i = 0; i < bitidx; i += 2) { - if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) { - BitStream[bit2idx++] = 1 ^ invert; - } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) { - BitStream[bit2idx++] = 0 ^ invert; - } else { - // We cannot end up in this state, this means we are unsynchronized, - // move up 1 bit: - i++; - warnings++; - PrintAndLog("Unsynchronized, resync..."); - PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)"); - - if (warnings > 10) - { - PrintAndLog("Error: too many decode errors, aborting."); - return 0; - } - } - } - } - - PrintAndLog("Manchester decoded bitstream"); - // Now output the bitstream to the scrollback by line of 16 bits - for (i = 0; i < (bit2idx-16); i+=16) { - PrintAndLog("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", - BitStream[i], - BitStream[i+1], - BitStream[i+2], - BitStream[i+3], - BitStream[i+4], - BitStream[i+5], - BitStream[i+6], - BitStream[i+7], - BitStream[i+8], - BitStream[i+9], - BitStream[i+10], - BitStream[i+11], - BitStream[i+12], - BitStream[i+13], - BitStream[i+14], - BitStream[i+15]); - } - return 0; -} - -/* Modulate our data into manchester */ -int CmdManchesterMod(const char *Cmd) -{ - int i, j; - int clock; - int bit, lastbit, wave; - - /* Get our clock */ - clock = GetAskClock(Cmd, 0, 1); - - wave = 0; - lastbit = 1; - for (i = 0; i < (int)(GraphTraceLen / clock); i++) - { - bit = GraphBuffer[i * clock] ^ 1; - - for (j = 0; j < (int)(clock/2); j++) - GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave; - for (j = (int)(clock/2); j < clock; j++) - GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1; - - /* Keep track of how we start our wave and if we changed or not this time */ - wave ^= bit ^ lastbit; - lastbit = bit; - } - - RepaintGraphWindow(); - return 0; -} - int CmdNorm(const char *Cmd) { int i; @@ -2674,20 +2089,6 @@ int CmdScale(const char *Cmd) return 0; } -int CmdThreshold(const char *Cmd) -{ - int threshold = atoi(Cmd); - - for (int i = 0; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] >= threshold) - GraphBuffer[i] = 1; - else - GraphBuffer[i] = -1; - } - RepaintGraphWindow(); - return 0; -} - int CmdDirectionalThreshold(const char *Cmd) { int8_t upThres = param_get8(Cmd, 0); @@ -2755,19 +2156,15 @@ int CmdZerocrossings(const char *Cmd) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"amp", CmdAmp, 1, "Amplify peaks"}, - //{"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"}, - {"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)"}, {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, - //{"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"}, {"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)"}, - //{"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"}, {"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"}, @@ -2782,20 +2179,18 @@ static command_t CommandTable[] = {"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"}, - //{"mandemod", CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, - {"manrawdecode", Cmdmandecoderaw, 1, "Manchester decode binary stream in DemodBuffer"}, - {"manmod", CmdManchesterMod, 1, "[clock rate] -- Manchester modulate a binary stream"}, + {"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"}, {"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)"}, {"scale", CmdScale, 1, " -- Set cursor display scale"}, {"setdebugmode", CmdSetDebugMode, 1, "<0|1> -- Turn on or off Debugging Mode for demods"}, {"shiftgraphzero", CmdGraphShiftZero, 1, " -- Shift 0 for Graphed wave + or - shift value"}, - //{"threshold", CmdThreshold, 1, " -- Maximize/minimize every value in the graph window depending on threshold"}, {"dirthreshold", CmdDirectionalThreshold, 1, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"}, {"undec", CmdUndec, 1, "Un-decimate samples by 2"}, diff --git a/client/cmddata.h b/client/cmddata.h index f6b4b950..57f04001 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -15,10 +15,7 @@ command_t * CmdDataCommands(); int CmdData(const char *Cmd); void printDemodBuff(void); -void printBitStream(uint8_t BitStream[], uint32_t bitLen); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); -int CmdAmp(const char *Cmd); -int Cmdaskdemod(const char *Cmd); int CmdAskEM410xDemod(const char *Cmd); int CmdG_Prox_II_Demod(const char *Cmd); int Cmdaskrawdemod(const char *Cmd); @@ -27,12 +24,10 @@ int AutoCorrelate(int window, bool SaveGrph, bool verbose); int CmdAutoCorr(const char *Cmd); int CmdBiphaseDecodeRaw(const char *Cmd); int CmdBitsamples(const char *Cmd); -int CmdBitstream(const char *Cmd); int CmdBuffClear(const char *Cmd); int CmdDec(const char *Cmd); int CmdDetectClockRate(const char *Cmd); int CmdFSKdemodAWID(const char *Cmd); -int CmdFSKdemod(const char *Cmd); int CmdFSKdemodHID(const char *Cmd); int CmdFSKdemodIO(const char *Cmd); int CmdFSKdemodParadox(const char *Cmd); @@ -40,6 +35,7 @@ int CmdFSKdemodPyramid(const char *Cmd); int CmdFSKrawdemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd); +int CmdPSKNexWatch(const char *Cmd); int CmdGrid(const char *Cmd); int CmdGetBitStream(const char *Cmd); int CmdHexsamples(const char *Cmd); @@ -49,24 +45,22 @@ int CmdLoad(const char *Cmd); int CmdLtrim(const char *Cmd); int CmdRtrim(const char *Cmd); int Cmdmandecoderaw(const char *Cmd); -int CmdManchesterDemod(const char *Cmd); -int CmdManchesterMod(const char *Cmd); int CmdNorm(const char *Cmd); int CmdNRZrawDemod(const char *Cmd); int CmdPlot(const char *Cmd); +int CmdPrintDemodBuff(const char *Cmd); int CmdRawDemod(const char *Cmd); int CmdSamples(const char *Cmd); int CmdTuneSamples(const char *Cmd); int CmdSave(const char *Cmd); int CmdScale(const char *Cmd); -int CmdThreshold(const char *Cmd); int CmdDirectionalThreshold(const char *Cmd); int CmdZerocrossings(const char *Cmd); int CmdIndalaDecode(const char *Cmd); -int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo); +int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ); +int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose); int ASKbiphaseDemod(const char *Cmd, bool verbose); -int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch); -int ASKrawDemod(const char *Cmd, bool verbose); +int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType); int FSKrawDemod(const char *Cmd, bool verbose); int PSKDemod(const char *Cmd, bool verbose); int NRZrawDemod(const char *Cmd, bool verbose); @@ -77,7 +71,7 @@ int getSamples(const char *Cmd, bool silent); #define MAX_DEMOD_BUF_LEN (1024*128) extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; extern int DemodBufferLen; - +extern uint8_t g_debugMode; #define BIGBUF_SIZE 40000 #endif diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 5f2e8dec..b96c9c1a 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1499,16 +1499,16 @@ int CmdHF14AMfCSetUID(const char *Cmd) int CmdHF14AMfCSetBlk(const char *Cmd) { - uint8_t uid[8] = {0x00}; uint8_t memBlock[16] = {0x00}; uint8_t blockNo = 0; + bool wipeCard = FALSE; int res; if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { - PrintAndLog("Usage: hf mf csetblk "); + PrintAndLog("Usage: hf mf csetblk [w]"); PrintAndLog("sample: hf mf csetblk 1 01020304050607080910111213141516"); - PrintAndLog("Set block data for magic Chinese card (only works with!!!)"); - PrintAndLog("If you want wipe card then add 'w' into command line. \n"); + PrintAndLog("Set block data for magic Chinese card (only works with such cards)"); + PrintAndLog("If you also want wipe the card then add 'w' at the end of the command line"); return 0; } @@ -1519,14 +1519,15 @@ int CmdHF14AMfCSetBlk(const char *Cmd) return 1; } + char ctmp = param_getchar(Cmd, 2); + wipeCard = (ctmp == 'w' || ctmp == 'W'); PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16)); - res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER); + res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER); if (res) { - PrintAndLog("Can't write block. error=%d", res); - return 1; - } - + PrintAndLog("Can't write block. error=%d", res); + return 1; + } return 0; } @@ -1637,7 +1638,7 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { PrintAndLog("Usage: hf mf cgetblk "); PrintAndLog("sample: hf mf cgetblk 1"); - PrintAndLog("Get block data from magic Chinese card (only works with!!!)\n"); + PrintAndLog("Get block data from magic Chinese card (only works with such cards)\n"); return 0; } @@ -1664,7 +1665,7 @@ int CmdHF14AMfCGetSc(const char *Cmd) { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { PrintAndLog("Usage: hf mf cgetsc "); PrintAndLog("sample: hf mf cgetsc 0"); - PrintAndLog("Get sector data from magic Chinese card (only works with!!!)\n"); + PrintAndLog("Get sector data from magic Chinese card (only works with such cards)\n"); return 0; } diff --git a/client/cmdlf.c b/client/cmdlf.c index 54f396fd..dfbbe992 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -522,7 +522,8 @@ static void ChkBitstream(const char *str) } } } -//appears to attempt to simulate manchester +//Attempt to simulate any wave in buffer (one bit per output sample) +// converts GraphBuffer to bitstream (based on zero crossings) if needed. int CmdLFSim(const char *Cmd) { int i,j; @@ -530,11 +531,11 @@ int CmdLFSim(const char *Cmd) sscanf(Cmd, "%i", &gap); - /* convert to bitstream if necessary */ + // convert to bitstream if necessary ChkBitstream(Cmd); - //can send 512 bits at a time (1 byte sent per bit...) + //can send only 512 bits at a time (1 byte sent per bit...) printf("Sending [%d bytes]", GraphTraceLen); for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) { UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}}; @@ -606,8 +607,8 @@ int usage_lf_simpsk(void) // - allow pull data from DemodBuffer int CmdLFfskSim(const char *Cmd) { - //might be able to autodetect FC and clock from Graphbuffer if using demod buffer - //will need FChigh, FClow, Clock, and bitstream + //might be able to autodetect FCs and clock from Graphbuffer if using demod buffer + // otherwise will need FChigh, FClow, Clock, and bitstream uint8_t fcHigh=0, fcLow=0, clk=0; uint8_t invert=0; bool errors = FALSE; @@ -682,6 +683,8 @@ int CmdLFfskSim(const char *Cmd) } else { setDemodBuf(data, dataLen, 0); } + + //default if not found if (clk == 0) clk = 50; if (fcHigh == 0) fcHigh = 10; if (fcLow == 0) fcLow = 8; @@ -706,9 +709,8 @@ int CmdLFfskSim(const char *Cmd) int CmdLFaskSim(const char *Cmd) { //autodetect clock from Graphbuffer if using demod buffer - //will need clock, invert, manchester/raw as m or r, separator as s, and bitstream + // needs clock, invert, manchester/raw as m or r, separator as s, and bitstream uint8_t encoding = 1, separator = 0; - //char cmdp = Cmd[0], par3='m', par4=0; uint8_t clk=0, invert=0; bool errors = FALSE; char hexData[32] = {0x00}; @@ -913,30 +915,6 @@ int CmdLFSimBidir(const char *Cmd) return 0; } -/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */ -/* -int CmdLFSimManchester(const char *Cmd) -{ - static int clock, gap; - static char data[1024], gapstring[8]; - - sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap); - - ClearGraph(0); - - for (int i = 0; i < strlen(data) ; ++i) - AppendGraph(0, clock, data[i]- '0'); - - CmdManchesterMod(""); - - RepaintGraphWindow(); - - sprintf(&gapstring[0], "%i", gap); - CmdLFSim(gapstring); - return 0; -} -*/ - int CmdVchDemod(const char *Cmd) { // Is this the entire sync pattern, or does this also include some @@ -1033,8 +1011,8 @@ int CmdLFfind(const char *Cmd) } if (!offline && (cmdp != '1')){ - ans=CmdLFRead(""); - ans=CmdSamples("20000"); + CmdLFRead("s"); + getSamples("30000",false); } else if (GraphTraceLen < 1000) { PrintAndLog("Data in Graphbuffer was too small."); return 0; @@ -1094,26 +1072,36 @@ int CmdLFfind(const char *Cmd) return 1; } + ans=EM4x50Read("", false); + if (ans>0) { + PrintAndLog("\nValid EM4x50 ID Found!"); + return 1; + } + + ans=CmdPSKNexWatch(""); + if (ans>0) { + PrintAndLog("\nValid NexWatch ID Found!"); + return 1; + } + PrintAndLog("\nNo Known Tags Found!\n"); if (testRaw=='u' || testRaw=='U'){ //test unknown tag formats (raw mode) PrintAndLog("\nChecking for Unknown tags:\n"); ans=AutoCorrelate(4000, FALSE, FALSE); if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans); - ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); // + ans=GetFskClock("",FALSE,FALSE); if (ans != 0){ //fsk - ans=FSKrawDemod("",FALSE); + ans=FSKrawDemod("",TRUE); if (ans>0) { PrintAndLog("\nUnknown FSK Modulated Tag Found!"); - printDemodBuff(); return 1; } } - ans=ASKmanDemod("",FALSE,FALSE); + ans=ASKDemod("0 0 0",TRUE,FALSE,1); if (ans>0) { PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!"); PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'"); - printDemodBuff(); return 1; } ans=CmdPSK1rawDemod(""); @@ -1121,7 +1109,6 @@ int CmdLFfind(const char *Cmd) PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'"); PrintAndLog("\nCould also be PSK3 - [currently not supported]"); PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod"); - printDemodBuff(); return 1; } PrintAndLog("\nNo Data Found!\n"); @@ -1147,7 +1134,6 @@ static command_t CommandTable[] = {"simfsk", CmdLFfskSim, 0, "[c ] [i] [H ] [L ] [d ] -- Simulate LF FSK tag from demodbuffer or input"}, {"simpsk", CmdLFpskSim, 0, "[1|2|3] [c ] [i] [r ] [d ] -- Simulate LF PSK tag from demodbuffer or input"}, {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, - //{"simman", CmdLFSimManchester, 0, " [GAP] Simulate arbitrary Manchester LF tag"}, {"snoop", CmdLFSnoop, 0, "['l'|'h'|] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"}, {"ti", CmdLFTI, 1, "{ TI RFIDs... }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"}, diff --git a/client/cmdlf.h b/client/cmdlf.h index 254d8807..7dd1b044 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -23,7 +23,6 @@ int CmdLFaskSim(const char *Cmd); int CmdLFfskSim(const char *Cmd); int CmdLFpskSim(const char *Cmd); int CmdLFSimBidir(const char *Cmd); -//int CmdLFSimManchester(const char *Cmd); int CmdLFSnoop(const char *Cmd); int CmdVchDemod(const char *Cmd); int CmdLFfind(const char *Cmd); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index b915aa5a..c492a64d 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -19,6 +19,7 @@ #include "cmddata.h" #include "cmdlf.h" #include "cmdlfem4x.h" +#include "lfdemod.h" char *global_em410xId; static int CmdHelp(const char *Cmd); @@ -26,11 +27,11 @@ static int CmdHelp(const char *Cmd); int CmdEMdemodASK(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); - int findone = (cmdp == '1') ? 1 : 0; - UsbCommand c={CMD_EM410X_DEMOD}; - c.arg[0]=findone; - SendCommand(&c); - return 0; + int findone = (cmdp == '1') ? 1 : 0; + UsbCommand c={CMD_EM410X_DEMOD}; + c.arg[0]=findone; + SendCommand(&c); + return 0; } /* Read the ID of an EM410x tag. @@ -43,21 +44,21 @@ int CmdEMdemodASK(const char *Cmd) */ int CmdEM410xRead(const char *Cmd) { - uint32_t hi=0; - uint64_t lo=0; - - if(!AskEm410xDemod("", &hi, &lo)) return 0; - PrintAndLog("EM410x pattern found: "); - printEM410x(hi, lo); - if (hi){ - PrintAndLog ("EM410x XL pattern found"); - return 0; - } - char id[12] = {0x00}; - sprintf(id, "%010llx",lo); - - global_em410xId = id; - return 1; + uint32_t hi=0; + uint64_t lo=0; + + if(!AskEm410xDemod("", &hi, &lo, false)) return 0; + PrintAndLog("EM410x pattern found: "); + printEM410x(hi, lo); + if (hi){ + PrintAndLog ("EM410x XL pattern found"); + return 0; + } + char id[12] = {0x00}; + sprintf(id, "%010llx",lo); + + global_em410xId = id; + return 1; } // emulate an EM410X tag @@ -83,52 +84,52 @@ int CmdEM410xSim(const char *Cmd) PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]); PrintAndLog("Press pm3-button to about simulation"); - /* clock is 64 in EM410x tags */ - int clock = 64; - - /* clear our graph */ - ClearGraph(0); - - /* write 9 start bits */ - for (i = 0; i < 9; i++) - AppendGraph(0, clock, 1); - - /* for each hex char */ - parity[0] = parity[1] = parity[2] = parity[3] = 0; - for (i = 0; i < 10; i++) - { - /* read each hex char */ - sscanf(&Cmd[i], "%1x", &n); - for (j = 3; j >= 0; j--, n/= 2) - binary[j] = n % 2; - - /* append each bit */ - AppendGraph(0, clock, binary[0]); - AppendGraph(0, clock, binary[1]); - AppendGraph(0, clock, binary[2]); - AppendGraph(0, clock, binary[3]); - - /* append parity bit */ - AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); - - /* keep track of column parity */ - parity[0] ^= binary[0]; - parity[1] ^= binary[1]; - parity[2] ^= binary[2]; - parity[3] ^= binary[3]; - } - - /* parity columns */ - AppendGraph(0, clock, parity[0]); - AppendGraph(0, clock, parity[1]); - AppendGraph(0, clock, parity[2]); - AppendGraph(0, clock, parity[3]); - - /* stop bit */ - AppendGraph(1, clock, 0); + /* clock is 64 in EM410x tags */ + int clock = 64; + + /* clear our graph */ + ClearGraph(0); + + /* write 9 start bits */ + for (i = 0; i < 9; i++) + AppendGraph(0, clock, 1); + + /* for each hex char */ + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++) + { + /* read each hex char */ + sscanf(&Cmd[i], "%1x", &n); + for (j = 3; j >= 0; j--, n/= 2) + binary[j] = n % 2; + + /* append each bit */ + AppendGraph(0, clock, binary[0]); + AppendGraph(0, clock, binary[1]); + AppendGraph(0, clock, binary[2]); + AppendGraph(0, clock, binary[3]); + + /* append parity bit */ + AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + + /* keep track of column parity */ + parity[0] ^= binary[0]; + parity[1] ^= binary[1]; + parity[2] ^= binary[2]; + parity[3] ^= binary[3]; + } + + /* parity columns */ + AppendGraph(0, clock, parity[0]); + AppendGraph(0, clock, parity[1]); + AppendGraph(0, clock, parity[2]); + AppendGraph(0, clock, parity[3]); + + /* stop bit */ + AppendGraph(1, clock, 0); - CmdLFSim("0"); //240 start_gap. - return 0; + CmdLFSim("0"); //240 start_gap. + return 0; } /* Function is equivalent of lf read + data samples + em410xread @@ -139,7 +140,6 @@ int CmdEM410xSim(const char *Cmd) * rate gets lower, then grow the number of samples * Changed by martin, 4000 x 4 = 16000, * see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235 - */ int CmdEM410xWatch(const char *Cmd) { @@ -150,12 +150,13 @@ int CmdEM410xWatch(const char *Cmd) } CmdLFRead("s"); - getSamples("8192",true); //capture enough to get 2 full messages + getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9) } while (!CmdEM410xRead("")); return 0; } +//currently only supports manchester modulations int CmdEM410xWatchnSpoof(const char *Cmd) { CmdEM410xWatch(Cmd); @@ -164,154 +165,10 @@ int CmdEM410xWatchnSpoof(const char *Cmd) return 0; } -/* Read the transmitted data of an EM4x50 tag - * Format: - * - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * CCCCCCCC <- column parity bits - * 0 <- stop bit - * LW <- Listen Window - * - * This pattern repeats for every block of data being transmitted. - * Transmission starts with two Listen Windows (LW - a modulated - * pattern of 320 cycles each (32/32/128/64/64)). - * - * Note that this data may or may not be the UID. It is whatever data - * is stored in the blocks defined in the control word First and Last - * Word Read values. UID is stored in block 32. - */ -int CmdEM4x50Read(const char *Cmd) -{ - int i, j, startblock, skip, block, start, end, low, high; - bool complete= false; - int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; - char tmp[6]; - - high= low= 0; - memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64); - - /* first get high and low values */ - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* populate a buffer with pulse lengths */ - i= 0; - j= 0; - while (i < GraphTraceLen) - { - // measure from low to low - while ((GraphBuffer[i] > low) && (i low) && (i=(MAX_GRAPH_TRACE_LEN/64)) { - break; - } - tmpbuff[j++]= i - start; - } - - /* look for data start - should be 2 pairs of LW (pulses of 192,128) */ - start= -1; - skip= 0; - for (i= 0; i < j - 4 ; ++i) - { - skip += tmpbuff[i]; - if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) - if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) - if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) - if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) - { - start= i + 3; - break; - } - } - startblock= i + 3; - - /* skip over the remainder of the LW */ - skip += tmpbuff[i+1]+tmpbuff[i+2]; - while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low) - ++skip; - skip += 8; - - /* now do it again to find the end */ - end= start; - for (i += 3; i < j - 4 ; ++i) - { - end += tmpbuff[i]; - if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) - if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) - if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) - if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) - { - complete= true; - break; - } - } - - if (start >= 0) - PrintAndLog("Found data at sample: %i",skip); - else - { - PrintAndLog("No data found!"); - PrintAndLog("Try again with more samples."); - return 0; - } - - if (!complete) - { - PrintAndLog("*** Warning!"); - PrintAndLog("Partial data - no end found!"); - PrintAndLog("Try again with more samples."); - } - - /* get rid of leading crap */ - sprintf(tmp,"%i",skip); - CmdLtrim(tmp); - - /* now work through remaining buffer printing out data blocks */ - block= 0; - i= startblock; - while (block < 6) - { - PrintAndLog("Block %i:", block); - // mandemod routine needs to be split so we can call it for data - // just print for now for debugging - CmdManchesterDemod("i 64"); - skip= 0; - /* look for LW before start of next block */ - for ( ; i < j - 4 ; ++i) - { - skip += tmpbuff[i]; - if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) - if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) - break; - } - while (GraphBuffer[skip] > low) - ++skip; - skip += 8; - sprintf(tmp,"%i",skip); - CmdLtrim(tmp); - start += skip; - block++; - } - return 0; -} - int CmdEM410xWrite(const char *Cmd) { - uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value - int card = 0xFF; // invalid card value + uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value + int card = 0xFF; // invalid card value unsigned int clock = 0; // invalid clock value sscanf(Cmd, "%" PRIx64 " %d %d", &id, &card, &clock); @@ -370,133 +227,404 @@ int CmdEM410xWrite(const char *Cmd) return 0; } - UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}}; - SendCommand(&c); + UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}}; + SendCommand(&c); + + return 0; +} - return 0; +bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) +{ + if (rows*cols>size) return false; + uint8_t colP=0; + //assume last col is a parity and do not test + for (uint8_t colNum = 0; colNum < cols-1; colNum++) { + for (uint8_t rowNum = 0; rowNum < rows; rowNum++) { + colP ^= BitStream[(rowNum*cols)+colNum]; + } + if (colP != pType) return false; + } + return true; +} + +bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) +{ + if (rows*cols>size) return false; + uint8_t rowP=0; + //assume last row is a parity row and do not test + for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) { + for (uint8_t colNum = 0; colNum < cols; colNum++) { + rowP ^= BitStream[(rowNum*cols)+colNum]; + } + if (rowP != pType) return false; + } + return true; +} + +uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) +{ + if (size<45) return 0; + uint32_t code = bytebits_to_byte(BitStream,8); + code = code<<8 | bytebits_to_byte(BitStream+9,8); + code = code<<8 | bytebits_to_byte(BitStream+18,8); + code = code<<8 | bytebits_to_byte(BitStream+27,8); + if (verbose || g_debugMode){ + for (uint8_t i = 0; i<5; i++){ + if (i == 4) PrintAndLog(""); //parity byte spacer + PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x", + BitStream[i*9], + BitStream[i*9+1], + BitStream[i*9+2], + BitStream[i*9+3], + BitStream[i*9+4], + BitStream[i*9+5], + BitStream[i*9+6], + BitStream[i*9+7], + BitStream[i*9+8], + bytebits_to_byte(BitStream+i*9,8) + ); + } + if (pTest) + PrintAndLog("Parity Passed"); + else + PrintAndLog("Parity Failed"); + } + return code; +} +/* Read the transmitted data of an EM4x50 tag + * Format: + * + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * CCCCCCCC <- column parity bits + * 0 <- stop bit + * LW <- Listen Window + * + * This pattern repeats for every block of data being transmitted. + * Transmission starts with two Listen Windows (LW - a modulated + * pattern of 320 cycles each (32/32/128/64/64)). + * + * Note that this data may or may not be the UID. It is whatever data + * is stored in the blocks defined in the control word First and Last + * Word Read values. UID is stored in block 32. + */ + //completed by Marshmellow +int EM4x50Read(const char *Cmd, bool verbose) +{ + uint8_t fndClk[] = {8,16,32,40,50,64,128}; + int clk = 0; + int invert = 0; + int tol = 0; + int i, j, startblock, skip, block, start, end, low, high, minClk; + bool complete = false; + int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; + uint32_t Code[6]; + char tmp[6]; + char tmp2[20]; + int phaseoff; + high = low = 0; + memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64); + + // get user entry if any + sscanf(Cmd, "%i %i", &clk, &invert); + + // save GraphBuffer - to restore it later + save_restoreGB(1); + + // first get high and low values + for (i = 0; i < GraphTraceLen; i++) { + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; + } + + i = 0; + j = 0; + minClk = 255; + // get to first full low to prime loop and skip incomplete first pulse + while ((GraphBuffer[i] < high) && (i < GraphTraceLen)) + ++i; + while ((GraphBuffer[i] > low) && (i < GraphTraceLen)) + ++i; + skip = i; + + // populate tmpbuff buffer with pulse lengths + while (i < GraphTraceLen) { + // measure from low to low + while ((GraphBuffer[i] > low) && (i < GraphTraceLen)) + ++i; + start= i; + while ((GraphBuffer[i] < high) && (i < GraphTraceLen)) + ++i; + while ((GraphBuffer[i] > low) && (i < GraphTraceLen)) + ++i; + if (j>=(MAX_GRAPH_TRACE_LEN/64)) { + break; + } + tmpbuff[j++]= i - start; + if (i-start < minClk && i < GraphTraceLen) { + minClk = i - start; + } + } + // set clock + if (!clk) { + for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) { + tol = fndClk[clkCnt]/8; + if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) { + clk=fndClk[clkCnt]; + break; + } + } + if (!clk) return 0; + } else tol = clk/8; + + // look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2) + start = -1; + for (i= 0; i < j - 4 ; ++i) { + skip += tmpbuff[i]; + if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks + if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks + if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks + if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following + { + start= i + 4; + break; + } + } + startblock = i + 4; + + // skip over the remainder of LW + skip += tmpbuff[i+1] + tmpbuff[i+2] + clk; + if (tmpbuff[i+3]>clk) + phaseoff = tmpbuff[i+3]-clk; + else + phaseoff = 0; + // now do it again to find the end + end = skip; + for (i += 3; i < j - 4 ; ++i) { + end += tmpbuff[i]; + if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks + if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks + if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks + if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following + { + complete= true; + break; + } + } + end = i; + // report back + if (verbose || g_debugMode) { + if (start >= 0) { + PrintAndLog("\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)"); + } else { + PrintAndLog("No data found!, clock tried:%d",clk); + PrintAndLog("Try again with more samples."); + PrintAndLog(" or after a 'data askedge' command to clean up the read"); + return 0; + } + } else if (start < 0) return 0; + start = skip; + snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47); + // get rid of leading crap + snprintf(tmp, sizeof(tmp), "%i", skip); + CmdLtrim(tmp); + bool pTest; + bool AllPTest = true; + // now work through remaining buffer printing out data blocks + block = 0; + i = startblock; + while (block < 6) { + if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block); + skip = phaseoff; + + // look for LW before start of next block + for ( ; i < j - 4 ; ++i) { + skip += tmpbuff[i]; + if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) + if (tmpbuff[i+1] >= clk-tol) + break; + } + if (i >= j-4) break; //next LW not found + skip += clk; + if (tmpbuff[i+1]>clk) + phaseoff = tmpbuff[i+1]-clk; + else + phaseoff = 0; + i += 2; + if (ASKDemod(tmp2, false, false, 1) < 1) { + save_restoreGB(0); + return 0; + } + //set DemodBufferLen to just one block + DemodBufferLen = skip/clk; + //test parities + pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0); + pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0); + AllPTest &= pTest; + //get output + Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest); + if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d", skip, skip/clk); + //skip to start of next block + snprintf(tmp,sizeof(tmp),"%i",skip); + CmdLtrim(tmp); + block++; + if (i >= end) break; //in case chip doesn't output 6 blocks + } + //print full code: + if (verbose || g_debugMode || AllPTest){ + if (!complete) { + PrintAndLog("*** Warning!"); + PrintAndLog("Partial data - no end found!"); + PrintAndLog("Try again with more samples."); + } + PrintAndLog("Found data at sample: %i - using clock: %i", start, clk); + end = block; + for (block=0; block < end; block++){ + PrintAndLog("Block %d: %08x",block,Code[block]); + } + if (AllPTest) { + PrintAndLog("Parities Passed"); + } else { + PrintAndLog("Parities Failed"); + PrintAndLog("Try cleaning the read samples with 'data askedge'"); + } + } + + //restore GraphBuffer + save_restoreGB(0); + return (int)AllPTest; +} + +int CmdEM4x50Read(const char *Cmd) +{ + return EM4x50Read(Cmd, true); } int CmdReadWord(const char *Cmd) { int Word = -1; //default to invalid word - UsbCommand c; - - sscanf(Cmd, "%d", &Word); - + UsbCommand c; + + sscanf(Cmd, "%d", &Word); + if ( (Word > 15) | (Word < 0) ) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Reading word %d", Word); - - c.cmd = CMD_EM4X_READ_WORD; - c.d.asBytes[0] = 0x0; //Normal mode - c.arg[0] = 0; - c.arg[1] = Word; - c.arg[2] = 0; - SendCommand(&c); - return 0; + PrintAndLog("Word must be between 0 and 15"); + return 1; + } + + PrintAndLog("Reading word %d", Word); + + c.cmd = CMD_EM4X_READ_WORD; + c.d.asBytes[0] = 0x0; //Normal mode + c.arg[0] = 0; + c.arg[1] = Word; + c.arg[2] = 0; + SendCommand(&c); + return 0; } int CmdReadWordPWD(const char *Cmd) { int Word = -1; //default to invalid word - int Password = 0xFFFFFFFF; //default to blank password - UsbCommand c; - - sscanf(Cmd, "%d %x", &Word, &Password); - + int Password = 0xFFFFFFFF; //default to blank password + UsbCommand c; + + sscanf(Cmd, "%d %x", &Word, &Password); + if ( (Word > 15) | (Word < 0) ) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Reading word %d with password %08X", Word, Password); - - c.cmd = CMD_EM4X_READ_WORD; - c.d.asBytes[0] = 0x1; //Password mode - c.arg[0] = 0; - c.arg[1] = Word; - c.arg[2] = Password; - SendCommand(&c); - return 0; + PrintAndLog("Word must be between 0 and 15"); + return 1; + } + + PrintAndLog("Reading word %d with password %08X", Word, Password); + + c.cmd = CMD_EM4X_READ_WORD; + c.d.asBytes[0] = 0x1; //Password mode + c.arg[0] = 0; + c.arg[1] = Word; + c.arg[2] = Password; + SendCommand(&c); + return 0; } int CmdWriteWord(const char *Cmd) { - int Word = 16; //default to invalid block - int Data = 0xFFFFFFFF; //default to blank data - UsbCommand c; - - sscanf(Cmd, "%x %d", &Data, &Word); - - if (Word > 15) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Writing word %d with data %08X", Word, Data); - - c.cmd = CMD_EM4X_WRITE_WORD; - c.d.asBytes[0] = 0x0; //Normal mode - c.arg[0] = Data; - c.arg[1] = Word; - c.arg[2] = 0; - SendCommand(&c); - return 0; + int Word = 16; //default to invalid block + int Data = 0xFFFFFFFF; //default to blank data + UsbCommand c; + + sscanf(Cmd, "%x %d", &Data, &Word); + + if (Word > 15) { + PrintAndLog("Word must be between 0 and 15"); + return 1; + } + + PrintAndLog("Writing word %d with data %08X", Word, Data); + + c.cmd = CMD_EM4X_WRITE_WORD; + c.d.asBytes[0] = 0x0; //Normal mode + c.arg[0] = Data; + c.arg[1] = Word; + c.arg[2] = 0; + SendCommand(&c); + return 0; } int CmdWriteWordPWD(const char *Cmd) { - int Word = 16; //default to invalid word - int Data = 0xFFFFFFFF; //default to blank data - int Password = 0xFFFFFFFF; //default to blank password - UsbCommand c; - - sscanf(Cmd, "%x %d %x", &Data, &Word, &Password); - - if (Word > 15) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password); - - c.cmd = CMD_EM4X_WRITE_WORD; - c.d.asBytes[0] = 0x1; //Password mode - c.arg[0] = Data; - c.arg[1] = Word; - c.arg[2] = Password; - SendCommand(&c); - return 0; + int Word = 16; //default to invalid word + int Data = 0xFFFFFFFF; //default to blank data + int Password = 0xFFFFFFFF; //default to blank password + UsbCommand c; + + sscanf(Cmd, "%x %d %x", &Data, &Word, &Password); + + if (Word > 15) { + PrintAndLog("Word must be between 0 and 15"); + return 1; + } + + PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password); + + c.cmd = CMD_EM4X_WRITE_WORD; + c.d.asBytes[0] = 0x1; //Password mode + c.arg[0] = Data; + c.arg[1] = Word; + c.arg[2] = Password; + SendCommand(&c); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, - {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"}, - {"em410xsim", CmdEM410xSim, 0, " -- Simulate EM410x tag"}, - {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, - {"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, - {"em410xwrite", CmdEM410xWrite, 1, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, - {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, - {"readword", CmdReadWord, 1, " -- Read EM4xxx word data"}, - {"readwordPWD", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode"}, - {"writeword", CmdWriteWord, 1, " -- Write EM4xxx word data"}, - {"writewordPWD", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"}, + {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"}, + {"em410xsim", CmdEM410xSim, 0, " -- Simulate EM410x tag"}, + {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, + {"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, + {"em410xwrite", CmdEM410xWrite, 0, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, + {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, + {"readword", CmdReadWord, 1, " -- Read EM4xxx word data"}, + {"readwordPWD", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode"}, + {"writeword", CmdWriteWord, 1, " -- Write EM4xxx word data"}, + {"writewordPWD", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, + {NULL, NULL, 0, NULL} }; int CmdLFEM4X(const char *Cmd) { - CmdsParse(CommandTable, Cmd); - return 0; + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index baea50a4..400536d3 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -11,7 +11,6 @@ #ifndef CMDLFEM4X_H__ #define CMDLFEM4X_H__ -int CmdLFEM4X(const char *Cmd); int CmdEMdemodASK(const char *Cmd); int CmdEM410xRead(const char *Cmd); int CmdEM410xSim(const char *Cmd); @@ -19,9 +18,11 @@ int CmdEM410xWatch(const char *Cmd); int CmdEM410xWatchnSpoof(const char *Cmd); int CmdEM410xWrite(const char *Cmd); int CmdEM4x50Read(const char *Cmd); +int CmdLFEM4X(const char *Cmd); int CmdReadWord(const char *Cmd); int CmdReadWordPWD(const char *Cmd); int CmdWriteWord(const char *Cmd); int CmdWriteWordPWD(const char *Cmd); +int EM4x50Read(const char *Cmd, bool verbose); #endif diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index c6d54e78..4e103f1a 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -17,7 +17,7 @@ #include "cmdlfhid.h" static int CmdHelp(const char *Cmd); - +/* int CmdHIDDemod(const char *Cmd) { if (GraphTraceLen < 4800) { @@ -36,7 +36,7 @@ int CmdHIDDemod(const char *Cmd) RepaintGraphWindow(); return 0; } - +*/ int CmdHIDDemodFSK(const char *Cmd) { int findone=0; @@ -106,7 +106,7 @@ int CmdHIDClone(const char *Cmd) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"}, + //{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"}, {"fskdemod", CmdHIDDemodFSK, 0, "['1'] Realtime HID FSK demodulator (option '1' for one tag only)"}, {"sim", CmdHIDSim, 0, " -- HID tag simulator"}, {"clone", CmdHIDClone, 0, " ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"}, diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index 328f3b13..7021492b 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -12,9 +12,9 @@ #define CMDLFHID_H__ int CmdLFHID(const char *Cmd); - -int CmdHIDDemod(const char *Cmd); +//int CmdHIDDemod(const char *Cmd); int CmdHIDDemodFSK(const char *Cmd); int CmdHIDSim(const char *Cmd); +int CmdHIDClone(const char *Cmd); #endif diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 14ce5498..aa21c44b 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -24,7 +24,7 @@ int CmdIODemodFSK(const char *Cmd) SendCommand(&c); return 0; } - +/* int CmdIOProxDemod(const char *Cmd){ if (GraphTraceLen < 4800) { PrintAndLog("too short; need at least 4800 samples"); @@ -37,7 +37,7 @@ int CmdIOProxDemod(const char *Cmd){ RepaintGraphWindow(); return 0; } - +*/ int CmdIOClone(const char *Cmd) { unsigned int hi = 0, lo = 0; @@ -67,7 +67,7 @@ int CmdIOClone(const char *Cmd) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdIOProxDemod, 1, "Demodulate Stream"}, + //{"demod", CmdIOProxDemod, 1, "Demodulate Stream"}, {"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"}, {"clone", CmdIOClone, 0, "Clone ioProx Tag"}, {NULL, NULL, 0, NULL} @@ -83,4 +83,4 @@ int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; -} \ No newline at end of file +} diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index b6b29c05..d4b72b32 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "proxmark3.h" #include "ui.h" #include "graph.h" @@ -147,31 +148,37 @@ int CmdT55xxSetConfig(const char *Cmd) { param_getstr(Cmd, cmdp+1, modulation); cmdp += 2; - if ( strcmp(modulation, "FSK" ) == 0) + if ( strcmp(modulation, "FSK" ) == 0) { config.modulation = DEMOD_FSK; - else if ( strcmp(modulation, "FSK1" ) == 0) + } else if ( strcmp(modulation, "FSK1" ) == 0) { config.modulation = DEMOD_FSK1; - else if ( strcmp(modulation, "FSK1a" ) == 0) + config.inverted=1; + } else if ( strcmp(modulation, "FSK1a" ) == 0) { config.modulation = DEMOD_FSK1a; - else if ( strcmp(modulation, "FSK2" ) == 0) + config.inverted=0; + } else if ( strcmp(modulation, "FSK2" ) == 0) { config.modulation = DEMOD_FSK2; - else if ( strcmp(modulation, "FSK2a" ) == 0) + config.inverted=0; + } else if ( strcmp(modulation, "FSK2a" ) == 0) { config.modulation = DEMOD_FSK2a; - else if ( strcmp(modulation, "ASK" ) == 0) + config.inverted=1; + } else if ( strcmp(modulation, "ASK" ) == 0) { config.modulation = DEMOD_ASK; - else if ( strcmp(modulation, "NRZ" ) == 0) + } else if ( strcmp(modulation, "NRZ" ) == 0) { config.modulation = DEMOD_NRZ; - else if ( strcmp(modulation, "PSK1" ) == 0) + } else if ( strcmp(modulation, "PSK1" ) == 0) { config.modulation = DEMOD_PSK1; - else if ( strcmp(modulation, "PSK2" ) == 0) + } else if ( strcmp(modulation, "PSK2" ) == 0) { config.modulation = DEMOD_PSK2; - else if ( strcmp(modulation, "PSK3" ) == 0) + } else if ( strcmp(modulation, "PSK3" ) == 0) { config.modulation = DEMOD_PSK3; - else if ( strcmp(modulation, "BIa" ) == 0) + } else if ( strcmp(modulation, "BIa" ) == 0) { config.modulation = DEMOD_BIa; - else if ( strcmp(modulation, "BI" ) == 0) + config.inverted=1; + } else if ( strcmp(modulation, "BI" ) == 0) { config.modulation = DEMOD_BI; - else { + config.inverted=0; + } else { PrintAndLog("Unknown modulation '%s'", modulation); errors = TRUE; } @@ -255,77 +262,51 @@ int CmdT55xxReadBlock(const char *Cmd) { bool DecodeT55xxBlock(){ - char buf[8] = {0x00}; + char buf[30] = {0x00}; char *cmdStr = buf; int ans = 0; uint8_t bitRate[8] = {8,16,32,40,50,64,100,128}; - DemodBufferLen = 0x00; + //trim 1/2 a clock from beginning + snprintf(cmdStr, sizeof(buf),"%d", bitRate[config.bitrate]/2 ); + CmdLtrim(cmdStr); switch( config.modulation ){ case DEMOD_FSK: - //CmdLtrim("26"); - sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 ); - CmdLtrim(cmdStr); - sprintf(cmdStr,"%d %d", bitRate[config.bitrate], config.inverted ); + snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted ); ans = FSKrawDemod(cmdStr, FALSE); break; case DEMOD_FSK1: - //CmdLtrim("26"); - sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 ); - CmdLtrim(cmdStr); - sprintf(cmdStr,"%d 1 8 5", bitRate[config.bitrate] ); - ans = FSKrawDemod(cmdStr, FALSE); - break; case DEMOD_FSK1a: - //CmdLtrim("26"); - sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 ); - CmdLtrim(cmdStr); - sprintf(cmdStr,"%d 0 8 5", bitRate[config.bitrate] ); + snprintf(cmdStr, sizeof(buf),"%d %d 8 5", bitRate[config.bitrate], config.inverted ); ans = FSKrawDemod(cmdStr, FALSE); break; case DEMOD_FSK2: - //CmdLtrim("26"); - sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 ); - CmdLtrim(cmdStr); - sprintf(cmdStr,"%d 0 10 8", bitRate[config.bitrate] ); - ans = FSKrawDemod(cmdStr, FALSE); - break; case DEMOD_FSK2a: - //CmdLtrim("26"); - sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 ); - CmdLtrim(cmdStr); - sprintf(cmdStr,"%d 1 10 8", bitRate[config.bitrate] ); + snprintf(cmdStr, sizeof(buf),"%d %d 10 8", bitRate[config.bitrate], config.inverted ); ans = FSKrawDemod(cmdStr, FALSE); break; case DEMOD_ASK: - sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); - ans = ASKmanDemod(cmdStr, FALSE, FALSE); + snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted ); + ans = ASKDemod(cmdStr, FALSE, FALSE, 1); break; case DEMOD_PSK1: - sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); + snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted ); ans = PSKDemod(cmdStr, FALSE); break; - case DEMOD_PSK2: - sprintf(cmdStr,"%d 1", bitRate[config.bitrate] ); - ans = PSKDemod(cmdStr, FALSE); - psk1TOpsk2(DemodBuffer, DemodBufferLen); - break; - case DEMOD_PSK3: - sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); + case DEMOD_PSK2: //inverted won't affect this + case DEMOD_PSK3: //not fully implemented + snprintf(cmdStr, sizeof(buf),"%d 0 1", bitRate[config.bitrate] ); ans = PSKDemod(cmdStr, FALSE); psk1TOpsk2(DemodBuffer, DemodBufferLen); break; case DEMOD_NRZ: - sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted ); + snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted ); ans = NRZrawDemod(cmdStr, FALSE); break; case DEMOD_BI: - sprintf(cmdStr,"0 %d 0 1", bitRate[config.bitrate] ); - ans = ASKbiphaseDemod(cmdStr, FALSE); - break; case DEMOD_BIa: - sprintf(cmdStr,"0 %d 1 1", bitRate[config.bitrate] ); + snprintf(cmdStr, sizeof(buf),"0 %d %d 0", bitRate[config.bitrate], config.inverted ); ans = ASKbiphaseDemod(cmdStr, FALSE); break; default: @@ -354,114 +335,141 @@ bool tryDetectModulation(){ char cmdStr[8] = {0}; uint8_t hits = 0; t55xx_conf_block_t tests[15]; - + int bitRate=0; + uint8_t fc1 = 0, fc2 = 0, clk=0; + save_restoreGB(1); if (GetFskClock("", FALSE, FALSE)){ - uint8_t fc1 = 0, fc2 = 0, clk=0; fskClocks(&fc1, &fc2, &clk, FALSE); sprintf(cmdStr,"%d", clk/2); CmdLtrim(cmdStr); - if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset)){ + if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)){ tests[hits].modulation = DEMOD_FSK; if (fc1==8 && fc2 == 5) tests[hits].modulation = DEMOD_FSK1a; else if (fc1==10 && fc2 == 8) tests[hits].modulation = DEMOD_FSK2; - + tests[hits].bitrate = bitRate; tests[hits].inverted = FALSE; tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); ++hits; } - if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset)) { + if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)) { tests[hits].modulation = DEMOD_FSK; - if (fc1==8 && fc2 == 5) + if (fc1 == 8 && fc2 == 5) tests[hits].modulation = DEMOD_FSK1; - else if (fc1==10 && fc2 == 8) + else if (fc1 == 10 && fc2 == 8) tests[hits].modulation = DEMOD_FSK2a; + tests[hits].bitrate = bitRate; tests[hits].inverted = TRUE; tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); ++hits; } } else { - if ( ASKmanDemod("0 0 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) { - tests[hits].modulation = DEMOD_ASK; - tests[hits].inverted = FALSE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; + clk = GetAskClock("", FALSE, FALSE); + if (clk>0) { + sprintf(cmdStr,"%d", clk/2); + CmdLtrim(cmdStr); + if ( ASKDemod("0 0 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) { + tests[hits].modulation = DEMOD_ASK; + tests[hits].bitrate = bitRate; + tests[hits].inverted = FALSE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; } - - if ( ASKmanDemod("0 1 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) { - tests[hits].modulation = DEMOD_ASK; - tests[hits].inverted = TRUE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; + if ( ASKDemod("0 1 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) { + tests[hits].modulation = DEMOD_ASK; + tests[hits].bitrate = bitRate; + tests[hits].inverted = TRUE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } + if ( ASKbiphaseDemod("0 0 0 0", FALSE) && test(DEMOD_BI, &tests[hits].offset, &bitRate) ) { + tests[hits].modulation = DEMOD_BI; + tests[hits].bitrate = bitRate; + tests[hits].inverted = FALSE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } + if ( ASKbiphaseDemod("0 0 1 0", FALSE) && test(DEMOD_BIa, &tests[hits].offset, &bitRate) ) { + tests[hits].modulation = DEMOD_BIa; + tests[hits].bitrate = bitRate; + tests[hits].inverted = TRUE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; } - - if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) { - tests[hits].modulation = DEMOD_NRZ; - tests[hits].inverted = FALSE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; } + //undo trim from ask + save_restoreGB(0); + clk = GetNrzClock("", FALSE, FALSE); + if (clk>0) { + sprintf(cmdStr,"%d", clk/2); + CmdLtrim(cmdStr); + if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) { + tests[hits].modulation = DEMOD_NRZ; + tests[hits].bitrate = bitRate; + tests[hits].inverted = FALSE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } - if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) { - tests[hits].modulation = DEMOD_NRZ; - tests[hits].inverted = TRUE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; + if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) { + tests[hits].modulation = DEMOD_NRZ; + tests[hits].bitrate = bitRate; + tests[hits].inverted = TRUE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; } - - if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) { - tests[hits].modulation = DEMOD_PSK1; - tests[hits].inverted = FALSE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; } - if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) { - tests[hits].modulation = DEMOD_PSK1; - tests[hits].inverted = TRUE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; - } - - // PSK2 - needs a call to psk1TOpsk2. - if ( PSKDemod("0 0 1", FALSE)) { - psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (test(DEMOD_PSK2, &tests[hits].offset)){ - tests[hits].modulation = DEMOD_PSK2; + //undo trim from nrz + save_restoreGB(0); + clk = GetPskClock("", FALSE, FALSE); + if (clk>0) { + PrintAndLog("clk %d",clk); + sprintf(cmdStr,"%d", clk/2); + CmdLtrim(cmdStr); + if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) { + tests[hits].modulation = DEMOD_PSK1; + tests[hits].bitrate = bitRate; tests[hits].inverted = FALSE; tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); ++hits; } - } // inverse waves does not affect this demod - - // PSK3 - needs a call to psk1TOpsk2. - if ( PSKDemod("0 0 1", FALSE)) { - psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (test(DEMOD_PSK3, &tests[hits].offset)){ - tests[hits].modulation = DEMOD_PSK3; - tests[hits].inverted = FALSE; + if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) { + tests[hits].modulation = DEMOD_PSK1; + tests[hits].bitrate = bitRate; + tests[hits].inverted = TRUE; tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); ++hits; } - } // inverse waves does not affect this demod - - if ( ASKbiphaseDemod("0 0 0 1", FALSE) && test(DEMOD_BI, &tests[hits].offset) ) { - tests[hits].modulation = DEMOD_BI; - tests[hits].inverted = FALSE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; - } - if ( ASKbiphaseDemod("0 0 1 1", FALSE) && test(DEMOD_BIa, &tests[hits].offset) ) { - tests[hits].modulation = DEMOD_BIa; - tests[hits].inverted = TRUE; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; + // PSK2 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 1", FALSE)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate)){ + tests[hits].modulation = DEMOD_PSK2; + tests[hits].bitrate = bitRate; + tests[hits].inverted = FALSE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } + } // inverse waves does not affect this demod + // PSK3 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 1", FALSE)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate)){ + tests[hits].modulation = DEMOD_PSK3; + tests[hits].bitrate = bitRate; + tests[hits].inverted = FALSE; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } + } // inverse waves does not affect this demod } } if ( hits == 1) { config.modulation = tests[0].modulation; + config.bitrate = tests[0].bitrate; config.inverted = tests[0].inverted; config.offset = tests[0].offset; config.block0 = tests[0].block0; @@ -516,81 +524,32 @@ bool testBitRate(uint8_t readRate, uint8_t mod){ uint8_t detRate = 0; switch( mod ){ case DEMOD_FSK: - detRate = GetFskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; case DEMOD_FSK1: - detRate = GetFskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; case DEMOD_FSK1a: - detRate = GetFskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; case DEMOD_FSK2: - detRate = GetFskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; case DEMOD_FSK2a: detRate = GetFskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; + if (expected[readRate] == detRate) return TRUE; - } break; case DEMOD_ASK: + case DEMOD_BI: + case DEMOD_BIa: detRate = GetAskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; + if (expected[readRate] == detRate) return TRUE; - } break; case DEMOD_PSK1: - detRate = GetPskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; case DEMOD_PSK2: - detRate = GetPskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; case DEMOD_PSK3: detRate = GetPskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; + if (expected[readRate] == detRate) return TRUE; - } break; case DEMOD_NRZ: detRate = GetNrzClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; - return TRUE; - } - break; - case DEMOD_BI: - detRate = GetAskClock("",FALSE, FALSE); - if (expected[readRate] == detRate) { - config.bitrate = readRate; + if (expected[readRate] == detRate) return TRUE; - } break; default: return FALSE; @@ -598,26 +557,27 @@ bool testBitRate(uint8_t readRate, uint8_t mod){ return FALSE; } -bool test(uint8_t mode, uint8_t *offset){ +bool test(uint8_t mode, uint8_t *offset, int *fndBitRate){ - if ( !DemodBufferLen) return FALSE; + if ( DemodBufferLen < 64 ) return FALSE; uint8_t si = 0; for (uint8_t idx = 0; idx < 64; idx++){ si = idx; if ( PackBits(si, 32, DemodBuffer) == 0x00 ) continue; - uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key + uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key uint8_t resv = PackBits(si, 4, DemodBuffer); si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode // 2nibble must be zeroed. // moved test to here, since this gets most faults first. if ( resv > 0x00) continue; - uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //new - uint8_t bitRate = PackBits(si, 3, DemodBuffer); si += 3; //new could check bit rate + uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //extended mode part of rate + int bitRate = PackBits(si, 3, DemodBuffer); si += 3; //bit rate + if (bitRate > 7) continue; uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode - uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //new - //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //new could check psk cr - uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24 , 30, 31 could be tested for 0 if not extended mode + uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; + //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr + uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2; //if extended mode @@ -628,15 +588,15 @@ bool test(uint8_t mode, uint8_t *offset){ } //test modulation if (!testModulation(mode, modread)) continue; - - *offset = idx; if (!testBitRate(bitRate, mode)) continue; + *fndBitRate = bitRate; + *offset = idx; return TRUE; } return FALSE; } -void printT55xxBlock(const char *demodStr){ +void printT55xxBlock(const char *blockNum){ uint8_t i = config.offset; uint8_t endpos = 32 + i; @@ -654,7 +614,7 @@ void printT55xxBlock(const char *demodStr){ bits[i - config.offset]=DemodBuffer[i]; blockData = PackBits(0, 32, bits); - PrintAndLog("0x%08X %s [%s]", blockData, sprint_bin(bits,32), demodStr); + PrintAndLog("[%s] 0x%08X %s", blockNum, blockData, sprint_bin(bits,32)); } int special(const char *Cmd) { @@ -746,16 +706,28 @@ int CmdT55xxReadTrace(const char *Cmd) uint32_t bl0 = PackBits(si, 32, DemodBuffer); uint32_t bl1 = PackBits(si+32, 32, DemodBuffer); - uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8; - uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8; - uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5; - uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3; - uint32_t year = PackBits(si, 4, DemodBuffer); si += 4; - uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2; - uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14; - uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5; + uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8; + uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8; + uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5; + uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3; + uint32_t year = PackBits(si, 4, DemodBuffer); si += 4; + uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2; + uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14; + uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5; uint32_t dw = PackBits(si, 15, DemodBuffer); + time_t t = time(NULL); + struct tm tm = *localtime(&t); + if ( year > tm.tm_year-110) + year += 2000; + else + year += 2010; + + if ( acl != 0xE0 ) { + PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. "); + return 1; + } + PrintAndLog(""); PrintAndLog("-- T55xx Trace Information ----------------------------------"); PrintAndLog("-------------------------------------------------------------"); @@ -764,7 +736,7 @@ int CmdT55xxReadTrace(const char *Cmd) PrintAndLog(" CID : 0x%02X (%d) - %s", cid, cid, GetModelStrFromCID(cid)); PrintAndLog(" ICR IC Revision : %d",icr ); PrintAndLog(" Manufactured"); - PrintAndLog(" Year/Quarter : 20?%d/%d",year, quarter); + PrintAndLog(" Year/Quarter : %d/%d",year, quarter); PrintAndLog(" Lot ID : %d", lotid ); PrintAndLog(" Wafer number : %d", wafer); PrintAndLog(" Die Number : %d", dw); @@ -774,8 +746,6 @@ int CmdT55xxReadTrace(const char *Cmd) PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); PrintAndLog("-------------------------------------------------------------"); - if ( acl != 0xE0 ) - PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. "); /* TRACE - BLOCK O Bits Definition HEX @@ -809,10 +779,10 @@ int CmdT55xxInfo(const char *Cmd){ if (strlen(Cmd)==0) AquireData( CONFIGURATION_BLOCK ); - + if (!DecodeT55xxBlock()) return 1; - if ( !DemodBufferLen) return 1; + if ( DemodBufferLen < 32) return 1; uint8_t si = config.offset; uint32_t bl0 = PackBits(si, 32, DemodBuffer); @@ -922,7 +892,8 @@ int AquireData( uint8_t block ){ } char * GetBitRateStr(uint32_t id){ - static char buf[40]; + static char buf[25]; + char *retStr = buf; switch (id){ case 0: @@ -957,7 +928,6 @@ char * GetBitRateStr(uint32_t id){ return buf; } - char * GetSaferStr(uint32_t id){ static char buf[40]; char *retStr = buf; @@ -974,7 +944,7 @@ char * GetSaferStr(uint32_t id){ } char * GetModulationStr( uint32_t id){ - static char buf[40]; + static char buf[60]; char *retStr = buf; switch (id){ @@ -1003,7 +973,7 @@ char * GetModulationStr( uint32_t id){ snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id); break; case 8: - snprintf(retStr,sizeof(buf),"%d - Manschester",id); + snprintf(retStr,sizeof(buf),"%d - Manchester",id); break; case 16: snprintf(retStr,sizeof(buf),"%d - Biphase",id); @@ -1026,8 +996,8 @@ char * GetModelStrFromCID(uint32_t cid){ static char buf[10]; char *retStr = buf; - if (cid == 1) sprintf(retStr,"ATA5577M1"); - if (cid == 2) sprintf(retStr,"ATA5577M2"); + if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1"); + if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2"); return buf; } diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index a64b1eda..364f0271 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -53,13 +53,13 @@ char * GetSaferStr(uint32_t id); char * GetModulationStr( uint32_t id); char * GetModelStrFromCID(uint32_t cid); char * GetSelectedModulationStr( uint8_t id); -uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream); +uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream); void printT55xxBlock(const char *demodStr); void printConfiguration( t55xx_conf_block_t b); bool DecodeT55xxBlock(); bool tryDetectModulation(); -bool test(uint8_t mode, uint8_t *offset); +bool test(uint8_t mode, uint8_t *offset, int *fndBitRate); int special(const char *Cmd); int AquireData( uint8_t block ); diff --git a/client/graph.c b/client/graph.c index f4acc579..06279848 100644 --- a/client/graph.c +++ b/client/graph.c @@ -17,7 +17,6 @@ int GraphBuffer[MAX_GRAPH_TRACE_LEN]; int GraphTraceLen; - /* write a manchester bit to the graph */ void AppendGraph(int redraw, int clock, int bit) { @@ -46,6 +45,24 @@ int ClearGraph(int redraw) return gtl; } +// option '1' to save GraphBuffer any other to restore +void save_restoreGB(uint8_t saveOpt) +{ + static int SavedGB[MAX_GRAPH_TRACE_LEN]; + static int SavedGBlen; + static bool GB_Saved = false; + + if (saveOpt==1) { //save + memcpy(SavedGB, GraphBuffer, sizeof(GraphBuffer)); + SavedGBlen = GraphTraceLen; + GB_Saved=true; + } else if (GB_Saved){ //restore + memcpy(GraphBuffer, SavedGB, sizeof(GraphBuffer)); + GraphTraceLen = SavedGBlen; + RepaintGraphWindow(); + } + return; +} // DETECT CLOCK NOW IN LFDEMOD.C @@ -126,10 +143,10 @@ int GetAskClock(const char str[], bool printAns, bool verbose) PrintAndLog("Failed to copy from graphbuffer"); return -1; } - DetectASKClock(grph, size, &clock, 20); + int start = DetectASKClock(grph, size, &clock, 20); // Only print this message if we're not looping something if (printAns){ - PrintAndLog("Auto-detected clock rate: %d", clock); + PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); } return clock; } diff --git a/client/graph.h b/client/graph.h index 8f810669..8deeb386 100644 --- a/client/graph.h +++ b/client/graph.h @@ -23,6 +23,7 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose); uint8_t GetFskClock(const char str[], bool printAns, bool verbose); uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose); void setGraphBuf(uint8_t *buff, size_t size); +void save_restoreGB(uint8_t saveOpt); bool HasGraphData(); void DetectHighLowInGraph(int *high, int *low, bool addFuzz); diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index ad8f6e00..b0257ef0 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -138,6 +138,8 @@ local _commands = { CMD_MIFAREUC_AUTH1 = 0x0724, CMD_MIFAREUC_AUTH2 = 0x0725, CMD_MIFAREUC_READCARD = 0x0726, + CMD_MIFAREUC_SETPWD = 0x0727, + CMD_MIFAREU_SETUID = 0x0728, --// mifare desfire CMD_MIFARE_DESFIRE_READBL = 0x0728, @@ -153,10 +155,10 @@ local _commands = { local _reverse_lookup,k,v = {} -for k, v in pairs(_commands) do - _reverse_lookup[v] = k -end -_commands.tostring = function(command) + for k, v in pairs(_commands) do + _reverse_lookup[v] = k + end + _commands.tostring = function(command) if(type(command) == 'number') then return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) end @@ -217,7 +219,6 @@ function Command:getBytes() local data = self.data local cmd = self.cmd local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 - - return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data); + return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data); end return _commands diff --git a/client/lualibs/default_toys.lua b/client/lualibs/default_toys.lua index 048a29c9..f34d510d 100644 --- a/client/lualibs/default_toys.lua +++ b/client/lualibs/default_toys.lua @@ -1,196 +1,333 @@ local _names = { - --[[ + --[[ decimal, hexadecimal, ccc, elements, group, name --]] - ["0000"]="WHIRLWIND", - ["0100"]="SONIC BOOM", - ["0200"]="WARNADO", - ["0300"]="LIGHTNINGROD", - ["0400"]="BASH", - ["0500"]="TERRAFIN", - ["0600"]="DINORANG" , - ["0700"]="LIGHTCORE PRISM BREAK", - ["0800"]="SUNBURN", - ["0900"]="LIGHTCORE ERUPTOR", - ["0A00"]="IGNITOR", - ["0B00"]="FLAMESLINGER", - ["0C00"]="ZAP", - ["0D00"]="WHAM SHELL", - ["0E00"]="GILL GRUNT", - ["0F00"]="SLAMBAM", - ["1000"]="SPYRO", - ["1100"]="VOODOOD", - ["1200"]="DOUBLE TROUBLE", - ["1300"]="TRIGGER HAPPY", - ["1400"]="DROBOT", - ["1500"]="DRILLSERGEANT", - ["1600"]="BOOMER", - ["1700"]="WRECKING BALL", - ["1800"]="CAMO", - ["1900"]="ZOOK", - ["1A00"]="STEALTH ELF", - ["1B00"]="STUMP SMASH", - ["1D00"]="HEX", - ["1C00"]="DARK SPYRO", - ["1E00"]="CHOPCHOP", - ["1F00"]="GHOST ROASTER", - ["2000"]="CYNDER", - --[[ - GIANTS - --]] - ["6400"]="GIANT JET-VAC", - ["6500"]="GIANT SWARM", - ["6600"]="GIANT CRUSHER", - ["6700"]="GIANT FLASHWING", - ["6800"]="GIANT HOTHEAD", - ["6900"]="GIANT HOTDOG", - ["6A00"]="GIANT CHILL", - ["6B00"]="GIANT THUMPBACK", - ["6C00"]="GIANT POPFIZZ", - ["6D00"]="GIANT NINJINI", - ["6E00"]="GIANT BOUNCER", - ["6F00"]="GIANT SPROCKET", - ["7000"]="GIANT TREE REX", - ["7100"]="LIGHTCORE SHROOMBOOM", - ["7200"]="GIANT EYEBROAWL", - ["7300"]="GIANT FRIGHTRIDER", - - --[[ - ITEM - --]] - ["C800"]="ANVIL", - ["C900"]="SECRET STASH", - ["CA00"]="REGENERATION", - ["CD00"]="SHIELD", - ["CB00"]="CROSSED SWORDS", - ["CC00"]="HOURGLASS", - ["CE00"]="SPEED BOOTS", - ["CF00"]="SPARX", - ["D000"]="CANNON", - ["D100"]="SCORPIONSTRIKER", - - --[[ - ITEM TRAPS - --]] - ["D200"]="MAGIC TRAP", - ["D300"]="WATER TRAP", - ["D400"]="AIR TRAP", - ["D500"]="UNDEAD TRAP", - ["D600"]="TECH TRAP", - ["D700"]="FIRE TRAP", - ["D800"]="EARTH TRAP", - ["D900"]="LIFE TRAP", - ["DA00"]="DARK TRAP", - ["DB00"]="LIGHT TRAP", - ["DC00"]="KAOS TRAP", - - --[[ - ITEM - --]] - ["E600"]="HAND OF FATE", - ["E700"]="PIGGYBANK", - ["E800"]="ROCKET RAM", - ["E900"]="TIKI SPEAKY", - - - --[[ - EXPANSION - --]] - ["012C"]="DRAGONS PEAK", - ["012D"]="EMPIRE OF ICE", - ["012E"]="PIRATE SEAS", - ["012F"]="DARKLIGHT CRYPT", - ["0130"]="VOLCANIC VAULT", - ["0131"]="MIRROR OF MYSTERY", - ["0132"]="NIGHTMARE EXPRESS", - ["0133"]="SUNSCRAPER SPIRE", - ["0134"]="MIDNIGHT MUSEUM", +{"0", "0000", "0030", "air", "regular", "Whirlwind"}, +--{"0", "0000", "0030", "air", "regular", "Elite Whirlwind"}, +--{"0", "0000", "0030", "air", "regular", "Polar Whirlwind"}, +{"1", "0100", "0030", "air", "regular", "Sonic Boom"}, +{"2", "0200", "0030", "air", "regular", "Warnado"}, +{"3", "0300", "0030", "air", "regular", "Lightning Rod"}, +{"4", "0400", "0030", "earth", "regular", "Bash"}, +--{"4", "0400", "0030", "earth", "regular", "Birthday Bash"}, +{"5", "0500", "0030", "earth", "regular", "Terrafin"}, +--{"5", "0500", "0030", "earth", "regular", "Elite Terrafin"}, +{"6", "0600", "0030", "earth", "regular", "Dino Rang"}, +{"7", "0700", "0030", "earth", "regular", "Prism Break"}, --lightcore +{"8", "0800", "0030", "fire", "regular", "Sunburn"}, +{"9", "0900", "0030", "fire", "regular", "Eruptor"}, --lightcore +--{"9", "0900", "0030", "fire", "regular", "Elite Eruptor"}, +--{"9", "0900", "0030", "fire", "regular", "Volcanic Eruptor"}, +{"10", "0a00", "0030", "fire", "regular", "Ignitor"}, +{"11", "0b00", "0030", "fire", "regular", "Flameslinger"}, +--{"11", "0b00", "0030", "fire", "regular", "Cupid Flameslinger"}, +{"12", "0c00", "0030", "water", "regular", "Zap"}, +{"13", "0d00", "0030", "water", "regular", "Wham Shell"}, +{"14", "0e00", "0030", "water", "regular", "Gill Grunt"}, +--{"14", "0e00", "0030", "water", "regular", "Elite Gill Grunt"}, +{"15", "0f00", "0030", "water", "regular", "Slam Bam"}, +--{"15", "0f00", "0030", "water", "regular", "Surfer Slam Bam"}, +{"16", "1000", "0030", "magic", "regular", "Spyro"}, +{"17", "1100", "0030", "magic", "regular", "Voodood"}, +{"18", "1200", "0030", "magic", "regular", "Double Trouble"}, +--{"18", "1200", "0030", "magic", "regular", "Royal Double Trouble"}, +{"19", "1300", "0030", "tech", "regular", "Trigger Happy"}, +--{"19", "1300", "0030", "tech", "regular", "Elite Trigger Happy"}, +--{"19", "1300", "0030", "tech", "regular", "Springtime Trigger Happy"}, +{"20", "1400", "0030", "tech", "regular", "Drobot"}, +{"21", "1500", "0030", "tech", "regular", "Drill Sergeant"}, +{"22", "1600", "0030", "tech", "regular", "Boomer"}, +--{"22", "1600", "0030", "tech", "regular", "Lucky Boomer"}, +{"23", "1700", "0030", "magic", "regular", "Wrecking Ball"}, +--{"23", "1700", "0030", "magic", "regular", "Buddy Wrecking Ball"}, +{"24", "1800", "0030", "life", "regular", "Camo"}, +{"25", "1900", "0030", "life", "regular", "Zook"}, +{"26", "1a00", "0030", "life", "regular", "Stealth Elf"}, +--{"26", "1a00", "0030", "life", "regular", "Elite Stealth Elf"}, +--{"26", "1a00", "0030", "life", "regular", "Dark Stealth Elf"}, +{"27", "1b00", "0030", "life", "regular", "Stump Smash"}, +{"27", "1b00", "0118", "life", "regular", "Stump Smash"}, +--{"27", "1b00", "0030", "life", "regular", "Autumn Stump Smash"}, +{"28", "1c00", "0030", "magic", "regular", "Dark Spyro"}, +--{"28", "1c00", "0030", "magic", "regular", "Elite Spyro"}, +{"29", "1d00", "0030", "undead", "regular", "Hex"}, +--{"29", "1d00", "0030", "undead", "regular", "Hallows' Eve Hex"}, +{"30", "1e00", "0030", "undead", "regular", "Chop Chop"}, +--{"30", "1e00", "0030", "undead", "regular", "Elite Chop Chop"}, +--{"30", "1e00", "0030", "undead", "regular", "Grill Master Chop Chop"}, +{"31", "1f00", "0030", "undead", "regular", "Ghost Roaster"}, +{"32", "2000", "0030", "undead", "regular", "Cynder"}, +--{"32", "2000", "0030", "undead", "regular", "Skeletal Cynder"}, + +{"100", "6400", "0030", "air", "giant", "Jet Vac"}, +{"101", "6500", "0030", "air", "giant", "Swarm"}, +{"102", "6600", "0030", "earth", "giant", "Crusher"}, +{"103", "6700", "0030", "earth", "giant", "Flashwing"}, +--{"103", "6700", "0030", "earth", "giant", "Jade Flashwing"}, +{"104", "6800", "0030", "fire", "giant", "Hot Head"}, +{"105", "6900", "0030", "fire", "giant", "Hot Dog"}, +--{"105", "6900", "0030", "fire", "giant", "Molten Hot Dog"}, +{"106", "6a00", "0030", "water", "giant", "Chill"}, +{"107", "6b00", "0030", "water", "giant", "Thumpback"}, +--{"107", "6b00", "0030", "water", "giant", "Admiral Thumpback"}, +{"108", "6c00", "0030", "magic", "giant", "Pop Fizz"}, +--{"108", "6c00", "0030", "magic", "giant", "Hoppity Pop Fizz"}, +{"108", "6c00", "023c", "magic", "giant", "Love Potion Pop Fizz"}, +--{"108", "6c00", "0030", "magic", "giant", "Punch Pop Fizz"}, +{"109", "6d00", "0030", "magic", "giant", "Nin Jini"}, +{"110", "6e00", "0030", "tech", "giant", "Bouncer"}, +{"111", "6f00", "0030", "tech", "giant", "Sprocket"}, +{"112", "7000", "0030", "life", "giant", "Tree Rex"}, +--{"112", "7000", "0030", "life", "giant", "Gnarly Tree Rex"}, +{"113", "7100", "0030", "life", "giant", "Shroomboom"}, --lightcore +{"114", "7200", "0030", "undead", "giant", "Eye Broawl"}, +{"115", "7300", "0030", "undead", "giant", "Fright Rider"}, + +{"200", "c800", "0030", "", "item", "Anvil Rain"}, +{"201", "c900", "0030", "", "item", "Platinum Treasure Chest"}, +{"202", "ca00", "0030", "", "item", "Healing Elixer"}, +{"203", "cb00", "0030", "", "item", "Ghost Pirate Swords"}, +{"204", "cc00", "0030", "", "item", "Time Twist Hourglass"}, +{"205", "cd00", "0030", "", "item", "Sky Iron Shield"}, +{"206", "ce00", "0030", "", "item", "Winged Boots"}, +{"207", "cf00", "0030", "", "item", "Sparx"}, +{"208", "d000", "0030", "", "item", "Cannon"}, +{"209", "d100", "0030", "", "item", "Scorpion Striker"}, + +{"210", "d200", "0230", "magic", "trap", "Biter's Bane"}, +{"210", "d200", "0830", "magic", "trap", "Sorcerous Skull"}, +-- legendary Sorcerous Skull? +{"210", "d200", "0b30", "magic", "trap", "Axe Of Illusion"}, +{"210", "d200", "0e30", "magic", "trap", "Arcane Hourglass"}, +{"210", "d200", "1230", "magic", "trap", "Spell Slapper"}, +{"210", "d200", "1430", "magic", "trap", "Rune Rocket"}, + +{"211", "d300", "0130", "water", "trap", "Tidal Tiki"}, +{"211", "d300", "0230", "water", "trap", "Wet Walter"}, +{"211", "d300", "0630", "water", "trap", "Flood Flask"}, +-- legendary flood flask? +{"211", "d300", "0730", "water", "trap", "Soaking Staff"}, +{"211", "d300", "0b30", "water", "trap", "Aqua Axe"}, +{"211", "d300", "1630", "water", "trap", "Frost Helm"}, + +{"212", "d400", "0330", "air", "trap", "Breezy Bird"}, +{"212", "d400", "0630", "air", "trap", "Drafty Decanter"}, +{"212", "d400", "0d30", "air", "trap", "Tempest Timer"}, +{"212", "d400", "1030", "air", "trap", "Cloudy Cobra"}, +{"212", "d400", "1130", "air", "trap", "Storm Warning"}, +{"212", "d400", "1830", "air", "trap", "Cycone Saber"}, + +{"213", "d500", "0430", "undead", "trap", "Spirit Sphere"}, +{"213", "d500", "0830", "undead", "trap", "Spectral Skull"}, +{"213", "d500", "0b30", "undead", "trap", "Haunted Hatchet"}, +{"213", "d500", "0c30", "undead", "trap", "Grim Gripper"}, +{"213", "d500", "1030", "undead", "trap", "Spooky Snake"}, +{"213", "d500", "1730", "undead", "trap", "Dream Piercer"}, + +{"214", "d600", "0030", "tech", "trap", "tech Totem"}, +{"214", "d600", "0730", "tech", "trap", "Automatic Angel"}, +{"214", "d600", "0930", "tech", "trap", "Factory Flower"}, +{"214", "d600", "0c30", "tech", "trap", "Grabbing Gadget"}, +{"214", "d600", "1630", "tech", "trap", "Makers Mana"}, +{"214", "d600", "1a30", "tech", "trap", "Topsy techy"}, + +{"215", "d700", "0530", "fire", "trap", "Eternal Flame"}, +{"215", "d700", "0930", "fire", "trap", "fire Flower"}, +{"215", "d700", "1130", "fire", "trap", "Scorching Stopper"}, +{"215", "d700", "1230", "fire", "trap", "Searing Spinner"}, +{"215", "d700", "1730", "fire", "trap", "Spark Spear"}, +{"215", "d700", "1b30", "fire", "trap", "Blazing Belch"}, + +{"216", "d800", "0030", "earth", "trap", "Banded Boulder"}, +{"216", "d800", "0330", "earth", "trap", "Rock Hawk"}, +{"216", "d800", "0a30", "earth", "trap", "Slag Hammer"}, +{"216", "d800", "0e30", "earth", "trap", "Dust Of Time"}, +{"216", "d800", "1330", "earth", "trap", "Spinning Sandstorm"}, +{"216", "d800", "1a30", "earth", "trap", "Rubble Trouble"}, + +{"217", "d900", "0330", "life", "trap", "Oak Eagle"}, +{"217", "d900", "0530", "life", "trap", "Emerald Energy"}, +{"217", "d900", "0a30", "life", "trap", "Weed Whacker"}, +{"217", "d900", "1030", "life", "trap", "Seed Serpent"}, +{"217", "d900", "1830", "life", "trap", "Jade Blade"}, +{"217", "d900", "1b30", "life", "trap", "Shrub Shrieker"}, + +{"218", "da00", "0030", "dark", "trap", "dark Dagger"}, +{"218", "da00", "1430", "dark", "trap", "Shadow Spider"}, +{"218", "da00", "1a30", "dark", "trap", "Ghastly Grimace"}, + +{"219", "db00", "0030", "light", "trap", "Shining Ship"}, +{"219", "db00", "0f30", "light", "trap", "Heavenly Hawk"}, +{"219", "db00", "1b30", "light", "trap", "Beam Scream"}, + +{"220", "dc00", "3030", "kaos", "trap", "Kaos trap!"}, +--{"220", "dc00", "3130", "kaos", "trap", "Ultimate Kaos trap!"}, ? + + +{"230", "e600", "0030", "none", "item", "Hand Of Fate"}, +{"231", "e700", "0030", "none", "item", "Piggy Bank"}, +{"232", "e800", "0030", "none", "item", "Rocket Ram"}, +{"233", "e900", "0030", "none", "item", "Tiki Speaky"}, + +{"300", "2c01", "0030", "none", "location", "Dragons Peak"}, +{"301", "2d01", "0030", "none", "location", "Empire Of Ice"}, +{"302", "2e01", "0030", "none", "location", "Pirate Seas"}, +{"303", "2f01", "0030", "none", "location", "darklight Crypt"}, +{"304", "3001", "0030", "none", "location", "Volcanic Vault"}, +{"305", "3101", "0030", "none", "location", "Mirror Of Mystery"}, +{"306", "3201", "0030", "none", "location", "Nightmare Express"}, +{"307", "3301", "0030", "light", "location", "Sunscraper Spire"}, +{"308", "3401", "0030", "dark", "location", "Midnight Museum"}, + +{"404", "9401", "0030", "earth", "legendary","Bash"}, +{"416", "a001", "0030", "magic", "legendary", "Spyro"}, + --{"", "", "0030", "magic", "legendary", "Deja Vu"}, +{"419", "a301", "0030", "tech", "legendary", "Trigger Happy"}, + --{"", "", "0030", "tech", "legendary", "bouncer"}, + --{"", "", "0030", "tech", "legendary", "jawbreaker"}, +{"430", "ae01", "0030", "undead", "legendary", "Chop Chop"}, + --{"", "", "0030", "undead", "legendary", "grim creeper"}, + --{"", "", "0030", "undead", "legendary", "night shift"}, - --[[ - LEGENDARY - --]] - ["0194"]="LEGENDARY BASH", - ["01A0"]="LEGENDARY SPYRO", - ["01A3"]="LEGENDARY TRIGGER HAPPY", - ["01AE"]="LEGENDARY CHOPCHOP", + --{"", "", "0030", "air", "legendary", "blades"}, + --{"", "", "0030", "air", "legendary", "jet vac"}, + --{"", "", "0030", "air", "legendary", "Free Ranger"}, + --{"", "", "0030", "life", "legendary", "stealth elf"}, + --{"", "", "0030", "life", "legendary", "Bushwhack"}, + --{"", "", "0030", "fire", "legendary", "ignitor"}, + --{"", "", "0030", "water", "legendary", "slam bam"}, + --{"", "", "0030", "water", "legendary", "chill"}, + + --{"", "", "0030", "", "legendary", "zoo lou"}, - --[[ - TRAPTEAM - --]] - ["01C2"]="TRAPTEAM GUSTO", - ["01C3"]="TRAPTEAM THUNDERBOLT", - ["01C4"]="TRAPTEAM FLING KONG", - ["01C5"]="TRAPTEAM BLADES", - ["01C6"]="TRAPTEAM WALLOP", - ["01C7"]="TRAPTEAM HEAD RUSH", - ["01C8"]="TRAPTEAM FIST BUMP", - ["01C9"]="TRAPTEAM ROCKY ROLL", - ["01CA"]="TRAPTEAM WILDFIRE", - ["01CB"]="TRAPTEAM KA BOOM", - ["01CC"]="TRAPTEAM TRAIL BLAZER", - ["01CD"]="TRAPTEAM TORCH", - ["01CE"]="TRAPTEAM SNAP SHOT", - ["01CF"]="TRAPTEAM LOB STAR", - ["01D0"]="TRAPTEAM FLIP WRECK", - ["01D1"]="TRAPTEAM ECHO", - ["01D2"]="TRAPTEAM BLASTERMIND", - ["01D3"]="TRAPTEAM ENIGMA", - ["01D4"]="TRAPTEAM DEJA VU", - ["01D5"]="TRAPTEAM COBRA CADABRA", - ["01D6"]="TRAPTEAM JAWBREAKER", - ["01D7"]="TRAPTEAM GEARSHIFT", - ["01D8"]="TRAPTEAM CHOPPER", - ["01D9"]="TRAPTEAM TREAD HEAD", - ["01DA"]="TRAPTEAM BUSHWHACK", - ["01DB"]="TRAPTEAM TUFF LUCK", - ["01DC"]="TRAPTEAM FOOD FIGHT", - ["01DD"]="TRAPTEAM HIGH FIVE", - ["01DE"]="TRAPTEAM NITRO KRYPT KING", - ["01DF"]="TRAPTEAM SHORT CUT", - ["01E0"]="TRAPTEAM BAT SPIN", - ["01E1"]="TRAPTEAM FUNNY BONE", - ["01E2"]="TRAPTEAM KNIGHT LIGHT", - ["01E3"]="TRAPTEAM SPOTLIGHT", - ["01E4"]="TRAPTEAM KNIGHT MARE", - ["01E5"]="TRAPTEAM BLACKOUT", - - --[[ - PET - --]] - ["01F6"]="PET BOP", - ["01F7"]="PET SPRY", - ["01F8"]="PET HIJINX", - ["01F9"]="PET TERRAFIN", - ["01FA"]="PET BREEZE", - ["01FB"]="PET WEERUPTOR", - ["01FC"]="PET PET VAC", - ["01FD"]="PET SMALL FRY", - ["01FE"]="PET DROBIT", - ["0202"]="PET GILL GRUNT", - ["0207"]="PET TRIGGER SNAPPY", - ["020E"]="PET WHISPER ELF", - ["021C"]="PET BARKLEY", - ["021D"]="PET THUMPLING", - ["021E"]="PET MINI JINI", - ["021F"]="PET EYE SMALL", - - --[[ - SWAP FORCE - --]] - ["0BB8"]="SWAPFORCE SCRATCH", - ["0BB9"]="SWAPFORCE POPTHORN", - ["0BBA"]="SWAPFORCE SLOBBER TOOTH", - ["0BBB"]="SWAPFORCE SCORP", - ["0BBC"]="SWAPFORCE HOG WILD FRYNO", - ["0BBD"]="SWAPFORCE SMOLDER DASH", - ["0BBE"]="SWAPFORCE BUMBLE BLAST", - ["0BBF"]="SWAPFORCE ZOO LOU", - ["0BC0"]="SWAPFORCE DUNE BUG", - ["0BC1"]="SWAPFORCE STAR STRIKE", - ["0BC2"]="SWAPFORCE COUNTDOWN", - ["0BC3"]="SWAPFORCE WIND UP", - ["0BC4"]="SWAPFORCE ROLLER BRAWL", - ["0BC5"]="SWAPFORCE GRIM CREEPER", - ["0BC6"]="SWAPFORCE RIP TIDE", - ["0BC7"]="SWAPFORCE PUNK SHOCK", +{"450", "c201", "0030", "air", "trapmaster", "Gusto"}, +--{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"}, +{"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"}, +--{"451", "c301", "0234", "air", "trapmaster", "Special Thunderbolt"}, +{"452", "c401", "0030", "air", "regular", "Fling Kong"}, +{"453", "c501", "0030", "air", "regular", "Blades"}, +{"454", "c601", "0030", "earth", "trapmaster", "Wallop"}, +--{"454", "c601", "0234", "earth", "trapmaster", "Special Wallop"}, +{"455", "c701", "0030", "earth", "trapmaster", "Head Rush"}, +{"455", "c701", "0234", "earth", "trapmaster", "Nitro Head Rush"}, +{"456", "c801", "0030", "earth", "regular", "Fist Bump"}, +{"457", "c901", "0030", "earth", "regular", "Rocky Roll"}, +--{"457", "c901", "0030", "earth", "regular", "Rocky Egg Roll"}, +{"458", "ca01", "0030", "fire", "trapmaster", "Wildfire"}, +{"458", "ca01", "0234", "fire", "trapmaster", "Dark Wildfire"}, +{"459", "cb01", "0030", "fire", "trapmaster", "Ka Boom"}, +--{"459", "cb01", "0234", "fire", "trapmaster", "Special Ka Boom"}, +{"460", "cc01", "0030", "fire", "regular", "Trail Blazer"}, +{"461", "cd01", "0030", "fire", "regular", "Torch"}, +{"462", "ce01", "0030", "water", "trapmaster", "Snap Shot"}, +{"462", "ce01", "0234", "water", "trapmaster", "Dark Snap Shot"}, +{"462", "6c00", "023c", "water", "trapmaster", "Instant Snap Shot"}, +--, "water", "trapmaster", "Merry Snap Shot"}, +{"463", "cf01", "0030", "water", "trapmaster", "Lob Star"}, +{"463", "cf01", "0234", "water", "trapmaster", "Winterfest Lob Star"}, +{"464", "d001", "0030", "water", "regular", "Flip Wreck"}, +{"465", "d101", "0030", "water", "regular", "Echo"}, +{"466", "d201", "0030", "magic", "trapmaster", "Blastermind"}, +--{"466", "d201", "0234", "magic", "trapmaster", "Special Blastermind"}, +{"467", "d301", "0030", "magic", "trapmaster", "Enigma"}, +--{"467", "d301", "0234", "magic", "trapmaster", "Special Enigma"}, +{"468", "d401", "0030", "magic", "regular", "Deja Vu"}, +{"469", "d501", "0030", "magic", "regular", "Cobra Cadabra"}, +--{"469", "d501", "0030", "magic", "regular", "Charming Cobra Cadabra"}, +--{"469", "d501", "0030", "magic", "regular", "King Cobra Cadabra"}, +{"470", "d601", "0030", "tech", "trapmaster", "Jawbreaker"}, +--{"470", "d601", "0234", "tech", "trapmaster", "Special Jawbreaker"}, +--{"470", "d601", "0234", "tech", "trapmaster", "Knockout Jawbreaker"}, +{"471", "d701", "0030", "tech", "trapmaster", "Gearshift"}, +--{"471", "d701", "0234", "tech", "trapmaster", "Special Gearshift"}, +{"472", "d801", "0030", "tech", "regular", "Chopper"}, +{"473", "d901", "0030", "tech", "regular", "Tread Head"}, +{"474", "da01", "0030", "life", "trapmaster", "Bushwhack"}, +--{"474", "da01", "0234", "life", "trapmaster", "Special Bushwhack"}, +{"475", "db01", "0030", "life", "trapmaster", "Tuff Luck"}, +--{"475", "db01", "0234", "life", "trapmaster", "Special Tuff Luck"}, +{"476", "dc01", "0030", "life", "regular", "Food Fight"}, +{"476", "dc01", "0612", "life", "regular", "LightCore Food Fight"}, +--{"476", "dc01", "0030", "life", "regular", "Dark Food Fight"}, +--{"476", "dc01", "0030", "life", "regular", "Frosted Food Fight"}, +--{"476", "dc01", "0030", "life", "regular", "Instant Food Fight"}, +{"477", "dd01", "0030", "life", "regular", "High Five"}, +{"478", "de01", "0030", "undead", "trapmaster", "Krypt King"}, +{"478", "de01", "0234", "undead", "trapmaster", "Nitro Krypt King"}, +{"479", "df01", "0030", "undead", "trapmaster", "Short Cut"}, +--{"479", "df01", "0234", "undead", "trapmaster", "Special Short Cut"}, +{"480", "e001", "0030", "undead", "regular", "Bat Spin"}, +{"481", "e101", "0030", "undead", "regular", "Funny Bone"}, +{"481", "e101", "0612", "undead", "regular", "LightCore Funny Bone"}, +--{"481", "e101", "0030", "undead", "regular", "Fortune Funny Bone"}, +{"482", "e201", "0030", "light", "trapmaster", "Knight light"}, +--{"482", "e201", "0234", "light", "trapmaster", "Special Knight light"}, +{"483", "e301", "0030", "light", "regular", "Spotlight"}, +--{"483", "e301", "0234", "light", "regular", "Special Spotlight"}, +{"484", "e401", "0030", "dark", "trapmaster", "Knight Mare"}, +--{"484", "e401", "0234", "dark", "trapmaster", "Special Knight Mare"}, +{"485", "e501", "0030", "dark", "regular", "Blackout"}, +--{"485", "e501", "0234", "dark", "regular", "Special Blackout"}, + +{"502", "f601", "0030", "earth", "mini", "Bop"}, +{"503", "f701", "0030", "magic", "mini", "Spry"}, +{"504", "f801", "0030", "undead", "mini", "Hijinx"}, +{"505", "f901", "0030", "earth", "mini", "Terrabite"}, +{"506", "fa01", "0030", "air", "mini", "Breeze"}, +{"507", "fb01", "0030", "fire", "mini", "Weeruptor"}, +--{"507", "fb01", "0030", "fire", "mini", "Eggsellent Weeruptor"}, +{"508", "fc01", "0030", "air", "mini", "Pet Vac"}, +--{"508", "fc01", "0030", "air", "mini", "Power Punch Pet Vac"}, +{"509", "fd01", "0030", "fire", "mini", "Small Fry"}, +{"510", "fe01", "0030", "tech", "mini", "Drobit"}, +{"514", "0202", "0030", "water", "mini", "Gill Runt"}, +{"519", "0702", "0030", "tech", "mini", "Trigger Snappy"}, +{"526", "0e02", "0030", "life", "mini", "Whisper Elf"}, +{"540", "1c02", "0030", "life", "mini", "Barkley"}, +--{"540", "1c02", "0030", "life", "mini", "Gnarly Barkley"}, +{"541", "1d02", "0030", "water", "mini", "Thumpling"}, +{"542", "1e02", "0030", "magic", "mini", "mini Jini"}, +{"543", "1f02", "0030", "undead", "mini", "Eye Small"}, + +{"3000", "b80b", "0030", "air", "SWAPFORCE", "Scratch"}, +{"3001", "b90b", "0030", "air", "SWAPFORCE", "Pop Thorn"}, +--{"3001", "b90b", "0030", "air", "SWAPFORCE", "Buttered Pop Thorn"}, +{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Slobber Tooth"}, +--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Dark Slobber Tooth"}, +--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Sundae Slobber Tooth"}, +{"3003", "bb0b", "0030", "earth", "SWAPFORCE", "Scorp"}, +{"3004", "bc0b", "0030", "fire", "SWAPFORCE", "Fryno"}, +{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Hog Wild Fryno"}, +--{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Flip flop Fryno"}, +{"3005", "bd0b", "0030", "fire", "SWAPFORCE", "Smolderdash"}, +{"3006", "be0b", "0030", "life", "SWAPFORCE", "Bumble Blast"}, +--{"3006", "be0b", "0030", "life", "SWAPFORCE", "Jolly Bumble Blast"}, +{"3007", "bf0b", "0030", "life", "SWAPFORCE", "Zoo Lou"}, +{"3008", "c00b", "0030", "magic", "SWAPFORCE", "Dune Bug"}, +{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Star Strike"}, +--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Enchanted Star Strike"}, +--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Mystic Star Strike"}, +{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Countdown"}, +--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Kickoff Countdown"}, +--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "New Year's Countdown"}, +{"3011", "c30b", "0030", "tech", "SWAPFORCE", "Wind Up"}, +{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Roller Brawl"}, +--{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Snowler Roller Brawl"}, +{"3013", "c50b", "0030", "undead", "SWAPFORCE", "Grim Creeper"}, +{"3014", "c60b", "0030", "water", "SWAPFORCE", "Rip Tide"}, +{"3015", "c70b", "0030", "water", "SWAPFORCE", "Punk Shock"}, +} + +local function find( main, sub) + main = main:lower() + sub = sub:lower() + for k, v in pairs(_names) do + if ( v[2]:lower() == main and v[3]:lower() == sub) then + return v + end + end + return nil +end + +return { + Find = find, } -return _names diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index da1a1ef2..3b27cac3 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -205,7 +205,7 @@ local function main( args) -- NDEF compliant? if b3chars[1] ~= 0xE1 then - return oops("This tag is not NDEF-Complian") + return oops("This tag is not NDEF-Compliant") end local ndefVersion = b3chars[2] diff --git a/client/scripts/test_t55x7_ask.lua b/client/scripts/test_t55x7_ask.lua index 569d4260..f8990b15 100644 --- a/client/scripts/test_t55x7_ask.lua +++ b/client/scripts/test_t55x7_ask.lua @@ -95,6 +95,7 @@ end function test() local y + local block = "00" for y = 0x0, 0x1d, 0x4 do for _ = 1, #procedurecmds do local pcmd = procedurecmds[_] @@ -107,7 +108,7 @@ function test() dbg(('lf t55xx write 0 %s'):format(config)) config = tonumber(config,16) - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config} + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} local err = core.SendCommand(writecmd:getBytes()) if err then return oops(err) end local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) diff --git a/client/scripts/test_t55x7_bi.lua b/client/scripts/test_t55x7_bi.lua index a1793ba6..e8950ab8 100644 --- a/client/scripts/test_t55x7_bi.lua +++ b/client/scripts/test_t55x7_bi.lua @@ -89,6 +89,7 @@ end function test() local y + local block = "00" for y = 1, 0x1D, 4 do for _ = 1, #procedurecmds do local pcmd = procedurecmds[_] @@ -98,10 +99,10 @@ function test() elseif _ == 1 then local config = pcmd:format(config1, y, config2) - dbg(('lf t55xx wr 0 %s'):format(config)) - - config = tonumber(config,16) - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config} + dbg(('lf t55xx write 0 %s'):format(config)) + + config = tonumber(config,16) + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} local err = core.SendCommand(writecmd:getBytes()) if err then return oops(err) end local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) diff --git a/client/scripts/test_t55x7_fsk.lua b/client/scripts/test_t55x7_fsk.lua index f42dd147..c9c1f09c 100644 --- a/client/scripts/test_t55x7_fsk.lua +++ b/client/scripts/test_t55x7_fsk.lua @@ -92,6 +92,7 @@ end function test(modulation) local y + local block = "00" for y = 0x0, 0x1d, 0x4 do for _ = 1, #procedurecmds do local pcmd = procedurecmds[_] @@ -104,7 +105,7 @@ function test(modulation) dbg(('lf t55xx write 0 %s'):format(config)) config = tonumber(config,16) - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config} + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} local err = core.SendCommand(writecmd:getBytes()) if err then return oops(err) end local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) diff --git a/client/scripts/test_t55x7_psk.lua b/client/scripts/test_t55x7_psk.lua index cbd78e87..bdd644a7 100644 --- a/client/scripts/test_t55x7_psk.lua +++ b/client/scripts/test_t55x7_psk.lua @@ -108,6 +108,7 @@ end function test(modulation) local bitrate local clockrate + local block = "00" for bitrate = 0x0, 0x1d, 0x4 do for clockrate = 0,8,4 do @@ -125,8 +126,8 @@ function test(modulation) dbg(('lf t55xx write 0 %s'):format(config)) config = tonumber(config,16) - local writecommand = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config ,arg2 = 0, arg3 = 0} - local err = core.SendCommand(writecommand:getBytes()) + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} + local err = core.SendCommand(writecmd:getBytes()) if err then return oops(err) end local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) else diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua new file mode 100644 index 00000000..6c4a148c --- /dev/null +++ b/client/scripts/tnp3clone.lua @@ -0,0 +1,161 @@ +local cmds = require('commands') +local getopt = require('getopt') +local lib14a = require('read14a') +local utils = require('utils') +local pre = require('precalc') +local toys = require('default_toys') + +local lsh = bit32.lshift +local rsh = bit32.rshift +local bor = bit32.bor +local band = bit32.band + +example =[[ + script run tnp3clone + script run tnp3clone -h + script run tnp3clone -t aa00 -s 0030 + +]] +author = "Iceman" +usage = "script run tnp3clone -t -s " +desc =[[ +This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card. + +Arguments: + -h : this help + -t : toytype id, 4hex symbols. + -s : subtype id, 4hex symbols + + For fun, try the following subtype id: + 0612 - Lightcore + 0118 - Series 1 + 0138 - Series 2 + 0234 - Special + 023c - Special + +]] + + +-- This is only meant to be used when errors occur +function oops(err) + print("ERROR: ",err) +end +-- Usage help +function help() + print(desc) + print("Example usage") + print(example) +end + +local function waitCmd() + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000) + if response then + local count,cmd,arg0 = bin.unpack('LL',response) + if(arg0==1) then + local count,arg1,arg2,data = bin.unpack('LLH511',response,count) + return data:sub(1,32) + else + return nil, "Couldn't read block." + end + end + return nil, "No response from device" +end + +local function readblock( blocknum, keyA ) + -- Read block 0 + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA} + err = core.SendCommand(cmd:getBytes()) + if err then return nil, err end + local block0, err = waitCmd() + if err then return nil, err end + return block0 +end +local function readmagicblock( blocknum ) + -- Read block 0 + local CSETBLOCK_SINGLE_OPERATION = 0x1F + cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} + err = core.SendCommand(cmd:getBytes()) + if err then return nil, err end + local block0, err = waitCmd() + if err then return nil, err end + return block0 +end + +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + + local numBlocks = 64 + local cset = 'hf mf csetbl ' + local csetuid = 'hf mf csetuid ' + local cget = 'hf mf cgetbl ' + local empty = '00000000000000000000000000000000' + local AccAndKeyB = '7F078869000000000000' + -- Defaults to Gusto + local toytype = 'C201' + local subtype = '0030' + local DEBUG = true + + -- Arguments for the script + for o, a in getopt.getopt(args, 'ht:s:') do + if o == "h" then return help() end + if o == "t" then toytype = a end + if o == "s" then subtype = a end + end + + if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end + if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end + + -- look up type, find & validate types + local item = toys.Find( toytype, subtype) + if item then + print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) ) + else + print('Didn\'t find item type. If you are sure about it, report it in') + end + --15,16 + --13-14 + + + -- find tag + result, err = lib14a.read1443a(false) + if not result then return oops(err) end + + -- load keys + local akeys = pre.GetAll(result.uid) + local keyA = akeys:sub(1, 12 ) + + local b0 = readblock(0,keyA) + if not b0 then + print('failed reading block with factorydefault key. Trying chinese magic read.') + b0, err = readmagicblock(0) + if not b0 then + oops(err) + return oops('failed reading block with chinese magic command. quitting...') + end + end + + -- wipe card. + local cmd = (csetuid..'%s 0004 08 w'):format(result.uid) + core.console(cmd) + + local b1 = toytype..'00000000000000000000'..subtype + local calc = utils.Crc16(b0..b1) + local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) + + local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) + core.console(cmd) + + local pos, key + for blockNo = 2, numBlocks-1, 1 do + pos = (math.floor( blockNo / 4 ) * 12)+1 + key = akeys:sub(pos, pos + 11 ) + if blockNo%4 == 3 then + cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB) + core.console(cmd) + end + end + core.clearCommandBuffer() +end +main(args) \ No newline at end of file diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index dedd3df1..cd547e8a 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -5,19 +5,21 @@ local lib14a = require('read14a') local utils = require('utils') local md5 = require('md5') local dumplib = require('html_dumplib') -local toyNames = require('default_toys') +local toys = require('default_toys') example =[[ - 1. script run tnp3dump - 2. script run tnp3dump -n - 3. script run tnp3dump -k aabbccddeeff - 4. script run tnp3dump -k aabbccddeeff -n - 5. script run tnp3dump -o myfile - 6. script run tnp3dump -n -o myfile - 7. script run tnp3dump -k aabbccddeeff -n -o myfile + script run tnp3dump + script run tnp3dump -n + script run tnp3dump -p + script run tnp3dump -k aabbccddeeff + script run tnp3dump -k aabbccddeeff -n + script run tnp3dump -o myfile + script run tnp3dump -n -o myfile + script run tnp3dump -p -o myfile + script run tnp3dump -k aabbccddeeff -n -o myfile ]] author = "Iceman" -usage = "script run tnp3dump -k -n -o " +usage = "script run tnp3dump -k -n -p -o " desc =[[ This script will try to dump the contents of a Mifare TNP3xxx card. It will need a valid KeyA in order to find the other keys and decode the card. @@ -25,11 +27,10 @@ Arguments: -h : this help -k : Sector 0 Key A. -n : Use the nested cmd to find all keys + -p : Use the precalc to find all keys -o : filename for the saved dumps ]] - -local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' - +local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = false -- the debug flag local numBlocks = 64 @@ -93,16 +94,6 @@ local function waitCmd() return nil, "No response from device" end -local function computeCrc16(s) - local hash = core.crc16(utils.ConvertHexToAscii(s)) - return hash -end - -local function reverseCrcBytes(crc) - crc2 = crc:sub(3,4)..crc:sub(1,2) - return tonumber(crc2,16) -end - local function main(args) print( string.rep('--',20) ) @@ -112,18 +103,20 @@ local function main(args) local cmd local err local useNested = false + local usePreCalc = false local cmdReadBlockString = 'hf mf rdbl %d A %s' local input = "dumpkeys.bin" local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); -- Arguments for the script - for o, a in getopt.getopt(args, 'hk:no:') do + for o, a in getopt.getopt(args, 'hk:npo:') do if o == "h" then return help() end if o == "k" then keyA = a end if o == "n" then useNested = true end + if o == "p" then usePreCalc = true end if o == "o" then outputTemplate = a end end - + -- validate input args. keyA = keyA or '4b0b20107ccb' if #(keyA) ~= 12 then @@ -141,30 +134,31 @@ local function main(args) core.clearCommandBuffer() - if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx - return oops('This is not a TNP3xxx tag. aborting.') - end - -- Show tag info - print((' Found tag : %s'):format(result.name)) - print(('Using keyA : %s'):format(keyA)) + print((' Found tag %s'):format(result.name)) + + dbg(('Using keyA : %s'):format(keyA)) --Trying to find the other keys if useNested then core.console( ('hf mf nested 1 0 A %s d'):format(keyA) ) end - + core.clearCommandBuffer() - -- Loading keyfile - print('Loading dumpkeys.bin') - local hex, err = utils.ReadDumpFile(input) - if not hex then - return oops(err) + local akeys = '' + if usePreCalc then + local pre = require('precalc') + akeys = pre.GetAll(result.uid) + else + print('Loading dumpkeys.bin') + local hex, err = utils.ReadDumpFile(input) + if not hex then + return oops(err) + end + akeys = hex:sub(0,12*16) end - - local akeys = hex:sub(0,12*16) - + -- Read block 0 cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA} err = core.SendCommand(cmd:getBytes()) @@ -179,6 +173,8 @@ local function main(args) local block1, err = waitCmd() if err then return oops(err) end + local tmpHash = block0..block1..'%02x'..RANDOM + local key local pos = 0 local blockNo @@ -188,7 +184,7 @@ local function main(args) core.clearCommandBuffer() -- main loop - io.write('Decrypting blocks > ') + io.write('Reading blocks > ') for blockNo = 0, numBlocks-1, 1 do if core.ukbhit() then @@ -204,25 +200,23 @@ local function main(args) local blockdata, err = waitCmd() if err then return oops(err) end + if blockNo%4 ~= 3 then + if blockNo < 8 then -- Block 0-7 not encrypted blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else - local base = ('%s%s%02x%s'):format(block0, block1, blockNo, HASHCONSTANT) - local baseStr = utils.ConvertHexToAscii(base) - local md5hash = md5.sumhexa(baseStr) - local aestest = core.aes(md5hash, blockdata) - - local hex = utils.ConvertAsciiToBytes(aestest) - hex = utils.ConvertBytesToHex(hex) - -- blocks with zero not encrypted. if string.find(blockdata, '^0+$') then blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) - io.write( blockNo..',') + local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo)) + local key = md5.sumhexa(baseStr) + local aestest = core.aes128_decrypt(key, blockdata) + local hex = utils.ConvertAsciiToBytes(aestest) + hex = utils.ConvertBytesToHex(hex) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) end end else @@ -246,31 +240,38 @@ local function main(args) emldata = emldata..slice..'\n' for c in (str):gmatch('.') do bindata[#bindata+1] = c - end + end end - + print( string.rep('--',20) ) + local uid = block0:sub(1,8) - local itemtype = block1:sub(1,4) + local toytype = block1:sub(1,4) + local cardidLsw = block1:sub(9,16) + local cardidMsw = block1:sub(16,24) local cardid = block1:sub(9,24) - local traptype = block1:sub(25,28) + local subtype = block1:sub(25,28) -- Write dump to files if not DEBUG then - local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin') - print(("Wrote a BIN dump to the file %s"):format(foo)) - local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml') - print(("Wrote a EML dump to the file %s"):format(bar)) + local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin') + print(("Wrote a BIN dump to: %s"):format(foo)) + local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml') + print(("Wrote a EML dump to: %s"):format(bar)) end - - -- Show info + print( string.rep('--',20) ) - print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) ) - print( (' Alter ego / traptype : 0x%s'):format(traptype) ) + -- Show info + + local item = toys.Find(toytype, subtype) + if item then + print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) ) + else + print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype)) + end + print( (' UID : 0x%s'):format(uid) ) print( (' CARDID : 0x%s'):format(cardid ) ) - print( string.rep('--',20) ) - end main(args) \ No newline at end of file diff --git a/client/scripts/tnp3sim.lua b/client/scripts/tnp3sim.lua index adc34cce..af3d2d4c 100644 --- a/client/scripts/tnp3sim.lua +++ b/client/scripts/tnp3sim.lua @@ -4,7 +4,7 @@ local bin = require('bin') local lib14a = require('read14a') local utils = require('utils') local md5 = require('md5') -local toyNames = require('default_toys') +local toys = require('default_toys') example =[[ 1. script run tnp3sim @@ -27,6 +27,17 @@ Arguments: local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = true -- the debug flag + + +local band = bit32.band +local bor = bit32.bor +local lshift = bit32.lshift +local rshift = bit32.rshift +local byte = string.byte +local char = string.char +local sub = string.sub +local format = string.format + --- -- A debug printout-function function dbg(args) @@ -65,7 +76,6 @@ function ExitMsg(msg) print() end - local function writedumpfile(infile) t = infile:read("*all") len = string.len(t) @@ -187,7 +197,6 @@ local function ValidateCheckSums(blocks) io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) end - local function LoadEmulator(blocks) local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' local cmd @@ -219,6 +228,102 @@ local function LoadEmulator(blocks) io.write('\n') end +local function Num2Card(m, l) + + local k = { + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, + 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00 + } + local msw = tonumber(utils.SwapEndiannessStr(m,32),16) + local lsw = tonumber(utils.SwapEndiannessStr(l,32),16) + + if msw > 0x17ea1 then + return "too big" + end + + if msw == 0x17ea1 and lsw > 0x8931fee8 then + return "out of range" + end + + local s = "" + local index + for i = 1,10 do + index, msw, lsw = DivideByK( msw, lsw) + if ( index <= 1 ) then + s = char(k[index]) .. s + else + s = char(k[index-1]) .. s + end + print (index-1, msw, lsw) + end + return s +end +--33LRT-LM9Q9 +--7, 122, 3474858630 +--20, 4, 1008436634 +--7, 0, 627182959 +--17, 0, 21626998 +--16, 0, 745758 +--23, 0, 25715 +--21, 0, 886 +--16, 0, 30 +--1, 0, 1 +--1, 0, 0 + +function DivideByK(msw, lsw) + + local lowLSW + local highLSW + local remainder = 0 + local RADIX = 29 + + --local num = 0 | band( rshift(msw,16), 0xffff) + local num = band( rshift(msw, 16), 0xffff) + + --highLSW = 0 | lshift( (num / RADIX) , 16) + highLSW = lshift( (num / RADIX) , 16) + remainder = num % RADIX + + num = bor( lshift(remainder,16), band(msw, 0xffff)) + + --highLSW |= num / RADIX + highLSW = highLSW or (num / RADIX) + remainder = num % RADIX + + num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff))) + + --lowLSW = 0 | (num / RADIX) << 16 + lowLSW = 0 or (lshift( (num / RADIX), 16)) + remainder = num % RADIX + + num = bor( lshift(remainder,16) , band(lsw, 0xffff) ) + + lowLSW = bor(lowLSW, (num / RADIX)) + remainder = num % RADIX + return remainder, highLSW, lowLSW + + -- uint num = 0 | (msw >> 16) & 0xffff; + + -- highLSW = 0 | (num / RADIX) << 16; + -- remainder = num % RADIX; + + -- num = (remainder << 16) | (msw & 0xffff); + + -- highLSW |= num / RADIX; + -- remainder = num % RADIX; + + -- num = (remainder << 16) | ((lsw >> 16) & 0xffff); + + -- lowLSW = 0 | (num / RADIX) << 16; + -- remainder = num % RADIX; + + -- num = (remainder << 16) | (lsw & 0xffff); + + -- lowLSW |= num / RADIX; + -- remainder = num % RADIX; + +end + local function main(args) print( string.rep('--',20) ) @@ -277,16 +382,31 @@ local function main(args) print( string.rep('--',20) ) print(' Gathering info') local uid = blocks[0]:sub(1,8) - local itemtype = blocks[1]:sub(1,4) - local cardid = blocks[1]:sub(9,24) + local toytype = blocks[1]:sub(1,4) + local cardidLsw = blocks[1]:sub(9,16) + local cardidMsw = blocks[1]:sub(17,24) + local subtype = blocks[1]:sub(25,28) -- Show info print( string.rep('--',20) ) - print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) ) + + local item = toys.Find( toytype, subtype) + if item then + local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4]) + print(' ITEM TYPE :'..itemStr ) + else + print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) ) + end + print( (' UID : 0x%s'):format(uid) ) - print( (' CARDID : 0x%s'):format(cardid ) ) + print( (' CARDID : 0x%s %s [%s]'):format( + cardidMsw,cardidLsw, + --Num2Card(cardidMsw, cardidLsw)) + '') + ) print( string.rep('--',20) ) + -- lets do something. -- local experience = blocks[8]:sub(1,6) @@ -351,7 +471,7 @@ local function main(args) err = LoadEmulator(blocks) if err then return oops(err) end core.clearCommandBuffer() - print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..' x\" <--') + print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--') end end main(args) \ No newline at end of file diff --git a/client/util.c b/client/util.c index edd9aebc..709e2014 100644 --- a/client/util.c +++ b/client/util.c @@ -121,19 +121,24 @@ char * sprint_hex(const uint8_t * data, const size_t len) { return buf; } -char * sprint_bin(const uint8_t * data, const size_t len) { +char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) { int maxLen = ( len > 1024) ? 1024 : len; static char buf[1024]; - char * tmp = buf; - size_t i; + char *tmp = buf; - for (i=0; i < maxLen; ++i, ++tmp) - sprintf(tmp, "%u", data[i]); + for (size_t i=0; i < maxLen; ++i){ + sprintf(tmp++, "%u", data[i]); + if (breaks > 0 && !((i+1) % breaks)) + sprintf(tmp++, "%s","\n"); + } return buf; } +char *sprint_bin(const uint8_t *data, const size_t len) { + return sprint_bin_break(data, len, 0); +} void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { while (len--) { diff --git a/client/util.h b/client/util.h index 5001acdc..a6d0f49f 100644 --- a/client/util.h +++ b/client/util.h @@ -39,6 +39,7 @@ void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext, int byteCount); void print_hex(const uint8_t * data, const size_t len); char * sprint_hex(const uint8_t * data, const size_t len); char * sprint_bin(const uint8_t * data, const size_t len); +char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); diff --git a/common/lfdemod.c b/common/lfdemod.c index ffa807fe..7d40d22e 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -81,10 +81,8 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_ // otherwise could be a void with no arguments //set defaults uint32_t i = 0; - if (BitStream[1]>1){ //allow only 1s and 0s - // PrintAndLog("no data found"); - return 0; - } + if (BitStream[1]>1) return 0; //allow only 1s and 0s + // 111111111 bit pattern represent start of frame // include 0 in front to help get start pos uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; @@ -115,216 +113,11 @@ uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_ } //by marshmellow -//takes 3 arguments - clock, invert, maxErr as integers -//attempts to demodulate ask while decoding manchester -//prints binary found and saves in graphbuffer for further commands -int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr) -{ - size_t i; - int start = DetectASKClock(BinStream, *size, clk, 20); //clock default - if (*clk==0 || start < 0) return -3; - if (*invert != 1) *invert=0; - uint8_t initLoopMax = 255; - if (initLoopMax > *size) initLoopMax = *size; - // Detect high and lows - // 25% fuzz in case highs and lows aren't clipped [marshmellow] - int high, low; - if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) return -2; //just noise - - // PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low); - int lastBit = 0; //set first clock check - uint16_t bitnum = 0; //output counter - uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave - if (*clk <= 32) tol=1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely - size_t iii = 0; - //if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance - if (!maxErr) initLoopMax = *clk * 2; - uint16_t errCnt = 0, MaxBits = 512; - uint16_t bestStart = start; - uint16_t bestErrCnt = 0; - // PrintAndLog("DEBUG - lastbit - %d",lastBit); - // if best start position not already found by detect clock then - if (start <= 0 || start > initLoopMax){ - bestErrCnt = maxErr+1; - // loop to find first wave that works - for (iii=0; iii < initLoopMax; ++iii){ - // if no peak skip - if (BinStream[iii] < high && BinStream[iii] > low) continue; - - lastBit = iii - *clk; - // loop through to see if this start location works - for (i = iii; i < *size; ++i) { - if ((i-lastBit) > (*clk-tol) && (BinStream[i] >= high || BinStream[i] <= low)) { - lastBit += *clk; - } else if ((i-lastBit) > (*clk+tol)) { - errCnt++; - lastBit += *clk; - } - if ((i-iii) > (MaxBits * *clk) || errCnt > maxErr) break; //got plenty of bits or too many errors - } - //we got more than 64 good bits and not all errors - if ((((i-iii)/ *clk) > (64)) && (errCnt<=maxErr)) { - //possible good read - if (!errCnt || errCnt < bestErrCnt){ - bestStart = iii; //set this as new best run - bestErrCnt = errCnt; - if (!errCnt) break; //great read - finish - } - } - errCnt = 0; - } - } - if (bestErrCnt > maxErr){ - *invert = bestStart; - *clk = iii; - return -1; - } - //best run is good enough set to best run and set overwrite BinStream - lastBit = bestStart - *clk; - errCnt = 0; - for (i = bestStart; i < *size; ++i) { - if ((BinStream[i] >= high) && ((i-lastBit) > (*clk-tol))){ - //high found and we are expecting a bar - lastBit += *clk; - BinStream[bitnum++] = *invert; - } else if ((BinStream[i] <= low) && ((i-lastBit) > (*clk-tol))){ - //low found and we are expecting a bar - lastBit += *clk; - BinStream[bitnum++] = *invert ^ 1; - } else if ((i-lastBit)>(*clk+tol)){ - //should have hit a high or low based on clock!! - //PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit); - if (bitnum > 0) { - BinStream[bitnum++] = 77; - errCnt++; - } - lastBit += *clk;//skip over error - } - if (bitnum >= MaxBits) break; - } - *size = bitnum; - return bestErrCnt; -} - -//by marshmellow -//encode binary data into binary manchester -int ManchesterEncode(uint8_t *BitStream, size_t size) -{ - size_t modIdx=20000, i=0; - if (size>modIdx) return -1; - for (size_t idx=0; idx < size; idx++){ - BitStream[idx+modIdx++] = BitStream[idx]; - BitStream[idx+modIdx++] = BitStream[idx]^1; - } - for (; i<(size*2); i++){ - BitStream[i] = BitStream[i+20000]; - } - return i; -} - -//by marshmellow -//take 10 and 01 and manchester decode -//run through 2 times and take least errCnt -int manrawdecode(uint8_t * BitStream, size_t *size) -{ - uint16_t bitnum=0, MaxBits = 512, errCnt = 0; - size_t i, ii; - uint16_t bestErr = 1000, bestRun = 0; - if (size == 0) return -1; - for (ii=0;ii<2;++ii){ - for (i=ii; i<*size-2; i+=2) - if (BitStream[i]==BitStream[i+1]) - errCnt++; - - if (bestErr>errCnt){ - bestErr=errCnt; - bestRun=ii; - } - errCnt=0; - } - if (bestErr<20){ - for (i=bestRun; i < *size-2; i+=2){ - if(BitStream[i] == 1 && (BitStream[i+1] == 0)){ - BitStream[bitnum++]=0; - } else if((BitStream[i] == 0) && BitStream[i+1] == 1){ - BitStream[bitnum++]=1; - } else { - BitStream[bitnum++]=77; - } - if(bitnum>MaxBits) break; - } - *size=bitnum; - } - return bestErr; -} - -//by marshmellow -//take 01 or 10 = 1 and 11 or 00 = 0 -//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010 -//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding -int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert) -{ - uint16_t bitnum = 0; - uint16_t errCnt = 0; - size_t i = offset; - uint16_t MaxBits=512; - //if not enough samples - error - if (*size < 51) return -1; - //check for phase change faults - skip one sample if faulty - uint8_t offsetA = 1, offsetB = 1; - for (; i<48; i+=2){ - if (BitStream[i+1]==BitStream[i+2]) offsetA=0; - if (BitStream[i+2]==BitStream[i+3]) offsetB=0; - } - if (!offsetA && offsetB) offset++; - for (i=offset; i<*size-3; i+=2){ - //check for phase error - if (BitStream[i+1]==BitStream[i+2]) { - BitStream[bitnum++]=77; - errCnt++; - } - if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){ - BitStream[bitnum++]=1^invert; - } else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){ - BitStream[bitnum++]=invert; - } else { - BitStream[bitnum++]=77; - errCnt++; - } - if(bitnum>MaxBits) break; - } - *size=bitnum; - return errCnt; -} - -//by marshmellow -void askAmp(uint8_t *BitStream, size_t size) -{ - int shift = 127; - int shiftedVal=0; - for(size_t i = 1; i=30) //large jump up - shift=127; - else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down - shift=-127; - - shiftedVal=BitStream[i]+shift; - - if (shiftedVal>255) - shiftedVal=255; - else if (shiftedVal<0) - shiftedVal=0; - BitStream[i-1] = shiftedVal; - } - return; -} - -// demodulates strong heavily clipped samples +//demodulates strong heavily clipped samples int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low) { size_t bitCnt=0, smplCnt=0, errCnt=0; uint8_t waveHigh = 0; - //PrintAndLog("clk: %d", clk); for (size_t i=0; i < *size; i++){ if (BinStream[i] >= high && waveHigh){ smplCnt++; @@ -335,7 +128,7 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int if (smplCnt > clk-(clk/4)-1) { //full clock if (smplCnt > clk + (clk/4)+1) { //too many samples errCnt++; - BinStream[bitCnt++]=77; + BinStream[bitCnt++]=7; } else if (waveHigh) { BinStream[bitCnt++] = invert; BinStream[bitCnt++] = invert; @@ -371,111 +164,79 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int } //by marshmellow -//takes 3 arguments - clock, invert and maxErr as integers -//attempts to demodulate ask only -int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp) +void askAmp(uint8_t *BitStream, size_t size) +{ + for(size_t i = 1; i=30) //large jump up + BitStream[i]=127; + else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down + BitStream[i]=-127; + } + return; +} + +//by marshmellow +//attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester +int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType) { if (*size==0) return -1; - int start = DetectASKClock(BinStream, *size, clk, 20); //clock default - if (*clk==0 || start < 0) return -1; + int start = DetectASKClock(BinStream, *size, clk, maxErr); //clock default + if (*clk==0 || start < 0) return -3; if (*invert != 1) *invert = 0; if (amp==1) askAmp(BinStream, *size); uint8_t initLoopMax = 255; - if (initLoopMax > *size) initLoopMax=*size; + if (initLoopMax > *size) initLoopMax = *size; // Detect high and lows //25% clip in case highs and lows aren't clipped [marshmellow] int high, low; if (getHiLo(BinStream, initLoopMax, &high, &low, 75, 75) < 1) - return -1; //just noise + return -2; //just noise + size_t errCnt = 0; // if clean clipped waves detected run alternate demod - if (DetectCleanAskWave(BinStream, *size, high, low)) - return cleanAskRawDemod(BinStream, size, *clk, *invert, high, low); + if (DetectCleanAskWave(BinStream, *size, high, low)) { + errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low); + if (askType) //askman + return manrawdecode(BinStream, size, 0); + else //askraw + return errCnt; + } - int lastBit = 0; //set first clock check - can go negative - size_t i, iii = 0; - size_t errCnt = 0, bitnum = 0; //output counter + int lastBit; //set first clock check - can go negative + size_t i, bitnum = 0; //output counter uint8_t midBit = 0; - size_t bestStart = start, bestErrCnt = 0; //(*size/1000); + uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave + if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely size_t MaxBits = 1024; + lastBit = start - *clk; - //if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance - if (!maxErr) initLoopMax = *clk * 2; - //if best start not already found by detectclock - if (start <= 0 || start > initLoopMax){ - bestErrCnt = maxErr+1; - //PrintAndLog("DEBUG - lastbit - %d",lastBit); - //loop to find first wave that works - for (iii=0; iii < initLoopMax; ++iii){ - if ((BinStream[iii] >= high) || (BinStream[iii] <= low)){ - lastBit = iii - *clk; - //loop through to see if this start location works - for (i = iii; i < *size; ++i) { - if (i-lastBit > *clk && (BinStream[i] >= high || BinStream[i] <= low)){ - lastBit += *clk; - midBit = 0; - } else if (i-lastBit > (*clk/2) && midBit == 0) { - midBit = 1; - } else if ((i-lastBit) > *clk) { - //should have hit a high or low based on clock!! - //PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit); - errCnt++; - lastBit += *clk;//skip over until hit too many errors - if (errCnt > maxErr) - break; - } - if ((i-iii)>(MaxBits * *clk)) break; //got enough bits - } - //we got more than 64 good bits and not all errors - if ((((i-iii)/ *clk) > 64) && (errCnt<=maxErr)) { - //possible good read - if (errCnt==0){ - bestStart=iii; - bestErrCnt=errCnt; - break; //great read - finish - } - if (errCnt maxErr){ - *invert = bestStart; - *clk = iii; - return -1; - } - //best run is good enough - set to best run and overwrite BinStream - lastBit = bestStart - *clk - 1; - errCnt = 0; - - for (i = bestStart; i < *size; ++i) { - if (i - lastBit > *clk){ + for (i = start; i < *size; ++i) { + if (i-lastBit >= *clk-tol){ if (BinStream[i] >= high) { BinStream[bitnum++] = *invert; } else if (BinStream[i] <= low) { BinStream[bitnum++] = *invert ^ 1; - } else { + } else if (i-lastBit >= *clk+tol) { if (bitnum > 0) { - BinStream[bitnum++]=77; + BinStream[bitnum++]=7; errCnt++; } + } else { //in tolerance - looking for peak + continue; } midBit = 0; lastBit += *clk; - } else if (i-lastBit > (*clk/2) && midBit == 0){ + } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){ if (BinStream[i] >= high) { BinStream[bitnum++] = *invert; } else if (BinStream[i] <= low) { BinStream[bitnum++] = *invert ^ 1; - } else { - + } else if (i-lastBit >= *clk/2+tol) { BinStream[bitnum] = BinStream[bitnum-1]; bitnum++; + } else { //in tolerance - looking for peak + continue; } midBit = 1; } @@ -485,6 +246,98 @@ int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int max return errCnt; } +//by marshmellow +//take 10 and 01 and manchester decode +//run through 2 times and take least errCnt +int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert) +{ + uint16_t bitnum=0, MaxBits = 512, errCnt = 0; + size_t i, ii; + uint16_t bestErr = 1000, bestRun = 0; + if (*size < 16) return -1; + //find correct start position [alignment] + for (ii=0;ii<2;++ii){ + for (i=ii; i<*size-3; i+=2) + if (BitStream[i]==BitStream[i+1]) + errCnt++; + + if (bestErr>errCnt){ + bestErr=errCnt; + bestRun=ii; + } + errCnt=0; + } + //decode + for (i=bestRun; i < *size-3; i+=2){ + if(BitStream[i] == 1 && (BitStream[i+1] == 0)){ + BitStream[bitnum++]=invert; + } else if((BitStream[i] == 0) && BitStream[i+1] == 1){ + BitStream[bitnum++]=invert^1; + } else { + BitStream[bitnum++]=7; + } + if(bitnum>MaxBits) break; + } + *size=bitnum; + return bestErr; +} + +//by marshmellow +//encode binary data into binary manchester +int ManchesterEncode(uint8_t *BitStream, size_t size) +{ + size_t modIdx=20000, i=0; + if (size>modIdx) return -1; + for (size_t idx=0; idx < size; idx++){ + BitStream[idx+modIdx++] = BitStream[idx]; + BitStream[idx+modIdx++] = BitStream[idx]^1; + } + for (; i<(size*2); i++){ + BitStream[i] = BitStream[i+20000]; + } + return i; +} + +//by marshmellow +//take 01 or 10 = 1 and 11 or 00 = 0 +//check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010 +//decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding +int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert) +{ + uint16_t bitnum = 0; + uint16_t errCnt = 0; + size_t i = offset; + uint16_t MaxBits=512; + //if not enough samples - error + if (*size < 51) return -1; + //check for phase change faults - skip one sample if faulty + uint8_t offsetA = 1, offsetB = 1; + for (; i<48; i+=2){ + if (BitStream[i+1]==BitStream[i+2]) offsetA=0; + if (BitStream[i+2]==BitStream[i+3]) offsetB=0; + } + if (!offsetA && offsetB) offset++; + for (i=offset; i<*size-3; i+=2){ + //check for phase error + if (BitStream[i+1]==BitStream[i+2]) { + BitStream[bitnum++]=7; + errCnt++; + } + if((BitStream[i]==1 && BitStream[i+1]==0) || (BitStream[i]==0 && BitStream[i+1]==1)){ + BitStream[bitnum++]=1^invert; + } else if((BitStream[i]==0 && BitStream[i+1]==0) || (BitStream[i]==1 && BitStream[i+1]==1)){ + BitStream[bitnum++]=invert; + } else { + BitStream[bitnum++]=7; + errCnt++; + } + if(bitnum>MaxBits) break; + } + *size=bitnum; + return errCnt; +} + +// by marshmellow // demod gProxIIDemod // error returns as -x // success returns start position in BitStream @@ -780,12 +633,13 @@ int PyramiddemodFSK(uint8_t *dest, size_t *size) return (int)startIdx; } - -uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low) +// by marshmellow +// to detect a wave that has heavily clipped (clean) samples +uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low) { uint16_t allPeaks=1; uint16_t cntPeaks=0; - size_t loopEnd = 572; + size_t loopEnd = 512+60; if (loopEnd > size) loopEnd = size; for (size_t i=60; ilow && dest[i]128) { - if (!high){ - high=1; - if (cnt > highCnt){ - if (highCnt != 0) highCnt2 = highCnt; - highCnt = cnt; - } else if (cnt > highCnt2) { - highCnt2 = cnt; - } - cnt=1; - } else { - cnt++; - } - } else if (dest[idx] <= 128){ - if (high) { - high=0; - if (cnt > highCnt) { - if (highCnt != 0) highCnt2 = highCnt; - highCnt = cnt; - } else if (cnt > highCnt2) { - highCnt2 = cnt; - } - cnt=1; - } else { - cnt++; - } - } + uint8_t fndClk[] = {8,16,32,40,50,64,128}; + size_t startwave; + size_t i = 0; + size_t minClk = 255; + // get to first full low to prime loop and skip incomplete first pulse + while ((dest[i] < high) && (i < size)) + ++i; + while ((dest[i] > low) && (i < size)) + ++i; + + // loop through all samples + while (i < size) { + // measure from low to low + while ((dest[i] > low) && (i < size)) + ++i; + startwave= i; + while ((dest[i] < high) && (i < size)) + ++i; + while ((dest[i] > low) && (i < size)) + ++i; + //get minimum measured distance + if (i-startwave < minClk && i < size) + minClk = i - startwave; } - uint8_t tol; - for (idx=8; idx>0; idx--){ - tol = clk[idx]/8; - if (clk[idx] >= highCnt - tol && clk[idx] <= highCnt + tol) - return clk[idx]; - if (clk[idx] >= highCnt2 - tol && clk[idx] <= highCnt2 + tol) - return clk[idx]; + // set clock + for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) { + if (minClk >= fndClk[clkCnt]-(fndClk[clkCnt]/8) && minClk <= fndClk[clkCnt]+1) + return fndClk[clkCnt]; } - return -1; + return 0; } // by marshmellow @@ -856,45 +696,61 @@ int DetectStrongAskClock(uint8_t dest[], size_t size) // return start index of best starting position for that clock and return clock (by reference) int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) { - size_t i=0; - uint8_t clk[]={8,16,32,40,50,64,100,128,255}; + size_t i=1; + uint8_t clk[] = {255,8,16,32,40,50,64,100,128,255}; + uint8_t clkEnd = 9; uint8_t loopCnt = 255; //don't need to loop through entire array... if (size <= loopCnt) return -1; //not enough samples - //if we already have a valid clock quit - - for (;i<8;++i) - if (clk[i] == *clock) return 0; + + //if we already have a valid clock + uint8_t clockFnd=0; + for (;i0; i--){ - if (clk[i] == ans) { - *clock = ans; - return 0; + if (!clockFnd){ + if (DetectCleanAskWave(dest, size, peak, low)==1){ + int ans = DetectStrongAskClock(dest, size, peak, low); + for (i=clkEnd-1; i>0; i--){ + if (clk[i] == ans) { + *clock = ans; + //clockFnd = i; + return 0; // for strong waves i don't use the 'best start position' yet... + //break; //clock found but continue to find best startpos [not yet] + } } } } + uint8_t ii; uint8_t clkCnt, tol = 0; uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000}; uint8_t bestStart[]={0,0,0,0,0,0,0,0,0}; size_t errCnt = 0; size_t arrLoc, loopEnd; + + if (clockFnd>0) { + clkCnt = clockFnd; + clkEnd = clockFnd+1; + } + else clkCnt=1; + //test each valid clock from smallest to greatest to see which lines up - for(clkCnt=0; clkCnt < 8; clkCnt++){ - if (clk[clkCnt] == 32){ + for(; clkCnt < clkEnd; clkCnt++){ + if (clk[clkCnt] <= 32){ tol=1; }else{ tol=0; } - if (!maxErr) loopCnt=clk[clkCnt]*2; + //if no errors allowed - keep start within the first clock + if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt]<128) loopCnt=clk[clkCnt]*2; bestErr[clkCnt]=1000; - //try lining up the peaks by moving starting point (try first 256) + //try lining up the peaks by moving starting point (try first few clocks) for (ii=0; ii < loopCnt; ii++){ if (dest[ii] < peak && dest[ii] > low) continue; @@ -910,11 +766,11 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) errCnt++; } } - //if we found no errors then we can stop here + //if we found no errors then we can stop here and a low clock (common clocks) // this is correct one - return this clock //PrintAndLog("DEBUG: clk %d, err %d, ii %d, i %d",clk[clkCnt],errCnt,ii,i); - if(errCnt==0 && clkCnt<6) { - *clock = clk[clkCnt]; + if(errCnt==0 && clkCnt<7) { + if (!clockFnd) *clock = clk[clkCnt]; return ii; } //if we found errors see if it is lowest so far and save it as best run @@ -924,9 +780,9 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr) } } } - uint8_t iii=0; + uint8_t iii; uint8_t best=0; - for (iii=0; iii<8; ++iii){ + for (iii=1; iii maxErr) return -1; - *clock = clk[best]; + //if (bestErr[best] > maxErr) return -1; + if (!clockFnd) *clock = clk[best]; return bestStart[best]; } @@ -1115,7 +971,7 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size) size_t i=1; uint8_t lastBit=BitStream[0]; for (; i lastClkBit + *clock + tol + fc){ lastClkBit += *clock; //no phase shift but clock bit diff --git a/common/lfdemod.h b/common/lfdemod.h index 15121cbf..ab81c34c 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -15,34 +15,37 @@ #define LFDEMOD_H__ #include -int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr); -uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low); -int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr); -uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); -int ManchesterEncode(uint8_t *BitStream, size_t size); -int manrawdecode(uint8_t *BitStream, size_t *size); -int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert); -int askrawdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp); +//generic +int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType); +int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert); +uint32_t bytebits_to_byte(uint8_t* src, size_t numbits); +uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj); +int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr); +uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, uint8_t low); +uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow); +int DetectNRZClock(uint8_t dest[], size_t size, int clock); +int DetectPSKClock(uint8_t dest[], size_t size, int clock); +int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low); +uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); +int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow); +int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +int ManchesterEncode(uint8_t *BitStream, size_t size); +int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert); +int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr); +uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); +uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); +int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert); +void psk2TOpsk1(uint8_t *BitStream, size_t size); +void psk1TOpsk2(uint8_t *BitStream, size_t size); +size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); + +//tag specific +int AWIDdemodFSK(uint8_t *dest, size_t *size); int gProxII_Demod(uint8_t BitStream[], size_t *size); int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); int IOdemodFSK(uint8_t *dest, size_t size); -int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow); -uint32_t bytebits_to_byte(uint8_t* src, size_t numbits); -int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int maxErr); -void psk1TOpsk2(uint8_t *BitStream, size_t size); -void psk2TOpsk1(uint8_t *BitStream, size_t size); -int DetectNRZClock(uint8_t dest[], size_t size, int clock); int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); int PyramiddemodFSK(uint8_t *dest, size_t *size); -int AWIDdemodFSK(uint8_t *dest, size_t *size); -size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); -uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj); -uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow); -int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); -uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); -uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); -int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert); -int DetectPSKClock(uint8_t dest[], size_t size, int clock); #endif