From: skamkar Date: Thu, 2 Jul 2009 03:13:13 +0000 (+0000) Subject: Added em410xread, em410xsim, em410xread, bitstream, manmod, detectclock commands... X-Git-Tag: v1.0.0~596 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/9760414b9672e778317fc9238265cf7fc36061b8 Added em410xread, em410xsim, em410xread, bitstream, manmod, detectclock commands. Added an offline mode. Improved manchester demod routine, auto-detect clock rate in various routines. --- diff --git a/winsrc/command.cpp b/winsrc/command.cpp index a02803db..1c434ebb 100644 --- a/winsrc/command.cpp +++ b/winsrc/command.cpp @@ -14,7 +14,10 @@ #include "../common/iso14443_crc.c" #define arraylen(x) (sizeof(x)/sizeof((x)[0])) +#define BIT(x) GraphBuffer[x * clock] +#define BITS (GraphTraceLen / clock) +int go = 0; static int CmdHisamplest(char *str, int nrlow); static void GetFromBigBuf(BYTE *dest, int bytes) @@ -34,7 +37,7 @@ static void GetFromBigBuf(BYTE *dest, int bytes) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return; } @@ -83,19 +86,19 @@ static void CmdHi14read(char *str) c.ext1 = atoi(str); SendCommand(&c, FALSE); } - - -/* New command to read the contents of a SRI512 tag - * SRI512 tags are ISO14443-B modulated memory tags, - * this command just dumps the contents of the memory/ - */ -static void CmdSri512read(char *str) -{ + + +/* New command to read the contents of a SRI512 tag + * SRI512 tags are ISO14443-B modulated memory tags, + * this command just dumps the contents of the memory/ + */ +static void CmdSri512read(char *str) +{ UsbCommand c; c.cmd = CMD_READ_SRI512_TAG; c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} + SendCommand(&c, FALSE); +} // ## New command static void CmdHi14areader(char *str) @@ -161,8 +164,6 @@ static void CmdHi14sim(char *str) c.cmd = CMD_SIMULATE_TAG_ISO_14443; SendCommand(&c, FALSE); } - - static void CmdHi14asim(char *str) // ## simulate iso14443a tag { // ## greg - added ability to specify tag UID @@ -205,11 +206,284 @@ static void CmdFPGAOff(char *str) // ## FPGA Control SendCommand(&c, FALSE); } -static void CmdLosim(char *str) +/* clear out our graph window */ +int CmdClearGraph(int redraw) +{ + int gtl = GraphTraceLen; + GraphTraceLen = 0; + + if (redraw) + RepaintGraphWindow(); + + return gtl; +} + +/* write a bit to the graph */ +static void CmdAppendGraph(int redraw, int clock, int bit) { int i; - for(i = 0; i < GraphTraceLen; i += 48) { + for (i = 0; i < (int)(clock/2); i++) + GraphBuffer[GraphTraceLen++] = bit ^ 1; + + for (i = (int)(clock/2); i < clock; i++) + GraphBuffer[GraphTraceLen++] = bit; + + if (redraw) + RepaintGraphWindow(); +} + +/* Function is equivalent of loread + losamples + em410xread + * looped until an EM410x tag is detected */ +static void CmdEM410xwatch(char *str) +{ + char *zero = ""; + char *twok = "2000"; + go = 1; + + do + { + CmdLoread(zero); + CmdLosamples(twok); + CmdEM410xread(zero); + } while (go); +} + +/* Read the ID of an EM410x tag. + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ +static void CmdEM410xread(char *str) +{ + int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low; + int parity[4]; + char id[11]; + int BitStream[MAX_GRAPH_TRACE_LEN]; + high = low = 0; + + /* 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 clock */ + clock = GetClock(str, high); + + /* parity for our 4 columns */ + parity[0] = parity[1] = parity[2] = parity[3] = 0; + header = rows = 0; + + /* manchester demodulate */ + bit = bit2idx = 0; + for (i = 0; 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; + } + + /* We go till 5 before the graph ends because we'll get that far below */ + for (i = 1; i < bit2idx - 5; i++) + { + /* Step 2: We have our header but need our tag ID */ + if (header == 9 && rows < 10) + { + /* Confirm parity is correct */ + if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4]) + { + /* Read another byte! */ + sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3])); + rows++; + + /* Keep parity info */ + parity[0] ^= BitStream[i]; + parity[1] ^= BitStream[i+1]; + parity[2] ^= BitStream[i+2]; + parity[3] ^= BitStream[i+3]; + + /* Move 4 bits ahead */ + i += 4; + } + + /* Damn, something wrong! reset */ + else + { + PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i); + + /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ + i -= 9 + (5 * rows) - 5; + + rows = header = 0; + } + } + + /* Step 3: Got our 40 bits! confirm column parity */ + else if (rows == 10) + { + /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ + if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] && + BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] && + BitStream[i+4] == 0) + { + /* Sweet! */ + PrintToScrollback("EM410x Tag ID: %s", id); + + /* Stop any loops */ + go = 0; + break; + } + + /* Crap! Incorrect parity or no stop bit, start all over */ + else + { + rows = header = 0; + + /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ + i -= 59; + } + } + + /* Step 1: get our header */ + else if (header < 9) + { + /* Need 9 consecutive 1's */ + if (BitStream[i] == 1) + header++; + + /* We don't have a header, not enough consecutive 1 bits */ + else + header = 0; + } + } +} + +/* emulate an EM410X tag + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ +static void CmdEM410xsim(char *str) +{ + int i, n, j, h, binary[4], parity[4]; + char *s = "0"; + + /* clock is 64 in EM410x tags */ + int clock = 64; + + /* clear our graph */ + CmdClearGraph(0); + + /* write it out a few times */ + for (h = 0; h < 4; h++) + { + /* write 9 start bits */ + for (i = 0; i < 9; i++) + CmdAppendGraph(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(&str[i], "%1x", &n); + for (j = 3; j >= 0; j--, n/= 2) + binary[j] = n % 2; + + /* append each bit */ + CmdAppendGraph(0, clock, binary[0]); + CmdAppendGraph(0, clock, binary[1]); + CmdAppendGraph(0, clock, binary[2]); + CmdAppendGraph(0, clock, binary[3]); + + /* append parity bit */ + CmdAppendGraph(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 */ + CmdAppendGraph(0, clock, parity[0]); + CmdAppendGraph(0, clock, parity[1]); + CmdAppendGraph(0, clock, parity[2]); + CmdAppendGraph(0, clock, parity[3]); + + /* stop bit */ + CmdAppendGraph(0, clock, 0); + } + + /* modulate that biatch */ + Cmdmanchestermod(s); + + /* booyah! */ + RepaintGraphWindow(); + + CmdLosim(s); +} + +static void ChkBitstream(char *str) +{ + int i; + + /* convert to bitstream if necessary */ + for (i = 0; i < (int)(GraphTraceLen / 2); i++) + { + if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) + { + Cmdbitstream(str); + break; + } + } +} + +static void CmdLosim(char *str) +{ + int i; + char *zero = "0"; + + /* convert to bitstream if necessary */ + ChkBitstream(str); + + for (i = 0; i < GraphTraceLen; i += 48) { UsbCommand c; int j; for(j = 0; j < 48; j++) { @@ -259,7 +533,8 @@ static void CmdLosamples(char *str) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + if (!go) + PrintToScrollback("bad resp"); return; } int j; @@ -285,7 +560,7 @@ static void CmdBitsamples(char *str) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return; } int j, k; @@ -316,7 +591,7 @@ static void CmdHisamples(char *str) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return; } int j; @@ -349,7 +624,7 @@ static int CmdHisamplest(char *str, int nrlow) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return 0; } int j; @@ -418,7 +693,7 @@ static void CmdHexsamples(char *str) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return; } int j; @@ -457,7 +732,7 @@ static void CmdHisampless(char *str) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return; } int j; @@ -947,7 +1222,7 @@ static void CmdTibits(char *str) SendCommand(&c, FALSE); ReceiveCommand(&c); if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) { - PrintToScrollback("bad resp\n"); + PrintToScrollback("bad resp"); return; } int j; @@ -1545,112 +1820,259 @@ static void CmdFlexdemod(char *str) RepaintGraphWindow(); } - -/* - * Generic command to demodulate ASK. bit length in argument. - * Giving the bit length helps discriminate ripple effects - * upon zero crossing for noisy traces. - * - * Second is convention: positive or negative (High mod means zero - * or high mod means one) - * - * Updates the Graph trace with 0/1 values - * - * Arguments: - * sl : bit length in terms of number of samples per bit - * (use yellow/purple markers to compute). - * c : 0 or 1 - */ - -static void Cmdaskdemod(char *str) { - int i; - int sign = 1; - int n = 0; + +/* + * Generic command to demodulate ASK. bit length in argument. + * Giving the bit length helps discriminate ripple effects + * upon zero crossing for noisy traces. + * + * Second is convention: positive or negative (High mod means zero + * or high mod means one) + * + * Updates the Graph trace with 0/1 values + * + * Arguments: + * sl : bit length in terms of number of samples per bit + * (use yellow/purple markers to compute). + * c : 0 or 1 + */ + +static void Cmdaskdemod(char *str) { + int i; + int sign = 1; + int n = 0; int c = 0; - int t1 = 0; - - // TODO: complain if we do not give 2 arguments here ! - sscanf(str, "%i %i", &n, &c); - if (c == 0) { - c = 1 ; - } else { - c = -1; - } - - if (GraphBuffer[0]*c > 0) { - GraphBuffer[0] = 1; - } else { - GraphBuffer[0] = 0; - } - for(i=1;i n/4 ) { - sign = -sign; - t1=i; - if (GraphBuffer[i]*c > 0){ - GraphBuffer[i]=1; - } else { - GraphBuffer[i]=0; - } - } else { - /* This is a ripple, set the current sample value - to the same as previous */ - GraphBuffer[i] = GraphBuffer[i-1]; - } - } else { - GraphBuffer[i] = GraphBuffer[i-1]; - } - } - RepaintGraphWindow(); -} - - -/* - * 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... - */ -static void Cmdmanchesterdemod(char *str) { + int t1 = 0; + + // TODO: complain if we do not give 2 arguments here ! + sscanf(str, "%i %i", &n, &c); + if (c == 0) { + c = 1 ; + } else { + c = -1; + } + + if (GraphBuffer[0]*c > 0) { + GraphBuffer[0] = 1; + } else { + GraphBuffer[0] = 0; + } + for(i=1;i n/4 ) { + sign = -sign; + t1=i; + if (GraphBuffer[i]*c > 0){ + GraphBuffer[i]=1; + } else { + GraphBuffer[i]=0; + } + } else { + /* This is a ripple, set the current sample value + to the same as previous */ + GraphBuffer[i] = GraphBuffer[i-1]; + } + } else { + GraphBuffer[i] = GraphBuffer[i-1]; + } + } + RepaintGraphWindow(); +} + +/* Print our clock rate */ +static void Cmddetectclockrate(char *str) +{ + int clock = detectclock(0); + PrintToScrollback("Auto-detected clock rate: %d", clock); +} + +/* + * Detect clock rate + */ +int detectclock(int peak) +{ + int i; + int clock = 0xFFFF; + int lastpeak = 0; + + /* Detect peak if we don't have one */ + if (!peak) + for (i = 0; i < GraphTraceLen; i++) + if (GraphBuffer[i] > peak) + peak = GraphBuffer[i]; + + for (i = 1; i < GraphTraceLen; i++) + { + /* If this is the beginning of a peak */ + if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak) + { + /* Find lowest difference between peaks */ + if (lastpeak && i - lastpeak < clock) + { + clock = i - lastpeak; + } + lastpeak = i; + } + } + + return clock; +} + +/* Get or auto-detect clock rate */ +int GetClock(char *str, int peak) +{ + int clock; + + sscanf(str, "%i", &clock); + if (!strcmp(str, "")) + clock = 0; + + /* Auto-detect clock */ + if (!clock) + { + clock = detectclock(peak); + + /* Only print this message if we're not looping something */ + if (!go) + PrintToScrollback("Auto-detected clock rate: %d", clock); + } + + return clock; +} + +/* + * Convert to a bitstream + */ +static void Cmdbitstream(char *str) { int i, j; int bit; - int clock; - int lastval; + int gtl; + int clock; int low = 0; int high = 0; int hithigh, hitlow, first; - int lc = 0; - int bitidx = 0; - int bit2idx = 0; - int warnings = 0; - - sscanf(str, "%i", &clock); - if (!clock) + + /* Detect high and lows and clock */ + for (i = 0; i < GraphTraceLen; i++) { - PrintToScrollback("You must provide a clock rate."); - return; + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; } - - int tolerance = clock/4; - /* 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 */ - int BitStream[MAX_GRAPH_TRACE_LEN]; - + + /* Get our clock */ + clock = GetClock(str, high); + + gtl = CmdClearGraph(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; + + CmdAppendGraph(0, clock, bit); +// for (j = 0; j < (int)(clock/2); j++) +// GraphBuffer[(i * clock) + j] = bit ^ 1; +// for (j = (int)(clock/2); j < clock; j++) +// GraphBuffer[(i * clock) + j] = bit; + } + + RepaintGraphWindow(); +} + +/* Modulate our data into manchester */ +static void Cmdmanchestermod(char *str) +{ + int i, j; + int clock; + int bit, lastbit, wave; + + /* Get our clock */ + clock = GetClock(str, 0); + + 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(); +} + +/* + * 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... + */ +static void Cmdmanchesterdemod(char *str) { + int i, j; + int bit; + int clock; + int lastval; + int low = 0; + int high = 0; + int hithigh, hitlow, first; + int lc = 0; + int bitidx = 0; + int bit2idx = 0; + int warnings = 0; + + /* 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 */ + int BitStream[MAX_GRAPH_TRACE_LEN]; + /* Detect high and lows */ for (i = 0; i < GraphTraceLen; i++) { @@ -1660,24 +2082,27 @@ static void Cmdmanchesterdemod(char *str) { low = GraphBuffer[i]; } - /* Detect first transition */ - /* Lo-Hi (arbitrary) */ + /* Get our clock */ + clock = GetClock(str, high); + + int tolerance = clock/4; + + /* Detect first transition */ + /* Lo-Hi (arbitrary) */ for (i = 0; i < GraphTraceLen; i++) { if (GraphBuffer[i] == low) { -// BitStream[0]=0; // Previous state = 0; - lastval = i; - break; - } - } -//PrintToScrollback("cool %d %d %d %d", low, high, lastval, GraphBuffer[i]); + lastval = i; + break; + } + } /* If we're not working with 1/0s, demod based off clock */ if (high != 1) { bit = 0; - for (i = 0; i < (GraphTraceLen / clock); i++) + for (i = 0; i < (int)(GraphTraceLen / clock); i++) { hithigh = 0; hitlow = 0; @@ -1713,98 +2138,98 @@ static void Cmdmanchesterdemod(char *str) { /* standard 1/0 bitstream */ else { - - /* Then detect duration between 2 successive transitions */ + + /* 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) ) { - PrintToScrollback("Error: the clock you gave is probably wrong, aborting."); - return; - } - // 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 + 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) ) { + PrintToScrollback("Error: the clock you gave is probably wrong, aborting."); + return; + } + // 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++; - PrintToScrollback("Warning: Manchester decode error for pulse width detection."); - PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); + PrintToScrollback("Warning: Manchester decode error for pulse width detection."); + PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); if (warnings > 100) { PrintToScrollback("Error: too many detection errors, aborting."); return; } - } - } - } - - // 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; - } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) { - BitStream[bit2idx++] = 0; - } else { - // We cannot end up in this state, this means we are unsynchronized, - // move up 1 bit: - i++; + } + } + } + + // 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; + } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) { + BitStream[bit2idx++] = 0; + } else { + // We cannot end up in this state, this means we are unsynchronized, + // move up 1 bit: + i++; warnings++; - PrintToScrollback("Unsynchronized, resync..."); - PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); + PrintToScrollback("Unsynchronized, resync..."); + PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); if (warnings > 100) { PrintToScrollback("Error: too many decode errors, aborting."); return; } - } - } + } + } } PrintToScrollback("Manchester decoded bitstream"); - // Now output the bitstream to the scrollback by line of 16 bits - for (i = 0; i < (bit2idx-16); i+=16) { - PrintToScrollback("%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]); - } -} - - - -/* - * Usage ??? + // Now output the bitstream to the scrollback by line of 16 bits + for (i = 0; i < (bit2idx-16); i+=16) { + PrintToScrollback("%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]); + } +} + + + +/* + * Usage ??? */ static void CmdHiddemod(char *str) { @@ -1923,11 +2348,11 @@ static void CmdLcd(char *str) static void CmdTest(char *str) { } - -/* - * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below - * 600kHz. - */ + +/* + * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below + * 600kHz. + */ static void CmdSetDivisor(char *str) { UsbCommand c; @@ -1947,15 +2372,15 @@ static void CmdSweepLF(char *str) c.cmd = CMD_SWEEP_LF; SendCommand(&c, FALSE); } - - + + typedef void HandlerFunction(char *cmdline); static struct { char *name; HandlerFunction *handler; int offline; // 1 if the command can be used when in offline mode - char *docString; + char *docString; } CommandTable[] = { "tune", CmdTune,0, "measure antenna tuning", "tiread", CmdTiread,0, "read a TI-type 134 kHz tag", @@ -1965,6 +2390,9 @@ static struct { "plot", CmdPlot,1, "show graph window", "hide", CmdHide,1, "hide graph window", "losim", CmdLosim,0, "simulate LF tag", + "em410xsim", CmdEM410xsim,1, "simulate EM410x tag", + "em410xread", CmdEM410xread,1, "extract ID from EM410x tag", + "em410xwatch", CmdEM410xwatch,0, "watches for EM410x tags", "loread", CmdLoread,0, "read (125/134 kHz) LF ID-only tag", "losamples", CmdLosamples,0, "get raw samples for LF tag", "hisamples", CmdHisamples,0, "get raw samples for HF tag", @@ -2002,8 +2430,11 @@ static struct { "hidfskdemod", CmdHIDdemodFSK,0, "HID FSK demodulator", "indalademod", CmdIndalademod,0, "demod samples for Indala", "askdemod", Cmdaskdemod,1, "Attempt to demodulate simple ASK tags", + "bitstream", Cmdbitstream,1, "Convert waveform into a bitstream", "hidsimtag", CmdHIDsimTAG,0, "HID tag simulator", "mandemod", Cmdmanchesterdemod,1, "Try a Manchester demodulation on a binary stream", + "manmod", Cmdmanchestermod,1, "Manchester modulate a binary stream", + "detectclock", Cmddetectclockrate,1, "Detect clock rate", "fpgaoff", CmdFPGAOff,0, "set FPGA off", // ## FPGA Control "lcdreset", CmdLcdReset,0, "Hardware reset LCD", "lcd", CmdLcd,0, "Send command/data to LCD", @@ -2076,7 +2507,7 @@ void UsbCommandReceived(UsbCommand *c) memcpy(s, c->d.asBytes, c->ext1); s[c->ext1] = '\0'; PrintToScrollback("#db# %s", s); - break; + break; } case CMD_DEBUG_PRINT_INTEGERS: diff --git a/winsrc/gui.cpp b/winsrc/gui.cpp index cc8e17f9..44792b4c 100644 --- a/winsrc/gui.cpp +++ b/winsrc/gui.cpp @@ -33,7 +33,6 @@ void dbp(char *str, ...) int GraphBuffer[MAX_GRAPH_TRACE_LEN]; int GraphTraceLen; -int offline; // Whether the GUI operates in Offline mode. HPEN GreyPen, GreenPen, WhitePen, YellowPen; HBRUSH GreenBrush, YellowBrush; @@ -384,7 +383,7 @@ static void SetCommandEditTo(char *str) SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str)); } -void ShowGui(void) +void ShowGui() { WNDCLASSEX wc; memset(&wc, 0, sizeof(wc)); @@ -505,9 +504,11 @@ void ShowGui(void) } } - UsbCommand c; - if(ReceiveCommandPoll(&c)) { - UsbCommandReceived(&c); + if (!offline) + { + UsbCommand c; + if(ReceiveCommandPoll(&c)) + UsbCommandReceived(&c); } Sleep(10); diff --git a/winsrc/prox.cpp b/winsrc/prox.cpp index e95a4aff..e2c0a79c 100644 --- a/winsrc/prox.cpp +++ b/winsrc/prox.cpp @@ -13,6 +13,7 @@ extern "C" { #define OUR_VID 0x9ac4 #define OUR_PID 0x4b8f +int offline = 0; HANDLE UsbHandle; static void ShowError(void) @@ -326,30 +327,35 @@ static void LoadFlashFromSRecords(char *file, int addr) int main(int argc, char **argv) { int i = 0; - + if(argc < 2) { printf("Usage: %s bootrom file.s19\n", argv[0]); printf(" %s load osimage.s19\n", argv[0]); printf(" %s fpga fpgaimg.s19\n", argv[0]); printf(" %s gui\n", argv[0]); + printf(" %s offline\n", argv[0]); return -1; } - - for(;;) { - if(UsbConnect()) { - break; - } - if(i == 0) { - printf("...no device connected, polling for it now\n"); - } - if(i > 50000) { - printf("Could not connect to USB device; exiting.\n"); - return -1; + + // Only do this if NOT in offline mode + if (strcmp(argv[1], "offline")) + { + for(;;) { + if(UsbConnect()) { + break; + } + if(i == 0) { + printf("...no device connected, polling for it now\n"); + } + if(i > 50000) { + printf("Could not connect to USB device; exiting.\n"); + return -1; + } + i++; + Sleep(5); } - i++; - Sleep(5); } - + if(strcmp(argv[1], "bootrom")==0 || strcmp(argv[1], "load")==0 || strcmp(argv[1], "fpga")==0) { if(argc != 3) { printf("Need filename.\n"); @@ -364,6 +370,9 @@ int main(int argc, char **argv) } } else if(strcmp(argv[1], "gui")==0) { ShowGui(); + } else if(strcmp(argv[1], "offline")==0) { + offline = 1; + ShowGui(); } else if(strcmp(argv[1], "cmd")==0) { if(argc != 3) { printf("Need command.\n"); diff --git a/winsrc/prox.h b/winsrc/prox.h index 7c0219e0..232aba1f 100644 --- a/winsrc/prox.h +++ b/winsrc/prox.h @@ -9,7 +9,7 @@ BOOL ReceiveCommandPoll(UsbCommand *c); void SendCommand(UsbCommand *c, BOOL wantAck); // gui.cpp -void ShowGui(void); +void ShowGui(); void HideGraphWindow(void); void ShowGraphWindow(void); void RepaintGraphWindow(void); @@ -19,13 +19,82 @@ extern int GraphBuffer[MAX_GRAPH_TRACE_LEN]; extern int GraphTraceLen; extern double CursorScaleFactor; extern int CommandFinished; -extern int offline; // Set to 1 if the proxmark is offline - +extern int offline; // command.cpp +static void GetFromBigBuf(BYTE *dest, int bytes); +static void CmdReset(char *str); +static void CmdQuit(char *str); +static void CmdEM410xread(char *str); +static void CmdEM410xwatch(char *str); +static void ChkBitstream(char *str); +int GetClock(char *str, int peak); +static void CmdHIDdemodFSK(char *str); +static void Cmdmanchestermod(char *str); +static void CmdTune(char *str); +static void CmdHi15read(char *str); +static void CmdHi14read(char *str); +static void CmdSri512read(char *str); +static void CmdHi14areader(char *str); +static void CmdHi15reader(char *str); +static void CmdHi15tag(char *str); +static void CmdHi14read_sim(char *str); +static void CmdHi14readt(char *str); +static void CmdHisimlisten(char *str); +static void CmdHi14sim(char *str); +static void CmdHi14asim(char *str); +static void CmdHi14snoop(char *str); +static void CmdHi14asnoop(char *str); +static void CmdFPGAOff(char *str); +int CmdClearGraph(int redraw); +static void CmdAppendGraph(int redraw, int clock, int bit); +static void CmdEM410xsim(char *str); +static void CmdLosim(char *str); +static void CmdLoread(char *str); +static void CmdLosamples(char *str); +static void CmdBitsamples(char *str); +static void CmdHisamples(char *str); +static int CmdHisamplest(char *str, int nrlow); +static void CmdHexsamples(char *str); +static void CmdHisampless(char *str); +static WORD Iso15693Crc(BYTE *v, int n); +static void CmdHi14bdemod(char *str); +static void CmdHi14list(char *str); +static void CmdHi14alist(char *str); +static void CmdHi15demod(char *str); +static void CmdTiread(char *str); +static void CmdTibits(char *str); +static void CmdTidemod(char *cmdline); +static void CmdNorm(char *str); +static void CmdDec(char *str); +static void CmdHpf(char *str); +static void CmdZerocrossings(char *str); +static void CmdLtrim(char *str); +static void CmdAutoCorr(char *str); +static void CmdVchdemod(char *str); +static void CmdIndalademod(char *str); +static void CmdFlexdemod(char *str); +static void Cmdaskdemod(char *str); +static void Cmddetectclockrate(char *str); +int detectclock(int peak); +static void Cmdbitstream(char *str); +static void Cmdmanchesterdemod(char *str); +static void CmdHiddemod(char *str); +static void CmdPlot(char *str); +static void CmdHide(char *str); +static void CmdScale(char *str); +static void CmdSave(char *str); +static void CmdLoad(char *str); +static void CmdHIDsimTAG(char *str); +static void CmdLcdReset(char *str); +static void CmdLcd(char *str); +static void CmdTest(char *str); +static void CmdSetDivisor(char *str); +static void CmdSweepLF(char *str); void CommandReceived(char *cmd); void UsbCommandReceived(UsbCommand *c); + // cmdline.cpp void ShowCommandline(void); void ExecCmd(char *cmd);