]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Added em410xread, em410xsim, em410xread, bitstream, manmod, detectclock commands...
authorskamkar <skamkar@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Thu, 2 Jul 2009 03:13:13 +0000 (03:13 +0000)
committerskamkar <skamkar@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Thu, 2 Jul 2009 03:13:13 +0000 (03:13 +0000)
winsrc/command.cpp
winsrc/gui.cpp
winsrc/prox.cpp
winsrc/prox.h

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