X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/1de3416e5a5ba6c60e0257ce667bb08fd8ebbcde..8172fb35dd18116560c903b14c432394b1cdd06b:/winsrc/command.cpp diff --git a/winsrc/command.cpp b/winsrc/command.cpp index f8a9d569..b5d3e3d7 100644 --- a/winsrc/command.cpp +++ b/winsrc/command.cpp @@ -256,6 +256,148 @@ static void CmdEM410xwatch(char *str) } while (go); } +/* 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. + */ +static void CmdEM4x50read(char *str) +{ + int i, j, startblock, clock, skip, block, start, end, low, high; + BOOL complete= FALSE; + int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; + char tmp[6]; + + high= low= 0; + clock= 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; + start= i; + while(GraphBuffer[i] < high) + ++i; + while(GraphBuffer[i] > low) + ++i; + 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(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) + PrintToScrollback("Found data at sample: %i",skip); + else + { + PrintToScrollback("No data found!"); + PrintToScrollback("Try again with more samples."); + return; + } + + if (!complete) + { + PrintToScrollback("*** Warning!"); + PrintToScrollback("Partial data - no end found!"); + PrintToScrollback("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) + { + PrintToScrollback("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++; + } +} + + /* Read the ID of an EM410x tag. * Format: * 1111 1111 1 <-- standard non-repeatable header @@ -497,7 +639,6 @@ static void ChkBitstream(char *str) static void CmdLosim(char *str) { int i; - char *zero = "0"; /* convert to bitstream if necessary */ ChkBitstream(str); @@ -535,6 +676,22 @@ static void CmdLoread(char *str) SendCommand(&c, FALSE); } +static void CmdDetectReader(char *str) +{ + UsbCommand c; + // 'l' means LF - 125/134 kHz + if(*str == 'l') { + c.ext1 = 1; + } else if (*str == 'h') { + c.ext1 = 2; + } else if (*str != '\0') { + PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); + return; + } + c.cmd = CMD_LISTEN_READER_FIELD; + SendCommand(&c, FALSE); +} + /* send a command before reading */ static void CmdLoCommandRead(char *str) { @@ -546,7 +703,7 @@ static void CmdLoCommandRead(char *str) c.cmd = CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K; sscanf(str, "%i %i %i %s %s", &c.ext1, &c.ext2, &c.ext3, &c.d.asBytes,&dummy+1); // in case they specified 'h' - strcpy(&c.d.asBytes + strlen(c.d.asBytes),dummy); + strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); SendCommand(&c, FALSE); } @@ -1869,8 +2026,7 @@ static void CmdFlexdemod(char *str) static void Cmdaskdemod(char *str) { int i; - int n = 0; - int c,high,low = 0; + int c, high = 0, low = 0; // TODO: complain if we do not give 2 arguments here ! sscanf(str, "%i", &c); @@ -2431,9 +2587,11 @@ static struct { "buffclear", CmdBuffClear,0, " Clear sample buffer and graph window", "dec", CmdDec,1, " Decimate samples", "detectclock", Cmddetectclockrate,1, " Detect clock rate", + "detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)", "em410xsim", CmdEM410xsim,1, " -- Simulate EM410x tag", "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag", "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags", + "em4x50read", CmdEM4x50read,1, " Extract data from EM4x50 tag", "exit", CmdQuit,1, " Exit program", "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass", "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control